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

Commit c82f8e1

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

File tree

2 files changed

+59
-13
lines changed

2 files changed

+59
-13
lines changed

gcc/d/ChangeLog

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
* d-elem.cc(HaltExp::toElem): Use __builtin_trap to halt execution,
44
rather than the library abort() call.
5+
(needsInvariant): New function.
6+
(AssertExp::toElem): Check if there are any invariants found in the
7+
class object's vtable, and only call the invariant if the classinfo
8+
doesn't match at runtime.
59

610
2015-08-07 Iain Buclaw <[email protected]>
711

gcc/d/d-elem.cc

+55-13
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,25 @@ 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+
// Add check for:
1836+
// if (arg.classinfo == typeid(tb1)
1837+
tree tinfo1 = build_ctype(Type::typeinfoclass->type);
1838+
tree tinfo2 = tb1->getTypeInfo(NULL)->toElem(NULL);
1839+
tree classinfo = indirect_ref(build_pointer_type(tinfo1), arg);
1840+
classinfo = indirect_ref(tinfo1, classinfo);
1841+
1842+
invc = build3(COND_EXPR, void_type_node,
1843+
build_boolop(EQ_EXPR, classinfo, tinfo2),
1844+
void_node, invc);
1845+
}
18001846

18011847
// This does a null pointer check before calling _d_invariant
18021848
return build3 (COND_EXPR, void_type_node,
18031849
build_boolop (NE_EXPR, arg, null_pointer_node),
1804-
invc ? invc : void_node, assert_call);
1850+
invc, assert_call);
18051851
}
18061852
else
18071853
{
@@ -1811,16 +1857,12 @@ AssertExp::toElem (IRState *)
18111857
tree invc = NULL_TREE;
18121858
tree e1_t = e1->toElem(NULL);
18131859

1814-
if (global.params.useInvariants
1815-
&& tb1->ty == Tpointer && tb1->nextOf()->ty == Tstruct)
1860+
FuncDeclaration *inv = needsInvariant(tb1);
1861+
if (inv != NULL)
18161862
{
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-
}
1863+
Expressions args;
1864+
e1_t = maybe_make_temp (e1_t);
1865+
invc = d_build_call (inv, e1_t, &args);
18241866
}
18251867
result = build3 (COND_EXPR, void_type_node,
18261868
convert_for_condition (e1_t, e1->type),

0 commit comments

Comments
 (0)