Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
coelckers committed Jun 6, 2022
1 parent 71ce8aa commit d1caf3a
Show file tree
Hide file tree
Showing 9 changed files with 45 additions and 39 deletions.
39 changes: 22 additions & 17 deletions src/common/objects/dobjgc.h
Expand Up @@ -180,70 +180,64 @@ 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;
return *this;
}

// 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;
}
Expand All @@ -255,6 +249,17 @@ class TObjPtr
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)
Expand Down
8 changes: 4 additions & 4 deletions src/g_levellocals.h
Expand Up @@ -540,7 +540,7 @@ struct FLevelLocals

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.
Expand Down Expand Up @@ -690,10 +690,10 @@ struct FLevelLocals

// 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);

//==========================================================================
//
Expand Down
3 changes: 2 additions & 1 deletion src/g_statusbar/sbar.h
Expand Up @@ -84,7 +84,8 @@ class DHUDMessageBase : public DObject
void CallDraw(int bottom, int visibility);

private:
TObjPtr<DHUDMessageBase*> Next = nullptr;
TObjPtr<DHUDMessageBase*> Next = MakeObjPtr<DHUDMessageBase*>(nullptr);
;
uint32_t SBarID = 0;
friend class DBaseStatusBar;

Expand Down
2 changes: 1 addition & 1 deletion src/playsim/a_action.cpp
Expand Up @@ -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;
Expand Down
16 changes: 8 additions & 8 deletions src/playsim/d_player.h
Expand Up @@ -340,7 +340,7 @@ class player_t

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
Expand All @@ -355,36 +355,36 @@ class player_t
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;
int morphTics = 0; // player is a chicken/pig if > 0
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.
int8_t crouching = 0;
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;
Expand All @@ -406,7 +406,7 @@ class player_t
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;

Expand Down
2 changes: 1 addition & 1 deletion src/playsim/fragglescript/t_load.cpp
Expand Up @@ -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));
}
}
2 changes: 1 addition & 1 deletion src/playsim/p_pspr.cpp
Expand Up @@ -173,14 +173,14 @@ DPSprite::DPSprite(player_t *owner, AActor *caller, int id)
Tics(0),
Translation(0),
Flags(0),
Caller(caller),
Owner(owner),
State(nullptr),
Sprite(0),
Frame(0),
ID(id),
processPending(true)
{
Caller = caller;
baseScale = {1.0, 1.2};
rotation = 0.;
scale = {1.0, 1.0};
Expand Down
6 changes: 3 additions & 3 deletions src/r_data/r_interpolate.h
Expand Up @@ -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;
Expand Down Expand Up @@ -46,7 +46,7 @@ class DInterpolation : public DObject

struct FInterpolator
{
TObjPtr<DInterpolation*> Head = nullptr;
TObjPtr<DInterpolation*> Head = MakeObjPtr<DInterpolation*>(nullptr);
bool didInterp = false;
int count = 0;

Expand Down
6 changes: 3 additions & 3 deletions src/sound/s_sndseq.cpp
Expand Up @@ -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)
Expand Down

0 comments on commit d1caf3a

Please sign in to comment.