From 2b9fdd6e4207f2a6e00332650cbf617cec8c6f2d Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Fri, 21 Aug 2026 22:21:54 +0000 Subject: [PATCH] Fix the check that every registered diagnostic kind is declared (#7660) `load_diagnostic_kind` matched `^\s+CARBON_DIAGNOSTIC_KIND` without `re.MULTILINE` against a file whose entries start at column zero, so it found nothing: `check_unused` was comparing an empty set of declarations against every use and reporting nothing at all. The check has never run. With it running, three kinds turn out to be registered and never declared, and go: `BuildFailureRunningClangToLink`, `BuildOutputFileOpenError`, and `BuildPreludeManifestError`. `load_diagnostic_uses_in` looked only for `CARBON_DIAGNOSTIC`, so a diagnostic declared with `CARBON_DIAGNOSTIC_ON_SCOPE` counted as unused, and it read the two macros' own definitions in `diagnostic.h` as uses. Both are why the kinds above could not simply be deleted before. Assisted-by: Claude Code --------- Co-authored-by: Geoff Romer --- toolchain/diagnostics/check_diagnostics.py | 12 +++++++++--- toolchain/diagnostics/coverage_test.cpp | 3 --- toolchain/diagnostics/kind.def | 3 --- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/toolchain/diagnostics/check_diagnostics.py b/toolchain/diagnostics/check_diagnostics.py index c4e74db735b9..baaa9082e5ad 100755 --- a/toolchain/diagnostics/check_diagnostics.py +++ b/toolchain/diagnostics/check_diagnostics.py @@ -56,7 +56,9 @@ def load_diagnostic_kind() -> Set[str]: """ path = Path("toolchain/diagnostics/kind.def") content = path.read_text() - decls = set(re.findall(r"^\s+CARBON_DIAGNOSTIC_KIND\((.+)\)", content)) + decls = set( + re.findall(r"^CARBON_DIAGNOSTIC_KIND\((.+)\)", content, flags=re.M) + ) return decls.difference(IGNORED) @@ -71,9 +73,13 @@ def load_diagnostic_uses_in( line_offset = 0 found: Dict[str, List[Loc]] = collections.defaultdict(lambda: []) - for m in re.finditer(r"CARBON_DIAGNOSTIC\(\s*(\w+),", content): + # `CARBON_DIAGNOSTIC_ON_SCOPE` declares a diagnostic too; the definitions of + # both macros name their own parameter, which is not a use. + for m in re.finditer( + r"(?