forked from Mirrors/openclonk
Remove references to functions defined in unloading defs (#1776)
parent
ab1e6bd5a4
commit
f7a04624eb
|
@ -319,11 +319,11 @@ C4Def::~C4Def()
|
|||
|
||||
void C4Def::Clear()
|
||||
{
|
||||
Script.Clear();
|
||||
C4PropList::Clear();
|
||||
|
||||
Graphics.Clear();
|
||||
|
||||
Script.Clear();
|
||||
StringTable.Clear();
|
||||
if (pClonkNames && fClonkNamesOwned) delete pClonkNames; pClonkNames=NULL;
|
||||
if (pRankNames && fRankNamesOwned) delete pRankNames; pRankNames=NULL;
|
||||
|
|
|
@ -463,6 +463,7 @@ void C4AulCompiler::PreparseAstVisitor::visit(const ::aul::ast::FunctionDecl *n)
|
|||
C4AulFunc *parent_func = Parent->GetFunc(cname);
|
||||
|
||||
Fn = new C4AulScriptFunc(Parent, target_host, cname, n->loc);
|
||||
host->ownedFunctions.insert(Fn);
|
||||
for (const auto ¶m : n->params)
|
||||
{
|
||||
Fn->AddPar(param.name.c_str(), param.type);
|
||||
|
|
|
@ -53,7 +53,7 @@ class C4AulFunc: public C4RefCnt
|
|||
public:
|
||||
C4AulFunc(C4PropListStatic * Parent, const char *pName);
|
||||
|
||||
const C4PropListStatic * Parent;
|
||||
C4PropListStatic * Parent;
|
||||
const char * GetName() const { return Name ? Name->GetCStr() : 0; }
|
||||
virtual StdStrBuf GetFullName() const; // get a fully classified name (C4ID::Name) for debug output
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ C4ScriptHost::~C4ScriptHost()
|
|||
|
||||
void C4ScriptHost::Clear()
|
||||
{
|
||||
UnlinkOwnedFunctions();
|
||||
C4ComponentHost::Clear();
|
||||
ast.reset();
|
||||
Script.Clear();
|
||||
|
@ -70,6 +71,49 @@ void C4ScriptHost::Clear()
|
|||
State = ASS_NONE;
|
||||
}
|
||||
|
||||
void C4ScriptHost::UnlinkOwnedFunctions()
|
||||
{
|
||||
// Remove owned functions from their parents. This solves a problem
|
||||
// where overloading a definition would unload the C4ScriptHost, but
|
||||
// keep around global functions, which then contained dangling pointers.
|
||||
for (auto func : ownedFunctions)
|
||||
{
|
||||
C4PropList *parent = func->Parent;
|
||||
if (parent == GetPropList())
|
||||
continue;
|
||||
assert(parent == &::ScriptEngine);
|
||||
C4Value v;
|
||||
parent->GetPropertyByS(func->Name, &v);
|
||||
if (v.getFunction() == func)
|
||||
{
|
||||
// If the function we're deleting is the top-level function in
|
||||
// the inheritance chain, promote the next one in its stead;
|
||||
// if there is no overloaded function, remove the property.
|
||||
if (func->OwnerOverloaded)
|
||||
parent->SetPropertyByS(func->Name, C4VFunction(func->OwnerOverloaded));
|
||||
else
|
||||
parent->ResetProperty(func->Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
C4AulScriptFunc *func_chain = v.getFunction()->SFunc();
|
||||
assert(func_chain != func);
|
||||
while (func_chain)
|
||||
{
|
||||
// Unlink the removed function from the inheritance chain
|
||||
if (func_chain->OwnerOverloaded == func)
|
||||
{
|
||||
func_chain->OwnerOverloaded = func->OwnerOverloaded;
|
||||
break;
|
||||
}
|
||||
assert(func_chain->OwnerOverloaded && "Removed function not found in inheritance chain");
|
||||
func_chain = func_chain->OwnerOverloaded->SFunc();
|
||||
}
|
||||
}
|
||||
}
|
||||
ownedFunctions.clear();
|
||||
}
|
||||
|
||||
void C4ScriptHost::Unreg()
|
||||
{
|
||||
// remove from list
|
||||
|
|
|
@ -54,6 +54,9 @@ public:
|
|||
std::string Translate(const std::string &text) const;
|
||||
std::list<C4ScriptHost *> SourceScripts;
|
||||
StdCopyStrBuf ScriptName; // script name
|
||||
|
||||
void UnlinkOwnedFunctions();
|
||||
|
||||
protected:
|
||||
C4ScriptHost();
|
||||
void Unreg(); // remove from list
|
||||
|
@ -83,6 +86,10 @@ protected:
|
|||
C4LangStringTable *stringTable;
|
||||
C4Set<C4Property> LocalValues;
|
||||
C4AulScriptState State; // script state
|
||||
|
||||
// list of all functions generated from code in this script host
|
||||
std::set<C4AulScriptFunc*> ownedFunctions;
|
||||
|
||||
friend class C4AulParse;
|
||||
friend class C4AulProfiler;
|
||||
friend class C4AulScriptEngine;
|
||||
|
|
Loading…
Reference in New Issue