From 2da52cedc960babe42ab17a04023b3265782e988 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 16 Oct 2016 12:47:26 +0200 Subject: [PATCH] - restrict 8 and 16 bit integer types to struct and class members - and I am not really sure if they should even be allowed there, aside from legacy readonly properties. For 32 bit floats the same would hold, but those are already mapped to 64 bit doubles silently. ZDoom only uses these types in a very few isolated places, and even those can be removed without problems, so it's very doubtful that having support for these types is of any benefit - on the other hand, having them will most likely introduce more code than is saved in the data by using them... --- src/dobjtype.cpp | 2 + src/dobjtype.h | 1 + src/scripting/zscript/zcc_compile.cpp | 75 ++++++++++++++++++--------- src/scripting/zscript/zcc_compile.h | 2 +- 4 files changed, 54 insertions(+), 26 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 966663f12..b023a2693 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -727,6 +727,7 @@ PInt::PInt() PInt::PInt(unsigned int size, bool unsign) : PBasicType(size, size), Unsigned(unsign) { + MemberOnly = (size < 4); if (!unsign) { int maxval = (1 << ((8 * size) - 1)) - 1; @@ -1018,6 +1019,7 @@ PFloat::PFloat(unsigned int size) else { assert(size == 4); + MemberOnly = true; SetSingleSymbols(); } } diff --git a/src/dobjtype.h b/src/dobjtype.h index a5da177a4..885e1ea0e 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -221,6 +221,7 @@ public: unsigned int Align; // this type's preferred alignment PType *HashNext; // next type in this type table PSymbolTable Symbols; + bool MemberOnly = false; // type may only be used as a struct/class member but not as a local variable or function argument. PType(); PType(unsigned int size, unsigned int align); diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index b2f22555f..f6d23a99b 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1205,7 +1205,7 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel { auto field = Fields[0]; - PType *fieldtype = DetermineType(type, field, field->Names->Name, field->Type, true); + PType *fieldtype = DetermineType(type, field, field->Names->Name, field->Type, true, true); // For structs only allow 'deprecated', for classes exclude function qualifiers. int notallowed = forstruct? ~ZCC_Deprecated : ZCC_Latent | ZCC_Final | ZCC_Action | ZCC_Static | ZCC_FuncConst | ZCC_Abstract; @@ -1290,8 +1290,9 @@ FString ZCCCompiler::FlagsToString(uint32_t flags) // //========================================================================== -PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes) +PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes, bool formember) { + PType *retval = TypeError; if (!allowarraytypes && ztype->ArraySize != nullptr) { Error(field, "%s: Array type not allowed", name.GetChars()); @@ -1305,26 +1306,33 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n switch (btype->Type) { case ZCC_SInt8: - return TypeSInt8; + retval = TypeSInt8; + break; case ZCC_UInt8: - return TypeUInt8; + retval = TypeUInt8; + break; case ZCC_SInt16: - return TypeSInt16; + retval = TypeSInt16; + break; case ZCC_UInt16: - return TypeUInt16; + retval = TypeUInt16; + break; case ZCC_SInt32: case ZCC_IntAuto: // todo: for enums, autoselect appropriately sized int - return TypeSInt32; + retval = TypeSInt32; + break; case ZCC_UInt32: - return TypeUInt32; + retval = TypeUInt32; + break; case ZCC_Bool: - return TypeBool; + retval = TypeBool; + break; // Do we really want to allow single precision floats, despite all the problems they cause? // These are nearly guaranteed to desync between MSVC and GCC on x87, because GCC does not implement an IEEE compliant mode @@ -1332,19 +1340,24 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n case ZCC_FloatAuto: //return TypeFloat32; case ZCC_Float64: - return TypeFloat64; + retval = TypeFloat64; + return; case ZCC_String: - return TypeString; + retval = TypeString; + break; case ZCC_Name: - return TypeName; + retval = TypeName; + break; case ZCC_Vector2: - return TypeVector2; + retval = TypeVector2; + break; case ZCC_Vector3: - return TypeVector3; + retval = TypeVector3; + break; case ZCC_Vector4: // This has almost no use, so we really shouldn't bother. @@ -1352,18 +1365,22 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n return TypeError; case ZCC_State: - return TypeState; + retval = TypeState; + break; case ZCC_Color: - return TypeColor; + retval = TypeColor; + break; case ZCC_Sound: - return TypeSound; + retval = TypeSound; + break; case ZCC_UserType: - return ResolveUserType(btype, &outertype->Symbols); + retval = ResolveUserType(btype, &outertype->Symbols); break; } + break; } case AST_MapType: @@ -1372,7 +1389,8 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n Error(field, "%s: Map types not implemented yet", name.GetChars()); // Todo: Decide what we allow here and if it makes sense to allow more complex constructs. auto mtype = static_cast(ztype); - return NewMap(DetermineType(outertype, field, name, mtype->KeyType, false), DetermineType(outertype, field, name, mtype->ValueType, false)); + retval = NewMap(DetermineType(outertype, field, name, mtype->KeyType, false, false), DetermineType(outertype, field, name, mtype->ValueType, false, false)); + break; } break; @@ -1381,7 +1399,8 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n { Error(field, "%s: Dynamic array types not implemented yet", name.GetChars()); auto atype = static_cast(ztype); - return NewDynArray(DetermineType(outertype, field, name, atype->ElementType, false)); + retval = NewDynArray(DetermineType(outertype, field, name, atype->ElementType, false, false)); + break; } break; @@ -1390,7 +1409,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n auto ctype = static_cast(ztype); if (ctype->Restriction == nullptr) { - return NewClassPointer(RUNTIME_CLASS(DObject)); + retval = NewClassPointer(RUNTIME_CLASS(DObject)); } else { @@ -1407,11 +1426,17 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n Error(field, "%s does not represent a class type", FName(ctype->Restriction->Id).GetChars()); return TypeError; } - return NewClassPointer(static_cast(typesym->Type)); + retval = NewClassPointer(static_cast(typesym->Type)); } + break; } } - return TypeError; + if (retval != TypeError && retval->MemberOnly && !formember) + { + Error(field, "Invalid type"); // fixme: Types need a descriptive name that can be output here. + return TypeError; + } + return retval; } //========================================================================== @@ -1900,7 +1925,7 @@ void ZCCCompiler::InitFunctions() { do { - auto type = DetermineType(c->Type(), f, f->Name, t, false); + auto type = DetermineType(c->Type(), f, f->Name, t, false, false); if (type->IsKindOf(RUNTIME_CLASS(PStruct))) { // structs and classes only get passed by pointer. @@ -1951,7 +1976,7 @@ void ZCCCompiler::InitFunctions() { if (p->Type != nullptr) { - auto type = DetermineType(c->Type(), p, f->Name, p->Type, false); + auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false); int flags; if (p->Flags & ZCC_In) flags |= VARF_In; if (p->Flags & ZCC_Out) flags |= VARF_Out; diff --git a/src/scripting/zscript/zcc_compile.h b/src/scripting/zscript/zcc_compile.h index 7a0246ea1..cf2775834 100644 --- a/src/scripting/zscript/zcc_compile.h +++ b/src/scripting/zscript/zcc_compile.h @@ -95,7 +95,7 @@ private: void CompileAllFields(); bool CompileFields(PStruct *type, TArray &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct); FString FlagsToString(uint32_t flags); - PType *DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes); + PType *DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes, bool formember); PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PSymbolTable *sym); PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym);