Skip to content
This repository was archived by the owner on Jun 20, 2019. It is now read-only.

Commit 4e7dfe6

Browse files
committed
Only call class invariant if one provably exists in any base classes
1 parent 78c3891 commit 4e7dfe6

File tree

2 files changed

+63
-13
lines changed

2 files changed

+63
-13
lines changed

gcc/d/ChangeLog

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
2015-08-12 Iain Buclaw <[email protected]>
2+
3+
(needsInvariant): New function.
4+
(AssertExp::toElem): Check if there are any invariants found in the
5+
class object's vtable, and only call the invariant if the classinfo
6+
doesn't match at runtime.
7+
18
2015-08-10 Iain Buclaw <[email protected]>
29

310
* d-elem.cc(HaltExp::toElem): Use __builtin_trap to halt execution,

gcc/d/d-elem.cc

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,6 +1746,41 @@ DotVarExp::toElem (IRState *)
17461746
return error_mark_node;
17471747
}
17481748

1749+
// Determine if type is an aggregate that contains or inherits an invariant.
1750+
static FuncDeclaration *
1751+
needsInvariant(Type *t)
1752+
{
1753+
if (global.params.useInvariants)
1754+
{
1755+
t = t->toBasetype();
1756+
1757+
// If type is a struct, return its invariant.
1758+
if (t->ty == Tpointer && t->nextOf()->ty == Tstruct)
1759+
{
1760+
StructDeclaration *sd = ((TypeStruct *) t->nextOf())->sym;
1761+
return sd->inv;
1762+
}
1763+
1764+
// If type is a class, search all base classes for an invariant.
1765+
if (t->ty == Tclass)
1766+
{
1767+
ClassDeclaration *cd = ((TypeClass *) t)->sym;
1768+
1769+
// Interfaces and C++ classes don't have invariants.
1770+
if (cd->isInterfaceDeclaration() || cd->isCPPclass())
1771+
return NULL;
1772+
1773+
for ( ; cd != NULL; cd = cd->baseClass)
1774+
{
1775+
if (cd->inv)
1776+
return cd->inv;
1777+
}
1778+
}
1779+
}
1780+
1781+
return NULL;
1782+
}
1783+
17491784
elem *
17501785
AssertExp::toElem (IRState *)
17511786
{
@@ -1784,7 +1819,6 @@ AssertExp::toElem (IRState *)
17841819
{
17851820
ClassDeclaration *cd = tb1->isClassHandle();
17861821
tree arg = e1->toElem(NULL);
1787-
tree invc = NULL_TREE;
17881822

17891823
if (cd->isCOMclass())
17901824
{
@@ -1795,13 +1829,26 @@ AssertExp::toElem (IRState *)
17951829
else if (cd->isInterfaceDeclaration())
17961830
arg = convert_expr (arg, tb1, build_object_type());
17971831

1798-
if (global.params.useInvariants && !cd->isCPPclass())
1799-
invc = build_libcall (LIBCALL_INVARIANT, 1, &arg);
1832+
tree invc = build_libcall (LIBCALL_INVARIANT, 1, &arg);
1833+
if (!needsInvariant(tb1))
1834+
{
1835+
// Wrap call to _d_invariant inside the following check:
1836+
// if (typeid(arg) != typeid(tb1))
1837+
// _d_invariant(arg);
1838+
tree tinfo = build_ctype(Type::typeinfoclass->type);
1839+
tree tidtype = tb1->getTypeInfo(NULL)->toElem(NULL);
1840+
tree tidarg = indirect_ref(build_pointer_type(tinfo), arg);
1841+
tidarg = indirect_ref(tinfo, tidarg);
1842+
1843+
invc = build3(COND_EXPR, void_type_node,
1844+
build_boolop(EQ_EXPR, tidarg, tidtype),
1845+
void_node, invc);
1846+
}
18001847

18011848
// This does a null pointer check before calling _d_invariant
18021849
return build3 (COND_EXPR, void_type_node,
18031850
build_boolop (NE_EXPR, arg, null_pointer_node),
1804-
invc ? invc : void_node, assert_call);
1851+
invc, assert_call);
18051852
}
18061853
else
18071854
{
@@ -1811,16 +1858,12 @@ AssertExp::toElem (IRState *)
18111858
tree invc = NULL_TREE;
18121859
tree e1_t = e1->toElem(NULL);
18131860

1814-
if (global.params.useInvariants
1815-
&& tb1->ty == Tpointer && tb1->nextOf()->ty == Tstruct)
1861+
FuncDeclaration *inv = needsInvariant(tb1);
1862+
if (inv != NULL)
18161863
{
1817-
FuncDeclaration *inv = ((TypeStruct *) tb1->nextOf())->sym->inv;
1818-
if (inv != NULL)
1819-
{
1820-
Expressions args;
1821-
e1_t = maybe_make_temp (e1_t);
1822-
invc = d_build_call (inv, e1_t, &args);
1823-
}
1864+
Expressions args;
1865+
e1_t = maybe_make_temp (e1_t);
1866+
invc = d_build_call (inv, e1_t, &args);
18241867
}
18251868
result = build3 (COND_EXPR, void_type_node,
18261869
convert_for_condition (e1_t, e1->type),

0 commit comments

Comments
 (0)