diff --git a/docs/C11_SOURCE_COMPATIBILITY.md b/docs/C11_SOURCE_COMPATIBILITY.md new file mode 100644 index 00000000..1a0c4119 --- /dev/null +++ b/docs/C11_SOURCE_COMPATIBILITY.md @@ -0,0 +1,8 @@ +# C11 source compatibility + +A C11 label must precede a statement. The empty statement after retry_candidates keeps the following local declaration valid without changing control flow. +main.cpp uses fntrace.h as the single owner of fntrace_is_game_started and its C linkage. Redundant block declarations can disagree under GCC 9. + +Run `python runtime/tests/test_overlay_retry_c11.py --compiler gcc` and `python runtime/tests/test_fntrace_c_linkage.py`. +The first compiles the actual label/declaration excerpt in strict C11 mode. The second checks declaration ownership. +These focused checks do not replace a full GCC 9 compile/link of the current framework. diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 21ae85a5..829d345a 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -562,6 +562,10 @@ if(BUILD_TESTING) find_package(Python3 COMPONENTS Interpreter) if(Python3_Interpreter_FOUND) + add_test(NAME fntrace_c_linkage_test COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_fntrace_c_linkage.py) + if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") + add_test(NAME overlay_retry_c11_test COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_overlay_retry_c11.py --compiler ${CMAKE_C_COMPILER}) + endif() add_test(NAME disc_companion_test COMMAND ${Python3_EXECUTABLE} ${PSXRECOMP_ROOT}/tools/tests/test_disc_companion.py) add_test(NAME sbi_registry_test COMMAND ${Python3_EXECUTABLE} ${PSXRECOMP_ROOT}/tools/tests/test_sbi_registry.py) add_test(NAME frame_interpolation_context_ownership_test diff --git a/runtime/src/main.cpp b/runtime/src/main.cpp index 5ab2d000..121dfbfa 100644 --- a/runtime/src/main.cpp +++ b/runtime/src/main.cpp @@ -6740,7 +6740,6 @@ static NetplayVblankEpilogue sdl_vblank_present_body(void) { ep.override = override; /* Turbo-active / multitap arming share game-started detection. */ - extern int fntrace_is_game_started(void); if (psx_netplay_active()) { psx_netplay_finish_frame(); @@ -7070,7 +7069,6 @@ static NetplayVblankEpilogue sdl_vblank_present_body(void) { return ep; /* Engage widescreen at game entry: BIOS boot stays authentic 4:3. */ if (!g_ws_engaged) { - extern int fntrace_is_game_started(void); if (fntrace_is_game_started()) { g_ws_engaged = true; g_ws_projection_mode = -1; diff --git a/runtime/src/overlay_loader.c b/runtime/src/overlay_loader.c index e0b4bc27..c2c7ea89 100644 --- a/runtime/src/overlay_loader.c +++ b/runtime/src/overlay_loader.c @@ -3597,6 +3597,7 @@ int overlay_loader_dispatch(CPUState *cpu, uint32_t addr) { } int lazy_loaded = 0; retry_candidates: + ; /* C11 labels must precede a statement. */ int head = idx_head(phys); int loaded_range_ci = -1; int lazy_exact = 0; diff --git a/runtime/tests/test_fntrace_c_linkage.py b/runtime/tests/test_fntrace_c_linkage.py new file mode 100644 index 00000000..330ff900 --- /dev/null +++ b/runtime/tests/test_fntrace_c_linkage.py @@ -0,0 +1,6 @@ +from pathlib import Path +p=Path(__file__).resolve().parents[2]/"runtime/src/main.cpp" +s=p.read_text(encoding="utf-8") +assert '#include "fntrace.h"' in s +assert 'extern int fntrace_is_game_started' not in s +print("fntrace C header ownership: PASS") diff --git a/runtime/tests/test_overlay_retry_c11.py b/runtime/tests/test_overlay_retry_c11.py new file mode 100644 index 00000000..3d2c345f --- /dev/null +++ b/runtime/tests/test_overlay_retry_c11.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +"""Compile the production retry label and following declaration as strict C11.""" +import argparse +from pathlib import Path +import shutil +import subprocess +import tempfile +parser = argparse.ArgumentParser() +parser.add_argument('--compiler', default='cc') +args = parser.parse_args() +root = Path(__file__).resolve().parents[1] +text = (root/'src/overlay_loader.c').read_text(encoding='utf-8') +start = text.index('retry_candidates:') +end = text.index('int loaded_range_ci', start) +fragment = text[start:end] +with tempfile.TemporaryDirectory() as tmp: + source = Path(tmp)/'label.c' + source.write_text('static int idx_head(int p) { return p; }\nint main(void) { int phys=0; if (phys) goto retry_candidates;\n'+fragment+'return head; }\n') + subprocess.run([shutil.which(args.compiler) or args.compiler,'-std=c11','-pedantic-errors','-fsyntax-only',str(source)],check=True) +print('production retry label: strict C11 passes')