Skip to content

Commit 7747ac0

Browse files
committed
fix(windows): preserve NOMINMAX checker coordinates (#462)
Use one comment-and-literal-inert structural source view for both local directive parsing and the windows.h location. This keeps line and byte coordinates aligned while preventing string literals from masquerading as active preprocessor definitions. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Codex:GPT-5 [Codex]
1 parent a300bf3 commit 7747ac0

3 files changed

Lines changed: 156 additions & 6 deletions

File tree

.agents/specs/windows-msvc-central-nominmax.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,15 @@ containing directive decoys must pass. Removing the central definition with no
156156
fallbacks must reject all five sources. The central CMake definition, all four
157157
source removals, `/W4 /WX`, guarded standalone fallbacks, and the release
158158
invocation remain unchanged.
159+
160+
The recognized RED run reproduced both defects: the independent guarded-before
161+
case falsely rejected MiniMax-H3 sharded loading, filesystem offload, and the
162+
CPU threadpool, and raw/ordinary string decoys were falsely treated as active
163+
definitions. Line and block comment decoys already passed. The repair reuses
164+
`without_cpp_comments_and_literals`, whose space-for-byte replacement preserves
165+
newlines and offsets, and passes that single structural view to both the
166+
directive state machine and the `windows.h` search. The complete focused matrix
167+
then passes: guarded-before independently in all five sources, late and
168+
unguarded definitions rejected in all five, all four inert decoys accepted, and
169+
central removal without fallbacks rejected in all five. The direct production
170+
checker and the complete 68-test Windows portability suite pass.

scripts/check-windows-portability.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,11 @@ def _has_central_msvc_nominmax(cmake: str) -> bool:
6060
)
6161

6262

