From 3a526c9e5af02323003fe550f64d22f23c3a5576 Mon Sep 17 00:00:00 2001 From: Player701 Date: Sat, 9 Nov 2019 19:22:47 +0300 Subject: [PATCH] - Implement return type covariance for ZScript virtual functions --- src/common/objects/dobjtype.cpp | 8 ++++++-- src/common/objects/dobjtype.h | 2 +- src/common/scripting/backend/codegen.cpp | 4 ++-- src/common/scripting/frontend/zcc_compile.cpp | 5 +++-- wadsrc/static/zscript.txt | 2 +- wadsrc_extra/static/filter/harmony/zscript.txt | 2 +- 6 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/common/objects/dobjtype.cpp b/src/common/objects/dobjtype.cpp index cf6d32d04d..a22a9f1856 100644 --- a/src/common/objects/dobjtype.cpp +++ b/src/common/objects/dobjtype.cpp @@ -51,6 +51,7 @@ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- +bool AreCompatiblePointerTypes(PType* dest, PType* source, bool forcompare = false); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -665,7 +666,7 @@ PClass *PClass::FindClassTentative(FName name) // //========================================================================== -int PClass::FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc) +int PClass::FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc, bool exactReturnType) { auto proto = variant->Proto; for (unsigned i = 0; i < Virtuals.Size(); i++) @@ -693,7 +694,10 @@ int PClass::FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction for (unsigned a = 0; a < proto->ReturnTypes.Size(); a++) { - if (proto->ReturnTypes[a] != vproto->ReturnTypes[a]) + PType* expected = vproto->ReturnTypes[a]; + PType* actual = proto->ReturnTypes[a]; + + if (expected != actual && (exactReturnType || !AreCompatiblePointerTypes(expected, actual))) { fail = true; break; diff --git a/src/common/objects/dobjtype.h b/src/common/objects/dobjtype.h index 07a48454e4..f7996d89db 100644 --- a/src/common/objects/dobjtype.h +++ b/src/common/objects/dobjtype.h @@ -43,7 +43,7 @@ public: void InitializeSpecials(void* addr, void* defaults, TArray PClass::* Inits); void WriteAllFields(FSerializer &ar, const void *addr) const; bool ReadAllFields(FSerializer &ar, void *addr) const; - int FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc); + int FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc, bool exactReturnType); PSymbol *FindSymbol(FName symname, bool searchparents) const; PField *AddField(FName name, PType *type, uint32_t flags); void InitializeDefaults(); diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index 0ec83f20af..fe3d8e9382 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -81,7 +81,7 @@ static const FLOP FxFlops[] = { NAME_Round, FLOP_ROUND, [](double v) { return round(v); } }, }; -static bool AreCompatiblePointerTypes(PType* dest, PType* source, bool forcompare = false); +bool AreCompatiblePointerTypes(PType* dest, PType* source, bool forcompare = false); //========================================================================== // @@ -271,7 +271,7 @@ PFunction *FindBuiltinFunction(FName funcname) // //========================================================================== -static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompare) +bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompare) { if (dest->isPointer() && source->isPointer()) { diff --git a/src/common/scripting/frontend/zcc_compile.cpp b/src/common/scripting/frontend/zcc_compile.cpp index 0bc337bde0..a4908e7bcf 100644 --- a/src/common/scripting/frontend/zcc_compile.cpp +++ b/src/common/scripting/frontend/zcc_compile.cpp @@ -2366,6 +2366,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool sym->Variants[0].Implementation->VarFlags = sym->Variants[0].Flags; } + bool exactReturnType = mVersion < MakeVersion(4, 4); PClass *clstype = forclass? static_cast(c->Type())->Descriptor : nullptr; if (varflags & VARF_Virtual) { @@ -2379,7 +2380,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool { auto parentfunc = clstype->ParentClass? dyn_cast(clstype->ParentClass->VMType->Symbols.FindSymbol(sym->SymbolName, true)) : nullptr; - int vindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], parentfunc); + int vindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], parentfunc, exactReturnType); // specifying 'override' is necessary to prevent one of the biggest problem spots with virtual inheritance: Mismatching argument types. if (varflags & VARF_Override) { @@ -2459,7 +2460,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool } else if (forclass) { - int vindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], nullptr); + int vindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], nullptr, exactReturnType); if (vindex != -1) { Error(f, "Function %s attempts to override parent function without 'override' qualifier", FName(f->Name).GetChars()); diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index cfd2ff1666..6476252f6b 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -1,4 +1,4 @@ -version "4.3" +version "4.4" #include "zscript/base.zs" #include "zscript/sounddata.zs" #include "zscript/mapdata.zs" diff --git a/wadsrc_extra/static/filter/harmony/zscript.txt b/wadsrc_extra/static/filter/harmony/zscript.txt index 339942ecbd..5a512e6636 100644 --- a/wadsrc_extra/static/filter/harmony/zscript.txt +++ b/wadsrc_extra/static/filter/harmony/zscript.txt @@ -1,2 +1,2 @@ -version "4.2" +version "4.4" #include "zscript/harm_sbar.zs" \ No newline at end of file