- 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.
This commit is contained in:
Christoph Oelckers 2022-06-06 15:19:31 +02:00
parent 71ce8aa79a
commit d1caf3a471
9 changed files with 45 additions and 39 deletions

View file

@ -180,27 +180,21 @@ class TObjPtr
DObject *o; DObject *o;
}; };
public: public:
TObjPtr() = default;
TObjPtr(const TObjPtr<T> &q) = default;
TObjPtr(T q) noexcept constexpr TObjPtr<T>& operator=(T q) noexcept
: pp(q)
{
}
T operator=(T q)
{ {
pp = q; pp = q;
return *this; return *this;
} }
T operator=(std::nullptr_t nul) constexpr TObjPtr<T>& operator=(std::nullptr_t nul) noexcept
{ {
o = nullptr; o = nullptr;
return *this; return *this;
} }
// To allow NULL, too. // To allow NULL, too.
T operator=(const int val) TObjPtr<T>& operator=(const int val) noexcept
{ {
assert(val == 0); assert(val == 0);
o = nullptr; o = nullptr;
@ -208,42 +202,42 @@ public:
} }
// To allow NULL, too. In Clang NULL is a long. // To allow NULL, too. In Clang NULL is a long.
T operator=(const long val) TObjPtr<T>& operator=(const long val) noexcept
{ {
assert(val == 0); assert(val == 0);
o = nullptr; o = nullptr;
return *this; return *this;
} }
T Get() noexcept constexpr T Get() noexcept
{ {
return GC::ReadBarrier(pp); 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; return pp;
} }
operator T() noexcept constexpr operator T() noexcept
{ {
return GC::ReadBarrier(pp); return GC::ReadBarrier(pp);
} }
T &operator*() noexcept constexpr T &operator*() noexcept
{ {
T q = GC::ReadBarrier(pp); T q = GC::ReadBarrier(pp);
assert(q != NULL); assert(q != NULL);
return *q; return *q;
} }
T operator->() noexcept constexpr T operator->() noexcept
{ {
return GC::ReadBarrier(pp); return GC::ReadBarrier(pp);
} }
bool operator!=(T u) noexcept constexpr bool operator!=(T u) noexcept
{ {
return GC::ReadBarrier(o) != u; return GC::ReadBarrier(o) != u;
} }
bool operator==(T u) noexcept constexpr bool operator==(T u) noexcept
{ {
return GC::ReadBarrier(o) == u; return GC::ReadBarrier(o) == u;
} }
@ -255,6 +249,17 @@ public:
friend class DObject; 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<class T>
constexpr TObjPtr<T> 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<T> tt;
tt = t;
return tt;
}
// Use barrier_cast instead of static_cast when you need to cast // Use barrier_cast instead of static_cast when you need to cast
// the contents of a TObjPtr to a related type. // the contents of a TObjPtr to a related type.
template<class T,class U> inline T barrier_cast(TObjPtr<U> &o) template<class T,class U> inline T barrier_cast(TObjPtr<U> &o)

View file

@ -540,7 +540,7 @@ public:
static const int BODYQUESIZE = 32; static const int BODYQUESIZE = 32;
TObjPtr<AActor*> bodyque[BODYQUESIZE]; TObjPtr<AActor*> bodyque[BODYQUESIZE];
TObjPtr<DAutomapBase*> automap = nullptr; TObjPtr<DAutomapBase*> automap = MakeObjPtr<DAutomapBase*>(nullptr);
int bodyqueslot; 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. // 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 // links to global game objects
TArray<TObjPtr<AActor *>> CorpseQueue; TArray<TObjPtr<AActor *>> CorpseQueue;
TObjPtr<DFraggleThinker *> FraggleScriptThinker = nullptr; TObjPtr<DFraggleThinker *> FraggleScriptThinker = MakeObjPtr<DFraggleThinker*>(nullptr);
TObjPtr<DACSThinker*> ACSThinker = nullptr; TObjPtr<DACSThinker*> ACSThinker = MakeObjPtr<DACSThinker*>(nullptr);
TObjPtr<DSpotState *> SpotState = nullptr; TObjPtr<DSpotState *> SpotState = MakeObjPtr<DSpotState*>(nullptr);
//========================================================================== //==========================================================================
// //

View file

