From 19db55c64b3bed78d62fbccc74b726dcdea7d11f Mon Sep 17 00:00:00 2001 From: Kovalev Vladislav Date: Thu, 22 Oct 2026 17:01:09 +0600 Subject: [PATCH] fix(tools): strip save-temps flags from syntax checks --- tools/check_compile.py | 3 +- tools/tests/test_check_compile.py | 47 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/tools/check_compile.py b/tools/check_compile.py index 24500ab954..24daf7321a 100644 --- a/tools/check_compile.py +++ b/tools/check_compile.py @@ -11,7 +11,8 @@ from contextlib import nullcontext from pathlib import Path CPP = (".cpp", ".cc", ".cxx", ".c") -DROP = ("-c", "-MD", "-MMD", "-MP", "-fsyntax-only", "-fno-syntax-only") +DROP = ("-c", "-MD", "-MMD", "-MP", "-fsyntax-only", "-fno-syntax-only", "-save-temps", "--save-temps", + "-save-temps=cwd", "-save-temps=obj", "--save-temps=cwd", "--save-temps=obj") DROP_WITH_VALUE = ("-o", "-MT", "-MF", "-MQ", "-MJ") PREPROCESSING = ("-E", "--preprocess", "-M", "--dependencies", "-MM", "--user-dependencies", "-MG", "--print-missing-file-dependencies", "-P", "--no-line-commands", diff --git a/tools/tests/test_check_compile.py b/tools/tests/test_check_compile.py index 6bbbbf5570..1490024f4e 100644 --- a/tools/tests/test_check_compile.py +++ b/tools/tests/test_check_compile.py @@ -79,6 +79,53 @@ class CheckCompileTests(unittest.TestCase): for path, content in outputs.items(): self.assertEqual(path.read_bytes(), content) + def test_saved_temporaries_do_not_rewrite_files_or_hide_compiler_errors(self): + compiler = shutil.which("gcc") or shutil.which("clang") + if compiler is None: + self.skipTest("needs a C compiler") + source = self.source("unit.c") + for option, field in (("-save-temps", "arguments"), ("--save-temps", "command"), + ("-save-temps=cwd", "arguments"), ("-save-temps=obj", "command")): + with self.subTest(option=option, field=field): + source.write_text("#ifndef REQUIRED\n#error missing definition\n#endif\nint value;\n", encoding="utf-8") + arguments = [compiler, "-Werror", "-DREQUIRED", option, "-c", str(source), + "-o", str(self.build / "unit.o")] + original = subprocess.run(arguments, cwd=self.build, capture_output=True, text=True) + self.assertEqual(original.returncode, 0, original.stderr) + for name in ("a-unit", "a-unit.i"): + (self.build / name).write_bytes(b"previous build output") + command = (subprocess.list2cmdline(arguments) if os.name == "nt" else + " ".join(shlex.quote(argument) for argument in arguments)) + self.manifest([{"directory": str(self.build), "file": str(source), + field: arguments if field == "arguments" else command}]) + preserved = {path: path.read_bytes() for path in self.build.iterdir()} + result = self.tool("unit.c") + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertIn("1 translation units compile", result.stdout) + for path, content in preserved.items(): + self.assertEqual(path.read_bytes(), content, str(path)) + self.assertEqual(set(self.build.iterdir()), set(preserved)) + source.write_text("#error syntax_check_must_fail\n", encoding="utf-8") + result = self.tool("unit.c") + self.assertEqual(result.returncode, 1, result.stdout + result.stderr) + self.assertIn("syntax_check_must_fail", result.stderr) + for path, content in preserved.items(): + self.assertEqual(path.read_bytes(), content, str(path)) + self.assertEqual(set(self.build.iterdir()), set(preserved)) + + def test_unknown_saved_temporary_mode_is_still_rejected_by_the_compiler(self): + compiler = shutil.which("gcc") or shutil.which("clang") + if compiler is None: + self.skipTest("needs a C compiler") + source = self.source("unit.c") + self.manifest([{"directory": str(self.build), "file": str(source), + "arguments": [compiler, "-save-temps=invalid", "-c", str(source), + "-o", str(self.build / "unit.o")]}]) + result = self.tool("unit.c") + self.assertEqual(result.returncode, 1, result.stdout + result.stderr) + self.assertIn("save-temps", result.stderr) + self.assertFalse((self.build / "unit.o").exists()) + def test_ninja_response_file_is_expanded_before_syntax_rewriting(self): compiler = shutil.which("clang") or shutil.which("gcc") if compiler is None or shutil.which("ninja") is None: