- 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;
};
public:
TObjPtr() = default;
TObjPtr(const TObjPtr<T> &q) = default;
TObjPtr(T q) noexcept
: pp(q)
{
}
T operator=(T q)
constexpr TObjPtr<T>& operator=(T q) noexcept
{
pp = q;
return *this;
}
T operator=(std::nullptr_t nul)
constexpr TObjPtr<T>& operator=(std::nullptr_t nul) noexcept
{
o = nullptr;
return *this;
}
// To allow NULL, too.
T operator=(const int val)
TObjPtr<T>& 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<T>& 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<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
// the contents of a TObjPtr to a related type.
template<class T,class U> inline T barrier_cast(TObjPtr<U> &o)

View file

@ -540,7 +540,7 @@ public:
static const int BODYQUESIZE = 32;
TObjPtr<AActor*> bodyque[BODYQUESIZE];
TObjPtr<DAutomapBase*> automap = nullptr;
TObjPtr<DAutomapBase*> automap = MakeObjPtr<DAutomapBase*>(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<TObjPtr<AActor *>> CorpseQueue;
TObjPtr<DFraggleThinker *> FraggleScriptThinker = nullptr;
TObjPtr<DACSThinker*> ACSThinker = nullptr;
TObjPtr<DFraggleThinker *> FraggleScriptThinker = MakeObjPtr<DFraggleThinker*>(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);
private:
TObjPtr<DHUDMessageBase*> Next = nullptr;
TObjPtr<DHUDMessageBase*> Next = MakeObjPtr<DHUDMessageBase*>(nullptr);
;
uint32_t SBarID = 0;
friend class DBaseStatusBar;

View file

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

View file

@ -340,7 +340,7 @@ public:
AActor *ReadyWeapon = nullptr;
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 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<AActor*> poisoner = nullptr; // NULL for non-player actors
TObjPtr<AActor*> attacker = nullptr; // who did damage (NULL for floors)
TObjPtr<AActor*> poisoner = MakeObjPtr<AActor*>(nullptr); // NULL for non-player actors
TObjPtr<AActor*> attacker = MakeObjPtr<AActor*>(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<AActor*> PremorphWeapon = nullptr; // ready weapon before morphing
TObjPtr<AActor*> PremorphWeapon = MakeObjPtr<AActor*>(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<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
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;
bool settings_controller = false; // Player can control game settings.
@ -384,7 +384,7 @@ public:
int8_t crouchdir = 0;
//Added by MC:
TObjPtr<DBot*> Bot = nullptr;
TObjPtr<DBot*> Bot = MakeObjPtr<DBot*>(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<AActor*> ConversationNPC = nullptr, ConversationPC = nullptr;
TObjPtr<AActor*> ConversationNPC = MakeObjPtr<AActor*>(nullptr), ConversationPC = MakeObjPtr<AActor*>(nullptr);
DAngle ConversationNPCAngle = 0.;
bool ConversationFaceTalker = false;

View file

@ -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<AActor*>(ac));
}
}

View file

@ -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};

View file

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

View file

@ -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)