Conversation
Enables /std:c++20 (LanguageStandard=stdcpp20) for the Client (Swarm), Server (Swarm) and missionchooser projects in every build configuration, and fixes every error the switch surfaces. No compiler conformance switch was relaxed: neither /Zc:twoPhase- nor /Zc:strictStrings- was added. Where the legacy code relied on a macro workaround (clamp in mathlib.h), the workaround was removed and the code fixed instead. Process: complete build logs were collected per project in parallel so that a failure in one project did not hide diagnostics in the others; errors were grouped by root cause rather than by file; and each batch was followed by a rebuild of every affected configuration. Every edit was dry-run verified with occurrence-count checks, preserving existing source encodings (including the Windows-1252 files in parts of the tree). 167 files changed: 164 sources and the 3 project files. 1. Two-phase lookup and dependent base classes: C3861/C2065 for Base, Count, m_Size, GetTypeName, log10, CopyArray and others, plus C2027 for incomplete types. Fixed with this->, explicit declarations, missing math/KeyValues includes and out-of-line definitions, in about 20 files, mostly headers. The Debug configuration additionally required this-> where Assert and #ifdef _DEBUG compile the call out in Release (utllinkedlist.h, utlobjectreference.h, ai_speech.h). 2. concept is a C++20 keyword: used as an identifier in the AI speech code, it produced C2059/C2143 and a cascade of about 31,000 diagnostics in a single project build. Renamed 216 identifiers from concept to conceptName across 20 files, skipping comments and string literals. 3. clamp macro vs std::clamp: the legacy macro in mathlib.h corrupted <algorithm> (C2059/C2988) with large translation-unit cascades. Removed the macro and generalized the basetypes.h clamp template to three parameter types with explicit result conversion. 4. Strict string literals: about 3,000 C2440/C2664 diagnostics. Made the datatable API const-correct (dt_recv, dt_send, dt_utlvector_recv, dt_utlvector_send, ClientClass, ServerClass, recvproxy, sendproxy), which fixes the RECVINFO/SENDINFO macro call sites without touching the tables, and fixed about 60 further sites. Several of those are parameter changes, not call sites: UTIL_ImpactTrace and CBaseEntity::ImpactTrace including its overrides, SetSuitUpdate, UTIL_LogPrintf, GetTotalAmmoCount, CDescription::InitFromFile, UTIL_va, SetStatsFilename, AddGlobalFlexController, LoadHudTextures, and IMatSystemSurface DrawColoredText, DrawColoredTextRect, DrawTextHeight and DrawTextLen in IMatSystemSurface.h and IMatSystemSurfaceV5.h. The Debug-only name parameters of CBaseEntity::TouchSet, UseSet and BlockedSet were made const char* as well. 5. false is not a null pointer constant: conformance mode now enforces the C++11 rule, so bool to pointer conversions are rejected. Fixed chunkfile.cpp return(false) -> return(NULL) and a misplaced EmitSound argument. For that call the missing argument is supplied as an explicit NULL instead of casting the attenuation to soundlevel_t, which would silently select the other overload and change the attenuation. 6. C++20 rewritten comparison candidates: fixed C2666/C2593/C2445 for CUtlSymbol, DHANDLE, CUtlReference and CHandle with explicit IsValid()/Get() and casts for ScriptVariant_t. 7. Temporaries cannot bind to non-const references: fixed C2665/C2664 in VectorNormalize, Tracer_Draw, MeleeAttack, SetMoveTarget, FindSnowVolumes, FX_MicroExplosion, ReadParticleConfigFile and GetParticleSystemsInBuffer by introducing local Vector, QAngle and CUtlBuffer variables. 8. Other conformance errors: C2216 friend static, C4596 qualified member declarations inside a class body, C2362 goto crossing an initialization, C2614 dependent-base injected-class-name in a mem-initializer, and a use before declaration in UtlCachedFileData.h (CSortedCacheFile was used near line 715 and defined near line 965). 9. Explicit specializations of class template members are not implicitly inline and legacy MSVC folded the duplicates: fixed LNK2005/LNK1169 by marking the four ITilegenClassFactory<T>::ReadLiteralValue specializations and C_SpatialEntityTemplate<Vector>::ResetAccumulation inline. MaterialSystemUtil.h was intentionally left at char *pStrOptionalName: MaterialSystemUtil.cpp belongs to none of the three projects and its implementation is provided by the prebuilt engine, so const char * produced LNK2001. The affected call sites use explicit casts instead. Review notes: the changes are intended to be behaviour preserving, conformance and const-correctness only, with explicit casts in a few read-only legacy interfaces. Everything that only affects Debug is gated by Assert or #ifdef _DEBUG, so the Release binaries are unaffected. The build still emits warnings (3,161 in Release, 3,249 in Debug) and the projects do not use /WX. Runtime validation covered one solo map in each build only; no multiplayer or campaign-wide regression run was performed. Verified with: MSBuild src\reactivedrop_vs13.sln /t:Rebuild for Release|Win32 and Debug|Win32 - 0 errors in both; client.dll, server.dll and missionchooser.dll produced for each. Both the Release and the Debug DLLs were then swapped into the game installation and a smoke test was played on one solo map.
Contributor
|
Most changes (all except |
Kitsune44
marked this pull request as draft
September 28, 2026 02:09
Kitsune44
force-pushed
the
cpp20-build_warnings
branch
2 times, most recently
from
September 28, 2026 03:48
34ec40c to
6c12199
Compare
The migration added (char *) and (wchar_t *) casts on string literals. This change removes twelve of them, either by making a local const or by const-correcting a whole in-repo call chain, and it adds no new cast: 1. asw_hud_3dmarinenames.cpp: IMatSystemSurface::DrawColoredText and DrawColoredTextRect already take a const char *fmt, so the two casts on those literals were redundant. 2. vhybridbutton.cpp and objectivetitlepanel.cpp: declare the wide-string locals const wchar_t * instead of casting L"" back to wchar_t *. ILocalize::Find returns wchar_t *, so adding const to the local is free, and ConvertUnicodeToANSI and ConstructString already accept const wchar_t *. 3. CNPC_BaseScanner::GetEngineSound and GetScannerSoundPrefix (npc_basescanner.h, npc_scanner.h/.cpp): the only call sites are CSoundEnvelopeController::SoundCreate, which takes const char *, and a sprintf. Both classes live in the server binary, so the return type is changed for the whole chain. 4. CBaseCombatWeapon::GetDeathNoticeName (basecombatweapon_shared.h, basecombatweapon_shared.cpp): its only caller already keeps the result in a const char *. 5. C_BaseEntity tesla effect data (fx.h, fx.cpp): m_pszSpriteName is only ever read, its consumer FX_BuildTesla already takes const char *, and its other producer is a char[256] member. Deliberately not touched, because each would move a cast rather than remove it, or would const-correct only half of a contract whose boundary stays mutable: - keyframe.cpp keeps TimeModifier_t::szName and RotationInterpolator_t::szName as char *. IPositionInterpolator:: GetDetails and Motion_Get*Details hand out a mutable char * through char ** outName, so making the fields const would only push the cast from the table initialisers to the output assignment. - studiohdr_t::pszNodeName and the Motion_Get*Details helpers keep char *: they have no caller in this tree, so they are exported entry points and a signature change would change the mangled name, the same class of breakage as MaterialSystemUtil.cpp, which is not built here either. - IHudTextMessage::LookupString keeps char *: it hands out a writable pointer and asw_hud_chat.cpp strips newlines in place. - IVTex::VTex(int, char **) is argv-style, so its arguments may be written to; the fix there is a writable buffer, not a cast. - ReadAndAllocStringValue returns caller-owned memory, so its char * return type is deliberate; its failure path returning a literal is a separate ownership issue. - CSplitString stores char * elements by design and is implemented outside this tree. - CTextureReference::InitRenderTarget and friends keep char *: their implementation is in the prebuilt engine, so const char * there produced LNK2001. No behaviour change: every signature changed here is only read from, and every removed cast re-created exactly the expression that replaced it. Verified with: MSBuild for the client and server projects in Release|Win32, Debug|Win32 and Profile|Win32 - 0 errors in all six.
Kitsune44
force-pushed
the
cpp20-build_warnings
branch
from
September 28, 2026 04:22
6c12199 to
601fe6f
Compare
Kitsune44
marked this pull request as ready for review
September 28, 2026 04:36
Kitsune44
marked this pull request as draft
September 28, 2026 04:36
Kitsune44
force-pushed
the
cpp20-build_warnings
branch
from
September 28, 2026 06:05
601fe6f to
2358711
Compare
The C++20 migration extracted a named local for every temporary that had to bind to a non-const reference. All of those parameters are ours and are only read, so the fix belongs in the signatures instead, and callers can pass vector and angle arithmetic directly again. - Tracer_Draw (c_tracer.h, c_tracer.cpp): both overloads take const Vector& start and const Vector& delta. The function forwards them to Tracer_ComputeVerts, which already takes them by const reference, so the non-const parameters contradicted the line below. - CSnowFallManager::FindSnowVolumes (c_effects.cpp): vecEyePos is only read, so it is const Vector& now. - CASW_Simple_Alien::SetMoveTarget (asw_simple_alien.h, asw_simple_alien.cpp): it only stores the value, so it is const Vector& now. TryMove and ApplyGravity keep Vector& because they modify their argument. - The melee helpers CASW_Drone_Advanced::MeleeAttack, CASW_Shieldbug::MeleeAttack and CASW_Simple_Alien::MeleeAttack (three independent class hierarchies) take const QAngle& viewPunch and const Vector& shove now. Their bodies only read both, through ViewPunch() and the shove components. Six call sites lose their QAngle/Vector locals. - FX_MicroExplosion (fx.h, fx_sparks.cpp): const Vector& for both parameters. It only reads them, and the address it passes on goes to a Setup() that already takes const Vector*. - asw_broadcast_camera.cpp no longer extracts a vector just to feed the normalising VectorNormalize(Vector&): the call uses VectorLength(), which takes a const reference. VectorNormalize returned v.Length(), and Vector::Length() is literally VectorLength( *this ), while the normalised vector was never read again, so the value is identical. The extracted locals are gone from all fourteen call sites, and the calls pass the arithmetic directly again. Left alone, because a signature change is not the fix there: IParticleSystemMgr::ReadParticleConfigFile and GetParticleSystemsInBuffer take CUtlBuffer& because parsing consumes the buffer, and that interface is implemented by the engine (declared in public/particles/particles.h, with no implementation in this tree), so the two locals in entity_client_tools.cpp are correct as they are. No behaviour change: every parameter that became const is only read, and the restored call expressions are exactly the ones the migration replaced. Verified with: MSBuild for the client and server projects in Release|Win32 - 0 errors in both.
Reduces the warning count of src/reactivedrop_vs13.sln from 3,249
lines in Debug|Win32 (17 codes, 824 distinct file:line sites) and
3,161 in Release|Win32 to 5 in both configurations, all of them the
C5205 uses documented at the end. The projects keep /W4, do not use
/WX, and no warning was disabled, no pragma added and no conformance
switch relaxed. Every edit is behaviour preserving.
Warnings were fixed at their root cause where one existed, so that a
single declaration or macro covers hundreds of sites, and with an
explicit conversion or a scope-local rename otherwise. Edits preserved
the existing file encodings (parts of the tree are Windows-1252) and
BOMs. A rebuild followed every batch, so that a regression could not
hide behind an unrelated diagnostic, and both configurations were
finally rebuilt from scratch.
The groups, in descending order of size:
1. C5054 (1,868 occurrences / 642 sites), comparisons between two
different enumeration types, which C++20 deprecates. Three causes:
- Classify() returns Class_T while the entity classes of this mod
(CLASS_ASW_*, CLASS_FUNC_*) are a separate anonymous enum that
continues the Class_T numbering from LAST_SHARED_ENTITY_CLASS.
The enum is now named ASW_Class_T and the intended comparison with
Class_T is stated once, as four inline ==/!= operators, instead of
converting roughly 585 call sites.
- ASW_COLLISION_GROUP_* continues Collision_Group_t and
SHOULD_COLLIDE()/ASSERT_INVARIANT() compare the two numberings
with <=. Those assertions now compare (int) values.
- Six further sites (the COMPILE_TIME_ASSERT of bits_BUILD_* against
bits_CAP_MOVE_*, MAX( ASW_NUM_EQUIP_* ), two shadow flag bitmasks
and MB_FIELD_TEXCOORD_LAST) take an explicit conversion.
2. C4471 (1,150 / 12), forward declarations of unscoped enumerations
without an underlying type: they now name : int, and the two enums
that could be defined before their declaration (ASW_Skill,
RD_Crafting_Material_t) received the same fixed type in their
definition, so declaration order no longer matters. The unused
DXGI_FORMAT forward declaration in bitmap/imageformat.h was removed:
nothing in the tree refers to it and the DXGI headers define it
without an explicit underlying type, so any fixed type would
conflict with them.
3. C4456/C4457/C4458/C4459 (112), shadowing of class members, globals,
parameters and enclosing locals. The shadowing declaration was
renamed inside its own scope only (index -> iIndex, view ->
viewSetup, effects -> nEffects, flags -> nFlags, model -> pModel,
pRenderContext -> pRenderCtx, ...), leaving access to members and
statements preceding the declaration untouched. One of the 112 was
not renamed but removed: the inner declaration in
CNPC_AttackHelicopter::Event_Killed re-fetched
CSoundEnvelopeController::GetController(), a side-effect-free
accessor that returns a reference to a file-static singleton
(soundenvelope.cpp). The same object was therefore already in scope
and the second declaration was redundant by construction. Every other
case either declares a fresh object (a buffer, an RAII guard, a
re-initialised local) or re-reads a value that is only incidentally
identical, and keeps the rename. The five reports in
CShadowDepthView::Draw come from VPROF_BUDGET() declaring a fixed
local name, so nesting a budget inside the braces of an enclosing
budget shadowed the outer scope object; the macro now uses the
existing UNIQUE_ID.
4. C4864 (56 / 2), a dependent template name used without the template
keyword in CSOAAttributeReference::operator=.
5. C5055 (21), enumeration constants used in floating point arithmetic,
now converted to float explicitly.
6. The single groups: C5033 (register), C4189 (locals that are dead, or
referenced by Assert() only in a release build), C4211 (command
callbacks that a friend declaration introduces with external linkage
now use CON_COMMAND_EXTERN_F), C4005 (INVALID_HANDLE_VALUE is left
to the platform headers on Windows and the duplicate ALIGN_VALUE in
video_material.cpp is dropped), C4018, C4706, C4554 (parentheses
only, the existing evaluation order is kept), C4463 (a 1-bit signed
bit-field is made unsigned) and the release-only C4756, where
HUGE_VAL becomes std::numeric_limits<float>::infinity(): the same
+inf value, but it does not overflow while the LTCG code generator
folds the constant.
Not fixed: the five C5205 reports in asw_util_shared.cpp,
video_material.cpp and optionssubmultiplayer.cpp. IVguiMatInfo,
IVguiMatInfoVar and IDirectSoundBuffer are abstract interfaces
implemented outside this solution (the VGUI surface of the prebuilt
material system and the DirectSound SDK), and IVguiMatInfo.h explicitly
asks the caller to delete the object. Adding a virtual destructor would
change the vtable of an interface whose implementation is not rebuilt
here, and replacing the delete with a release call would change
ownership semantics, so both are worse than the diagnostic.
Verified with: MSBuild src\reactivedrop_vs13.sln /t:Rebuild for
Debug|Win32 and Release|Win32 - 0 errors in both, 5 warnings in both,
all of them C5205; client.dll, server.dll and missionchooser.dll
produced for each configuration. Both the Release and the Debug DLLs
were then swapped into the game installation and a smoke test was
played on one solo map.
Kitsune44
force-pushed
the
cpp20-build_warnings
branch
from
September 28, 2026 07:35
2358711 to
474cdc9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Eliminate level-4 warnings
Reduces the warning count of src/reactivedrop_vs13.sln from 3,249 lines in Debug|Win32 (17 codes, 824 distinct file:line sites) and 3,161 in Release|Win32 to 5 in both configurations, all of them the C5205 uses documented at the end. The projects keep /W4, do not use /WX, and no warning was disabled, no pragma added and no conformance switch relaxed. Every edit is behaviour preserving.
Warnings were fixed at their root cause where one existed, so that a single declaration or macro covers hundreds of sites, and with an explicit conversion or a scope-local rename otherwise. Edits preserved the existing file encodings (parts of the tree are Windows-1252) and BOMs. A rebuild followed every batch, so that a regression could not hide behind an unrelated diagnostic, and both configurations were finally rebuilt from scratch.
The groups, in descending order of size
C5054 (1,868 occurrences / 642 sites), comparisons between two different enumeration types, which C++20 deprecates. Three causes:
Classify() returns Class_T while the entity classes of this mod (CLASS_ASW_, CLASS_FUNC_) are a separate anonymous enum that continues the Class_T numbering from LAST_SHARED_ENTITY_CLASS. The enum is now named ASW_Class_T and the intended comparison with Class_T is stated once, as four inline ==/!= operators, instead of converting roughly 585 call sites.
ASW_COLLISION_GROUP_* continues Collision_Group_t and SHOULD_COLLIDE()/ASSERT_INVARIANT() compare the two numberings with <=. Those assertions now compare (int) values.
Six further sites (the COMPILE_TIME_ASSERT of bits_BUILD_* against bits_CAP_MOVE_, MAX( ASW_NUM_EQUIP_ ), two shadow flag bitmasks and MB_FIELD_TEXCOORD_LAST) take an explicit conversion.
C4471 (1,150 / 12), forward declarations of unscoped enumerations without an underlying type: they now name : int, and the two enums that could be defined before their declaration (ASW_Skill, RD_Crafting_Material_t) received the same fixed type in their definition, so declaration order no longer matters. The unused DXGI_FORMAT forward declaration in bitmap/imageformat.h was removed: nothing in the tree refers to it and the DXGI headers define it without an explicit underlying type, so any fixed type would conflict with them.
C4456/C4457/C4458/C4459 (112), shadowing of class members, globals, parameters and enclosing locals. The shadowing declaration was renamed inside its own scope only (index -> iIndex, view -> viewSetup, effects -> nEffects, flags -> nFlags, model -> pModel, pRenderContext -> pRenderCtx, ...), leaving access to members and statements preceding the declaration untouched. The five reports in CShadowDepthView::Draw come from VPROF_BUDGET() declaring a fixed local name, so nesting a budget inside the braces of an enclosing budget shadowed the outer scope object; the macro now uses the existing UNIQUE_ID.
C4864 (56 / 2), a dependent template name used without the template keyword in CSOAAttributeReference::operator=.
C5055 (21), enumeration constants used in floating point arithmetic, now converted to float explicitly.
The single groups: C5033 (register), C4189 (locals that are dead, or referenced by Assert() only in a release build), C4211 (command callbacks that a friend declaration introduces with external linkage now use CON_COMMAND_EXTERN_F), C4005 (INVALID_HANDLE_VALUE is left to the platform headers on Windows and the duplicate ALIGN_VALUE in video_material.cpp is dropped), C4018, C4706, C4554 (parentheses only, the existing evaluation order is kept), C4463 (a 1-bit signed bit-field is made unsigned) and the release-only C4756, where HUGE_VAL becomes std::numeric_limits::infinity(): the same +inf value, but it does not overflow while the LTCG code generator folds the constant.
Not fixed: the five C5205 reports in asw_util_shared.cpp, video_material.cpp and optionssubmultiplayer.cpp. IVguiMatInfo, IVguiMatInfoVar and IDirectSoundBuffer are abstract interfaces implemented outside this solution (the VGUI surface of the prebuilt material system and the DirectSound SDK), and IVguiMatInfo.h explicitly asks the caller to delete the object. Adding a virtual destructor would change the vtable of an interface whose implementation is not rebuilt here, and replacing the delete with a release call would change ownership semantics, so both are worse than the diagnostic.