mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-18 15:42:34 +00:00
- fixed: Readonly pointers never were flagged as such.
- fixed: Assignment from a readonly to a read-allowed pointer must be an error. - made GetDefaultByType a builtin so that it can do proper type assignment to the result, which for a function would be problematic in this case, even if automatic type deduction was implemented. Since this returns the class defaults which are not a real object, the result cannot be subjected to a type cast. - error out if a type cast of a readonly pointer is attempted. - fixed: FxBooleanNot could clobber a local variable because it used the source register to manipulate the result.
This commit is contained in:
parent
3dd323ac0d
commit
f409a24d2d
7 changed files with 125 additions and 13 deletions
|
@ -1688,7 +1688,7 @@ PPointer *NewPointer(PType *type, bool isconst)
|
|||
PType *ptype = TypeTable.FindType(RUNTIME_CLASS(PPointer), (intptr_t)type, isconst ? 1 : 0, &bucket);
|
||||
if (ptype == NULL)
|
||||
{
|
||||
ptype = new PPointer(type);
|
||||
ptype = new PPointer(type, isconst);
|
||||
TypeTable.AddType(ptype, RUNTIME_CLASS(PPointer), (intptr_t)type, isconst ? 1 : 0, bucket);
|
||||
}
|
||||
return static_cast<PPointer *>(ptype);
|
||||
|
|
|
@ -286,6 +286,7 @@ xx(Random2)
|
|||
xx(RandomPick)
|
||||
xx(FRandomPick)
|
||||
xx(GetClass)
|
||||
xx(GetDefaultByType)
|
||||
xx(Exp)
|
||||
xx(Log10)
|
||||
xx(Ceil)
|
||||
|
|
|
@ -262,7 +262,7 @@ static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompar
|
|||
auto fromtype = static_cast<PPointer *>(source);
|
||||
auto totype = static_cast<PPointer *>(dest);
|
||||
if (fromtype == nullptr) return true;
|
||||
if (!forcompare && totype->IsConst && !fromtype->IsConst) return false;
|
||||
if (!forcompare && totype->IsConst != fromtype->IsConst) return false;
|
||||
if (fromtype == totype) return true;
|
||||
if (fromtype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)) && totype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
|
||||
{
|
||||
|
@ -1874,10 +1874,13 @@ ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build)
|
|||
assert(Operand->ValueType == TypeBool);
|
||||
assert(ValueType == TypeBool || IsInteger()); // this may have been changed by an int cast.
|
||||
ExpEmit from = Operand->Emit(build);
|
||||
from.Free(build);
|
||||
ExpEmit to(build, REGT_INT);
|
||||
assert(!from.Konst);
|
||||
// boolean not is the same as XOR-ing the lowest bit
|
||||
build->Emit(OP_XOR_RK, from.RegNum, from.RegNum, build->GetConstantInt(1));
|
||||
return from;
|
||||
|
||||
build->Emit(OP_XOR_RK, to.RegNum, from.RegNum, build->GetConstantInt(1));
|
||||
return to;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -4309,7 +4312,18 @@ FxExpression *FxDynamicCast::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(expr, ctx);
|
||||
if (expr->ExprType == EFX_GetDefaultByType)
|
||||
{
|
||||
int a = 0;
|
||||
}
|
||||
bool constflag = expr->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast<PPointer *>(expr->ValueType)->IsConst;
|
||||
if (constflag)
|
||||
{
|
||||
// readonly pointers are normally only used for class defaults which lack type information to be cast properly, so we have to error out here.
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot cast a readonly pointer");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
expr = new FxTypeCast(expr, NewPointer(RUNTIME_CLASS(DObject), constflag), true, true);
|
||||
expr = expr->Resolve(ctx);
|
||||
if (expr == nullptr)
|
||||
|
@ -7012,6 +7026,14 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
|||
}
|
||||
break;
|
||||
|
||||
case NAME_GetDefaultByType:
|
||||
if (CheckArgSize(NAME_GetDefaultByType, ArgList, 1, 1, ScriptPosition))
|
||||
{
|
||||
func = new FxGetDefaultByType(ArgList[0]);
|
||||
ArgList[0] = nullptr;
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_Random:
|
||||
// allow calling Random without arguments to default to (0, 255)
|
||||
if (ArgList.Size() == 0)
|
||||
|
@ -8147,6 +8169,78 @@ ExpEmit FxGetClass::Emit(VMFunctionBuilder *build)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FxGetDefaultByType::FxGetDefaultByType(FxExpression *self)
|
||||
:FxExpression(EFX_GetDefaultByType, self->ScriptPosition)
|
||||
{
|
||||
Self = self;
|
||||
}
|
||||
|
||||
FxGetDefaultByType::~FxGetDefaultByType()
|
||||
{
|
||||
SAFE_DELETE(Self);
|
||||
}
|
||||
|
||||
FxExpression *FxGetDefaultByType::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
SAFE_RESOLVE(Self, ctx);
|
||||
PClass *cls = nullptr;
|
||||
|
||||
if (Self->ValueType == TypeString || Self->ValueType == TypeName)
|
||||
{
|
||||
if (Self->isConstant())
|
||||
{
|
||||
cls = PClass::FindActor(static_cast<FxConstant *>(Self)->GetValue().GetName());
|
||||
if (cls == nullptr)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "GetDefaultByType() requires an actor class type, but got %s", static_cast<FxConstant *>(Self)->GetValue().GetString().GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
Self = new FxConstant(cls, NewClassPointer(cls), ScriptPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is the ugly case. We do not know what we have and cannot do proper type casting.
|
||||
// For now error out and let this case require explicit handling on the user side.
|
||||
ScriptPosition.Message(MSG_ERROR, "GetDefaultByType() requires an actor class type", static_cast<FxConstant *>(Self)->GetValue().GetString().GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto cp = dyn_cast<PClassPointer>(Self->ValueType);
|
||||
if (cp == nullptr || !cp->ClassRestriction->IsDescendantOf(RUNTIME_CLASS(AActor)))
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "GetDefaultByType() requires an actor class type");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
cls = cp->ClassRestriction;
|
||||
}
|
||||
ValueType = NewPointer(cls, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
ExpEmit FxGetDefaultByType::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
ExpEmit op = Self->Emit(build);
|
||||
op.Free(build);
|
||||
ExpEmit to(build, REGT_POINTER);
|
||||
if (op.Konst)
|
||||
{
|
||||
build->Emit(OP_LKP, to.RegNum, op.RegNum);
|
||||
op = to;
|
||||
}
|
||||
build->Emit(OP_LO, to.RegNum, op.RegNum, build->GetConstantInt(myoffsetof(PClass, Defaults)));
|
||||
return to;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxColorLiteral::FxColorLiteral(FArgumentList &args, FScriptPosition &sc)
|
||||
:FxExpression(EFX_ColorLiteral, sc)
|
||||
{
|
||||
|
|
|
@ -289,6 +289,7 @@ enum EFxType
|
|||
EFX_NamedNode,
|
||||
EFX_GetClass,
|
||||
EFX_ColorLiteral,
|
||||
EFX_GetDefaultByType,
|
||||
EFX_COUNT
|
||||
};
|
||||
|
||||
|
@ -1542,6 +1543,24 @@ public:
|
|||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxFlopFunctionCall
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxGetDefaultByType : public FxExpression
|
||||
{
|
||||
FxExpression *Self;
|
||||
|
||||
public:
|
||||
|
||||
FxGetDefaultByType(FxExpression *self);
|
||||
~FxGetDefaultByType();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxColorLiteral
|
||||
|
|
|
@ -424,7 +424,7 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur
|
|||
{
|
||||
bool allocated = false;
|
||||
try
|
||||
{
|
||||
{
|
||||
if (func->Native)
|
||||
{
|
||||
return static_cast<VMNativeFunction *>(func)->NativeCall(this, params, func->DefaultArgs, numparams, results, numresults);
|
||||
|
|
|
@ -238,7 +238,7 @@ class Actor : Thinker native
|
|||
VisiblePitch 0, 0;
|
||||
DefaultStateUsage SUF_ACTOR|SUF_OVERLAY;
|
||||
}
|
||||
|
||||
|
||||
// Functions
|
||||
|
||||
// 'parked' global functions.
|
||||
|
@ -268,7 +268,6 @@ class Actor : Thinker native
|
|||
virtual native bool SpecialBlastHandling (Actor source, double strength);
|
||||
|
||||
|
||||
native static readonly<Actor> GetDefaultByType(class<Actor> cls);
|
||||
native static double GetDefaultSpeed(class<Actor> type);
|
||||
native void RemoveFromHash();
|
||||
native string GetTag(string defstr = "");
|
||||
|
|
|
@ -28,7 +28,7 @@ class PoisonBag : Actor
|
|||
|
||||
void A_PoisonBagInit()
|
||||
{
|
||||
Actor mo = Spawn("PoisonCloud", (pos.xy, 28), ALLOW_REPLACE);
|
||||
Actor mo = Spawn("PoisonCloud", pos + (0, 0, 28), ALLOW_REPLACE);
|
||||
if (mo)
|
||||
{
|
||||
mo.target = target;
|
||||
|
@ -184,8 +184,7 @@ class ArtiPoisonBag : Inventory
|
|||
// If a subclass's specific icon is not defined, let it use the base class's.
|
||||
if (!Icon.isValid())
|
||||
{
|
||||
Inventory defbag = Inventory(GetDefaultByType("ArtiPoisonBag"));
|
||||
Icon = defbag.Icon;
|
||||
Icon = GetDefaultByType("ArtiPoisonBag").Icon;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -469,7 +468,7 @@ class PoisonCloud : Actor
|
|||
special1 = 24+(random[PoisonCloud]() & 7);
|
||||
special2 = 0;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -482,7 +481,7 @@ class PoisonCloud : Actor
|
|||
{
|
||||
bool mate = (target != null && victim.player != target.player && victim.IsTeammate (target));
|
||||
bool dopoison;
|
||||
|
||||
|
||||
if (!mate)
|
||||
{
|
||||
dopoison = victim.player.poisoncount < 4;
|
||||
|
@ -494,7 +493,7 @@ class PoisonCloud : Actor
|
|||
|
||||
if (dopoison)
|
||||
{
|
||||
int damage = 15 + (random[PoisonCloud]()&15);
|
||||
damage = 15 + (random[PoisonCloud]() & 15);
|
||||
if (mate)
|
||||
{
|
||||
damage = (int)(damage * level.teamdamage);
|
||||
|
|
Loading…
Reference in a new issue