From d1caf3a471164a97272043c80e312b3958a31865 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 6 Jun 2022 15:19:31 +0200 Subject: [PATCH] - made TObjPtr as trivial as possible. Mainly to avoid problems with Raze, but eliminating this constructor lets us catch erroneous local definitions via 'auto', which can cause major problems if left undetected. --- src/common/objects/dobjgc.h | 39 ++++++++++++++++------------ src/g_levellocals.h | 8 +++--- src/g_statusbar/sbar.h | 3 ++- src/playsim/a_action.cpp | 2 +- src/playsim/d_player.h | 16 ++++++------ src/playsim/fragglescript/t_load.cpp | 2 +- src/playsim/p_pspr.cpp | 2 +- src/r_data/r_interpolate.h | 6 ++--- src/sound/s_sndseq.cpp | 6 ++--- 9 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/common/objects/dobjgc.h b/src/common/objects/dobjgc.h index 1fd293263..a1695b8ef 100644 --- a/src/common/objects/dobjgc.h +++ b/src/common/objects/dobjgc.h @@ -180,27 +180,21 @@ class TObjPtr DObject *o; }; public: - TObjPtr() = default; - TObjPtr(const TObjPtr &q) = default; - TObjPtr(T q) noexcept - : pp(q) - { - } - T operator=(T q) + constexpr TObjPtr& operator=(T q) noexcept { pp = q; return *this; } - T operator=(std::nullptr_t nul) + constexpr TObjPtr& operator=(std::nullptr_t nul) noexcept { o = nullptr; return *this; } // To allow NULL, too. - T operator=(const int val) + TObjPtr& operator=(const int val) noexcept { assert(val == 0); o = nullptr; @@ -208,42 +202,42 @@ public: } // To allow NULL, too. In Clang NULL is a long. - T operator=(const long val) + TObjPtr& operator=(const long val) noexcept { assert(val == 0); o = nullptr; return *this; } - T Get() noexcept + constexpr T Get() noexcept { return GC::ReadBarrier(pp); } - T ForceGet() noexcept //for situations where the read barrier needs to be skipped. + constexpr T ForceGet() noexcept //for situations where the read barrier needs to be skipped. { return pp; } - operator T() noexcept + constexpr operator T() noexcept { return GC::ReadBarrier(pp); } - T &operator*() noexcept + constexpr T &operator*() noexcept { T q = GC::ReadBarrier(pp); assert(q != NULL); return *q; } - T operator->() noexcept + constexpr T operator->() noexcept { return GC::ReadBarrier(pp); } - bool operator!=(T u) noexcept + constexpr bool operator!=(T u) noexcept { return GC::ReadBarrier(o) != u; } - bool operator==(T u) noexcept + constexpr bool operator==(T u) noexcept { return GC::ReadBarrier(o) == u; } @@ -255,6 +249,17 @@ public: friend class DObject; }; +// This is only needed because some parts of GCC do not treat a class with any constructor as trivial. +// TObjPtr needs to be fully trivial, though - some parts in the engine depend on it. +template +constexpr TObjPtr MakeObjPtr(T t) noexcept +{ + // since this exists to replace the constructor we cannot initialize in the declaration as this would require the constructor we want to avoid. + TObjPtr tt; + tt = t; + return tt; +} + // Use barrier_cast instead of static_cast when you need to cast // the contents of a TObjPtr to a related type. template inline T barrier_cast(TObjPtr &o) diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 265997f5c..09a2df310 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -540,7 +540,7 @@ public: static const int BODYQUESIZE = 32; TObjPtr bodyque[BODYQUESIZE]; - TObjPtr automap = nullptr; + TObjPtr automap = MakeObjPtr(nullptr); int bodyqueslot; // For now this merely points to the global player array, but with this in place, access to this array can be moved over to the level. @@ -690,10 +690,10 @@ public: // links to global game objects TArray> CorpseQueue; - TObjPtr FraggleScriptThinker = nullptr; - TObjPtr ACSThinker = nullptr; + TObjPtr FraggleScriptThinker = MakeObjPtr(nullptr); + TObjPtr ACSThinker = MakeObjPtr(nullptr); - TObjPtr SpotState = nullptr; + TObjPtr SpotState = MakeObjPtr(nullptr); //========================================================================== // diff --git a/src/g_statusbar/sbar.h b/src/g_statusbar/sbar.h index 85fd62305..278f6d923 100644 --- a/src/g_statusbar/sbar.h +++ b/src/g_statusbar/sbar.h @@ -84,7 +84,8 @@ public: void CallDraw(int bottom, int visibility); private: - TObjPtr Next = nullptr; + TObjPtr Next = MakeObjPtr(nullptr); +; uint32_t SBarID = 0; friend class DBaseStatusBar; diff --git a/src/playsim/a_action.cpp b/src/playsim/a_action.cpp index 63fca0ece..d9f53903d 100644 --- a/src/playsim/a_action.cpp +++ b/src/playsim/a_action.cpp @@ -104,7 +104,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_QueueCorpse) if (corpse) corpse->Destroy(); corpsequeue.Delete(0); } - corpsequeue.Push(self); + corpsequeue.Push(MakeObjPtr(self)); GC::WriteBarrier(self); } return 0; diff --git a/src/playsim/d_player.h b/src/playsim/d_player.h index 5f5c8866e..bbc440ac4 100644 --- a/src/playsim/d_player.h +++ b/src/playsim/d_player.h @@ -340,7 +340,7 @@ public: AActor *ReadyWeapon = nullptr; AActor *PendingWeapon = nullptr; // WP_NOCHANGE if not changing - TObjPtr psprites = nullptr; // view sprites (gun, etc) + TObjPtr psprites = MakeObjPtr(nullptr); // view sprites (gun, etc) int cheats = 0; // bit flags int timefreezer = 0; // Player has an active time freezer @@ -355,8 +355,8 @@ public: int poisoncount = 0; // screen flash for poison damage FName poisontype = NAME_None; // type of poison damage to apply FName poisonpaintype = NAME_None; // type of Pain state to enter for poison damage - TObjPtr poisoner = nullptr; // NULL for non-player actors - TObjPtr attacker = nullptr; // who did damage (NULL for floors) + TObjPtr poisoner = MakeObjPtr(nullptr); // NULL for non-player actors + TObjPtr attacker = MakeObjPtr(nullptr); // who did damage (NULL for floors) int extralight = 0; // so gun flashes light up areas short fixedcolormap = 0; // can be set to REDCOLORMAP, etc. short fixedlightlevel = 0; @@ -364,19 +364,19 @@ public: PClassActor *MorphedPlayerClass = nullptr; // [MH] (for SBARINFO) class # for this player instance when morphed int MorphStyle = 0; // which effects to apply for this player instance when morphed PClassActor *MorphExitFlash = nullptr; // flash to apply when demorphing (cache of value given to MorphPlayer) - TObjPtr PremorphWeapon = nullptr; // ready weapon before morphing + TObjPtr PremorphWeapon = MakeObjPtr(nullptr); // ready weapon before morphing int chickenPeck = 0; // chicken peck countdown int jumpTics = 0; // delay the next jump for a moment bool onground = 0; // Identifies if this player is on the ground or other object int respawn_time = 0; // [RH] delay respawning until this tic - TObjPtr camera = nullptr; // [RH] Whose eyes this player sees through + TObjPtr camera = MakeObjPtr(nullptr); // [RH] Whose eyes this player sees through int air_finished = 0; // [RH] Time when you start drowning FName LastDamageType = NAME_None; // [RH] For damage-specific pain and death sounds - TObjPtr MUSINFOactor = nullptr; // For MUSINFO purposes + TObjPtr MUSINFOactor = MakeObjPtr(nullptr); // For MUSINFO purposes int8_t MUSINFOtics = 0; bool settings_controller = false; // Player can control game settings. @@ -384,7 +384,7 @@ public: int8_t crouchdir = 0; //Added by MC: - TObjPtr Bot = nullptr; + TObjPtr Bot = MakeObjPtr(nullptr); float BlendR = 0; // [RH] Final blending values float BlendG = 0; @@ -406,7 +406,7 @@ public: FWeaponSlots weapons; // [CW] I moved these here for multiplayer conversation support. - TObjPtr ConversationNPC = nullptr, ConversationPC = nullptr; + TObjPtr ConversationNPC = MakeObjPtr(nullptr), ConversationPC = MakeObjPtr(nullptr); DAngle ConversationNPCAngle = 0.; bool ConversationFaceTalker = false; diff --git a/src/playsim/fragglescript/t_load.cpp b/src/playsim/fragglescript/t_load.cpp index dd7ddd815..efd27a070 100644 --- a/src/playsim/fragglescript/t_load.cpp +++ b/src/playsim/fragglescript/t_load.cpp @@ -315,6 +315,6 @@ void T_AddSpawnedThing(FLevelLocals *Level, AActor * ac) if (Level->FraggleScriptThinker) { auto &SpawnedThings = Level->FraggleScriptThinker->SpawnedThings; - SpawnedThings.Push(GC::ReadBarrier(ac)); + SpawnedThings.Push(MakeObjPtr(ac)); } } diff --git a/src/playsim/p_pspr.cpp b/src/playsim/p_pspr.cpp index 6f57fb6d4..eb9f351cb 100644 --- a/src/playsim/p_pspr.cpp +++ b/src/playsim/p_pspr.cpp @@ -173,7 +173,6 @@ DPSprite::DPSprite(player_t *owner, AActor *caller, int id) Tics(0), Translation(0), Flags(0), - Caller(caller), Owner(owner), State(nullptr), Sprite(0), @@ -181,6 +180,7 @@ DPSprite::DPSprite(player_t *owner, AActor *caller, int id) ID(id), processPending(true) { + Caller = caller; baseScale = {1.0, 1.2}; rotation = 0.; scale = {1.0, 1.0}; diff --git a/src/r_data/r_interpolate.h b/src/r_data/r_interpolate.h index 888f387c5..29f3f56df 100644 --- a/src/r_data/r_interpolate.h +++ b/src/r_data/r_interpolate.h @@ -17,8 +17,8 @@ class DInterpolation : public DObject DECLARE_ABSTRACT_CLASS(DInterpolation, DObject) HAS_OBJECT_POINTERS - TObjPtr Next = nullptr; - TObjPtr Prev = nullptr; + TObjPtr Next; + TObjPtr Prev; protected: FLevelLocals *Level; @@ -46,7 +46,7 @@ public: struct FInterpolator { - TObjPtr Head = nullptr; + TObjPtr Head = MakeObjPtr(nullptr); bool didInterp = false; int count = 0; diff --git a/src/sound/s_sndseq.cpp b/src/sound/s_sndseq.cpp index ed82d8a57..9182575da 100644 --- a/src/sound/s_sndseq.cpp +++ b/src/sound/s_sndseq.cpp @@ -832,10 +832,10 @@ void DSeqNode::ActivateSequence (int sequence) m_Atten = ATTN_IDLE; // ...and idle attenuation } -DSeqActorNode::DSeqActorNode (AActor *actor, int sequence, int modenum) - : DSeqNode (actor->Level, sequence, modenum), - m_Actor (actor) +DSeqActorNode::DSeqActorNode(AActor* actor, int sequence, int modenum) + : DSeqNode(actor->Level, sequence, modenum) { + m_Actor = actor; } DSeqPolyNode::DSeqPolyNode (FPolyObj *poly, int sequence, int modenum)