[LLVMbugs] [Bug 12200] New: "noreturn" follows virtual method implementation (opposite of g++)

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Tue Mar 6 18:49:13 PST 2012


http://llvm.org/bugs/show_bug.cgi?id=12200

             Bug #: 12200
           Summary: "noreturn" follows virtual method implementation
                    (opposite of g++)
           Product: clang
           Version: unspecified
          Platform: Macintosh
        OS/Version: MacOS X
            Status: NEW
          Severity: normal
          Priority: P
         Component: C++
        AssignedTo: unassignedclangbugs at nondot.org
        ReportedBy: m-llvm at bodyfour.com
                CC: dgregor at apple.com, llvmbugs at cs.uiuc.edu
    Classification: Unclassified


Created attachment 8146
  --> http://llvm.org/bugs/attachment.cgi?id=8146
test case

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.

-- 
Configure bugmail: http://llvm.org/bugs/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.



More information about the llvm-bugs mailing list