Skip to content

"noreturn" follows virtual method implementation (opposite of g++) #12572

@mitchblank

Description

@mitchblank
mannequin
Bugzilla Link 12200
Version unspecified
OS MacOS X
Attachments test case
CC @AaronBallman,@DougGregor,@eugenis,@mitchblank,@zygoloid,@rjmccall,@rnk,@seanm

Extended Description

Note this problem is with /usr/bin/c++ in the latest XCode "Version 4.3 (4E109)" Sorry if this isn't the best place to file xcode bugs or if it's already fixed in trunk. I looked around bugzilla and didn't see a duplicate.

I'm porting a large commercial C++ package to build on clang. Things mostly compiled OK, but I've had to track down a tricky crash. The issue turned out to be a difference in how clang treats the combination of "virtual" and "attribute((noreturn))" on methods.

For instance, on g++ you can do:

  class A {
    virtual void handleFoo() __attribute__((noreturn)) { throw FooNotImplmented(); }
  };
  class B : public A  {
    void handleFoo() { do_something(); }
  };

Here the "noreturn" only applies to A::handleFoo() (and you'll get a warning if you DON'T add the attribute), not any method which might overload it. So if someone does:

  B b;
  A *a = &b;
  a->handleFoo();   // will return since this isn't really A::handleFoo()
  puts("after handleFoo");

In clang++, the "noreturn" attribute from the virtual method seems to be interpreted below and the puts() will end up elided.

Attached is a simple test program which demonstrates this:

  $ g++ a.cpp
  $ ./a.out 
  in B::foo()
  at end of A::go()

  $ clang++ a.cpp
  $ ./a.out 
  in B::foo()
  in B::foo()
  Segmentation fault: 11 (core dumped)

  $ clang++ --version
  Apple clang version 3.1 (tags/Apple/clang-318.0.45) (based on LLVM 3.1svn)
  Target: x86_64-apple-darwin11.3.0
  Thread model: posix

NOTE: even if you think the llvm behavior here is the correct one (and there is a case to be made for it) then clang++ desperately needs to emit a warning in this case. clang is already very strict about "noreturn" being part of the function signature (as per Bug 10338) but it's silent if a non-noreturn method overrides a noreturn method in a base class. Instead it just emits broken code (it took about a day of reading assembly to figure out where the problem was :-( )

However, I think the best thing to do would be to just treat noreturn the same way as g++, i.e. never assume a virtual method dispatch won't return.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugzillaIssues migrated from bugzillac++clang:codegenIR generation bugs: mangling, exceptions, etc.diverges-from:gccDoes the clang frontend diverge from gcc on this issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions