@@ -1746,6 +1746,41 @@ DotVarExp::toElem (IRState *)
1746
1746
return error_mark_node;
1747
1747
}
1748
1748
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
+
1749
1784
elem *
1750
1785
AssertExp::toElem (IRState *)
1751
1786
{
@@ -1784,7 +1819,6 @@ AssertExp::toElem (IRState *)
1784
1819
{
1785
1820
ClassDeclaration *cd = tb1->isClassHandle ();
1786
1821
tree arg = e1 ->toElem (NULL );
1787
- tree invc = NULL_TREE;
1788
1822
1789
1823
if (cd->isCOMclass ())
1790
1824
{
@@ -1795,13 +1829,25 @@ AssertExp::toElem (IRState *)
1795
1829
else if (cd->isInterfaceDeclaration ())
1796
1830
arg = convert_expr (arg, tb1, build_object_type ());
1797
1831
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
+ }
1800
1846
1801
1847
// This does a null pointer check before calling _d_invariant
1802
1848
return build3 (COND_EXPR, void_type_node,
1803
1849
build_boolop (NE_EXPR, arg, null_pointer_node),
1804
- invc ? invc : void_node , assert_call);
1850
+ invc, assert_call);
1805
1851
}
1806
1852
else
1807
1853
{
@@ -1811,16 +1857,12 @@ AssertExp::toElem (IRState *)
1811
1857
tree invc = NULL_TREE;
1812
1858
tree e1_t = e1 ->toElem (NULL );
1813
1859
1814
- if (global. params . useInvariants
1815
- && tb1-> ty == Tpointer && tb1-> nextOf ()-> ty == Tstruct )
1860
+ FuncDeclaration *inv = needsInvariant (tb1);
1861
+ if (inv != NULL )
1816
1862
{
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);
1824
1866
}
1825
1867
result = build3 (COND_EXPR, void_type_node,
1826
1868
convert_for_condition (e1_t , e1 ->type ),
0 commit comments