mirror of https://github.com/ZDoom/gzdoom.git
Disallow creation of abstract classes outside of their own class (this is so that modders can create their own factory methods, not just for native)
This commit is contained in:
parent
363990a105
commit
7d3663500f
|
@ -205,7 +205,7 @@ enum EObjectFlags
|
|||
OF_Transient = 1 << 11, // Object should not be archived (references to it will be nulled on disk)
|
||||
OF_Spawned = 1 << 12, // Thinker was spawned at all (some thinkers get deleted before spawning)
|
||||
OF_Released = 1 << 13, // Object was released from the GC system and should not be processed by GC function
|
||||
OF_Abstract = 1 << 14, // Marks a class that cannot be created with CreateNew
|
||||
OF_Abstract = 1 << 14, // Marks a class that cannot be created with new() function
|
||||
};
|
||||
|
||||
template<class T> class TObjPtr;
|
||||
|
|
|
@ -5023,6 +5023,7 @@ FxNew::FxNew(FxExpression *v)
|
|||
{
|
||||
val = new FxClassTypeCast(NewClassPointer(RUNTIME_CLASS(DObject)), v, false);
|
||||
ValueType = NewPointer(RUNTIME_CLASS(DObject));
|
||||
CallingClass = nullptr;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -5047,6 +5048,7 @@ FxExpression *FxNew::Resolve(FCompileContext &ctx)
|
|||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(val, ctx);
|
||||
|
||||
CallingClass = (PClass*)ctx.Class;
|
||||
if (!val->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Class type expected");
|
||||
|
@ -5058,6 +5060,7 @@ FxExpression *FxNew::Resolve(FCompileContext &ctx)
|
|||
auto cls = static_cast<PClass *>(static_cast<FxConstant*>(val)->GetValue().GetPointer());
|
||||
ValueType = NewPointer(cls);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -5072,7 +5075,7 @@ ExpEmit FxNew::Emit(VMFunctionBuilder *build)
|
|||
ExpEmit from = val->Emit(build);
|
||||
from.Free(build);
|
||||
ExpEmit to(build, REGT_POINTER);
|
||||
build->Emit(from.Konst ? OP_NEW_K : OP_NEW, to.RegNum, from.RegNum);
|
||||
build->Emit(from.Konst ? OP_NEW_K : OP_NEW, to.RegNum, from.RegNum, build->GetConstantAddress(CallingClass, ATAG_OBJECT));
|
||||
return to;
|
||||
}
|
||||
|
||||
|
@ -7527,8 +7530,18 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
|||
break;
|
||||
|
||||
case NAME_New:
|
||||
if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition))
|
||||
if (CheckArgSize(MethodName, ArgList, 0, 1, ScriptPosition))
|
||||
{
|
||||
// [ZZ] allow implicit new() call to mean "create current class instance"
|
||||
if (!ArgList.Size() && !ctx.Class->IsKindOf(RUNTIME_CLASS(PClass)))
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot use implicit new() in a struct");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
else if (!ArgList.Size())
|
||||
ArgList.Push(new FxConstant((PClass*)ctx.Class, NewClassPointer((PClass*)ctx.Class), ScriptPosition));
|
||||
|
||||
func = new FxNew(ArgList[0]);
|
||||
ArgList[0] = nullptr;
|
||||
}
|
||||
|
|
|
@ -1208,6 +1208,7 @@ private:
|
|||
class FxNew : public FxExpression
|
||||
{
|
||||
FxExpression *val;
|
||||
PClass *CallingClass;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -787,7 +787,8 @@ begin:
|
|||
{
|
||||
b = B;
|
||||
PClass *cls = (PClass*)(pc->op == OP_NEW ? reg.a[b] : konsta[b].v);
|
||||
if (cls->ObjectFlags & OF_Abstract) ThrowAbortException(X_OTHER, "Cannot instantiate abstract class %s", cls->TypeName.GetChars());
|
||||
PClass *callingcls = (PClass*)konsta[C].o; // [ZZ] due to how this is set, it's always const
|
||||
if ((cls->ObjectFlags & OF_Abstract) && callingcls != cls) ThrowAbortException(X_OTHER, "Cannot instantiate abstract class %s outside of that class", cls->TypeName.GetChars());
|
||||
reg.a[a] = cls->CreateNew();
|
||||
reg.atag[a] = ATAG_OBJECT;
|
||||
NEXTOP;
|
||||
|
|
Loading…
Reference in New Issue