4

Working through a an update of VS2010 to 2012 here, and there are a couple of unittests failing due to either bad code generation or programming error but I'm not sure which. The code I'm posting is nearly equal to the orginal, and also reproduces the problems.

Here's a case; all classes/implementations are in seperate files.

class Base
{
public:
  virtual ~Base(){}
  void DoIt(){ DoItImpl(); }
protected:
  virtual void DoItImpl() = 0;
};

class Base2 : public Base
{
public:
  virtual void DoStuff() = 0;
};

class Impl : public Base2
{
public:
  Impl();
  void DoStuff();
protected:
  void DoItImpl();
};

void Impl::DoStuff()
{
  throw std::runtime_error( "oops" );
}

void Impl::DoItImpl()
{
  throw std::runtime_error( "oops" );
}

The above resides in a dll, and is tested using unittest++ in an exe (I epanded the CHECK_THROW macro for clarity, doesn't change a thing though):

SUITE( Base )
{
  TEST( Impl )
  {
    Impl c;
    bool caught = false;
    try
    {
      c.DoIt();
    }
    catch( const std::exception& )
    {
      caught = true;
    }

    //this point is never reached, instead control goes to the
    //try/catch in unittest++'s ExecuteTest function
    CHECK( caught );
  }
}

Whether it's a bug or not, is there a workaround I can use immediately, or some general rules on how to avoid this?

edit Added implementation of DoStuff(), if I call that instead of DoIt() there is no problem!

edit This should rule out the possibility of the unittest framework or any other code being the problem, or catching by const reference, or the compiler not knowing runtime_error derives from exception; I expanded the unittest macros to show what they actually do, and created a new project containing just this source file:

namespace SuiteImpl
{
  class TestImpl
  {
  public:
    TestImpl() {}
    virtual void RunImpl() const;
  };

  void TestImpl::RunImpl() const
  {
    xxx::Impl c;
    try
    {
      c.DoIt();
    }
    catch( std::exception& )
    {
      std::cout << "good" << std::endl;
    }
  }
}

int main()
{
  SuiteImpl::TestImpl impl;

  try
  {
    impl.RunImpl();
  }
  catch( const std::exception& )
  {
    std::cout << "not good" << std::endl;
  }
}

The output is not good.

stijn
  • 34,664
  • 13
  • 111
  • 163
  • So you say this works fine with debug build and shows different behavior with release build? Just this fragment and nothing else? – Balog Pal Jul 02 '13 at 15:59
  • [http://stackoverflow.com/a/5108118/1807078](http://stackoverflow.com/a/5108118/1807078) might be related. Make sure to compile the dll and unittest++ with VS2012. – Chris Cooper Jul 02 '13 at 16:02
  • @BalogPal Indeed, debug is fine, release not. Not sure what you mean with "this fragment only"; there's hundreds of tests in the project but this one fails. – stijn Jul 02 '13 at 16:03
  • @ChrisCooper Everything is compiled using VS212 and using the same settings. Also see edit. – stijn Jul 02 '13 at 16:04
  • 2
    @stijn: I mean in good isolation. The posted code looks fine. But if some unrelated part causes undefined behavior, or you manage to break ODR that could manifest in the observed misbehavior with a good compiler. So can you reproduce the bug with just this minimal code? – Balog Pal Jul 02 '13 at 16:08
  • To me this looks more like the functionality of your unit testing framework than your code under test. – John Dibling Jul 02 '13 at 16:21
  • One possibility is that the compiler doesn't realize `runtime_error` is a child of `exception` and thus doesn't consider your catch a candidate. – Mark B Jul 02 '13 at 17:06
  • Have you tried to remove const from catch? – Tomek Jul 02 '13 at 18:12
  • @stijn: in the code in the edit, If it works properly, it should display "`good\nimpossible\nnot good\n`". want to fix that up? – Mooing Duck Jul 02 '13 at 18:28
  • @MooingDuck yeah sorry I was a bit too hasty; however it does not work properly hence so far the output remains 'not good; – stijn Jul 02 '13 at 18:34

1 Answers1

1

This is confirmed to be an optimizer bug and they're hoping to fix it VS2012 Update 4.

stijn
  • 34,664
  • 13
  • 111
  • 163