63-
def _local_nominmax_definitions(source: str) -> list[tuple[int, bool]]:
64-
"""Return local NOMINMAX definition lines and whether absence-guarded."""
63+
def _local_nominmax_definitions(active_source: str) -> list[tuple[int, bool]]:
64+
"""Return active NOMINMAX definition lines and whether absence-guarded."""
6565
definitions: list[tuple[int, bool]] = []
6666
absence_guards: list[bool] = []
67-
for number, line in enumerate(without_cpp_comments(source).splitlines(), 1):
67+
for number, line in enumerate(active_source.splitlines(), 1):
6868
match = re.match(r"\s*#\s*(\w+)(.*)$", line)
6969
if match is None:
7070
continue
@@ -1726,18 +1726,19 @@ def check(root: Path, build_dir: Path | None = None,
17261726

17271727
central_nominmax = _has_central_msvc_nominmax(cmake)
17281728
for relative, source in texts.items():
1729-
definitions = _local_nominmax_definitions(source)
1729+
active_source = without_cpp_comments_and_literals(source)
1730+
definitions = _local_nominmax_definitions(active_source)
17301731
for line, guarded in definitions:
17311732
if not guarded:
17321733
errors.append(
17331734
f"{relative}:{line}: unguarded source-local NOMINMAX is forbidden"
17341735
)
17351736
windows_header = re.search(
1736-
r"(?m)^\s*#\s*include\s*<windows\.h>", without_cpp_comments(source)
1737+
r"(?m)^\s*#\s*include\s*<windows\.h>", active_source
17371738
)
17381739
if windows_header is None or central_nominmax:
17391740
continue
1740-
header_line = source.count("\n", 0, windows_header.start()) + 1
1741+
header_line = active_source.count("\n", 0, windows_header.start()) + 1
17411742
if not any(guarded and line < header_line for line, guarded in definitions):
17421743
errors.append(
17431744
f"{relative}: NOMINMAX must be defined centrally or by an "

tests/scripts/test_check_windows_portability.py

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@
2424
UNSUPPORTED_TIER_FILTER = (
2525
"--test-case=elementwise CPU GEMM: the forced tier is the tier that actually ran"
2626
)
27+
NOMINMAX_REAL_CLOSURE = (
28+
"src/vllm/model_executor/models/minimax_h3_sharded.cpp",
29+
"src/vllm/v1/kv_offload/fs_io.cpp",
30+
"src/vt/cpu/cpu_threadpool.cpp",
31+
"src/vllm/platform/console_shutdown.cpp",
32+
"src/vllm/platform/process.cpp",
33+
)
2734

2835

2936
SAFE_FILES = {
@@ -267,6 +274,27 @@ def assert_rejected(self, relative: str, content: str, reason: str) -> None:
267274
self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)
268275
self.assertIn(reason, result.stdout + result.stderr)
269276

277+
@staticmethod
278+
def nominmax_real_sources() -> dict[str, str]:
279+
return {
280+
relative: (REPO / relative).read_text(encoding="utf-8")
281+
for relative in NOMINMAX_REAL_CLOSURE
282+
}
283+
284+
@staticmethod
285+
def with_nominmax_fallback(source: str, *, before: bool,
286+
guarded: bool = True) -> str:
287+
header = "#include <windows.h>"
288+
if source.count(header) != 1:
289+
raise AssertionError("expected exactly one windows.h include")
290+
definition = "#define NOMINMAX\n"
291+
if guarded:
292+
definition = "#ifndef NOMINMAX\n#define NOMINMAX\n#endif\n"
293+
return source.replace(
294+
header,
295+
definition + header if before else header + "\n" + definition,
296+
)
297+
270298
def test_accepts_complete_guarded_contract(self) -> None:
271299
result = self.run_checker(self.make_tree())
272300
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
@@ -704,6 +732,115 @@ def test_nominmax_contract_follows_central_compile_definition(self) -> None:
704732
"unguarded source-local NOMINMAX",
705733
)
706734

735+
def test_nominmax_real_closure_accepts_guarded_fallbacks_before_headers(
736+
self) -> None:
737+
cmake = textwrap.dedent(SAFE_FILES["CMakeLists.txt"])
738+
without_central = cmake.replace(
739+
"add_compile_definitions(NOMINMAX _CRT_SECURE_NO_WARNINGS)", ""
740+
)
741+
safe_fs = textwrap.dedent(
742+
SAFE_FILES["src/vllm/v1/kv_offload/fs_io.cpp"]
743+
)
744+
real_sources = self.nominmax_real_sources()
745+
for relative, source in real_sources.items():
746+
with self.subTest(relative=relative):
747+
result = self.run_checker(self.make_tree({
748+
"CMakeLists.txt": without_central,
749+
"src/vllm/v1/kv_offload/fs_io.cpp":
750+
self.with_nominmax_fallback(safe_fs, before=True),
751+
relative: self.with_nominmax_fallback(
752+
source, before=True
753+
),
754+
}))
755+
self.assertEqual(
756+
result.returncode, 0, result.stdout + result.stderr
757+
)
758+
759+
def test_nominmax_real_closure_rejects_late_and_unguarded_fallbacks(
760+
self) -> None:
761+
cmake = textwrap.dedent(SAFE_FILES["CMakeLists.txt"])
762+
without_central = cmake.replace(
763+
"add_compile_definitions(NOMINMAX _CRT_SECURE_NO_WARNINGS)", ""
764+
)
765+
real_sources = self.nominmax_real_sources()
766+
all_guarded = {
767+
relative: self.with_nominmax_fallback(source, before=True)
768+
for relative, source in real_sources.items()
769+
}
770+
for relative, source in real_sources.items():
771+
with self.subTest(relative=relative, shape="late"):
772+
mutations = dict(all_guarded)
773+
mutations[relative] = self.with_nominmax_fallback(
774+
source, before=False
775+
)
776+
result = self.run_checker(self.make_tree({
777+
"CMakeLists.txt": without_central,
778+
**mutations,
779+
}))
780+
self.assertNotEqual(
781+
result.returncode, 0, result.stdout + result.stderr
782+
)
783+
self.assertIn(
784+
f"{relative}: NOMINMAX must be defined centrally",
785+
result.stdout + result.stderr,
786+
)
787+
788+
with self.subTest(relative=relative, shape="unguarded"):
789+
mutations = dict(real_sources)
790+
mutations[relative] = self.with_nominmax_fallback(
791+
source, before=True, guarded=False
792+
)
793+
result = self.run_checker(self.make_tree(mutations))
794+
self.assertNotEqual(
795+
result.returncode, 0, result.stdout + result.stderr
796+
)
797+
self.assertRegex(
798+
result.stdout + result.stderr,
799+
rf"{re.escape(relative)}:\d+: unguarded source-local "
800+
r"NOMINMAX is forbidden",
801+
)
802+
803+
def test_nominmax_real_closure_ignores_comment_and_literal_decoys(
804+
self) -> None:
805+
real_sources = self.nominmax_real_sources()
806+
target = "src/vllm/platform/process.cpp"
807+
source = real_sources[target]
808+
decoys = {
809+
"raw string": 'constexpr auto kRaw = R"TAG(\n#define NOMINMAX\n)TAG";\n',
810+
"ordinary string": 'constexpr auto kString = "\\\n#define NOMINMAX";\n',
811+
"line comment": "// #define NOMINMAX\n",
812+
"block comment": "/*\n#define NOMINMAX\n*/\n",
813+
}
814+
for shape, decoy in decoys.items():
815+
with self.subTest(shape=shape):
816+
mutations = dict(real_sources)
817+
mutations[target] = source.replace(
818+
"#include <windows.h>",
819+
decoy + "#include <windows.h>",
820+
)
821+
result = self.run_checker(self.make_tree(mutations))
822+
self.assertEqual(
823+
result.returncode, 0, result.stdout + result.stderr
824+
)
825+
826+
def test_nominmax_real_closure_without_contract_rejects_all_five_sources(
827+
self) -> None:
828+
cmake = textwrap.dedent(SAFE_FILES["CMakeLists.txt"])
829+
without_central = cmake.replace(
830+
"add_compile_definitions(NOMINMAX _CRT_SECURE_NO_WARNINGS)", ""
831+
)
832+
result = self.run_checker(self.make_tree({
833+
"CMakeLists.txt": without_central,
834+
**self.nominmax_real_sources(),
835+
}))
836+
self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)
837+
output = result.stdout + result.stderr
838+
for relative in NOMINMAX_REAL_CLOSURE:
839+
with self.subTest(relative=relative):
840+
self.assertIn(
841+
f"{relative}: NOMINMAX must be defined centrally", output
842+
)
843+
707844
def test_pins_peer_close_invalidation(self) -> None:
708845
source = textwrap.dedent(
709846
SAFE_FILES["src/vllm/v1/kv_offload/lmcache/remote_client.cpp"]

0 commit comments

Comments
 (0)