[LLVMbugs] [Bug 10142] New: Exception mistakenly moved from

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Wed Jun 15 07:18:21 PDT 2011


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

           Summary: Exception mistakenly moved from
           Product: clang
           Version: trunk
          Platform: PC
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: C++0x
        AssignedTo: unassignedclangbugs at nondot.org
        ReportedBy: hhinnant at apple.com
                CC: llvmbugs at cs.uiuc.edu, dgregor at apple.com


I stumbled across the following code:


#include <iostream>
using std::cout;
using std::cin;
using std::endl;

struct Blob {
  Blob() { cout << "C" << endl; }
  Blob(const Blob&) { cout << "c" << endl; }
  Blob(Blob&&) { cout << "m" << endl; }
  Blob& operator =(const Blob&) { cout << "=" << endl; return *this; }
  Blob& operator =(Blob&&) { cout << "=m" << endl; return *this; }
  ~Blob() { cout << "~" << endl; }

  int i;
};

int main() {
  try {
     cout << "Throw directly: " << endl;
     throw Blob();
  } catch(const Blob& e) { cout << "caught: " << &e << endl; }
  try {
     cout << "Throw with object about to die anyhow" << endl;
     Blob b;
     throw b;
  } catch(const Blob& e) { cout << "caught: " << &e << endl;  }
  {
    cout << "Throw with object not about to die anyhow (enter non-zero
integer)" << endl;
    Blob b;
    int tmp = 1;
    try {
      if(tmp) throw b;
      cout << "Test is worthless if you enter '0' silly" << endl;
    } catch(const Blob& e) { cout << "caught: " << &e << endl;  }
    b.i = tmp;
    cout << b.i << endl;
  }
}

This code detects whether the compiler moves from the local exception object in
the throw expression.  clang does so for the 2nd and 3rd throw expressions. 
This is correct for the 2nd, but not for the 3rd.  Reference
[class.copy]/p31/b2:

* in a throw-expression, when the operand is the name of a non-volatile
automatic object (other than a function or catch-clause parameter) whose scope
does not extend beyond the end of the innermost enclosing try-block (if there
is one), the copy/move operation from the operand to the exception object
(15.1) can be omitted by constructing the automatic object directly into the
exception object

In the 3rd case of the example the scope **does** extend beyond the end of the
innermost enclosing try-block, and thus 'b' is not eligible for copy/move
elision, and thus according to p32, should not be implicitly moved from.  That
is, the output should be:

...
Throw with object not about to die anyhow (enter non-zero integer)
C
c
...

instead of:

...
Throw with object not about to die anyhow (enter non-zero integer)
C
m
...

-- 
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