|
|
@@ -1,6 +1,6 @@
|
|
|
/*
|
|
|
AngelCode Scripting Library
|
|
|
- Copyright (c) 2003-2019 Andreas Jonsson
|
|
|
+ Copyright (c) 2003-2020 Andreas Jonsson
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
warranty. In no event will the authors be held liable for any
|
|
|
@@ -28,7 +28,7 @@
|
|
|
[email protected]
|
|
|
*/
|
|
|
|
|
|
-// Modified by Lasse Oorni for Urho3D
|
|
|
+// Modified for Urho3D
|
|
|
|
|
|
//
|
|
|
// as_compiler.cpp
|
|
|
@@ -103,6 +103,10 @@ asCCompiler::~asCCompiler()
|
|
|
for (asUINT n = 0; n < usedStringConstants.GetLength(); n++)
|
|
|
engine->stringFactory->ReleaseStringConstant(usedStringConstants[n]);
|
|
|
usedStringConstants.SetLength(0);
|
|
|
+
|
|
|
+ // Clean up the temporary script nodes that were allocated during compilation
|
|
|
+ for (asUINT n = 0; n < nodesToFreeUponComplete.GetLength(); n++)
|
|
|
+ nodesToFreeUponComplete[n]->Destroy(engine);
|
|
|
}
|
|
|
|
|
|
void asCCompiler::Reset(asCBuilder *in_builder, asCScriptCode *in_script, asCScriptFunction *in_outFunc)
|
|
|
@@ -353,7 +357,9 @@ int asCCompiler::SetupParametersAndReturnVariable(asCArray<asCString> ¶meter
|
|
|
|
|
|
// Is the return type allowed?
|
|
|
if( returnType != asCDataType::CreatePrimitive(ttVoid, false) &&
|
|
|
- !returnType.CanBeInstantiated() )
|
|
|
+ !returnType.CanBeInstantiated() &&
|
|
|
+ !returnType.IsReference() &&
|
|
|
+ !returnType.IsObjectHandle() )
|
|
|
{
|
|
|
// TODO: Hasn't this been validated by the builder already?
|
|
|
asCString str;
|
|
|
@@ -432,6 +438,7 @@ void asCCompiler::CompileMemberInitialization(asCByteCode *bc, bool onlyDefaults
|
|
|
asCObjectProperty *prop = outFunc->objectType->properties[n];
|
|
|
|
|
|
// Check if the property has an initialization expression
|
|
|
+ asCParser parser(builder);
|
|
|
asCScriptNode *declNode = 0;
|
|
|
asCScriptNode *initNode = 0;
|
|
|
asCScriptCode *initScript = 0;
|
|
|
@@ -467,7 +474,6 @@ void asCCompiler::CompileMemberInitialization(asCByteCode *bc, bool onlyDefaults
|
|
|
initScript = script;
|
|
|
#else
|
|
|
// Re-parse the initialization expression as the parser now knows the types, which it didn't earlier
|
|
|
- asCParser parser(builder);
|
|
|
int r = parser.ParseVarInit(initScript, initNode);
|
|
|
if( r < 0 )
|
|
|
continue;
|
|
|
@@ -1474,7 +1480,8 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asCExprContext *ctx, as
|
|
|
int offset;
|
|
|
if( refType == asTM_INREF )
|
|
|
{
|
|
|
- ProcessPropertyGetAccessor(ctx, node);
|
|
|
+ if( ProcessPropertyGetAccessor(ctx, node) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
// Add the type id as hidden arg if the parameter is a ? type
|
|
|
if( paramType->GetTokenType() == ttQuestion )
|
|
|
@@ -1761,7 +1768,8 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asCExprContext *ctx, as
|
|
|
}
|
|
|
else if( refType == asTM_INOUTREF )
|
|
|
{
|
|
|
- ProcessPropertyGetAccessor(ctx, node);
|
|
|
+ if( ProcessPropertyGetAccessor(ctx, node) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
// Add the type id as hidden arg if the parameter is a ? type
|
|
|
if( paramType->GetTokenType() == ttQuestion )
|
|
|
@@ -1795,7 +1803,10 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asCExprContext *ctx, as
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // Perform implicit ref cast if necessary, but don't allow the implicit conversion to create new objects
|
|
|
+ // Allow anonymous init lists to be converted to the arg type
|
|
|
+ if( ctx->IsAnonymousInitList() )
|
|
|
+ ImplicitConversion(ctx, dt, node, asIC_IMPLICIT_CONV, true, true);
|
|
|
+
|
|
|
if( (ctx->type.dataType.IsObject() || ctx->type.dataType.IsFuncdef()) && ctx->type.dataType.GetTypeInfo() != dt.GetTypeInfo() )
|
|
|
ImplicitConversion(ctx, dt, node, asIC_IMPLICIT_CONV, true, false);
|
|
|
|
|
|
@@ -1857,7 +1868,8 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asCExprContext *ctx, as
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- ProcessPropertyGetAccessor(ctx, node);
|
|
|
+ if( ProcessPropertyGetAccessor(ctx, node) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
if( dt.IsPrimitive() )
|
|
|
{
|
|
|
@@ -2317,6 +2329,12 @@ int asCCompiler::CompileDefaultAndNamedArgs(asCScriptNode *node, asCArray<asCExp
|
|
|
}
|
|
|
|
|
|
MergeExprBytecodeAndType(args[n], &expr);
|
|
|
+ if (args[n]->exprNode)
|
|
|
+ {
|
|
|
+ // Disconnect the node from the parser, and tell the compiler to free it when complete
|
|
|
+ args[n]->exprNode->DisconnectParent();
|
|
|
+ nodesToFreeUponComplete.PushLast(args[n]->exprNode);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
reservedVariables.SetLength(prevReservedVars);
|
|
|
@@ -2650,6 +2668,8 @@ bool asCCompiler::CompileAutoType(asCDataType &type, asCExprContext &compiledCtx
|
|
|
// Handle const qualifier on auto
|
|
|
if (type.IsReadOnly())
|
|
|
newType.MakeReadOnly(true);
|
|
|
+ else if (type.IsHandleToConst())
|
|
|
+ newType.MakeHandleToConst(true);
|
|
|
else if (newType.IsPrimitive())
|
|
|
newType.MakeReadOnly(false);
|
|
|
|
|
|
@@ -3990,7 +4010,8 @@ void asCCompiler::CompileSwitchStatement(asCScriptNode *snode, bool *, asCByteCo
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- ProcessPropertyGetAccessor(&expr, snode);
|
|
|
+ if( ProcessPropertyGetAccessor(&expr, snode) < 0 )
|
|
|
+ return;
|
|
|
|
|
|
// TODO: Need to support 64bit integers
|
|
|
// Convert the expression to a 32bit variable
|
|
|
@@ -4353,7 +4374,8 @@ void asCCompiler::CompileIfStatement(asCScriptNode *inode, bool *hasReturn, asCB
|
|
|
{
|
|
|
if( !expr.type.isConstant )
|
|
|
{
|
|
|
- ProcessPropertyGetAccessor(&expr, inode);
|
|
|
+ if( ProcessPropertyGetAccessor(&expr, inode) < 0 )
|
|
|
+ return;
|
|
|
ConvertToVariable(&expr);
|
|
|
ProcessDeferredParams(&expr);
|
|
|
|
|
|
@@ -4505,7 +4527,8 @@ void asCCompiler::CompileForStatement(asCScriptNode *fnode, asCByteCode *bc)
|
|
|
Error(TXT_EXPR_MUST_BE_BOOL, second);
|
|
|
else
|
|
|
{
|
|
|
- ProcessPropertyGetAccessor(&expr, second);
|
|
|
+ if( ProcessPropertyGetAccessor(&expr, second) < 0 )
|
|
|
+ return;
|
|
|
ConvertToVariable(&expr);
|
|
|
ProcessDeferredParams(&expr);
|
|
|
|
|
|
@@ -4617,7 +4640,8 @@ void asCCompiler::CompileWhileStatement(asCScriptNode *wnode, asCByteCode *bc)
|
|
|
Error(TXT_EXPR_MUST_BE_BOOL, wnode->firstChild);
|
|
|
else
|
|
|
{
|
|
|
- ProcessPropertyGetAccessor(&expr, wnode);
|
|
|
+ if( ProcessPropertyGetAccessor(&expr, wnode) < 0 )
|
|
|
+ return;
|
|
|
ConvertToVariable(&expr);
|
|
|
ProcessDeferredParams(&expr);
|
|
|
|
|
|
@@ -4706,7 +4730,8 @@ void asCCompiler::CompileDoWhileStatement(asCScriptNode *wnode, asCByteCode *bc)
|
|
|
Error(TXT_EXPR_MUST_BE_BOOL, wnode->firstChild);
|
|
|
else
|
|
|
{
|
|
|
- ProcessPropertyGetAccessor(&expr, wnode);
|
|
|
+ if( ProcessPropertyGetAccessor(&expr, wnode) < 0 )
|
|
|
+ return;
|
|
|
ConvertToVariable(&expr);
|
|
|
ProcessDeferredParams(&expr);
|
|
|
|
|
|
@@ -4797,7 +4822,8 @@ void asCCompiler::CompileExpressionStatement(asCScriptNode *enode, asCByteCode *
|
|
|
// accessor, then process it as a get access. Don't call if there is
|
|
|
// already a compile error, or we might report an error that is not valid
|
|
|
if( !hasCompileErrors )
|
|
|
- ProcessPropertyGetAccessor(&expr, enode);
|
|
|
+ if( ProcessPropertyGetAccessor(&expr, enode) < 0 )
|
|
|
+ return;
|
|
|
|
|
|
// Pop the value from the stack
|
|
|
if( !expr.type.dataType.IsPrimitive() )
|
|
|
@@ -4830,7 +4856,7 @@ void asCCompiler::PrepareTemporaryVariable(asCScriptNode *node, asCExprContext *
|
|
|
{
|
|
|
ctx->bc.Instr(asBC_PopPtr);
|
|
|
ctx->bc.InstrSHORT(asBC_PSF, ctx->type.stackOffset);
|
|
|
- ctx->type.dataType.MakeReference(true);
|
|
|
+ ctx->type.dataType.MakeReference(IsVariableOnHeap(ctx->type.stackOffset));
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
@@ -4993,7 +5019,6 @@ void asCCompiler::CompileReturnStatement(asCScriptNode *rnode, asCByteCode *bc)
|
|
|
// be done before the expression is evaluated.
|
|
|
DestroyVariables(bc);
|
|
|
|
|
|
-
|
|
|
// For primitives the reference is already in the register,
|
|
|
// but for non-primitives the reference is on the stack so we
|
|
|
// need to load it into the register
|
|
|
@@ -5010,7 +5035,8 @@ void asCCompiler::CompileReturnStatement(asCScriptNode *rnode, asCByteCode *bc)
|
|
|
}
|
|
|
else // if( !v->type.IsReference() )
|
|
|
{
|
|
|
- ProcessPropertyGetAccessor(&expr, rnode);
|
|
|
+ if( ProcessPropertyGetAccessor(&expr, rnode) < 0 )
|
|
|
+ return;
|
|
|
|
|
|
// Prepare the value for assignment
|
|
|
IsVariableInitialized(&expr.type, rnode->firstChild);
|
|
|
@@ -5499,8 +5525,8 @@ void asCCompiler::PrepareForAssignment(asCDataType *lvalue, asCExprContext *rctx
|
|
|
int l = int(reservedVariables.GetLength());
|
|
|
if( lvalueExpr ) lvalueExpr->bc.GetVarsUsed(reservedVariables);
|
|
|
|
|
|
-
|
|
|
- ProcessPropertyGetAccessor(rctx, node);
|
|
|
+ if( ProcessPropertyGetAccessor(rctx, node) < 0 )
|
|
|
+ return;
|
|
|
|
|
|
// Make sure the rvalue is initialized if it is a variable
|
|
|
IsVariableInitialized(&rctx->type, node);
|
|
|
@@ -8276,8 +8302,8 @@ int asCCompiler::DoAssignment(asCExprContext *ctx, asCExprContext *lctx, asCExpr
|
|
|
lctx->type.isExplicitHandle = true;
|
|
|
}
|
|
|
|
|
|
- // Urho3D: if there is a handle type, and it does not have an overloaded assignment operator, convert to an explicit handle
|
|
|
- // for scripting convenience. (For the Urho3D handle types, value assignment is not supported)
|
|
|
+ // Urho3D: if there is a handle type, and it does not have an overloaded assignment operator, convert to an explicit handle
|
|
|
+ // for scripting convenience. (For the Urho3D handle types, value assignment is not supported)
|
|
|
if (lctx->type.dataType.IsObjectHandle() && !lctx->type.dataType.IsTemplate() && !lctx->type.isExplicitHandle &&
|
|
|
(!lctx->type.dataType.GetBehaviour() || !lctx->type.dataType.GetBehaviour()->copy))
|
|
|
lctx->type.isExplicitHandle = true;
|
|
|
@@ -8319,7 +8345,8 @@ int asCCompiler::DoAssignment(asCExprContext *ctx, asCExprContext *lctx, asCExpr
|
|
|
else if( lctx->property_get && lctx->type.dataType.IsObjectHandle() && !lctx->type.isExplicitHandle )
|
|
|
{
|
|
|
// Get the handle to the object that will be used for the value assignment
|
|
|
- ProcessPropertyGetAccessor(lctx, opNode);
|
|
|
+ if( ProcessPropertyGetAccessor(lctx, opNode) < 0 )
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
if( lctx->type.dataType.IsPrimitive() )
|
|
|
@@ -8517,9 +8544,20 @@ int asCCompiler::DoAssignment(asCExprContext *ctx, asCExprContext *lctx, asCExpr
|
|
|
bool needConversion = false;
|
|
|
if( !lctx->type.dataType.IsEqualExceptRefAndConst(rctx->type.dataType) )
|
|
|
needConversion = true;
|
|
|
-
|
|
|
+
|
|
|
if( !simpleExpr || needConversion )
|
|
|
{
|
|
|
+ if( rctx->type.dataType.IsObjectHandle() && !rctx->type.isExplicitHandle &&
|
|
|
+ !lctx->type.dataType.IsObjectHandle() && rctx->type.dataType.GetTypeInfo() == lctx->type.dataType.GetTypeInfo() )
|
|
|
+ {
|
|
|
+ // Make the conversion from handle to non-handle without creating
|
|
|
+ // a copy of the object (otherwise done by PrepareArgument)
|
|
|
+ asCDataType dt = rctx->type.dataType;
|
|
|
+ dt.MakeHandle(false);
|
|
|
+ ImplicitConversion(rctx, dt, rexpr, asIC_IMPLICIT_CONV);
|
|
|
+ needConversion = false;
|
|
|
+ }
|
|
|
+
|
|
|
asCDataType dt = lctx->type.dataType;
|
|
|
dt.MakeReference(true);
|
|
|
// A funcdef can be accessed by ref, but only as read-only
|
|
|
@@ -8539,7 +8577,8 @@ int asCCompiler::DoAssignment(asCExprContext *ctx, asCExprContext *lctx, asCExpr
|
|
|
else
|
|
|
{
|
|
|
// Process any property accessor first, before placing the final reference on the stack
|
|
|
- ProcessPropertyGetAccessor(rctx, rexpr);
|
|
|
+ if( ProcessPropertyGetAccessor(rctx, rexpr) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
if( rctx->type.dataType.IsReference() && (!(rctx->type.isVariable || rctx->type.isTemporary) || IsVariableOnHeap(rctx->type.stackOffset)) )
|
|
|
rctx->bc.Instr(asBC_RDSPtr);
|
|
|
@@ -8621,7 +8660,8 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asCExprContext *ctx)
|
|
|
}
|
|
|
ctype = e.type;
|
|
|
|
|
|
- ProcessPropertyGetAccessor(&e, cexpr);
|
|
|
+ if( ProcessPropertyGetAccessor(&e, cexpr) < 0)
|
|
|
+ return -1;
|
|
|
|
|
|
if( e.type.dataType.IsReference() ) ConvertToVariable(&e);
|
|
|
ProcessDeferredParams(&e);
|
|
|
@@ -8649,8 +8689,10 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asCExprContext *ctx)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- ProcessPropertyGetAccessor(&le, cexpr->next);
|
|
|
- ProcessPropertyGetAccessor(&re, cexpr->next->next);
|
|
|
+ if( ProcessPropertyGetAccessor(&le, cexpr->next) < 0 )
|
|
|
+ return -1;
|
|
|
+ if( ProcessPropertyGetAccessor(&re, cexpr->next->next) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
bool isExplicitHandle = le.type.isExplicitHandle || re.type.isExplicitHandle;
|
|
|
|
|
|
@@ -9131,13 +9173,17 @@ int asCCompiler::CompileExpressionTerm(asCScriptNode *node, asCExprContext *ctx)
|
|
|
vnode = vnode->next;
|
|
|
|
|
|
asCExprContext v(engine);
|
|
|
- int r = CompileExpressionValue(vnode, &v); if( r < 0 ) return r;
|
|
|
+ int r = CompileExpressionValue(vnode, &v);
|
|
|
+ if( r < 0 )
|
|
|
+ return r;
|
|
|
|
|
|
// Compile post fix operators
|
|
|
asCScriptNode *pnode = vnode->next;
|
|
|
while( pnode )
|
|
|
{
|
|
|
- r = CompileExpressionPostOp(pnode, &v); if( r < 0 ) return r;
|
|
|
+ r = CompileExpressionPostOp(pnode, &v);
|
|
|
+ if( r < 0 )
|
|
|
+ return r;
|
|
|
pnode = pnode->next;
|
|
|
}
|
|
|
|
|
|
@@ -9145,7 +9191,9 @@ int asCCompiler::CompileExpressionTerm(asCScriptNode *node, asCExprContext *ctx)
|
|
|
pnode = vnode->prev;
|
|
|
while( pnode )
|
|
|
{
|
|
|
- r = CompileExpressionPreOp(pnode, &v); if( r < 0 ) return r;
|
|
|
+ r = CompileExpressionPreOp(pnode, &v);
|
|
|
+ if( r < 0 )
|
|
|
+ return r;
|
|
|
pnode = pnode->prev;
|
|
|
}
|
|
|
|
|
|
@@ -9201,9 +9249,10 @@ asCCompiler::SYMBOLTYPE asCCompiler::SymbolLookupMember(const asCString &name, a
|
|
|
// Normal property access
|
|
|
r = FindPropertyAccessor(name, &access, 0, 0, true);
|
|
|
}
|
|
|
- if (r < 0) return SL_ERROR;
|
|
|
- if (access.property_get || access.property_set)
|
|
|
+ if (r <= -3) return SL_ERROR;
|
|
|
+ if (r != 0)
|
|
|
{
|
|
|
+ // The symbol matches getters/setters (though not necessarily a compilable match)
|
|
|
MergeExprBytecodeAndType(outResult, &access);
|
|
|
outResult->type.dataType.SetTypeInfo(objType);
|
|
|
return SL_CLASSPROPACCESS;
|
|
|
@@ -9225,7 +9274,7 @@ asCCompiler::SYMBOLTYPE asCCompiler::SymbolLookupMember(const asCString &name, a
|
|
|
{
|
|
|
asCScriptFunction *f = engine->scriptFunctions[ot->methods[n]];
|
|
|
if (f->name == name &&
|
|
|
- (builder->module->accessMask & f->accessMask))
|
|
|
+ (builder->module->m_accessMask & f->accessMask))
|
|
|
{
|
|
|
outResult->type.dataType.SetTypeInfo(objType);
|
|
|
return SL_CLASSMETHOD;
|
|
|
@@ -9281,10 +9330,10 @@ asCCompiler::SYMBOLTYPE asCCompiler::SymbolLookup(const asCString &name, const a
|
|
|
}
|
|
|
|
|
|
// Is it a class member?
|
|
|
- // This is not accessible by default arg expressions
|
|
|
- if (!isCompilingDefaultArg && scope == "" && ((objType) || (outFunc && outFunc->objectType)))
|
|
|
+ if (scope == "" && ((objType) || (outFunc && outFunc->objectType)))
|
|
|
{
|
|
|
- if (name == THIS_TOKEN && !objType)
|
|
|
+ // 'this' is not accessible by default arg expressions
|
|
|
+ if (name == THIS_TOKEN && !objType && !isCompilingDefaultArg)
|
|
|
{
|
|
|
asCDataType dt = asCDataType::CreateType(outFunc->objectType, outFunc->IsReadOnly());
|
|
|
|
|
|
@@ -9293,7 +9342,8 @@ asCCompiler::SYMBOLTYPE asCCompiler::SymbolLookup(const asCString &name, const a
|
|
|
return SL_THISPTR;
|
|
|
}
|
|
|
|
|
|
- if (m_isConstructor && name == SUPER_TOKEN && !objType)
|
|
|
+ // 'super' is not accessible by default arg expressions
|
|
|
+ if (m_isConstructor && name == SUPER_TOKEN && !objType && !isCompilingDefaultArg)
|
|
|
{
|
|
|
// If the class is derived from another class, then super can be used to call the base' class constructor
|
|
|
if (outFunc && outFunc->objectType->derivedFrom)
|
|
|
@@ -9304,9 +9354,13 @@ asCCompiler::SYMBOLTYPE asCCompiler::SymbolLookup(const asCString &name, const a
|
|
|
}
|
|
|
|
|
|
// Look for members in the type
|
|
|
- SYMBOLTYPE r = SymbolLookupMember(name, objType ? objType : outFunc->objectType, outResult);
|
|
|
- if (r != 0)
|
|
|
- return r;
|
|
|
+ // class members are only accessible in default arg expressions as post op '.'
|
|
|
+ if( !isCompilingDefaultArg || (isCompilingDefaultArg && objType) )
|
|
|
+ {
|
|
|
+ SYMBOLTYPE r = SymbolLookupMember(name, objType ? objType : outFunc->objectType, outResult);
|
|
|
+ if (r != 0)
|
|
|
+ return r;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// Recursively search parent namespaces for global entities
|
|
|
@@ -9420,9 +9474,10 @@ asCCompiler::SYMBOLTYPE asCCompiler::SymbolLookup(const asCString &name, const a
|
|
|
// Normal property access
|
|
|
r = FindPropertyAccessor(name, &access, 0, ns);
|
|
|
}
|
|
|
- if (r < 0) return SL_ERROR;
|
|
|
- if (access.property_get || access.property_set)
|
|
|
+ if (r <= -3) return SL_ERROR;
|
|
|
+ if (r != 0)
|
|
|
{
|
|
|
+ // The symbol matches getters/setters (though not necessarily a compilable match)
|
|
|
MergeExprBytecodeAndType(outResult, &access);
|
|
|
outResult->symbolNamespace = ns;
|
|
|
return SL_GLOBALPROPACCESS;
|
|
|
@@ -9801,7 +9856,7 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s
|
|
|
{
|
|
|
asCScriptFunction *f = engine->scriptFunctions[ot->methods[n]];
|
|
|
if (f->name == name &&
|
|
|
- (builder->module->accessMask & f->accessMask))
|
|
|
+ (builder->module->m_accessMask & f->accessMask))
|
|
|
{
|
|
|
func = f;
|
|
|
break;
|
|
|
@@ -10631,7 +10686,8 @@ int asCCompiler::CompileConversion(asCScriptNode *node, asCExprContext *ctx)
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- ProcessPropertyGetAccessor(&expr, node);
|
|
|
+ if( ProcessPropertyGetAccessor(&expr, node) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
// Don't allow any operators on expressions that take address of class method
|
|
|
if( expr.IsClassMethod() )
|
|
|
@@ -10866,7 +10922,7 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asCExprContext *ctx)
|
|
|
|
|
|
// It is possible that the name is really a constructor
|
|
|
asCDataType dt;
|
|
|
- dt = builder->CreateDataTypeFromNode(node->firstChild, script, outFunc->nameSpace);
|
|
|
+ dt = builder->CreateDataTypeFromNode(node->firstChild, script, outFunc->nameSpace, false, outFunc->objectType);
|
|
|
if( dt.IsPrimitive() )
|
|
|
{
|
|
|
// This is a cast to a primitive type
|
|
|
@@ -10927,9 +10983,13 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asCExprContext *ctx)
|
|
|
if( args.GetLength() == 1 )
|
|
|
{
|
|
|
asCExprContext conv(engine);
|
|
|
- conv.type = args[0]->type;
|
|
|
+ conv.Copy(args[0]);
|
|
|
asUINT cost = ImplicitConversion(&conv, dt, node->lastChild, asIC_EXPLICIT_VAL_CAST, false);
|
|
|
|
|
|
+ // Clean the property_arg in the temporary copy so
|
|
|
+ // it isn't deleted when conv goes out of scope
|
|
|
+ conv.property_arg = 0;
|
|
|
+
|
|
|
// Don't use this if the cost is 0 because it would mean that nothing
|
|
|
// is done and the script wants a new value to be constructed
|
|
|
if( conv.type.dataType.IsEqualExceptRef(dt) && cost > 0 )
|
|
|
@@ -10938,7 +10998,8 @@ int asCCompiler::CompileConstructCall(asCScriptNode *node, asCExprContext *ctx)
|
|
|
dt.MakeReference(true);
|
|
|
|
|
|
// Make sure any property accessor is already evaluated
|
|
|
- ProcessPropertyGetAccessor(args[0], args[0]->exprNode);
|
|
|
+ if( ProcessPropertyGetAccessor(args[0], args[0]->exprNode) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
ImplicitConversion(args[0], dt, node->lastChild, asIC_EXPLICIT_VAL_CAST);
|
|
|
|
|
|
@@ -11218,19 +11279,10 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asCExprContext *ctx, a
|
|
|
symbolType == SL_GLOBALPROPACCESS || symbolType == SL_GLOBALCONST || symbolType == SL_GLOBALVAR || symbolType == SL_ENUMVAL)
|
|
|
{
|
|
|
// Variables/properties can be used as functions if they have the opCall
|
|
|
- if (!(lookupResult.type.dataType.IsFuncdef() || lookupResult.type.dataType.IsObject()))
|
|
|
- {
|
|
|
- // The variable is not a function or object with opCall
|
|
|
- asCString msg;
|
|
|
- msg.Format(TXT_NOT_A_FUNC_s_IS_TYPE_s, name.AddressOf(), lookupResult.type.dataType.Format(outFunc->nameSpace).AddressOf());
|
|
|
- Error(msg, node);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
+
|
|
|
// Compile the variable
|
|
|
// TODO: Take advantage of the known symbol, so it doesn't have to be looked up again
|
|
|
localVar = CompileVariableAccess(name, scope, &funcExpr, node, false, objectType);
|
|
|
- asASSERT(localVar >= 0);
|
|
|
if( localVar < 0 )
|
|
|
return -1;
|
|
|
|
|
|
@@ -11264,7 +11316,8 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asCExprContext *ctx, a
|
|
|
funcExpr.property_ref = ctx->type.dataType.IsReference();
|
|
|
}
|
|
|
MergeExprBytecodeAndType(ctx, &funcExpr);
|
|
|
- ProcessPropertyGetAccessor(ctx, node);
|
|
|
+ if( ProcessPropertyGetAccessor(ctx, node) < 0 )
|
|
|
+ return -1;
|
|
|
Dereference(ctx, true);
|
|
|
|
|
|
objectType = CastToObjectType(funcExpr.type.dataType.GetTypeInfo());
|
|
|
@@ -11277,6 +11330,14 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asCExprContext *ctx, a
|
|
|
|
|
|
builder->GetObjectMethodDescriptions("opCall", CastToObjectType(funcExpr.type.dataType.GetTypeInfo()), funcs, objIsConst);
|
|
|
}
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // The variable is not a function or object with opCall
|
|
|
+ asCString msg;
|
|
|
+ msg.Format(TXT_NOT_A_FUNC_s_IS_TYPE_s, name.AddressOf(), lookupResult.type.dataType.Format(outFunc->nameSpace).AddressOf());
|
|
|
+ Error(msg, node);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// Is the symbol matching a class method?
|
|
|
@@ -11373,7 +11434,7 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asCExprContext *ctx, a
|
|
|
if (symbolType == SL_CLASSTYPE || symbolType == SL_GLOBALTYPE)
|
|
|
{
|
|
|
bool isValid = false;
|
|
|
- asCDataType dt = builder->CreateDataTypeFromNode(node->firstChild, script, outFunc->nameSpace, false, 0, false, &isValid);
|
|
|
+ asCDataType dt = builder->CreateDataTypeFromNode(node->firstChild, script, outFunc->nameSpace, false, outFunc->objectType, false, &isValid);
|
|
|
if (isValid)
|
|
|
return CompileConstructCall(node, ctx);
|
|
|
}
|
|
|
@@ -11427,7 +11488,8 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asCExprContext *ctx, a
|
|
|
|
|
|
if( funcExpr.property_get > 0 )
|
|
|
{
|
|
|
- ProcessPropertyGetAccessor(&funcExpr, node);
|
|
|
+ if( ProcessPropertyGetAccessor(&funcExpr, node) < 0 )
|
|
|
+ return -1;
|
|
|
Dereference(&funcExpr, true);
|
|
|
}
|
|
|
else
|
|
|
@@ -11447,7 +11509,12 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asCExprContext *ctx, a
|
|
|
ReleaseTemporaryVariable(tmp, &ctx->bc);
|
|
|
}
|
|
|
|
|
|
- MakeFunctionCall(ctx, funcs[0], objectType, args, node, false, 0, funcExpr.type.stackOffset);
|
|
|
+ r = MakeFunctionCall(ctx, funcs[0], objectType, args, node, false, 0, funcExpr.type.stackOffset);
|
|
|
+ if( r < 0 )
|
|
|
+ {
|
|
|
+ ctx->type.SetDummy();
|
|
|
+ isOK = false;
|
|
|
+ }
|
|
|
}
|
|
|
else
|
|
|
isOK = false;
|
|
|
@@ -11611,7 +11678,8 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asCExprContext *ctx
|
|
|
if( opName )
|
|
|
{
|
|
|
// TODO: Should convert this to something similar to CompileOverloadedDualOperator2
|
|
|
- ProcessPropertyGetAccessor(ctx, node);
|
|
|
+ if( ProcessPropertyGetAccessor(ctx, node) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
// TODO: If the value isn't const, then first try to find the non const method, and if not found try to find the const method
|
|
|
|
|
|
@@ -11634,8 +11702,7 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asCExprContext *ctx
|
|
|
if( funcs.GetLength() == 1 )
|
|
|
{
|
|
|
asCArray<asCExprContext *> args;
|
|
|
- MakeFunctionCall(ctx, funcs[0], CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node);
|
|
|
- return 0;
|
|
|
+ return MakeFunctionCall(ctx, funcs[0], CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node);
|
|
|
}
|
|
|
else if( funcs.GetLength() == 0 )
|
|
|
{
|
|
|
@@ -11679,7 +11746,8 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asCExprContext *ctx
|
|
|
}
|
|
|
|
|
|
|
|
|
- ProcessPropertyGetAccessor(ctx, node);
|
|
|
+ if( ProcessPropertyGetAccessor(ctx, node) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
asCDataType to = ctx->type.dataType;
|
|
|
|
|
|
@@ -11776,7 +11844,8 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asCExprContext *ctx
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- ProcessPropertyGetAccessor(ctx, node);
|
|
|
+ if( ProcessPropertyGetAccessor(ctx, node) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
ConvertToTempVariable(ctx);
|
|
|
asASSERT(!ctx->type.isLValue);
|
|
|
@@ -11791,7 +11860,8 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asCExprContext *ctx
|
|
|
}
|
|
|
else if( op == ttBitNot )
|
|
|
{
|
|
|
- ProcessPropertyGetAccessor(ctx, node);
|
|
|
+ if( ProcessPropertyGetAccessor(ctx, node) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
asCDataType to = ctx->type.dataType;
|
|
|
|
|
|
@@ -11956,8 +12026,17 @@ int asCCompiler::FindPropertyAccessor(const asCString &name, asCExprContext *ctx
|
|
|
return FindPropertyAccessor(name, ctx, 0, node, ns, isThisAccess);
|
|
|
}
|
|
|
|
|
|
+// Returns:
|
|
|
+// 1 = a valid match was found
|
|
|
+// 0 = no matching symbols (or feature disabled)
|
|
|
+// -1 = ambiguous getters or setters, i.e. multiple methods match symbol name and signature
|
|
|
+// -2 = mismatching type for getter and setter
|
|
|
+// -3 = processing error, e.g. out of memory
|
|
|
int asCCompiler::FindPropertyAccessor(const asCString &name, asCExprContext *ctx, asCExprContext *arg, asCScriptNode *node, asSNameSpace *ns, bool isThisAccess)
|
|
|
{
|
|
|
+ // TODO: With asEP_PROPERTY_ACCESSOR_MODE == 3 this method doesn't need to validate the
|
|
|
+ // getter/setter as it is done at the time of declaration. Should deprecate the other options
|
|
|
+
|
|
|
if( engine->ep.propertyAccessorMode == 0 )
|
|
|
{
|
|
|
// Property accessors have been disabled by the application
|
|
|
@@ -11976,13 +12055,17 @@ int asCCompiler::FindPropertyAccessor(const asCString &name, asCExprContext *ctx
|
|
|
// Don't look for property accessors in script classes if the script
|
|
|
// property accessors have been disabled by the application
|
|
|
if( !(ctx->type.dataType.GetTypeInfo()->flags & asOBJ_SCRIPT_OBJECT) ||
|
|
|
- engine->ep.propertyAccessorMode == 2 )
|
|
|
+ engine->ep.propertyAccessorMode >= 2 )
|
|
|
{
|
|
|
// Check if the object has any methods with the corresponding accessor name(s)
|
|
|
asCObjectType *ot = CastToObjectType(ctx->type.dataType.GetTypeInfo());
|
|
|
for( asUINT n = 0; n < ot->methods.GetLength(); n++ )
|
|
|
{
|
|
|
asCScriptFunction *f = engine->scriptFunctions[ot->methods[n]];
|
|
|
+
|
|
|
+ if( engine->ep.propertyAccessorMode == 3 && !f->IsProperty() )
|
|
|
+ continue;
|
|
|
+
|
|
|
// TODO: The type of the parameter should match the argument (unless the arg is a dummy)
|
|
|
if( f->name == getName && (int)f->parameterTypes.GetLength() == (arg?1:0) )
|
|
|
{
|
|
|
@@ -12023,6 +12106,14 @@ int asCCompiler::FindPropertyAccessor(const asCString &name, asCExprContext *ctx
|
|
|
for( n = 0; n < funcs.GetLength(); n++ )
|
|
|
{
|
|
|
asCScriptFunction *f = builder->GetFunctionDescription(funcs[n]);
|
|
|
+
|
|
|
+ if( engine->ep.propertyAccessorMode == 3 && !f->IsProperty() )
|
|
|
+ continue;
|
|
|
+
|
|
|
+ // Ignore script functions, if the application has disabled script defined property accessors
|
|
|
+ if( engine->ep.propertyAccessorMode == 1 && f->funcType == asFUNC_SCRIPT )
|
|
|
+ continue;
|
|
|
+
|
|
|
// TODO: The type of the parameter should match the argument (unless the arg is a dummy)
|
|
|
if( (int)f->parameterTypes.GetLength() == (arg?1:0) )
|
|
|
{
|
|
|
@@ -12043,6 +12134,14 @@ int asCCompiler::FindPropertyAccessor(const asCString &name, asCExprContext *ctx
|
|
|
for( n = 0; n < funcs.GetLength(); n++ )
|
|
|
{
|
|
|
asCScriptFunction *f = builder->GetFunctionDescription(funcs[n]);
|
|
|
+
|
|
|
+ if( engine->ep.propertyAccessorMode == 3 && !f->IsProperty() )
|
|
|
+ continue;
|
|
|
+
|
|
|
+ // Ignore script functions, if the application has disabled script defined property accessors
|
|
|
+ if( engine->ep.propertyAccessorMode == 1 && f->funcType == asFUNC_SCRIPT )
|
|
|
+ continue;
|
|
|
+
|
|
|
// TODO: getset: If the parameter is a reference, it must not be an out reference. Should we allow inout ref?
|
|
|
if( (int)f->parameterTypes.GetLength() == (arg?2:1) )
|
|
|
{
|
|
|
@@ -12137,7 +12236,7 @@ int asCCompiler::FindPropertyAccessor(const asCString &name, asCExprContext *ctx
|
|
|
PrintMatchingFuncs(funcs, node);
|
|
|
}
|
|
|
|
|
|
- return -1;
|
|
|
+ return -2;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -12159,7 +12258,7 @@ int asCCompiler::FindPropertyAccessor(const asCString &name, asCExprContext *ctx
|
|
|
realSetId = outFunc->objectType->virtualFunctionTable[setFunc->vfTableIdx]->id;
|
|
|
}
|
|
|
|
|
|
- // Avoid recursive call, by not treating this as a property accessor call.
|
|
|
+ // Avoid recursive call by not treating this as a property accessor call.
|
|
|
// This will also allow having the real property with the same name as the accessors.
|
|
|
if( (isThisAccess || outFunc->objectType == 0) &&
|
|
|
((realGetId && realGetId == outFunc->id) ||
|
|
|
@@ -12169,15 +12268,6 @@ int asCCompiler::FindPropertyAccessor(const asCString &name, asCExprContext *ctx
|
|
|
setId = 0;
|
|
|
}
|
|
|
|
|
|
- // Check if the application has disabled script written property accessors
|
|
|
- if( engine->ep.propertyAccessorMode == 1 )
|
|
|
- {
|
|
|
- if( getId && builder->GetFunctionDescription(getId)->funcType != asFUNC_SYSTEM )
|
|
|
- getId = 0;
|
|
|
- if( setId && builder->GetFunctionDescription(setId)->funcType != asFUNC_SYSTEM )
|
|
|
- setId = 0;
|
|
|
- }
|
|
|
-
|
|
|
if( getId || setId )
|
|
|
{
|
|
|
// Property accessors were found, but we don't know which is to be used yet, so
|
|
|
@@ -12230,7 +12320,7 @@ int asCCompiler::FindPropertyAccessor(const asCString &name, asCExprContext *ctx
|
|
|
if( ctx->property_arg == 0 )
|
|
|
{
|
|
|
// Out of memory
|
|
|
- return -1;
|
|
|
+ return -3;
|
|
|
}
|
|
|
|
|
|
MergeExprBytecodeAndType(ctx->property_arg, arg);
|
|
|
@@ -12292,7 +12382,7 @@ int asCCompiler::ProcessPropertySetAccessor(asCExprContext *ctx, asCExprContext
|
|
|
}
|
|
|
|
|
|
// Call the accessor
|
|
|
- MakeFunctionCall(ctx, ctx->property_set, func->objectType, args, node);
|
|
|
+ int r = MakeFunctionCall(ctx, ctx->property_set, func->objectType, args, node);
|
|
|
|
|
|
ctx->property_get = 0;
|
|
|
ctx->property_set = 0;
|
|
|
@@ -12302,7 +12392,7 @@ int asCCompiler::ProcessPropertySetAccessor(asCExprContext *ctx, asCExprContext
|
|
|
ctx->property_arg = 0;
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
+ return r;
|
|
|
}
|
|
|
|
|
|
int asCCompiler::ProcessPropertyGetSetAccessor(asCExprContext *ctx, asCExprContext *lctx, asCExprContext *rctx, eTokenType op, asCScriptNode *errNode)
|
|
|
@@ -12448,18 +12538,17 @@ int asCCompiler::ProcessPropertyGetSetAccessor(asCExprContext *ctx, asCExprConte
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-void asCCompiler::ProcessPropertyGetAccessor(asCExprContext *ctx, asCScriptNode *node)
|
|
|
+int asCCompiler::ProcessPropertyGetAccessor(asCExprContext *ctx, asCScriptNode *node)
|
|
|
{
|
|
|
// If no property accessor has been prepared then don't do anything
|
|
|
if( !ctx->property_get && !ctx->property_set )
|
|
|
- return;
|
|
|
+ return 0;
|
|
|
|
|
|
if( !ctx->property_get )
|
|
|
{
|
|
|
// Raise error on missing accessor
|
|
|
Error(TXT_PROPERTY_HAS_NO_GET_ACCESSOR, node);
|
|
|
- ctx->type.SetDummy();
|
|
|
- return;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
asCExprValue objType = ctx->type;
|
|
|
@@ -12480,8 +12569,7 @@ void asCCompiler::ProcessPropertyGetAccessor(asCExprContext *ctx, asCScriptNode
|
|
|
asDELETE(ctx->property_arg, asCExprContext);
|
|
|
ctx->property_arg = 0;
|
|
|
}
|
|
|
- ctx->type.SetDummy();
|
|
|
- return;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
if( func->objectType )
|
|
|
@@ -12498,6 +12586,7 @@ void asCCompiler::ProcessPropertyGetAccessor(asCExprContext *ctx, asCScriptNode
|
|
|
asCArray<int> funcCandidates;
|
|
|
funcCandidates.PushLast(ctx->property_get);
|
|
|
PrintMatchingFuncs(funcCandidates, node);
|
|
|
+ return -1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -12505,7 +12594,7 @@ void asCCompiler::ProcessPropertyGetAccessor(asCExprContext *ctx, asCScriptNode
|
|
|
bool isExplicitHandle = ctx->type.isExplicitHandle;
|
|
|
|
|
|
// Call the accessor
|
|
|
- MakeFunctionCall(ctx, ctx->property_get, func->objectType, args, node);
|
|
|
+ int r = MakeFunctionCall(ctx, ctx->property_get, func->objectType, args, node);
|
|
|
if( isExplicitHandle )
|
|
|
ctx->type.isExplicitHandle = true;
|
|
|
|
|
|
@@ -12517,6 +12606,8 @@ void asCCompiler::ProcessPropertyGetAccessor(asCExprContext *ctx, asCScriptNode
|
|
|
asDELETE(ctx->property_arg, asCExprContext);
|
|
|
ctx->property_arg = 0;
|
|
|
}
|
|
|
+
|
|
|
+ return r;
|
|
|
}
|
|
|
|
|
|
int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asCExprContext *ctx)
|
|
|
@@ -12551,7 +12642,8 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asCExprContext *ct
|
|
|
if( opName )
|
|
|
{
|
|
|
// TODO: Should convert this to something similar to CompileOverloadedDualOperator2
|
|
|
- ProcessPropertyGetAccessor(ctx, node);
|
|
|
+ if( ProcessPropertyGetAccessor(ctx, node) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
// TODO: If the value isn't const, then first try to find the non const method, and if not found try to find the const method
|
|
|
|
|
|
@@ -12574,8 +12666,7 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asCExprContext *ct
|
|
|
if( funcs.GetLength() == 1 )
|
|
|
{
|
|
|
asCArray<asCExprContext *> args;
|
|
|
- MakeFunctionCall(ctx, funcs[0], CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node);
|
|
|
- return 0;
|
|
|
+ return MakeFunctionCall(ctx, funcs[0], CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node);
|
|
|
}
|
|
|
else if( funcs.GetLength() == 0 )
|
|
|
{
|
|
|
@@ -12679,7 +12770,8 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asCExprContext *ct
|
|
|
{
|
|
|
if( node->firstChild->nodeType == snIdentifier )
|
|
|
{
|
|
|
- ProcessPropertyGetAccessor(ctx, node);
|
|
|
+ if( ProcessPropertyGetAccessor(ctx, node) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
// Get the property name
|
|
|
asCString name(&script->code[node->firstChild->tokenPos], node->firstChild->tokenLength);
|
|
|
@@ -12838,7 +12930,8 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asCExprContext *ct
|
|
|
}
|
|
|
|
|
|
// Process the get property accessor
|
|
|
- ProcessPropertyGetAccessor(ctx, node);
|
|
|
+ if( ProcessPropertyGetAccessor(ctx, node) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
// Compile function call
|
|
|
int r = CompileFunctionCall(node->firstChild, ctx, CastToObjectType(ctx->type.dataType.GetTypeInfo()), ctx->type.dataType.IsObjectConst());
|
|
|
@@ -12898,7 +12991,8 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asCExprContext *ct
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- ProcessPropertyGetAccessor(ctx, node);
|
|
|
+ if( ProcessPropertyGetAccessor(ctx, node) < 0 )
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
// Compile the expression
|
|
|
@@ -12934,9 +13028,9 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asCExprContext *ct
|
|
|
// Add the default values for arguments not explicitly supplied
|
|
|
int r = CompileDefaultAndNamedArgs(node, args, funcs[0], objectType);
|
|
|
|
|
|
- if( r == 0 )
|
|
|
- MakeFunctionCall(ctx, funcs[0], objectType, args, node, false, 0, ctx->type.stackOffset);
|
|
|
- else
|
|
|
+ if( r < 0 )
|
|
|
+ isOK = false;
|
|
|
+ else if( MakeFunctionCall(ctx, funcs[0], objectType, args, node, false, 0, ctx->type.stackOffset) < 0 )
|
|
|
isOK = false;
|
|
|
}
|
|
|
}
|
|
|
@@ -12997,6 +13091,7 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asCExprContext *ct
|
|
|
}
|
|
|
|
|
|
// Compile arguments
|
|
|
+ bool isOK = true;
|
|
|
asCArray<asCExprContext *> args;
|
|
|
asCArray<asSNamedArgument> namedArgs;
|
|
|
if( CompileArgumentList(node->lastChild, args, namedArgs) >= 0 )
|
|
|
@@ -13045,8 +13140,12 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asCExprContext *ct
|
|
|
ctx->bc.Instr(asBC_PopPtr);
|
|
|
}
|
|
|
|
|
|
- MakeFunctionCall(ctx, funcs[0], ctx->type.dataType.IsFuncdef() ? 0 : CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node, false, 0, ctx->type.stackOffset);
|
|
|
+ r = MakeFunctionCall(ctx, funcs[0], ctx->type.dataType.IsFuncdef() ? 0 : CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node, false, 0, ctx->type.stackOffset);
|
|
|
+ if( r < 0 )
|
|
|
+ isOK = false;
|
|
|
}
|
|
|
+ else
|
|
|
+ isOK = false;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
@@ -13063,6 +13162,9 @@ int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asCExprContext *ct
|
|
|
{
|
|
|
asDELETE(namedArgs[n].ctx, asCExprContext);
|
|
|
}
|
|
|
+
|
|
|
+ if( !isOK )
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
@@ -13166,9 +13268,9 @@ int asCCompiler::MatchArgument(asCScriptFunction *desc, const asCExprContext *ar
|
|
|
// Anonymous init lists can only match parameters that can be initialized with a list
|
|
|
if (argExpr->IsAnonymousInitList())
|
|
|
{
|
|
|
- if ((desc->parameterTypes[paramNum].IsReference() && desc->inOutFlags[paramNum] != asTM_INREF) ||
|
|
|
+ if( (desc->parameterTypes[paramNum].IsReference() && (desc->inOutFlags[paramNum] & asTM_INREF) == 0) ||
|
|
|
desc->parameterTypes[paramNum].GetBehaviour() == 0 ||
|
|
|
- desc->parameterTypes[paramNum].GetBehaviour()->listFactory == 0)
|
|
|
+ desc->parameterTypes[paramNum].GetBehaviour()->listFactory == 0 )
|
|
|
{
|
|
|
return -1;
|
|
|
}
|
|
|
@@ -13524,7 +13626,7 @@ int asCCompiler::CompileOverloadedDualOperator2(asCScriptNode *node, const char
|
|
|
(!isConst || func->IsReadOnly()) )
|
|
|
{
|
|
|
// Make sure the method is accessible by the module
|
|
|
- if( builder->module->accessMask & func->accessMask )
|
|
|
+ if( builder->module->m_accessMask & func->accessMask )
|
|
|
{
|
|
|
funcs.PushLast(func->id);
|
|
|
}
|
|
|
@@ -13563,7 +13665,8 @@ int asCCompiler::CompileOverloadedDualOperator2(asCScriptNode *node, const char
|
|
|
rctx->bc.GetVarsUsed(reservedVariables);
|
|
|
|
|
|
// Process the lctx expression as get accessor
|
|
|
- ProcessPropertyGetAccessor(lctx, node);
|
|
|
+ if( ProcessPropertyGetAccessor(lctx, node) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
reservedVariables.SetLength(l);
|
|
|
|
|
|
@@ -13655,7 +13758,8 @@ int asCCompiler::CompileOverloadedDualOperator2(asCScriptNode *node, const char
|
|
|
args.PushLast(rctx);
|
|
|
MergeExprBytecode(ctx, lctx);
|
|
|
ctx->type = lctx->type;
|
|
|
- MakeFunctionCall(ctx, ops[0], CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node);
|
|
|
+ if( MakeFunctionCall(ctx, ops[0], CastToObjectType(ctx->type.dataType.GetTypeInfo()), args, node) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
// Rearrange the bytecode so the left argument is computed first
|
|
|
if (leftToRight)
|
|
|
@@ -13683,7 +13787,7 @@ int asCCompiler::CompileOverloadedDualOperator2(asCScriptNode *node, const char
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-void asCCompiler::MakeFunctionCall(asCExprContext *ctx, int funcId, asCObjectType *objectType, asCArray<asCExprContext*> &args, asCScriptNode *node, bool useVariable, int stackOffset, int funcPtrVar)
|
|
|
+int asCCompiler::MakeFunctionCall(asCExprContext *ctx, int funcId, asCObjectType *objectType, asCArray<asCExprContext*> &args, asCScriptNode *node, bool useVariable, int stackOffset, int funcPtrVar)
|
|
|
{
|
|
|
if( objectType )
|
|
|
Dereference(ctx, true);
|
|
|
@@ -13697,7 +13801,7 @@ void asCCompiler::MakeFunctionCall(asCExprContext *ctx, int funcId, asCObjectTyp
|
|
|
|
|
|
int r = PrepareFunctionCall(funcId, &ctx->bc, args);
|
|
|
if (r < 0)
|
|
|
- return;
|
|
|
+ return r;
|
|
|
|
|
|
// Verify if any of the args variable offsets are used in the other code.
|
|
|
// If they are exchange the offset for a new one
|
|
|
@@ -13744,6 +13848,8 @@ void asCCompiler::MakeFunctionCall(asCExprContext *ctx, int funcId, asCObjectTyp
|
|
|
MoveArgsToStack(funcId, &ctx->bc, args, objectType ? true : false);
|
|
|
|
|
|
PerformFunctionCall(funcId, ctx, false, &args, 0, useVariable, stackOffset, funcPtrVar);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
int asCCompiler::CompileOperator(asCScriptNode *node, asCExprContext *lctx, asCExprContext *rctx, asCExprContext *ctx, eTokenType op, bool leftToRight)
|
|
|
@@ -13792,8 +13898,10 @@ int asCCompiler::CompileOperator(asCScriptNode *node, asCExprContext *lctx, asCE
|
|
|
}
|
|
|
|
|
|
// Process the property get accessors (if any)
|
|
|
- ProcessPropertyGetAccessor(lctx, node);
|
|
|
- ProcessPropertyGetAccessor(rctx, node);
|
|
|
+ if( ProcessPropertyGetAccessor(lctx, node) < 0 )
|
|
|
+ return -1;
|
|
|
+ if( ProcessPropertyGetAccessor(rctx, node) < 0 )
|
|
|
+ return -1;
|
|
|
|
|
|
// Make sure we have two variables or constants
|
|
|
if( lctx->type.dataType.IsReference() ) ConvertToVariableNotIn(lctx, rctx);
|
|
|
@@ -15367,8 +15475,10 @@ void asCCompiler::CompileBooleanOperator(asCScriptNode *node, asCExprContext *lc
|
|
|
void asCCompiler::CompileOperatorOnHandles(asCScriptNode *node, asCExprContext *lctx, asCExprContext *rctx, asCExprContext *ctx, eTokenType opToken)
|
|
|
{
|
|
|
// Process the property accessor as get
|
|
|
- ProcessPropertyGetAccessor(lctx, node);
|
|
|
- ProcessPropertyGetAccessor(rctx, node);
|
|
|
+ if( ProcessPropertyGetAccessor(lctx, node) < 0 )
|
|
|
+ return;
|
|
|
+ if( ProcessPropertyGetAccessor(rctx, node) < 0 )
|
|
|
+ return;
|
|
|
|
|
|
DetermineSingleFunc(lctx, node);
|
|
|
DetermineSingleFunc(rctx, node);
|
|
|
@@ -16300,26 +16410,34 @@ bool asCExprContext::IsAnonymousInitList() const
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+void asCExprContext::Copy(asCExprContext *other)
|
|
|
+{
|
|
|
+ type = other->type;
|
|
|
+ property_get = other->property_get;
|
|
|
+ property_set = other->property_set;
|
|
|
+ property_const = other->property_const;
|
|
|
+ property_handle = other->property_handle;
|
|
|
+ property_ref = other->property_ref;
|
|
|
+ property_arg = other->property_arg;
|
|
|
+ exprNode = other->exprNode;
|
|
|
+ methodName = other->methodName;
|
|
|
+ enumValue = other->enumValue;
|
|
|
+ isVoidExpression = other->isVoidExpression;
|
|
|
+ isCleanArg = other->isCleanArg;
|
|
|
+ isAnonymousInitList = other->isAnonymousInitList;
|
|
|
+ origCode = other->origCode;
|
|
|
+
|
|
|
+ // Do not copy the origExpr member
|
|
|
+}
|
|
|
+
|
|
|
void asCExprContext::Merge(asCExprContext *after)
|
|
|
{
|
|
|
- type = after->type;
|
|
|
- property_get = after->property_get;
|
|
|
- property_set = after->property_set;
|
|
|
- property_const = after->property_const;
|
|
|
- property_handle = after->property_handle;
|
|
|
- property_ref = after->property_ref;
|
|
|
- property_arg = after->property_arg;
|
|
|
- exprNode = after->exprNode;
|
|
|
- methodName = after->methodName;
|
|
|
- enumValue = after->enumValue;
|
|
|
- isVoidExpression = after->isVoidExpression;
|
|
|
- isCleanArg = after->isCleanArg;
|
|
|
- isAnonymousInitList = after->isAnonymousInitList;
|
|
|
- origCode = after->origCode;
|
|
|
+ // Overwrite properties with the expression that comes after
|
|
|
+ Copy(after);
|
|
|
|
|
|
+ // Clean the properties in 'after' that have now moved into
|
|
|
+ // this structure so they are not cleaned up accidentally
|
|
|
after->property_arg = 0;
|
|
|
-
|
|
|
- // Do not copy the origExpr member
|
|
|
}
|
|
|
|
|
|
|