- implicitly clear local dynamic arrays

https://forum.zdoom.org/viewtopic.php?t=62710
This commit is contained in:
alexey.lysiuk 2019-10-20 12:59:20 +03:00 committed by Christoph Oelckers
parent 1dd08a73ed
commit ce8b235d0b
2 changed files with 30 additions and 15 deletions

View file

@ -11272,6 +11272,7 @@ FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name,
Name = name; Name = name;
RegCount = type == TypeVector2 ? 2 : type == TypeVector3 ? 3 : 1; RegCount = type == TypeVector2 ? 2 : type == TypeVector3 ? 3 : 1;
Init = initval; Init = initval;
clearExpr = nullptr;
} }
FxLocalVariableDeclaration::~FxLocalVariableDeclaration() FxLocalVariableDeclaration::~FxLocalVariableDeclaration()
@ -11282,6 +11283,15 @@ FxLocalVariableDeclaration::~FxLocalVariableDeclaration()
FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx) FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx)
{ {
CHECKRESOLVED(); CHECKRESOLVED();
if (IsDynamicArray())
{
auto stackVar = new FxStackVariable(ValueType, StackOffset, ScriptPosition);
FArgumentList argsList;
clearExpr = new FxMemberFunctionCall(stackVar, "Clear", argsList, ScriptPosition);
SAFE_RESOLVE(clearExpr, ctx);
}
if (ctx.Block == nullptr) if (ctx.Block == nullptr)
{ {
ScriptPosition.Message(MSG_ERROR, "Variable declaration outside compound statement"); ScriptPosition.Message(MSG_ERROR, "Variable declaration outside compound statement");
@ -11476,6 +11486,10 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build)
} }
if (pstr->mDestructor != nullptr) build->ConstructedStructs.Push(this); if (pstr->mDestructor != nullptr) build->ConstructedStructs.Push(this);
} }
else if (ValueType->isDynArray())
{
ClearDynamicArray(build);
}
} }
return ExpEmit(); return ExpEmit();
} }
@ -11507,6 +11521,11 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build)
// For that all local stack variables need to live for the entire execution of a function. // For that all local stack variables need to live for the entire execution of a function.
} }
void FxLocalVariableDeclaration::ClearDynamicArray(VMFunctionBuilder *build)
{
assert(clearExpr != nullptr);
clearExpr->Emit(build);
}
FxStaticArray::FxStaticArray(PType *type, FName name, FArgumentList &args, const FScriptPosition &pos) FxStaticArray::FxStaticArray(PType *type, FName name, FArgumentList &args, const FScriptPosition &pos)
: FxLocalVariableDeclaration(NewArray(type, args.Size()), name, nullptr, VARF_Static|VARF_ReadOnly, pos) : FxLocalVariableDeclaration(NewArray(type, args.Size()), name, nullptr, VARF_Static|VARF_ReadOnly, pos)
@ -11591,7 +11610,6 @@ FxLocalArrayDeclaration::FxLocalArrayDeclaration(PType *type, FName name, FArgum
{ {
ExprType = EFX_LocalArrayDeclaration; ExprType = EFX_LocalArrayDeclaration;
values = std::move(args); values = std::move(args);
clearExpr = nullptr;
} }
FxExpression *FxLocalArrayDeclaration::Resolve(FCompileContext &ctx) FxExpression *FxLocalArrayDeclaration::Resolve(FCompileContext &ctx)
@ -11607,16 +11625,6 @@ FxExpression *FxLocalArrayDeclaration::Resolve(FCompileContext &ctx)
auto elementType = (static_cast<PArray *> (ValueType))->ElementType; auto elementType = (static_cast<PArray *> (ValueType))->ElementType;
auto elementCount = (static_cast<PArray *> (ValueType))->ElementCount; auto elementCount = (static_cast<PArray *> (ValueType))->ElementCount;
// We HAVE to clear dynamic arrays before initializing them
if (IsDynamicArray())
{
FArgumentList argsList;
argsList.Clear();
clearExpr = new FxMemberFunctionCall(stackVar, "Clear", argsList, (const FScriptPosition) ScriptPosition);
SAFE_RESOLVE(clearExpr, ctx);
}
if (values.Size() > elementCount) if (values.Size() > elementCount)
{ {
ScriptPosition.Message(MSG_ERROR, "Initializer contains more elements than the array can contain"); ScriptPosition.Message(MSG_ERROR, "Initializer contains more elements than the array can contain");
@ -11673,9 +11681,11 @@ ExpEmit FxLocalArrayDeclaration::Emit(VMFunctionBuilder *build)
{ {
assert(!(VarFlags & VARF_Out)); // 'out' variables should never be initialized, they can only exist as function parameters. assert(!(VarFlags & VARF_Out)); // 'out' variables should never be initialized, they can only exist as function parameters.
if (IsDynamicArray() && clearExpr != nullptr) const bool isDynamicArray = IsDynamicArray();
if (isDynamicArray)
{ {
clearExpr->Emit(build); ClearDynamicArray(build);
} }
auto elementSizeConst = build->GetConstantInt(static_cast<PArray *>(ValueType)->ElementSize); auto elementSizeConst = build->GetConstantInt(static_cast<PArray *>(ValueType)->ElementSize);
@ -11686,7 +11696,7 @@ ExpEmit FxLocalArrayDeclaration::Emit(VMFunctionBuilder *build)
{ {
ExpEmit emitval = v->Emit(build); ExpEmit emitval = v->Emit(build);
if (IsDynamicArray()) if (isDynamicArray)
{ {
continue; continue;
} }

View file

@ -2131,6 +2131,12 @@ class FxLocalVariableDeclaration : public FxExpression
FxExpression *Init; FxExpression *Init;
int VarFlags; int VarFlags;
int RegCount; int RegCount;
protected:
FxExpression *clearExpr;
void ClearDynamicArray(VMFunctionBuilder *build);
public: public:
int StackOffset = -1; int StackOffset = -1;
int RegNum = -1; int RegNum = -1;
@ -2194,7 +2200,6 @@ class FxLocalArrayDeclaration : public FxLocalVariableDeclaration
{ {
PType *ElementType; PType *ElementType;
FArgumentList values; FArgumentList values;
FxExpression *clearExpr;
public: public: