-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Description
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.