Supposedly implemented a write check between ui/play/data

This commit is contained in:
ZZYZX 2017-02-17 22:41:04 +02:00
parent 8b0dee6f66
commit a7a4406bb1
2 changed files with 46 additions and 5 deletions

View file

@ -6706,11 +6706,28 @@ bool FxStructMember::RequestAddress(FCompileContext &ctx, bool *writable)
AddressRequested = true; AddressRequested = true;
if (writable != nullptr) if (writable != nullptr)
{ {
*writable = (AddressWritable && !ctx.CheckWritable(membervar->Flags) && // [ZZ] original check.
bool bWritable = (AddressWritable && !ctx.CheckWritable(membervar->Flags) &&
(!classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) || !static_cast<PPointer*>(classx->ValueType)->IsConst)); (!classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) || !static_cast<PPointer*>(classx->ValueType)->IsConst));
// [ZZ] self in a const function is not writable. // [ZZ] self in a const function is not writable.
if ((classx->ExprType == EFX_Self) && (ctx.Function && (ctx.Function->Variants[0].Flags & VARF_ReadOnly))) if (bWritable) // don't do complex checks on early fail
*writable = false; {
if ((classx->ExprType == EFX_Self) && (ctx.Function && (ctx.Function->Variants[0].Flags & VARF_ReadOnly)))
bWritable = false;
}
// [ZZ] plain data "inherits" scope of whatever it was defined in.
if (bWritable) // don't do complex checks on early fail
{
if (ctx.Function && FString(ctx.Function->SymbolName) == FString("DrawPowerup"))
Printf("field type = %d\n", BarrierSide);
int outerflags = 0;
if (ctx.Function)
outerflags = ctx.Function->Variants[0].Flags;
FScopeBarrier scopeBarrier(outerflags, FScopeBarrier::FlagsFromSide(BarrierSide), membervar->SymbolName.GetChars());
if (!scopeBarrier.writable)
bWritable = false;
}
*writable = bWritable;
} }
return true; return true;
} }
@ -6741,6 +6758,15 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
return x->Resolve(ctx); return x->Resolve(ctx);
} }
// [ZZ] support magic
BarrierSide = FScopeBarrier::SideFromFlags(membervar->Flags);
if (classx->ExprType == EFX_StructMember || classx->ExprType == EFX_ClassMember)
{
FxStructMember* pmember = (FxStructMember*)classx;
if (BarrierSide == FScopeBarrier::Side_PlainData && pmember)
BarrierSide = pmember->BarrierSide;
}
if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
{ {
PPointer *ptrtype = dyn_cast<PPointer>(classx->ValueType); PPointer *ptrtype = dyn_cast<PPointer>(classx->ValueType);

View file

@ -93,7 +93,7 @@ struct FScopeBarrier
int sidelast; int sidelast;
// Note: the same object can't be both UI and Play. This is checked explicitly in the field construction and will cause esoteric errors here if found. // Note: the same object can't be both UI and Play. This is checked explicitly in the field construction and will cause esoteric errors here if found.
int SideFromFlags(int flags) static int SideFromFlags(int flags)
{ {
if (flags & VARF_UI) if (flags & VARF_UI)
return Side_UI; return Side_UI;
@ -102,8 +102,22 @@ struct FScopeBarrier
return Side_PlainData; return Side_PlainData;
} }
//
static int FlagsFromSide(int side)
{
switch (side)
{
case Side_Play:
return VARF_Play;
case Side_UI:
return VARF_UI;
default:
return 0;
}
}
// used for errors // used for errors
const char* StringFromSide(int side) static const char* StringFromSide(int side)
{ {
switch (side) switch (side)
{ {
@ -1451,6 +1465,7 @@ public:
PField *membervar; PField *membervar;
bool AddressRequested = false; bool AddressRequested = false;
bool AddressWritable = true; bool AddressWritable = true;
int BarrierSide = -1; // [ZZ] some magic
FxMemberBase(EFxType type, PField *f, const FScriptPosition &p); FxMemberBase(EFxType type, PField *f, const FScriptPosition &p);
}; };