mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51:51 +00:00
- improved handling of return value mismatches
Prohibit returning more values than declared in function The exception is a void function returning one value, but only for compatibility with old scripts https://forum.zdoom.org/viewtopic.php?t=66341
This commit is contained in:
parent
8c05816378
commit
6ad965abb5
1 changed files with 28 additions and 11 deletions
|
@ -10716,27 +10716,44 @@ FxExpression *FxReturnStatement::Resolve(FCompileContext &ctx)
|
||||||
|
|
||||||
PPrototype *retproto;
|
PPrototype *retproto;
|
||||||
|
|
||||||
if (ctx.ReturnProto != nullptr && ctx.ReturnProto->ReturnTypes.Size() == 0 && ctx.ReturnProto->ReturnTypes.Size() != Args.Size())
|
const bool hasProto = ctx.ReturnProto != nullptr;
|
||||||
|
const unsigned protoRetCount = hasProto ? ctx.ReturnProto->ReturnTypes.Size() : 0;
|
||||||
|
const unsigned retCount = Args.Size();
|
||||||
|
int mismatchSeverity = -1;
|
||||||
|
|
||||||
|
if (hasProto)
|
||||||
{
|
{
|
||||||
int severity = ctx.Version >= MakeVersion(3, 7) ? MSG_ERROR : MSG_WARNING;
|
if (protoRetCount == 0 && retCount == 1)
|
||||||
ScriptPosition.Message(severity, "Incorrect number of return values. Got %u, but expected %u", Args.Size(), ctx.ReturnProto->ReturnTypes.Size());
|
{
|
||||||
if (severity == MSG_ERROR)
|
// Handle the case with void function returning something, but only for one value
|
||||||
|
// It was accepted in previous versions, do not abort with fatal error when compiling old scripts
|
||||||
|
mismatchSeverity = ctx.Version >= MakeVersion(3, 7) ? MSG_ERROR : MSG_WARNING;
|
||||||
|
}
|
||||||
|
else if (protoRetCount < retCount)
|
||||||
|
{
|
||||||
|
mismatchSeverity = MSG_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mismatchSeverity != -1)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(mismatchSeverity, "Incorrect number of return values. Got %u, but expected %u", Args.Size(), ctx.ReturnProto->ReturnTypes.Size());
|
||||||
|
if (mismatchSeverity == MSG_ERROR)
|
||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
// For older script versions this must fall through.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Args.Size() == 0)
|
if (retCount == 0)
|
||||||
{
|
{
|
||||||
TArray<PType *> none(0);
|
TArray<PType *> none(0);
|
||||||
retproto = NewPrototype(none, none);
|
retproto = NewPrototype(none, none);
|
||||||
}
|
}
|
||||||
else if (Args.Size() == 1)
|
else if (retCount == 1)
|
||||||
{
|
{
|
||||||
// If we already know the real return type we need at least try to cast the value to its proper type (unless in an anonymous function.)
|
// If we already know the real return type we need at least try to cast the value to its proper type (unless in an anonymous function.)
|
||||||
if (ctx.ReturnProto != nullptr && ctx.ReturnProto->ReturnTypes.Size() > 0 && ctx.Function->SymbolName != NAME_None)
|
if (hasProto && protoRetCount > 0 && ctx.Function->SymbolName != NAME_None)
|
||||||
{
|
{
|
||||||
Args[0] = new FxTypeCast(Args[0], ctx.ReturnProto->ReturnTypes[0], false, false);
|
Args[0] = new FxTypeCast(Args[0], ctx.ReturnProto->ReturnTypes[0], false, false);
|
||||||
Args[0] = Args[0]->Resolve(ctx);
|
Args[0] = Args[0]->Resolve(ctx);
|
||||||
|
@ -10746,7 +10763,7 @@ FxExpression *FxReturnStatement::Resolve(FCompileContext &ctx)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < Args.Size(); i++)
|
for (unsigned i = 0; i < retCount; i++)
|
||||||
{
|
{
|
||||||
Args[i] = new FxTypeCast(Args[i], ctx.ReturnProto->ReturnTypes[i], false, false);
|
Args[i] = new FxTypeCast(Args[i], ctx.ReturnProto->ReturnTypes[i], false, false);
|
||||||
Args[i] = Args[i]->Resolve(ctx);
|
Args[i] = Args[i]->Resolve(ctx);
|
||||||
|
|
Loading…
Reference in a new issue