Skip to content

Commit

Permalink
- Compiler no longer silently accepts implicit conversion from null h…
Browse files Browse the repository at this point in the history
…andle to object type registered with ASHANDLE if there is no matching implicit constructor (Thanks Patrick Jeeves)

- weakref now has its constructor that takes a handle marked as explicit


git-svn-id: http://svn.code.sf.net/p/angelscript/code/trunk@2737 404ce1b2-830e-0410-a2e2-b09542c77caf
  • Loading branch information
angelcode committed Jul 19, 2021
1 parent f7aed93 commit 003b9e4
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 8 deletions.
8 changes: 4 additions & 4 deletions sdk/add_on/weakref/weakref.cpp
Expand Up @@ -226,7 +226,7 @@ void RegisterScriptWeakRef_Native(asIScriptEngine *engine)
r = engine->RegisterObjectType("weakref<class T>", sizeof(CScriptWeakRef), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_TEMPLATE | asOBJ_APP_CLASS_DAK); assert( r >= 0 );

r = engine->RegisterObjectBehaviour("weakref<T>", asBEHAVE_CONSTRUCT, "void f(int&in)", asFUNCTION(ScriptWeakRefConstruct), asCALL_CDECL_OBJLAST); assert( r>= 0 );
r = engine->RegisterObjectBehaviour("weakref<T>", asBEHAVE_CONSTRUCT, "void f(int&in, T@+)", asFUNCTION(ScriptWeakRefConstruct2), asCALL_CDECL_OBJLAST); assert( r>= 0 );
r = engine->RegisterObjectBehaviour("weakref<T>", asBEHAVE_CONSTRUCT, "void f(int&in, T@+) explicit", asFUNCTION(ScriptWeakRefConstruct2), asCALL_CDECL_OBJLAST); assert( r>= 0 );
r = engine->RegisterObjectBehaviour("weakref<T>", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(ScriptWeakRefDestruct), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("weakref<T>", asBEHAVE_TEMPLATE_CALLBACK, "bool f(int&in, bool&out)", asFUNCTION(ScriptWeakRefTemplateCallback), asCALL_CDECL); assert( r >= 0 );

Expand All @@ -242,7 +242,7 @@ void RegisterScriptWeakRef_Native(asIScriptEngine *engine)
r = engine->RegisterObjectType("const_weakref<class T>", sizeof(CScriptWeakRef), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_TEMPLATE | asOBJ_APP_CLASS_DAK); assert( r >= 0 );

r = engine->RegisterObjectBehaviour("const_weakref<T>", asBEHAVE_CONSTRUCT, "void f(int&in)", asFUNCTION(ScriptWeakRefConstruct), asCALL_CDECL_OBJLAST); assert( r>= 0 );
r = engine->RegisterObjectBehaviour("const_weakref<T>", asBEHAVE_CONSTRUCT, "void f(int&in, const T@+)", asFUNCTION(ScriptWeakRefConstruct2), asCALL_CDECL_OBJLAST); assert( r>= 0 );
r = engine->RegisterObjectBehaviour("const_weakref<T>", asBEHAVE_CONSTRUCT, "void f(int&in, const T@+) explicit", asFUNCTION(ScriptWeakRefConstruct2), asCALL_CDECL_OBJLAST); assert( r>= 0 );
r = engine->RegisterObjectBehaviour("const_weakref<T>", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(ScriptWeakRefDestruct), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("const_weakref<T>", asBEHAVE_TEMPLATE_CALLBACK, "bool f(int&in, bool&out)", asFUNCTION(ScriptWeakRefTemplateCallback), asCALL_CDECL); assert( r >= 0 );

Expand Down Expand Up @@ -332,7 +332,7 @@ void RegisterScriptWeakRef_Generic(asIScriptEngine *engine)
r = engine->RegisterObjectType("weakref<class T>", sizeof(CScriptWeakRef), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_TEMPLATE | asOBJ_APP_CLASS_DAK); assert( r >= 0 );

r = engine->RegisterObjectBehaviour("weakref<T>", asBEHAVE_CONSTRUCT, "void f(int&in)", asFUNCTION(ScriptWeakRefConstruct_Generic), asCALL_GENERIC); assert( r>= 0 );
r = engine->RegisterObjectBehaviour("weakref<T>", asBEHAVE_CONSTRUCT, "void f(int&in, T@+)", asFUNCTION(ScriptWeakRefConstruct2_Generic), asCALL_GENERIC); assert( r>= 0 );
r = engine->RegisterObjectBehaviour("weakref<T>", asBEHAVE_CONSTRUCT, "void f(int&in, T@+) explicit", asFUNCTION(ScriptWeakRefConstruct2_Generic), asCALL_GENERIC); assert( r>= 0 );
r = engine->RegisterObjectBehaviour("weakref<T>", asBEHAVE_TEMPLATE_CALLBACK, "bool f(int&in, bool&out)", asFUNCTION(ScriptWeakRefTemplateCallback_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("weakref<T>", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(ScriptWeakRefDestruct_Generic), asCALL_GENERIC); assert( r >= 0 );

Expand All @@ -348,7 +348,7 @@ void RegisterScriptWeakRef_Generic(asIScriptEngine *engine)
r = engine->RegisterObjectType("const_weakref<class T>", sizeof(CScriptWeakRef), asOBJ_VALUE | asOBJ_ASHANDLE | asOBJ_TEMPLATE | asOBJ_APP_CLASS_DAK); assert( r >= 0 );

r = engine->RegisterObjectBehaviour("const_weakref<T>", asBEHAVE_CONSTRUCT, "void f(int&in)", asFUNCTION(ScriptWeakRefConstruct_Generic), asCALL_GENERIC); assert( r>= 0 );
r = engine->RegisterObjectBehaviour("const_weakref<T>", asBEHAVE_CONSTRUCT, "void f(int&in, const T@+)", asFUNCTION(ScriptWeakRefConstruct2_Generic), asCALL_GENERIC); assert( r>= 0 );
r = engine->RegisterObjectBehaviour("const_weakref<T>", asBEHAVE_CONSTRUCT, "void f(int&in, const T@+) explicit", asFUNCTION(ScriptWeakRefConstruct2_Generic), asCALL_GENERIC); assert( r>= 0 );
r = engine->RegisterObjectBehaviour("const_weakref<T>", asBEHAVE_TEMPLATE_CALLBACK, "bool f(int&in, bool&out)", asFUNCTION(ScriptWeakRefTemplateCallback_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("const_weakref<T>", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(ScriptWeakRefDestruct_Generic), asCALL_GENERIC); assert( r >= 0 );

Expand Down
16 changes: 14 additions & 2 deletions sdk/angelscript/source/as_compiler.cpp
Expand Up @@ -1513,7 +1513,8 @@ int asCCompiler::PrepareArgument(asCDataType *paramType, asCExprContext *ctx, as
else if( ctx->type.dataType.IsNullHandle() )
{
// Make sure the argument type can support handles (or is itself a handle)
if( !dt.SupportHandles() && !dt.IsObjectHandle() )
// Don't allow null handle to be converted to an object type of ASHANDLE here, that would require more logic to call the constructor (which should be handled in ImplicitConversion)
if( (!dt.SupportHandles() && !dt.IsObjectHandle()) || (dt.GetTypeInfo() && (dt.GetTypeInfo()->GetFlags() & asOBJ_ASHANDLE)) )
{
asCString str;
str.Format(TXT_CANT_IMPLICITLY_CONVERT_s_TO_s, ctx->type.dataType.Format(outFunc->nameSpace).AddressOf(), param.Format(outFunc->nameSpace).AddressOf());
Expand Down Expand Up @@ -7173,12 +7174,23 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asCExprContext *ctx, const asCDat
asUINT cost = ImplicitConvObjectRef(ctx, to, node, convType, generateCode);

// If the desired type is an asOBJ_ASHANDLE then we'll assume it is allowed to implicitly
// construct the object through any of the available constructors
// construct the object through any of the available constructors (except those marked as explicit)
if( to.GetTypeInfo() && (to.GetTypeInfo()->flags & asOBJ_ASHANDLE) && to.GetTypeInfo() != ctx->type.dataType.GetTypeInfo() && allowObjectConstruct )
{
asCArray<int> funcs;
funcs = CastToObjectType(to.GetTypeInfo())->beh.constructors;

// Don't allow use of explicit constructors/factories in implicit conversions
if (convType == asIC_IMPLICIT_CONV)
{
for (asUINT n = 0; n < funcs.GetLength(); n++)
{
asCScriptFunction* desc = builder->GetFunctionDescription(funcs[n]);
if (desc->IsExplicit())
funcs.RemoveIndex(n--);
}
}

asCArray<asCExprContext *> args;
args.PushLast(ctx);

Expand Down
4 changes: 3 additions & 1 deletion sdk/docs/articles/changes2.html
Expand Up @@ -15,7 +15,7 @@

<h1>AngelScript Change Log</h1>

<h2>Version 2.35.1 WIP - 2021/07/04</h2>
<h2>Version 2.35.1 WIP - 2021/07/19</h2>

<ul>
<li>Bug fixes
Expand All @@ -36,6 +36,7 @@ <h2>Version 2.35.1 WIP - 2021/07/04</h2>
<li>Fixed invalid bytecode sequence in initialization lists with value types whose opAssign returns void (Thanks jiandingzhe)
<li>Fixed registering asBEHAVE_LIST_CONSTRUCT on value type templates (Thanks Suedwest)
<li>Fixed compiler error in as_symboltable.h on GCC 11 (Thanks shirubax)
<li>Compiler no longer silently accepts implicit conversion from null handle to object type registered with ASHANDLE if there is no matching implicit constructor (Thanks Patrick Jeeves)
</ul>
<li>Library
<ul>
Expand Down Expand Up @@ -69,6 +70,7 @@ <h2>Version 2.35.1 WIP - 2021/07/04</h2>
<li>Fixed the samples concurrent and events on Linux (Thanks Dantrell B)
<li>Fixed WRAP_MFN on gnuc when used within templated functions (Thanks vballDrummer)
<li>Fixed issue in array::sort with callback that could cause objects in the array to be destroyed by gc (Thanks Miss)
<li>weakref now has its constructor that takes a handle marked as explicit
</ul>
<li>Project
<ul>
Expand Down
5 changes: 5 additions & 0 deletions sdk/docs/doxygen/source/doc_script_stdlib.h
Expand Up @@ -637,7 +637,12 @@ can be used in place of the handle where the reference to the object is needed b
\section doc_datatypes_weakref_addon Supporting weakref object
\subsection doc_datatypes_weakref_addon_construct Constructors
<b>weakref<T></b>()<br>
<b>weakref<T></b>(T@) explicit<br>
<b>const_weakref<T></b>()<br>
<b>const_weakref<T></b>(const T@) explicit<br>
\subsection doc_datatypes_weakref_addon_ops Operators
Expand Down
58 changes: 57 additions & 1 deletion sdk/tests/test_feature/source/test_addon_weakref.cpp
Expand Up @@ -70,6 +70,39 @@ bool Test()
CBufferedOutStream bout;
asIScriptEngine *engine;

// Test value-assigning null to the weakref
// Reported by Patrick Jeeves
{
engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
bout.buffer = "";
RegisterScriptWeakRef(engine);
engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC);

const char* script =
"class GameObject {} \n"
"weakref<GameObject> m_connect; \n"
"void main() \n"
"{ \n"
" m_connect = null; \n"
"} \n";

asIScriptModule* mod = engine->GetModule("test", asGM_ALWAYS_CREATE);
mod->AddScriptSection(TESTNAME, script);
r = mod->Build();
if (r >= 0)
TEST_FAILED;

if (bout.buffer != "Test_Addon_WeakRef (3, 1) : Info : Compiling void main()\n"
"Test_Addon_WeakRef (5, 14) : Error : Can't implicitly convert from '<null handle>' to 'weakref<GameObject>&'.\n")
{
PRINTF("%s", bout.buffer.c_str());
TEST_FAILED;
}

engine->Release();
}

// Ordinary tests
{
engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
Expand Down Expand Up @@ -130,7 +163,7 @@ bool Test()
"class Foo {} \n"
"void main() \n"
"{ \n"
" weakref<Foo> a = Foo(); \n"
" weakref<Foo> @a = Foo(); \n"
" weakref<Foo> b; \n"
" b = a; \n"
" assert( a.get() is b.get() ); \n"
Expand All @@ -153,6 +186,29 @@ bool Test()
TEST_FAILED;
}

// It is not allowed to do a value assign directly to the weakref on declaration
bout.buffer = "";
mod->Discard();
mod = engine->GetModule("test", asGM_ALWAYS_CREATE);
mod->AddScriptSection("test",
"class Foo {} \n"
"void main() \n"
"{ \n"
" weakref<Foo> a = Foo(); \n"
"} \n"
);
r = mod->Build();
if (r >= 0)
TEST_FAILED;

if (bout.buffer != "test (2, 1) : Info : Compiling void main()\n"
"test (4, 20) : Error : Can't implicitly convert from 'Foo@&' to 'weakref<Foo>'.\n")
{
PRINTF("%s", bout.buffer.c_str());
TEST_FAILED;
}


engine->ShutDownAndRelease();
}

Expand Down

0 comments on commit 003b9e4

Please sign in to comment.