diff --git a/src/common/objects/dobjgc.h b/src/common/objects/dobjgc.h index 1fd2932631..a1695b8efa 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 265997f5ca..09a2df310f 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 85fd623055..278f6d9236 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 63fca0ecef..d9f53903d8 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 5f5c8866e3..bbc440ac4d 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 dd7ddd8158..efd27a070d 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 6f57fb6d4e..eb9f351cb2 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 888f387c51..29f3f56dfa 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 ed82d8a571..9182575dad 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)