mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-23 04:22:34 +00:00
Allow calling const methods on readonly structs
This commit is contained in:
parent
0f031c5f22
commit
338e676e73
3 changed files with 27 additions and 23 deletions
|
@ -167,7 +167,8 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos)
|
|||
}
|
||||
}
|
||||
|
||||
bool FCompileContext::CheckReadOnly(int flags)
|
||||
// [ZZ] I find it really dumb that something called CheckReadOnly returns false for readonly. renamed.
|
||||
bool FCompileContext::CheckWritable(int flags)
|
||||
{
|
||||
if (!(flags & VARF_ReadOnly)) return false;
|
||||
if (!(flags & VARF_InternalAccess)) return true;
|
||||
|
@ -6202,7 +6203,7 @@ FxExpression *FxLocalVariable::Resolve(FCompileContext &ctx)
|
|||
bool FxLocalVariable::RequestAddress(FCompileContext &ctx, bool *writable)
|
||||
{
|
||||
AddressRequested = true;
|
||||
if (writable != nullptr) *writable = !ctx.CheckReadOnly(Variable->VarFlags);
|
||||
if (writable != nullptr) *writable = !ctx.CheckWritable(Variable->VarFlags);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -6420,7 +6421,7 @@ FxGlobalVariable::FxGlobalVariable(PField* mem, const FScriptPosition &pos)
|
|||
bool FxGlobalVariable::RequestAddress(FCompileContext &ctx, bool *writable)
|
||||
{
|
||||
AddressRequested = true;
|
||||
if (writable != nullptr) *writable = AddressWritable && !ctx.CheckReadOnly(membervar->Flags);
|
||||
if (writable != nullptr) *writable = AddressWritable && !ctx.CheckWritable(membervar->Flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -6610,7 +6611,7 @@ FxStackVariable::~FxStackVariable()
|
|||
bool FxStackVariable::RequestAddress(FCompileContext &ctx, bool *writable)
|
||||
{
|
||||
AddressRequested = true;
|
||||
if (writable != nullptr) *writable = AddressWritable && !ctx.CheckReadOnly(membervar->Flags);
|
||||
if (writable != nullptr) *writable = AddressWritable && !ctx.CheckWritable(membervar->Flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -6708,7 +6709,7 @@ bool FxStructMember::RequestAddress(FCompileContext &ctx, bool *writable)
|
|||
return false;
|
||||
}
|
||||
AddressRequested = true;
|
||||
if (writable != nullptr) *writable = (AddressWritable && !ctx.CheckReadOnly(membervar->Flags) &&
|
||||
if (writable != nullptr) *writable = (AddressWritable && !ctx.CheckWritable(membervar->Flags) &&
|
||||
(!classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) || !static_cast<PPointer*>(classx->ValueType)->IsConst));
|
||||
return true;
|
||||
}
|
||||
|
@ -7618,6 +7619,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
PStruct *cls;
|
||||
bool staticonly = false;
|
||||
bool novirtual = false;
|
||||
bool isreadonly = false;
|
||||
|
||||
PStruct *ccls = nullptr;
|
||||
|
||||
|
@ -7912,7 +7914,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
auto x = new FxGetParentClass(Self);
|
||||
return x->Resolve(ctx);
|
||||
}
|
||||
|
||||
|
||||
if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)) && !Self->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||
{
|
||||
auto ptype = static_cast<PPointer *>(Self->ValueType)->PointedType;
|
||||
|
@ -7943,18 +7945,11 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
else if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)))
|
||||
{
|
||||
bool writable;
|
||||
if (Self->RequestAddress(ctx, &writable) && writable)
|
||||
{
|
||||
cls = static_cast<PStruct*>(Self->ValueType);
|
||||
Self->ValueType = NewPointer(Self->ValueType);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cannot be made writable so we cannot use its methods.
|
||||
ScriptPosition.Message(MSG_ERROR, "Invalid expression on left hand side of %s\n", MethodName.GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// [ZZ] allow const method to be called on a readonly struct
|
||||
isreadonly = !(Self->RequestAddress(ctx, &writable) && writable);
|
||||
cls = static_cast<PStruct*>(Self->ValueType);
|
||||
Self->ValueType = NewPointer(Self->ValueType);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -7981,6 +7976,15 @@ isresolved:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (isreadonly && !(afd->Variants[0].Flags & VARF_ReadOnly))
|
||||
{
|
||||
// Cannot be made writable so we cannot use its methods.
|
||||
// [ZZ] Why this esoteric message?
|
||||
ScriptPosition.Message(MSG_ERROR, "Readonly struct on left hand side of %s not allowed\n", MethodName.GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (staticonly && (afd->Variants[0].Flags & VARF_Method))
|
||||
{
|
||||
if (!novirtual || !(afd->Variants[0].Flags & VARF_Virtual))
|
||||
|
|
|
@ -219,7 +219,7 @@ struct FCompileContext
|
|||
|
||||
void HandleJumps(int token, FxExpression *handler);
|
||||
void CheckReturn(PPrototype *proto, FScriptPosition &pos);
|
||||
bool CheckReadOnly(int flags);
|
||||
bool CheckWritable(int flags);
|
||||
FxLocalVariableDeclaration *FindLocalVariable(FName name);
|
||||
};
|
||||
|
||||
|
|
|
@ -579,10 +579,10 @@ struct StringStruct native
|
|||
native vararg void AppendFormat(String fmt, ...);
|
||||
|
||||
native void Replace(String pattern, String replacement);
|
||||
native String Mid(int pos = 0, int len = 2147483647);
|
||||
native int Len();
|
||||
native String CharAt(int pos);
|
||||
native int CharCodeAt(int pos);
|
||||
native String Mid(int pos = 0, int len = 2147483647) const;
|
||||
native int Len() const;
|
||||
native String CharAt(int pos) const;
|
||||
native int CharCodeAt(int pos) const;
|
||||
}
|
||||
|
||||
class Floor : Thinker native
|
||||
|
|
Loading…
Reference in a new issue