@@ -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+ 
17491784elem *
17501785AssertExp::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