Merging 68 commit(s) from Chromium's toolchain-utils

Merged commit digest:
  a37c013c llvm_tools: move FindChromeOSRootAbove to chroot.py
  c6733c05 auto_abandon_cls: include internal CLs
  8a26cd3e cros_utils: add support for parsing for internal CL uploads
  54e65f79 git: add helper to determine if something's a full SHA
  f46a883d llvm_tools: add package stabilization script
  c5dcecf1 llvm_tools: remove LLVM_HASH usage from get_upstream_patch
  5a25614b llvm_tools: migrate nightly_revert_checker to get_llvm_hash
  18a3ccb6 llvm_tools: let `get_llvm_hash` grab llvm-next/llvm hashes
  53ba4150 llvm_tools: add bb_add.py
  f8e584c2 llvm_tools: add a file to contain llvm testing information
  5910e9f1 llvm_tools: add internal CL support to cros_cls
  977ad131 rust-analyzer-chromiumos-wrapper: Perform exact prefix match for replacement
  51776b56 rust-analyzer-chromiumos-wrapper: Update rust-analyzer in chroot to /usr/bin
  7da035ef rust-analyzer-chromiumos-wrapper: Replace on first match only.
  9b49b4f2 rust-analyzer-chromiumos-wrapper: Use arrays instead of hashmaps to store replacements
  dc3dc47e rust-analyzer-chromiumos-wrapper: Simplify test payloads
  48b9e2d0 rust-analyzer-chromiumos-wrapper: Simplify test output Vec initialization
  92a0ed1a rust-analyzer-chromiumos-wrapper: Generate Content-Length for tests in the helper
  6523933c patch_sync: Fix android patch filtering.
  e72432d7 patch_sync: Clean up clippy lints
  9418ce84 llvm_tools: add gerrit cwd
  91004c13 llvm_tools: add revision autodetection to the patch cleanup script
  26d580d4 afdo_tools: move worktree creation to git_utils
  13efc0f6 Make git am a dry run when running test_apply()
  9a6d822b afdo_metadata: Publish the new kernel profiles
  ae16c1dd setup_for_workon: make --checkout or --no-checkout mandatory
  b5f88d7d llvm_tools: use new make_tempdir method in tests
  f6dc855c llvm_tools: add clean_up_old_llvm_patches script
  e1133ef4 afdo_metadata: Publish the new kernel profiles
  4db0e315 llvm_tools: fix `cros lint` & mypy issues in patch_utils
  3f4382d0 llvm_tools: remove unused `patch_cmd` arg
  0fc9b4d6 llvm_tools: remove REMOVE_PATCHES failure mode
  f710649f afdo_tools: move git utilities into cros_utils
  226bf89b compiler_wrapper: automatic sync
  feab5cec afdo_metadata: Publish the new kernel profiles
  443429f4 check-presubmit: add missing f
  baceb2f1 afdo_tools: Replace gsutil with gsutil.py
  67fd41ab replace shlex.quote with shlex.join
  44fc9bbb update_packages_and_run_tests: set wip on uploaded changes
  ad01c999 update_kernel_afdo: clarify logging slightly
  08f5f2ad afdo_metadata: Publish the new kernel profiles
  f49627a5 compiler_wrapper: automatic sync
  a692f08c llvm_tools: update repo manifest by default for llvm upgrades
  b8a26ea2 afdo_metadata: Publish the new kernel profiles
  3c03d572 delete `auto_delete_nightly_test_data.py`
  3b0d75a2 afdo_tools: remove update_kernel_afdo
  14fc4f03 afdo_tools: update profiles even if they're old
  b824cf76 afdo_tools: add chromeos-tree flag to update_kernel_afdo.py
  12edaa8d afdo_tools: fix `git` invocation in update_kernel_afdo.py
  23453f96 llvm_tools: add llvm_simple_bisect.py
  112b4b64 compiler_wrapper: automatic sync
  83ca115a afdo_metadata: Publish the new kernel profiles
  e351bbc6 afdo_tools: add update_kernel_afdo.py
  7b937bee afdo_tools: skip kernel 5.4 temporarily in upgrades
  7539fd49 llvm_tools: support new LLVM_VERSION_MAJOR location
  013f7a3e toolchain_utils_githooks: add --install_deps_only flag
  9b2e8e11 afdo_tools: print arch info when saying 'wrong version'
  1409d51f auto_delete_nightly_test_data: split abandoning into another script
  56b13e96 afdo_tools: un-add 6.6 kernel version
  f3de6683 update_packages_and_run_tests: add chroot args
  ddbd42cf llvm_tools: s/chroot_path/chromeos_path
  e28af8e1 update_kernel_afdo: roll for kernels 6.6 and 6.1
  db4d68ea afdo_tools: fix script output for stable channel
  84141e2b compiler_wrapper: automatic sync
  7707b2c7 auto_update_rust_bootstrap: gracefully handle multiple CLs
  1ea2d92f pgo_rust: emerge `cross-*/rust` packages
  423ae14d rust_uprev: skip fetching bootstrap tbz2
  159f6741 rust_uprev: specify category for `equery w rust`

Change-Id: Ia1a4e4b4639bf304559360fbec431b67588304f6
diff --git a/afdo_metadata/kernel_afdo.json b/afdo_metadata/kernel_afdo.json
index d752cad..0180b30 100644
--- a/afdo_metadata/kernel_afdo.json
+++ b/afdo_metadata/kernel_afdo.json
@@ -1,11 +1,14 @@
 {
-    "chromeos-kernel-5_4": {
-        "name": "R121-15699.29-1705314853"
-    },
     "chromeos-kernel-5_10": {
-        "name": "R122-15699.25-1704709934"
+        "name": "R125-15823.16-1712568782"
     },
     "chromeos-kernel-5_15": {
-        "name": "R122-15699.25-1704709973"
+        "name": "R125-15832.0-1712569184"
+    },
+    "chromeos-kernel-5_4": {
+        "name": "R125-15823.16-1712569649"
+    },
+    "chromeos-kernel-6_1": {
+        "name": "R125-15823.16-1712569561"
     }
-}
+}
\ No newline at end of file
diff --git a/afdo_metadata/kernel_arm_afdo.json b/afdo_metadata/kernel_arm_afdo.json
index cbe71c5..f2c0209 100644
--- a/afdo_metadata/kernel_arm_afdo.json
+++ b/afdo_metadata/kernel_arm_afdo.json
@@ -1,5 +1,5 @@
 {
     "chromeos-kernel-5_15": {
-        "name": "R122-15699.25-1704710142"
+        "name": "R124-15786.10-1709548825"
     }
-}
+}
\ No newline at end of file
diff --git a/afdo_tools/update_kernel_afdo b/afdo_tools/update_kernel_afdo
deleted file mode 100755
index 6bfa53f..0000000
--- a/afdo_tools/update_kernel_afdo
+++ /dev/null
@@ -1,424 +0,0 @@
-#!/bin/bash
-# Copyright 2020 The ChromiumOS Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Due to crbug.com/1081332, we need to update AFDO metadata
-# manually. This script performs a few checks and generates a
-# new kernel_afdo.json file, which can then be submitted.
-#
-
-USAGE="
-Usage: $(basename "$0") [--help] [--(no)upload] [--nointeractive]
-          [main|beta|stable|all]
-
-Description:
-  The script takes one optional argument which is the channel where we want
-to update the kernel afdo and creates a commit (or commits with \"all\"
-channels) in the corresponding branch.
-  No arguments defaults to \"all\".
-  Follow the prompt to upload the changes with --noupload. Otherwise
-  the script will automatically create CL and send to the detective
-  for review.
-  NO CLEAN-UP NEEDED. The script ignores any local changes and keeps
-the current branch unchanged.
-
-  Args:
-    --help      Show this help.
-    --upload    Upload CLs when the update succeeded (default).
-    --noupload  Do not upload CLs. Instead, print the upload commands.
-    --nointeractive   Runs the script without user interaction.
-    main|beta|stable  Update metadata only on the specified channel.
-"
-
-set -eu
-set -o pipefail
-
-# Branch independent constants.
-# Changes here will affect kernel afdo update in cros branches.
-# -------------------
-ARCHS="amd arm"
-AMD_GS_BASE=gs://chromeos-prebuilt/afdo-job/vetted/kernel/amd64
-ARM_GS_BASE=gs://chromeos-prebuilt/afdo-job/vetted/kernel/arm
-UPDATE_CONFIG_FILE="afdo_tools/update_kernel_afdo.cfg"
-# CL reviewers and cc.
-REVIEWERS="c-compiler-chrome@google.com"
-CC="denik@google.com,gbiv@google.com"
-# Add skipped chrome branches in ascending order here.
-SKIPPED_BRANCHES="95"
-# NOTE: We enable/disable kernel AFDO starting from a particular branch.
-#   For example if we want to enable kernel AFDO in 5.15, first, we do it
-#   in main. In this case we want to disable it in beta and stable branches.
-#   The second scenario is when we want to disable kernel AFDO (when all devices
-#   move to kernelnext and there are no new profiles from the field). In this
-#   case we disable AFDO in main but still keep it live in beta and stable.
-declare -A SKIPPED_ARCHKVERS_IN_BRANCHES
-# In SKIPPED_ARCHKVERS_IN_BRANCHES
-# - key is a branch number string;
-# - value is the list of arch/kver separated by space.
-# Example: SKIPPED_ARCHKVERS_IN_BRANCHES["105"]="amd/4.4 arm/5.15"
-# -------------------
-# Kernel tracing was disabled on arm in 114, b/275560674.
-SKIPPED_ARCHKVERS_IN_BRANCHES["114"]="arm/5.15"
-SKIPPED_ARCHKVERS_IN_BRANCHES["115"]="arm/5.15"
-
-script_dir=$(dirname "$0")
-tc_utils_dir="${script_dir}/.."
-# Convert toolchain_utils into the absolute path.
-abs_tc_utils_dir="$(realpath "${tc_utils_dir}")"
-
-# Check profiles uploaded within the last week.
-expected_time=$(date +%s -d "week ago")
-# Upload CLs on success.
-upload_cl=true
-# Interactive mode.
-interactive=true
-# Without arguments the script updates all branches.
-channels=""
-failed_channels=""
-
-declare -A arch_gsbase arch_kvers arch_outfile
-declare -A branch branch_number commit
-remote_repo=$(git -C "${tc_utils_dir}" remote)
-canary_ref="refs/heads/main"
-# Read the last two release-Rxx from remote branches
-# and assign them to stable_ref and beta_ref.
-# sort -V is the version sort which puts R100 after R99.
-# We need `echo` to convert newlines into spaces for read.
-read -r stable_ref beta_ref <<< "$(git -C "${tc_utils_dir}" ls-remote -h \
-  "${remote_repo}" release-R\* | cut -f2 | sort -V | tail -n 2 | paste -s)"
-# Branch names which start from release-R.
-branch["beta"]=${beta_ref##*/}
-branch["stable"]=${stable_ref##*/}
-branch["canary"]=${canary_ref##*/}
-
-# Get current branch numbers (number which goes after R).
-branch_number["stable"]=$(echo "${branch["stable"]}" | \
-  sed -n -e "s/^release-R\([0-9][0-9]*\).*$/\1/p")
-branch_number["beta"]=$(echo "${branch["beta"]}" | \
-  sed -n -e "s/^release-R\([0-9][0-9]*\).*$/\1/p")
-branch_number["canary"]="$((branch_number[beta] + 1))"
-for skipped_branch in ${SKIPPED_BRANCHES} ; do
-  if [[ ${branch_number["canary"]} == "${skipped_branch}" ]] ; then
-    ((branch_number[canary]++))
-  fi
-done
-config_file="$(realpath --relative-to="${tc_utils_dir}" \
-       "${tc_utils_dir}/${UPDATE_CONFIG_FILE}")"
-
-for arg in "$@"
-do
-  case "${arg}" in
-  stable | canary | beta )
-    channels="${channels} ${arg}"
-    ;;
-  main )
-    channels="${channels} canary"
-    ;;
-  all )
-    channels="canary beta stable"
-    ;;
-  --noupload | --no-upload)
-    upload_cl=false
-    ;;
-  --upload)
-    upload_cl=true
-    ;;
-  --nointeractive)
-    interactive=false
-    ;;
-  --help | help | -h )
-    echo "${USAGE}"
-    exit 0
-    ;;
-  -*)
-    echo "ERROR: Option \"${arg}\" is not supported." >&2
-    echo "${USAGE}"
-    exit 1
-    ;;
-  *)
-    echo "Channel \"${arg}\" is not supported.
-Must be main (or canary), beta, stable or all." >&2
-    echo "${USAGE}"
-    exit 1
-  esac
-done
-
-if [[ -z "${channels}" ]]
-then
-  channels="canary beta stable"
-fi
-
-# Fetch latest branches.
-git -C "${tc_utils_dir}" fetch "${remote_repo}"
-
-worktree_dir=$(mktemp -d)
-echo "-> Working in ${worktree_dir}"
-# Create a worktree and make changes there.
-# This way we don't need to clean-up and sync toolchain_utils before the
-# change. Neither we should care about clean-up after the submit.
-git -C "${tc_utils_dir}" worktree add --detach "${worktree_dir}"
-trap 'git -C "${abs_tc_utils_dir}" worktree remove -f "${worktree_dir}" \
-      && git -C "${abs_tc_utils_dir}" branch -D ${channels}' EXIT
-pushd "${worktree_dir}"
-
-for channel in ${channels}
-do
-  set +u
-  if [[ -n "${commit[${channel}]}" ]]
-  then
-    echo "Skipping channel ${channel} which already has commit\
- ${commit[${channel}]}."
-    continue
-  fi
-  set -u
-
-  errs=""
-  successes=0
-  curr_branch_number=${branch_number[${channel}]}
-  curr_branch=${branch[${channel}]}
-  echo
-  echo "Checking \"${channel}\" channel..."
-  echo "branch_number=${curr_branch_number} branch=${curr_branch}"
-
-  git reset --hard HEAD
-  git checkout -b "${channel}" "${remote_repo}/${curr_branch}"
-
-  # Read branch-dependent constants from $remote_repo.
-  # shellcheck source=afdo_tools/update_kernel_afdo.cfg
-  if [[ -e "${config_file}" ]]
-  then
-    # Branch dependent constants were moved to config_file.
-    # IMPORTANT: Starting from M-113 update_kernel_afdo reads branch-dependent
-    # constants from config_file from remote refs.
-    source "${config_file}"
-  else
-    # DON'T UPDATE THESE CONSTANTS HERE!
-    # Update ${config_file} instead.
-    AMD_KVERS="4.14 4.19 5.4 5.10"
-    ARM_KVERS="5.15"
-    AMD_METADATA_FILE="afdo_metadata/kernel_afdo.json"
-    ARM_METADATA_FILE="afdo_metadata/kernel_arm_afdo.json"
-  fi
-
-  amd_outfile="$(realpath --relative-to="${tc_utils_dir}" \
-    "${tc_utils_dir}/${AMD_METADATA_FILE}")"
-  arm_outfile="$(realpath --relative-to="${tc_utils_dir}" \
-    "${tc_utils_dir}/${ARM_METADATA_FILE}")"
-  arch_gsbase["amd"]="${AMD_GS_BASE}"
-  arch_gsbase["arm"]="${ARM_GS_BASE}"
-  arch_kvers["amd"]="${AMD_KVERS}"
-  arch_kvers["arm"]="${ARM_KVERS}"
-  arch_outfile["amd"]="${amd_outfile}"
-  arch_outfile["arm"]="${arm_outfile}"
-
-  new_changes=false
-  for arch in ${ARCHS}
-  do
-    json="{"
-    sep=""
-    for kver in ${arch_kvers[${arch}]}
-    do
-      # Skip kernels disabled in this branch.
-      skipped=false
-      for skipped_branch in "${!SKIPPED_ARCHKVERS_IN_BRANCHES[@]}"
-      do
-        if [[ ${curr_branch_number} == "${skipped_branch}" ]]
-        then
-          # Current branch is in the keys of SKIPPED_ARCHKVERS_IN_BRANCHES.
-          # Now lets check if $arch/$kver is in the list.
-          for skipped_archkver in \
-            ${SKIPPED_ARCHKVERS_IN_BRANCHES[${skipped_branch}]}
-          do
-            if [[ "${arch}/${kver}" == "${skipped_archkver}" ]]
-            then
-              skipped=true
-              break
-            fi
-          done
-        fi
-      done
-      if ${skipped}
-      then
-        echo "${arch}/${kver} is skipped in branch ${curr_branch_number}."
-        continue
-      fi
-      # Sort the gs output by timestamp, default ordering is by name. So
-      # R86-13310.3-1594633089.gcov.xz goes after
-      # R86-13310.18-1595237847.gcov.xz.
-      latest=$(gsutil.py ls -l "${arch_gsbase[${arch}]}/${kver}/" | sort -k2 | \
-               grep "R${curr_branch_number}" | tail -1 || true)
-      prev_branch=$((curr_branch_number - 1))
-      if [[ -z "${latest}" && "${channel}" != "stable" ]]
-      then
-        # if no profiles exist for the current branch, try the previous branch
-        latest=$(gsutil.py ls -l "${arch_gsbase[${arch}]}/${kver}/" | \
-          sort -k2 | grep "R${prev_branch}" | tail -1 || true)
-      fi
-      if [[ -z "${latest}" ]]
-      then
-        echo "ERROR: No M${curr_branch_number}, M${prev_branch} profiles in\
- ${arch_gsbase[${arch}]}/${kver}/" >&2
-        echo "Skipping ${arch}/${kver}" >&2
-        errs="${errs} ${kver}"
-        continue
-      fi
-
-      # Verify that the file has the expected date.
-      file_time=$(echo "${latest}" | awk '{print $2}')
-      file_time_unix=$(date +%s -d "${file_time}")
-      if [ "${file_time_unix}" -lt "${expected_time}" ]
-      then
-        expected=$(env TZ=UTC date +%Y-%m-%dT%H:%M:%SZ -d @"${expected_time}")
-        echo "ERROR: Wrong date for ${kver}: ${file_time} is before\
- ${expected}" >&2
-        errs="${errs} ${kver}"
-        continue
-      fi
-
-      # Generate JSON.
-      json_kver=$(echo "${kver}" | tr . _)
-      # b/147370213 (migrating profiles from gcov format) may result in the
-      # pattern below no longer doing the right thing.
-      name="$(basename "${latest%.gcov.*}")"
-      # Skip kernels with no AFDO support in the current channel.
-      if [[ "${name}" == "" ]]
-      then
-        continue
-      fi
-      json=$(cat <<EOT
-${json}${sep}
-    "chromeos-kernel-${json_kver}": {
-        "name": "${name}"
-    }
-EOT
-      )
-      sep=","
-      successes=$((successes + 1))
-    done # kvers loop
-
-    # If we did not succeed for any kvers, exit now.
-    if [[ ${successes} -eq 0 ]]
-    then
-      echo "ERROR: AFDO profiles out of date for all kernel versions" >&2
-      failed_channels="${failed_channels} ${channel}"
-      continue
-    fi
-
-    # Write new JSON file.
-    # Don't use `echo` since `json` might have esc characters in it.
-    printf "%s\n}\n" "${json}" > "${arch_outfile[${arch}]}"
-
-    # If no changes were made, say so.
-    outdir=$(dirname "${arch_outfile[${arch}]}")
-    shortstat=$(cd "${outdir}" &&\
-      git status --short "$(basename "${arch_outfile[${arch}]}")")
-    [ -z "${shortstat}" ] &&\
-      echo "$(basename "${arch_outfile[${arch}]}") is up to date." \
-      && continue
-
-    # If we had any errors, warn about them.
-    if [[ -n "${errs}" ]]
-    then
-      echo "WARNING: failed to update ${errs} in ${channel}" >&2
-      failed_channels="${failed_channels} ${channel}"
-      continue
-    fi
-
-    git add "${arch_outfile[${arch}]}"
-    new_changes=true
-  done # ARCHS loop
-
-  if ! ${new_changes}
-  then
-    echo "Skipping \"${channel}\" - all profiles are up to date"
-    continue
-  fi
-
-  case "${channel}" in
-    canary )
-      commit_contents=$'afdo_metadata: Publish the new kernel profiles\n\n'
-      for arch in ${ARCHS} ; do
-        for kver in ${arch_kvers[${arch}]} ; do
-          commit_contents="${commit_contents}Update ${arch} profile on\
- chromeos-kernel-${kver}"$'\n'
-        done
-      done
-      commit_contents="${commit_contents}
-
-BUG=None
-TEST=Verified in kernel-release-afdo-verify-orchestrator"
-      ;;
-    beta | stable )
-      commit_contents="afdo_metadata: Publish the new kernel profiles\
- in ${curr_branch}
-
-Have PM pre-approval because this shouldn't break the release branch.
-
-BUG=None
-TEST=Verified in kernel-release-afdo-verify-orchestrator"
-      ;;
-    * )
-      echo "Internal error: unhandled channel \"${channel}\"" >&2
-      exit 2
-  esac
-
-  if ${interactive}
-  then
-    git commit -v -e -m "${commit_contents}"
-  else
-    git commit -m "${commit_contents}"
-  fi
-
-  commit[${channel}]=$(git -C "${worktree_dir}" rev-parse HEAD)
-done
-
-popd
-echo
-# Array size check doesn't play well with the unbound variable option.
-set +u
-if [[ ${#commit[@]} -gt 0 ]]
-then
-  set -u
-  echo "The change is applied in ${!commit[*]}."
-  if ${upload_cl}
-  then
-    for channel in "${!commit[@]}"
-    do
-      if ${interactive}
-      then
-        (cd "${tc_utils_dir}" && \
-          repo upload --br="${channel}" --re="${REVIEWERS}" --cc="${CC}" .)
-      else
-        (cd "${tc_utils_dir}" && \
-          repo upload --br="${channel}" --no-verify -y --re="${REVIEWERS}" \
-                      --cc="${CC}" .)
-      fi
-    done
-  else
-    echo "Run these commands to upload the change:"
-    echo
-    for channel in "${!commit[@]}"
-    do
-      echo -e "\tgit -C ${tc_utils_dir} push ${remote_repo} \
-  ${commit[${channel}]}:refs/for/${branch[${channel}]}"
-    done
-  fi
-
-  # Report failed channels.
-  if [[ -n "${failed_channels}" ]]
-  then
-    echo
-    echo "ERROR: failed to update kernel afdo in ${failed_channels}" >&2
-    exit 3
-  fi
-else
-  # No commits. Check if it is due to failures.
-  if [[ -z "${failed_channels}" ]]
-  then
-    echo "No changes are applied. It looks like AFDO versions are up to date."
-  else
-    echo "ERROR: update in ${failed_channels} failed" >&2
-    exit 3
-  fi
-fi
diff --git a/afdo_tools/update_kernel_afdo.cfg b/afdo_tools/update_kernel_afdo.cfg
index 821c9c1..a69d6f8 100644
--- a/afdo_tools/update_kernel_afdo.cfg
+++ b/afdo_tools/update_kernel_afdo.cfg
@@ -2,7 +2,7 @@
 # All changes here won't affect kernel afdo update in branches.
 # WARNING: Changes must be submitted to have effect.
 
-AMD_KVERS="5.4 5.10 5.15"
+AMD_KVERS="5.4 5.10 5.15 6.1"
 ARM_KVERS="5.15"
 AMD_METADATA_FILE="afdo_metadata/kernel_afdo.json"
 ARM_METADATA_FILE="afdo_metadata/kernel_arm_afdo.json"
diff --git a/afdo_tools/update_kernel_afdo.py b/afdo_tools/update_kernel_afdo.py
new file mode 100755
index 0000000..0a299bd
--- /dev/null
+++ b/afdo_tools/update_kernel_afdo.py
@@ -0,0 +1,803 @@
+#!/usr/bin/env python3
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""This script updates kernel profiles based on what's available in gs://.
+
+It supports updating on canary, stable, and beta branches.
+"""
+
+import argparse
+import dataclasses
+import datetime
+import enum
+import json
+import logging
+import os
+from pathlib import Path
+import re
+import shlex
+import subprocess
+import sys
+from typing import Dict, Iterable, List, Optional, Tuple
+
+from cros_utils import git_utils
+
+
+# Folks who should be on the R-line of any CLs that get uploaded.
+CL_REVIEWERS = (git_utils.REVIEWER_DETECTIVE,)
+
+# Folks who should be on the CC-line of any CLs that get uploaded.
+CL_CC = (
+    "denik@google.com",
+    "gbiv@google.com",
+)
+
+# Determine which gsutil to use.
+# 'gsutil.py' is provided by depot_tools, whereas 'gsutil'
+# is provided by either https://cloud.google.com/sdk/docs/install, or
+# the 'google-cloud-cli' package. Since we need depot_tools to even
+# use 'repo', 'gsutil.py' is guaranteed to exist.
+GSUTIL = "gsutil.py"
+
+
+class Arch(enum.Enum):
+    """An enum for CPU architectures."""
+
+    AMD64 = "amd64"
+    ARM = "arm"
+
+    @property
+    def cwp_gs_location(self) -> str:
+        """Returns the location in gs:// where these profiles live."""
+        if self == self.AMD64:
+            return "gs://chromeos-prebuilt/afdo-job/vetted/kernel/amd64"
+        if self == self.ARM:
+            return "gs://chromeos-prebuilt/afdo-job/vetted/kernel/arm"
+        assert False, f"Uncovered arch -> gs:// mapping for {self}"
+
+
+@dataclasses.dataclass(frozen=True, eq=True, order=True)
+class KernelVersion:
+    """A class representing a version of the kernel."""
+
+    major: int
+    minor: int
+
+    def __str__(self):
+        return f"{self.major}.{self.minor}"
+
+    @classmethod
+    def parse(cls, val: str) -> "KernelVersion":
+        m = re.fullmatch(r"(\d+).(\d+)", val)
+        if not m:
+            raise ValueError(f"{val!r} is an invalid kernel version")
+        return cls(major=int(m.group(1)), minor=int(m.group(2)))
+
+
+# Versions that rolling should be skipped on, for one reason or another.
+SKIPPED_VERSIONS: Dict[int, Iterable[Tuple[Arch, KernelVersion]]] = {
+    # Kernel tracing was disabled on ARM in 114, b/275560674
+    114: ((Arch.ARM, KernelVersion(5, 15)),),
+    115: ((Arch.ARM, KernelVersion(5, 15)),),
+}
+
+
+class Channel(enum.Enum):
+    """An enum that discusses channels."""
+
+    # Ordered from closest-to-ToT to farthest-from-ToT
+    CANARY = "canary"
+    BETA = "beta"
+    STABLE = "stable"
+
+    @classmethod
+    def parse(cls, val: str) -> "Channel":
+        for x in cls:
+            if val == x.value:
+                return x
+        raise ValueError(
+            f"No such channel: {val!r}; try one of {[x.value for x in cls]}"
+        )
+
+
+@dataclasses.dataclass(frozen=True)
+class ProfileSelectionInfo:
+    """Preferences about profiles to select."""
+
+    # A consistent timestamp for the program to run with.
+    now: datetime.datetime
+
+    # Maximum age of a profile that can be selected.
+    max_profile_age: datetime.timedelta
+
+
+def get_parser():
+    """Returns an argument parser for this script."""
+    parser = argparse.ArgumentParser(
+        description=__doc__,
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+    )
+    parser.add_argument(
+        "--debug",
+        action="store_true",
+        help="Enable debug logging.",
+    )
+    parser.add_argument(
+        "--upload",
+        action="store_true",
+        help="Automatically upload all changes that were made.",
+    )
+    parser.add_argument(
+        "--fetch",
+        action="store_true",
+        help="Run `git fetch` in toolchain-utils prior to running.",
+    )
+    parser.add_argument(
+        "--max-age-days",
+        type=int,
+        default=10,
+        help="""
+        The maximum number of days old a kernel profile can be before
+        it's ignored by this script. Default: %(default)s
+        """,
+    )
+    parser.add_argument(
+        "--chromeos-tree",
+        type=Path,
+        help="""
+        Root of a ChromeOS tree. This is optional to pass in, but doing so
+        unlocks extra convenience features on `--upload`. This script will try
+        to autodetect a tree if this isn't specified.
+        """,
+    )
+    parser.add_argument(
+        "channel",
+        nargs="*",
+        type=Channel.parse,
+        default=list(Channel),
+        help=f"""
+        Channel(s) to update. If none are passed, this will update all
+        channels. Choose from {[x.value for x in Channel]}.
+        """,
+    )
+    return parser
+
+
+@dataclasses.dataclass(frozen=True, eq=True, order=True)
+class GitBranch:
+    """Represents a ChromeOS branch."""
+
+    remote: str
+    release_number: int
+    branch_name: str
+
+
+def git_checkout(git_dir: Path, branch: GitBranch) -> None:
+    subprocess.run(
+        [
+            "git",
+            "checkout",
+            "--quiet",
+            f"{branch.remote}/{branch.branch_name}",
+        ],
+        check=True,
+        cwd=git_dir,
+        stdin=subprocess.DEVNULL,
+    )
+
+
+def git_fetch(git_dir: Path) -> None:
+    subprocess.run(
+        ["git", "fetch"],
+        check=True,
+        cwd=git_dir,
+        stdin=subprocess.DEVNULL,
+    )
+
+
+def git_rev_parse(git_dir: Path, ref_or_sha: str) -> str:
+    return subprocess.run(
+        ["git", "rev-parse", ref_or_sha],
+        check=True,
+        cwd=git_dir,
+        stdin=subprocess.DEVNULL,
+        stdout=subprocess.PIPE,
+        encoding="utf-8",
+    ).stdout.strip()
+
+
+def autodetect_branches(toolchain_utils: Path) -> Dict[Channel, GitBranch]:
+    """Returns GitBranches for each branch type in toolchain_utils."""
+    stdout = subprocess.run(
+        [
+            "git",
+            "branch",
+            "-r",
+        ],
+        cwd=toolchain_utils,
+        check=True,
+        stdin=subprocess.DEVNULL,
+        stdout=subprocess.PIPE,
+        encoding="utf-8",
+    ).stdout
+
+    # Match "${remote}/release-R${branch_number}-${build}.B"
+    branch_re = re.compile(r"([^/]+)/(release-R(\d+)-\d+\.B)")
+    branches = []
+    for line in stdout.splitlines():
+        line = line.strip()
+        if m := branch_re.fullmatch(line):
+            remote, branch_name, branch_number = m.groups()
+            branches.append(GitBranch(remote, int(branch_number), branch_name))
+
+    branches.sort(key=lambda x: x.release_number)
+    if len(branches) < 2:
+        raise ValueError(
+            f"Expected at least two branches, but only found {len(branches)}"
+        )
+
+    stable = branches[-2]
+    beta = branches[-1]
+    canary = GitBranch(
+        remote=beta.remote,
+        release_number=beta.release_number + 1,
+        branch_name="main",
+    )
+    return {
+        Channel.CANARY: canary,
+        Channel.BETA: beta,
+        Channel.STABLE: stable,
+    }
+
+
+@dataclasses.dataclass(frozen=True, eq=True, order=True)
+class ArchUpdateConfig:
+    """The AFDO update config for one architecture."""
+
+    versions_to_track: List[KernelVersion]
+    metadata_file: Path
+
+
+def read_update_cfg_file(
+    toolchain_utils: Path, file_path: Path
+) -> Dict[Arch, ArchUpdateConfig]:
+    """Reads `update_kernel_afdo.cfg`."""
+    # These files were originally meant to be `source`d in bash, and are very
+    # simple. These are read from branches, so we'd need cherry-picks to go
+    # back and replace them with a singular format. Could be nice to move to
+    # JSON or something.
+
+    # Parse assignments that look like `FOO="bar"`. No escaping or variable
+    # expansion is supported.
+    kv_re = re.compile(r'^([a-zA-Z_0-9]+)="([^"]*)"(?:\s*#.*)?', re.MULTILINE)
+    kvs = kv_re.findall(file_path.read_text(encoding="utf-8"))
+    # Subtle: the regex above makes it so `kv_re.findall` returns a series of
+    # (variable_name, variable_value).
+    settings = dict(kvs)
+
+    logging.debug("Parsing cfg file gave back settings: %s", settings)
+    archs = (
+        (Arch.AMD64, "AMD"),
+        (Arch.ARM, "ARM"),
+    )
+
+    results = {}
+    for arch, arch_var_name in archs:
+        # This is a space-separated list of kernel versions.
+        kernel_versions = settings[f"{arch_var_name}_KVERS"]
+        parsed_versions = [
+            KernelVersion.parse(x) for x in kernel_versions.split()
+        ]
+
+        metadata_file = settings[f"{arch_var_name}_METADATA_FILE"]
+        results[arch] = ArchUpdateConfig(
+            versions_to_track=parsed_versions,
+            metadata_file=toolchain_utils / metadata_file,
+        )
+    return results
+
+
+@dataclasses.dataclass(frozen=True, eq=True)
+class KernelGsProfile:
+    """Represents a kernel profile in gs://."""
+
+    release_number: int
+    chrome_build: str
+    cwp_timestamp: int
+    suffix: str
+    gs_timestamp: datetime.datetime
+
+    _FILE_NAME_PARSE_RE = re.compile(r"R(\d+)-(\d+\.\d+)-(\d+)(\..+\..+)")
+
+    @property
+    def file_name_no_suffix(self):
+        return (
+            f"R{self.release_number}-{self.chrome_build}-{self.cwp_timestamp}"
+        )
+
+    @property
+    def file_name(self):
+        return f"{self.file_name_no_suffix}{self.suffix}"
+
+    @classmethod
+    def from_file_name(
+        cls, timestamp: datetime.datetime, file_name: str
+    ) -> "KernelGsProfile":
+        m = cls._FILE_NAME_PARSE_RE.fullmatch(file_name)
+        if not m:
+            raise ValueError(f"{file_name!r} doesn't parse as a profile name")
+        release_number, chrome_build, cwp_timestamp, suffix = m.groups()
+        return cls(
+            release_number=int(release_number),
+            chrome_build=chrome_build,
+            cwp_timestamp=int(cwp_timestamp),
+            suffix=suffix,
+            gs_timestamp=timestamp,
+        )
+
+
+def datetime_from_gs_time(timestamp_str: str) -> datetime.datetime:
+    """Parses a datetime from gs."""
+    return datetime.datetime.strptime(
+        timestamp_str, "%Y-%m-%dT%H:%M:%SZ"
+    ).replace(tzinfo=datetime.timezone.utc)
+
+
+class KernelProfileFetcher:
+    """Fetches kernel profiles from gs://. Caches results."""
+
+    def __init__(self):
+        self._cached_results: Dict[str, List[KernelGsProfile]] = {}
+
+    @staticmethod
+    def _parse_gs_stdout(stdout: str) -> List[KernelGsProfile]:
+        line_re = re.compile(r"\s*\d+\s+(\S+T\S+)\s+(gs://.+)")
+        results = []
+        # Ignore the last line, since that's "TOTAL:"
+        for line in stdout.splitlines()[:-1]:
+            line = line.strip()
+            if not line:
+                continue
+            m = line_re.fullmatch(line)
+            if m is None:
+                raise ValueError(f"Unexpected line from gs: {line!r}")
+            timestamp_str, gs_url = m.groups()
+            timestamp = datetime_from_gs_time(timestamp_str)
+            file_name = os.path.basename(gs_url)
+            results.append(KernelGsProfile.from_file_name(timestamp, file_name))
+        return results
+
+    @classmethod
+    def _fetch_impl(cls, gs_url: str) -> List[KernelGsProfile]:
+        cmd = [
+            GSUTIL,
+            "ls",
+            "-l",
+            gs_url,
+        ]
+        result = subprocess.run(
+            cmd,
+            check=False,
+            stdin=subprocess.DEVNULL,
+            stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE,
+            encoding="utf-8",
+        )
+
+        if result.returncode:
+            # If nothing could be found, gsutil will exit after printing this.
+            if "One or more URLs matched no objects." in result.stderr:
+                return []
+            logging.error(
+                "%s failed; stderr:\n%s", shlex.join(cmd), result.stderr
+            )
+            result.check_returncode()
+            assert False, "unreachable"
+
+        return cls._parse_gs_stdout(result.stdout)
+
+    def fetch(self, gs_url: str) -> List[KernelGsProfile]:
+        cached = self._cached_results.get(gs_url)
+        if cached is None:
+            logging.info("Fetching profiles from %s...", gs_url)
+            fetched = self._fetch_impl(gs_url)
+            logging.info("Found %d profiles in %s", len(fetched), gs_url)
+            self._cached_results[gs_url] = fetched
+            cached = fetched
+
+        # Create a copy to keep mutations from causing problems.
+        # KernelGsProfiles are frozen, at least.
+        return cached[:]
+
+
+def find_newest_afdo_artifact(
+    fetcher: KernelProfileFetcher,
+    arch: Arch,
+    kernel_version: KernelVersion,
+    release_number: int,
+) -> Optional[KernelGsProfile]:
+    """Returns info about the latest AFDO artifact for the given parameters."""
+    gs_base_location = arch.cwp_gs_location
+    kernel_profile_dir = os.path.join(gs_base_location, str(kernel_version))
+    kernel_profiles = fetcher.fetch(kernel_profile_dir)
+    if not kernel_profiles:
+        logging.error(
+            "Failed to find any kernel profiles in %s", kernel_profile_dir
+        )
+        return None
+
+    valid_profiles = [
+        x for x in kernel_profiles if x.release_number == release_number
+    ]
+    if not valid_profiles:
+        logging.warning(
+            "Failed to find any M%d kernel profiles in %s",
+            release_number,
+            kernel_profile_dir,
+        )
+        return None
+
+    # We want the most recently uploaded profile, since that should correspond
+    # with the newest profile. If there're multiple profiles for some reason,
+    # choose what _should_ be a consistent tie-breaker.
+    return max(
+        valid_profiles,
+        key=lambda x: (x.gs_timestamp, x.cwp_timestamp, x.chrome_build),
+    )
+
+
+def read_afdo_descriptor_file(path: Path) -> Dict[KernelVersion, str]:
+    """Reads the AFDO descriptor file.
+
+    "AFDO descriptor file" is jargon to refer to the actual JSON file that PUpr
+    monitors.
+    """
+    try:
+        with path.open(encoding="utf-8") as f:
+            raw_contents = json.load(f)
+    except FileNotFoundError:
+        return {}
+
+    # The format of this is:
+    # {
+    #   "chromeos-kernel-${major}_${minor}": {
+    #     "name": "${profile_gs_name}",
+    #   }
+    # }
+    key_re = re.compile(r"^chromeos-kernel-(\d)+_(\d+)$")
+    result = {}
+    for kernel_key, val in raw_contents.items():
+        m = key_re.fullmatch(kernel_key)
+        if not m:
+            raise ValueError(f"Invalid key in JSON: {kernel_key}")
+        major, minor = m.groups()
+        version = KernelVersion(major=int(major), minor=int(minor))
+        result[version] = val["name"]
+    return result
+
+
+def write_afdo_descriptor_file(
+    path: Path, contents: Dict[KernelVersion, str]
+) -> bool:
+    """Writes the file at path with the given contents.
+
+    Returns:
+        True if the file was written due to changes, False otherwise.
+    """
+    contents_dict = {
+        f"chromeos-kernel-{k.major}_{k.minor}": {"name": gs_name}
+        for k, gs_name in contents.items()
+    }
+
+    contents_json = json.dumps(contents_dict, indent=4, sort_keys=True)
+    try:
+        existing_contents = path.read_text(encoding="utf-8")
+    except FileNotFoundError:
+        existing_contents = ""
+
+    # Compare the _textual representation_ of each of these, since things like
+    # formatting changes should be propagated eagerly.
+    if contents_json == existing_contents:
+        return False
+
+    tmp_path = path.with_suffix(".json.tmp")
+    tmp_path.write_text(contents_json, encoding="utf-8")
+    tmp_path.rename(path)
+    return True
+
+
+@dataclasses.dataclass
+class UpdateResult:
+    """Result of `update_afdo_for_channel`."""
+
+    # True if changes were made to the AFDO files that map kernel versions to
+    # AFDO profiles.
+    made_changes: bool
+
+    # Whether issues were had updating one or more profiles. If this is True,
+    # you may expect that there will be logs about the issues already.
+    had_failures: bool
+
+
+def fetch_and_validate_newest_afdo_artifact(
+    fetcher: KernelProfileFetcher,
+    selection_info: ProfileSelectionInfo,
+    arch: Arch,
+    kernel_version: KernelVersion,
+    branch: GitBranch,
+    channel: Channel,
+) -> Optional[Tuple[str, bool]]:
+    """Tries to update one AFDO profile on a branch.
+
+    Returns:
+        None if something failed, and the update couldn't be completed.
+        Otherwise, this returns a tuple of (profile_name, is_old). If `is_old`
+        is True, this function logs an error.
+    """
+    newest_artifact = find_newest_afdo_artifact(
+        fetcher, arch, kernel_version, branch.release_number
+    )
+    # Try an older branch if we're not on stable. We should fail harder if we
+    # only have old profiles on stable, though.
+    if newest_artifact is None and channel != Channel.STABLE:
+        newest_artifact = find_newest_afdo_artifact(
+            fetcher, arch, kernel_version, branch.release_number - 1
+        )
+
+    if newest_artifact is None:
+        logging.error(
+            "No new profile found for %s/%s on M%d; not updating entry",
+            arch,
+            kernel_version,
+            branch.release_number,
+        )
+        return None
+
+    logging.info(
+        "Newest profile is %s for %s/%s on M%d",
+        newest_artifact.file_name,
+        arch,
+        kernel_version,
+        branch.release_number,
+    )
+    age = selection_info.now - newest_artifact.gs_timestamp
+    is_old = False
+    if age > selection_info.max_profile_age:
+        is_old = True
+        logging.error(
+            "Profile %s is %s old. The configured limit is %s.",
+            newest_artifact.file_name,
+            age,
+            selection_info.max_profile_age,
+        )
+    return newest_artifact.file_name_no_suffix, is_old
+
+
+def update_afdo_for_channel(
+    fetcher: KernelProfileFetcher,
+    toolchain_utils: Path,
+    selection_info: ProfileSelectionInfo,
+    channel: Channel,
+    branch: GitBranch,
+    skipped_versions: Dict[int, Iterable[Tuple[Arch, KernelVersion]]],
+) -> UpdateResult:
+    """Updates AFDO on the given channel."""
+    git_checkout(toolchain_utils, branch)
+    update_cfgs = read_update_cfg_file(
+        toolchain_utils,
+        toolchain_utils / "afdo_tools" / "update_kernel_afdo.cfg",
+    )
+
+    to_skip = skipped_versions.get(branch.release_number)
+    made_changes = False
+    had_failures = False
+    for arch, cfg in update_cfgs.items():
+        afdo_mappings = read_afdo_descriptor_file(cfg.metadata_file)
+        for kernel_version in cfg.versions_to_track:
+            if to_skip and (arch, kernel_version) in to_skip:
+                logging.info(
+                    "%s/%s on M%d is in the skip list; ignoring it.",
+                    arch,
+                    kernel_version,
+                    branch.release_number,
+                )
+                continue
+
+            artifact_info = fetch_and_validate_newest_afdo_artifact(
+                fetcher,
+                selection_info,
+                arch,
+                kernel_version,
+                branch,
+                channel,
+            )
+            if artifact_info is None:
+                # Assume that the problem was already logged.
+                had_failures = True
+                continue
+
+            newest_name, is_old = artifact_info
+            if is_old:
+                # Assume that the problem was already logged, but continue to
+                # land this in case it makes a difference.
+                had_failures = True
+
+            afdo_mappings[kernel_version] = newest_name
+
+        if write_afdo_descriptor_file(cfg.metadata_file, afdo_mappings):
+            made_changes = True
+            logging.info(
+                "Wrote new AFDO mappings for arch %s on M%d",
+                arch,
+                branch.release_number,
+            )
+        else:
+            logging.info(
+                "No changes to write for arch %s on M%d",
+                arch,
+                branch.release_number,
+            )
+    return UpdateResult(
+        made_changes=made_changes,
+        had_failures=had_failures,
+    )
+
+
+def commit_new_profiles(
+    toolchain_utils: Path, channel: Channel, had_failures: bool
+):
+    """Runs `git commit -a` with an appropriate message."""
+    commit_message_lines = [
+        "afdo_metadata: Publish the new kernel profiles",
+        "",
+    ]
+
+    if had_failures:
+        commit_message_lines += (
+            "This brings some profiles to their newest versions. The CrOS",
+            "toolchain detective has been notified about the failures that",
+            "occurred in this update.",
+        )
+    else:
+        commit_message_lines.append(
+            "This brings all profiles to their newest versions."
+        )
+
+    if channel != Channel.CANARY:
+        commit_message_lines += (
+            "",
+            "Have PM pre-approval because this shouldn't break the release",
+            "branch.",
+        )
+
+    commit_message_lines += (
+        "",
+        "BUG=None",
+        "TEST=Verified in kernel-release-afdo-verify-orchestrator",
+    )
+
+    commit_msg = "\n".join(commit_message_lines)
+    subprocess.run(
+        [
+            "git",
+            "commit",
+            "--quiet",
+            "-a",
+            "-m",
+            commit_msg,
+        ],
+        cwd=toolchain_utils,
+        check=True,
+        stdin=subprocess.DEVNULL,
+    )
+
+
+def upload_head_to_gerrit(
+    toolchain_utils: Path,
+    chromeos_tree: Optional[Path],
+    branch: GitBranch,
+):
+    """Uploads HEAD to gerrit as a CL, and sets reviewers/CCs."""
+    cl_ids = git_utils.upload_to_gerrit(
+        toolchain_utils,
+        branch.remote,
+        branch.branch_name,
+        CL_REVIEWERS,
+        CL_CC,
+    )
+
+    if len(cl_ids) > 1:
+        raise ValueError(f"Unexpected: wanted just one CL upload; got {cl_ids}")
+
+    cl_id = cl_ids[0]
+    logging.info("Uploaded CL http://crrev.com/c/%s successfully.", cl_id)
+
+    if chromeos_tree is None:
+        logging.info(
+            "Skipping gerrit convenience commands, since no CrOS tree was "
+            "specified."
+        )
+        return
+
+    git_utils.try_set_autosubmit_labels(chromeos_tree, cl_id)
+
+
+def find_chromeos_tree_root(a_dir: Path) -> Optional[Path]:
+    for parent in a_dir.parents:
+        if (parent / ".repo").is_dir():
+            return parent
+    return None
+
+
+def main(argv: List[str]) -> None:
+    my_dir = Path(__file__).resolve().parent
+    toolchain_utils = my_dir.parent
+
+    opts = get_parser().parse_args(argv)
+    logging.basicConfig(
+        format=">> %(asctime)s: %(levelname)s: %(filename)s:%(lineno)d: "
+        "%(message)s",
+        level=logging.DEBUG if opts.debug else logging.INFO,
+    )
+
+    chromeos_tree = opts.chromeos_tree
+    if not chromeos_tree:
+        chromeos_tree = find_chromeos_tree_root(my_dir)
+        if chromeos_tree:
+            logging.info("Autodetected ChromeOS tree root at %s", chromeos_tree)
+
+    if opts.fetch:
+        logging.info("Fetching in %s...", toolchain_utils)
+        git_fetch(toolchain_utils)
+
+    selection_info = ProfileSelectionInfo(
+        now=datetime.datetime.now(datetime.timezone.utc),
+        max_profile_age=datetime.timedelta(days=opts.max_age_days),
+    )
+
+    branches = autodetect_branches(toolchain_utils)
+    logging.debug("Current branches: %s", branches)
+
+    assert all(x in branches for x in Channel), "branches are missing channels?"
+
+    fetcher = KernelProfileFetcher()
+    had_failures = False
+    with git_utils.create_worktree(toolchain_utils) as worktree:
+        for channel in opts.channel:
+            branch = branches[channel]
+            result = update_afdo_for_channel(
+                fetcher,
+                worktree,
+                selection_info,
+                channel,
+                branch,
+                SKIPPED_VERSIONS,
+            )
+            had_failures = had_failures or result.had_failures
+            if not result.made_changes:
+                logging.info("No new updates to post on %s", channel)
+                continue
+
+            commit_new_profiles(worktree, channel, result.had_failures)
+            if opts.upload:
+                logging.info("New profiles were committed. Uploading...")
+                upload_head_to_gerrit(worktree, chromeos_tree, branch)
+            else:
+                logging.info(
+                    "--upload not specified. Leaving commit for %s at %s",
+                    channel,
+                    git_rev_parse(worktree, "HEAD"),
+                )
+
+    if had_failures:
+        sys.exit(
+            "At least one failure was encountered running this script; see "
+            "above logs. Most likely the things you're looking for are logged "
+            "at the ERROR level."
+        )
+
+
+if __name__ == "__main__":
+    main(sys.argv[1:])
diff --git a/afdo_tools/update_kernel_afdo_test.py b/afdo_tools/update_kernel_afdo_test.py
new file mode 100755
index 0000000..1f36595
--- /dev/null
+++ b/afdo_tools/update_kernel_afdo_test.py
@@ -0,0 +1,304 @@
+#!/usr/bin/env python3
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Tests for update_kernel_afdo."""
+
+import datetime
+from pathlib import Path
+import shutil
+import subprocess
+import tempfile
+import textwrap
+import unittest
+from unittest import mock
+
+import update_kernel_afdo
+
+
+class Test(unittest.TestCase):
+    """Tests for update_kernel_afdo."""
+
+    def make_tempdir(self) -> Path:
+        x = Path(tempfile.mkdtemp(prefix="update_kernel_afdo_test_"))
+        self.addCleanup(shutil.rmtree, x)
+        return x
+
+    def test_kernel_version_parsing(self):
+        self.assertEqual(
+            update_kernel_afdo.KernelVersion.parse("5.10"),
+            update_kernel_afdo.KernelVersion(major=5, minor=10),
+        )
+
+        with self.assertRaisesRegex(ValueError, ".*invalid kernel version.*"):
+            update_kernel_afdo.KernelVersion.parse("5")
+
+    def test_kernel_version_formatting(self):
+        self.assertEqual(
+            str(update_kernel_afdo.KernelVersion(major=5, minor=10)), "5.10"
+        )
+
+    def test_channel_parsing(self):
+        with self.assertRaisesRegex(ValueError, "No such channel.*"):
+            update_kernel_afdo.Channel.parse("not a channel")
+
+        # Ensure these round-trip.
+        for channel in update_kernel_afdo.Channel:
+            self.assertEqual(
+                channel, update_kernel_afdo.Channel.parse(channel.value)
+            )
+
+    @mock.patch.object(subprocess, "run")
+    def test_branch_autodetection(self, subprocess_run):
+        subprocess_run.return_value = subprocess.CompletedProcess(
+            args=[],
+            returncode=0,
+            stdout=textwrap.dedent(
+                """
+                cros/not-a-release-branch
+                cros/release-R121-15699.B
+                cros/release-R122-15753.B
+                cros/release-R123-15786.B
+                cros/also-not-a-release-branch
+                m/main
+                """
+            ),
+        )
+
+        branch_dict = update_kernel_afdo.autodetect_branches(
+            toolchain_utils=self.make_tempdir()
+        )
+
+        self.assertEqual(
+            branch_dict,
+            {
+                update_kernel_afdo.Channel.CANARY: update_kernel_afdo.GitBranch(
+                    remote="cros",
+                    release_number=124,
+                    branch_name="main",
+                ),
+                update_kernel_afdo.Channel.BETA: update_kernel_afdo.GitBranch(
+                    remote="cros",
+                    release_number=123,
+                    branch_name="release-R123-15786.B",
+                ),
+                update_kernel_afdo.Channel.STABLE: update_kernel_afdo.GitBranch(
+                    remote="cros",
+                    release_number=122,
+                    branch_name="release-R122-15753.B",
+                ),
+            },
+        )
+
+    def test_read_update_cfg_file(self):
+        valid_contents = textwrap.dedent(
+            """
+            # some comment
+            # wow
+            AMD_KVERS="1.0 1.1"
+            ARM_KVERS="1.2"
+            AMD_METADATA_FILE="amd/file/path.json" # comment
+            ARM_METADATA_FILE="arm/file/path.json"
+            """
+        )
+        tmpdir = self.make_tempdir()
+        cfg_path = tmpdir / "test.cfg"
+        cfg_path.write_text(valid_contents, encoding="utf-8")
+        cfg = update_kernel_afdo.read_update_cfg_file(tmpdir, cfg_path)
+        expected_amd64 = update_kernel_afdo.ArchUpdateConfig(
+            versions_to_track=[
+                update_kernel_afdo.KernelVersion(1, 0),
+                update_kernel_afdo.KernelVersion(1, 1),
+            ],
+            metadata_file=tmpdir / "amd/file/path.json",
+        )
+        expected_arm = update_kernel_afdo.ArchUpdateConfig(
+            versions_to_track=[
+                update_kernel_afdo.KernelVersion(1, 2),
+            ],
+            metadata_file=tmpdir / "arm/file/path.json",
+        )
+
+        self.assertEqual(
+            cfg,
+            {
+                update_kernel_afdo.Arch.AMD64: expected_amd64,
+                update_kernel_afdo.Arch.ARM: expected_arm,
+            },
+        )
+
+    def test_parse_kernel_gs_profile(self):
+        timestamp = datetime.datetime.fromtimestamp(1234, datetime.timezone.utc)
+        profile = update_kernel_afdo.KernelGsProfile.from_file_name(
+            timestamp,
+            "R124-15808.0-1710149961.gcov.xz",
+        )
+        self.assertEqual(
+            profile,
+            update_kernel_afdo.KernelGsProfile(
+                release_number=124,
+                chrome_build="15808.0",
+                cwp_timestamp=1710149961,
+                suffix=".gcov.xz",
+                gs_timestamp=timestamp,
+            ),
+        )
+
+    def test_kernel_gs_profile_file_name(self):
+        timestamp = datetime.datetime.fromtimestamp(1234, datetime.timezone.utc)
+        profile = update_kernel_afdo.KernelGsProfile.from_file_name(
+            timestamp,
+            "R124-15808.0-1710149961.gcov.xz",
+        )
+        self.assertEqual(profile.file_name_no_suffix, "R124-15808.0-1710149961")
+        self.assertEqual(profile.file_name, "R124-15808.0-1710149961.gcov.xz")
+
+    def test_gs_time_parsing(self):
+        self.assertEqual(
+            update_kernel_afdo.datetime_from_gs_time("2024-03-04T10:38:50Z"),
+            datetime.datetime(
+                year=2024,
+                month=3,
+                day=4,
+                hour=10,
+                minute=38,
+                second=50,
+                tzinfo=datetime.timezone.utc,
+            ),
+        )
+
+    @mock.patch.object(subprocess, "run")
+    def test_kernel_profile_fetcher_works(self, subprocess_run):
+        subprocess_run.return_value = subprocess.CompletedProcess(
+            args=[],
+            returncode=0,
+            # Don't use textwrap.dedent; linter complains about the line being
+            # too long in that case.
+            stdout="""
+753112  2024-03-04T10:38:50Z gs://here/5.4/R124-15786.10-1709548729.gcov.xz
+TOTAL: 2 objects, 1234 bytes (1.1KiB)
+""",
+        )
+
+        fetcher = update_kernel_afdo.KernelProfileFetcher()
+        results = fetcher.fetch("gs://here/5.4")
+
+        expected_results = [
+            update_kernel_afdo.KernelGsProfile.from_file_name(
+                update_kernel_afdo.datetime_from_gs_time(
+                    "2024-03-04T10:38:50Z"
+                ),
+                "R124-15786.10-1709548729.gcov.xz",
+            ),
+        ]
+        self.assertEqual(results, expected_results)
+
+    @mock.patch.object(subprocess, "run")
+    def test_kernel_profile_fetcher_handles_no_profiles(self, subprocess_run):
+        subprocess_run.return_value = subprocess.CompletedProcess(
+            args=[],
+            returncode=1,
+            stderr="\nCommandException: One or more URLs matched no objects.\n",
+        )
+
+        fetcher = update_kernel_afdo.KernelProfileFetcher()
+        results = fetcher.fetch("gs://here/5.4")
+        self.assertEqual(results, [])
+
+    @mock.patch.object(subprocess, "run")
+    def test_kernel_profile_fetcher_caches_urls(self, subprocess_run):
+        subprocess_run.return_value = subprocess.CompletedProcess(
+            args=[],
+            returncode=0,
+            # Don't use textwrap.dedent; linter complains about the line being
+            # too long in that case.
+            stdout="""
+753112  2024-03-04T10:38:50Z gs://here/5.4/R124-15786.10-1709548729.gcov.xz
+TOTAL: 2 objects, 1234 bytes (1.1KiB)
+""",
+        )
+
+        fetcher = update_kernel_afdo.KernelProfileFetcher()
+        # Fetch these twice, and assert both that:
+        # - Only one fetch is performed.
+        # - Mutating the first list won't impact the later fetch.
+        result = fetcher.fetch("gs://here/5.4")
+        self.assertEqual(len(result), 1)
+        del result[:]
+        result = fetcher.fetch("gs://here/5.4")
+        self.assertEqual(len(result), 1)
+        subprocess_run.assert_called_once()
+
+    @mock.patch.object(update_kernel_afdo.KernelProfileFetcher, "fetch")
+    def test_newest_afdo_artifact_finding_works(self, fetch):
+        late = update_kernel_afdo.KernelGsProfile.from_file_name(
+            datetime.datetime.fromtimestamp(1236, datetime.timezone.utc),
+            "R124-15786.10-1709548729.gcov.xz",
+        )
+        early = update_kernel_afdo.KernelGsProfile.from_file_name(
+            datetime.datetime.fromtimestamp(1234, datetime.timezone.utc),
+            "R124-99999.99-9999999999.gcov.xz",
+        )
+        fetch.return_value = [early, late]
+
+        self.assertEqual(
+            update_kernel_afdo.find_newest_afdo_artifact(
+                update_kernel_afdo.KernelProfileFetcher(),
+                update_kernel_afdo.Arch.AMD64,
+                update_kernel_afdo.KernelVersion(5, 4),
+                release_number=124,
+            ),
+            late,
+        )
+
+    def test_afdo_descriptor_file_round_trips(self):
+        tmpdir = self.make_tempdir()
+        file_path = tmpdir / "desc-file.json"
+
+        contents = {
+            update_kernel_afdo.KernelVersion(5, 10): "file1",
+            update_kernel_afdo.KernelVersion(5, 15): "file2",
+        }
+        self.assertTrue(
+            update_kernel_afdo.write_afdo_descriptor_file(file_path, contents)
+        )
+        self.assertEqual(
+            update_kernel_afdo.read_afdo_descriptor_file(file_path),
+            contents,
+        )
+
+    def test_afdo_descriptor_file_refuses_to_rewrite_identical_contents(self):
+        tmpdir = self.make_tempdir()
+        file_path = tmpdir / "desc-file.json"
+
+        contents = {
+            update_kernel_afdo.KernelVersion(5, 10): "file1",
+            update_kernel_afdo.KernelVersion(5, 15): "file2",
+        }
+        self.assertTrue(
+            update_kernel_afdo.write_afdo_descriptor_file(file_path, contents)
+        )
+        self.assertFalse(
+            update_kernel_afdo.write_afdo_descriptor_file(file_path, contents)
+        )
+
+    def test_repo_autodetects_nothing_if_no_repo_dir(self):
+        self.assertIsNone(
+            update_kernel_afdo.find_chromeos_tree_root(
+                Path("/does/not/exist/nor/is/under/a/repo")
+            )
+        )
+
+    def test_repo_autodetects_repo_dir_correctly(self):
+        tmpdir = self.make_tempdir()
+        test_subdir = tmpdir / "a/directory/and/another/one"
+        test_subdir.mkdir(parents=True)
+        (tmpdir / ".repo").mkdir()
+        self.assertEqual(
+            tmpdir, update_kernel_afdo.find_chromeos_tree_root(test_subdir)
+        )
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/auto_abandon_cls.py b/auto_abandon_cls.py
new file mode 100755
index 0000000..ae78bfa
--- /dev/null
+++ b/auto_abandon_cls.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python3
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Abandons CLs from the current user that haven't been updated recently.
+
+Note that this needs to be run from inside a ChromeOS tree. Otherwise, the
+`gerrit` tool this depends on won't be found.
+"""
+
+import argparse
+import logging
+import subprocess
+import sys
+from typing import List
+
+
+def gerrit_cmd(internal: bool) -> List[str]:
+    cmd = ["gerrit"]
+    if internal:
+        cmd.append("--internal")
+    return cmd
+
+
+def enumerate_old_cls(old_days: int, internal: bool) -> List[int]:
+    """Returns CL numbers that haven't been updated in `old_days` days."""
+    stdout = subprocess.run(
+        gerrit_cmd(internal)
+        + ["--raw", "search", f"owner:me status:open age:{old_days}d"],
+        check=True,
+        stdin=subprocess.DEVNULL,
+        stdout=subprocess.PIPE,
+        encoding="utf-8",
+    ).stdout
+    # Sort for prettier output; it's unclear if Gerrit always sorts, and it's
+    # cheap.
+    lines = stdout.splitlines()
+    if internal:
+        # These are printed as `chrome-internal:NNNN`, rather than `NNNN`.
+        chrome_internal_prefix = "chrome-internal:"
+        assert all(x.startswith(chrome_internal_prefix) for x in lines), lines
+        lines = [x[len(chrome_internal_prefix) :] for x in lines]
+    return sorted(int(x) for x in lines)
+
+
+def abandon_cls(cls: List[int], internal: bool) -> None:
+    subprocess.run(
+        gerrit_cmd(internal) + ["abandon"] + [str(x) for x in cls],
+        check=True,
+        stdin=subprocess.DEVNULL,
+    )
+
+
+def detect_and_abandon_cls(
+    old_days: int, dry_run: bool, internal: bool
+) -> None:
+    old_cls = enumerate_old_cls(old_days, internal)
+    if not old_cls:
+        logging.info("No CLs less than %d days old found; quit", old_days)
+        return
+
+    cl_namespace = "i" if internal else "c"
+    logging.info(
+        "Abandoning CLs: %s", [f"crrev.com/{cl_namespace}/{x}" for x in old_cls]
+    )
+    if dry_run:
+        logging.info("--dry-run specified; skip the actual abandon part")
+        return
+
+    abandon_cls(old_cls, internal)
+
+
+def main(argv: List[str]) -> None:
+    logging.basicConfig(
+        format=">> %(asctime)s: %(levelname)s: %(filename)s:%(lineno)d: "
+        "%(message)s",
+        level=logging.INFO,
+    )
+
+    parser = argparse.ArgumentParser(
+        description=__doc__,
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+    )
+    parser.add_argument(
+        "--old-days",
+        default=14,
+        type=int,
+        help="""
+        How many days a CL needs to go without modification to be considered
+        'old'.
+        """,
+    )
+    parser.add_argument(
+        "--dry-run",
+        action="store_true",
+        help="Don't actually run the abandon command.",
+    )
+    opts = parser.parse_args(argv)
+
+    logging.info("Checking for external CLs...")
+    detect_and_abandon_cls(
+        old_days=opts.old_days,
+        dry_run=opts.dry_run,
+        internal=False,
+    )
+    logging.info("Checking for internal CLs...")
+    detect_and_abandon_cls(
+        old_days=opts.old_days,
+        dry_run=opts.dry_run,
+        internal=True,
+    )
+
+
+if __name__ == "__main__":
+    main(sys.argv[1:])
diff --git a/auto_delete_nightly_test_data.py b/auto_delete_nightly_test_data.py
deleted file mode 100755
index 06d0206..0000000
--- a/auto_delete_nightly_test_data.py
+++ /dev/null
@@ -1,266 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2019 The ChromiumOS Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""A crontab script to delete night test data."""
-
-__author__ = "shenhan@google.com (Han Shen)"
-
-import argparse
-import os
-from pathlib import Path
-import shutil
-import stat
-import sys
-import time
-import traceback
-from typing import Callable, List
-
-from cros_utils import command_executer
-from cros_utils import constants
-
-
-def ProcessArguments(argv):
-    """Process arguments."""
-    parser = argparse.ArgumentParser(
-        description="Automatically delete nightly test data directories.",
-        usage="auto_delete_nightly_test_data.py options",
-    )
-    parser.add_argument(
-        "-d",
-        "--dry_run",
-        dest="dry_run",
-        default=False,
-        action="store_true",
-        help="Only print command line, do not execute anything.",
-    )
-    parser.add_argument(
-        "--days_to_preserve",
-        dest="days_to_preserve",
-        default=3,
-        help=(
-            "Specify the number of days (not including today),"
-            " test data generated on these days will *NOT* be "
-            "deleted. Defaults to 3."
-        ),
-    )
-    options = parser.parse_args(argv)
-    return options
-
-
-def RemoveAllSubdirsMatchingPredicate(
-    base_dir: Path,
-    days_to_preserve: int,
-    dry_run: bool,
-    is_name_removal_worthy: Callable[[str], bool],
-) -> int:
-    """Removes all subdirs of base_dir that match the given predicate."""
-    secs_to_preserve = 60 * 60 * 24 * days_to_preserve
-    now = time.time()
-    remove_older_than_time = now - secs_to_preserve
-
-    try:
-        dir_entries = list(base_dir.iterdir())
-    except FileNotFoundError as e:
-        # We get this if the directory itself doesn't exist. Since we're
-        # cleaning tempdirs, that's as good as a success. Further, the prior
-        # approach here was using the `find` binary, which exits successfully
-        # if nothing is found.
-        print(f"Error enumerating {base_dir}'s contents; skipping removal: {e}")
-        return 0
-
-    had_errors = False
-    for file in dir_entries:
-        if not is_name_removal_worthy(file.name):
-            continue
-
-        try:
-            # Take the stat here and use that later, so we only need to check
-            # for a nonexistent file once.
-            st = file.stat()
-        except FileNotFoundError:
-            # This was deleted while were checking; ignore it.
-            continue
-
-        if not stat.S_ISDIR(st.st_mode):
-            continue
-
-        if secs_to_preserve and st.st_atime >= remove_older_than_time:
-            continue
-
-        if dry_run:
-            print(f"Would remove {file}")
-            continue
-
-        this_iteration_had_errors = False
-
-        def OnError(_func, path_name, excinfo):
-            nonlocal this_iteration_had_errors
-            this_iteration_had_errors = True
-            print(f"Failed removing path at {path_name}; traceback:")
-            traceback.print_exception(*excinfo)
-
-        shutil.rmtree(file, onerror=OnError)
-
-        # Some errors can be other processes racing with us to delete things.
-        # Don't count those as an error which we complain loudly about.
-        if this_iteration_had_errors:
-            if file.exists():
-                had_errors = True
-            else:
-                print(
-                    f"Discarding removal errors for {file}; dir was still "
-                    "removed."
-                )
-
-    return 1 if had_errors else 0
-
-
-def IsChromeOsTmpDeletionCandidate(file_name: str):
-    """Returns whether the given basename can be deleted from chroot's /tmp."""
-    name_prefixes = (
-        "test_that_",
-        "cros-update",
-        "CrAU_temp_data",
-        # This might seem a bit broad, but after using custom heuristics for a
-        # while, `/tmp` was observed to have >75K files that matched all sorts
-        # of different `tmp.*` name patterns. Just remove them all.
-        "tmp",
-    )
-    return any(file_name.startswith(x) for x in name_prefixes)
-
-
-def CleanChromeOsTmpFiles(
-    chroot_tmp: str, days_to_preserve: int, dry_run: bool
-) -> int:
-    # Clean chroot/tmp/test_that_* and chroot/tmp/tmpxxxxxx, that were last
-    # accessed more than specified time ago.
-    return RemoveAllSubdirsMatchingPredicate(
-        Path(chroot_tmp),
-        days_to_preserve,
-        dry_run,
-        IsChromeOsTmpDeletionCandidate,
-    )
-
-
-def CleanChromeOsImageFiles(
-    chroot_tmp, subdir_suffix, days_to_preserve, dry_run
-):
-    # Clean files that were last accessed more than the specified time.
-    seconds_delta = days_to_preserve * 24 * 3600
-    now = time.time()
-    errors = 0
-
-    for tmp_dir in os.listdir(chroot_tmp):
-        # Directory under /tmp
-        tmp_dir = os.path.join(chroot_tmp, tmp_dir)
-        if tmp_dir.endswith(subdir_suffix):
-            # Tmp directory which ends with subdir_suffix.
-            for subdir in os.listdir(tmp_dir):
-                # Subdirectories targeted for deletion.
-                subdir_path = os.path.join(tmp_dir, subdir)
-                if now - os.path.getatime(subdir_path) > seconds_delta:
-                    if dry_run:
-                        print(f"Will run:\nshutil.rmtree({subdir_path!r})")
-                    else:
-                        try:
-                            shutil.rmtree(subdir_path)
-                            print(
-                                "Successfully cleaned chromeos image autotest "
-                                f"directories from {subdir_path!r}."
-                            )
-                        except OSError:
-                            print(
-                                "Some image autotest directories were not "
-                                f'"removed from {subdir_path}".'
-                            )
-                            errors += 1
-
-    return errors
-
-
-def CleanChromeOsTmpAndImages(days_to_preserve=1, dry_run=False) -> int:
-    """Delete temporaries, images under crostc/chromeos."""
-    chromeos_chroot_tmp = os.path.join(
-        constants.CROSTC_WORKSPACE, "chromeos", "out", "tmp"
-    )
-    # Clean files in tmp directory
-    rv = CleanChromeOsTmpFiles(chromeos_chroot_tmp, days_to_preserve, dry_run)
-    # Clean image files in *-tryjob directories
-    rv |= CleanChromeOsImageFiles(
-        chromeos_chroot_tmp, "-tryjob", days_to_preserve, dry_run
-    )
-    # Clean image files in *-release directories
-    rv |= CleanChromeOsImageFiles(
-        chromeos_chroot_tmp, "-release", days_to_preserve, dry_run
-    )
-    # Clean image files in *-pfq directories
-    rv |= CleanChromeOsImageFiles(
-        chromeos_chroot_tmp, "-pfq", days_to_preserve, dry_run
-    )
-    # Clean image files in *-llvm-next-nightly directories
-    rv |= CleanChromeOsImageFiles(
-        chromeos_chroot_tmp, "-llvm-next-nightly", days_to_preserve, dry_run
-    )
-
-    return rv
-
-
-def CleanOldCLs(days_to_preserve: str = "1", dry_run: bool = False) -> int:
-    """Abandon old CLs created by automation tooling."""
-    ce = command_executer.GetCommandExecuter()
-    chromeos_root = os.path.join(constants.CROSTC_WORKSPACE, "chromeos")
-    # Find Old CLs.
-    old_cls_cmd = (
-        'gerrit --raw search "owner:me status:open age:%sd"' % days_to_preserve
-    )
-    _, cls, _ = ce.ChrootRunCommandWOutput(
-        chromeos_root, old_cls_cmd, print_to_console=False
-    )
-    # Convert any whitespaces to spaces.
-    cls = " ".join(cls.split())
-    if not cls:
-        return 0
-
-    abandon_cls_cmd = "gerrit abandon %s" % cls
-    if dry_run:
-        print("Going to execute: %s" % abandon_cls_cmd)
-        return 0
-
-    return ce.ChrootRunCommand(
-        chromeos_root, abandon_cls_cmd, print_to_console=False
-    )
-
-
-def CleanChromeTelemetryTmpFiles(dry_run: bool) -> int:
-    tmp_dir = Path(constants.CROSTC_WORKSPACE) / "chrome" / "src" / "tmp"
-    return RemoveAllSubdirsMatchingPredicate(
-        tmp_dir,
-        days_to_preserve=0,
-        dry_run=dry_run,
-        is_name_removal_worthy=lambda x: x.startswith("tmp")
-        and x.endswith("telemetry_Crosperf"),
-    )
-
-
-def Main(argv: List[str]) -> int:
-    """Delete nightly test data directories, tmps and test images."""
-    options = ProcessArguments(argv)
-    ## Clean temporaries, images under crostc/chromeos
-    rv = CleanChromeOsTmpAndImages(
-        int(options.days_to_preserve), options.dry_run
-    )
-
-    # Clean CLs that are not updated in last 2 weeks.
-    rv |= CleanOldCLs("14", options.dry_run)
-
-    # Clean telemetry temporaries from chrome source tree inside chroot.
-    rv |= CleanChromeTelemetryTmpFiles(options.dry_run)
-
-    return 1 if rv else 0
-
-
-if __name__ == "__main__":
-    sys.exit(Main(sys.argv[1:]))
diff --git a/compiler_wrapper/README.md b/compiler_wrapper/README.md
index 7a05c81..38ff8a6 100644
--- a/compiler_wrapper/README.md
+++ b/compiler_wrapper/README.md
@@ -2,12 +2,9 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 
+### What
 Toolchain utils compiler wrapper sources.
 
-Build the wrapper:
-./build.py --config=<config name> --use_ccache=<bool> \
-  --use_llvm_next=<bool> --output_file=<file>
-
 Please note that there's a regular syncing operation between
 `chromiumos-overlay/sys-devel/llvm/files/compiler_wrapper` and
 `toolchain-utils/compiler_wrapper`. This sync is one way (from
@@ -15,3 +12,33 @@
 toolchain keep up-to-date with our wrapper easily, as they're a downstream
 consumer of it. For this reason, **please be sure to land all actual changes in
 chromeos-overlay**.
+
+### Build + Run Tests
+1. Install the wrapper locally in chroot (builds as well)
+```
+(chroot) ./install_compiler_wrapper.sh
+```
+
+#### Running a manual test
+Test a manual build command with `-print-cmdline`
+```
+(chroot) x86_64-cros-linux-gnu-clang++ -o test_exec -f<some_flag_to_add>='some_value' -print-cmdline test.cc
+```
+-  `test.cc` doesn't actually have to exist.
+-  The command above will output the additional build flags that are added in by the wrapper.
+
+#### Testing your changes
+1. Add tests to your wrapper changes
+1. Run all the tests via:
+```
+go test -vet=all
+```
+
+### Build Only
+This is handy if you just want to test that the build works.
+
+Build the wrapper:
+```
+./build.py --config=<config name> --use_ccache=<bool> \
+  --use_llvm_next=<bool> --output_file=<file>
+  ```
diff --git a/compiler_wrapper/compiler_wrapper.go b/compiler_wrapper/compiler_wrapper.go
index 22109e3..7f2c8d1 100644
--- a/compiler_wrapper/compiler_wrapper.go
+++ b/compiler_wrapper/compiler_wrapper.go
@@ -168,8 +168,7 @@
 			return 0, newErrorwithSourceLocf("unsupported compiler: %s", mainBuilder.target.compiler)
 		}
 	} else {
-		_, tidyFlags, tidyMode := processClangTidyFlags(mainBuilder)
-		cSrcFile, iwyuFlags, iwyuMode := processIWYUFlags(mainBuilder)
+		cSrcFile, tidyFlags, tidyMode := processClangTidyFlags(mainBuilder)
 		crashArtifactsDir := detectCrashArtifactsDir(env, cfg)
 		if mainBuilder.target.compilerType == clangType {
 			err := prepareClangCommand(crashArtifactsDir, mainBuilder)
@@ -200,19 +199,6 @@
 				}
 			}
 
-			if iwyuMode != iwyuModeNone {
-				if iwyuMode == iwyuModeError {
-					panic("Unknown IWYU mode")
-				}
-
-				allowCCache = false
-				clangCmdWithoutRemoteBuildAndCCache := mainBuilder.build()
-				err := runIWYU(env, clangCmdWithoutRemoteBuildAndCCache, cSrcFile, iwyuFlags)
-				if err != nil {
-					return 0, err
-				}
-			}
-
 			if remoteBuildUsed, err = processRemoteBuildAndCCacheFlags(allowCCache, mainBuilder); err != nil {
 				return 0, err
 			}
@@ -350,9 +336,9 @@
 	}
 }
 
-func hasFlag(flag string, flagList ...string) bool {
-	for _, flagVal := range flagList {
-		if strings.Contains(flagVal, flag) {
+func hasUserArg(argName string, builder *commandBuilder) bool {
+	for _, argValue := range builder.args {
+		if strings.Contains(argValue.value, argName) && argValue.fromUser {
 			return true
 		}
 	}
@@ -367,8 +353,7 @@
 
 	var crashDiagFlagName = "-fcrash-diagnostics-dir"
 	if crashArtifactsDir != "" &&
-		!hasFlag(crashDiagFlagName, builder.cfg.clangFlags...) &&
-		!hasFlag(crashDiagFlagName, builder.cfg.clangPostFlags...) {
+		!hasUserArg(crashDiagFlagName, builder) {
 		builder.addPreUserArgs(crashDiagFlagName + "=" + crashArtifactsDir)
 	}
 
diff --git a/compiler_wrapper/compiler_wrapper_test.go b/compiler_wrapper/compiler_wrapper_test.go
index 2cace6e..79edab6 100644
--- a/compiler_wrapper/compiler_wrapper_test.go
+++ b/compiler_wrapper/compiler_wrapper_test.go
@@ -253,36 +253,6 @@
 	}
 }
 
-// If "crash-diagnostics-dir" flag is already provided, only use that flag and don't add a dupe
-func TestCrashDiagPreFlag(t *testing.T) {
-	withTestContext(t, func(ctx *testContext) {
-		ctx.cfg.clangFlags = []string{"-fcrash-diagnostics-dir=/build/something/foo"}
-		ctx.env = []string{
-			"CROS_ARTIFACTS_TMP_DIR=/tmp/foo",
-		}
-		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
-			ctx.newCommand(clangX86_64, mainCc)))
-		if err := verifyArgCount(cmd, 1, "-fcrash-diagnostics-dir=/build/something/foo"); err != nil {
-			t.Error(err)
-		}
-	})
-}
-
-// If "crash-diagnostics-dir" flag is already provided, only use that flag and don't add a dupe
-func TestCrashDiagPostFlag(t *testing.T) {
-	withTestContext(t, func(ctx *testContext) {
-		ctx.cfg.clangPostFlags = []string{"-fcrash-diagnostics-dir=/build/something/foo"}
-		ctx.env = []string{
-			"CROS_ARTIFACTS_TMP_DIR=/tmp/foo",
-		}
-		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
-			ctx.newCommand(clangX86_64, mainCc)))
-		if err := verifyArgCount(cmd, 1, "-fcrash-diagnostics-dir=/build/something/foo"); err != nil {
-			t.Error(err)
-		}
-	})
-}
-
 // If "crash-diagnostics-dir" flag is not provided, add one in
 func TestCrashDiagDefault(t *testing.T) {
 	withTestContext(t, func(ctx *testContext) {
@@ -291,8 +261,31 @@
 		}
 		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
 			ctx.newCommand(clangX86_64, mainCc)))
+
+		// Verify that we added the default flag
 		if err := verifyArgCount(cmd, 1, "-fcrash-diagnostics-dir=/tmp/foo/toolchain/clang_crash_diagnostics"); err != nil {
 			t.Error(err)
 		}
 	})
 }
+
+// If "crash-diagnostics-dir" flag is already provided by the user, only use that flag and don't add a dupe
+func TestCrashDiagUserFlag(t *testing.T) {
+	withTestContext(t, func(ctx *testContext) {
+		ctx.env = []string{
+			"CROS_ARTIFACTS_TMP_DIR=/tmp/foo",
+		}
+		cmd := ctx.must(callCompiler(ctx, ctx.cfg,
+			ctx.newCommand(clangX86_64, mainCc, "-fcrash-diagnostics-dir=/build/something/foozz")))
+
+		// Verify that user flag is not removed
+		if err := verifyArgCount(cmd, 1, "-fcrash-diagnostics-dir=/build/something/foozz"); err != nil {
+			t.Error(err)
+		}
+
+		// Verify that we did not add the default flag
+		if err := verifyArgCount(cmd, 0, "-fcrash-diagnostics-dir=/tmp/foo/toolchain/clang_crash_diagnostics"); err != nil {
+			t.Error(err)
+		}
+	})
+}
diff --git a/compiler_wrapper/config.go b/compiler_wrapper/config.go
index 5bfc800..b445ce9 100644
--- a/compiler_wrapper/config.go
+++ b/compiler_wrapper/config.go
@@ -28,8 +28,6 @@
 	// Toolchain root path relative to the wrapper binary.
 	clangRootRelPath string
 	gccRootRelPath   string
-	// Directory to store errors that were prevented with -Wno-error.
-	newWarningsDir string
 	// Version. Only exposed via -print-config.
 	version string
 }
@@ -108,8 +106,6 @@
 	return []string{
 		"-Qunused-arguments",
 		"-Werror=poison-system-directories",
-		"-Wno-compound-token-split-by-macro",
-		"-Wno-deprecated-builtins",
 		"-Wno-deprecated-declarations",
 		"-Wno-enum-constexpr-conversion",
 		"-Wno-error=implicit-function-declaration",
@@ -122,6 +118,8 @@
 		"-fdebug-default-version=5",
 		"-Wno-int-conversion",
 		"-Wno-incompatible-function-pointer-types",
+		// TODO(b/316021385): Temporarily disables warnings for variable length arrays.
+		"-Wno-error=vla-cxx-extension",
 		"-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
 		// TODO(b/315504245): Temporarily prevents new mangling rules from taking effect.
 		"-fclang-abi-compat=17",
@@ -165,7 +163,6 @@
 		"-ftrivial-auto-var-init=zero",
 	),
 	clangPostFlags: crosCommonClangPostFlags(),
-	newWarningsDir: "fatal_clang_warnings",
 }
 
 // Flags to be added to non-hardened toolchain.
@@ -185,7 +182,6 @@
 		"-Wno-section",
 	),
 	clangPostFlags: crosCommonClangPostFlags(),
-	newWarningsDir: "fatal_clang_warnings",
 }
 
 // Flags to be added to host toolchain.
@@ -212,7 +208,6 @@
 	),
 	// Temporarily disable Wdeprecated-copy. b/191479033
 	clangPostFlags: crosCommonClangPostFlags(),
-	newWarningsDir: "fatal_clang_warnings",
 }
 
 var androidConfig = config{
@@ -224,5 +219,4 @@
 	gccFlags:         []string{},
 	clangFlags:       []string{},
 	clangPostFlags:   []string{},
-	newWarningsDir:   "",
 }
diff --git a/compiler_wrapper/disable_werror_flag.go b/compiler_wrapper/disable_werror_flag.go
index b6dd844..45e818f 100644
--- a/compiler_wrapper/disable_werror_flag.go
+++ b/compiler_wrapper/disable_werror_flag.go
@@ -20,7 +20,7 @@
 const numWErrorEstimate = 30
 
 func getForceDisableWerrorDir(env env, cfg *config) string {
-	return path.Join(getCompilerArtifactsDir(env), cfg.newWarningsDir)
+	return path.Join(getCompilerArtifactsDir(env), "toolchain/fatal_clang_warnings")
 }
 
 type forceDisableWerrorConfig struct {
@@ -49,9 +49,13 @@
 	//   `-D_CROSTC_FORCE_DISABLE_WERROR=/path/to/directory`. This flag will be removed from the
 	//   command before the compiler is invoked. If multiple of these are passed, the last one
 	//   wins, but all are removed from the build command.
-	// 2 (deprecated). An environment variable, FORCE_DISABLE_WERROR, set to any nonempty value.
-	//   In this case, the wrapper will write to either somewhere under
-	//   ${CROS_ARTIFACTS_TMP_DIR}, or to /tmp.
+	// 2 (dispreferred, but supported). An environment variable, FORCE_DISABLE_WERROR, set to
+	//   any nonempty value. In this case, the wrapper will write to either
+	//   ${CROS_ARTIFACTS_TMP_DIR}/toolchain/fatal_clang_warnings, or to
+	//   /tmp/toolchain/fatal_clang_warnings.
+	//
+	// Two modes are supported because some ebuilds filter the env, while others will filter
+	// CFLAGS. Vanishingly few (none?) filter both, though.
 	const cflagPrefix = "-D_CROSTC_FORCE_DISABLE_WERROR="
 
 	argDir := ""
diff --git a/compiler_wrapper/disable_werror_flag_test.go b/compiler_wrapper/disable_werror_flag_test.go
index 639d404..dce0b29 100644
--- a/compiler_wrapper/disable_werror_flag_test.go
+++ b/compiler_wrapper/disable_werror_flag_test.go
@@ -377,7 +377,6 @@
 	withTestContext(t, func(ctx *testContext) {
 		ctx.NoteTestWritesToUmask()
 
-		ctx.cfg.newWarningsDir = "new_warnings"
 		ctx.env = []string{
 			"FORCE_DISABLE_WERROR=1",
 			artifactsTmpDirEnvName + "=" + path.Join(ctx.tempDir, "artifacts"),
diff --git a/compiler_wrapper/iwyu_flag.go b/compiler_wrapper/iwyu_flag.go
deleted file mode 100644
index 5788d8c..0000000
--- a/compiler_wrapper/iwyu_flag.go
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2022 The ChromiumOS Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package main
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	"os"
-	"path/filepath"
-	"strings"
-)
-
-type useIWYUMode int
-
-const (
-	iwyuModeNone useIWYUMode = iota
-	iwyuModeAll
-	iwyuModeError
-)
-
-var srcFileSuffixes = []string{
-	".c",
-	".cc",
-	".cpp",
-	".C",
-	".cxx",
-	".c++",
-}
-
-func findWithIWYUFlag(args []builderArg) (string, []builderArg) {
-	for i := range args {
-		if args[i].value == "--with-iwyu" {
-			args = append(args[:i], args[i+1:]...)
-			return "1", args
-		}
-	}
-	return "", args
-}
-
-func processIWYUFlags(builder *commandBuilder) (cSrcFile string, iwyuFlags []string, mode useIWYUMode) {
-	builder.transformArgs(func(arg builderArg) string {
-		const prefix = "-iwyu-flag="
-		if !strings.HasPrefix(arg.value, prefix) {
-			return arg.value
-		}
-
-		iwyuFlags = append(iwyuFlags, arg.value[len(prefix):])
-		return ""
-	})
-
-	cSrcFile = ""
-	lastArg := ""
-	for _, arg := range builder.args {
-		if lastArg != "-o" {
-			for _, suffix := range srcFileSuffixes {
-				if strings.HasSuffix(arg.value, suffix) {
-					cSrcFile = arg.value
-					break
-				}
-			}
-		}
-		lastArg = arg.value
-	}
-
-	if cSrcFile == "" {
-		return "", iwyuFlags, iwyuModeNone
-	}
-
-	withIWYU, _ := builder.env.getenv("WITH_IWYU")
-	if withIWYU == "" {
-		withIWYU, builder.args = findWithIWYUFlag(builder.args)
-		if withIWYU == "" {
-			return cSrcFile, iwyuFlags, iwyuModeNone
-		}
-	}
-
-	if withIWYU != "1" {
-		return cSrcFile, iwyuFlags, iwyuModeError
-	}
-
-	return cSrcFile, iwyuFlags, iwyuModeAll
-}
-
-func calcIWYUInvocation(env env, clangCmd *command, cSrcFile string, iwyuFlags ...string) (*command, error) {
-	resourceDir, err := getClangResourceDir(env, clangCmd.Path)
-	if err != nil {
-		return nil, err
-	}
-
-	iwyuPath := filepath.Join(filepath.Dir(clangCmd.Path), "include-what-you-use")
-	args := append([]string{}, iwyuFlags...)
-	args = append(args, "-resource-dir="+resourceDir)
-	args = append(args, clangCmd.Args...)
-
-	for i := 0; i < len(args); i++ {
-		for j := 0; j < len(srcFileSuffixes); j++ {
-			if strings.HasSuffix(args[i], srcFileSuffixes[j]) {
-				args = append(args[:i], args[i+1:]...)
-				break
-			}
-		}
-	}
-	args = append(args, cSrcFile)
-
-	return &command{
-		Path:       iwyuPath,
-		Args:       args,
-		EnvUpdates: clangCmd.EnvUpdates,
-	}, nil
-}
-
-func runIWYU(env env, clangCmd *command, cSrcFile string, extraIWYUFlags []string) error {
-	extraIWYUFlags = append(extraIWYUFlags, "-Xiwyu", "--mapping_file=/usr/share/include-what-you-use/libcxx.imp", "-Xiwyu", "--no_fwd_decls")
-	iwyuCmd, err := calcIWYUInvocation(env, clangCmd, cSrcFile, extraIWYUFlags...)
-	if err != nil {
-		return fmt.Errorf("calculating include-what-you-use invocation: %v", err)
-	}
-
-	// Note: We pass nil as stdin as we checked before that the compiler
-	// was invoked with a source file argument.
-	var stderr bytes.Buffer
-	stderrWriter := bufio.NewWriter(&stderr)
-	exitCode, err := wrapSubprocessErrorWithSourceLoc(iwyuCmd,
-		env.run(iwyuCmd, nil, nil, stderrWriter))
-	stderrMessage := stderr.String()
-	fmt.Fprintln(env.stderr(), stderrMessage)
-
-	if err == nil && exitCode != 0 {
-		// Note: We continue on purpose when include-what-you-use fails
-		// to maintain compatibility with the previous wrapper.
-		fmt.Fprintln(env.stderr(), "include-what-you-use failed")
-	}
-
-	iwyuDir := filepath.Join(getCompilerArtifactsDir(env), "linting-output", "iwyu")
-	if err := os.MkdirAll(iwyuDir, 0777); err != nil {
-		return fmt.Errorf("creating fixes directory at %q: %v", iwyuDir, err)
-	}
-
-	f, err := os.CreateTemp(iwyuDir, "*.out")
-	if err != nil {
-		return fmt.Errorf("making output file for iwyu: %v", err)
-	}
-	writer := bufio.NewWriter(f)
-	if _, err := writer.WriteString(stderrMessage); err != nil {
-		return fmt.Errorf("writing output file for iwyu: %v", err)
-	}
-	if err := writer.Flush(); err != nil {
-		return fmt.Errorf("flushing output file buffer for iwyu: %v", err)
-	}
-	if err := f.Close(); err != nil {
-		return fmt.Errorf("finalizing output file for iwyu: %v", err)
-	}
-
-	return err
-}
diff --git a/compiler_wrapper/iwyu_flag_test.go b/compiler_wrapper/iwyu_flag_test.go
deleted file mode 100644
index e2db3b4..0000000
--- a/compiler_wrapper/iwyu_flag_test.go
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2022 The ChromiumOS Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package main
-
-import (
-	"errors"
-	"io"
-	"strings"
-	"testing"
-)
-
-func TestIWYUArgOrder(t *testing.T) {
-	withIWYUTestContext(t, func(ctx *testContext) {
-		ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error {
-			if ctx.cmdCount == 2 {
-				if err := verifyArgOrder(cmd, "-checks=.*", mainCc, "--", "-resource-dir=.*", mainCc, "--some_arg"); err != nil {
-					return err
-				}
-			}
-			return nil
-		}
-		ctx.must(callCompiler(ctx, ctx.cfg,
-			ctx.newCommand(clangX86_64, mainCc, "--some_arg")))
-		if ctx.cmdCount < 2 {
-			t.Error("expected multiple calls.")
-		}
-	})
-}
-
-func TestIgnoreNonZeroExitCodeFromIWYU(t *testing.T) {
-	withIWYUTestContext(t, func(ctx *testContext) {
-		ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error {
-			if ctx.cmdCount == 2 {
-				return newExitCodeError(23)
-			}
-			return nil
-		}
-		ctx.must(callCompiler(ctx, ctx.cfg,
-			ctx.newCommand(clangX86_64, mainCc)))
-		stderr := ctx.stderrString()
-		if err := verifyNonInternalError(stderr, "include-what-you-use failed"); err != nil {
-			t.Error(err)
-		}
-	})
-}
-
-func TestReportGeneralErrorsFromIWYU(t *testing.T) {
-	withIWYUTestContext(t, func(ctx *testContext) {
-		ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error {
-			if ctx.cmdCount > 1 {
-				return errors.New("someerror")
-			}
-			return nil
-		}
-		stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg,
-			ctx.newCommand(clangX86_64, mainCc)))
-		if err := verifyInternalError(stderr); err != nil {
-			t.Fatal(err)
-		}
-		if !strings.Contains(stderr, "someerror") {
-			t.Errorf("unexpected error. Got: %s", stderr)
-		}
-	})
-}
-
-func TestUseIWYUBasedOnFileExtension(t *testing.T) {
-	withIWYUTestContext(t, func(ctx *testContext) {
-		testData := []struct {
-			args []string
-			iwyu bool
-		}{
-			{[]string{"main.cc"}, true},
-			{[]string{"main.cc"}, true},
-			{[]string{"main.C"}, true},
-			{[]string{"main.cxx"}, true},
-			{[]string{"main.c++"}, true},
-			{[]string{"main.xy"}, false},
-			{[]string{"-o", "main.cc"}, false},
-			{[]string{}, false},
-		}
-		for _, tt := range testData {
-			ctx.cmdCount = 0
-			ctx.must(callCompiler(ctx, ctx.cfg,
-				ctx.newCommand(clangX86_64, tt.args...)))
-			if ctx.cmdCount == 2 && !tt.iwyu {
-				t.Errorf("expected a call to iwyu but got none for args %s", tt.args)
-			}
-			if ctx.cmdCount == 1 && tt.iwyu {
-				t.Errorf("expected no call to iwyu but got one for args %s", tt.args)
-			}
-		}
-	})
-}
-
-func TestIWYUFiltersIWYUFlags(t *testing.T) {
-	withIWYUTestContext(t, func(ctx *testContext) {
-		addedFlag := "--some_iwyu_flag=flag"
-		ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error {
-			switch ctx.cmdCount {
-			case 1:
-				if err := verifyPath(cmd, "usr/bin/clang"); err != nil {
-					t.Error(err)
-				} else if err := verifyArgCount(cmd, 0, addedFlag); err != nil {
-					t.Error(err)
-				}
-				return nil
-			case 2:
-				if err := verifyPath(cmd, "usr/bin/include-what-you-use"); err != nil {
-					t.Error(err)
-				} else if verifyArgCount(cmd, 1, addedFlag); err != nil {
-					t.Error(err)
-				}
-				return nil
-			default:
-				return nil
-			}
-		}
-		cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(clangX86_64, mainCc, "-iwyu-flag="+addedFlag)))
-		if ctx.cmdCount < 2 {
-			t.Errorf("expected multiple calls.")
-		}
-		if err := verifyPath(cmd, "usr/bin/clang"); err != nil {
-			t.Error(err)
-		}
-	})
-}
-
-func withIWYUTestContext(t *testing.T, work func(ctx *testContext)) {
-	withTestContext(t, func(ctx *testContext) {
-		artifactDir := t.TempDir()
-		ctx.env = []string{"WITH_IWYU=1", "CROS_ARTIFACTS_TMP_DIR=" + artifactDir}
-		work(ctx)
-	})
-}
diff --git a/compiler_wrapper/testdata/cros_clang_host_golden/bisect.json b/compiler_wrapper/testdata/cros_clang_host_golden/bisect.json
index a8717e0..7526162 100644
--- a/compiler_wrapper/testdata/cros_clang_host_golden/bisect.json
+++ b/compiler_wrapper/testdata/cros_clang_host_golden/bisect.json
@@ -12,8 +12,6 @@
             "/tmp/stable/clang",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -26,6 +24,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -67,8 +66,6 @@
             "/tmp/stable/clang",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -81,6 +78,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -123,8 +121,6 @@
             "/tmp/stable/clang",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -137,6 +133,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
diff --git a/compiler_wrapper/testdata/cros_clang_host_golden/clang_ftrapv_maincc_target_specific.json b/compiler_wrapper/testdata/cros_clang_host_golden/clang_ftrapv_maincc_target_specific.json
index 843ae17..e60ff52 100644
--- a/compiler_wrapper/testdata/cros_clang_host_golden/clang_ftrapv_maincc_target_specific.json
+++ b/compiler_wrapper/testdata/cros_clang_host_golden/clang_ftrapv_maincc_target_specific.json
@@ -6,8 +6,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -20,6 +18,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -49,8 +48,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -63,6 +60,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -92,8 +90,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -106,6 +102,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -135,8 +132,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -149,6 +144,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -178,8 +174,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -192,6 +186,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -221,8 +216,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -235,6 +228,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -264,8 +258,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -278,6 +270,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -307,8 +300,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -321,6 +312,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -350,8 +342,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -364,6 +354,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
diff --git a/compiler_wrapper/testdata/cros_clang_host_golden/clang_host_wrapper.json b/compiler_wrapper/testdata/cros_clang_host_golden/clang_host_wrapper.json
index 383e41c..5bd833f 100644
--- a/compiler_wrapper/testdata/cros_clang_host_golden/clang_host_wrapper.json
+++ b/compiler_wrapper/testdata/cros_clang_host_golden/clang_host_wrapper.json
@@ -6,8 +6,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -20,6 +18,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
diff --git a/compiler_wrapper/testdata/cros_clang_host_golden/clang_maincc_target_specific.json b/compiler_wrapper/testdata/cros_clang_host_golden/clang_maincc_target_specific.json
index ffa5307..f0b6b97 100644
--- a/compiler_wrapper/testdata/cros_clang_host_golden/clang_maincc_target_specific.json
+++ b/compiler_wrapper/testdata/cros_clang_host_golden/clang_maincc_target_specific.json
@@ -6,8 +6,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -20,6 +18,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -48,8 +47,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -62,6 +59,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -90,8 +88,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -104,6 +100,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -132,8 +129,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -146,6 +141,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -174,8 +170,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -188,6 +182,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -216,8 +211,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -230,6 +223,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -258,8 +252,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -272,6 +264,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -300,8 +293,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -314,6 +305,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -342,8 +334,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -356,6 +346,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
diff --git a/compiler_wrapper/testdata/cros_clang_host_golden/clang_path.json b/compiler_wrapper/testdata/cros_clang_host_golden/clang_path.json
index 1993f10..f44863b 100644
--- a/compiler_wrapper/testdata/cros_clang_host_golden/clang_path.json
+++ b/compiler_wrapper/testdata/cros_clang_host_golden/clang_path.json
@@ -6,8 +6,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -20,6 +18,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -48,8 +47,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -62,6 +59,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -96,8 +94,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -110,6 +106,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -138,8 +135,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -152,6 +147,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -192,8 +188,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -206,6 +200,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -247,8 +242,6 @@
             "/somedir/clang",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -261,6 +254,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -304,8 +298,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -318,6 +310,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -355,8 +348,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -369,6 +360,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -397,8 +389,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -411,6 +401,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -439,8 +430,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -453,6 +442,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -481,8 +471,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -495,6 +483,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -523,8 +512,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -537,6 +524,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
diff --git a/compiler_wrapper/testdata/cros_clang_host_golden/clang_sanitizer_args.json b/compiler_wrapper/testdata/cros_clang_host_golden/clang_sanitizer_args.json
index d843aa1..707915c 100644
--- a/compiler_wrapper/testdata/cros_clang_host_golden/clang_sanitizer_args.json
+++ b/compiler_wrapper/testdata/cros_clang_host_golden/clang_sanitizer_args.json
@@ -6,8 +6,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -20,6 +18,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -51,8 +50,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -65,6 +62,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -96,8 +94,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -110,6 +106,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -141,8 +138,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -155,6 +150,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -186,8 +182,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -200,6 +194,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -230,8 +225,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -244,6 +237,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -276,8 +270,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -290,6 +282,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -320,8 +313,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -334,6 +325,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
diff --git a/compiler_wrapper/testdata/cros_clang_host_golden/clang_specific_args.json b/compiler_wrapper/testdata/cros_clang_host_golden/clang_specific_args.json
index d556723..9e236bd 100644
--- a/compiler_wrapper/testdata/cros_clang_host_golden/clang_specific_args.json
+++ b/compiler_wrapper/testdata/cros_clang_host_golden/clang_specific_args.json
@@ -6,8 +6,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -20,6 +18,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -66,8 +65,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -80,6 +77,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -110,8 +108,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -124,6 +120,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -154,8 +151,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -168,6 +163,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
diff --git a/compiler_wrapper/testdata/cros_clang_host_golden/clangtidy.json b/compiler_wrapper/testdata/cros_clang_host_golden/clangtidy.json
index 07fd941..cc3269c 100644
--- a/compiler_wrapper/testdata/cros_clang_host_golden/clangtidy.json
+++ b/compiler_wrapper/testdata/cros_clang_host_golden/clangtidy.json
@@ -19,8 +19,6 @@
             "-resource-dir=someResourceDir",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -33,6 +31,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -48,8 +47,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -62,6 +59,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -106,8 +104,6 @@
             "-resource-dir=someResourceDir",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -120,6 +116,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -136,8 +133,6 @@
             "/tmp/stable/clang",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -150,6 +145,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -195,8 +191,6 @@
             "-resource-dir=someResourceDir",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -209,6 +203,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -228,8 +223,6 @@
             "/tmp/stable/clang",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -242,6 +235,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -289,8 +283,6 @@
             "-resource-dir=someResourceDir",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -303,6 +295,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -319,8 +312,6 @@
             "/tmp/stable/clang",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -333,6 +324,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
diff --git a/compiler_wrapper/testdata/cros_clang_host_golden/force_disable_werror.json b/compiler_wrapper/testdata/cros_clang_host_golden/force_disable_werror.json
index 4004968..9851d54 100644
--- a/compiler_wrapper/testdata/cros_clang_host_golden/force_disable_werror.json
+++ b/compiler_wrapper/testdata/cros_clang_host_golden/force_disable_werror.json
@@ -6,8 +6,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -20,6 +18,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -51,8 +50,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -65,6 +62,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -82,8 +80,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -96,6 +92,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -130,8 +127,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -144,6 +139,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
@@ -161,8 +157,6 @@
           "args": [
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -175,6 +169,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-unused-local-typedefs",
diff --git a/compiler_wrapper/testdata/cros_hardened_golden/bisect.json b/compiler_wrapper/testdata/cros_hardened_golden/bisect.json
index e13331c..fac6fd4 100644
--- a/compiler_wrapper/testdata/cros_hardened_golden/bisect.json
+++ b/compiler_wrapper/testdata/cros_hardened_golden/bisect.json
@@ -14,8 +14,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -28,6 +26,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -86,8 +85,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -100,6 +97,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -159,8 +157,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -173,6 +169,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_golden/clang_ftrapv_maincc_target_specific.json b/compiler_wrapper/testdata/cros_hardened_golden/clang_ftrapv_maincc_target_specific.json
index 2e0fcaa..cd188ba 100644
--- a/compiler_wrapper/testdata/cros_hardened_golden/clang_ftrapv_maincc_target_specific.json
+++ b/compiler_wrapper/testdata/cros_hardened_golden/clang_ftrapv_maincc_target_specific.json
@@ -8,8 +8,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -22,6 +20,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -71,8 +70,6 @@
             "--sysroot=/usr/x86_64-cros-eabi",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -85,6 +82,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -134,8 +132,6 @@
             "--sysroot=/usr/x86_64-cros-win-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -148,6 +144,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -197,8 +194,6 @@
             "--sysroot=/usr/armv7m-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -211,6 +206,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -259,8 +255,6 @@
             "--sysroot=/usr/armv7m-cros-eabi",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -273,6 +267,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -321,8 +316,6 @@
             "--sysroot=/usr/armv7m-cros-win-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -335,6 +328,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -383,8 +377,6 @@
             "--sysroot=/usr/armv8m-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -397,6 +389,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -445,8 +438,6 @@
             "--sysroot=/usr/armv8m-cros-eabi",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -459,6 +450,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -507,8 +499,6 @@
             "--sysroot=/usr/armv8m-cros-win-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -521,6 +511,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_golden/clang_maincc_target_specific.json b/compiler_wrapper/testdata/cros_hardened_golden/clang_maincc_target_specific.json
index 739fe18..09b3dbf 100644
--- a/compiler_wrapper/testdata/cros_hardened_golden/clang_maincc_target_specific.json
+++ b/compiler_wrapper/testdata/cros_hardened_golden/clang_maincc_target_specific.json
@@ -8,8 +8,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -22,6 +20,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -69,8 +68,6 @@
             "--sysroot=/usr/x86_64-cros-eabi",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -83,6 +80,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -130,8 +128,6 @@
             "--sysroot=/usr/x86_64-cros-win-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -144,6 +140,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -191,8 +188,6 @@
             "--sysroot=/usr/armv7m-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -205,6 +200,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -251,8 +247,6 @@
             "--sysroot=/usr/armv7m-cros-eabi",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -265,6 +259,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -311,8 +306,6 @@
             "--sysroot=/usr/armv7m-cros-win-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -325,6 +318,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -371,8 +365,6 @@
             "--sysroot=/usr/armv8m-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -385,6 +377,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -431,8 +424,6 @@
             "--sysroot=/usr/armv8m-cros-eabi",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -445,6 +436,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -491,8 +483,6 @@
             "--sysroot=/usr/armv8m-cros-win-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -505,6 +495,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_golden/clang_path.json b/compiler_wrapper/testdata/cros_hardened_golden/clang_path.json
index fe64e2d..88e62ba 100644
--- a/compiler_wrapper/testdata/cros_hardened_golden/clang_path.json
+++ b/compiler_wrapper/testdata/cros_hardened_golden/clang_path.json
@@ -8,8 +8,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -22,6 +20,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -69,8 +68,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -83,6 +80,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -136,8 +134,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -150,6 +146,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -197,8 +194,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -211,6 +206,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -270,8 +266,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -284,6 +278,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -343,8 +338,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -357,6 +350,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -414,8 +408,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -428,6 +420,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -484,8 +477,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -498,6 +489,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -545,8 +537,6 @@
             "--sysroot=/tmp/stable/a/b/c/d/e/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -559,6 +549,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -606,8 +597,6 @@
             "--sysroot=/tmp/stable/a/b/c/d/e/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -620,6 +609,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -667,8 +657,6 @@
             "--sysroot=/tmp/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -681,6 +669,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -728,8 +717,6 @@
             "--sysroot=/tmp/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -742,6 +729,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_golden/clang_sanitizer_args.json b/compiler_wrapper/testdata/cros_hardened_golden/clang_sanitizer_args.json
index 25eabd1..b957392 100644
--- a/compiler_wrapper/testdata/cros_hardened_golden/clang_sanitizer_args.json
+++ b/compiler_wrapper/testdata/cros_hardened_golden/clang_sanitizer_args.json
@@ -8,8 +8,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -22,6 +20,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -71,8 +70,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -85,6 +82,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -134,8 +132,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -148,6 +144,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -197,8 +194,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -211,6 +206,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -260,8 +256,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -274,6 +268,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -322,8 +317,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -336,6 +329,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -386,8 +380,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -400,6 +392,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -448,8 +441,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -462,6 +453,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_golden/clang_specific_args.json b/compiler_wrapper/testdata/cros_hardened_golden/clang_specific_args.json
index f5c1129..6573336 100644
--- a/compiler_wrapper/testdata/cros_hardened_golden/clang_specific_args.json
+++ b/compiler_wrapper/testdata/cros_hardened_golden/clang_specific_args.json
@@ -8,8 +8,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -22,6 +20,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -87,8 +86,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -101,6 +98,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -150,8 +148,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -164,6 +160,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -213,8 +210,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -227,6 +222,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_golden/clang_sysroot_wrapper_common.json b/compiler_wrapper/testdata/cros_hardened_golden/clang_sysroot_wrapper_common.json
index 7136b3f..e2bd5d2 100644
--- a/compiler_wrapper/testdata/cros_hardened_golden/clang_sysroot_wrapper_common.json
+++ b/compiler_wrapper/testdata/cros_hardened_golden/clang_sysroot_wrapper_common.json
@@ -41,8 +41,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -55,6 +53,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -105,8 +104,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -119,6 +116,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -164,8 +162,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -178,6 +174,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -227,8 +224,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -241,6 +236,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -290,8 +286,6 @@
             "--sysroot=/usr/armv7a-cros-linux-gnueabihf",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -304,6 +298,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -351,8 +346,6 @@
             "../../usr/bin/clang",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -365,6 +358,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_golden/clangtidy.json b/compiler_wrapper/testdata/cros_hardened_golden/clangtidy.json
index 04ba844..dcad603 100644
--- a/compiler_wrapper/testdata/cros_hardened_golden/clangtidy.json
+++ b/compiler_wrapper/testdata/cros_hardened_golden/clangtidy.json
@@ -20,8 +20,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -34,6 +32,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -62,8 +61,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -76,6 +73,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -133,8 +131,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -147,6 +143,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -176,8 +173,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -190,6 +185,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -248,8 +244,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -262,6 +256,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -294,8 +289,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -308,6 +301,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -368,8 +362,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -382,6 +374,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -411,8 +404,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -425,6 +416,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_golden/force_disable_werror.json b/compiler_wrapper/testdata/cros_hardened_golden/force_disable_werror.json
index ebff9f9..ab17a91 100644
--- a/compiler_wrapper/testdata/cros_hardened_golden/force_disable_werror.json
+++ b/compiler_wrapper/testdata/cros_hardened_golden/force_disable_werror.json
@@ -8,8 +8,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -22,6 +20,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -72,8 +71,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -86,6 +83,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -122,8 +120,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -136,6 +132,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -189,8 +186,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -203,6 +198,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -239,8 +235,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -253,6 +247,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_golden/gcc_clang_syntax.json b/compiler_wrapper/testdata/cros_hardened_golden/gcc_clang_syntax.json
index 21f154d..719261f 100644
--- a/compiler_wrapper/testdata/cros_hardened_golden/gcc_clang_syntax.json
+++ b/compiler_wrapper/testdata/cros_hardened_golden/gcc_clang_syntax.json
@@ -7,8 +7,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -21,6 +19,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -90,8 +89,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -104,6 +101,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -171,8 +169,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -185,6 +181,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -235,8 +232,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -249,6 +244,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/bisect.json b/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/bisect.json
index e13331c..fac6fd4 100644
--- a/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/bisect.json
+++ b/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/bisect.json
@@ -14,8 +14,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -28,6 +26,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -86,8 +85,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -100,6 +97,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -159,8 +157,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -173,6 +169,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/clang_path.json b/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/clang_path.json
index fe64e2d..88e62ba 100644
--- a/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/clang_path.json
+++ b/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/clang_path.json
@@ -8,8 +8,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -22,6 +20,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -69,8 +68,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -83,6 +80,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -136,8 +134,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -150,6 +146,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -197,8 +194,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -211,6 +206,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -270,8 +266,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -284,6 +278,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -343,8 +338,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -357,6 +350,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -414,8 +408,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -428,6 +420,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -484,8 +477,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -498,6 +489,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -545,8 +537,6 @@
             "--sysroot=/tmp/stable/a/b/c/d/e/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -559,6 +549,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -606,8 +597,6 @@
             "--sysroot=/tmp/stable/a/b/c/d/e/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -620,6 +609,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -667,8 +657,6 @@
             "--sysroot=/tmp/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -681,6 +669,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -728,8 +717,6 @@
             "--sysroot=/tmp/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -742,6 +729,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/clangtidy.json b/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/clangtidy.json
index 04ba844..dcad603 100644
--- a/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/clangtidy.json
+++ b/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/clangtidy.json
@@ -20,8 +20,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -34,6 +32,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -62,8 +61,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -76,6 +73,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -133,8 +131,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -147,6 +143,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -176,8 +173,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -190,6 +185,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -248,8 +244,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -262,6 +256,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -294,8 +289,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -308,6 +301,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -368,8 +362,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -382,6 +374,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -411,8 +404,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -425,6 +416,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/force_disable_werror.json b/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/force_disable_werror.json
index ebff9f9..ab17a91 100644
--- a/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/force_disable_werror.json
+++ b/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/force_disable_werror.json
@@ -8,8 +8,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -22,6 +20,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -72,8 +71,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -86,6 +83,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -122,8 +120,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -136,6 +132,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -189,8 +186,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -203,6 +198,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -239,8 +235,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -253,6 +247,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/gcc_clang_syntax.json b/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/gcc_clang_syntax.json
index 21f154d..719261f 100644
--- a/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/gcc_clang_syntax.json
+++ b/compiler_wrapper/testdata/cros_hardened_llvmnext_golden/gcc_clang_syntax.json
@@ -7,8 +7,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -21,6 +19,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -90,8 +89,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -104,6 +101,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -171,8 +169,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -185,6 +181,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -235,8 +232,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -249,6 +244,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_noccache_golden/bisect.json b/compiler_wrapper/testdata/cros_hardened_noccache_golden/bisect.json
index b1e3f29..783d865 100644
--- a/compiler_wrapper/testdata/cros_hardened_noccache_golden/bisect.json
+++ b/compiler_wrapper/testdata/cros_hardened_noccache_golden/bisect.json
@@ -13,8 +13,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -27,6 +25,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -81,8 +80,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -95,6 +92,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -150,8 +148,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -164,6 +160,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_noccache_golden/clang_path.json b/compiler_wrapper/testdata/cros_hardened_noccache_golden/clang_path.json
index c4d2517..95c1e48 100644
--- a/compiler_wrapper/testdata/cros_hardened_noccache_golden/clang_path.json
+++ b/compiler_wrapper/testdata/cros_hardened_noccache_golden/clang_path.json
@@ -7,8 +7,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -21,6 +19,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -62,8 +61,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -76,6 +73,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -123,8 +121,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -137,6 +133,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -178,8 +175,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -192,6 +187,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -245,8 +241,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -259,6 +253,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -313,8 +308,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -327,6 +320,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -383,8 +377,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -397,6 +389,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -447,8 +440,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -461,6 +452,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -502,8 +494,6 @@
             "--sysroot=/tmp/stable/a/b/c/d/e/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -516,6 +506,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -557,8 +548,6 @@
             "--sysroot=/tmp/stable/a/b/c/d/e/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -571,6 +560,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -612,8 +602,6 @@
             "--sysroot=/tmp/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -626,6 +614,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -667,8 +656,6 @@
             "--sysroot=/tmp/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -681,6 +668,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_noccache_golden/clangtidy.json b/compiler_wrapper/testdata/cros_hardened_noccache_golden/clangtidy.json
index 04ba844..dcad603 100644
--- a/compiler_wrapper/testdata/cros_hardened_noccache_golden/clangtidy.json
+++ b/compiler_wrapper/testdata/cros_hardened_noccache_golden/clangtidy.json
@@ -20,8 +20,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -34,6 +32,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -62,8 +61,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -76,6 +73,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -133,8 +131,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -147,6 +143,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -176,8 +173,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -190,6 +185,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -248,8 +244,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -262,6 +256,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -294,8 +289,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -308,6 +301,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -368,8 +362,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -382,6 +374,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -411,8 +404,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -425,6 +416,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_noccache_golden/force_disable_werror.json b/compiler_wrapper/testdata/cros_hardened_noccache_golden/force_disable_werror.json
index 77485f0..7fef9a1 100644
--- a/compiler_wrapper/testdata/cros_hardened_noccache_golden/force_disable_werror.json
+++ b/compiler_wrapper/testdata/cros_hardened_noccache_golden/force_disable_werror.json
@@ -7,8 +7,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -21,6 +19,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -65,8 +64,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -79,6 +76,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -109,8 +107,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -123,6 +119,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -170,8 +167,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -184,6 +179,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -214,8 +210,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -228,6 +222,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_hardened_noccache_golden/gcc_clang_syntax.json b/compiler_wrapper/testdata/cros_hardened_noccache_golden/gcc_clang_syntax.json
index c3402a4..f0469d4 100644
--- a/compiler_wrapper/testdata/cros_hardened_noccache_golden/gcc_clang_syntax.json
+++ b/compiler_wrapper/testdata/cros_hardened_noccache_golden/gcc_clang_syntax.json
@@ -7,8 +7,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -21,6 +19,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -85,8 +84,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -99,6 +96,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -166,8 +164,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -180,6 +176,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
@@ -230,8 +227,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -244,6 +239,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "--unwindlib=libunwind",
diff --git a/compiler_wrapper/testdata/cros_nonhardened_golden/bisect.json b/compiler_wrapper/testdata/cros_nonhardened_golden/bisect.json
index c72cc99..8c25b71 100644
--- a/compiler_wrapper/testdata/cros_nonhardened_golden/bisect.json
+++ b/compiler_wrapper/testdata/cros_nonhardened_golden/bisect.json
@@ -14,8 +14,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -28,6 +26,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -79,8 +78,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -93,6 +90,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -145,8 +143,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -159,6 +155,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
diff --git a/compiler_wrapper/testdata/cros_nonhardened_golden/clang_ftrapv_maincc_target_specific.json b/compiler_wrapper/testdata/cros_nonhardened_golden/clang_ftrapv_maincc_target_specific.json
index 7932c23..f81d88c 100644
--- a/compiler_wrapper/testdata/cros_nonhardened_golden/clang_ftrapv_maincc_target_specific.json
+++ b/compiler_wrapper/testdata/cros_nonhardened_golden/clang_ftrapv_maincc_target_specific.json
@@ -8,8 +8,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -22,6 +20,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -64,8 +63,6 @@
             "--sysroot=/usr/x86_64-cros-eabi",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -78,6 +75,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -120,8 +118,6 @@
             "--sysroot=/usr/x86_64-cros-win-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -134,6 +130,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -176,8 +173,6 @@
             "--sysroot=/usr/armv7m-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -190,6 +185,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -232,8 +228,6 @@
             "--sysroot=/usr/armv7m-cros-eabi",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -246,6 +240,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -287,8 +282,6 @@
             "--sysroot=/usr/armv7m-cros-win-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -301,6 +294,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -343,8 +337,6 @@
             "--sysroot=/usr/armv8m-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -357,6 +349,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -399,8 +392,6 @@
             "--sysroot=/usr/armv8m-cros-eabi",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -413,6 +404,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -454,8 +446,6 @@
             "--sysroot=/usr/armv8m-cros-win-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -468,6 +458,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
diff --git a/compiler_wrapper/testdata/cros_nonhardened_golden/clang_maincc_target_specific.json b/compiler_wrapper/testdata/cros_nonhardened_golden/clang_maincc_target_specific.json
index 534526f..5d8f5be 100644
--- a/compiler_wrapper/testdata/cros_nonhardened_golden/clang_maincc_target_specific.json
+++ b/compiler_wrapper/testdata/cros_nonhardened_golden/clang_maincc_target_specific.json
@@ -8,8 +8,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -22,6 +20,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -62,8 +61,6 @@
             "--sysroot=/usr/x86_64-cros-eabi",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -76,6 +73,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -116,8 +114,6 @@
             "--sysroot=/usr/x86_64-cros-win-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -130,6 +126,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -170,8 +167,6 @@
             "--sysroot=/usr/armv7m-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -184,6 +179,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -224,8 +220,6 @@
             "--sysroot=/usr/armv7m-cros-eabi",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -238,6 +232,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -277,8 +272,6 @@
             "--sysroot=/usr/armv7m-cros-win-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -291,6 +284,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -331,8 +325,6 @@
             "--sysroot=/usr/armv8m-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -345,6 +337,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -385,8 +378,6 @@
             "--sysroot=/usr/armv8m-cros-eabi",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -399,6 +390,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -438,8 +430,6 @@
             "--sysroot=/usr/armv8m-cros-win-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -452,6 +442,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
diff --git a/compiler_wrapper/testdata/cros_nonhardened_golden/clang_path.json b/compiler_wrapper/testdata/cros_nonhardened_golden/clang_path.json
index 2fb92c6..768f2b2 100644
--- a/compiler_wrapper/testdata/cros_nonhardened_golden/clang_path.json
+++ b/compiler_wrapper/testdata/cros_nonhardened_golden/clang_path.json
@@ -8,8 +8,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -22,6 +20,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -62,8 +61,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -76,6 +73,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -122,8 +120,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -136,6 +132,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -176,8 +173,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -190,6 +185,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -242,8 +238,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -256,6 +250,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -308,8 +303,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -322,6 +315,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -372,8 +366,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -386,6 +378,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -435,8 +428,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -449,6 +440,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -489,8 +481,6 @@
             "--sysroot=/tmp/stable/a/b/c/d/e/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -503,6 +493,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -543,8 +534,6 @@
             "--sysroot=/tmp/stable/a/b/c/d/e/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -557,6 +546,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -597,8 +587,6 @@
             "--sysroot=/tmp/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -611,6 +599,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -651,8 +640,6 @@
             "--sysroot=/tmp/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -665,6 +652,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
diff --git a/compiler_wrapper/testdata/cros_nonhardened_golden/clang_sanitizer_args.json b/compiler_wrapper/testdata/cros_nonhardened_golden/clang_sanitizer_args.json
index ed20839..10329a5 100644
--- a/compiler_wrapper/testdata/cros_nonhardened_golden/clang_sanitizer_args.json
+++ b/compiler_wrapper/testdata/cros_nonhardened_golden/clang_sanitizer_args.json
@@ -8,8 +8,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -22,6 +20,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -65,8 +64,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -79,6 +76,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -122,8 +120,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -136,6 +132,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -179,8 +176,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -193,6 +188,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -236,8 +232,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -250,6 +244,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -292,8 +287,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -306,6 +299,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -350,8 +344,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -364,6 +356,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -406,8 +399,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -420,6 +411,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
diff --git a/compiler_wrapper/testdata/cros_nonhardened_golden/clang_specific_args.json b/compiler_wrapper/testdata/cros_nonhardened_golden/clang_specific_args.json
index 1d8d32c..be4f57a 100644
--- a/compiler_wrapper/testdata/cros_nonhardened_golden/clang_specific_args.json
+++ b/compiler_wrapper/testdata/cros_nonhardened_golden/clang_specific_args.json
@@ -8,8 +8,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -22,6 +20,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -80,8 +79,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -94,6 +91,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -136,8 +134,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -150,6 +146,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -192,8 +189,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -206,6 +201,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
diff --git a/compiler_wrapper/testdata/cros_nonhardened_golden/clang_sysroot_wrapper_common.json b/compiler_wrapper/testdata/cros_nonhardened_golden/clang_sysroot_wrapper_common.json
index 00202da..4f2bddb 100644
--- a/compiler_wrapper/testdata/cros_nonhardened_golden/clang_sysroot_wrapper_common.json
+++ b/compiler_wrapper/testdata/cros_nonhardened_golden/clang_sysroot_wrapper_common.json
@@ -38,8 +38,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -52,6 +50,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -95,8 +94,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -109,6 +106,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -147,8 +145,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -161,6 +157,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -203,8 +200,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -217,6 +212,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -260,8 +256,6 @@
             "--sysroot=/usr/armv7a-cros-linux-gnueabihf",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -274,6 +268,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -316,8 +311,6 @@
             "../../usr/bin/clang",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -330,6 +323,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
diff --git a/compiler_wrapper/testdata/cros_nonhardened_golden/clangtidy.json b/compiler_wrapper/testdata/cros_nonhardened_golden/clangtidy.json
index 0111275..e85c065 100644
--- a/compiler_wrapper/testdata/cros_nonhardened_golden/clangtidy.json
+++ b/compiler_wrapper/testdata/cros_nonhardened_golden/clangtidy.json
@@ -20,8 +20,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -34,6 +32,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -55,8 +54,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -69,6 +66,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -119,8 +117,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -133,6 +129,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -155,8 +152,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -169,6 +164,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -220,8 +216,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -234,6 +228,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -259,8 +254,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -273,6 +266,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -326,8 +320,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -340,6 +332,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -362,8 +355,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -376,6 +367,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
diff --git a/compiler_wrapper/testdata/cros_nonhardened_golden/force_disable_werror.json b/compiler_wrapper/testdata/cros_nonhardened_golden/force_disable_werror.json
index 0bc3345..7e4b4d6 100644
--- a/compiler_wrapper/testdata/cros_nonhardened_golden/force_disable_werror.json
+++ b/compiler_wrapper/testdata/cros_nonhardened_golden/force_disable_werror.json
@@ -8,8 +8,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -22,6 +20,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -65,8 +64,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -79,6 +76,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -108,8 +106,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -122,6 +118,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -168,8 +165,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -182,6 +177,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -211,8 +207,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -225,6 +219,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
diff --git a/compiler_wrapper/testdata/cros_nonhardened_golden/gcc_clang_syntax.json b/compiler_wrapper/testdata/cros_nonhardened_golden/gcc_clang_syntax.json
index ef1d1cb..daa023f 100644
--- a/compiler_wrapper/testdata/cros_nonhardened_golden/gcc_clang_syntax.json
+++ b/compiler_wrapper/testdata/cros_nonhardened_golden/gcc_clang_syntax.json
@@ -7,8 +7,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -21,6 +19,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -80,8 +79,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -94,6 +91,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -151,8 +149,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -165,6 +161,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
@@ -208,8 +205,6 @@
             "--sysroot=/usr/x86_64-cros-linux-gnu",
             "-Qunused-arguments",
             "-Werror=poison-system-directories",
-            "-Wno-compound-token-split-by-macro",
-            "-Wno-deprecated-builtins",
             "-Wno-deprecated-declarations",
             "-Wno-enum-constexpr-conversion",
             "-Wno-error=implicit-function-declaration",
@@ -222,6 +217,7 @@
             "-fdebug-default-version=5",
             "-Wno-int-conversion",
             "-Wno-incompatible-function-pointer-types",
+            "-Wno-error=vla-cxx-extension",
             "-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES",
             "-fclang-abi-compat=17",
             "-Wno-section",
diff --git a/compiler_wrapper/testutil_test.go b/compiler_wrapper/testutil_test.go
index 7b50d4b..6c5f1da 100644
--- a/compiler_wrapper/testutil_test.go
+++ b/compiler_wrapper/testutil_test.go
@@ -196,11 +196,6 @@
 
 func (ctx *testContext) updateConfig(cfg *config) {
 	*ctx.cfg = *cfg
-	ctx.cfg.newWarningsDir = filepath.Join(ctx.tempDir, "fatal_clang_warnings")
-
-	// Ensure this is always empty, so any test that depends on it will see no output unless
-	// it's properly set up.
-	ctx.cfg.newWarningsDir = ""
 }
 
 func (ctx *testContext) newCommand(path string, args ...string) *command {
diff --git a/cros_utils/git_utils.py b/cros_utils/git_utils.py
new file mode 100644
index 0000000..d8c11d0
--- /dev/null
+++ b/cros_utils/git_utils.py
@@ -0,0 +1,159 @@
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Shared utilities for working with git."""
+
+import contextlib
+import logging
+from pathlib import Path
+import re
+import shlex
+import subprocess
+import tempfile
+from typing import Generator, Iterable, List
+
+
+# Email address used to tag the detective as a reviewer.
+REVIEWER_DETECTIVE = "c-compiler-chrome@google.com"
+
+
+def _parse_cls_from_upload_output(upload_output: str) -> List[int]:
+    """Returns the CL number in the given upload output."""
+    id_regex = re.compile(
+        r"^remote:\s+https://"
+        r"(?:chromium|chrome-internal)"
+        r"-review\S+/\+/(\d+)\s",
+        re.MULTILINE,
+    )
+
+    results = id_regex.findall(upload_output)
+    if not results:
+        raise ValueError(
+            f"Wanted at least one match for {id_regex} in {upload_output!r}; "
+            "found 0"
+        )
+    return [int(x) for x in results]
+
+
+def upload_to_gerrit(
+    git_repo: Path,
+    remote: str,
+    branch: str,
+    reviewers: Iterable[str] = (),
+    cc: Iterable[str] = (),
+    ref: str = "HEAD",
+) -> List[int]:
+    """Uploads `ref` to gerrit, optionally adding reviewers/CCs."""
+    # https://gerrit-review.googlesource.com/Documentation/user-upload.html#reviewers
+    # for more info on the `%` params.
+    option_list = [f"r={x}" for x in reviewers]
+    option_list += (f"cc={x}" for x in cc)
+    if option_list:
+        trailing_options = "%" + ",".join(option_list)
+    else:
+        trailing_options = ""
+
+    run_result = subprocess.run(
+        [
+            "git",
+            "push",
+            remote,
+            # https://gerrit-review.googlesource.com/Documentation/user-upload.html#reviewers
+            # for more info on the `%` params.
+            f"{ref}:refs/for/{branch}{trailing_options}",
+        ],
+        cwd=git_repo,
+        check=False,
+        stdin=subprocess.DEVNULL,
+        stdout=subprocess.PIPE,
+        stderr=subprocess.STDOUT,
+        encoding="utf-8",
+    )
+
+    logging.info(
+        "`git push`ing %s to %s/%s had this output:\n%s",
+        ref,
+        remote,
+        branch,
+        run_result.stdout,
+    )
+    run_result.check_returncode()
+    return _parse_cls_from_upload_output(run_result.stdout)
+
+
+def try_set_autosubmit_labels(cwd: Path, cl_id: int) -> None:
+    """Sets autosubmit on a CL. Logs - not raises - on failure.
+
+    This sets a series of convenience labels on the given cl_number, so landing
+    it (e.g., for the detective) is as easy as possible.
+
+    Args:
+        cwd: the directory that the `gerrit` tool should be run in. Anywhere in
+            a ChromeOS tree will do. The `gerrit` command fails if it isn't run
+            from within a ChromeOS tree.
+        cl_id: The CL number to apply labels to.
+    """
+    gerrit_cl_id = str(cl_id)
+    gerrit_commands = (
+        ["gerrit", "label-as", gerrit_cl_id, "1"],
+        ["gerrit", "label-cq", gerrit_cl_id, "1"],
+        ["gerrit", "label-v", gerrit_cl_id, "1"],
+    )
+    for cmd in gerrit_commands:
+        # Run the gerrit commands inside of toolchain_utils, since `gerrit`
+        # needs to be run inside of a ChromeOS tree to work. While
+        # `toolchain-utils` can be checked out on its own, that's not how this
+        # script is expeted to be used.
+        return_code = subprocess.run(
+            cmd,
+            cwd=cwd,
+            check=False,
+            stdin=subprocess.DEVNULL,
+        ).returncode
+        if return_code:
+            logging.warning(
+                "Failed to run gerrit command %s. Ignoring.",
+                shlex.join(cmd),
+            )
+
+
+@contextlib.contextmanager
+def create_worktree(git_directory: Path) -> Generator[Path, None, None]:
+    """Creates a temp worktree of `git_directory`, yielding the result."""
+    with tempfile.TemporaryDirectory(prefix="update_kernel_afdo_") as t:
+        tempdir = Path(t)
+        logging.info(
+            "Establishing worktree of %s in %s", git_directory, tempdir
+        )
+        subprocess.run(
+            [
+                "git",
+                "worktree",
+                "add",
+                "--detach",
+                "--force",
+                tempdir,
+            ],
+            cwd=git_directory,
+            check=True,
+            stdin=subprocess.DEVNULL,
+        )
+
+        try:
+            yield tempdir
+        finally:
+            # Explicitly `git worktree remove` here, so the parent worktree's
+            # metadata is cleaned up promptly.
+            subprocess.run(
+                [
+                    "git",
+                    "worktree",
+                    "remove",
+                    "--force",
+                    tempdir,
+                ],
+                cwd=git_directory,
+                check=False,
+                stdin=subprocess.DEVNULL,
+            )
diff --git a/cros_utils/git_utils_test.py b/cros_utils/git_utils_test.py
new file mode 100755
index 0000000..f6060a7
--- /dev/null
+++ b/cros_utils/git_utils_test.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python3
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Tests for git_utils."""
+
+import unittest
+
+from cros_utils import git_utils
+
+
+# pylint: disable=protected-access
+
+GERRIT_OUTPUT_WITH_ONE_CL = r"""
+Enumerating objects: 4, done.
+Counting objects: 100% (4/4), done.
+Delta compression using up to 128 threads
+Compressing objects: 100% (2/2), done.
+Writing objects: 100% (3/3), 320 bytes | 106.00 KiB/s, done.
+Total 3 (delta 1), reused 1 (delta 0), pack-reused 0 (from 0)
+remote: Resolving deltas: 100% (1/1)
+remote: Processing changes: refs: 1, new: 1, done
+remote:
+remote: SUCCESS
+remote:
+remote:   https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/5375204 DO NOT COMMIT [WIP] [NEW]
+remote:
+To https://chromium.googlesource.com/chromiumos/third_party/toolchain-utils
+ * [new reference]     HEAD -> refs/for/main
+"""
+
+GERRIT_OUTPUT_WITH_TWO_CLS = r"""
+Enumerating objects: 4, done.
+Counting objects: 100% (4/4), done.
+Delta compression using up to 128 threads
+Compressing objects: 100% (2/2), done.
+Writing objects: 100% (3/3), 320 bytes | 106.00 KiB/s, done.
+Total 3 (delta 1), reused 1 (delta 0), pack-reused 0 (from 0)
+remote: Resolving deltas: 100% (1/1)
+remote: Processing changes: refs: 1, new: 1, done
+remote:
+remote: SUCCESS
+remote:
+remote:   https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/5375204 DO NOT COMMIT [WIP] [NEW]
+remote:   https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/5375205 DO NOT COMMIT [WIP] [NEW]
+remote:
+To https://chromium.googlesource.com/chromiumos/third_party/toolchain-utils
+ * [new reference]     HEAD -> refs/for/main
+"""
+
+
+GERRIT_OUTPUT_WITH_INTERNAL_CL = r"""
+Upload project manifest-internal/ to remote branch refs/heads/main:
+  branch DO-NOT-COMMIT ( 1 commit, Tue Apr 16 08:51:25 2024 -0600):
+         456aadd0 DO NOT COMMIT
+to https://chrome-internal-review.googlesource.com (y/N)? <--yes>
+Enumerating objects: 5, done.
+Counting objects: 100% (5/5), done.
+Delta compression using up to 128 threads
+Compressing objects: 100% (3/3), done.
+Writing objects: 100% (3/3), 334 bytes | 334.00 KiB/s, done.
+Total 3 (delta 2), reused 0 (delta 0), pack-reused 0 (from 0)
+remote: Resolving deltas: 100% (2/2)
+remote: Waiting for private key checker: 1/1 objects left
+remote: Processing changes: refs: 1, new: 1, done
+remote:
+remote: SUCCESS
+remote:
+remote:   https://chrome-internal-review.googlesource.com/c/chromeos/manifest-internal/+/7190037 DO NOT COMMIT [NEW]
+remote:
+To https://chrome-internal-review.googlesource.com/chromeos/manifest-internal
+ * [new reference]         DO-NOT-COMMIT -> refs/for/main
+
+----------------------------------------------------------------------
+[OK    ] manifest-internal/ DO-NOT-COMMIT
+"""
+
+
+class Test(unittest.TestCase):
+    """Tests for git_utils."""
+
+    def test_cl_parsing_complains_if_no_output(self):
+        with self.assertRaisesRegex(ValueError, ".*; found 0"):
+            git_utils._parse_cls_from_upload_output("")
+
+    def test_cl_parsing_works_with_one_cl(self):
+        self.assertEqual(
+            git_utils._parse_cls_from_upload_output(GERRIT_OUTPUT_WITH_ONE_CL),
+            [5375204],
+        )
+
+    def test_cl_parsing_works_with_two_cls(self):
+        self.assertEqual(
+            git_utils._parse_cls_from_upload_output(GERRIT_OUTPUT_WITH_TWO_CLS),
+            [5375204, 5375205],
+        )
+
+    def test_cl_parsing_works_with_internal_cl(self):
+        self.assertEqual(
+            git_utils._parse_cls_from_upload_output(
+                GERRIT_OUTPUT_WITH_INTERNAL_CL
+            ),
+            [7190037],
+        )
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/llvm_tools/README.md b/llvm_tools/README.md
index 8d0ff58..8072155 100644
--- a/llvm_tools/README.md
+++ b/llvm_tools/README.md
@@ -156,16 +156,6 @@
   --failure_mode disable_patches
 ```
 
-For example, to remove all patches that no longer apply:
-
-```
-$ ./patch_manager.py \
-  --svn_version 367622 \
-  --patch_metadata_file /abs/path/to/patch/file \
-  --src_path /abs/path/to/src/tree \
-  --failure_mode remove_patches
-```
-
 For example, to bisect a failing patch and stop at the first bisected patch:
 
 ```
@@ -244,7 +234,7 @@
   --last_tested /abs/path/to/last_tested_file.json \
   --extra_change_lists 513590 1394249 \
   --options latest-toolchain nochromesdk \
-  --chroot_path /path/to/chromeos/chroot \
+  --chromeos_path /path/to/chromeos/chroot \
   --builder eve-release-tryjob
 ```
 
@@ -449,7 +439,7 @@
 Usage:
 
 ```
-./get_upstream_patch.py --chroot_path /abs/path/to/chroot --start_sha llvm
+./get_upstream_patch.py --chromeos_path /abs/path/to/chroot --start_sha llvm
 --sha 174c3eb69f19ff2d6a3eeae31d04afe77e62c021 --sha 174c3eb69f19ff2d6a3eeae31d04afe77e62c021
 --differential D123456
 ```
diff --git a/llvm_tools/auto_llvm_bisection.py b/llvm_tools/auto_llvm_bisection.py
index d94b6f0..2b4f6f9 100755
--- a/llvm_tools/auto_llvm_bisection.py
+++ b/llvm_tools/auto_llvm_bisection.py
@@ -58,7 +58,7 @@
 }
 
 
-def GetBuildResult(chroot_path, buildbucket_id):
+def GetBuildResult(chromeos_path, buildbucket_id):
     """Returns the conversion of the result of 'cros buildresult'."""
 
     # Calls 'cros buildresult' to get the status of the tryjob.
@@ -72,7 +72,7 @@
                 "--report",
                 "json",
             ],
-            cwd=chroot_path,
+            cwd=chromeos_path,
             stderr=subprocess.STDOUT,
             encoding="utf-8",
         )
@@ -105,7 +105,7 @@
 
     args_output = llvm_bisection.GetCommandLineArgs()
 
-    chroot.VerifyChromeOSRoot(args_output.chroot_path)
+    chroot.VerifyChromeOSRoot(args_output.chromeos_path)
 
     if os.path.isfile(args_output.last_tested):
         print("Resuming bisection for %s" % args_output.last_tested)
@@ -132,7 +132,7 @@
                         == update_tryjob_status.TryjobStatus.PENDING.value
                     ):
                         status = GetBuildResult(
-                            args_output.chroot_path, tryjob["buildbucket_id"]
+                            args_output.chromeos_path, tryjob["buildbucket_id"]
                         )
                         if status:
                             tryjob["status"] = status
diff --git a/llvm_tools/bb_add.py b/llvm_tools/bb_add.py
new file mode 100755
index 0000000..1ff8349
--- /dev/null
+++ b/llvm_tools/bb_add.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python3
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs `bb add`, with additional convenience features."""
+
+import argparse
+import logging
+import os
+import shlex
+import sys
+from typing import Iterable, List
+
+import cros_cls
+import llvm_next
+
+
+def generate_bb_add_command(
+    use_llvm_next: bool,
+    disable_werror: bool,
+    extra_cls: Iterable[cros_cls.ChangeListURL],
+    bots: Iterable[str],
+) -> List[str]:
+    cls: List[cros_cls.ChangeListURL] = []
+    if use_llvm_next:
+        if not llvm_next.LLVM_NEXT_TESTING_CLS:
+            raise ValueError(
+                "llvm-next testing requested, but no llvm-next CLs exist."
+            )
+        cls += llvm_next.LLVM_NEXT_TESTING_CLS
+
+    if disable_werror:
+        cls.append(llvm_next.DISABLE_WERROR_CL)
+
+    if extra_cls:
+        cls += extra_cls
+
+    cmd = ["bb", "add"]
+    for cl in cls:
+        cmd += ("-cl", cl.crrev_url_without_http())
+    cmd += bots
+    return cmd
+
+
+def main(argv: List[str]) -> None:
+    logging.basicConfig(
+        format=">> %(asctime)s: %(levelname)s: %(filename)s:%(lineno)d: "
+        "%(message)s",
+        level=logging.INFO,
+    )
+
+    parser = argparse.ArgumentParser(
+        description=__doc__,
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+    )
+    parser.add_argument(
+        "--llvm-next",
+        action="store_true",
+        help="Add the current llvm-next patch set.",
+    )
+    parser.add_argument(
+        "--disable-werror",
+        action="store_true",
+        help="Add the 'disable -Werror' patch sets",
+    )
+    parser.add_argument(
+        "--cl",
+        action="append",
+        type=cros_cls.ChangeListURL.parse,
+        help="""
+        CL to add to the `bb add` run. May be specified multiple times. In the
+        form crrev.com/c/123456.
+        """,
+    )
+    parser.add_argument("bot", nargs="+", help="Bot(s) to run `bb add` with.")
+    opts = parser.parse_args(argv)
+
+    cmd = generate_bb_add_command(
+        use_llvm_next=opts.llvm_next,
+        disable_werror=opts.disable_werror,
+        extra_cls=opts.cl,
+        bots=opts.bot,
+    )
+    logging.info("Running `bb add` command: %s...", shlex.join(cmd))
+    # execvp raises if it fails, so no need to check.
+    os.execvp(cmd[0], cmd)
+
+
+if __name__ == "__main__":
+    main(sys.argv[1:])
diff --git a/llvm_tools/bb_add_test.py b/llvm_tools/bb_add_test.py
new file mode 100755
index 0000000..6f7fe6a
--- /dev/null
+++ b/llvm_tools/bb_add_test.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python3
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Tests for bb_add.py."""
+
+from typing import Iterable
+import unittest
+
+import bb_add
+import cros_cls
+import llvm_next
+
+
+_ARBITRARY_BOTS = ["chromeos/cq/amd64-generic-cq"]
+
+
+class Test(unittest.TestCase):
+    """Tests for bb_add.py."""
+
+    def set_llvm_next_cls(self, cls: Iterable[cros_cls.ChangeListURL]):
+        old_cls = llvm_next.LLVM_NEXT_TESTING_CLS
+        llvm_next.LLVM_NEXT_TESTING_CLS = cls
+
+        def restore_cls():
+            llvm_next.LLVM_NEXT_TESTING_CLS = old_cls
+
+        self.addCleanup(restore_cls)
+
+    def test_generate_bb_add_raises_if_no_llvm_next_cls(self):
+        self.set_llvm_next_cls(())
+        with self.assertRaisesRegex(
+            ValueError, "^llvm-next testing requested.*"
+        ):
+            bb_add.generate_bb_add_command(
+                use_llvm_next=True,
+                disable_werror=False,
+                extra_cls=(),
+                bots=_ARBITRARY_BOTS,
+            )
+
+    def test_generate_bb_add_adds_llvm_next_cls(self):
+        self.set_llvm_next_cls((cros_cls.ChangeListURL(123, 1),))
+        cmd = bb_add.generate_bb_add_command(
+            use_llvm_next=True,
+            disable_werror=False,
+            extra_cls=(),
+            bots=_ARBITRARY_BOTS,
+        )
+        self.assertEqual(
+            cmd, ["bb", "add", "-cl", "crrev.com/c/123/1"] + _ARBITRARY_BOTS
+        )
+
+    def test_generate_bb_add_adds_disable_werror_cl(self):
+        self.set_llvm_next_cls((cros_cls.ChangeListURL(123, 1),))
+        cmd = bb_add.generate_bb_add_command(
+            use_llvm_next=False,
+            disable_werror=True,
+            extra_cls=(),
+            bots=_ARBITRARY_BOTS,
+        )
+        self.assertEqual(
+            cmd,
+            [
+                "bb",
+                "add",
+                "-cl",
+                llvm_next.DISABLE_WERROR_CL.crrev_url_without_http(),
+            ]
+            + _ARBITRARY_BOTS,
+        )
+
+    def test_generate_bb_add_adds_extra_cls(self):
+        self.set_llvm_next_cls((cros_cls.ChangeListURL(123, 1),))
+        cmd = bb_add.generate_bb_add_command(
+            use_llvm_next=False,
+            disable_werror=False,
+            extra_cls=(
+                cros_cls.ChangeListURL(123, 1),
+                cros_cls.ChangeListURL(126),
+            ),
+            bots=_ARBITRARY_BOTS,
+        )
+        self.assertEqual(
+            cmd,
+            [
+                "bb",
+                "add",
+                "-cl",
+                "crrev.com/c/123/1",
+                "-cl",
+                "crrev.com/c/126",
+            ]
+            + _ARBITRARY_BOTS,
+        )
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/llvm_tools/chroot.py b/llvm_tools/chroot.py
index 5edcbf4..a104bd6 100755
--- a/llvm_tools/chroot.py
+++ b/llvm_tools/chroot.py
@@ -16,6 +16,16 @@
     return "CROS_WORKON_SRCROOT" in os.environ
 
 
+def VerifyInsideChroot() -> None:
+    """Checks whether the script invoked was executed in the chroot.
+
+    Raises:
+        AssertionError: The script was run outside the chroot.
+    """
+
+    assert InChroot(), "Script should be run inside the chroot."
+
+
 def VerifyOutsideChroot() -> None:
     """Checks whether the script invoked was executed in the chroot.
 
@@ -39,16 +49,37 @@
     assert path.is_dir(), msg
 
 
+def FindChromeOSRootAbove(chromeos_tree_path: Path) -> Path:
+    """Returns the root of a ChromeOS tree, given a path in said tree.
+
+    May return `chromeos_tree_path`, if that's already the root of the tree.
+
+    Raises:
+        ValueError if the given path is not in a ChromeOS tree.
+    """
+    if (chromeos_tree_path / ".repo").exists():
+        return chromeos_tree_path
+
+    for parent in chromeos_tree_path.parents:
+        if (parent / ".repo").exists():
+            return parent
+    raise ValueError(f"{chromeos_tree_path} is not in a repo checkout")
+
+
 def GetChrootEbuildPaths(
-    chromeos_root: Union[Path, str], packages: Iterable[str]
+    chromeos_root: Union[Path, str],
+    packages: Iterable[str],
+    chroot_name: str = "chroot",
+    out_dir: str = "out",
 ) -> List[str]:
     """Gets the chroot path(s) of the package(s).
 
     Args:
-        chromeos_root: The absolute path to the chroot to
-        use for executing chroot commands.
+        chromeos_root: The absolute path to the chromeos tree to use.
         packages: A list of a package/packages to
         be used to find their chroot path.
+        chroot_name: name of the chroot to enter.
+        out_dir: name of the out directory for the chroot.
 
     Returns:
         A list of chroot paths of the packages' ebuild files.
@@ -59,10 +90,16 @@
 
     chroot_paths = []
 
+    cros_sdk = [
+        "cros_sdk",
+        f"--chroot={chroot_name}",
+        f"--out-dir={out_dir}",
+    ]
+
     # Find the chroot path for each package's ebuild.
     for package in packages:
         chroot_path = subprocess.check_output(
-            ["cros_sdk", "--", "equery", "w", package],
+            cros_sdk + ["--", "equery", "w", package],
             cwd=chromeos_root,
             encoding="utf-8",
         )
diff --git a/llvm_tools/clean_up_old_llvm_patches.py b/llvm_tools/clean_up_old_llvm_patches.py
new file mode 100755
index 0000000..d1ae54b
--- /dev/null
+++ b/llvm_tools/clean_up_old_llvm_patches.py
@@ -0,0 +1,292 @@
+#!/usr/bin/env python3
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Removes all LLVM patches before a certain point."""
+
+import argparse
+import importlib.abc
+import importlib.util
+import logging
+from pathlib import Path
+import re
+import subprocess
+import sys
+import textwrap
+from typing import List, Optional
+
+from cros_utils import git_utils
+import patch_utils
+
+
+# The chromiumos-overlay packages to GC patches in.
+PACKAGES_TO_COLLECT = patch_utils.CHROMEOS_PATCHES_JSON_PACKAGES
+
+# Folks who should be on the R-line of any CLs that get uploaded.
+CL_REVIEWERS = (git_utils.REVIEWER_DETECTIVE,)
+
+# Folks who should be on the CC-line of any CLs that get uploaded.
+CL_CC = ("gbiv@google.com",)
+
+
+def maybe_autodetect_cros_overlay(my_dir: Path) -> Optional[Path]:
+    third_party = my_dir.parent.parent
+    cros_overlay = third_party / "chromiumos-overlay"
+    if cros_overlay.exists():
+        return cros_overlay
+    return None
+
+
+def remove_old_patches(cros_overlay: Path, min_revision: int) -> bool:
+    """Removes patches in cros_overlay. Returns whether changes were made."""
+    patches_removed = 0
+    for package in PACKAGES_TO_COLLECT:
+        logging.info("GC'ing patches from %s...", package)
+        patches_json = cros_overlay / package / "files/PATCHES.json"
+        removed_patch_files = patch_utils.remove_old_patches(
+            min_revision, patches_json
+        )
+        if not removed_patch_files:
+            logging.info("No patches removed from %s", patches_json)
+            continue
+
+        patches_removed += len(removed_patch_files)
+        for patch in removed_patch_files:
+            logging.info("Removing %s...", patch)
+            patch.unlink()
+    return patches_removed != 0
+
+
+def commit_changes(cros_overlay: Path, min_rev: int):
+    commit_msg = textwrap.dedent(
+        f"""
+        llvm: remove old patches
+
+        These patches stopped applying before r{min_rev}, so should no longer
+        be needed.
+
+        BUG=b:332601837
+        TEST=CQ
+        """
+    )
+
+    subprocess.run(
+        ["git", "commit", "--quiet", "-a", "-m", commit_msg],
+        cwd=cros_overlay,
+        check=True,
+        stdin=subprocess.DEVNULL,
+    )
+
+
+def upload_changes(cros_overlay: Path, autosubmit_cwd: Path) -> None:
+    cl_ids = git_utils.upload_to_gerrit(
+        cros_overlay,
+        remote="cros",
+        branch="main",
+        reviewers=CL_REVIEWERS,
+        cc=CL_CC,
+    )
+
+    if len(cl_ids) > 1:
+        raise ValueError(f"Unexpected: wanted just one CL upload; got {cl_ids}")
+
+    cl_id = cl_ids[0]
+    logging.info("Uploaded CL http://crrev.com/c/%s successfully.", cl_id)
+    git_utils.try_set_autosubmit_labels(autosubmit_cwd, cl_id)
+
+
+def find_chromeos_llvm_version(chromiumos_overlay: Path) -> int:
+    sys_devel_llvm = chromiumos_overlay / "sys-devel" / "llvm"
+
+    # Pick this from the name of the stable ebuild; 9999 is a bit harder to
+    # parse, and stable is just as good.
+    stable_llvm_re = re.compile(r"^llvm.*_pre(\d+)-r\d+\.ebuild$")
+    match_gen = (
+        stable_llvm_re.fullmatch(x.name) for x in sys_devel_llvm.iterdir()
+    )
+    matches = [int(x.group(1)) for x in match_gen if x]
+
+    if len(matches) != 1:
+        raise ValueError(
+            f"Expected exactly one ebuild name match in {sys_devel_llvm}; "
+            f"found {len(matches)}"
+        )
+    return matches[0]
+
+
+def find_android_llvm_version(android_toolchain_tree: Path) -> int:
+    android_version_py = (
+        android_toolchain_tree
+        / "toolchain"
+        / "llvm_android"
+        / "android_version.py"
+    )
+
+    # Per
+    # https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly.
+    # Parsing this file is undesirable, since `_svn_revision`, as a variable,
+    # isn't meant to be relied on. Let Python handle the logic instead.
+    module_name = "android_version"
+    android_version = sys.modules.get(module_name)
+    if android_version is None:
+        spec = importlib.util.spec_from_file_location(
+            module_name, android_version_py
+        )
+        if not spec:
+            raise ImportError(
+                f"Failed loading module spec from {android_version_py}"
+            )
+        android_version = importlib.util.module_from_spec(spec)
+        sys.modules[module_name] = android_version
+        loader = spec.loader
+        if not isinstance(loader, importlib.abc.Loader):
+            raise ValueError(
+                f"Loader for {android_version_py} was of type "
+                f"{type(loader)}; wanted an importlib.util.Loader"
+            )
+        loader.exec_module(android_version)
+
+    rev = android_version.get_svn_revision()
+    match = re.match(r"r(\d+)", rev)
+    assert match, f"Invalid SVN revision: {rev!r}"
+    return int(match.group(1))
+
+
+def get_opts(my_dir: Path, argv: List[str]) -> argparse.Namespace:
+    """Returns options for the script."""
+
+    parser = argparse.ArgumentParser(
+        description=__doc__,
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+    )
+    parser.add_argument(
+        "--android-toolchain",
+        type=Path,
+        help="""
+        Path to an android-toolchain repo root. Only meaningful if
+        `--autodetect-revision` is passed.
+        """,
+    )
+    parser.add_argument(
+        "--gerrit-tool-cwd",
+        type=Path,
+        help="""
+        Working directory for `gerrit` tool invocations. This should point to
+        somewhere within a ChromeOS source tree. If none is passed, this will
+        try running them in the path specified by `--chromiumos-overlay`.
+        """,
+    )
+    parser.add_argument(
+        "--chromiumos-overlay",
+        type=Path,
+        help="""
+        Path to chromiumos-overlay. Will autodetect if none is specified. If
+        autodetection fails and none is specified, this script will fail.
+        """,
+    )
+    parser.add_argument(
+        "--commit",
+        action="store_true",
+        help="Commit changes after making them.",
+    )
+    parser.add_argument(
+        "--upload-with-autoreview",
+        action="store_true",
+        help="""
+        Upload changes after committing them. Implies --commit. Also adds
+        default reviewers, and starts CQ+1 (among other convenience features).
+        """,
+    )
+
+    revision_opt = parser.add_mutually_exclusive_group(required=True)
+    revision_opt.add_argument(
+        "--revision",
+        type=int,
+        help="""
+        Revision to delete before (exclusive). All patches that stopped
+        applying before this will be removed. Phrased as an int, e.g.,
+        `--revision=1234`.
+        """,
+    )
+    revision_opt.add_argument(
+        "--autodetect-revision",
+        action="store_true",
+        help="""
+        Autodetect the value for `--revision`. If this is passed, you must also
+        pass `--android-toolchain`. This sets `--revision` to the _lesser_ of
+        Android's current LLVM version, and ChromeOS'.
+        """,
+    )
+    opts = parser.parse_args(argv)
+
+    if not opts.chromiumos_overlay:
+        maybe_overlay = maybe_autodetect_cros_overlay(my_dir)
+        if not maybe_overlay:
+            parser.error(
+                "Failed to autodetect --chromiumos-overlay; please pass a value"
+            )
+        opts.chromiumos_overlay = maybe_overlay
+
+    if not opts.gerrit_tool_cwd:
+        opts.gerrit_tool_cwd = opts.chromiumos_overlay
+
+    if opts.autodetect_revision:
+        if not opts.android_toolchain:
+            parser.error(
+                "--android-toolchain must be passed with --autodetect-revision"
+            )
+
+        cros_llvm_version = find_chromeos_llvm_version(opts.chromiumos_overlay)
+        logging.info("Detected CrOS LLVM revision: r%d", cros_llvm_version)
+        android_llvm_version = find_android_llvm_version(opts.android_toolchain)
+        logging.info(
+            "Detected Android LLVM revision: r%d", android_llvm_version
+        )
+        r = min(cros_llvm_version, android_llvm_version)
+        logging.info("Selected minimum LLVM revision: r%d", r)
+        opts.revision = r
+
+    return opts
+
+
+def main(argv: List[str]) -> None:
+    logging.basicConfig(
+        format=">> %(asctime)s: %(levelname)s: %(filename)s:%(lineno)d: "
+        "%(message)s",
+        level=logging.INFO,
+    )
+
+    my_dir = Path(__file__).resolve().parent
+    opts = get_opts(my_dir, argv)
+
+    cros_overlay = opts.chromiumos_overlay
+    gerrit_tool_cwd = opts.gerrit_tool_cwd
+    upload = opts.upload_with_autoreview
+    commit = opts.commit or upload
+    min_revision = opts.revision
+
+    made_changes = remove_old_patches(cros_overlay, min_revision)
+    if not made_changes:
+        logging.info("No changes made; exiting.")
+        return
+
+    if not commit:
+        logging.info(
+            "Changes were made, but --commit wasn't specified. My job is done."
+        )
+        return
+
+    logging.info("Committing changes...")
+    commit_changes(cros_overlay, min_revision)
+    if not upload:
+        logging.info("Change with removed patches has been committed locally.")
+        return
+
+    logging.info("Uploading changes...")
+    upload_changes(cros_overlay, gerrit_tool_cwd)
+    logging.info("Change sent for review.")
+
+
+if __name__ == "__main__":
+    main(sys.argv[1:])
diff --git a/llvm_tools/clean_up_old_llvm_patches_test.py b/llvm_tools/clean_up_old_llvm_patches_test.py
new file mode 100755
index 0000000..02100c8
--- /dev/null
+++ b/llvm_tools/clean_up_old_llvm_patches_test.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python3
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Tests for clean_up_old_llvm_patches"""
+
+from pathlib import Path
+import shutil
+import tempfile
+import unittest
+
+import clean_up_old_llvm_patches
+
+
+ANDROID_VERSION_PY_EXAMPLE = """
+def get_svn_revision():
+    return "r654321"
+"""
+
+
+class Test(unittest.TestCase):
+    """Tests for clean_up_old_llvm_patches"""
+
+    def make_tempdir(self) -> Path:
+        tmpdir = Path(tempfile.mkdtemp(prefix="patch_utils_unittest"))
+        self.addCleanup(shutil.rmtree, tmpdir)
+        return tmpdir
+
+    def test_android_version_autodetection(self):
+        android_root = self.make_tempdir()
+        android_version_py = (
+            android_root / "toolchain" / "llvm_android" / "android_version.py"
+        )
+        android_version_py.parent.mkdir(parents=True)
+        android_version_py.write_text(
+            ANDROID_VERSION_PY_EXAMPLE, encoding="utf-8"
+        )
+
+        self.assertEqual(
+            clean_up_old_llvm_patches.find_android_llvm_version(android_root),
+            654321,
+        )
+
+    def test_chromeos_version_autodetection(self):
+        chromiumos_overlay = self.make_tempdir()
+        llvm = chromiumos_overlay / "sys-devel" / "llvm"
+        llvm.mkdir(parents=True)
+
+        file_names = (
+            "Manifest",
+            "llvm-12.0-r1.ebuild",
+            "llvm-18.0_pre123456-r90.ebuild",
+            "llvm-9999.ebuild",
+        )
+        for f in file_names:
+            (llvm / f).touch()
+
+        self.assertEqual(
+            clean_up_old_llvm_patches.find_chromeos_llvm_version(
+                chromiumos_overlay
+            ),
+            123456,
+        )
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/llvm_tools/copy_helpers_to_chromiumos_overlay.py b/llvm_tools/copy_helpers_to_chromiumos_overlay.py
index 18510a4..59a664d 100755
--- a/llvm_tools/copy_helpers_to_chromiumos_overlay.py
+++ b/llvm_tools/copy_helpers_to_chromiumos_overlay.py
@@ -27,7 +27,7 @@
 def main():
     parser = argparse.ArgumentParser(description=__doc__)
     parser.add_argument(
-        "--chroot_path",
+        "--chromeos_path",
         help="Path to where CrOS' source tree lives. Will autodetect if you're "
         "running this from inside the CrOS source tree.",
     )
@@ -35,13 +35,13 @@
 
     my_dir = os.path.abspath(os.path.dirname(__file__))
 
-    repo_root = args.chroot_path
+    repo_root = args.chromeos_path
     if repo_root is None:
         repo_root = _find_repo_root(my_dir)
         if repo_root is None:
             sys.exit(
                 "Couldn't detect the CrOS checkout root; please provide a "
-                "value for --chroot_path"
+                "value for --chromeos_path"
             )
 
     chromiumos_overlay = os.path.join(
diff --git a/llvm_tools/cros_cls.py b/llvm_tools/cros_cls.py
index d0524b6..b74132e 100644
--- a/llvm_tools/cros_cls.py
+++ b/llvm_tools/cros_cls.py
@@ -65,6 +65,7 @@
 
     cl_id: int
     patch_set: Optional[int] = None
+    internal: bool = False
 
     @classmethod
     def parse(cls, url: str) -> "ChangeListURL":
@@ -73,8 +74,9 @@
             r"(?:https?://)?"
             # Match either chromium-review or crrev, leaving the CL number and
             # patch set as the next parts. These can be parsed in unison.
-            r"(?:chromium-review\.googlesource\.com.*/\+/"
-            r"|crrev\.com/c/)"
+            r"(chromium-review\.googlesource\.com.*/\+/"
+            r"|crrev\.com/[ci]/"
+            r"|chrome-internal-review\.googlesource\.com.*/\+/)"
             # Match the CL number...
             r"(\d+)"
             # and (optionally) the patch-set, as well as consuming any of the
@@ -91,12 +93,16 @@
                 "crrev.com/c/${cl_number}/${patch_set_number}, and "
                 "chromium-review.googlesource.com/c/project/path/+/"
                 "${cl_number}/${patch_set_number}. The patch-set number is "
-                "optional, and there may be a preceding http:// or https://."
+                "optional, and there may be a preceding http:// or https://. "
+                "Internal CL links are also supported."
             )
-        cl_id, maybe_patch_set = m.groups()
+        host, cl_id, maybe_patch_set = m.groups()
+        internal = host.startswith("chrome-internal-review") or host.startswith(
+            "crrev.com/i/"
+        )
         if maybe_patch_set is not None:
             maybe_patch_set = int(maybe_patch_set)
-        return cls(int(cl_id), maybe_patch_set)
+        return cls(int(cl_id), maybe_patch_set, internal)
 
     @classmethod
     def parse_with_patch_set(cls, url: str) -> "ChangeListURL":
@@ -106,12 +112,16 @@
             raise ValueError("A patchset number must be specified.")
         return result
 
-    def __str__(self):
-        result = f"https://crrev.com/c/{self.cl_id}"
+    def crrev_url_without_http(self):
+        namespace = "i" if self.internal else "c"
+        result = f"crrev.com/{namespace}/{self.cl_id}"
         if self.patch_set is not None:
             result += f"/{self.patch_set}"
         return result
 
+    def __str__(self):
+        return f"https://{self.crrev_url_without_http()}"
+
 
 def builder_url(build_id: BuildID) -> str:
     """Returns a builder URL given a build ID."""
diff --git a/llvm_tools/cros_cls_test.py b/llvm_tools/cros_cls_test.py
index fd4ed3e..45efaf3 100755
--- a/llvm_tools/cros_cls_test.py
+++ b/llvm_tools/cros_cls_test.py
@@ -22,6 +22,21 @@
             cros_cls.ChangeListURL(cl_id=123456, patch_set=None),
         )
 
+    def test_parsing_long_form_internal_url(self):
+        self.assertEqual(
+            cros_cls.ChangeListURL.parse(
+                "chrome-internal-review.googlesource.com/c/chromeos/"
+                "manifest-internal/+/654321"
+            ),
+            cros_cls.ChangeListURL(cl_id=654321, patch_set=None, internal=True),
+        )
+
+    def test_parsing_short_internal_url(self):
+        self.assertEqual(
+            cros_cls.ChangeListURL.parse("crrev.com/i/654321"),
+            cros_cls.ChangeListURL(cl_id=654321, patch_set=None, internal=True),
+        )
+
     def test_parsing_discards_http(self):
         self.assertEqual(
             cros_cls.ChangeListURL.parse("http://crrev.com/c/123456"),
@@ -106,6 +121,17 @@
             "https://crrev.com/c/1234",
         )
 
+        self.assertEqual(
+            str(
+                cros_cls.ChangeListURL(
+                    cl_id=1234,
+                    patch_set=2,
+                    internal=True,
+                )
+            ),
+            "https://crrev.com/i/1234/2",
+        )
+
 
 class Test(unittest.TestCase):
     """General tests for cros_cls."""
diff --git a/llvm_tools/failure_modes.py b/llvm_tools/failure_modes.py
index b9355b7..0df8119 100644
--- a/llvm_tools/failure_modes.py
+++ b/llvm_tools/failure_modes.py
@@ -14,7 +14,6 @@
     CONTINUE = "continue"
     DISABLE_PATCHES = "disable_patches"
     BISECT_PATCHES = "bisect_patches"
-    REMOVE_PATCHES = "remove_patches"
 
     # Only used by 'bisect_patches'.
     INTERNAL_BISECTION = "internal_bisection"
diff --git a/llvm_tools/get_llvm_hash.py b/llvm_tools/get_llvm_hash.py
index e9a8990..401a68a 100755
--- a/llvm_tools/get_llvm_hash.py
+++ b/llvm_tools/get_llvm_hash.py
@@ -17,7 +17,10 @@
 import tempfile
 from typing import Iterator, Optional, Tuple, Union
 
+import chroot
 import git_llvm_rev
+import llvm_next
+import manifest_utils
 import subprocess_helpers
 
 
@@ -25,7 +28,13 @@
     "https://chromium.googlesource.com/external/github.com/llvm/llvm-project"
 )
 
-KNOWN_HASH_SOURCES = {"google3", "google3-unstable", "tot"}
+KNOWN_HASH_SOURCES = (
+    "google3",
+    "google3-unstable",
+    "llvm",
+    "llvm-next",
+    "tot",
+)
 
 
 def GetVersionFrom(src_dir: Union[Path, str], git_hash: str) -> int:
@@ -81,23 +90,20 @@
     subprocess_helpers.CheckCommand(["git", "-C", src_dir, "pull"])
 
 
-def ParseLLVMMajorVersion(cmakelist: str):
+def ParseLLVMMajorVersion(cmakelist: str) -> Optional[str]:
     """Reads CMakeList.txt file contents for LLVMMajor Version.
 
     Args:
         cmakelist: contents of CMakeList.txt
 
     Returns:
-        The major version number as a string
-
-    Raises:
-        ValueError: The major version cannot be parsed from cmakelist
+        The major version number as a string, or None if it couldn't be found.
     """
     match = re.search(
         r"\n\s+set\(LLVM_VERSION_MAJOR (?P<major>\d+)\)", cmakelist
     )
     if not match:
-        raise ValueError("Failed to parse CMakeList for llvm major version")
+        return None
     return match.group("major")
 
 
@@ -117,17 +123,37 @@
         FileExistsError: The src directory doe not contain CMakeList.txt
     """
     src_dir = GetAndUpdateLLVMProjectInLLVMTools()
-    cmakelists_path = os.path.join(src_dir, "llvm", "CMakeLists.txt")
-    if git_hash:
-        subprocess_helpers.CheckCommand(
-            ["git", "-C", src_dir, "checkout", git_hash]
-        )
-    try:
-        with open(cmakelists_path, encoding="utf-8") as cmakelists_file:
-            return ParseLLVMMajorVersion(cmakelists_file.read())
-    finally:
+
+    # b/325895866#comment36: the LLVM version number was moved from
+    # `llvm/CMakeLists.txt` to `cmake/Modules/LLVMVersion.cmake` in upstream
+    # commit 81e20472a0c5a4a8edc5ec38dc345d580681af81 (r530225). Until we no
+    # longer care about looking before that, we need to support searching both
+    # files.
+    cmakelists_paths = (
+        Path(src_dir) / "llvm" / "CMakeLists.txt",
+        Path(src_dir) / "cmake" / "Modules" / "LLVMVersion.cmake",
+    )
+
+    with contextlib.ExitStack() as on_exit:
         if git_hash:
-            CheckoutBranch(src_dir, git_llvm_rev.MAIN_BRANCH)
+            subprocess_helpers.CheckCommand(
+                ["git", "-C", src_dir, "checkout", git_hash]
+            )
+            on_exit.callback(CheckoutBranch, src_dir, git_llvm_rev.MAIN_BRANCH)
+
+        for path in cmakelists_paths:
+            try:
+                file_contents = path.read_text(encoding="utf-8")
+            except FileNotFoundError:
+                # If this file DNE (yet), ignore it.
+                continue
+
+            if version := ParseLLVMMajorVersion(file_contents):
+                return version
+
+    raise ValueError(
+        f"Major version could not be parsed from any of {cmakelists_paths}"
+    )
 
 
 @contextlib.contextmanager
@@ -338,6 +364,21 @@
     return git_hash, version
 
 
+def GetCrOSCurrentLLVMHash(chromeos_tree: Path) -> str:
+    """Retrieves the current ChromeOS LLVM hash.
+
+    Args:
+        chromeos_tree: A ChromeOS source tree. This is allowed to be
+        arbitrary subdirectory of an actual ChromeOS tree, for convenience.
+
+    Raises:
+        ManifestValueError if the toolchain manifest doesn't match the
+        expected structure.
+    """
+    chromeos_root = chroot.FindChromeOSRootAbove(chromeos_tree)
+    return manifest_utils.extract_current_llvm_hash(chromeos_root)
+
+
 class LLVMHash:
     """Provides methods to retrieve a LLVM hash."""
 
@@ -380,15 +421,21 @@
         Returns:
             The hash as a string that corresponds to the LLVM version.
         """
-
         hash_value = GetGitHashFrom(
             GetAndUpdateLLVMProjectInLLVMTools(), version
         )
         return hash_value
 
+    def GetCrOSCurrentLLVMHash(self, chromeos_tree: Path) -> str:
+        """Retrieves the current ChromeOS LLVM hash."""
+        return GetCrOSCurrentLLVMHash(chromeos_tree)
+
+    def GetCrOSLLVMNextHash(self) -> str:
+        """Retrieves the current ChromeOS llvm-next hash."""
+        return llvm_next.LLVM_NEXT_HASH
+
     def GetGoogle3LLVMHash(self) -> str:
         """Retrieves the google3 LLVM hash."""
-
         return self.GetLLVMHash(GetGoogle3LLVMVersion(stable=True))
 
     def GetGoogle3UnstableLLVMHash(self) -> str:
@@ -411,6 +458,7 @@
     Parses the command line for the optional command line
     arguments.
     """
+    my_dir = Path(__file__).parent.resolve()
 
     # Create parser and add optional command-line arguments.
     parser = argparse.ArgumentParser(description="Finds the LLVM hash.")
@@ -421,17 +469,36 @@
         help="which git hash of LLVM to find. Either a svn revision, or one "
         "of %s" % sorted(KNOWN_HASH_SOURCES),
     )
+    parser.add_argument(
+        "--chromeos_tree",
+        type=Path,
+        required=True,
+        help="""
+        Path to a ChromeOS tree. If not passed, one will be inferred. If none
+        can be inferred, this script will fail.
+        """,
+    )
 
     # Parse command-line arguments.
     args_output = parser.parse_args()
 
     cur_llvm_version = args_output.llvm_version
+    chromeos_tree = args_output.chromeos_tree
+    if not chromeos_tree:
+        # Try to infer this unconditionally, so mishandling of this script can
+        # be more easily detected (which allows more flexibility in the
+        # implementation in the future for things outside of what directly
+        # needs this value).
+        chromeos_tree = chroot.FindChromeOSRootAbove(my_dir)
 
     new_llvm_hash = LLVMHash()
-
     if isinstance(cur_llvm_version, int):
         # Find the git hash of the specific LLVM version.
         print(new_llvm_hash.GetLLVMHash(cur_llvm_version))
+    elif cur_llvm_version == "llvm":
+        print(new_llvm_hash.GetCrOSCurrentLLVMHash(chromeos_tree))
+    elif cur_llvm_version == "llvm-next":
+        print(new_llvm_hash.GetCrOSLLVMNextHash())
     elif cur_llvm_version == "google3":
         print(new_llvm_hash.GetGoogle3LLVMHash())
     elif cur_llvm_version == "google3-unstable":
diff --git a/llvm_tools/get_llvm_hash_unittest.py b/llvm_tools/get_llvm_hash_unittest.py
index 66685ca..fda002c 100755
--- a/llvm_tools/get_llvm_hash_unittest.py
+++ b/llvm_tools/get_llvm_hash_unittest.py
@@ -6,11 +6,16 @@
 """Unit tests for retrieving the LLVM hash."""
 
 import contextlib
+from pathlib import Path
+import shutil
 import subprocess
+import tempfile
+import textwrap
 import unittest
 from unittest import mock
 
 import get_llvm_hash
+import llvm_next
 import subprocess_helpers
 
 
@@ -28,6 +33,15 @@
 class TestGetLLVMHash(unittest.TestCase):
     """The LLVMHash test class."""
 
+    def make_tempdir(self):
+        d = Path(tempfile.mkdtemp(prefix="get_llvm_hash_unittest_"))
+        self.addCleanup(shutil.rmtree, d)
+        return d
+
+    def setUp(self):
+        # We mock out quite a bit. Ensure every test is self-contained.
+        get_llvm_hash.GetLLVMMajorVersion.cache_clear()
+
     @mock.patch.object(subprocess, "run")
     def testCloneRepoSucceedsWhenGitSucceeds(self, run_mock):
         run_mock.return_value = mock_run_results(returncode=0, stderr=b"")
@@ -121,37 +135,79 @@
 
     def testParseLLVMMajorVersionInvalid(self):
         invalid_cmakelist = "invalid cmakelist.txt contents"
-        with self.assertRaises(ValueError):
+        self.assertIsNone(
             get_llvm_hash.ParseLLVMMajorVersion(invalid_cmakelist)
+        )
 
     @mock.patch.object(get_llvm_hash, "GetAndUpdateLLVMProjectInLLVMTools")
-    @mock.patch.object(get_llvm_hash, "ParseLLVMMajorVersion")
     @mock.patch.object(subprocess_helpers, "CheckCommand")
-    @mock.patch.object(get_llvm_hash, "CheckoutBranch")
-    @mock.patch(
-        "get_llvm_hash.open",
-        mock.mock_open(read_data="mock contents"),
-        create=True,
-    )
-    def testGetLLVMMajorVersion(
+    def testGetLLVMMajorVersionWithOldPath(
         self,
-        mock_checkout_branch,
-        mock_git_checkout,
-        mock_major_version,
-        mock_llvm_project_path,
+        _mock_check_command,
+        mock_update_project,
     ):
-        mock_llvm_project_path.return_value = "path/to/llvm-project"
-        mock_major_version.return_value = "1234"
-        self.assertEqual(get_llvm_hash.GetLLVMMajorVersion("314159265"), "1234")
-        # Second call should be memoized
-        self.assertEqual(get_llvm_hash.GetLLVMMajorVersion("314159265"), "1234")
-        mock_llvm_project_path.assert_called_once()
-        mock_major_version.assert_called_with("mock contents")
-        mock_git_checkout.assert_called_once_with(
-            ["git", "-C", "path/to/llvm-project", "checkout", "314159265"]
+        src_dir = self.make_tempdir()
+        mock_update_project.return_value = str(src_dir)
+
+        cmakelists = Path(src_dir) / "llvm" / "CMakeLists.txt"
+        cmakelists.parent.mkdir(parents=True)
+        cmakelists.write_text(
+            textwrap.dedent(
+                """
+                if(NOT DEFINED LLVM_VERSION_MAJOR)
+                  set(LLVM_VERSION_MAJOR 12345)
+                endif()
+                """
+            ),
+            encoding="utf-8",
         )
-        mock_checkout_branch.assert_called_once_with(
-            "path/to/llvm-project", "main"
+        self.assertEqual(get_llvm_hash.GetLLVMMajorVersion(), "12345")
+
+    @mock.patch.object(get_llvm_hash, "GetAndUpdateLLVMProjectInLLVMTools")
+    @mock.patch.object(subprocess_helpers, "CheckCommand")
+    def testGetLLVMMajorVersionWithNewPath(
+        self,
+        _mock_check_command,
+        mock_update_project,
+    ):
+        src_dir = self.make_tempdir()
+        mock_update_project.return_value = str(src_dir)
+
+        old_cmakelists = Path(src_dir) / "llvm" / "CMakeLists.txt"
+        old_cmakelists.parent.mkdir(parents=True)
+        old_cmakelists.write_text(
+            textwrap.dedent(
+                """
+                Some text
+                that has
+                nothing to do with
+                LLVM_VERSION_MAJOR
+                """
+            ),
+            encoding="utf-8",
+        )
+
+        new_cmakelists = (
+            Path(src_dir) / "cmake" / "Modules" / "LLVMVersion.cmake"
+        )
+        new_cmakelists.parent.mkdir(parents=True)
+        new_cmakelists.write_text(
+            textwrap.dedent(
+                """
+                if(NOT DEFINED LLVM_VERSION_MAJOR)
+                  set(LLVM_VERSION_MAJOR 5432)
+                endif()
+                """
+            ),
+            encoding="utf-8",
+        )
+
+        self.assertEqual(get_llvm_hash.GetLLVMMajorVersion(), "5432")
+
+    def testGetLLVMNextHash(self):
+        self.assertEqual(
+            get_llvm_hash.LLVMHash().GetCrOSLLVMNextHash(),
+            llvm_next.LLVM_NEXT_HASH,
         )
 
 
diff --git a/llvm_tools/get_upstream_patch.py b/llvm_tools/get_upstream_patch.py
index 52634cd..7335aad 100755
--- a/llvm_tools/get_upstream_patch.py
+++ b/llvm_tools/get_upstream_patch.py
@@ -12,7 +12,6 @@
 import logging
 import os
 from pathlib import Path
-import shlex
 import subprocess
 import sys
 import typing as t
@@ -26,7 +25,7 @@
 
 __DOC_EPILOGUE = """
 Example Usage:
-  get_upstream_patch --chroot_path ~/chromiumos --platform chromiumos \
+  get_upstream_patch --chromeos_path ~/chromiumos --platform chromiumos \
 --sha 1234567 --sha 890abdc
 """
 
@@ -191,41 +190,6 @@
     os.rename(temp_file, patches_json_path)
 
 
-def parse_ebuild_for_assignment(ebuild_path: str, var_name: str) -> str:
-    # '_pre' filters the LLVM 9.0 ebuild, which we never want to target, from
-    # this list.
-    candidates = [
-        x
-        for x in os.listdir(ebuild_path)
-        if x.endswith(".ebuild") and "_pre" in x
-    ]
-
-    if not candidates:
-        raise ValueError("No ebuilds found under %r" % ebuild_path)
-
-    ebuild = os.path.join(ebuild_path, max(candidates))
-    with open(ebuild, encoding="utf-8") as f:
-        var_name_eq = var_name + "="
-        for orig_line in f:
-            if not orig_line.startswith(var_name_eq):
-                continue
-
-            # We shouldn't see much variety here, so do the simplest thing
-            # possible.
-            line = orig_line[len(var_name_eq) :]
-            # Remove comments
-            line = line.split("#")[0]
-            # Remove quotes
-            parts = shlex.split(line)
-            if len(parts) != 1:
-                raise ValueError(
-                    "Expected exactly one quoted value in %r" % orig_line
-                )
-            return parts[0].strip()
-
-    raise ValueError("No %s= line found in %r" % (var_name, ebuild))
-
-
 # Resolves a git ref (or similar) to a LLVM SHA.
 def resolve_llvm_ref(llvm_dir: t.Union[Path, str], sha: str) -> str:
     return subprocess.check_output(
@@ -309,18 +273,18 @@
     git.DeleteBranch(llvm_symlink_dir, branch)
 
 
-def resolve_symbolic_sha(start_sha: str, llvm_symlink_dir: str) -> str:
+def resolve_symbolic_sha(start_sha: str, chromeos_path: Path) -> str:
     if start_sha == "llvm":
-        return parse_ebuild_for_assignment(llvm_symlink_dir, "LLVM_HASH")
+        return get_llvm_hash.LLVMHash().GetCrOSCurrentLLVMHash(chromeos_path)
 
     if start_sha == "llvm-next":
-        return parse_ebuild_for_assignment(llvm_symlink_dir, "LLVM_NEXT_HASH")
+        return get_llvm_hash.LLVMHash().GetCrOSLLVMNextHash()
 
     return start_sha
 
 
 def find_patches_and_make_cl(
-    chroot_path: str,
+    chromeos_path: str,
     patches: t.List[str],
     start_rev: git_llvm_rev.Rev,
     llvm_config: git_llvm_rev.LLVMConfig,
@@ -360,14 +324,14 @@
         packages = get_package_names(parsed_patch.sha, llvm_config.dir)
         # Find out the ebuild of the corresponding ChromeOS packages
         ebuild_paths = chroot.GetChrootEbuildPaths(
-            chroot_path,
+            chromeos_path,
             [
                 "sys-devel/llvm" if package == "llvm" else "sys-libs/" + package
                 for package in packages
             ],
         )
         ebuild_paths = chroot.ConvertChrootPathsToAbsolutePaths(
-            chroot_path, ebuild_paths
+            chromeos_path, ebuild_paths
         )
         # Create a local patch for all the affected llvm projects
         try:
@@ -390,7 +354,6 @@
         successes.append(parsed_patch.sha)
 
         if create_cl:
-
             commit_messages.extend(
                 [
                     parsed_patch.git_msg(),
@@ -492,7 +455,7 @@
 
 
 def get_from_upstream(
-    chroot_path: str,
+    chromeos_path: str,
     create_cl: bool,
     start_sha: str,
     patches: t.List[str],
@@ -503,8 +466,8 @@
     cc: t.Optional[t.List[str]] = None,
 ):
     llvm_symlink = chroot.ConvertChrootPathsToAbsolutePaths(
-        chroot_path,
-        chroot.GetChrootEbuildPaths(chroot_path, ["sys-devel/llvm"]),
+        chromeos_path,
+        chroot.GetChrootEbuildPaths(chromeos_path, ["sys-devel/llvm"]),
     )[0]
     llvm_symlink_dir = os.path.dirname(llvm_symlink)
 
@@ -516,7 +479,7 @@
         error_path = os.path.dirname(os.path.dirname(llvm_symlink_dir))
         raise ValueError(f"Uncommited changes detected in {error_path}")
 
-    start_sha = resolve_symbolic_sha(start_sha, llvm_symlink_dir)
+    start_sha = resolve_symbolic_sha(start_sha, Path(chromeos_path))
     logging.info("Base llvm hash == %s", start_sha)
 
     llvm_config = git_llvm_rev.LLVMConfig(
@@ -525,7 +488,7 @@
     start_sha = resolve_llvm_ref(llvm_config.dir, start_sha)
 
     find_patches_and_make_cl(
-        chroot_path=chroot_path,
+        chromeos_path=chromeos_path,
         patches=patches,
         platforms=platforms,
         start_rev=git_llvm_rev.translate_sha_to_rev(llvm_config, start_sha),
@@ -555,7 +518,7 @@
         epilog=__DOC_EPILOGUE,
     )
     parser.add_argument(
-        "--chroot_path",
+        "--chromeos_path",
         default=os.path.join(os.path.expanduser("~"), "chromiumos"),
         help="the path to the chroot (default: %(default)s)",
     )
@@ -604,7 +567,7 @@
         "when --differential appears exactly once.",
     )
     args = parser.parse_args()
-    chroot.VerifyChromeOSRoot(args.chroot_path)
+    chroot.VerifyChromeOSRoot(args.chromeos_path)
 
     if not (args.sha or args.differential):
         parser.error("--sha or --differential required")
@@ -616,7 +579,7 @@
         )
 
     get_from_upstream(
-        chroot_path=args.chroot_path,
+        chromeos_path=args.chromeos_path,
         allow_failures=args.allow_failures,
         create_cl=args.create_cl,
         start_sha=args.start_sha,
diff --git a/llvm_tools/git.py b/llvm_tools/git.py
index 7ca44b0..ea4ce3d 100755
--- a/llvm_tools/git.py
+++ b/llvm_tools/git.py
@@ -17,6 +17,11 @@
 CommitContents = collections.namedtuple("CommitContents", ["url", "cl_number"])
 
 
+def IsFullGitSHA(s: str) -> bool:
+    """Returns if `s` looks like a git SHA."""
+    return len(s) == 40 and all(x.isdigit() or "a" <= x <= "f" for x in s)
+
+
 def CreateBranch(repo: Union[Path, str], branch: str) -> None:
     """Creates a branch in the given repo.
 
diff --git a/llvm_tools/git_unittest.py b/llvm_tools/git_unittest.py
index 940f0db..fa756dd 100755
--- a/llvm_tools/git_unittest.py
+++ b/llvm_tools/git_unittest.py
@@ -17,10 +17,28 @@
 # These are unittests; protected access is OK to a point.
 # pylint: disable=protected-access
 
+EXAMPLE_GIT_SHA = "d46d9c1a23118e3943f43fe2dfc9f9c9c0b4aefe"
+
 
 class HelperFunctionsTest(unittest.TestCase):
     """Test class for updating LLVM hashes of packages."""
 
+    def testIsFullGitSHASuccessCases(self):
+        shas = ("a" * 40, EXAMPLE_GIT_SHA)
+        for s in shas:
+            self.assertTrue(git.IsFullGitSHA(s), s)
+
+    def testIsFullGitSHAFailureCases(self):
+        shas = (
+            "",
+            "A" * 40,
+            "g" * 40,
+            EXAMPLE_GIT_SHA[1:],
+            EXAMPLE_GIT_SHA + "a",
+        )
+        for s in shas:
+            self.assertFalse(git.IsFullGitSHA(s), s)
+
     @mock.patch.object(os.path, "isdir", return_value=False)
     def testFailedToCreateBranchForInvalidDirectoryPath(self, mock_isdir):
         path_to_repo = "/invalid/path/to/repo"
diff --git a/llvm_tools/llvm_bisection.py b/llvm_tools/llvm_bisection.py
index 2c5bc1a..336d433 100755
--- a/llvm_tools/llvm_bisection.py
+++ b/llvm_tools/llvm_bisection.py
@@ -115,7 +115,7 @@
 
     # Add argument for a specific chroot path.
     parser.add_argument(
-        "--chroot_path",
+        "--chromeos_path",
         default=cros_root,
         help="the path to the chroot (default: %(default)s)",
     )
@@ -279,7 +279,7 @@
     bisect_state,
     last_tested,
     update_packages,
-    chroot_path,
+    chromeos_path,
     extra_change_lists,
     options,
     builder,
@@ -292,7 +292,7 @@
                 update_packages,
                 git_hash,
                 svn_revision,
-                chroot_path,
+                chromeos_path,
                 extra_change_lists,
                 options,
                 builder,
@@ -333,7 +333,7 @@
     """
 
     chroot.VerifyOutsideChroot()
-    chroot.VerifyChromeOSRoot(args_output.chroot_path)
+    chroot.VerifyChromeOSRoot(args_output.chromeos_path)
     start = args_output.start_rev
     end = args_output.end_rev
 
@@ -410,7 +410,7 @@
         if args_output.cleanup:
             # Abandon all the CLs created for bisection
             gerrit = os.path.join(
-                args_output.chroot_path, "chromite/bin/gerrit"
+                args_output.chromeos_path, "chromite/bin/gerrit"
             )
             for build in bisect_state["jobs"]:
                 try:
@@ -439,7 +439,7 @@
         bisect_state,
         args_output.last_tested,
         update_chromeos_llvm_hash.DEFAULT_PACKAGES,
-        args_output.chroot_path,
+        args_output.chromeos_path,
         args_output.extra_change_lists,
         args_output.options,
         args_output.builder,
diff --git a/llvm_tools/llvm_bisection_unittest.py b/llvm_tools/llvm_bisection_unittest.py
index 1c1c816..273a4c9 100755
--- a/llvm_tools/llvm_bisection_unittest.py
+++ b/llvm_tools/llvm_bisection_unittest.py
@@ -247,7 +247,7 @@
                     bisection_contents,
                     temp_json_file,
                     packages,
-                    args_output.chroot_path,
+                    args_output.chromeos_path,
                     args_output.extra_change_lists,
                     args_output.options,
                     args_output.builders,
@@ -321,7 +321,7 @@
         args_output.end_rev = end
         args_output.parallel = 3
         args_output.src_path = None
-        args_output.chroot_path = "somepath"
+        args_output.chromeos_path = "somepath"
         args_output.cleanup = True
 
         self.assertEqual(
@@ -345,7 +345,7 @@
             mock.call(
                 [
                     os.path.join(
-                        args_output.chroot_path, "chromite/bin/gerrit"
+                        args_output.chromeos_path, "chromite/bin/gerrit"
                     ),
                     "abandon",
                     str(cl),
diff --git a/llvm_tools/llvm_next.py b/llvm_tools/llvm_next.py
new file mode 100644
index 0000000..1c075e5
--- /dev/null
+++ b/llvm_tools/llvm_next.py
@@ -0,0 +1,30 @@
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Contains useful constants for testing LLVM."""
+
+from typing import Iterable
+
+import cros_cls
+
+
+LLVM_NEXT_HASH = "28a8f1b901389c1e478407440f7ccf2d41c71b64"
+LLVM_NEXT_REV = 516547
+
+# NOTE: Always specify patch-sets for CLs. We don't want uploads by untrusted
+# users to turn into bot invocations w/ untrusted input.
+
+# A list of CLs that constitute the current llvm-next roll.
+# This is taken as the set of CLs that will be landed simultaneously in order
+# to make llvm-next go live.
+#
+# Generally speaking, for simple rolls, this should just contain a link to the
+# Manifest update CL.
+LLVM_NEXT_TESTING_CLS: Iterable[cros_cls.ChangeListURL] = ()
+
+# The CL used to disable -Werror, and report the results.
+DISABLE_WERROR_CL = cros_cls.ChangeListURL(
+    cl_id=2599698,
+    patch_set=5,
+)
diff --git a/llvm_tools/llvm_next_test.py b/llvm_tools/llvm_next_test.py
new file mode 100755
index 0000000..a4e6a39
--- /dev/null
+++ b/llvm_tools/llvm_next_test.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python3
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Tests for llvm_next."""
+
+import unittest
+
+import llvm_next
+
+
+class Test(unittest.TestCase):
+    """Tests for llvm_next."""
+
+    def test_all_cls_have_patchesets(self):
+        cls = [llvm_next.DISABLE_WERROR_CL]
+        cls += llvm_next.LLVM_NEXT_TESTING_CLS
+        for cl in cls:
+            self.assertIsNotNone(cl.patch_set, f"CL {cl} needs a patch-set")
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/llvm_tools/llvm_simple_bisect.py b/llvm_tools/llvm_simple_bisect.py
new file mode 100755
index 0000000..433fec7
--- /dev/null
+++ b/llvm_tools/llvm_simple_bisect.py
@@ -0,0 +1,351 @@
+#!/usr/bin/env python3
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Simple LLVM Bisection Script for use with the llvm-9999 ebuild.
+
+Example usage with `git bisect`:
+
+    cd path/to/llvm-project
+    git bisect good <GOOD_HASH>
+    git bisect bad <BAD_HASH>
+    git bisect run \
+        path/to/llvm_tools/llvm_simple_bisect.py --reset-llvm \
+        --test "emerge-atlas package" \
+        --search-error "some error that I care about"
+"""
+
+import argparse
+import dataclasses
+import logging
+import os
+from pathlib import Path
+import subprocess
+import sys
+from typing import Optional, Text
+
+import chroot
+
+
+# Git Bisection exit codes
+EXIT_GOOD = 0
+EXIT_BAD = 1
+EXIT_SKIP = 125
+EXIT_ABORT = 255
+
+
+class AbortingException(Exception):
+    """A nonrecoverable error occurred which should not depend on the LLVM Hash.
+
+    In this case we will abort bisection unless --never-abort is set.
+    """
+
+
+@dataclasses.dataclass(frozen=True)
+class CommandResult:
+    """Results a command"""
+
+    return_code: int
+    output: Text
+
+    def success(self) -> bool:
+        """Checks if command exited successfully."""
+        return self.return_code == 0
+
+    def search(self, error_string: Text) -> bool:
+        """Checks if command has error_string in output."""
+        return error_string in self.output
+
+    def exit_assert(
+        self,
+        error_string: Text,
+        llvm_hash: Text,
+        log_dir: Optional[Path] = None,
+    ):
+        """Exit program with error code based on result."""
+        if self.success():
+            decision, decision_str = EXIT_GOOD, "GOOD"
+        elif self.search(error_string):
+            if error_string:
+                logging.info("Found failure and output contained error_string")
+            decision, decision_str = EXIT_BAD, "BAD"
+        else:
+            if error_string:
+                logging.info(
+                    "Found failure but error_string was not found in results."
+                )
+            decision, decision_str = EXIT_SKIP, "SKIP"
+
+        logging.info("Completed bisection stage with: %s", decision_str)
+        if log_dir:
+            self.log_result(log_dir, llvm_hash, decision_str)
+        sys.exit(decision)
+
+    def log_result(self, log_dir: Path, llvm_hash: Text, decision: Text):
+        """Log command's output to `{log_dir}/{llvm_hash}.{decision}`.
+
+        Args:
+            log_dir: Path to the directory to use for log files
+            llvm_hash: LLVM Hash being tested
+            decision: GOOD, BAD, or SKIP decision returned for `git bisect`
+        """
+        log_dir = Path(log_dir)
+        log_dir.mkdir(parents=True, exist_ok=True)
+
+        log_file = log_dir / f"{llvm_hash}.{decision}"
+        log_file.touch()
+
+        logging.info("Writing output logs to %s", log_file)
+
+        log_file.write_text(self.output, encoding="utf-8")
+
+        # Fix permissions since sometimes this script gets called with sudo
+        log_dir.chmod(0o666)
+        log_file.chmod(0o666)
+
+
+class LLVMRepo:
+    """LLVM Repository git and workon information."""
+
+    REPO_PATH = Path("/mnt/host/source/src/third_party/llvm-project")
+
+    def __init__(self):
+        self.workon: Optional[bool] = None
+
+    def get_current_hash(self) -> Text:
+        try:
+            output = subprocess.check_output(
+                ["git", "rev-parse", "HEAD"],
+                cwd=self.REPO_PATH,
+                encoding="utf-8",
+            )
+            output = output.strip()
+        except subprocess.CalledProcessError as e:
+            output = e.output
+            logging.error("Could not get current llvm hash")
+            raise AbortingException
+        return output
+
+    def set_workon(self, workon: bool):
+        """Toggle llvm-9999 mode on or off."""
+        if self.workon == workon:
+            return
+        subcommand = "start" if workon else "stop"
+        try:
+            subprocess.check_call(
+                ["cros_workon", "--host", subcommand, "sys-devel/llvm"]
+            )
+        except subprocess.CalledProcessError:
+            logging.exception("cros_workon could not be toggled for LLVM.")
+            raise AbortingException
+        self.workon = workon
+
+    def reset(self):
+        """Reset installed LLVM version."""
+        logging.info("Reseting llvm to downloaded binary.")
+        self.set_workon(False)
+        files_to_rm = Path("/var/lib/portage/pkgs").glob("sys-*/*")
+        try:
+            subprocess.check_call(
+                ["sudo", "rm", "-f"] + [str(f) for f in files_to_rm]
+            )
+            subprocess.check_call(["emerge", "-C", "llvm"])
+            subprocess.check_call(["emerge", "-G", "llvm"])
+        except subprocess.CalledProcessError:
+            logging.exception("LLVM could not be reset.")
+            raise AbortingException
+
+    def build(self, use_flags: Text) -> CommandResult:
+        """Build selected LLVM version."""
+        logging.info(
+            "Building llvm with candidate hash. Use flags will be %s", use_flags
+        )
+        self.set_workon(True)
+        try:
+            output = subprocess.check_output(
+                ["sudo", "emerge", "llvm"],
+                env={"USE": use_flags, **os.environ},
+                encoding="utf-8",
+                stderr=subprocess.STDOUT,
+            )
+            return_code = 0
+        except subprocess.CalledProcessError as e:
+            return_code = e.returncode
+            output = e.output
+        return CommandResult(return_code, output)
+
+
+def run_test(command: Text) -> CommandResult:
+    """Run test command and get a CommandResult."""
+    logging.info("Running test command: %s", command)
+    result = subprocess.run(
+        command,
+        check=False,
+        encoding="utf-8",
+        shell=True,
+        stdout=subprocess.PIPE,
+        stderr=subprocess.STDOUT,
+    )
+    logging.info("Test command returned with: %d", result.returncode)
+    return CommandResult(result.returncode, result.stdout)
+
+
+def get_use_flags(
+    use_debug: bool, use_lto: bool, error_on_patch_failure: bool
+) -> str:
+    """Get the USE flags for building LLVM."""
+    use_flags = []
+    if use_debug:
+        use_flags.append("debug")
+    if not use_lto:
+        use_flags.append("-thinlto")
+        use_flags.append("-llvm_pgo_use")
+    if not error_on_patch_failure:
+        use_flags.append("continue-on-patch-failure")
+    return " ".join(use_flags)
+
+
+def abort(never_abort: bool):
+    """Exit with EXIT_ABORT or else EXIT_SKIP if never_abort is set."""
+    if never_abort:
+        logging.info(
+            "Would have aborted but --never-abort was set. "
+            "Completed bisection stage with: SKIP"
+        )
+        sys.exit(EXIT_SKIP)
+    else:
+        logging.info("Completed bisection stage with: ABORT")
+        sys.exit(EXIT_ABORT)
+
+
+def get_args() -> argparse.Namespace:
+    parser = argparse.ArgumentParser(
+        description="Simple LLVM Bisection Script for use with llvm-9999."
+    )
+
+    parser.add_argument(
+        "--never-abort",
+        action="store_true",
+        help=(
+            "Return SKIP (125) for unrecoverable hash-independent errors "
+            "instead of ABORT (255)."
+        ),
+    )
+    parser.add_argument(
+        "--reset-llvm",
+        action="store_true",
+        help="Reset llvm with downloaded prebuilds before rebuilding",
+    )
+    parser.add_argument(
+        "--skip-build",
+        action="store_true",
+        help="Don't build or reset llvm, even if --reset-llvm is set.",
+    )
+    parser.add_argument(
+        "--use-debug",
+        action="store_true",
+        help="Build llvm with assertions enabled",
+    )
+    parser.add_argument(
+        "--use-lto",
+        action="store_true",
+        help="Build llvm with thinlto and PGO. This will increase build times.",
+    )
+    parser.add_argument(
+        "--error-on-patch-failure",
+        action="store_true",
+        help="Don't add continue-on-patch-failure to LLVM use flags.",
+    )
+
+    test_group = parser.add_mutually_exclusive_group(required=True)
+    test_group.add_argument(
+        "--test-llvm-build",
+        action="store_true",
+        help="Bisect the llvm build instead of a test command/script.",
+    )
+    test_group.add_argument(
+        "--test", help="Command to test (exp. 'emerge-atlas grpc')"
+    )
+
+    parser.add_argument(
+        "--search-error",
+        default="",
+        help=(
+            "Search for an error string from test if test has nonzero exit "
+            "code. If test has a non-zero exit code but search string is not "
+            "found, git bisect SKIP will be used."
+        ),
+    )
+    parser.add_argument(
+        "--log-dir",
+        help=(
+            "Save a log of each output to a directory. "
+            "Logs will be written to `{log_dir}/{llvm_hash}.{decision}`"
+        ),
+    )
+
+    return parser.parse_args()
+
+
+def run(opts: argparse.Namespace):
+    # Validate path to Log dir.
+    log_dir = opts.log_dir
+    if log_dir:
+        log_dir = Path(log_dir)
+        if log_dir.exists() and not log_dir.is_dir():
+            logging.error("argument --log-dir: Given path is not a directory!")
+            raise AbortingException()
+
+    # Get LLVM repo
+    llvm_repo = LLVMRepo()
+    llvm_hash = llvm_repo.get_current_hash()
+    logging.info("Testing LLVM Hash: %s", llvm_hash)
+
+    # Build LLVM
+    if not opts.skip_build:
+
+        # Get llvm USE flags.
+        use_flags = get_use_flags(
+            opts.use_debug, opts.use_lto, opts.error_on_patch_failure
+        )
+
+        # Reset LLVM if needed.
+        if opts.reset_llvm:
+            llvm_repo.reset()
+
+        # Build new LLVM-9999.
+        build_result = llvm_repo.build(use_flags)
+
+        # Check LLVM-9999 build.
+        if opts.test_llvm_build:
+            logging.info("Checking result of build....")
+            build_result.exit_assert(opts.search_error, llvm_hash, opts.log_dir)
+        elif build_result.success():
+            logging.info("LLVM candidate built successfully.")
+        else:
+            logging.error("LLVM could not be built.")
+            logging.info("Completed bisection stage with: SKIP.")
+            sys.exit(EXIT_SKIP)
+
+    # Run Test Command.
+    test_result = run_test(opts.test)
+    logging.info("Checking result of test command....")
+    test_result.exit_assert(opts.search_error, llvm_hash, log_dir)
+
+
+def main():
+    logging.basicConfig(level=logging.INFO)
+    chroot.VerifyInsideChroot()
+    opts = get_args()
+    try:
+        run(opts)
+    except AbortingException:
+        abort(opts.never_abort)
+    except Exception:
+        logging.exception("Uncaught Exception in main")
+        abort(opts.never_abort)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/llvm_tools/manifest_utils.py b/llvm_tools/manifest_utils.py
index 3d6337b..e53afa6 100644
--- a/llvm_tools/manifest_utils.py
+++ b/llvm_tools/manifest_utils.py
@@ -11,7 +11,7 @@
 from pathlib import Path
 import shutil
 import subprocess
-from typing import List, Union
+from typing import List, Optional, Union
 from xml.etree import ElementTree
 
 import atomic_write_file
@@ -28,13 +28,64 @@
     """Error occurred when updating the manifest."""
 
 
-def make_xmlparser():
+class ManifestParseError(Exception):
+    """Error occurred when parsing the contents of the manifest."""
+
+
+def make_xmlparser() -> ElementTree.XMLParser:
     """Return a new xmlparser with custom TreeBuilder."""
     return ElementTree.XMLParser(
         target=ElementTree.TreeBuilder(insert_comments=True)
     )
 
 
+def _find_llvm_project_in_manifest_tree(
+    xmlroot: ElementTree.Element,
+) -> Optional[ElementTree.Element]:
+    """Returns the llvm-project `project` in `xmlroot`, if it exists."""
+    for child in xmlroot:
+        if (
+            child.tag == "project"
+            and child.attrib.get("path") == LLVM_PROJECT_PATH
+        ):
+            return child
+    return None
+
+
+def extract_current_llvm_hash(src_tree: Path) -> str:
+    """Returns the current LLVM SHA for the CrOS tree rooted at `src_tree`.
+
+    Raises:
+        ManifestParseError if the manifest didn't have the expected contents.
+    """
+    xmlroot = ElementTree.parse(
+        get_chromeos_manifest_path(src_tree), parser=make_xmlparser()
+    ).getroot()
+    return extract_current_llvm_hash_from_xml(xmlroot)
+
+
+def extract_current_llvm_hash_from_xml(xmlroot: ElementTree.Element) -> str:
+    """Returns the current LLVM SHA for the parsed XML file.
+
+    Raises:
+        ManifestParseError if the manifest didn't have the expected contents.
+    """
+    if xmlroot.tag != "manifest":
+        raise ManifestParseError(
+            f"Root tag is {xmlroot.tag}; should be `manifest`."
+        )
+
+    llvm_project = _find_llvm_project_in_manifest_tree(xmlroot)
+    if llvm_project is None:
+        raise ManifestParseError("No llvm-project `project` found in manifest.")
+
+    revision = llvm_project.attrib.get("revision")
+    if not revision:
+        raise ManifestParseError("Toolchain's `project` has no revision.")
+
+    return revision
+
+
 def update_chromeos_manifest(revision: str, src_tree: Path) -> Path:
     """Replaces the manifest project revision with 'revision'.
 
@@ -73,21 +124,11 @@
 
 def update_chromeos_manifest_tree(revision: str, xmlroot: ElementTree.Element):
     """Update the revision info for LLVM for a manifest XML root."""
-
-    # This exists mostly for testing.
-    def is_llvm_project(child):
-        return (
-            child.tag == "project" and child.attrib["path"] == LLVM_PROJECT_PATH
-        )
-
-    finder = (child for child in xmlroot if is_llvm_project(child))
-    llvm_project_elem = next(finder, None)
+    llvm_project_elem = _find_llvm_project_in_manifest_tree(xmlroot)
     # Element objects can be falsy, so we need to explicitly check None.
-    if llvm_project_elem is not None:
-        # Update the llvm revision git sha
-        llvm_project_elem.attrib["revision"] = revision
-    else:
+    if llvm_project_elem is None:
         raise UpdateManifestError("xmltree did not have llvm-project")
+    llvm_project_elem.attrib["revision"] = revision
 
 
 def format_manifest(repo_manifest: Path):
diff --git a/llvm_tools/manifest_utils_unittest.py b/llvm_tools/manifest_utils_unittest.py
index 8e283e3..2817941 100755
--- a/llvm_tools/manifest_utils_unittest.py
+++ b/llvm_tools/manifest_utils_unittest.py
@@ -77,6 +77,16 @@
         string_root2 = ElementTree.tostring(root)
         self.assertEqual(string_root1, string_root2)
 
+    def test_extract_current_llvm_hash(self):
+        root = ElementTree.fromstring(
+            MANIFEST_FIXTURE,
+            parser=manifest_utils.make_xmlparser(),
+        )
+        self.assertEqual(
+            manifest_utils.extract_current_llvm_hash_from_xml(root),
+            "abcd",
+        )
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/llvm_tools/modify_a_tryjob.py b/llvm_tools/modify_a_tryjob.py
index e5b583c..40024a9 100755
--- a/llvm_tools/modify_a_tryjob.py
+++ b/llvm_tools/modify_a_tryjob.py
@@ -93,7 +93,7 @@
 
     # Add argument for a specific chroot path.
     parser.add_argument(
-        "--chroot_path",
+        "--chromeos_path",
         default=cros_root,
         help="the path to the chroot (default: %(default)s)",
     )
@@ -128,7 +128,7 @@
     packages: Iterable[str],
     git_hash: str,
     svn_version: int,
-    chroot_path: Union[Path, str],
+    chromeos_path: Union[Path, str],
     svn_option: Union[int, str],
 ) -> git.CommitContents:
     """Updates the packages' LLVM_NEXT."""
@@ -139,7 +139,7 @@
         llvm_variant=update_chromeos_llvm_hash.LLVMVariant.next,
         git_hash=git_hash,
         svn_version=svn_version,
-        chroot_path=Path(chroot_path),
+        chroot_opts=update_chromeos_llvm_hash.ChrootOpts(Path(chromeos_path)),
         mode=failure_modes.FailureModes.DISABLE_PATCHES,
         git_hash_source=svn_option,
         extra_commit_msg_lines=None,
@@ -160,7 +160,7 @@
     extra_cls: List[int],
     options: List[str],
     builder: str,
-    chroot_path: Union[Path, str],
+    chromeos_path: Union[Path, str],
     cl_url: str,
     revision,
 ) -> Dict:
@@ -178,7 +178,7 @@
     #   }
     # ]
     tryjob_results = update_packages_and_run_tests.RunTryJobs(
-        cl, extra_cls, options, [builder], chroot_path
+        cl, extra_cls, options, [builder], chromeos_path
     )
     print("\nTryjob:")
     print(tryjob_results[0])
@@ -198,7 +198,7 @@
     packages: Iterable[str],
     git_hash: str,
     revision: int,
-    chroot_path: Union[Path, str],
+    chromeos_path: Union[Path, str],
     extra_cls: List[int],
     options: List[str],
     builder: str,
@@ -210,7 +210,7 @@
         packages,
         git_hash,
         revision,
-        chroot_path,
+        chromeos_path,
         svn_option,
     )
 
@@ -219,7 +219,7 @@
         extra_cls,
         options,
         builder,
-        chroot_path,
+        chromeos_path,
         change_list.url,
         revision,
     )
@@ -234,7 +234,7 @@
     extra_cls: List[int],
     options: List[str],
     builder: str,
-    chroot_path: Union[Path, str],
+    chromeos_path: Union[Path, str],
 ) -> None:
     """Removes, relaunches, or adds a tryjob.
 
@@ -246,8 +246,7 @@
         extra_cls: Extra change lists to be run alongside tryjob
         options: Extra options to pass into 'cros tryjob'.
         builder: The builder to use for 'cros tryjob'.
-        chroot_path: The absolute path to the chroot (used by 'cros tryjob'
-          when relaunching a tryjob).
+        chromeos_path: The absolute path to the chromeos checkout.
     """
 
     # Format of 'bisect_contents':
@@ -289,7 +288,7 @@
             bisect_contents["jobs"][tryjob_index]["extra_cls"],
             bisect_contents["jobs"][tryjob_index]["options"],
             bisect_contents["jobs"][tryjob_index]["builder"],
-            chroot_path,
+            chromeos_path,
         )
 
         bisect_contents["jobs"][tryjob_index][
@@ -326,7 +325,7 @@
                 update_chromeos_llvm_hash.DEFAULT_PACKAGES,
                 git_hash,
                 revision,
-                chroot_path,
+                chromeos_path,
                 extra_cls,
                 options,
                 builder,
@@ -356,7 +355,7 @@
 
     args_output = GetCommandLineArgs()
 
-    chroot.VerifyChromeOSRoot(args_output.chroot_path)
+    chroot.VerifyChromeOSRoot(args_output.chromeos_path)
 
     PerformTryjobModification(
         args_output.revision,
@@ -365,7 +364,7 @@
         args_output.extra_change_lists,
         args_output.options,
         args_output.builder,
-        args_output.chroot_path,
+        args_output.chromeos_path,
     )
 
 
diff --git a/llvm_tools/modify_a_tryjob_unittest.py b/llvm_tools/modify_a_tryjob_unittest.py
index 8b72ffd..0f693dc 100755
--- a/llvm_tools/modify_a_tryjob_unittest.py
+++ b/llvm_tools/modify_a_tryjob_unittest.py
@@ -44,7 +44,7 @@
                     args_output.extra_change_lists,
                     args_output.options,
                     args_output.builders,
-                    args_output.chroot_path,
+                    args_output.chromeos_path,
                 )
 
             self.assertEqual(
@@ -88,7 +88,7 @@
                     args_output.extra_change_lists,
                     args_output.options,
                     args_output.builders,
-                    args_output.chroot_path,
+                    args_output.chromeos_path,
                 )
 
             self.assertEqual(
@@ -130,7 +130,7 @@
                 args_output.extra_change_lists,
                 args_output.options,
                 args_output.builders,
-                args_output.chroot_path,
+                args_output.chromeos_path,
             )
 
             # Verify that the tryjob was removed from the status file.
@@ -198,7 +198,7 @@
                 args_output.extra_change_lists,
                 args_output.options,
                 args_output.builders,
-                args_output.chroot_path,
+                args_output.chromeos_path,
             )
 
             # Verify that the tryjob's information was updated after submtting
@@ -265,7 +265,7 @@
                     args_output.extra_change_lists,
                     args_output.options,
                     args_output.builders,
-                    args_output.chroot_path,
+                    args_output.chromeos_path,
                 )
 
             self.assertEqual(
@@ -312,7 +312,7 @@
                     args_output.extra_change_lists,
                     args_output.options,
                     args_output.builders,
-                    args_output.chroot_path,
+                    args_output.chromeos_path,
                 )
 
             self.assertEqual(
@@ -376,7 +376,7 @@
                 args_output.extra_change_lists,
                 args_output.options,
                 args_output.builders,
-                args_output.chroot_path,
+                args_output.chromeos_path,
             )
 
             # Verify that the tryjob was added to the status file.
@@ -429,7 +429,7 @@
                     args_output.extra_change_lists,
                     args_output.options,
                     args_output.builders,
-                    args_output.chroot_path,
+                    args_output.chromeos_path,
                 )
 
             self.assertEqual(
diff --git a/llvm_tools/nightly_revert_checker.py b/llvm_tools/nightly_revert_checker.py
index 88aac9b..6090e61 100755
--- a/llvm_tools/nightly_revert_checker.py
+++ b/llvm_tools/nightly_revert_checker.py
@@ -11,10 +11,10 @@
 
 import argparse
 import dataclasses
-import io
 import json
 import logging
 import os
+from pathlib import Path
 import pprint
 import subprocess
 import sys
@@ -131,57 +131,18 @@
     return result
 
 
-def _parse_llvm_ebuild_for_shas(
-    ebuild_file: io.TextIOWrapper,
-) -> List[Tuple[str, str]]:
-    def parse_ebuild_assignment(line: str) -> str:
-        no_comments = line.split("#")[0]
-        no_assign = no_comments.split("=", 1)[1].strip()
-        assert no_assign.startswith('"') and no_assign.endswith('"'), no_assign
-        return no_assign[1:-1]
-
-    llvm_hash, llvm_next_hash = None, None
-    for line in ebuild_file:
-        if line.startswith("LLVM_HASH="):
-            llvm_hash = parse_ebuild_assignment(line)
-            if llvm_next_hash:
-                break
-        if line.startswith("LLVM_NEXT_HASH"):
-            llvm_next_hash = parse_ebuild_assignment(line)
-            if llvm_hash:
-                break
-    if not llvm_next_hash or not llvm_hash:
-        raise ValueError(
-            "Failed to detect SHAs for llvm/llvm_next. Got: "
-            "llvm=%s; llvm_next=%s" % (llvm_hash, llvm_next_hash)
-        )
-
-    results: List[Tuple[str, str]] = [("llvm", llvm_hash)]
-    if llvm_next_hash != llvm_hash:
-        results.append(("llvm-next", llvm_next_hash))
-    return results
-
-
 def _find_interesting_chromeos_shas(
     chromeos_base: str,
 ) -> List[Tuple[str, str]]:
-    llvm_dir = os.path.join(
-        chromeos_base, "src/third_party/chromiumos-overlay/sys-devel/llvm"
-    )
-    candidate_ebuilds = [
-        os.path.join(llvm_dir, x)
-        for x in os.listdir(llvm_dir)
-        if "_pre" in x and not os.path.islink(os.path.join(llvm_dir, x))
-    ]
+    chromeos_path = Path(chromeos_base)
+    llvm_hash = get_llvm_hash.LLVMHash()
 
-    if len(candidate_ebuilds) != 1:
-        raise ValueError(
-            "Expected exactly one llvm ebuild candidate; got %s"
-            % pprint.pformat(candidate_ebuilds)
-        )
-
-    with open(candidate_ebuilds[0], encoding="utf-8") as f:
-        return _parse_llvm_ebuild_for_shas(f)
+    current_llvm = llvm_hash.GetCrOSCurrentLLVMHash(chromeos_path)
+    results = [("llvm", current_llvm)]
+    next_llvm = llvm_hash.GetCrOSLLVMNextHash()
+    if current_llvm != next_llvm:
+        results.append(("llvm-next", next_llvm))
+    return results
 
 
 _Email = NamedTuple(
diff --git a/llvm_tools/nightly_revert_checker_test.py b/llvm_tools/nightly_revert_checker_test.py
index 722ad12..dbcd01d 100755
--- a/llvm_tools/nightly_revert_checker_test.py
+++ b/llvm_tools/nightly_revert_checker_test.py
@@ -5,7 +5,6 @@
 
 """Tests for nightly_revert_checker."""
 
-import io
 import unittest
 from unittest import mock
 
@@ -138,43 +137,6 @@
 
         self.assertEqual(email, expected_email)
 
-    def test_llvm_ebuild_parsing_appears_to_function(self):
-        llvm_ebuild = io.StringIO(
-            "\n".join(
-                (
-                    "foo",
-                    '#LLVM_HASH="123"',
-                    'LLVM_HASH="123" # comment',
-                    'LLVM_NEXT_HASH="456"',
-                )
-            )
-        )
-
-        shas = nightly_revert_checker._parse_llvm_ebuild_for_shas(llvm_ebuild)
-        self.assertEqual(
-            shas,
-            [
-                ("llvm", "123"),
-                ("llvm-next", "456"),
-            ],
-        )
-
-    def test_llvm_ebuild_parsing_fails_if_both_hashes_arent_present(self):
-        bad_bodies = [
-            "",
-            'LLVM_HASH="123" # comment',
-            'LLVM_NEXT_HASH="123" # comment',
-            'LLVM_NEXT_HASH="123" # comment\n#LLVM_HASH="123"',
-        ]
-
-        for bad in bad_bodies:
-            with self.assertRaises(ValueError) as e:
-                nightly_revert_checker._parse_llvm_ebuild_for_shas(
-                    io.StringIO(bad)
-                )
-
-            self.assertIn("Failed to detect SHAs", str(e.exception))
-
     @mock.patch("revert_checker.find_reverts")
     @mock.patch("get_upstream_patch.get_from_upstream")
     def test_do_cherrypick_is_called(self, do_cherrypick, find_reverts):
diff --git a/llvm_tools/patch_manager.py b/llvm_tools/patch_manager.py
index 3327228..801f846 100755
--- a/llvm_tools/patch_manager.py
+++ b/llvm_tools/patch_manager.py
@@ -115,7 +115,6 @@
     llvm_src_dir: Path,
     patches_json_fp: Path,
     rel_patch_path: str,
-    patch_cmd: Optional[Callable] = None,
 ) -> GitBisectionCode:
     """Check that a given patch with the rel_patch_path applies in the stack.
 
@@ -131,7 +130,6 @@
         rel_patch_path: Relative patch path of the patch we want to check. If
           patches before this patch fail to apply, then the revision is
           skipped.
-        patch_cmd: Use 'git am' to patch instead of GNU 'patch'.
     """
     with patches_json_fp.open(encoding="utf-8") as f:
         patch_entries = patch_utils.json_to_patch_entries(
@@ -285,11 +283,6 @@
         )
         PrintPatchResults(result)
 
-    def _remove(args):
-        patch_utils.remove_old_patches(
-            args.svn_version, llvm_src_dir, patches_json_fp
-        )
-
     def _disable(args):
         patch_cmd = patch_utils.git_am if args.git_am else patch_utils.gnu_patch
         patch_utils.update_version_ranges(
@@ -302,13 +295,11 @@
                 "Running with bisect_patches requires the " "--test_patch flag."
             )
         svn_version = GetHEADSVNVersion(llvm_src_dir)
-        patch_cmd = patch_utils.git_am if args.git_am else patch_utils.gnu_patch
         error_code = CheckPatchApplies(
             svn_version,
             llvm_src_dir,
             patches_json_fp,
             args.test_patch,
-            patch_cmd,
         )
         # Since this is for bisection, we want to exit with the
         # GitBisectionCode enum.
@@ -317,7 +308,6 @@
     dispatch_table = {
         failure_modes.FailureModes.FAIL: _apply_all,
         failure_modes.FailureModes.CONTINUE: _apply_all,
-        failure_modes.FailureModes.REMOVE_PATCHES: _remove,
         failure_modes.FailureModes.DISABLE_PATCHES: _disable,
         failure_modes.FailureModes.BISECT_PATCHES: _test_single,
     }
diff --git a/llvm_tools/patch_manager_unittest.py b/llvm_tools/patch_manager_unittest.py
index 1087727..30acd24 100755
--- a/llvm_tools/patch_manager_unittest.py
+++ b/llvm_tools/patch_manager_unittest.py
@@ -124,7 +124,6 @@
                         dirpath,
                         patches_path,
                         "example.patch",
-                        patch_utils.gnu_patch,
                     )
                     self.assertEqual(result, expected)
                     m.assert_called()
@@ -165,7 +164,6 @@
                         dirpath,
                         patches_path,
                         "example.patch",
-                        patch_utils.gnu_patch,
                     )
                     self.assertEqual(result, expected)
 
diff --git a/llvm_tools/patch_sync/src/main.rs b/llvm_tools/patch_sync/src/main.rs
index 5f9b970..e3fa482 100644
--- a/llvm_tools/patch_sync/src/main.rs
+++ b/llvm_tools/patch_sync/src/main.rs
@@ -180,14 +180,16 @@
             )
         })?
     };
-    let new_android_patches = new_android_patches.filter_patches(|p| {
-        match (p.get_from_version(), p.get_until_version()) {
+    if args.verbose {
+        println!("Android LLVM version: r{}", android_llvm_version);
+    }
+    let new_cros_patches =
+        new_cros_patches.filter_patches(|p| match (p.get_from_version(), p.get_until_version()) {
             (Some(start), Some(end)) => start <= android_llvm_version && android_llvm_version < end,
             (Some(start), None) => start <= android_llvm_version,
             (None, Some(end)) => android_llvm_version < end,
             (None, None) => true,
-        }
-    });
+        });
 
     // Need to filter version updates to only existing patches to the other platform.
     let cros_version_updates =
diff --git a/llvm_tools/patch_sync/src/patch_parsing.rs b/llvm_tools/patch_sync/src/patch_parsing.rs
index 7f545e5..193c7fb 100644
--- a/llvm_tools/patch_sync/src/patch_parsing.rs
+++ b/llvm_tools/patch_sync/src/patch_parsing.rs
@@ -73,9 +73,12 @@
     }
 
     /// Copy this collection with patches filtered by given criterion.
-    pub fn filter_patches(&self, f: impl FnMut(&PatchDictSchema) -> bool) -> Self {
+    pub fn filter_patches<F>(&self, mut f: F) -> Self
+    where
+        F: FnMut(&PatchDictSchema) -> bool,
+    {
         Self {
-            patches: self.patches.iter().cloned().filter(f).collect(),
+            patches: self.patches.iter().filter(|&x| f(x)).cloned().collect(),
             workdir: self.workdir.clone(),
             indent_len: self.indent_len,
         }
@@ -310,11 +313,25 @@
                 .and_then(serde_json::Value::as_str)
                 .unwrap_or("[No Title]");
             let path = self.workdir.join(&p.rel_patch_path);
+            let from = p.get_from_version();
+            let until = p.get_until_version();
             writeln!(f, "* {}", title)?;
             if i == self.patches.len() - 1 {
-                write!(f, "  {}", path.display())?;
+                write!(
+                    f,
+                    "  {}\n  r{}-r{}",
+                    path.display(),
+                    from.map_or("None".to_string(), |x| x.to_string()),
+                    until.map_or("None".to_string(), |x| x.to_string())
+                )?;
             } else {
-                writeln!(f, "  {}", path.display())?;
+                writeln!(
+                    f,
+                    "  {}\n  r{}-r{}",
+                    path.display(),
+                    from.map_or("None".to_string(), |x| x.to_string()),
+                    until.map_or("None".to_string(), |x| x.to_string())
+                )?;
             }
         }
         Ok(())
@@ -437,7 +454,7 @@
         std::fs::create_dir_all(to_parent)?;
     }
 
-    copy(&from, &to)
+    copy(from, to)
         .with_context(|| format!("copying file from {} to {}", &from.display(), &to.display()))?;
     Ok(())
 }
diff --git a/llvm_tools/patch_sync/src/version_control.rs b/llvm_tools/patch_sync/src/version_control.rs
index 5d70a4b..55197f9 100644
--- a/llvm_tools/patch_sync/src/version_control.rs
+++ b/llvm_tools/patch_sync/src/version_control.rs
@@ -43,8 +43,8 @@
                 let android_git = anpp.parent().unwrap();
                 git_cd_cmd(android_git, ["checkout", ANDROID_MAIN_BRANCH])?;
             }
-            repo_cd_cmd(&self.cros_checkout, &["sync", CHROMIUMOS_OVERLAY_REL_PATH])?;
-            repo_cd_cmd(&self.android_checkout, &["sync", ANDROID_LLVM_REL_PATH])?;
+            repo_cd_cmd(&self.cros_checkout, ["sync", CHROMIUMOS_OVERLAY_REL_PATH])?;
+            repo_cd_cmd(&self.android_checkout, ["sync", ANDROID_LLVM_REL_PATH])?;
         }
         Ok(())
     }
@@ -52,7 +52,7 @@
     pub fn cros_repo_upload<S: AsRef<str>>(&self, reviewers: &[S]) -> Result<()> {
         let llvm_dir = self
             .cros_checkout
-            .join(&CHROMIUMOS_OVERLAY_REL_PATH)
+            .join(CHROMIUMOS_OVERLAY_REL_PATH)
             .join("sys-devel/llvm");
         ensure!(
             llvm_dir.is_dir(),
@@ -142,14 +142,14 @@
     /// Get the Android path to the PATCHES.json file
     pub fn android_patches_path(&self) -> PathBuf {
         self.android_checkout
-            .join(&ANDROID_LLVM_REL_PATH)
+            .join(ANDROID_LLVM_REL_PATH)
             .join("patches/PATCHES.json")
     }
 
     /// Get the ChromiumOS path to the PATCHES.json file
     pub fn cros_patches_path(&self) -> PathBuf {
         self.cros_checkout
-            .join(&CHROMIUMOS_OVERLAY_REL_PATH)
+            .join(CHROMIUMOS_OVERLAY_REL_PATH)
             .join("sys-devel/llvm/files/PATCHES.json")
     }
 
@@ -177,7 +177,7 @@
         commit_msg: &str,
         extra_flags: I,
     ) -> Result<()> {
-        let git_path = &checkout_path.join(&subproject_git_wd);
+        let git_path = &checkout_path.join(subproject_git_wd);
         ensure!(
             git_path.is_dir(),
             "git_path {} is not a directory",
@@ -185,7 +185,7 @@
         );
         repo_cd_cmd(
             checkout_path,
-            &["start", WORK_BRANCH_NAME, subproject_git_wd],
+            ["start", WORK_BRANCH_NAME, subproject_git_wd],
         )?;
         let base_args = ["upload", "--br", WORK_BRANCH_NAME, "-y", "--verify"];
         let new_args = base_args
@@ -193,8 +193,8 @@
             .copied()
             .chain(extra_flags)
             .chain(["--", subproject_git_wd]);
-        git_cd_cmd(git_path, &["add", "."])
-            .and_then(|_| git_cd_cmd(git_path, &["commit", "-m", commit_msg]))
+        git_cd_cmd(git_path, ["add", "."])
+            .and_then(|_| git_cd_cmd(git_path, ["commit", "-m", commit_msg]))
             .and_then(|_| repo_cd_cmd(checkout_path, new_args))?;
         Ok(())
     }
@@ -249,7 +249,7 @@
             file.to_str()
                 .ok_or_else(|| anyhow!("failed to convert filepath to str"))?
         );
-        let output = git_cd_cmd(pwd, &["show", &git_ref])?;
+        let output = git_cd_cmd(pwd, ["show", &git_ref])?;
         if !output.status.success() {
             bail!("could not get old file contents for {}", &git_ref)
         }
@@ -318,7 +318,7 @@
     S: AsRef<OsStr>,
 {
     let mut command = Command::new("git");
-    command.current_dir(&pwd).args(args);
+    command.current_dir(pwd).args(args);
     let output = command.output()?;
     if !output.status.success() {
         bail!(
@@ -337,7 +337,7 @@
     S: AsRef<OsStr>,
 {
     let mut command = Command::new("repo");
-    command.current_dir(&pwd).args(args);
+    command.current_dir(pwd).args(args);
     let status = command.status()?;
     if !status.success() {
         bail!("repo command failed:\n  {:?}  \n", command)
@@ -363,7 +363,7 @@
             // With revision
             let ebuild_name = "llvm-13.0_pre433403_p20211019-r10.ebuild";
             let ebuild_path = llvm_dir.join(ebuild_name);
-            File::create(&ebuild_path).expect("creating test ebuild file");
+            File::create(ebuild_path).expect("creating test ebuild file");
             let new_ebuild_path =
                 RepoSetupContext::rev_bump_llvm(&llvm_dir).expect("rev bumping the ebuild");
             assert!(
@@ -377,7 +377,7 @@
             // Without revision
             let ebuild_name = "llvm-13.0_pre433403_p20211019.ebuild";
             let ebuild_path = llvm_dir.join(ebuild_name);
-            File::create(&ebuild_path).expect("creating test ebuild file");
+            File::create(ebuild_path).expect("creating test ebuild file");
             let new_ebuild_path =
                 RepoSetupContext::rev_bump_llvm(&llvm_dir).expect("rev bumping the ebuild");
             assert!(
@@ -394,7 +394,7 @@
             File::create(&ebuild_path).expect("creating test ebuild file");
             let ebuild_link_name = "llvm-13.0_pre433403_p20211019-r2.ebuild";
             let ebuild_link_path = llvm_dir.join(ebuild_link_name);
-            File::create(&ebuild_link_path).expect("creating test ebuild link file");
+            File::create(ebuild_link_path).expect("creating test ebuild link file");
             let new_ebuild_path =
                 RepoSetupContext::rev_bump_llvm(&llvm_dir).expect("rev bumping the ebuild");
             assert!(
diff --git a/llvm_tools/patch_utils.py b/llvm_tools/patch_utils.py
index b21cf31..c180a87 100644
--- a/llvm_tools/patch_utils.py
+++ b/llvm_tools/patch_utils.py
@@ -34,6 +34,15 @@
 HUNK_END_RE = re.compile(r"^--\s*$")
 PATCH_SUBFILE_HEADER_RE = re.compile(r"^\+\+\+ [ab]/(.*)$")
 
+CHROMEOS_PATCHES_JSON_PACKAGES = (
+    "dev-util/lldb-server",
+    "sys-devel/llvm",
+    "sys-libs/compiler-rt",
+    "sys-libs/libcxx",
+    "sys-libs/llvm-libunwind",
+    "sys-libs/scudo",
+)
+
 
 @dataclasses.dataclass
 class Hunk:
@@ -149,6 +158,31 @@
         return s
 
 
+def git_apply(patch_path: Path) -> List[Union[str, Path]]:
+    """Patch a patch file using 'git apply'."""
+    return ["git", "apply", patch_path]
+
+
+def git_am(patch_path: Path) -> List[Union[str, Path]]:
+    """Patch a patch file using 'git am'."""
+    return ["git", "am", "--3way", patch_path]
+
+
+def gnu_patch(root_dir: Path, patch_path: Path) -> List[Union[str, Path]]:
+    """Patch a patch file using GNU 'patch'."""
+    return [
+        "patch",
+        "-d",
+        root_dir.absolute(),
+        "-f",
+        "-E",
+        "-p1",
+        "--no-backup-if-mismatch",
+        "-i",
+        patch_path,
+    ]
+
+
 @dataclasses.dataclass
 class PatchEntry:
     """Object mapping of an entry of PATCHES.json."""
@@ -232,16 +266,6 @@
             until_v = sys.maxsize
         return from_v <= svn_version < until_v
 
-    def is_old(self, svn_version: int) -> bool:
-        """Is this patch old compared to `svn_version`?"""
-        if not self.version_range:
-            return False
-        until_v = self.version_range.get("until")
-        # Sometimes the key is there, but it's set to None.
-        if until_v is None:
-            until_v = sys.maxsize
-        return svn_version >= until_v
-
     def apply(
         self,
         root_dir: Path,
@@ -256,11 +280,8 @@
                 f"Cannot apply: patch {abs_patch_path} is not a file"
             )
 
-        if not patch_cmd:
-            patch_cmd = gnu_patch
-
-        if patch_cmd == gnu_patch:
-            cmd = patch_cmd(root_dir, abs_patch_path) + (extra_args or [])
+        if not patch_cmd or patch_cmd is gnu_patch:
+            cmd = gnu_patch(root_dir, abs_patch_path) + (extra_args or [])
         else:
             cmd = patch_cmd(abs_patch_path) + (extra_args or [])
 
@@ -272,7 +293,7 @@
             parsed_hunks = self.parsed_hunks()
             failed_hunks_id_dict = parse_failed_patch_output(e.stdout)
             failed_hunks = {}
-            if patch_cmd == gnu_patch:
+            if patch_cmd is gnu_patch:
                 for path, failed_hunk_ids in failed_hunks_id_dict.items():
                     hunks_for_file = parsed_hunks[path]
                     failed_hunks[path] = [
@@ -281,7 +302,7 @@
                         if hunk.hunk_id in failed_hunk_ids
                     ]
             elif failed_hunks_id_dict:
-                # use git am
+                # using git am
                 failed_hunks = parsed_hunks
 
             return PatchResult(succeeded=False, failed_hunks=failed_hunks)
@@ -290,9 +311,19 @@
     def test_apply(
         self, root_dir: Path, patch_cmd: Optional[Callable] = None
     ) -> PatchResult:
-        """Dry run applying a patch to a given directory."""
-        extra_args = [] if patch_cmd == git_am else ["--dry-run"]
-        return self.apply(root_dir, patch_cmd, extra_args)
+        """Dry run applying a patch to a given directory.
+
+        When using gnu_patch, this will pass --dry-run.
+        When using git_am or git_apply, this will instead
+        use git_apply with --summary.
+        """
+        if patch_cmd is git_am or patch_cmd is git_apply:
+            # There is no dry run option for git am,
+            # so we use git apply for test.
+            return self.apply(root_dir, git_apply, ["--summary"])
+        if patch_cmd is gnu_patch or patch_cmd is None:
+            return self.apply(root_dir, patch_cmd, ["--dry-run"])
+        raise ValueError(f"No such patch command: {patch_cmd.__name__}.")
 
     def title(self) -> str:
         if not self.metadata:
@@ -300,6 +331,17 @@
         return self.metadata.get("title", "")
 
 
+def patch_applies_after(
+    version_range: Optional[Dict[str, Optional[int]]], svn_version: int
+) -> bool:
+    """Does this patch apply after `svn_version`?"""
+    if not version_range:
+        return True
+    until = version_range.get("until")
+    before_svn_version = until is not None and svn_version > until
+    return not before_svn_version
+
+
 @dataclasses.dataclass(frozen=True)
 class PatchInfo:
     """Holds info for a round of patch applications."""
@@ -376,6 +418,7 @@
         svn_version: LLVM Subversion revision to patch.
         llvm_src_dir: llvm-project root-level source directory to patch.
         patches_json_fp: Filepath to the PATCHES.json file.
+        patch_cmd: The function to use when actually applying the patch.
         continue_on_failure: Skip any patches which failed to apply,
           rather than throw an Exception.
     """
@@ -565,6 +608,7 @@
         svn_version: LLVM revision number.
         llvm_src_dir: llvm-project directory path.
         patch_entries: PatchEntry objects to modify.
+        patch_cmd: The function to use when actually applying the patch.
 
     Returns:
         Tuple of (modified entries, applied patches)
@@ -597,9 +641,7 @@
     return modified_entries, applied_patches
 
 
-def remove_old_patches(
-    svn_version: int, llvm_src_dir: Path, patches_json_fp: Path
-) -> PatchInfo:
+def remove_old_patches(svn_version: int, patches_json: Path) -> List[Path]:
     """Remove patches that don't and will never apply for the future.
 
     Patches are determined to be "old" via the "is_old" method for
@@ -607,54 +649,24 @@
 
     Args:
         svn_version: LLVM SVN version.
-        llvm_src_dir: LLVM source directory.
-        patches_json_fp: Location to edit patches on.
+        patches_json: Location of PATCHES.json.
 
     Returns:
-        PatchInfo for modified patches.
+        A list of all patch paths removed from PATCHES.json.
     """
-    with patches_json_fp.open(encoding="utf-8") as f:
-        contents = f.read()
+    contents = patches_json.read_text(encoding="utf-8")
     indent_len = predict_indent(contents.splitlines())
-    patch_entries = json_str_to_patch_entries(
-        llvm_src_dir,
-        contents,
-    )
-    oldness = [(entry, entry.is_old(svn_version)) for entry in patch_entries]
-    filtered_entries = [entry.to_dict() for entry, old in oldness if not old]
-    with atomic_write_file.atomic_write(patches_json_fp, encoding="utf-8") as f:
-        _write_json_changes(filtered_entries, f, indent_len=indent_len)
-    removed_entries = [entry for entry, old in oldness if old]
-    plural_patches = "patch" if len(removed_entries) == 1 else "patches"
-    print(f"Removed {len(removed_entries)} old {plural_patches}:")
-    for r in removed_entries:
-        print(f"- {r.rel_patch_path}: {r.title()}")
 
-    return PatchInfo(
-        non_applicable_patches=[],
-        applied_patches=[],
-        failed_patches=[],
-        disabled_patches=[],
-        removed_patches=[p.rel_patch_path for p in removed_entries],
-        modified_metadata=str(patches_json_fp) if removed_entries else None,
-    )
+    still_new = []
+    removed_patches = []
+    patches_parent = patches_json.parent
+    for entry in json.loads(contents):
+        if patch_applies_after(entry.get("version_range"), svn_version):
+            still_new.append(entry)
+        else:
+            removed_patches.append(patches_parent / entry["rel_patch_path"])
 
+    with atomic_write_file.atomic_write(patches_json, encoding="utf-8") as f:
+        _write_json_changes(still_new, f, indent_len=indent_len)
 
-def git_am(patch_path: Path) -> List[Union[str, Path]]:
-    cmd = ["git", "am", "--3way", str(patch_path)]
-    return cmd
-
-
-def gnu_patch(root_dir: Path, patch_path: Path) -> List[Union[str, Path]]:
-    cmd = [
-        "patch",
-        "-d",
-        str(root_dir.absolute()),
-        "-f",
-        "-E",
-        "-p1",
-        "--no-backup-if-mismatch",
-        "-i",
-        str(patch_path),
-    ]
-    return cmd
+    return removed_patches
diff --git a/llvm_tools/patch_utils_unittest.py b/llvm_tools/patch_utils_unittest.py
index 26a211e..311a4db 100755
--- a/llvm_tools/patch_utils_unittest.py
+++ b/llvm_tools/patch_utils_unittest.py
@@ -9,9 +9,9 @@
 import io
 import json
 from pathlib import Path
+import shutil
 import subprocess
 import tempfile
-from typing import Callable
 import unittest
 from unittest import mock
 
@@ -21,6 +21,11 @@
 class TestPatchUtils(unittest.TestCase):
     """Test the patch_utils."""
 
+    def make_tempdir(self) -> Path:
+        tmpdir = Path(tempfile.mkdtemp(prefix="patch_utils_unittest"))
+        self.addCleanup(shutil.rmtree, tmpdir)
+        return tmpdir
+
     def test_predict_indent(self):
         test_str1 = """
 a
@@ -170,7 +175,7 @@
             patch_dir, TestPatchUtils._default_json_dict()
         )
 
-        """Make a deepcopy of the case for testing commit patch option."""
+        # Make a deepcopy of the case for testing commit patch option.
         e1 = copy.deepcopy(e)
 
         with mock.patch("pathlib.Path.is_file", return_value=True):
@@ -178,7 +183,7 @@
                 result = e.apply(src_dir)
         self.assertTrue(result.succeeded)
 
-        """Test that commit patch option works."""
+        # Test that commit patch option works.
         with mock.patch("pathlib.Path.is_file", return_value=True):
             with mock.patch("subprocess.run", mock.MagicMock()):
                 result1 = e1.apply(src_dir, pu.git_am)
@@ -203,157 +208,141 @@
 
     def test_is_git_dirty(self):
         """Test if a git directory has uncommitted changes."""
-        with tempfile.TemporaryDirectory(
-            prefix="patch_utils_unittest"
-        ) as dirname:
-            dirpath = Path(dirname)
+        dirpath = self.make_tempdir()
 
-            def _run_h(cmd):
-                subprocess.run(
-                    cmd,
-                    cwd=dirpath,
-                    stdout=subprocess.DEVNULL,
-                    stderr=subprocess.DEVNULL,
-                    check=True,
-                )
+        def _run_h(cmd):
+            subprocess.run(
+                cmd,
+                cwd=dirpath,
+                stdout=subprocess.DEVNULL,
+                stderr=subprocess.DEVNULL,
+                check=True,
+            )
 
-            _run_h(["git", "init"])
-            self.assertFalse(pu.is_git_dirty(dirpath))
-            test_file = dirpath / "test_file"
-            test_file.touch()
-            self.assertTrue(pu.is_git_dirty(dirpath))
-            _run_h(["git", "add", "."])
-            _run_h(["git", "commit", "-m", "test"])
-            self.assertFalse(pu.is_git_dirty(dirpath))
-            test_file.touch()
-            self.assertFalse(pu.is_git_dirty(dirpath))
-            with test_file.open("w", encoding="utf-8"):
-                test_file.write_text("abc")
-            self.assertTrue(pu.is_git_dirty(dirpath))
+        _run_h(["git", "init"])
+        self.assertFalse(pu.is_git_dirty(dirpath))
+        test_file = dirpath / "test_file"
+        test_file.touch()
+        self.assertTrue(pu.is_git_dirty(dirpath))
+        _run_h(["git", "add", "."])
+        _run_h(["git", "commit", "-m", "test"])
+        self.assertFalse(pu.is_git_dirty(dirpath))
+        test_file.touch()
+        self.assertFalse(pu.is_git_dirty(dirpath))
+        with test_file.open("w", encoding="utf-8"):
+            test_file.write_text("abc")
+        self.assertTrue(pu.is_git_dirty(dirpath))
 
     @mock.patch("patch_utils.git_clean_context", mock.MagicMock)
     def test_update_version_ranges(self):
         """Test the UpdateVersionRanges function."""
-        with tempfile.TemporaryDirectory(
-            prefix="patch_manager_unittest"
-        ) as dirname:
-            dirpath = Path(dirname)
-            patches = [
-                pu.PatchEntry(
-                    workdir=dirpath,
-                    rel_patch_path="x.patch",
-                    metadata=None,
-                    platforms=None,
-                    version_range={
-                        "from": 0,
-                        "until": 2,
-                    },
-                ),
-                pu.PatchEntry(
-                    workdir=dirpath,
-                    rel_patch_path="y.patch",
-                    metadata=None,
-                    platforms=None,
-                    version_range={
-                        "from": 0,
-                        "until": 2,
-                    },
-                ),
-                pu.PatchEntry(
-                    workdir=dirpath,
-                    rel_patch_path="z.patch",
-                    metadata=None,
-                    platforms=None,
-                    version_range={
-                        "from": 4,
-                        "until": 5,
-                    },
-                ),
-            ]
-
-            patches[0].apply = mock.MagicMock(
-                return_value=pu.PatchResult(
-                    succeeded=False, failed_hunks={"a/b/c": []}
-                )
-            )
-            patches[1].apply = mock.MagicMock(
-                return_value=pu.PatchResult(succeeded=True)
-            )
-            patches[2].apply = mock.MagicMock(
-                return_value=pu.PatchResult(succeeded=False)
-            )
-
-            # Make a deepcopy of patches to test commit patch option
-            patches2 = copy.deepcopy(patches)
-
-            results, _ = pu.update_version_ranges_with_entries(
-                1, dirpath, patches, pu.gnu_patch
-            )
-
-            # We should only have updated the version_range of the first patch,
-            # as that one failed to apply.
-            self.assertEqual(len(results), 1)
-            self.assertEqual(results[0].version_range, {"from": 0, "until": 1})
-            self.assertEqual(patches[0].version_range, {"from": 0, "until": 1})
-            self.assertEqual(patches[1].version_range, {"from": 0, "until": 2})
-            self.assertEqual(patches[2].version_range, {"from": 4, "until": 5})
-
-            # Test git am option
-            results2, _ = pu.update_version_ranges_with_entries(
-                1, dirpath, patches2, pu.git_am
-            )
-
-            # We should only have updated the version_range of the first patch
-            # via git am, as that one failed to apply.
-            self.assertEqual(len(results2), 1)
-            self.assertEqual(results2[0].version_range, {"from": 0, "until": 1})
-            self.assertEqual(patches2[0].version_range, {"from": 0, "until": 1})
-            self.assertEqual(patches2[1].version_range, {"from": 0, "until": 2})
-            self.assertEqual(patches2[2].version_range, {"from": 4, "until": 5})
-
-    @mock.patch("builtins.print")
-    def test_remove_old_patches(self, _):
-        """Can remove old patches from PATCHES.json."""
-        one_patch_dict = {
-            "metadata": {
-                "title": "[some label] hello world",
-            },
-            "platforms": [
-                "chromiumos",
-            ],
-            "rel_patch_path": "x/y/z",
-            "version_range": {
-                "from": 4,
-                "until": 5,
-            },
-        }
+        dirpath = self.make_tempdir()
         patches = [
-            one_patch_dict,
-            {**one_patch_dict, "version_range": {"until": None}},
-            {**one_patch_dict, "version_range": {"from": 100}},
-            {**one_patch_dict, "version_range": {"until": 8}},
-        ]
-        cases = [
-            (0, lambda x: self.assertEqual(len(x), 4)),
-            (6, lambda x: self.assertEqual(len(x), 3)),
-            (8, lambda x: self.assertEqual(len(x), 2)),
-            (1000, lambda x: self.assertEqual(len(x), 2)),
+            pu.PatchEntry(
+                workdir=dirpath,
+                rel_patch_path="x.patch",
+                metadata=None,
+                platforms=None,
+                version_range={
+                    "from": 0,
+                    "until": 2,
+                },
+            ),
+            pu.PatchEntry(
+                workdir=dirpath,
+                rel_patch_path="y.patch",
+                metadata=None,
+                platforms=None,
+                version_range={
+                    "from": 0,
+                    "until": 2,
+                },
+            ),
+            pu.PatchEntry(
+                workdir=dirpath,
+                rel_patch_path="z.patch",
+                metadata=None,
+                platforms=None,
+                version_range={
+                    "from": 4,
+                    "until": 5,
+                },
+            ),
         ]
 
-        def _t(dirname: str, svn_version: int, assertion_f: Callable):
-            json_filepath = Path(dirname) / "PATCHES.json"
-            with json_filepath.open("w", encoding="utf-8") as f:
-                json.dump(patches, f)
-            pu.remove_old_patches(svn_version, Path(), json_filepath)
-            with json_filepath.open("r", encoding="utf-8") as f:
-                result = json.load(f)
-            assertion_f(result)
+        patches[0].apply = mock.MagicMock(
+            return_value=pu.PatchResult(
+                succeeded=False, failed_hunks={"a/b/c": []}
+            )
+        )
+        patches[1].apply = mock.MagicMock(
+            return_value=pu.PatchResult(succeeded=True)
+        )
+        patches[2].apply = mock.MagicMock(
+            return_value=pu.PatchResult(succeeded=False)
+        )
 
-        with tempfile.TemporaryDirectory(
-            prefix="patch_utils_unittest"
-        ) as dirname:
-            for r, a in cases:
-                _t(dirname, r, a)
+        # Make a deepcopy of patches to test commit patch option
+        patches2 = copy.deepcopy(patches)
+
+        results, _ = pu.update_version_ranges_with_entries(
+            1, dirpath, patches, pu.gnu_patch
+        )
+
+        # We should only have updated the version_range of the first patch,
+        # as that one failed to apply.
+        self.assertEqual(len(results), 1)
+        self.assertEqual(results[0].version_range, {"from": 0, "until": 1})
+        self.assertEqual(patches[0].version_range, {"from": 0, "until": 1})
+        self.assertEqual(patches[1].version_range, {"from": 0, "until": 2})
+        self.assertEqual(patches[2].version_range, {"from": 4, "until": 5})
+
+        # Test git am option
+        results2, _ = pu.update_version_ranges_with_entries(
+            1, dirpath, patches2, pu.git_am
+        )
+
+        # We should only have updated the version_range of the first patch
+        # via git am, as that one failed to apply.
+        self.assertEqual(len(results2), 1)
+        self.assertEqual(results2[0].version_range, {"from": 0, "until": 1})
+        self.assertEqual(patches2[0].version_range, {"from": 0, "until": 1})
+        self.assertEqual(patches2[1].version_range, {"from": 0, "until": 2})
+        self.assertEqual(patches2[2].version_range, {"from": 4, "until": 5})
+
+    def test_remove_old_patches(self):
+        patches = [
+            {"rel_patch_path": "foo.patch"},
+            {
+                "rel_patch_path": "bar.patch",
+                "version_range": {
+                    "from": 1,
+                },
+            },
+            {
+                "rel_patch_path": "baz.patch",
+                "version_range": {
+                    "until": 1,
+                },
+            },
+        ]
+
+        tempdir = self.make_tempdir()
+        patches_json = tempdir / "PATCHES.json"
+        with patches_json.open("w", encoding="utf-8") as f:
+            json.dump(patches, f)
+
+        removed_paths = pu.remove_old_patches(
+            svn_version=10, patches_json=patches_json
+        )
+        self.assertEqual(removed_paths, [tempdir / "baz.patch"])
+        expected_patches = [
+            x for x in patches if x["rel_patch_path"] != "baz.patch"
+        ]
+        self.assertEqual(
+            json.loads(patches_json.read_text(encoding="utf-8")),
+            expected_patches,
+        )
 
     @staticmethod
     def _default_json_dict():
diff --git a/llvm_tools/setup_for_workon.py b/llvm_tools/setup_for_workon.py
index 41f3d45..8c67f81 100755
--- a/llvm_tools/setup_for_workon.py
+++ b/llvm_tools/setup_for_workon.py
@@ -139,12 +139,6 @@
         """,
     )
     parser.add_argument(
-        "--checkout",
-        help="""
-        If specified, the llvm directory will be checked out to the given SHA.
-        """,
-    )
-    parser.add_argument(
         "--clean-llvm",
         action="store_true",
         help="""
@@ -175,6 +169,26 @@
         Set to 'host' for working on the host system, and not a board.
         """,
     )
+
+    checkout_group = parser.add_mutually_exclusive_group(required=True)
+    checkout_group.add_argument(
+        "--checkout",
+        help="""
+        If specified, the llvm directory will be checked out to the given SHA.
+        """,
+    )
+    # The value of this isn't used anywhere; it's just used as an explicit
+    # nudge for checking LLVM out.
+    checkout_group.add_argument(
+        "--no-checkout",
+        action="store_true",
+        help="""
+        Don't check llvm-project out to anything special before running. Useful
+        if you'd like to, for example, workon multiple LLVM projects
+        simultaneously and have already called `setup_for_workon` on another
+        one.
+        """,
+    )
     opts = parser.parse_args(argv)
 
     ebuild_dir = opts.ebuild_dir
@@ -199,7 +213,7 @@
             ["git", "reset", "--hard", "HEAD"],
         )
 
-    if opts.checkout:
+    if opts.checkout is not None:
         git_housekeeping_commands.append(
             ["git", "checkout", "--quiet", opts.checkout],
         )
diff --git a/llvm_tools/stabilize_all_llvm_packages.py b/llvm_tools/stabilize_all_llvm_packages.py
new file mode 100755
index 0000000..40ca29f
--- /dev/null
+++ b/llvm_tools/stabilize_all_llvm_packages.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python3
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Marks all LLVM packages as stable.
+
+This essentially performs the job of annealing: take whatever's in the 9999
+ebuilds, and put it in non-9999 ebuilds. The result is committed to
+chromiumos-overlay, unless there are no changes to make. If the stabilization
+does nothing, no new ebuilds will be created, and nothing will be committed.
+
+The results of this script should _not_ be uploaded. Annealing should be
+responsible for actually stabilizing our ebuilds upstream.
+
+Run this from inside of the chroot.
+"""
+
+import argparse
+import contextlib
+import logging
+from pathlib import Path
+import subprocess
+import sys
+from typing import List
+
+import chroot
+import get_upstream_patch
+import manifest_utils
+import patch_utils
+
+
+CROS_SOURCE_ROOT = Path("/mnt/host/source")
+
+
+@contextlib.contextmanager
+def llvm_checked_out_to(checkout_sha: str):
+    """Checks out LLVM to `checkout_sha`, if necessary.
+
+    Restores LLVM to the prior SHA when exited.
+    """
+    llvm_dir = CROS_SOURCE_ROOT / manifest_utils.LLVM_PROJECT_PATH
+    original_sha = subprocess.run(
+        ["git", "rev-parse", "HEAD"],
+        check=True,
+        cwd=llvm_dir,
+        stdout=subprocess.PIPE,
+        encoding="utf-8",
+    ).stdout.strip()
+    if checkout_sha == original_sha:
+        logging.info(
+            "LLVM is already checked out to %s; not checking out", checkout_sha
+        )
+        yield
+        return
+
+    return_code = subprocess.run(
+        ["git", "status", "--porcelain"],
+        check=False,
+        cwd=llvm_dir,
+    ).returncode
+    if return_code:
+        raise ValueError(
+            f"LLVM checkout at {llvm_dir} is unclean; refusing to modify"
+        )
+
+    logging.info("Checking %s out to SHA %s...", llvm_dir, checkout_sha)
+
+    subprocess.run(
+        ["git", "checkout", checkout_sha],
+        check=True,
+        cwd=llvm_dir,
+    )
+    try:
+        yield
+    finally:
+        logging.info("Restoring %s to original checkout...", llvm_dir)
+        return_code = subprocess.run(
+            ["git", "checkout", original_sha],
+            check=False,
+            cwd=llvm_dir,
+        ).returncode
+        if return_code:
+            logging.error(
+                "Failed checking llvm-project back out to %s :(",
+                original_sha,
+            )
+
+
+def resolve_llvm_sha(llvm_next: bool) -> str:
+    sys_devel_llvm = (
+        CROS_SOURCE_ROOT / "src/third_party/chromiumos-overlay/sys-devel/llvm"
+    )
+    sha = "llvm-next" if llvm_next else "llvm"
+    return get_upstream_patch.resolve_symbolic_sha(sha, str(sys_devel_llvm))
+
+
+def main(argv: List[str]) -> None:
+    chroot.VerifyInsideChroot()
+
+    logging.basicConfig(
+        format=">> %(asctime)s: %(levelname)s: %(filename)s:%(lineno)d: "
+        "%(message)s",
+        level=logging.INFO,
+    )
+
+    parser = argparse.ArgumentParser(
+        description=__doc__,
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+    )
+    parser.add_argument(
+        "--llvm-next",
+        action="store_true",
+        help="""
+        If passed, the ebuilds will be stabilized using the current llvm-next
+        hash.
+        """,
+    )
+    opts = parser.parse_args(argv)
+    desired_sha = resolve_llvm_sha(opts.llvm_next)
+
+    with llvm_checked_out_to(desired_sha):
+        packages_to_stabilize = patch_utils.CHROMEOS_PATCHES_JSON_PACKAGES
+        logging.info("Stabilizing %s...", ", ".join(packages_to_stabilize))
+
+        cros_overlay = CROS_SOURCE_ROOT / "src/third_party/chromiumos-overlay"
+        return_code = subprocess.run(
+            [
+                "cros_mark_as_stable",
+                f"--overlays={cros_overlay}",
+                "--packages=" + ":".join(packages_to_stabilize),
+                "commit",
+            ],
+            check=False,
+            stdin=subprocess.DEVNULL,
+        ).returncode
+        sys.exit(return_code)
+
+
+if __name__ == "__main__":
+    main(sys.argv[1:])
diff --git a/llvm_tools/subprocess_helpers.py b/llvm_tools/subprocess_helpers.py
index d0c619c..e1847c0 100644
--- a/llvm_tools/subprocess_helpers.py
+++ b/llvm_tools/subprocess_helpers.py
@@ -33,10 +33,21 @@
 
 # FIXME: CTRL+C does not work when executing a command inside the chroot via
 # `cros_sdk`.
-def ChrootRunCommand(chroot_path, cmd, verbose=False):
+def ChrootRunCommand(
+    chroot_path,
+    cmd,
+    verbose: bool = False,
+    chroot_name: str = "chroot",
+    out_name: str = "out",
+):
     """Runs the command inside the chroot."""
 
-    exec_chroot_cmd = ["cros_sdk", "--"]
+    exec_chroot_cmd = [
+        "cros_sdk",
+        f"--chroot={chroot_name}",
+        f"--out-dir={out_name}",
+        "--",
+    ]
     exec_chroot_cmd.extend(cmd)
 
     return ExecCommandAndCaptureOutput(
diff --git a/llvm_tools/test_helpers.py b/llvm_tools/test_helpers.py
index ea47a69..44d56f8 100644
--- a/llvm_tools/test_helpers.py
+++ b/llvm_tools/test_helpers.py
@@ -14,7 +14,7 @@
     """Testing class to simulate a argument parser object."""
 
     def __init__(self, svn_option="google3"):
-        self.chroot_path = "/abs/path/to/chroot"
+        self.chromeos_path = "/abs/path/to/chroot"
         self.last_tested = "/abs/path/to/last_tested_file.json"
         self.llvm_version = svn_option
         self.extra_change_lists = None
diff --git a/llvm_tools/update_chromeos_llvm_hash.py b/llvm_tools/update_chromeos_llvm_hash.py
index ea09af4..f616177 100755
--- a/llvm_tools/update_chromeos_llvm_hash.py
+++ b/llvm_tools/update_chromeos_llvm_hash.py
@@ -10,6 +10,7 @@
 """
 
 import argparse
+import dataclasses
 import enum
 import os
 from pathlib import Path
@@ -28,14 +29,8 @@
 import subprocess_helpers
 
 
-DEFAULT_PACKAGES = [
-    "dev-util/lldb-server",
-    "sys-devel/llvm",
-    "sys-libs/compiler-rt",
-    "sys-libs/libcxx",
-    "sys-libs/llvm-libunwind",
-    "sys-libs/scudo",
-]
+# Default list of packages to update.
+DEFAULT_PACKAGES = patch_utils.CHROMEOS_PATCHES_JSON_PACKAGES
 
 DEFAULT_MANIFEST_PACKAGES = ["sys-devel/llvm"]
 
@@ -48,19 +43,28 @@
     next = "LLVM_NEXT_HASH"
 
 
+@dataclasses.dataclass(frozen=True, eq=True)
+class ChrootOpts:
+    """A class that holds chroot options."""
+
+    chromeos_root: Path
+    chroot_name: str = "chroot"
+    out_name: str = "out"
+
+
 class PortagePackage:
     """Represents a portage package with location info."""
 
-    def __init__(self, chromeos_root: Path, package: str):
+    def __init__(self, chroot_opts: ChrootOpts, package: str):
         """Create a new PortagePackage.
 
         Args:
-            chromeos_root: Path to the root of the code checkout.
+            chroot_opts: options that specify the ChromeOS chroot to use.
             package: "category/package" string.
         """
         self.package = package
         potential_ebuild_path = PortagePackage.find_package_ebuild(
-            chromeos_root, package
+            chroot_opts, package
         )
         if potential_ebuild_path.is_symlink():
             self.uprev_target: Optional[Path] = potential_ebuild_path.absolute()
@@ -71,12 +75,14 @@
             self.ebuild_path = potential_ebuild_path.absolute()
 
     @staticmethod
-    def find_package_ebuild(chromeos_root: Path, package: str) -> Path:
+    def find_package_ebuild(chroot_opts: ChrootOpts, package: str) -> Path:
         """Look up the package's ebuild location."""
-        chromeos_root_str = str(chromeos_root)
+        chromeos_root_str = str(chroot_opts.chromeos_root)
         ebuild_paths = chroot.GetChrootEbuildPaths(
             chromeos_root_str,
             [package],
+            chroot_opts.chroot_name,
+            chroot_opts.out_name,
         )
         converted = chroot.ConvertChrootPathsToAbsolutePaths(
             chromeos_root_str, ebuild_paths
@@ -133,7 +139,7 @@
 
 
 def defaultCrosRoot() -> Path:
-    """Get default location of chroot_path.
+    """Get default location of chromeos_path.
 
     The logic assumes that the cros_root is ~/chromiumos, unless llvm_tools is
     inside of a CrOS checkout, in which case that checkout should be used.
@@ -164,7 +170,7 @@
 
     # Add argument for a specific chroot path.
     parser.add_argument(
-        "--chroot_path",
+        "--chromeos_path",
         type=Path,
         default=defaultCrosRoot(),
         help="the path to the chroot (default: %(default)s)",
@@ -211,7 +217,6 @@
             failure_modes.FailureModes.FAIL.value,
             failure_modes.FailureModes.CONTINUE.value,
             failure_modes.FailureModes.DISABLE_PATCHES.value,
-            failure_modes.FailureModes.REMOVE_PATCHES.value,
         ],
         help="the mode of the patch manager when handling failed patches "
         "(default: %(default)s)",
@@ -225,9 +230,10 @@
         "metadata if applicable (default: PATCHES.json inside $FILESDIR)",
     )
     parser.add_argument(
-        "--repo_manifest",
-        action="store_true",
-        help="Updates the llvm-project revision attribute"
+        "--no_repo_manifest",
+        dest="repo_manifest",
+        action="store_false",
+        help="Skip updating the llvm-project revision attribute"
         " in the internal manifest.",
     )
     parser.add_argument(
@@ -523,24 +529,26 @@
     return commit_messages
 
 
-def UpdatePortageManifests(packages: Iterable[str], chroot_path: Path) -> None:
+def UpdatePortageManifests(
+    packages: Iterable[str], chromeos_path: Path
+) -> None:
     """Updates portage manifest files for packages.
 
     Args:
         packages: A list of packages to update manifests for.
-        chroot_path: The absolute path to the chroot.
+        chromeos_path: The absolute path to the chromeos checkout.
 
     Raises:
         CalledProcessError: ebuild failed to update manifest.
     """
-    manifest_ebuilds = chroot.GetChrootEbuildPaths(chroot_path, packages)
+    manifest_ebuilds = chroot.GetChrootEbuildPaths(chromeos_path, packages)
     for ebuild_path in manifest_ebuilds:
         ebuild_dir = os.path.dirname(ebuild_path)
         subprocess_helpers.ChrootRunCommand(
-            chroot_path, ["ebuild", ebuild_path, "manifest"]
+            chromeos_path, ["ebuild", ebuild_path, "manifest"]
         )
         subprocess_helpers.ChrootRunCommand(
-            chroot_path, ["git", "-C", ebuild_dir, "add", "Manifest"]
+            chromeos_path, ["git", "-C", ebuild_dir, "add", "Manifest"]
         )
 
 
@@ -550,12 +558,13 @@
     llvm_variant: LLVMVariant,
     git_hash: str,
     svn_version: int,
-    chroot_path: Path,
+    chroot_opts: ChrootOpts,
     mode: Optional[failure_modes.FailureModes],
     git_hash_source: Union[int, str],
     extra_commit_msg_lines: Optional[Iterable[str]],
     delete_branch: bool = True,
     upload_changes: bool = True,
+    wip: bool = False,
 ) -> Optional[git.CommitContents]:
     """Updates an LLVM hash and uprevs the ebuild of the packages.
 
@@ -568,7 +577,7 @@
         llvm_variant: The LLVM hash to update.
         git_hash: The new git hash.
         svn_version: The SVN-style revision number of git_hash.
-        chroot_path: The absolute path to the chroot.
+        chroot_opts: options that specify the ChromeOS chroot to use.
         mode: The mode of the patch manager when handling an applicable patch.
           If None is passed, the patch manager won't be invoked.
         that failed to apply.
@@ -579,14 +588,15 @@
             Newlines are added automatically.
         delete_branch: Delete the git branch as a final step.
         upload_changes: Upload the commit to gerrit as a CL.
+        wip: if True, any changes uploaded will be uploaded as
+            work-in-progress.
 
     Returns:
         If upload_changes is set, a git.CommitContents object. Otherwise None.
     """
-
-    portage_packages = (PortagePackage(chroot_path, pkg) for pkg in packages)
+    portage_packages = (PortagePackage(chroot_opts, pkg) for pkg in packages)
     chromiumos_overlay_path = (
-        chroot_path / "src" / "third_party" / "chromiumos-overlay"
+        chroot_opts.chromeos_root / "src" / "third_party" / "chromiumos-overlay"
     )
     branch_name = "update-" + llvm_variant.value + "-" + git_hash
 
@@ -615,14 +625,14 @@
             updated_packages.append(pkg.package)
             commit_lines.append(pkg.package)
         if manifest_packages:
-            UpdatePortageManifests(manifest_packages, chroot_path)
+            UpdatePortageManifests(manifest_packages, chroot_opts.chromeos_root)
             commit_lines.append("Updated manifest for:")
             commit_lines.extend(manifest_packages)
-        EnsurePackageMaskContains(chroot_path, git_hash)
+        EnsurePackageMaskContains(chroot_opts.chromeos_root, git_hash)
         # Handle the patches for each package.
         if mode is not None:
             package_info_dict = UpdatePackagesPatchMetadataFile(
-                chroot_path, svn_version, updated_packages, mode
+                chroot_opts, svn_version, updated_packages, mode
             )
             # Update the commit message if changes were made to a package's
             # patches.
@@ -634,7 +644,9 @@
         git.CommitChanges(chromiumos_overlay_path, commit_lines)
         if upload_changes:
             change_list = git.UploadChanges(
-                chromiumos_overlay_path, branch_name
+                chromiumos_overlay_path,
+                branch_name,
+                wip=wip,
             )
     finally:
         if delete_branch:
@@ -645,12 +657,12 @@
 
 
 def EnsurePackageMaskContains(
-    chroot_path: Union[Path, str], git_hash: str
+    chromeos_path: Union[Path, str], git_hash: str
 ) -> None:
     """Adds the major version of llvm to package.mask if not already present.
 
     Args:
-        chroot_path: The absolute path to the chroot.
+        chromeos_path: The absolute path to the chromeos checkout.
         git_hash: The new git hash.
 
     Raises:
@@ -660,7 +672,7 @@
     llvm_major_version = get_llvm_hash.GetLLVMMajorVersion(git_hash)
 
     overlay_dir = os.path.join(
-        chroot_path, "src/third_party/chromiumos-overlay"
+        chromeos_path, "src/third_party/chromiumos-overlay"
     )
     mask_path = os.path.join(
         overlay_dir, "profiles/targets/chromeos/package.mask"
@@ -675,7 +687,7 @@
 
 
 def UpdatePackagesPatchMetadataFile(
-    chroot_path: Path,
+    chroot_opts: ChrootOpts,
     svn_version: int,
     packages: Iterable[str],
     mode: failure_modes.FailureModes,
@@ -683,7 +695,7 @@
     """Updates the packages metadata file.
 
     Args:
-        chroot_path: The absolute path to the chroot.
+        chroot_opts: options that specify the ChromeOS chroot to use.
         svn_version: The version to use for patch management.
         packages: All the packages to update their patch metadata file.
         mode: The mode for the patch manager to use when an applicable patch
@@ -712,7 +724,10 @@
             for cur_package in packages:
                 # Get the absolute path to $FILESDIR of the package.
                 chroot_ebuild_str = subprocess_helpers.ChrootRunCommand(
-                    chroot_path, ["equery", "w", cur_package]
+                    chroot_opts.chromeos_root,
+                    ["equery", "w", cur_package],
+                    chroot_name=chroot_opts.chroot_name,
+                    out_name=chroot_opts.out_name,
                 ).strip()
                 if not chroot_ebuild_str:
                     raise RuntimeError(
@@ -720,7 +735,7 @@
                     )
                 chroot_ebuild_path = Path(
                     chroot.ConvertChrootPathsToAbsolutePaths(
-                        str(chroot_path), [chroot_ebuild_str]
+                        str(chroot_opts.chromeos_root), [chroot_ebuild_str]
                     )[0]
                 )
                 patches_json_fp = (
@@ -744,10 +759,6 @@
                             continue_on_failure=mode
                             == failure_modes.FailureModes.CONTINUE,
                         )
-                    elif mode == failure_modes.FailureModes.REMOVE_PATCHES:
-                        patches_info = patch_utils.remove_old_patches(
-                            svn_version, src_path, patches_json_fp
-                        )
                     elif mode == failure_modes.FailureModes.DISABLE_PATCHES:
                         patches_info = patch_utils.update_version_ranges(
                             svn_version, src_path, patches_json_fp
@@ -835,7 +846,7 @@
 
     args_output = GetCommandLineArgs()
 
-    chroot.VerifyChromeOSRoot(args_output.chroot_path)
+    chroot.VerifyChromeOSRoot(args_output.chromeos_path)
 
     llvm_variant = LLVMVariant.current
     if args_output.is_llvm_next:
@@ -866,7 +877,7 @@
         llvm_variant=llvm_variant,
         git_hash=git_hash,
         svn_version=svn_version,
-        chroot_path=args_output.chroot_path,
+        chroot_opts=ChrootOpts(args_output.chromeos_path),
         mode=patch_update_mode,
         git_hash_source=git_hash_source,
         extra_commit_msg_lines=None,
@@ -880,7 +891,7 @@
     else:
         print("--no-upload passed, did not create a change list")
 
-    if args_output.repo_manifest:
+    if args_output.repo_manifest and not args_output.is_llvm_next:
         print(
             f"Updating internal manifest to {git_hash} ({svn_version})...",
             end="",
@@ -892,7 +903,7 @@
         )
         change_list = ChangeRepoManifest(
             git_hash,
-            args_output.chroot_path,
+            args_output.chromeos_path,
             extra_commit_msg_lines=cq_depend_line,
             delete_branch=not args_output.no_delete_branch,
             upload_changes=not args_output.no_upload_changes,
diff --git a/llvm_tools/update_chromeos_llvm_hash_unittest.py b/llvm_tools/update_chromeos_llvm_hash_unittest.py
index ad0bca7..bab1ebb 100755
--- a/llvm_tools/update_chromeos_llvm_hash_unittest.py
+++ b/llvm_tools/update_chromeos_llvm_hash_unittest.py
@@ -249,7 +249,7 @@
     def testFailedToUprevEbuildToVersionForInvalidSymlink(
         self, mock_islink, mock_llvm_version
     ):
-        symlink_path = "/path/to/chroot/package/package.ebuild"
+        symlink_path = "/path/to/chromeos/package/package.ebuild"
         svn_version = 1000
         git_hash = "badf00d"
         mock_llvm_version.return_value = "1234"
@@ -270,7 +270,7 @@
 
     @mock.patch.object(os.path, "islink", return_value=False)
     def testFailedToUprevEbuildSymlinkForInvalidSymlink(self, mock_islink):
-        symlink_path = "/path/to/chroot/package/package.ebuild"
+        symlink_path = "/path/to/chromeos/package/package.ebuild"
 
         # Verify the exception is raised when a invalid symbolic link is
         # passed in.
@@ -291,7 +291,7 @@
     def testFailedToUprevEbuildToVersion(
         self, mock_realpath, mock_islink, mock_llvm_version
     ):
-        symlink_path = "/path/to/chroot/llvm/llvm_pre123_p.ebuild"
+        symlink_path = "/path/to/chromeos/llvm/llvm_pre123_p.ebuild"
         mock_realpath.return_value = "/abs/path/to/llvm/llvm_pre123_p.ebuild"
         git_hash = "badf00d"
         mock_llvm_version.return_value = "1234"
@@ -312,7 +312,7 @@
     # Simulate 'os.path.islink' when a symbolic link is passed in.
     @mock.patch.object(os.path, "islink", return_value=True)
     def testFailedToUprevEbuildSymlink(self, mock_islink):
-        symlink_path = "/path/to/chroot/llvm/llvm_pre123_p.ebuild"
+        symlink_path = "/path/to/chromeos/llvm/llvm_pre123_p.ebuild"
 
         # Verify the exception is raised when the symlink does not match the
         # expected pattern
@@ -386,15 +386,17 @@
     @mock.patch.object(subprocess, "check_output", return_value="")
     def testManifestUpdate(self, mock_subprocess, mock_ebuild_paths):
         manifest_packages = ["sys-devel/llvm"]
-        chroot_path = "/path/to/chroot"
+        chromeos_path = "/path/to/chromeos"
         update_chromeos_llvm_hash.UpdatePortageManifests(
-            manifest_packages, Path(chroot_path)
+            manifest_packages, Path(chromeos_path)
         )
 
         args = mock_subprocess.call_args_list[0]
         manifest_cmd = (
             [
                 "cros_sdk",
+                "--chroot=chroot",
+                "--out-dir=out",
                 "--",
                 "ebuild",
                 "/chroot/path/test.ebuild",
@@ -407,6 +409,8 @@
         git_add_cmd = (
             [
                 "cros_sdk",
+                "--chroot=chroot",
+                "--out-dir=out",
                 "--",
                 "git",
                 "-C",
@@ -722,6 +726,7 @@
         mock_gethash.return_value = (git_hash, svn_version)
         argv = [
             "./update_chromeos_llvm_hash_unittest.py",
+            "--no_repo_manifest",
             "--llvm_version",
             "google3",
         ]
@@ -741,7 +746,7 @@
             llvm_variant=expected_llvm_variant,
             git_hash=git_hash,
             svn_version=svn_version,
-            chroot_path=expected_chroot,
+            chroot_opts=update_chromeos_llvm_hash.ChrootOpts(expected_chroot),
             mode=failure_modes.FailureModes.FAIL,
             git_hash_source="google3",
             extra_commit_msg_lines=None,
@@ -785,7 +790,7 @@
             llvm_variant=expected_llvm_variant,
             git_hash=git_hash,
             svn_version=svn_version,
-            chroot_path=expected_chroot,
+            chroot_opts=update_chromeos_llvm_hash.ChrootOpts(expected_chroot),
             mode=failure_modes.FailureModes.FAIL,
             git_hash_source="google3",
             extra_commit_msg_lines=None,
@@ -808,8 +813,8 @@
     ):
         packages_to_update = "test-packages/package1,test-libs/lib1"
         manifest_packages = "test-libs/lib1,test-libs/lib2"
-        failure_mode = failure_modes.FailureModes.REMOVE_PATCHES
-        chroot_path = Path("/some/path/to/chroot")
+        failure_mode = failure_modes.FailureModes.DISABLE_PATCHES
+        chromeos_path = Path("/some/path/to/chromeos")
         llvm_ver = 435698
         git_hash = "1234abcd"
         svn_version = 5678
@@ -820,8 +825,8 @@
             "--llvm_version",
             str(llvm_ver),
             "--is_llvm_next",
-            "--chroot_path",
-            str(chroot_path),
+            "--chromeos_path",
+            str(chromeos_path),
             "--update_packages",
             packages_to_update,
             "--manifest_packages",
@@ -830,6 +835,7 @@
             failure_mode.value,
             "--patch_metadata_file",
             "META.json",
+            "--no_repo_manifest",
         ]
 
         with mock.patch.object(sys, "argv", argv) as mock.argv:
@@ -844,7 +850,7 @@
             llvm_variant=expected_llvm_variant,
             git_hash=git_hash,
             svn_version=svn_version,
-            chroot_path=chroot_path,
+            chroot_opts=update_chromeos_llvm_hash.ChrootOpts(chromeos_path),
             mode=failure_mode,
             git_hash_source=llvm_ver,
             extra_commit_msg_lines=None,
@@ -859,7 +865,7 @@
     def testEnsurePackageMaskContainsExisting(
         self, mock_llvm_version, mock_git_add
     ):
-        chroot_path = "absolute/path/to/chroot"
+        chromeos_path = "absolute/path/to/chromeos"
         git_hash = "badf00d"
         mock_llvm_version.return_value = "1234"
         with mock.patch(
@@ -868,14 +874,14 @@
             create=True,
         ) as mock_file:
             update_chromeos_llvm_hash.EnsurePackageMaskContains(
-                chroot_path, git_hash
+                chromeos_path, git_hash
             )
             handle = mock_file()
             handle.write.assert_not_called()
         mock_llvm_version.assert_called_once_with(git_hash)
 
         overlay_dir = (
-            "absolute/path/to/chroot/src/third_party/chromiumos-overlay"
+            "absolute/path/to/chromeos/src/third_party/chromiumos-overlay"
         )
         mask_path = overlay_dir + "/profiles/targets/chromeos/package.mask"
         mock_git_add.assert_called_once_with(
@@ -887,7 +893,7 @@
     def testEnsurePackageMaskContainsNotExisting(
         self, mock_llvm_version, mock_git_add
     ):
-        chroot_path = "absolute/path/to/chroot"
+        chromeos_path = "absolute/path/to/chromeos"
         git_hash = "badf00d"
         mock_llvm_version.return_value = "1234"
         with mock.patch(
@@ -896,7 +902,7 @@
             create=True,
         ) as mock_file:
             update_chromeos_llvm_hash.EnsurePackageMaskContains(
-                chroot_path, git_hash
+                chromeos_path, git_hash
             )
             handle = mock_file()
             handle.write.assert_called_once_with(
@@ -905,7 +911,7 @@
         mock_llvm_version.assert_called_once_with(git_hash)
 
         overlay_dir = (
-            "absolute/path/to/chroot/src/third_party/chromiumos-overlay"
+            "absolute/path/to/chromeos/src/third_party/chromiumos-overlay"
         )
         mask_path = overlay_dir + "/profiles/targets/chromeos/package.mask"
         mock_git_add.assert_called_once_with(
diff --git a/llvm_tools/update_packages_and_run_tests.py b/llvm_tools/update_packages_and_run_tests.py
index b0655fe..3483763 100755
--- a/llvm_tools/update_packages_and_run_tests.py
+++ b/llvm_tools/update_packages_and_run_tests.py
@@ -54,9 +54,28 @@
 
     # Add argument for a specific chroot path.
     parser.add_argument(
-        "--chroot_path",
+        "--chromeos_path",
         default=cros_root,
-        help="the path to the chroot (default: %(default)s)",
+        help="the path to the ChromeOS tree (default: %(default)s)",
+    )
+
+    # Add argument for a specific chroot path.
+    parser.add_argument(
+        "--chroot_name",
+        default="chroot",
+        help="""
+        the name of the chroot to use in the CrOS checkout. Defaults to
+        'chroot'.
+        """,
+    )
+
+    parser.add_argument(
+        "--chroot_out",
+        help="""
+        the name of the chroot to use in the CrOS checkout. Defaults to
+        'out' if the chroot's name is 'chroot'; otherwise, defaults to
+        '${chroot_name}_out'.
+        """,
     )
 
     # Add argument to choose between llvm and llvm-next.
@@ -153,6 +172,14 @@
     if args_output.subparser_name not in subparser_names:
         parser.error("one of %s must be specified" % subparser_names)
 
+    if not args_output.chroot_out:
+        chroot_name = args_output.chroot_name
+        if chroot_name == "chroot":
+            out = "out"
+        else:
+            out = f"{chroot_name}_out"
+        args_output.chroot_out = out
+
     return args_output
 
 
@@ -190,17 +217,17 @@
 def AddReviewers(
     cl: int,
     reviewers: Iterable[str],
-    chroot_path: Union[Path, str],
+    chromeos_path: Union[Path, str],
 ) -> None:
     """Add reviewers for the created CL.
 
     Args:
         cl: The CL number to add reviewers to.
         reviewers: Email addresses of reviewers to add.
-        chroot_path: The absolute path to the chroot.
+        chromeos_path: The absolute path to the chromeos tree.
     """
 
-    gerrit_abs_path = os.path.join(chroot_path, "chromite/bin/gerrit")
+    gerrit_abs_path = os.path.join(chromeos_path, "chromite/bin/gerrit")
     for reviewer in reviewers:
         cmd = [gerrit_abs_path, "reviewers", str(cl), reviewer]
 
@@ -210,14 +237,14 @@
 def AddLinksToCL(
     tests: Iterable[Dict[str, Any]],
     cl: int,
-    chroot_path: Union[Path, str],
+    chromeos_path: Union[Path, str],
 ) -> None:
     """Adds the test link(s) to the CL as a comment.
 
     Args:
         tests: Links to the tests.
         cl: The number of the CL to add the test links to.
-        chroot_path: Absolute path to the chroot.
+        chromeos_path: Absolute path to the chromeos tree.
     """
 
     # NOTE: Invoking `cros_sdk` does not make each tryjob link appear on its
@@ -226,7 +253,7 @@
     #
     # FIXME: Need to figure out why `cros_sdk` does not add each tryjob link as
     # a newline.
-    gerrit_abs_path = os.path.join(chroot_path, "chromite/bin/gerrit")
+    gerrit_abs_path = os.path.join(chromeos_path, "chromite/bin/gerrit")
 
     links = ["Started the following tests:"]
     links.extend(test["link"] for test in tests)
@@ -281,7 +308,7 @@
     extra_change_lists: List[int],
     options: List[str],
     builders: Iterable[str],
-    chroot_path: Union[Path, str],
+    chromeos_path: Union[Path, str],
 ) -> List[Dict]:
     """Runs a tryjob/tryjobs.
 
@@ -291,7 +318,7 @@
           CL that was created by updating the packages ('cl_number').
         options: Any options to be passed into the 'tryjob' command.
         builders: All the builders to run the 'tryjob' with.
-        chroot_path: The absolute path to the chroot.
+        chromeos_path: The absolute path to the chromeos tree.
 
     Returns:
         A list that contains stdout contents of each tryjob, where stdout is
@@ -311,7 +338,7 @@
     for builder in builders:
         cmd = GetTryJobCommand(cl_number, extra_change_lists, options, builder)
 
-        out = subprocess.check_output(cmd, cwd=chroot_path, encoding="utf-8")
+        out = subprocess.check_output(cmd, cwd=chromeos_path, encoding="utf-8")
 
         test_output = json.loads(out)
 
@@ -328,7 +355,7 @@
             }
         )
 
-    AddLinksToCL(tests, cl_number, chroot_path)
+    AddLinksToCL(tests, cl_number, chromeos_path)
 
     return tests
 
@@ -338,7 +365,7 @@
     extra_change_lists: List[int],
     options: List[str],
     builders: List[str],
-    chroot_path: Union[Path, str],
+    chromeos_path: Union[Path, str],
 ) -> List[Dict]:
     """Launch recipe builders.
 
@@ -348,7 +375,7 @@
           CL that was created by updating the packages ('cl_number').
         options: Any options to be passed into the 'tryjob' command.
         builders: All the builders to run the 'tryjob' with.
-        chroot_path: The absolute path to the chroot.
+        chromeos_path: The absolute path to the chromeos tree.
 
     Returns:
         A list that contains stdout contents of each builder, where stdout is
@@ -380,7 +407,7 @@
 
         cmd.append(builder)
 
-        out = subprocess.check_output(cmd, cwd=chroot_path, encoding="utf-8")
+        out = subprocess.check_output(cmd, cwd=chromeos_path, encoding="utf-8")
 
         test_output = json.loads(out)
 
@@ -395,7 +422,7 @@
             }
         )
 
-    AddLinksToCL(tests, cl_number, chroot_path)
+    AddLinksToCL(tests, cl_number, chromeos_path)
 
     return tests
 
@@ -428,11 +455,11 @@
 def StartCQDryRun(
     cl: int,
     dependent_cls: List[int],
-    chroot_path: Union[Path, str],
+    chromeos_path: Union[Path, str],
 ) -> None:
     """Start CQ dry run for the changelist and dependencies."""
 
-    gerrit_abs_path = os.path.join(chroot_path, "chromite/bin/gerrit")
+    gerrit_abs_path = os.path.join(chromeos_path, "chromite/bin/gerrit")
 
     cl_list = [cl]
     cl_list.extend(dependent_cls)
@@ -454,7 +481,7 @@
 
     args_output = GetCommandLineArgs()
 
-    chroot.VerifyChromeOSRoot(args_output.chroot_path)
+    chroot.VerifyChromeOSRoot(args_output.chromeos_path)
 
     svn_option = args_output.llvm_version
 
@@ -469,7 +496,10 @@
     # arguments last time --last_tested is used.
     if args_output.last_tested:
         chroot_file_paths = chroot.GetChrootEbuildPaths(
-            args_output.chroot_path, update_chromeos_llvm_hash.DEFAULT_PACKAGES
+            args_output.chromeos_path,
+            update_chromeos_llvm_hash.DEFAULT_PACKAGES,
+            args_output.chroot_name,
+            args_output.chroot_out,
         )
         arg_dict = {
             "svn_version": svn_version,
@@ -512,14 +542,21 @@
         llvm_variant=llvm_variant,
         git_hash=git_hash,
         svn_version=svn_version,
-        chroot_path=Path(args_output.chroot_path),
+        chroot_opts=update_chromeos_llvm_hash.ChrootOpts(
+            chromeos_root=Path(args_output.chromeos_path),
+            chroot_name=args_output.chroot_name,
+            out_name=args_output.chroot_out,
+        ),
         mode=failure_modes.FailureModes.DISABLE_PATCHES,
         git_hash_source=svn_option,
         extra_commit_msg_lines=extra_commit_msg_lines,
+        # b/331607705: set WIP on these changes, so the code-review-nudger bot
+        # doesn't ping them.
+        wip=True,
     )
 
     AddReviewers(
-        change_list.cl_number, args_output.reviewers, args_output.chroot_path
+        change_list.cl_number, args_output.reviewers, args_output.chromeos_path
     )
 
     print("Successfully updated packages to %d" % svn_version)
@@ -532,7 +569,7 @@
             args_output.extra_change_lists,
             args_output.options,
             args_output.builders,
-            args_output.chroot_path,
+            args_output.chromeos_path,
         )
         print("Tests:")
         for test in tests:
@@ -543,7 +580,7 @@
             args_output.extra_change_lists,
             args_output.options,
             args_output.builders,
-            args_output.chroot_path,
+            args_output.chromeos_path,
         )
         print("Tests:")
         for test in tests:
@@ -553,7 +590,7 @@
         StartCQDryRun(
             change_list.cl_number,
             args_output.extra_change_lists,
-            args_output.chroot_path,
+            args_output.chromeos_path,
         )
 
     # If --last_tested is specified, record the arguments used
diff --git a/llvm_tools/update_packages_and_run_tests_unittest.py b/llvm_tools/update_packages_and_run_tests_unittest.py
index 76482c4..9abdc19 100755
--- a/llvm_tools/update_packages_and_run_tests_unittest.py
+++ b/llvm_tools/update_packages_and_run_tests_unittest.py
@@ -152,14 +152,14 @@
 
         mock_cmd.return_value = json.dumps([{"id": bb_id, "url": url}])
 
-        chroot_path = "/some/path/to/chroot"
+        chromeos_path = "/some/path/to/chromeos"
         cl = 900
         extra_cls = [1200]
         options = ["some_option"]
         builders = ["builder1"]
 
         tests = update_packages_and_run_tests.RunTryJobs(
-            cl, extra_cls, options, builders, chroot_path
+            cl, extra_cls, options, builders, chromeos_path
         )
 
         expected_tests = [
@@ -176,7 +176,7 @@
         self.assertEqual(tests, expected_tests)
 
         mock_cmd.assert_called_once_with(
-            expected_cmd, cwd=chroot_path, encoding="utf-8"
+            expected_cmd, cwd=chromeos_path, encoding="utf-8"
         )
 
         mock_add_links_to_cl.assert_called_once()
@@ -205,14 +205,14 @@
             {"id": bb_id, "createTime": create_time}
         )
 
-        chroot_path = "/some/path/to/chroot"
+        chromeos_path = "/some/path/to/chromeos"
         cl = 900
         extra_cls = [1200]
         options = ["some_option"]
         builders = ["builder1"]
 
         tests = update_packages_and_run_tests.StartRecipeBuilders(
-            cl, extra_cls, options, builders, chroot_path
+            cl, extra_cls, options, builders, chromeos_path
         )
 
         expected_tests = [
@@ -229,25 +229,25 @@
         self.assertEqual(tests, expected_tests)
 
         mock_cmd.assert_called_once_with(
-            expected_cmd, cwd=chroot_path, encoding="utf-8"
+            expected_cmd, cwd=chromeos_path, encoding="utf-8"
         )
 
         mock_add_links_to_cl.assert_called_once()
 
     @mock.patch.object(subprocess, "check_output", return_value=None)
     def testSuccessfullyAddedTestLinkToCL(self, mock_exec_cmd):
-        chroot_path = "/abs/path/to/chroot"
+        chromeos_path = "/abs/path/to/chromeos"
 
         test_cl_number = 1000
 
         tests = [{"link": "https://some_tryjob_link.com"}]
 
         update_packages_and_run_tests.AddLinksToCL(
-            tests, test_cl_number, chroot_path
+            tests, test_cl_number, chromeos_path
         )
 
         expected_gerrit_message = [
-            "%s/chromite/bin/gerrit" % chroot_path,
+            "%s/chromite/bin/gerrit" % chromeos_path,
             "message",
             str(test_cl_number),
             "Started the following tests:\n%s" % tests[0]["link"],
@@ -299,6 +299,8 @@
 
             # Call with a changed LLVM svn version
             args_output = test_helpers.ArgsOutputTest()
+            args_output.chroot_name = "custom-chroot"
+            args_output.chroot_out = "custom-chroot_out"
             args_output.is_llvm_next = True
             args_output.extra_change_lists = extra_cls
             args_output.last_tested = last_tested_file
@@ -403,17 +405,17 @@
 
     @mock.patch.object(subprocess, "check_output", return_value=None)
     def testStartCQDryRunNoDeps(self, mock_exec_cmd):
-        chroot_path = "/abs/path/to/chroot"
+        chromeos_path = "/abs/path/to/chromeos"
         test_cl_number = 1000
 
         # test with no deps cls.
         extra_cls = []
         update_packages_and_run_tests.StartCQDryRun(
-            test_cl_number, extra_cls, chroot_path
+            test_cl_number, extra_cls, chromeos_path
         )
 
         expected_gerrit_message = [
-            "%s/chromite/bin/gerrit" % chroot_path,
+            "%s/chromite/bin/gerrit" % chromeos_path,
             "label-cq",
             str(test_cl_number),
             "1",
@@ -425,22 +427,22 @@
     @mock.patch.object(subprocess, "check_output", return_value=None)
     # test with a single deps cl.
     def testStartCQDryRunSingleDep(self, mock_exec_cmd):
-        chroot_path = "/abs/path/to/chroot"
+        chromeos_path = "/abs/path/to/chromeos"
         test_cl_number = 1000
 
         extra_cls = [2000]
         update_packages_and_run_tests.StartCQDryRun(
-            test_cl_number, extra_cls, chroot_path
+            test_cl_number, extra_cls, chromeos_path
         )
 
         expected_gerrit_cmd_1 = [
-            "%s/chromite/bin/gerrit" % chroot_path,
+            "%s/chromite/bin/gerrit" % chromeos_path,
             "label-cq",
             str(test_cl_number),
             "1",
         ]
         expected_gerrit_cmd_2 = [
-            "%s/chromite/bin/gerrit" % chroot_path,
+            "%s/chromite/bin/gerrit" % chromeos_path,
             "label-cq",
             str(2000),
             "1",
@@ -457,29 +459,29 @@
     # Mock ExecCommandAndCaptureOutput for the gerrit command execution.
     @mock.patch.object(subprocess, "check_output", return_value=None)
     def testStartCQDryRunMultipleDep(self, mock_exec_cmd):
-        chroot_path = "/abs/path/to/chroot"
+        chromeos_path = "/abs/path/to/chromeos"
         test_cl_number = 1000
 
         # test with multiple deps cls.
         extra_cls = [3000, 4000]
         update_packages_and_run_tests.StartCQDryRun(
-            test_cl_number, extra_cls, chroot_path
+            test_cl_number, extra_cls, chromeos_path
         )
 
         expected_gerrit_cmd_1 = [
-            "%s/chromite/bin/gerrit" % chroot_path,
+            "%s/chromite/bin/gerrit" % chromeos_path,
             "label-cq",
             str(test_cl_number),
             "1",
         ]
         expected_gerrit_cmd_2 = [
-            "%s/chromite/bin/gerrit" % chroot_path,
+            "%s/chromite/bin/gerrit" % chromeos_path,
             "label-cq",
             str(3000),
             "1",
         ]
         expected_gerrit_cmd_3 = [
-            "%s/chromite/bin/gerrit" % chroot_path,
+            "%s/chromite/bin/gerrit" % chromeos_path,
             "label-cq",
             str(4000),
             "1",
@@ -500,12 +502,12 @@
     @mock.patch.object(subprocess, "check_output", return_value=None)
     # test with no reviewers.
     def testAddReviewersNone(self, mock_exec_cmd):
-        chroot_path = "/abs/path/to/chroot"
+        chromeos_path = "/abs/path/to/chromeos"
         reviewers = []
         test_cl_number = 1000
 
         update_packages_and_run_tests.AddReviewers(
-            test_cl_number, reviewers, chroot_path
+            test_cl_number, reviewers, chromeos_path
         )
         self.assertTrue(mock_exec_cmd.not_called)
 
@@ -513,22 +515,22 @@
     @mock.patch.object(subprocess, "check_output", return_value=None)
     # test with multiple reviewers.
     def testAddReviewersMultiple(self, mock_exec_cmd):
-        chroot_path = "/abs/path/to/chroot"
+        chromeos_path = "/abs/path/to/chromeos"
         reviewers = ["none1@chromium.org", "none2@chromium.org"]
         test_cl_number = 1000
 
         update_packages_and_run_tests.AddReviewers(
-            test_cl_number, reviewers, chroot_path
+            test_cl_number, reviewers, chromeos_path
         )
 
         expected_gerrit_cmd_1 = [
-            "%s/chromite/bin/gerrit" % chroot_path,
+            "%s/chromite/bin/gerrit" % chromeos_path,
             "reviewers",
             str(test_cl_number),
             "none1@chromium.org",
         ]
         expected_gerrit_cmd_2 = [
-            "%s/chromite/bin/gerrit" % chroot_path,
+            "%s/chromite/bin/gerrit" % chromeos_path,
             "reviewers",
             str(test_cl_number),
             "none2@chromium.org",
diff --git a/pgo_tools/benchmark_pgo_profiles.py b/pgo_tools/benchmark_pgo_profiles.py
index d6fb494..121fb77 100755
--- a/pgo_tools/benchmark_pgo_profiles.py
+++ b/pgo_tools/benchmark_pgo_profiles.py
@@ -118,8 +118,8 @@
     else:
         raise ValueError(f"Unknown profile type: {type(profile)}")
 
-    quickpkg_restore = " ".join(
-        shlex.quote(str(x))
+    quickpkg_restore = shlex.join(
+        str(x)
         for x in pgo_tools.generate_quickpkg_restoration_command(llvm_binpkg)
     )
 
@@ -231,7 +231,7 @@
             logging.info(
                 "Profile %r: Running %s",
                 str(profile),
-                " ".join(shlex.quote(str(x)) for x in cmd),
+                shlex.join(str(x) for x in cmd),
             )
             pgo_tools.run(cmd)
 
diff --git a/pgo_tools/create_chroot_and_generate_pgo_profile.py b/pgo_tools/create_chroot_and_generate_pgo_profile.py
index b9e4c62..c09cb4d 100755
--- a/pgo_tools/create_chroot_and_generate_pgo_profile.py
+++ b/pgo_tools/create_chroot_and_generate_pgo_profile.py
@@ -231,9 +231,7 @@
         if opts.upload:
             pgo_tools.run(upload_command)
         else:
-            friendly_upload_command = " ".join(
-                shlex.quote(str(x)) for x in upload_command
-            )
+            friendly_upload_command = shlex.join(str(x) for x in upload_command)
             logging.info(
                 "To upload the profile, run %r in %r",
                 friendly_upload_command,
diff --git a/pgo_tools/pgo_tools.py b/pgo_tools/pgo_tools.py
index 577fa37..2702d60 100644
--- a/pgo_tools/pgo_tools.py
+++ b/pgo_tools/pgo_tools.py
@@ -35,7 +35,7 @@
         env = None
 
     if logging.getLogger().isEnabledFor(logging.DEBUG):
-        c = " ".join(shlex.quote(str(x)) for x in command)
+        c = shlex.join(str(x) for x in command)
         dir_extra = f" in {cwd}" if cwd is not None else ""
         logging.debug("Running `%s`%s", c, dir_extra)
 
diff --git a/pgo_tools_rust/pgo_rust.py b/pgo_tools_rust/pgo_rust.py
index ecf4f05..7d9e4f7 100755
--- a/pgo_tools_rust/pgo_rust.py
+++ b/pgo_tools_rust/pgo_rust.py
@@ -1,10 +1,10 @@
 #!/usr/bin/env python3
-#
 # Copyright 2022 The ChromiumOS Authors
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
 # pylint: disable=line-too-long
+
 """Handle most aspects of creating and benchmarking PGO profiles for Rust.
 
 This is meant to be done at Rust uprev time. Ultimately profdata files need
@@ -278,7 +278,6 @@
     use_frontend_profile: bool = False,
     use_llvm_profile: bool = False,
 ):
-
     if use_frontend_profile or use_llvm_profile:
         assert not generate_frontend_profile and not generate_llvm_profile, (
             "Can't build a compiler to both use profile information "
@@ -301,15 +300,20 @@
 
     env_use = os.getenv("USE", "").rstrip()
     use = (env_use + " " + use).strip()
+    rust_cross_packages = [
+        f"cross-{x}/rust" for x in TARGET_TRIPLES if "-pc-linux-" not in x
+    ]
+
     # -E to preserve environment variables like USE, FEATURES, etc.
     run(
         [
             "sudo",
             "-E",
             "emerge",
+            "-j",
             "dev-lang/rust-host",
-            "dev-lang/rust",
-        ],
+        ]
+        + rust_cross_packages,
         env={"USE": use},
     )
 
diff --git a/rust-analyzer-chromiumos-wrapper/Cargo.lock b/rust-analyzer-chromiumos-wrapper/Cargo.lock
index 248b313..a3b4096 100644
--- a/rust-analyzer-chromiumos-wrapper/Cargo.lock
+++ b/rust-analyzer-chromiumos-wrapper/Cargo.lock
@@ -3,15 +3,6 @@
 version = 3
 
 [[package]]
-name = "aho-corasick"
-version = "1.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
-dependencies = [
- "memchr",
-]
-
-[[package]]
 name = "anyhow"
 version = "1.0.57"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -24,18 +15,31 @@
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
+name = "form_urlencoded"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "idna"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
 name = "itoa"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
 
 [[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
-[[package]]
 name = "libc"
 version = "0.2.126"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -51,12 +55,6 @@
 ]
 
 [[package]]
-name = "memchr"
-version = "2.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
-
-[[package]]
 name = "num_threads"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -66,44 +64,20 @@
 ]
 
 [[package]]
-name = "regex"
-version = "1.10.2"
+name = "percent-encoding"
+version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-automata",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
 
 [[package]]
 name = "rust-analyzer-chromiumos-wrapper"
 version = "0.1.0"
 dependencies = [
  "anyhow",
- "lazy_static",
  "log",
- "regex",
  "serde_json",
  "simplelog",
+ "url",
 ]
 
 [[package]]
@@ -168,6 +142,47 @@
 checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
 
 [[package]]
+name = "tinyvec"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "url"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+]
+
+[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/rust-analyzer-chromiumos-wrapper/Cargo.toml b/rust-analyzer-chromiumos-wrapper/Cargo.toml
index a6deac2..9fcc002 100644
--- a/rust-analyzer-chromiumos-wrapper/Cargo.toml
+++ b/rust-analyzer-chromiumos-wrapper/Cargo.toml
@@ -8,11 +8,10 @@
 
 [dependencies]
 anyhow = "1.0"
-lazy_static = "1.4"
 log = { version = "0.4.17" }
-regex = "1.0"
 serde_json = "1.0"
 simplelog = { version = "0.12.0" }
+url = "2.5.0"
 
 [features]
 default = ["no_debug_log"]
diff --git a/rust-analyzer-chromiumos-wrapper/src/main.rs b/rust-analyzer-chromiumos-wrapper/src/main.rs
index 43ca5a3..b55623b 100644
--- a/rust-analyzer-chromiumos-wrapper/src/main.rs
+++ b/rust-analyzer-chromiumos-wrapper/src/main.rs
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use std::collections::HashMap;
 use std::env;
+use std::ffi::OsStr;
 use std::fs::File;
 use std::io::{self, BufRead, BufReader, BufWriter, Write};
 use std::os::unix::process::CommandExt;
@@ -13,16 +13,15 @@
 use std::thread;
 
 use anyhow::{anyhow, bail, Context, Result};
-use lazy_static::lazy_static;
-use log::trace;
-
-use regex::Regex;
+use log::{trace, warn};
 
 use simplelog::{Config, LevelFilter, WriteLogger};
 
 use serde_json::{from_slice, to_writer, Value};
+use url::Url;
 
-const CHROOT_SERVER_PATH: &str = "/usr/sbin/rust-analyzer";
+const SERVER_FILENAME: &str = "rust-analyzer-chromiumos-wrapper";
+const CHROOT_SERVER_PATH: &str = "/usr/bin/rust-analyzer";
 
 fn main() -> Result<()> {
     let args = env::args().skip(1);
@@ -122,16 +121,14 @@
     let mut child_stdin = BufWriter::new(child.0.stdin.take().unwrap());
     let mut child_stdout = BufReader::new(child.0.stdout.take().unwrap());
 
-    let replacement_map = {
-        let mut m = HashMap::new();
-        m.insert(outside_prefix, inside_prefix);
-        m.insert(outside_sysroot_prefix, "/usr/lib/rustlib");
-        m.insert(outside_home, "/home");
-        m
-    };
+    let replacement_map = [
+        (outside_prefix, inside_prefix),
+        (outside_sysroot_prefix, "/usr/lib/rustlib"),
+        (outside_home, "/home"),
+    ];
 
     let join_handle = {
-        let rm = replacement_map.clone();
+        let rm = replacement_map;
         thread::spawn(move || {
             let mut stdin = io::stdin().lock();
             stream_with_replacement(&mut stdin, &mut child_stdin, &rm)
@@ -140,7 +137,7 @@
     };
 
     // For the mapping between inside to outside, we just reverse the map.
-    let replacement_map_rev = replacement_map.iter().map(|(k, v)| (*v, *k)).collect();
+    let replacement_map_rev = replacement_map.map(|(k, v)| (v, k));
     let mut stdout = BufWriter::new(io::stdout().lock());
     stream_with_replacement(&mut child_stdout, &mut stdout, &replacement_map_rev)
         .context("Streaming from rust-analyzer into stdout")?;
@@ -207,32 +204,82 @@
     }
 }
 
+// The url crate's percent decoding helper returns a Path, while for non-url strings we don't
+// want to decode all of them as a Path since most of them are non-path strings.
+// We opt for not sharing the code paths as the handling of plain strings and Paths are slightly
+// different (notably that Path normalizes away trailing slashes), but otherwise the two functions
+// are functionally equal.
+fn replace_uri(s: &str, replacement_map: &[(&str, &str)]) -> Result<String> {
+    let uri = Url::parse(s).with_context(|| format!("while parsing path {s:?}"))?;
+    let is_dir = uri.as_str().ends_with('/');
+    let path = uri
+        .to_file_path()
+        .map_err(|()| anyhow!("while converting {s:?} to file path"))?;
+
+    // Always replace the server path everywhere.
+    if path.file_name() == Some(OsStr::new(SERVER_FILENAME)) {
+        return Ok(CHROOT_SERVER_PATH.into());
+    }
+
+    fn path_to_url(path: &Path, is_dir: bool) -> Result<String> {
+        let url = if is_dir {
+            Url::from_directory_path(path)
+        } else {
+            Url::from_file_path(path)
+        };
+        url.map_err(|()| anyhow!("while converting {path:?} to url"))
+            .map(|p| p.into())
+    }
+
+    // Replace by the first prefix match.
+    for (pattern, replacement) in replacement_map {
+        if let Ok(rest) = path.strip_prefix(pattern) {
+            let new_path = Path::new(replacement).join(rest);
+            return path_to_url(&new_path, is_dir);
+        }
+    }
+
+    Ok(s.into())
+}
+
+fn replace_path(s: &str, replacement_map: &[(&str, &str)]) -> String {
+    // Always replace the server path everywhere.
+    if s.strip_suffix(SERVER_FILENAME)
+        .is_some_and(|s| s.ends_with('/'))
+    {
+        return CHROOT_SERVER_PATH.into();
+    }
+
+    // Replace by the first prefix match.
+    for (pattern, replacement) in replacement_map {
+        if let Some(rest) = s.strip_prefix(pattern) {
+            if rest.is_empty() || rest.starts_with('/') {
+                return [replacement, rest].concat();
+            }
+        }
+    }
+
+    s.into()
+}
+
 /// Extend `dest` with `contents`, replacing any occurrence of patterns in a json string in
 /// `contents` with a replacement.
-fn replace(
-    contents: &[u8],
-    replacement_map: &HashMap<&str, &str>,
-    dest: &mut Vec<u8>,
-) -> Result<()> {
-    fn map_value(val: Value, replacement_map: &HashMap<&str, &str>) -> Value {
+fn replace(contents: &[u8], replacement_map: &[(&str, &str)], dest: &mut Vec<u8>) -> Result<()> {
+    fn map_value(val: Value, replacement_map: &[(&str, &str)]) -> Value {
         match val {
-            Value::String(s) =>
-            // `s.replace` is very likely doing more work than necessary. Probably we only need
-            // to look for the pattern at the beginning of the string.
-            {
-                lazy_static! {
-                    static ref SERVER_PATH_REGEX: Regex =
-                        Regex::new(r".*/rust-analyzer-chromiumos-wrapper$").unwrap();
+            Value::String(mut s) => {
+                if s.starts_with("file:") {
+                    // rust-analyzer uses LSP paths most of the time, which are encoded with the
+                    // file: URL scheme.
+                    s = replace_uri(&s, replacement_map).unwrap_or_else(|e| {
+                        warn!("replace_uri failed: {e:?}");
+                        s
+                    });
+                } else {
+                    // For certain config items, paths may be used instead of URIs.
+                    s = replace_path(&s, replacement_map);
                 }
-                // Always replace the server path everywhere.
-                let mut s = SERVER_PATH_REGEX
-                    .replace_all(&s, CHROOT_SERVER_PATH)
-                    .to_string();
-                // Then replace all mappings we get.
-                for (pattern, replacement) in replacement_map {
-                    s = s.replace(pattern, replacement);
-                }
-                Value::String(s.to_string())
+                Value::String(s)
             }
             Value::Array(mut v) => {
                 for val_ref in v.iter_mut() {
@@ -271,7 +318,7 @@
 fn stream_with_replacement<R: BufRead, W: Write>(
     r: &mut R,
     w: &mut W,
-    replacement_map: &HashMap<&str, &str>,
+    replacement_map: &[(&str, &str)],
 ) -> Result<()> {
     let mut head = Header::default();
     let mut buf = Vec::with_capacity(1024);
@@ -350,17 +397,12 @@
 
     fn test_stream_with_replacement(
         read: &str,
-        pattern: &str,
-        replacement: &str,
+        replacement_map: &[(&str, &str)],
         json_expected: &str,
     ) -> Result<()> {
-        let mut w = Vec::<u8>::with_capacity(read.len());
-        let replacement_map = {
-            let mut m = HashMap::new();
-            m.insert(pattern, replacement);
-            m
-        };
-        stream_with_replacement(&mut read.as_bytes(), &mut w, &replacement_map)?;
+        let mut w = Vec::new();
+        let input = format!("Content-Length: {}\r\n\r\n{}", read.as_bytes().len(), read);
+        stream_with_replacement(&mut input.as_bytes(), &mut w, &replacement_map)?;
 
         // serde_json may not format the json output the same as we do, so we can't just compare
         // as strings or slices.
@@ -384,48 +426,72 @@
     }
 
     #[test]
-    fn test_stream_with_replacement_1() -> Result<()> {
+    fn test_stream_with_replacement_simple() -> Result<()> {
         test_stream_with_replacement(
-            // read
-            "Content-Length: 93\r\n\r\n{\"somekey\": {\"somepath\": \"XYZXYZabc\",\
-            \"anotherpath\": \"somestring\"}, \"anotherkey\": \"XYZXYZdef\"}",
-            // pattern
-            "XYZXYZ",
-            // replacement
-            "REPLACE",
-            // json_expected
-            "{\"somekey\": {\"somepath\": \"REPLACEabc\", \"anotherpath\": \"somestring\"},\
-            \"anotherkey\": \"REPLACEdef\"}",
+            r#"{
+                "somekey": {
+                    "somepath": "/XYZXYZ/",
+                    "anotherpath": "/some/string"
+                },
+                "anotherkey": "/XYZXYZ/def"
+            }"#,
+            &[("/XYZXYZ", "/REPLACE")],
+            r#"{
+                "somekey": {
+                    "somepath": "/REPLACE/",
+                    "anotherpath": "/some/string"
+                },
+                "anotherkey": "/REPLACE/def"
+            }"#,
         )
     }
 
     #[test]
-    fn test_stream_with_replacement_2() -> Result<()> {
+    fn test_stream_with_replacement_file_uri() -> Result<()> {
         test_stream_with_replacement(
-            // read
-            "Content-Length: 83\r\n\r\n{\"key0\": \"sometextABCDEF\",\
-            \"key1\": {\"key2\": 5, \"key3\": \"moreABCDEFtext\"}, \"key4\": 1}",
-            // pattern
-            "ABCDEF",
-            // replacement
-            "replacement",
-            // json_expected
-            "{\"key0\": \"sometextreplacement\", \"key1\": {\"key2\": 5,\
-            \"key3\": \"morereplacementtext\"}, \"key4\": 1}",
+            r#"{
+                "key0": "file:///ABCDEF/",
+                "key1": {
+                    "key2": 5,
+                    "key3": "file:///ABCDEF/text"
+                },
+                "key4": 1
+            }"#,
+            &[("/ABCDEF", "/replacement")],
+            r#"{
+                "key0": "file:///replacement/",
+                "key1": {
+                    "key2": 5,
+                    "key3": "file:///replacement/text"
+                },
+                "key4": 1
+            }"#,
         )
     }
 
     #[test]
-    fn test_stream_with_replacement_3() -> Result<()> {
+    fn test_stream_with_replacement_self_binary() -> Result<()> {
         test_stream_with_replacement(
-            // read
-            "Content-Length: 55\r\n\r\n{\"path\": \"/my_folder/rust-analyzer-chromiumos-wrapper\"}",
-            // pattern
-            "",
-            // replacement
-            "",
-            // json_expected
-            "{\"path\": \"/usr/sbin/rust-analyzer\"}",
+            r#"{
+                "path": "/my_folder/rust-analyzer-chromiumos-wrapper"
+            }"#,
+            &[],
+            r#"{
+                "path": "/usr/bin/rust-analyzer"
+            }"#,
+        )
+    }
+
+    #[test]
+    fn test_stream_with_replacement_replace_once() -> Result<()> {
+        test_stream_with_replacement(
+            r#"{
+                "path": "/mnt/home/file"
+            }"#,
+            &[("/mnt/home", "/home"), ("/home", "/foo")],
+            r#"{
+                "path": "/home/file"
+            }"#,
         )
     }
 }
diff --git a/rust_tools/auto_update_rust_bootstrap.py b/rust_tools/auto_update_rust_bootstrap.py
index 09df9bd..c41fcd0 100755
--- a/rust_tools/auto_update_rust_bootstrap.py
+++ b/rust_tools/auto_update_rust_bootstrap.py
@@ -377,17 +377,17 @@
     )
 
 
-def scrape_git_push_cl_id(git_push_output: str) -> int:
+def scrape_git_push_cl_id_strs(git_push_output: str) -> List[str]:
     id_regex = re.compile(
         r"^remote:\s+https://chromium-review\S+/\+/(\d+)\s", re.MULTILINE
     )
     results = id_regex.findall(git_push_output)
-    if len(results) != 1:
+    if not results:
         raise ValueError(
-            f"Found {len(results)} matches of {id_regex} in"
-            f"{git_push_output!r}; expected 1"
+            f"Found 0 matches of {id_regex} in {git_push_output!r}; expected "
+            "at least 1."
         )
-    return int(results[0])
+    return results
 
 
 def upload_changes(git_dir: Path):
@@ -405,22 +405,25 @@
     print(result.stdout, end=None)
     result.check_returncode()
 
-    cl_id = str(scrape_git_push_cl_id(result.stdout))
-    logging.info("Uploaded crrev.com/c/%s successfully!", cl_id)
-    gerrit_commands = (
-        ["gerrit", "label-v", cl_id, "1"],
-        ["gerrit", "label-cq", cl_id, "1"],
-        ["gerrit", "label-as", cl_id, "1"],
-        ["gerrit", "reviewers", cl_id] + list(DEFAULT_CL_REVIEWERS),
-        ["gerrit", "ready", cl_id],
+    cl_ids = scrape_git_push_cl_id_strs(result.stdout)
+    logging.info(
+        "Uploaded %s successfully!", [f"crrev.com/c/{x}" for x in cl_ids]
     )
-    for command in gerrit_commands:
-        logging.info("Running gerrit command: %s", command)
-        subprocess.run(
-            command,
-            check=True,
-            stdin=subprocess.DEVNULL,
+    for cl_id in cl_ids:
+        gerrit_commands = (
+            ["gerrit", "label-v", cl_id, "1"],
+            ["gerrit", "label-cq", cl_id, "1"],
+            ["gerrit", "label-as", cl_id, "1"],
+            ["gerrit", "reviewers", cl_id] + list(DEFAULT_CL_REVIEWERS),
+            ["gerrit", "ready", cl_id],
         )
+        for command in gerrit_commands:
+            logging.info("Running gerrit command: %s", command)
+            subprocess.run(
+                command,
+                check=True,
+                stdin=subprocess.DEVNULL,
+            )
 
 
 def maybe_add_newest_prebuilts(
diff --git a/rust_tools/auto_update_rust_bootstrap_test.py b/rust_tools/auto_update_rust_bootstrap_test.py
index ea58e72..0578539 100755
--- a/rust_tools/auto_update_rust_bootstrap_test.py
+++ b/rust_tools/auto_update_rust_bootstrap_test.py
@@ -5,7 +5,6 @@
 
 """Tests for auto_update_rust_bootstrap."""
 
-
 import os
 from pathlib import Path
 import shutil
@@ -36,6 +35,26 @@
  * [new reference]             HEAD -> refs/for/main
 """
 
+_GIT_PUSH_MULTI_CL_OUTPUT = r"""
+remote: Waiting for private key checker: 2/2 objects left
+remote:
+remote: Processing changes: new: 1 (\)
+remote: Processing changes: new: 1 (|)
+remote: Processing changes: new: 1 (/)
+remote: Processing changes: refs: 1, new: 1 (/)
+remote: Processing changes: refs: 1, new: 1 (/)
+remote: Processing changes: refs: 1, new: 1 (/)
+remote: Processing changes: refs: 1, new: 1, done
+remote:
+remote: SUCCESS
+remote:
+remote:   https://chromium-review.googlesource.com/c/chromiumos/overlays/chromiumos-overlay/+/5339923 rust-bootstrap: add version 1.75.0 [NEW]
+remote:   https://chromium-review.googlesource.com/c/chromiumos/overlays/chromiumos-overlay/+/5339924 rust-bootstrap: remove unused ebuilds [NEW]
+remote:
+To https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay
+ * [new reference]             HEAD -> refs/for/main
+"""
+
 
 class Test(unittest.TestCase):
     """Tests for auto_update_rust_bootstrap."""
@@ -49,8 +68,17 @@
 
     def test_git_cl_id_scraping(self):
         self.assertEqual(
-            auto_update_rust_bootstrap.scrape_git_push_cl_id(_GIT_PUSH_OUTPUT),
-            5018826,
+            auto_update_rust_bootstrap.scrape_git_push_cl_id_strs(
+                _GIT_PUSH_OUTPUT
+            ),
+            ["5018826"],
+        )
+
+        self.assertEqual(
+            auto_update_rust_bootstrap.scrape_git_push_cl_id_strs(
+                _GIT_PUSH_MULTI_CL_OUTPUT
+            ),
+            ["5339923", "5339924"],
         )
 
     def test_ebuild_linking_logic_handles_direct_relative_symlinks(self):
diff --git a/rust_tools/rust_uprev.py b/rust_tools/rust_uprev.py
index ee95613..9845c7c 100755
--- a/rust_tools/rust_uprev.py
+++ b/rust_tools/rust_uprev.py
@@ -204,10 +204,6 @@
     return f"rustc-{version}-src.tar.gz"
 
 
-def compute_rust_bootstrap_prebuilt_name(version: RustVersion) -> str:
-    return f"rust-bootstrap-{version}.tbz2"
-
-
 def find_ebuild_for_package(name: str) -> str:
     """Returns the path to the ebuild for the named package."""
     return run_in_chroot(
@@ -546,7 +542,6 @@
     are available on the mirror and the local copies are the same as
     the ones on the mirror.
     """
-    fetch_distfile_from_mirror(compute_rust_bootstrap_prebuilt_name(version))
     fetch_distfile_from_mirror(compute_rustc_src_name(version))
 
 
@@ -1201,7 +1196,7 @@
         # Determine the template version, if not given.
         template_version = args.template
         if template_version is None:
-            rust_ebuild = find_ebuild_for_package("rust")
+            rust_ebuild = find_ebuild_for_package("dev-lang/rust")
             template_version = RustVersion.parse_from_ebuild(rust_ebuild)
 
         run_step("create new repo", lambda: create_new_repo(args.uprev))
diff --git a/toolchain_utils_githooks/check-presubmit.py b/toolchain_utils_githooks/check-presubmit.py
index 2af7569..127726a 100755
--- a/toolchain_utils_githooks/check-presubmit.py
+++ b/toolchain_utils_githooks/check-presubmit.py
@@ -72,6 +72,7 @@
 # The files and directories on which we run the mypy typechecker. The paths are
 # relative to the root of the toolchain-utils repository.
 MYPY_CHECKED_PATHS = (
+    "afdo_tools/update_kernel_afdo.py",
     "check_portable_toolchains.py",
     "cros_utils/bugs.py",
     "cros_utils/bugs_test.py",
@@ -109,15 +110,6 @@
     return shutil.which(exe) is not None
 
 
-def escape_command(command: Iterable[str]) -> str:
-    """Returns a human-readable and copy-pastable shell command.
-
-    Only intended for use in output to users. shell=True is strongly
-    discouraged.
-    """
-    return " ".join(shlex.quote(x) for x in command)
-
-
 def remove_deleted_files(files: Iterable[str]) -> List[str]:
     return [f for f in files if os.path.exists(f)]
 
@@ -278,8 +270,8 @@
     if not bad_files:
         return CheckResult(
             ok=False,
-            output="`%s` failed; stdout/stderr:\n%s"
-            % (escape_command(command), stdout_and_stderr),
+            output=f"`{shlex.join(command)}` failed; stdout/stderr:\n"
+            f"{stdout_and_stderr}",
             autofix_commands=[],
         )
 
@@ -710,8 +702,7 @@
     if exit_code:
         return CheckResult(
             ok=False,
-            output="%s failed; stdout/stderr:\n%s"
-            % (escape_command(command), output),
+            output=f"{shlex.join(command)} failed; stdout/stderr:\n{output}",
             autofix_commands=[],
         )
 
@@ -799,9 +790,10 @@
     if isinstance(check_results, CheckResult):
         ok, output, autofix_commands = check_results
         if not ok and autofix_commands:
-            recommendation = "Recommended command(s) to fix this: %s" % [
-                escape_command(x) for x in autofix_commands
-            ]
+            recommendation = (
+                "Recommended command(s) to fix this: "
+                f"{[shlex.join(x) for x in autofix_commands]}"
+            )
             if output:
                 output += "\n" + recommendation
             else:
@@ -817,8 +809,8 @@
             if not ok and autofix:
                 message.append(
                     indent_block(
-                        "Recommended command(s) to fix this: %s"
-                        % [escape_command(x) for x in autofix]
+                        "Recommended command(s) to fix this: "
+                        f"{[shlex.join(x) for x in autofix]}"
                     )
                 )
 
@@ -869,12 +861,12 @@
 
         if exit_code:
             print(
-                "*** Autofix command `%s` exited with code %d; stdout/stderr:"
-                % (escape_command(command), exit_code)
+                f"*** Autofix command `{shlex.join(command)}` exited with "
+                f"code {exit_code}; stdout/stderr:"
             )
             print(output)
         else:
-            print("*** Autofix `%s` succeeded" % escape_command(command))
+            print(f"*** Autofix `{shlex.join(command)}` succeeded")
             anything_succeeded = True
 
     if anything_succeeded:
@@ -897,7 +889,9 @@
     return os.path.exists("/etc/cros_chroot_version")
 
 
-def maybe_reexec_inside_chroot(autofix: bool, files: List[str]) -> None:
+def maybe_reexec_inside_chroot(
+    autofix: bool, install_deps_only: bool, files: List[str]
+) -> None:
     if is_in_chroot():
         return
 
@@ -944,6 +938,8 @@
 
     if not autofix:
         args.append("--no_autofix")
+    if install_deps_only:
+        args.append("--install_deps_only")
     args.extend(rebase_path(x) for x in files)
 
     if chdir_to is None:
@@ -990,20 +986,39 @@
         action="store_false",
         help="Prevent auto-entering the chroot if we're not already in it.",
     )
+    parser.add_argument(
+        "--install_deps_only",
+        action="store_true",
+        help="""
+        Only install dependencies that would be required if presubmits were
+        being run, and quit. This skips all actual checking.
+        """,
+    )
     parser.add_argument("files", nargs="*")
     opts = parser.parse_args(argv)
 
     files = opts.files
-    if not files:
+    install_deps_only = opts.install_deps_only
+    if not files and not install_deps_only:
         return 0
 
     if opts.enter_chroot:
-        maybe_reexec_inside_chroot(opts.autofix, opts.files)
+        maybe_reexec_inside_chroot(opts.autofix, install_deps_only, files)
 
     # If you ask for --no_enter_chroot, you're on your own for installing these
     # things.
     if is_in_chroot():
         ensure_pip_deps_installed()
+        if install_deps_only:
+            print(
+                "Dependency installation complete & --install_deps_only "
+                "passed. Quit."
+            )
+            return 0
+    elif install_deps_only:
+        parser.error(
+            "--install_deps_only is meaningless if the chroot isn't entered"
+        )
 
     files = [os.path.abspath(f) for f in files]