From b17ab7a1334967de278c7f83e6e5b52bb67f9e29 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 12 Apr 2017 11:40:40 +0200 Subject: [PATCH] - put PObjectPointer to some use. - fixed: There was no check for compatible class pointers. --- src/dobjtype.h | 1 + src/scripting/backend/codegen.cpp | 20 +++++++++++++++----- src/scripting/backend/codegen.h | 2 +- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/dobjtype.h b/src/dobjtype.h index abee1e36d..a4d0f4402 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -428,6 +428,7 @@ public: void WriteValue(FSerializer &ar, const char *key, const void *addr) const override; bool ReadValue(FSerializer &ar, const char *key, void *addr) const override; void SetPointer(void *base, unsigned offset, TArray *special = NULL) const override; + PClass *PointedClass() const; }; diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 66f9f308e..8414762b0 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -56,6 +56,8 @@ #include "w_wad.h" #include "math/cmath.h" +inline PClass *PObjectPointer::PointedClass() const { return static_cast(PointedType); } + extern FRandom pr_exrandom; FMemArena FxAlloc(65536); int utf8_decode(const char *src, int *size); @@ -294,10 +296,18 @@ static bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompar // A type is always compatible to itself. if (fromtype == totype) return true; // Pointers to different types are only compatible if both point to an object and the source type is a child of the destination type. - if (fromtype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)) && totype->PointedType->IsKindOf(RUNTIME_CLASS(PClass))) + if (source->IsA(RUNTIME_CLASS(PObjectPointer)) && dest->IsA(RUNTIME_CLASS(PObjectPointer))) { - auto fromcls = static_cast(fromtype->PointedType); - auto tocls = static_cast(totype->PointedType); + auto fromcls = static_cast(source)->PointedClass(); + auto tocls = static_cast(dest)->PointedClass(); + if (forcompare && tocls->IsDescendantOf(fromcls)) return true; + return (fromcls->IsDescendantOf(tocls)); + } + // The same rules apply to class pointers. A child type can be assigned to a variable of a parent type. + if (source->IsA(RUNTIME_CLASS(PClassPointer)) && dest->IsA(RUNTIME_CLASS(PClassPointer))) + { + auto fromcls = static_cast(source)->ClassRestriction; + auto tocls = static_cast(dest)->ClassRestriction; if (forcompare && tocls->IsDescendantOf(fromcls)) return true; return (fromcls->IsDescendantOf(tocls)); } @@ -6958,8 +6968,8 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) if (membervar->SymbolName == NAME_Default) { - if (!classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) - || !static_cast(classx->ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(AActor))) + if (!classx->ValueType->IsKindOf(RUNTIME_CLASS(PObjectPointer)) + || !static_cast(classx->ValueType)->PointedClass()->IsDescendantOf(RUNTIME_CLASS(AActor))) { ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type"); delete this; diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index 0a6b6cc44..f1a322d7a 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -333,7 +333,7 @@ public: bool IsPointer() const { return ValueType->GetRegType() == REGT_POINTER; } bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3; }; bool IsBoolCompat() const { return ValueType->GetRegCount() == 1 && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT || ValueType->GetRegType() == REGT_POINTER); } - bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)) && ValueType != TypeNullPtr && static_cast(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PClass)); } + bool IsObject() const { return ValueType->IsKindOf(RUNTIME_CLASS(PObjectPointer)); } bool IsArray() const { return ValueType->IsKindOf(RUNTIME_CLASS(PArray)) || (ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PArray))); } bool IsResizableArray() const { return (ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && static_cast(ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(PStaticArray))); } // can only exist in pointer form. bool IsDynamicArray() const { return (ValueType->IsKindOf(RUNTIME_CLASS(PDynArray))); }