- added an option to FindClassTentative to make eventual failure to declare the missing class non-fatal.

Damn those old mods with broken actor references. Thanks to those FxClassTypeCast may not throw fatal errors.
This commit is contained in:
Christoph Oelckers 2016-02-09 12:26:00 +01:00
parent 26b657b637
commit 6c92525fcd
4 changed files with 32 additions and 24 deletions

View file

@ -2322,13 +2322,20 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
const PClass *existclass = FindClass(name); const PClass *existclass = FindClass(name);
// This is a placeholder so fill it in // This is a placeholder so fill it in
if (existclass != NULL && existclass->Size == (unsigned)-1) if (existclass != NULL && (existclass->Size == TClass_Fatal || existclass->Size == TClass_Nonfatal))
{ {
type = const_cast<PClass*>(existclass); type = const_cast<PClass*>(existclass);
if (!IsDescendantOf(type->ParentClass)) if (!IsDescendantOf(type->ParentClass))
{
if (existclass->Size == TClass_Fatal)
{ {
I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars()); I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars());
} }
else
{
Printf(TEXTCOLOR_RED "%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars());
}
}
DPrintf("Defining placeholder class %s\n", name.GetChars()); DPrintf("Defining placeholder class %s\n", name.GetChars());
notnew = true; notnew = true;
} }
@ -2380,7 +2387,7 @@ unsigned int PClass::Extend(unsigned int extension)
// //
//========================================================================== //==========================================================================
PClass *PClass::FindClassTentative(FName name) PClass *PClass::FindClassTentative(FName name, bool fatal)
{ {
if (name == NAME_None) if (name == NAME_None)
{ {
@ -2400,7 +2407,7 @@ PClass *PClass::FindClassTentative(FName name)
type->TypeName = name; type->TypeName = name;
type->ParentClass = this; type->ParentClass = this;
type->Size = -1; type->Size = fatal? TClass_Fatal : TClass_Nonfatal;
type->bRuntimeClass = true; type->bRuntimeClass = true;
TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket); TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket);
return type; return type;

View file

@ -599,6 +599,12 @@ public:
// Meta-info for every class derived from DObject --------------------------- // Meta-info for every class derived from DObject ---------------------------
enum
{
TClass_Fatal = UINT_MAX,
TClass_Nonfatal = UINT_MAX - 1
};
class PClassClass; class PClassClass;
class PClass : public PStruct class PClass : public PStruct
{ {
@ -661,7 +667,7 @@ public:
static PClassActor *FindActor(const FString &name) { return FindActor(FName(name, true)); } static PClassActor *FindActor(const FString &name) { return FindActor(FName(name, true)); }
static PClassActor *FindActor(ENamedName name) { return FindActor(FName(name)); } static PClassActor *FindActor(ENamedName name) { return FindActor(FName(name)); }
static PClassActor *FindActor(FName name); static PClassActor *FindActor(FName name);
PClass *FindClassTentative(FName name); // not static! PClass *FindClassTentative(FName name, bool fatal = true); // not static!
static TArray<PClass *> AllClasses; static TArray<PClass *> AllClasses;

View file

@ -340,10 +340,15 @@ static void FinishThingdef()
{ {
PClassActor *ti = PClassActor::AllActorClasses[i]; PClassActor *ti = PClassActor::AllActorClasses[i];
if (ti->Size == (unsigned)-1) if (ti->Size == TClass_Fatal || ti->Size == TClass_Nonfatal)
{ {
Printf("Class %s referenced but not defined\n", ti->TypeName.GetChars()); Printf(TEXTCOLOR_RED "Class %s referenced but not defined\n", ti->TypeName.GetChars());
errorcount++; if (ti->Size == TClass_Fatal) errorcount++;
else
{
// In order to prevent a crash, this class needs to be completed, even though it defines nothing.
ti->ParentClass->CreateDerivedClass(ti->TypeName, ti->ParentClass->Size);
}
continue; continue;
} }

View file

@ -3546,24 +3546,14 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
if (clsname != NAME_None) if (clsname != NAME_None)
{ {
cls = desttype->FindClassTentative(clsname); // for backwards compatibility with old times it cannot be made a fatal error, if the class is not defined. :(
if (cls == NULL) cls = desttype->FindClassTentative(clsname, false);
{
/* lax */
// Since this happens in released WADs it must pass without a terminal error... :(
ScriptPosition.Message(MSG_WARNING,
"Unknown class name '%s'",
clsname.GetChars(), desttype->TypeName.GetChars());
}
else
{
if (!cls->IsDescendantOf(desttype)) if (!cls->IsDescendantOf(desttype))
{ {
ScriptPosition.Message(MSG_ERROR,"class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); ScriptPosition.Message(MSG_ERROR,"class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars());
delete this; delete this;
return NULL; return NULL;
} }
}
ScriptPosition.Message(MSG_DEBUG,"resolving '%s' as class name", clsname.GetChars()); ScriptPosition.Message(MSG_DEBUG,"resolving '%s' as class name", clsname.GetChars());
} }
FxExpression *x = new FxConstant(cls, ScriptPosition); FxExpression *x = new FxConstant(cls, ScriptPosition);