@ -84,7 +84,8 @@ public:
void CallDraw(int bottom, int visibility); void CallDraw(int bottom, int visibility);
private: private:
TObjPtr<DHUDMessageBase*> Next = nullptr; TObjPtr<DHUDMessageBase*> Next = MakeObjPtr<DHUDMessageBase*>(nullptr);
;
uint32_t SBarID = 0; uint32_t SBarID = 0;
friend class DBaseStatusBar; friend class DBaseStatusBar;

View file

@ -104,7 +104,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_QueueCorpse)
if (corpse) corpse->Destroy(); if (corpse) corpse->Destroy();
corpsequeue.Delete(0); corpsequeue.Delete(0);
} }
corpsequeue.Push(self); corpsequeue.Push(MakeObjPtr<AActor*>(self));
GC::WriteBarrier(self); GC::WriteBarrier(self);
} }
return 0; return 0;

View file

@ -340,7 +340,7 @@ public:
AActor *ReadyWeapon = nullptr; AActor *ReadyWeapon = nullptr;
AActor *PendingWeapon = nullptr; // WP_NOCHANGE if not changing AActor *PendingWeapon = nullptr; // WP_NOCHANGE if not changing
TObjPtr<DPSprite*> psprites = nullptr; // view sprites (gun, etc) TObjPtr<DPSprite*> psprites = MakeObjPtr<DPSprite*>(nullptr); // view sprites (gun, etc)
int cheats = 0; // bit flags int cheats = 0; // bit flags
int timefreezer = 0; // Player has an active time freezer int timefreezer = 0; // Player has an active time freezer
@ -355,8 +355,8 @@ public:
int poisoncount = 0; // screen flash for poison damage int poisoncount = 0; // screen flash for poison damage
FName poisontype = NAME_None; // type of poison damage to apply FName poisontype = NAME_None; // type of poison damage to apply
FName poisonpaintype = NAME_None; // type of Pain state to enter for poison damage FName poisonpaintype = NAME_None; // type of Pain state to enter for poison damage
TObjPtr<AActor*> poisoner = nullptr; // NULL for non-player actors TObjPtr<AActor*> poisoner = MakeObjPtr<AActor*>(nullptr); // NULL for non-player actors
TObjPtr<AActor*> attacker = nullptr; // who did damage (NULL for floors) TObjPtr<AActor*> attacker = MakeObjPtr<AActor*>(nullptr); // who did damage (NULL for floors)
int extralight = 0; // so gun flashes light up areas int extralight = 0; // so gun flashes light up areas
short fixedcolormap = 0; // can be set to REDCOLORMAP, etc. short fixedcolormap = 0; // can be set to REDCOLORMAP, etc.
short fixedlightlevel = 0; short fixedlightlevel = 0;
@ -364,19 +364,19 @@ public:
PClassActor *MorphedPlayerClass = nullptr; // [MH] (for SBARINFO) class # for this player instance when morphed 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 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) PClassActor *MorphExitFlash = nullptr; // flash to apply when demorphing (cache of value given to MorphPlayer)
TObjPtr<AActor*> PremorphWeapon = nullptr; // ready weapon before morphing TObjPtr<AActor*> PremorphWeapon = MakeObjPtr<AActor*>(nullptr); // ready weapon before morphing
int chickenPeck = 0; // chicken peck countdown int chickenPeck = 0; // chicken peck countdown
int jumpTics = 0; // delay the next jump for a moment int jumpTics = 0; // delay the next jump for a moment
bool onground = 0; // Identifies if this player is on the ground or other object bool onground = 0; // Identifies if this player is on the ground or other object
int respawn_time = 0; // [RH] delay respawning until this tic int respawn_time = 0; // [RH] delay respawning until this tic
TObjPtr<AActor*> camera = nullptr; // [RH] Whose eyes this player sees through TObjPtr<AActor*> camera = MakeObjPtr<AActor*>(nullptr); // [RH] Whose eyes this player sees through
int air_finished = 0; // [RH] Time when you start drowning int air_finished = 0; // [RH] Time when you start drowning
FName LastDamageType = NAME_None; // [RH] For damage-specific pain and death sounds FName LastDamageType = NAME_None; // [RH] For damage-specific pain and death sounds
TObjPtr<AActor*> MUSINFOactor = nullptr; // For MUSINFO purposes TObjPtr<AActor*> MUSINFOactor = MakeObjPtr<AActor*>(nullptr); // For MUSINFO purposes
int8_t MUSINFOtics = 0; int8_t MUSINFOtics = 0;
bool settings_controller = false; // Player can control game settings. bool settings_controller = false; // Player can control game settings.
@ -384,7 +384,7 @@ public:
int8_t crouchdir = 0; int8_t crouchdir = 0;
//Added by MC: //Added by MC:
TObjPtr<DBot*> Bot = nullptr; TObjPtr<DBot*> Bot = MakeObjPtr<DBot*>(nullptr);
float BlendR = 0; // [RH] Final blending values float BlendR = 0; // [RH] Final blending values
float BlendG = 0; float BlendG = 0;
@ -406,7 +406,7 @@ public:
FWeaponSlots weapons; FWeaponSlots weapons;
// [CW] I moved these here for multiplayer conversation support. // [CW] I moved these here for multiplayer conversation support.
TObjPtr<AActor*> ConversationNPC = nullptr, ConversationPC = nullptr; TObjPtr<AActor*> ConversationNPC = MakeObjPtr<AActor*>(nullptr), ConversationPC = MakeObjPtr<AActor*>(nullptr);
DAngle ConversationNPCAngle = 0.; DAngle ConversationNPCAngle = 0.;
bool ConversationFaceTalker = false; bool ConversationFaceTalker = false;

View file

@ -315,6 +315,6 @@ void T_AddSpawnedThing(FLevelLocals *Level, AActor * ac)
if (Level->FraggleScriptThinker) if (Level->FraggleScriptThinker)
{ {
auto &SpawnedThings = Level->FraggleScriptThinker->SpawnedThings; auto &SpawnedThings = Level->FraggleScriptThinker->SpawnedThings;
SpawnedThings.Push(GC::ReadBarrier(ac)); SpawnedThings.Push(MakeObjPtr<AActor*>(ac));
} }
} }

View file

@ -173,7 +173,6 @@ DPSprite::DPSprite(player_t *owner, AActor *caller, int id)
Tics(0), Tics(0),
Translation(0), Translation(0),
Flags(0), Flags(0),
Caller(caller),
Owner(owner), Owner(owner),
State(nullptr), State(nullptr),
Sprite(0), Sprite(0),
@ -181,6 +180,7 @@ DPSprite::DPSprite(player_t *owner, AActor *caller, int id)
ID(id), ID(id),
processPending(true) processPending(true)
{ {
Caller = caller;
baseScale = {1.0, 1.2}; baseScale = {1.0, 1.2};
rotation = 0.; rotation = 0.;
scale = {1.0, 1.0}; scale = {1.0, 1.0};

View file

@ -17,8 +17,8 @@ class DInterpolation : public DObject
DECLARE_ABSTRACT_CLASS(DInterpolation, DObject) DECLARE_ABSTRACT_CLASS(DInterpolation, DObject)
HAS_OBJECT_POINTERS HAS_OBJECT_POINTERS
TObjPtr<DInterpolation*> Next = nullptr; TObjPtr<DInterpolation*> Next;
TObjPtr<DInterpolation*> Prev = nullptr; TObjPtr<DInterpolation*> Prev;
protected: protected:
FLevelLocals *Level; FLevelLocals *Level;
@ -46,7 +46,7 @@ public:
struct FInterpolator struct FInterpolator
{ {
TObjPtr<DInterpolation*> Head = nullptr; TObjPtr<DInterpolation*> Head = MakeObjPtr<DInterpolation*>(nullptr);
bool didInterp = false; bool didInterp = false;
int count = 0; int count = 0;

View file

@ -832,10 +832,10 @@ void DSeqNode::ActivateSequence (int sequence)
m_Atten = ATTN_IDLE; // ...and idle attenuation m_Atten = ATTN_IDLE; // ...and idle attenuation
} }
DSeqActorNode::DSeqActorNode (AActor *actor, int sequence, int modenum) DSeqActorNode::DSeqActorNode(AActor* actor, int sequence, int modenum)
: DSeqNode (actor->Level, sequence, modenum), : DSeqNode(actor->Level, sequence, modenum)
m_Actor (actor)
{ {
m_Actor = actor;
} }
DSeqPolyNode::DSeqPolyNode (FPolyObj *poly, int sequence, int modenum) DSeqPolyNode::DSeqPolyNode (FPolyObj *poly, int sequence, int modenum)