From 6fa409825b1f70e00462bdca2fbad506b899ecb9 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 # Conflicts: # src/dobjtype.h # wadsrc_extra/static/filter/harmony/zscript.txt --- src/dobjtype.cpp | 8 ++++++-- src/dobjtype.h | 2 +- src/scripting/backend/codegen.cpp | 4 ++-- src/scripting/zscript/zcc_compile.cpp | 5 +++-- wadsrc/static/zscript.txt | 2 +- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 294036fbd..6a057e0ac 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -59,6 +59,7 @@ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- +bool AreCompatiblePointerTypes(PType* dest, PType* source, bool forcompare = false); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -778,7 +779,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++) @@ -806,7 +807,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/dobjtype.h b/src/dobjtype.h index 3445e02ba..20af3daec 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -42,7 +42,7 @@ public: void WriteAllFields(FSerializer &ar, const void *addr) const; bool ReadAllFields(FSerializer &ar, void *addr) const; void InitializeDefaults(); - 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); diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 75f9fe21b..e81b9d843 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -92,7 +92,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); //========================================================================== // @@ -288,7 +288,7 @@ static 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/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index d4370578b..f09cdfca4 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -3013,6 +3013,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) { @@ -3026,7 +3027,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) { @@ -3106,7 +3107,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 83d68104a..6e01b39d9 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"