Allow calling const methods on readonly structs

This commit is contained in:
ZZYZX 2017-02-17 19:25:29 +02:00
parent 0f031c5f22
commit 338e676e73
3 changed files with 27 additions and 23 deletions

View file

@ -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;
@ -7943,20 +7945,13 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
else if (Self->ValueType->IsKindOf(RUNTIME_CLASS(PStruct)))
{
bool writable;
if (Self->RequestAddress(ctx, &writable) && writable)
{
// [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
{
// 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;
}
}
else
{
ScriptPosition.Message(MSG_ERROR, "Invalid expression on left hand side of %s\n", MethodName.GetChars());
delete this;
@ -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))

View file

@ -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);
};

View file

@ -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