From 8104ef5189bd2dd42745e47c15d2f984b4213ec3 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 3 Nov 2017 13:33:36 +0200 Subject: [PATCH] Added warning for uninitialized variables in ZScript https://forum.zdoom.org/viewtopic.php?t=57868 --- src/scripting/backend/codegen.cpp | 36 +++++++++++++++++++++++++++---- src/scripting/backend/codegen.h | 9 ++++++-- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 5642402034c..1de09e741f2 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -2692,6 +2692,7 @@ FxExpression *FxMultiAssign::Resolve(FCompileContext &ctx) for (unsigned i = 0; i < Base.Size(); i++) { auto singlevar = new FxLocalVariableDeclaration(rets[i], NAME_None, nullptr, 0, ScriptPosition); + singlevar->IsInitialized = true; LocalVarContainer->Add(singlevar); Base[i] = Base[i]->Resolve(ctx); ABORT(Base[i]); @@ -6031,7 +6032,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) } else { - auto x = new FxStackVariable(local->ValueType, local->StackOffset, ScriptPosition); + auto x = new FxStackVariable(local, ScriptPosition); delete this; return x->Resolve(ctx); } @@ -6520,6 +6521,7 @@ FxLocalVariable::FxLocalVariable(FxLocalVariableDeclaration *var, const FScriptP FxExpression *FxLocalVariable::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); + IsLocalVariable = ctx.FunctionArgs.Find(Variable) == ctx.FunctionArgs.Size(); return this; } @@ -6553,7 +6555,16 @@ ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build) { ExpEmit ret(Variable->RegNum + RegOffset, Variable->ValueType->GetRegType(), false, true); ret.RegCount = ValueType->GetRegCount(); - if (AddressRequested) ret.Target = true; + if (AddressRequested) + { + Variable->IsInitialized = true; + ret.Target = true; + } + else if (IsLocalVariable) + { + Variable->WarnIfUninitialized(ScriptPosition); + } + return ret; } } @@ -6895,8 +6906,9 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) // //========================================================================== -FxStackVariable::FxStackVariable(PType *type, int offset, const FScriptPosition &pos) - : FxMemberBase(EFX_StackVariable, Create(NAME_None, type, 0, offset), pos) +FxStackVariable::FxStackVariable(FxLocalVariableDeclaration *var, const FScriptPosition &pos) + : FxMemberBase(EFX_StackVariable, Create(NAME_None, var->ValueType, 0, var->StackOffset), pos) + , Variable(var) { } @@ -6947,6 +6959,8 @@ ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build) if (AddressRequested) { + Variable->IsInitialized = true; + if (offsetreg >= 0) { ExpEmit obj(build, REGT_POINTER); @@ -6958,6 +6972,10 @@ ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build) return build->FramePointer; } } + else + { + Variable->WarnIfUninitialized(ScriptPosition); + } ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount()); if (membervar->BitValue == -1) @@ -11403,6 +11421,16 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build) // For that all local stack variables need to live for the entire execution of a function. } +void FxLocalVariableDeclaration::WarnIfUninitialized(const FScriptPosition &varPos) const +{ + if (!IsInitialized && nullptr == Init) + { + varPos.Message(MSG_WARNING, + "Usage of uninitialized variable '%s' defined at line %i", + Name.GetChars(), ScriptPosition.ScriptLine); + } +} + FxStaticArray::FxStaticArray(PType *type, FName name, FArgumentList &args, const FScriptPosition &pos) : FxLocalVariableDeclaration(NewArray(type, args.Size()), name, nullptr, VARF_Static|VARF_ReadOnly, pos) diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index 8ee32423fa0..f035039e267 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -1425,6 +1425,7 @@ class FxLocalVariable : public FxExpression public: FxLocalVariableDeclaration *Variable; bool AddressRequested; + bool IsLocalVariable; // false for function parameter and true otherwise int RegOffset; FxLocalVariable(FxLocalVariableDeclaration*, const FScriptPosition&); @@ -1442,7 +1443,9 @@ class FxLocalVariable : public FxExpression class FxStackVariable : public FxMemberBase { public: - FxStackVariable(PType *type, int offset, const FScriptPosition&); + FxLocalVariableDeclaration *Variable; + + FxStackVariable(FxLocalVariableDeclaration*, const FScriptPosition&); ~FxStackVariable(); FxExpression *Resolve(FCompileContext&); bool RequestAddress(FCompileContext &ctx, bool *writable); @@ -2121,6 +2124,7 @@ class FxLocalVariableDeclaration : public FxExpression { friend class FxCompoundStatement; friend class FxLocalVariable; + friend class FxStackVariable; friend class FxStaticArrayVariable; FName Name; @@ -2130,6 +2134,7 @@ class FxLocalVariableDeclaration : public FxExpression public: int StackOffset = -1; int RegNum = -1; + bool IsInitialized = false; FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p); ~FxLocalVariableDeclaration(); @@ -2137,7 +2142,7 @@ class FxLocalVariableDeclaration : public FxExpression ExpEmit Emit(VMFunctionBuilder *build); void Release(VMFunctionBuilder *build); void SetReg(ExpEmit reginfo); - + void WarnIfUninitialized(const FScriptPosition &varPos) const; }; //==========================================================================