mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
Implemented implicit 'protected' inheritance in virtual functions
This commit is contained in:
parent
b87f9b540e
commit
7cbabfb0d4
5 changed files with 25 additions and 23 deletions
|
@ -8725,7 +8725,7 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
||||||
}
|
}
|
||||||
|
|
||||||
VMFunction *vmfunc = Function->Variants[0].Implementation;
|
VMFunction *vmfunc = Function->Variants[0].Implementation;
|
||||||
bool staticcall = (vmfunc->Final || vmfunc->VirtualIndex == ~0u || NoVirtual);
|
bool staticcall = ((vmfunc->VarFlags & VARF_Final) || vmfunc->VirtualIndex == ~0u || NoVirtual);
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
// Emit code to pass implied parameters
|
// Emit code to pass implied parameters
|
||||||
|
|
|
@ -705,10 +705,8 @@ do_double: if (inexact)
|
||||||
class VMFunction
|
class VMFunction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool Native;
|
bool Unsafe = false;
|
||||||
bool Final = false; // cannot be overridden
|
int VarFlags = 0; // [ZZ] this replaces 5+ bool fields
|
||||||
bool Unsafe = false; // Contains references to class fields that are unsafe for psp and item state calls.
|
|
||||||
bool FuncConst = false; // [ZZ] readonly function
|
|
||||||
int BarrierSide = 0; // [ZZ] FScopeBarrier::Side
|
int BarrierSide = 0; // [ZZ] FScopeBarrier::Side
|
||||||
BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action
|
BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action
|
||||||
unsigned VirtualIndex = ~0u;
|
unsigned VirtualIndex = ~0u;
|
||||||
|
@ -718,7 +716,7 @@ public:
|
||||||
|
|
||||||
class PPrototype *Proto;
|
class PPrototype *Proto;
|
||||||
|
|
||||||
VMFunction(FName name = NAME_None) : Native(false), ImplicitArgs(0), Name(name), Proto(NULL)
|
VMFunction(FName name = NAME_None) : ImplicitArgs(0), Name(name), Proto(NULL)
|
||||||
{
|
{
|
||||||
AllFunctions.Push(this);
|
AllFunctions.Push(this);
|
||||||
}
|
}
|
||||||
|
@ -942,9 +940,10 @@ class VMNativeFunction : public VMFunction
|
||||||
public:
|
public:
|
||||||
typedef int (*NativeCallType)(VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret);
|
typedef int (*NativeCallType)(VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret);
|
||||||
|
|
||||||
VMNativeFunction() : NativeCall(NULL) { Native = true; }
|
// 8 is VARF_Native.
|
||||||
VMNativeFunction(NativeCallType call) : NativeCall(call) { Native = true; }
|
VMNativeFunction() : NativeCall(NULL) { VarFlags = 8; }
|
||||||
VMNativeFunction(NativeCallType call, FName name) : VMFunction(name), NativeCall(call) { Native = true; }
|
VMNativeFunction(NativeCallType call) : NativeCall(call) { VarFlags = 8; }
|
||||||
|
VMNativeFunction(NativeCallType call, FName name) : VMFunction(name), NativeCall(call) { VarFlags = 8; }
|
||||||
|
|
||||||
// Return value is the number of results.
|
// Return value is the number of results.
|
||||||
NativeCallType NativeCall;
|
NativeCallType NativeCall;
|
||||||
|
|
|
@ -22,7 +22,7 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret)
|
||||||
const FVoidObj *konsta;
|
const FVoidObj *konsta;
|
||||||
const VM_ATAG *konstatag;
|
const VM_ATAG *konstatag;
|
||||||
|
|
||||||
if (f->Func != NULL && !f->Func->Native)
|
if (f->Func != NULL && !(f->Func->VarFlags & VARF_Native))
|
||||||
{
|
{
|
||||||
sfunc = static_cast<VMScriptFunction *>(f->Func);
|
sfunc = static_cast<VMScriptFunction *>(f->Func);
|
||||||
konstd = sfunc->KonstD;
|
konstd = sfunc->KonstD;
|
||||||
|
@ -679,7 +679,7 @@ begin:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FillReturns(reg, f, returns, pc+1, C);
|
FillReturns(reg, f, returns, pc+1, C);
|
||||||
if (call->Native)
|
if (call->VarFlags & VARF_Native)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -736,7 +736,7 @@ begin:
|
||||||
{
|
{
|
||||||
VMFunction *call = (VMFunction *)ptr;
|
VMFunction *call = (VMFunction *)ptr;
|
||||||
|
|
||||||
if (call->Native)
|
if (call->VarFlags & VARF_Native)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -1966,7 +1966,7 @@ static void SetReturn(const VMRegisters ®, VMFrame *frame, VMReturn *ret, VM_
|
||||||
const void *src;
|
const void *src;
|
||||||
VMScriptFunction *func = static_cast<VMScriptFunction *>(frame->Func);
|
VMScriptFunction *func = static_cast<VMScriptFunction *>(frame->Func);
|
||||||
|
|
||||||
assert(func != NULL && !func->Native);
|
assert(func != NULL && !(func->VarFlags & VARF_Native));
|
||||||
assert((regtype & ~REGT_KONST) == ret->RegType);
|
assert((regtype & ~REGT_KONST) == ret->RegType);
|
||||||
|
|
||||||
switch (regtype & REGT_TYPE)
|
switch (regtype & REGT_TYPE)
|
||||||
|
|
|
@ -48,7 +48,6 @@ TArray<VMFunction *> VMFunction::AllFunctions;
|
||||||
|
|
||||||
VMScriptFunction::VMScriptFunction(FName name)
|
VMScriptFunction::VMScriptFunction(FName name)
|
||||||
{
|
{
|
||||||
Native = false;
|
|
||||||
Name = name;
|
Name = name;
|
||||||
LineInfo = nullptr;
|
LineInfo = nullptr;
|
||||||
Code = NULL;
|
Code = NULL;
|
||||||
|
@ -438,7 +437,7 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur
|
||||||
bool allocated = false;
|
bool allocated = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (func->Native)
|
if (func->VarFlags & VARF_Native)
|
||||||
{
|
{
|
||||||
return static_cast<VMNativeFunction *>(func)->NativeCall(params, func->DefaultArgs, numparams, results, numresults);
|
return static_cast<VMNativeFunction *>(func)->NativeCall(params, func->DefaultArgs, numparams, results, numresults);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2416,6 +2416,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
{
|
{
|
||||||
// [ZZ] unspecified virtual function inherits old scope. virtual function scope can't be changed.
|
// [ZZ] unspecified virtual function inherits old scope. virtual function scope can't be changed.
|
||||||
sym->Variants[0].Implementation->BarrierSide = FScopeBarrier::SideFromFlags(varflags);
|
sym->Variants[0].Implementation->BarrierSide = FScopeBarrier::SideFromFlags(varflags);
|
||||||
|
sym->Variants[0].Implementation->VarFlags = sym->Variants[0].Flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
PClass *clstype = static_cast<PClass *>(c->Type());
|
PClass *clstype = static_cast<PClass *>(c->Type());
|
||||||
|
@ -2427,11 +2428,6 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (varflags & VARF_Final)
|
|
||||||
sym->Variants[0].Implementation->Final = true;
|
|
||||||
if (varflags & VARF_ReadOnly)
|
|
||||||
sym->Variants[0].Implementation->FuncConst = true;
|
|
||||||
|
|
||||||
if (forclass)
|
if (forclass)
|
||||||
{
|
{
|
||||||
int vindex = clstype->FindVirtualIndex(sym->SymbolName, sym->Variants[0].Proto);
|
int vindex = clstype->FindVirtualIndex(sym->SymbolName, sym->Variants[0].Proto);
|
||||||
|
@ -2445,7 +2441,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto oldfunc = clstype->Virtuals[vindex];
|
auto oldfunc = clstype->Virtuals[vindex];
|
||||||
if (oldfunc->Final)
|
if (oldfunc->VarFlags & VARF_Final)
|
||||||
{
|
{
|
||||||
Error(f, "Attempt to override final function %s", FName(f->Name).GetChars());
|
Error(f, "Attempt to override final function %s", FName(f->Name).GetChars());
|
||||||
}
|
}
|
||||||
|
@ -2455,19 +2451,27 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
Error(f, "Attempt to change scope for virtual function %s", FName(f->Name).GetChars());
|
Error(f, "Attempt to change scope for virtual function %s", FName(f->Name).GetChars());
|
||||||
}
|
}
|
||||||
// you can't change const qualifier for a virtual method
|
// you can't change const qualifier for a virtual method
|
||||||
if (sym->Variants[0].Implementation->FuncConst && !oldfunc->FuncConst)
|
if ((sym->Variants[0].Implementation->VarFlags & VARF_ReadOnly) && !(oldfunc->VarFlags & VARF_ReadOnly))
|
||||||
{
|
{
|
||||||
Error(f, "Attempt to add const qualifier to virtual function %s", FName(f->Name).GetChars());
|
Error(f, "Attempt to add const qualifier to virtual function %s", FName(f->Name).GetChars());
|
||||||
}
|
}
|
||||||
|
// you can't change protected qualifier for a virtual method (i.e. putting private), because this cannot be reliably checked without runtime stuff
|
||||||
|
if (f->Flags & (ZCC_Private | ZCC_Protected))
|
||||||
|
{
|
||||||
|
Error(f, "Attempt to change private/protected qualifiers for virtual function %s", FName(f->Name).GetChars());
|
||||||
|
}
|
||||||
// inherit scope of original function if override not specified
|
// inherit scope of original function if override not specified
|
||||||
sym->Variants[0].Implementation->BarrierSide = oldfunc->BarrierSide;
|
sym->Variants[0].Implementation->BarrierSide = oldfunc->BarrierSide;
|
||||||
sym->Variants[0].Flags = FScopeBarrier::ChangeSideInFlags(sym->Variants[0].Flags, oldfunc->BarrierSide);
|
sym->Variants[0].Flags = FScopeBarrier::ChangeSideInFlags(sym->Variants[0].Flags, oldfunc->BarrierSide);
|
||||||
// inherit const from original function
|
// inherit const from original function
|
||||||
if ((sym->Variants[0].Implementation->FuncConst = oldfunc->FuncConst))
|
if (oldfunc->VarFlags & VARF_ReadOnly)
|
||||||
sym->Variants[0].Flags |= VARF_ReadOnly;
|
sym->Variants[0].Flags |= VARF_ReadOnly;
|
||||||
|
if (oldfunc->VarFlags & VARF_Protected)
|
||||||
|
sym->Variants[0].Flags |= VARF_Protected;
|
||||||
|
|
||||||
clstype->Virtuals[vindex] = sym->Variants[0].Implementation;
|
clstype->Virtuals[vindex] = sym->Variants[0].Implementation;
|
||||||
sym->Variants[0].Implementation->VirtualIndex = vindex;
|
sym->Variants[0].Implementation->VirtualIndex = vindex;
|
||||||
|
sym->Variants[0].Implementation->VarFlags = sym->Variants[0].Flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue