From 70b11ee1208932af180bc88b8fa1b761927b2117 Mon Sep 17 00:00:00 2001 From: "Marco Antonio J. Costa" Date: Wed, 22 Jul 2026 10:41:59 -0300 Subject: [PATCH] make narrowing conversions in braced initialisers explicit A braced initialiser does not allow a narrowing conversion unless the value is a constant expression the compiler can prove fits. Every site here holds a runtime value: WORLD_COLS is the global guiWorldCols, the laptop screen coordinates are built from iScreenWidthOffset, the sector limits come from the externalised options. MSVC accepts all of it silently; clang rejects it, and it is ill-formed. Nothing about the generated code changes. MSVC was already performing these conversions; the casts only say so out loud, at the 73 places where it was happening implicitly. The invariant: each site is wrapped in a static_cast to the element type the initialiser already had, and nothing else is touched. No type is widened, no expression is reassociated, no value is clamped or checked. static_cast rather than a C-style cast so that a later reader can grep for the narrowings, and so that none of these can quietly become a reinterpret_cast if a type changes. Verification: # every changed line differs only by inserted casts and their parentheses git show HEAD -U0 | grep '^[+-][^+-]' | sed -E 's/static_cast<[A-Za-z0-9_]+>//g; s/[()]//g; s/^[+-]//' | sort | uniq -c | awk '$1 % 2' # no output git show HEAD -U0 | grep -c '^+[^+]' # 38 lines, 73 casts ninja -C build parse # narrowing class gone: 129 -> 91 sites ninja -C build -k 0 # Release, four applications, green ninja -C build-debug -k 0 # Debug, four applications, green Co-Authored-By: Claude Opus 4.8 --- Ja2/SaveLoadGame.cpp | 6 +++--- Laptop/AimSort.cpp | 30 +++++++++++++++--------------- Laptop/BobbyR.cpp | 10 +++++----- Strategic/strategicmap.cpp | 12 ++++++------ Tactical/Soldier Control.cpp | 2 +- TacticalAI/AIMain.cpp | 2 +- TileEngine/Isometric Utils.cpp | 12 ++++++------ sgp/video.cpp | 2 +- 8 files changed, 38 insertions(+), 38 deletions(-) diff --git a/Ja2/SaveLoadGame.cpp b/Ja2/SaveLoadGame.cpp index 9546b02eb..5b3bed95b 100644 --- a/Ja2/SaveLoadGame.cpp +++ b/Ja2/SaveLoadGame.cpp @@ -7746,9 +7746,9 @@ BOOLEAN LoadTacticalStatusFromSavedGame( HWFILE hFile ) for (int idx = OUR_TEAM; idx <= CIV_TEAM; ++idx) { cntFromFile[ idx ] = gTacticalStatus.Team[ idx ].bLastID - gTacticalStatus.Team[ idx ].bFirstID + 1; } - int cntFromIni[] = {gGameExternalOptions.ubGameMaximumNumberOfPlayerMercs + gGameExternalOptions.ubGameMaximumNumberOfPlayerVehicles, - gGameExternalOptions.ubGameMaximumNumberOfEnemies, gGameExternalOptions.ubGameMaximumNumberOfCreatures, - gGameExternalOptions.ubGameMaximumNumberOfRebels, gGameExternalOptions.ubGameMaximumNumberOfCivilians}; + int cntFromIni[] = {static_cast(gGameExternalOptions.ubGameMaximumNumberOfPlayerMercs + gGameExternalOptions.ubGameMaximumNumberOfPlayerVehicles), + static_cast(gGameExternalOptions.ubGameMaximumNumberOfEnemies), static_cast(gGameExternalOptions.ubGameMaximumNumberOfCreatures), + static_cast(gGameExternalOptions.ubGameMaximumNumberOfRebels), static_cast(gGameExternalOptions.ubGameMaximumNumberOfCivilians)}; CHAR16 *errMsgTxt[] = {L"Mercenary / Vehicle", L"Enemy", L"Creature", L"Militia", L"Civilian"}; errMsgTxt[0] = Additional113Text[ERROR_MAX_MERCSVEHICLES]; diff --git a/Laptop/AimSort.cpp b/Laptop/AimSort.cpp index 3652bf56b..0a8a763bd 100644 --- a/Laptop/AimSort.cpp +++ b/Laptop/AimSort.cpp @@ -108,21 +108,21 @@ #define AIM_SORT_SORT_BY_HEIGHT 81 UINT16 AimSortCheckBoxLoc[]={ - (AIM_SORT_SORT_BY_X + 9), (AIM_SORT_SORT_BY_Y + 34), - (AIM_SORT_SORT_BY_X + 9), (AIM_SORT_SORT_BY_Y + 47), - (AIM_SORT_SORT_BY_X + 9), (AIM_SORT_SORT_BY_Y + 60), - (AIM_SORT_SORT_BY_X + 105), (AIM_SORT_SORT_BY_Y + 34), - (AIM_SORT_SORT_BY_X + 105), (AIM_SORT_SORT_BY_Y + 47), - (AIM_SORT_SORT_BY_X + 105), (AIM_SORT_SORT_BY_Y + 60), - (AIM_SORT_SORT_BY_X + 201), (AIM_SORT_SORT_BY_Y + 34), - (AIM_SORT_SORT_BY_X + 201), (AIM_SORT_SORT_BY_Y + 47), - (AIM_SORT_SORT_BY_X + 201), (AIM_SORT_SORT_BY_Y + 60), - (AIM_SORT_SORT_BY_X + 297), (AIM_SORT_SORT_BY_Y + 34), - (AIM_SORT_SORT_BY_X + 297), (AIM_SORT_SORT_BY_Y + 47), - (AIM_SORT_SORT_BY_X + 297), (AIM_SORT_SORT_BY_Y + 60), - (AIM_SORT_SORT_BY_X + 9), (AIM_SORT_SORT_BY_Y + 21), - (AIM_SORT_SORT_BY_X + 372), (AIM_SORT_SORT_BY_Y + 4), - (AIM_SORT_SORT_BY_X + 372), (AIM_SORT_SORT_BY_Y + 17)}; + static_cast(AIM_SORT_SORT_BY_X + 9), static_cast(AIM_SORT_SORT_BY_Y + 34), + static_cast(AIM_SORT_SORT_BY_X + 9), static_cast(AIM_SORT_SORT_BY_Y + 47), + static_cast(AIM_SORT_SORT_BY_X + 9), static_cast(AIM_SORT_SORT_BY_Y + 60), + static_cast(AIM_SORT_SORT_BY_X + 105), static_cast(AIM_SORT_SORT_BY_Y + 34), + static_cast(AIM_SORT_SORT_BY_X + 105), static_cast(AIM_SORT_SORT_BY_Y + 47), + static_cast(AIM_SORT_SORT_BY_X + 105), static_cast(AIM_SORT_SORT_BY_Y + 60), + static_cast(AIM_SORT_SORT_BY_X + 201), static_cast(AIM_SORT_SORT_BY_Y + 34), + static_cast(AIM_SORT_SORT_BY_X + 201), static_cast(AIM_SORT_SORT_BY_Y + 47), + static_cast(AIM_SORT_SORT_BY_X + 201), static_cast(AIM_SORT_SORT_BY_Y + 60), + static_cast(AIM_SORT_SORT_BY_X + 297), static_cast(AIM_SORT_SORT_BY_Y + 34), + static_cast(AIM_SORT_SORT_BY_X + 297), static_cast(AIM_SORT_SORT_BY_Y + 47), + static_cast(AIM_SORT_SORT_BY_X + 297), static_cast(AIM_SORT_SORT_BY_Y + 60), + static_cast(AIM_SORT_SORT_BY_X + 9), static_cast(AIM_SORT_SORT_BY_Y + 21), + static_cast(AIM_SORT_SORT_BY_X + 372), static_cast(AIM_SORT_SORT_BY_Y + 4), + static_cast(AIM_SORT_SORT_BY_X + 372), static_cast(AIM_SORT_SORT_BY_Y + 17)}; UINT8 gubCurrentSortMode; UINT8 gubOldSortMode; diff --git a/Laptop/BobbyR.cpp b/Laptop/BobbyR.cpp index 504ce3032..037295cb8 100644 --- a/Laptop/BobbyR.cpp +++ b/Laptop/BobbyR.cpp @@ -250,11 +250,11 @@ BOOLEAN EnterBobbyR() } //End Dealtar's Airport Externalization. // an array of mouse regions for the bobbies signs. Top Left corner, bottom right corner - UINT16 usMouseRegionPosArray[] = {BOBBIES_USED_SIGN_X, BOBBIES_USED_SIGN_Y, BOBBIES_USED_SIGN_X+BOBBIES_USED_SIGN_WIDTH, BOBBIES_USED_SIGN_Y+BOBBIES_USED_SIGN_HEIGHT, - BOBBIES_MISC_SIGN_X, BOBBIES_MISC_SIGN_Y, BOBBIES_MISC_SIGN_X+BOBBIES_MISC_SIGN_WIDTH, BOBBIES_MISC_SIGN_Y+BOBBIES_MISC_SIGN_HEIGHT, - BOBBIES_GUNS_SIGN_X, BOBBIES_GUNS_SIGN_Y, BOBBIES_GUNS_SIGN_X+BOBBIES_GUNS_SIGN_WIDTH, BOBBIES_GUNS_SIGN_Y+BOBBIES_GUNS_SIGN_HEIGHT, - BOBBIES_AMMO_SIGN_X, BOBBIES_AMMO_SIGN_Y, BOBBIES_AMMO_SIGN_X+BOBBIES_AMMO_SIGN_WIDTH, BOBBIES_AMMO_SIGN_Y+BOBBIES_AMMO_SIGN_HEIGHT, - BOBBIES_ARMOUR_SIGN_X, BOBBIES_ARMOUR_SIGN_Y, BOBBIES_ARMOUR_SIGN_X+BOBBIES_ARMOUR_SIGN_WIDTH, BOBBIES_ARMOUR_SIGN_Y+BOBBIES_ARMOUR_SIGN_HEIGHT}; + UINT16 usMouseRegionPosArray[] = {static_cast(BOBBIES_USED_SIGN_X), static_cast(BOBBIES_USED_SIGN_Y), static_cast(BOBBIES_USED_SIGN_X+BOBBIES_USED_SIGN_WIDTH), static_cast(BOBBIES_USED_SIGN_Y+BOBBIES_USED_SIGN_HEIGHT), + static_cast(BOBBIES_MISC_SIGN_X), static_cast(BOBBIES_MISC_SIGN_Y), static_cast(BOBBIES_MISC_SIGN_X+BOBBIES_MISC_SIGN_WIDTH), static_cast(BOBBIES_MISC_SIGN_Y+BOBBIES_MISC_SIGN_HEIGHT), + static_cast(BOBBIES_GUNS_SIGN_X), static_cast(BOBBIES_GUNS_SIGN_Y), static_cast(BOBBIES_GUNS_SIGN_X+BOBBIES_GUNS_SIGN_WIDTH), static_cast(BOBBIES_GUNS_SIGN_Y+BOBBIES_GUNS_SIGN_HEIGHT), + static_cast(BOBBIES_AMMO_SIGN_X), static_cast(BOBBIES_AMMO_SIGN_Y), static_cast(BOBBIES_AMMO_SIGN_X+BOBBIES_AMMO_SIGN_WIDTH), static_cast(BOBBIES_AMMO_SIGN_Y+BOBBIES_AMMO_SIGN_HEIGHT), + static_cast(BOBBIES_ARMOUR_SIGN_X), static_cast(BOBBIES_ARMOUR_SIGN_Y), static_cast(BOBBIES_ARMOUR_SIGN_X+BOBBIES_ARMOUR_SIGN_WIDTH), static_cast(BOBBIES_ARMOUR_SIGN_Y+BOBBIES_ARMOUR_SIGN_HEIGHT)}; InitBobbyRWoodBackground(); diff --git a/Strategic/strategicmap.cpp b/Strategic/strategicmap.cpp index 32a4cc930..692008aa2 100644 --- a/Strategic/strategicmap.cpp +++ b/Strategic/strategicmap.cpp @@ -6934,22 +6934,22 @@ void HandlePlayerTeamQuotesWhenEnteringSector( INT16 sSectorX, INT16 sSectorY, I ENTER_SECTOR_PLAYER_QUOTE PlayerSectorDescQuote[ NUM_VALID_SECTORS ] = { //SEC_H9-0 - { SECTOR( gGameUBOptions.SectorGuardPostX, gGameUBOptions.SectorGuardPostY ), gGameUBOptions.SectorGuardPostZ, QUOTE_HATED_1_ON_TEAM }, + { SECTOR( gGameUBOptions.SectorGuardPostX, gGameUBOptions.SectorGuardPostY ), static_cast(gGameUBOptions.SectorGuardPostZ), QUOTE_HATED_1_ON_TEAM }, //SEC_I9-0 - { SECTOR( gGameUBOptions.I9SectorPlayerQuoteX, gGameUBOptions.I9SectorPlayerQuoteY ), gGameUBOptions.I9SectorPlayerQuoteZ, QUOTE_LEARNED_TO_HATE_MERC_ON_TEAM }, + { SECTOR( gGameUBOptions.I9SectorPlayerQuoteX, gGameUBOptions.I9SectorPlayerQuoteY ), static_cast(gGameUBOptions.I9SectorPlayerQuoteZ), QUOTE_LEARNED_TO_HATE_MERC_ON_TEAM }, //SEC_H10-0 - { SECTOR( gGameUBOptions.H10SectorPlayerQuoteX, gGameUBOptions.H10SectorPlayerQuoteY ), gGameUBOptions.H10SectorPlayerQuoteZ, QUOTE_LEARNED_TO_HATE_MERC_ON_TEAM }, + { SECTOR( gGameUBOptions.H10SectorPlayerQuoteX, gGameUBOptions.H10SectorPlayerQuoteY ), static_cast(gGameUBOptions.H10SectorPlayerQuoteZ), QUOTE_LEARNED_TO_HATE_MERC_ON_TEAM }, //SEC_I10-0 - { SECTOR( gGameUBOptions.FristSectorTownX, gGameUBOptions.FristSectorTownY ), gGameUBOptions.FristSectorTownZ, QUOTE_HATED_2_ON_TEAM }, + { SECTOR( gGameUBOptions.FristSectorTownX, gGameUBOptions.FristSectorTownY ), static_cast(gGameUBOptions.FristSectorTownZ), QUOTE_HATED_2_ON_TEAM }, //SEC_J13-0 - { SECTOR( gGameUBOptions.SectorFanX, gGameUBOptions.SectorFanY ), gGameUBOptions.SectorFanZ, QUOTE_ENTER_SECTOR_WITH_FAN_1 }, + { SECTOR( gGameUBOptions.SectorFanX, gGameUBOptions.SectorFanY ), static_cast(gGameUBOptions.SectorFanZ), QUOTE_ENTER_SECTOR_WITH_FAN_1 }, //SEC_J14-1 - { SECTOR( gGameUBOptions.SectorGuardPostX, gGameUBOptions.SectorGuardPostY ), gGameUBOptions.ExitForFanToPowerGenSectorZ, 0 }, + { SECTOR( gGameUBOptions.SectorGuardPostX, gGameUBOptions.SectorGuardPostY ), static_cast(gGameUBOptions.ExitForFanToPowerGenSectorZ), 0 }, }; //loop through all the sectors that have the quotes diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 2320ffcd8..85ef12836 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -1704,7 +1704,7 @@ BOOLEAN gfCalcTranslucency = FALSE; INT16 gsFullTileDirections[MAX_FULLTILE_DIRECTIONS] = { - -1, -WORLD_COLS - 1, -WORLD_COLS + -1, static_cast(-WORLD_COLS - 1), static_cast(-WORLD_COLS) }; diff --git a/TacticalAI/AIMain.cpp b/TacticalAI/AIMain.cpp index 2af30ab0b..800f47c35 100644 --- a/TacticalAI/AIMain.cpp +++ b/TacticalAI/AIMain.cpp @@ -1137,7 +1137,7 @@ BOOLEAN DestNotSpokenFor(SOLDIERTYPE *pSoldier, INT32 sGridNo) INT32 FindAdjacentSpotBeside(SOLDIERTYPE *pSoldier, INT32 sGridNo) { INT32 cnt; - INT16 mods[4] = {-1,-WORLD_COLS,1,WORLD_COLS}; + INT16 mods[4] = {-1,static_cast(-WORLD_COLS),1,static_cast(WORLD_COLS)}; INT32 sTempGridNo = NOWHERE, sCheapestDest = MAX_MAP_POS; INT16 sCheapestCost=500, sMovementCost; diff --git a/TileEngine/Isometric Utils.cpp b/TileEngine/Isometric Utils.cpp index f52d0b5d5..af0e98aa6 100644 --- a/TileEngine/Isometric Utils.cpp +++ b/TileEngine/Isometric Utils.cpp @@ -16,14 +16,14 @@ UINT32 guiForceRefreshMousePositionCalculation = 0; // GLOBALS INT16 DirIncrementer[8] = { - -WORLD_COLS, //N - 1-WORLD_COLS, //NE + static_cast(-WORLD_COLS), //N + static_cast(1-WORLD_COLS), //NE 1, //E - 1+WORLD_COLS, //SE - WORLD_COLS, //S - WORLD_COLS-1, //SW + static_cast(1+WORLD_COLS), //SE + static_cast(WORLD_COLS), //S + static_cast(WORLD_COLS-1), //SW -1, //W - -WORLD_COLS-1 //NW + static_cast(-WORLD_COLS-1) //NW }; // Opposite directions diff --git a/sgp/video.cpp b/sgp/video.cpp index bbd93c4b5..1a8cbd741 100644 --- a/sgp/video.cpp +++ b/sgp/video.cpp @@ -1946,7 +1946,7 @@ void RefreshScreen(void *DummyVariable) try { vfs::COpenWriteFile wfile(FileName,true,true); - char head[] = {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, LOBYTE(SCREEN_WIDTH), HIBYTE(SCREEN_WIDTH), LOBYTE(SCREEN_HEIGHT), HIBYTE(SCREEN_HEIGHT), 0x10, 0}; + char head[] = {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, static_cast(LOBYTE(SCREEN_WIDTH)), static_cast(HIBYTE(SCREEN_WIDTH)), static_cast(LOBYTE(SCREEN_HEIGHT)), static_cast(HIBYTE(SCREEN_HEIGHT)), 0x10, 0}; SGP_TRYCATCH_RETHROW(wfile->write(head,18), L""); //