Skip to content

Commit

Permalink
Move callScopeDtor to dsymbolsem.d, make private
Browse files Browse the repository at this point in the history
reduce nesting
  • Loading branch information
thewilsonator authored and dlang-bot committed Oct 3, 2024
1 parent f0a2ac5 commit 793efaf
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 112 deletions.
112 changes: 0 additions & 112 deletions compiler/src/dmd/declaration.d
Original file line number Diff line number Diff line change
Expand Up @@ -1172,118 +1172,6 @@ extern (C++) class VarDeclaration : Declaration
return edtor && !(storage_class & STC.nodtor);
}

/******************************************
* If a variable has a scope destructor call, return call for it.
* Otherwise, return NULL.
*/
extern (D) final Expression callScopeDtor(Scope* sc)
{
//printf("VarDeclaration::callScopeDtor() %s\n", toChars());

// Destruction of STC.field's is handled by buildDtor()
if (storage_class & (STC.nodtor | STC.ref_ | STC.out_ | STC.field))
{
return null;
}

if (iscatchvar)
return null; // destructor is built by `void semantic(Catch c, Scope* sc)`, not here

Expression e = null;
// Destructors for structs and arrays of structs
Type tv = type.baseElemOf();
if (tv.ty == Tstruct)
{
StructDeclaration sd = (cast(TypeStruct)tv).sym;
if (!sd.dtor || sd.errors)
return null;

const sz = type.size();
assert(sz != SIZE_INVALID);
if (!sz)
return null;

if (type.toBasetype().ty == Tstruct)
{
// v.__xdtor()
e = new VarExp(loc, this);

/* This is a hack so we can call destructors on const/immutable objects.
* Need to add things like "const ~this()" and "immutable ~this()" to
* fix properly.
*/
e.type = e.type.mutableOf();

// Enable calling destructors on shared objects.
// The destructor is always a single, non-overloaded function,
// and must serve both shared and non-shared objects.
e.type = e.type.unSharedOf;

e = new DotVarExp(loc, e, sd.dtor, false);
e = new CallExp(loc, e);
}
else
{
// __ArrayDtor(v[0 .. n])
e = new VarExp(loc, this);

const sdsz = sd.type.size();
assert(sdsz != SIZE_INVALID && sdsz != 0);
const n = sz / sdsz;
SliceExp se = new SliceExp(loc, e, new IntegerExp(loc, 0, Type.tsize_t),
new IntegerExp(loc, n, Type.tsize_t));

// Prevent redundant bounds check
se.upperIsInBounds = true;
se.lowerIsLessThanUpper = true;

// This is a hack so we can call destructors on const/immutable objects.
se.type = sd.type.arrayOf();

e = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), se);
}
return e;
}
// Destructors for classes
if (storage_class & (STC.auto_ | STC.scope_) && !(storage_class & STC.parameter))
{
for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass)
{
/* We can do better if there's a way with onstack
* classes to determine if there's no way the monitor
* could be set.
*/
//if (cd.isInterfaceDeclaration())
// error("interface `%s` cannot be scope", cd.toChars());

if (onstack) // if any destructors
{
// delete'ing C++ classes crashes (and delete is deprecated anyway)
if (cd.classKind == ClassKind.cpp)
{
// Don't call non-existant dtor
if (!cd.dtor)
break;

e = new VarExp(loc, this);
e.type = e.type.mutableOf().unSharedOf(); // Hack for mutable ctor on immutable instances
e = new DotVarExp(loc, e, cd.dtor, false);
e = new CallExp(loc, e);
break;
}

// delete this;
Expression ec;
ec = new VarExp(loc, this);
e = new DeleteExp(loc, ec, true);
e.type = Type.tvoid;
break;
}
}
}
return e;
}

/*******************************************
* If variable has a constant expression initializer, get it.
* Otherwise, return null.
Expand Down
111 changes: 111 additions & 0 deletions compiler/src/dmd/dsymbolsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -7474,3 +7474,114 @@ bool isGNUABITag(Expression e)
return false;
return true;
}

/******************************************
* If a variable has a scope destructor call, return call for it.
* Otherwise, return NULL.
*/
private Expression callScopeDtor(VarDeclaration vd, Scope* sc)
{
//printf("VarDeclaration::callScopeDtor() %s\n", toChars());

// Destruction of STC.field's is handled by buildDtor()
if (vd.storage_class & (STC.nodtor | STC.ref_ | STC.out_ | STC.field))
{
return null;
}

if (vd.iscatchvar)
return null; // destructor is built by `void semantic(Catch c, Scope* sc)`, not here

Expression e = null;
// Destructors for structs and arrays of structs
Type tv = vd.type.baseElemOf();
if (tv.ty == Tstruct)
{
StructDeclaration sd = (cast(TypeStruct)tv).sym;
if (!sd.dtor || sd.errors)
return null;

const sz = vd.type.size();
assert(sz != SIZE_INVALID);
if (!sz)
return null;

if (vd.type.toBasetype().ty == Tstruct)
{
// v.__xdtor()
e = new VarExp(vd.loc, vd);

/* This is a hack so we can call destructors on const/immutable objects.
* Need to add things like "const ~this()" and "immutable ~this()" to
* fix properly.
*/
e.type = e.type.mutableOf();

// Enable calling destructors on shared objects.
// The destructor is always a single, non-overloaded function,
// and must serve both shared and non-shared objects.
e.type = e.type.unSharedOf;

e = new DotVarExp(vd.loc, e, sd.dtor, false);
e = new CallExp(vd.loc, e);
}
else
{
// __ArrayDtor(v[0 .. n])
e = new VarExp(vd.loc, vd);

const sdsz = sd.type.size();
assert(sdsz != SIZE_INVALID && sdsz != 0);
const n = sz / sdsz;
SliceExp se = new SliceExp(vd.loc, e, new IntegerExp(vd.loc, 0, Type.tsize_t),
new IntegerExp(vd.loc, n, Type.tsize_t));

// Prevent redundant bounds check
se.upperIsInBounds = true;
se.lowerIsLessThanUpper = true;

// This is a hack so we can call destructors on const/immutable objects.
se.type = sd.type.arrayOf();

e = new CallExp(vd.loc, new IdentifierExp(vd.loc, Id.__ArrayDtor), se);
}
return e;
}
// Destructors for classes
if (!(vd.storage_class & (STC.auto_ | STC.scope_) && !(vd.storage_class & STC.parameter)))
return null;

for (ClassDeclaration cd = vd.type.isClassHandle(); cd; cd = cd.baseClass)
{
/* We can do better if there's a way with onstack
* classes to determine if there's no way the monitor
* could be set.
*/
//if (cd.isInterfaceDeclaration())
// error("interface `%s` cannot be scope", cd.toChars());

if (!vd.onstack) // if any destructors
continue;
// delete'ing C++ classes crashes (and delete is deprecated anyway)
if (cd.classKind == ClassKind.cpp)
{
// Don't call non-existant dtor
if (!cd.dtor)
break;

e = new VarExp(vd.loc, vd);
e.type = e.type.mutableOf().unSharedOf(); // Hack for mutable ctor on immutable instances
e = new DotVarExp(vd.loc, e, cd.dtor, false);
e = new CallExp(vd.loc, e);
break;
}

// delete this;
Expression ec;
ec = new VarExp(vd.loc, vd);
e = new DeleteExp(vd.loc, ec, true);
e.type = Type.tvoid;
break;
}
return e;
}

0 comments on commit 793efaf

Please sign in to comment.