<html>
    <head>
      <base href="http://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - Move from destroyed object in tuple_cat of nested tuples"
   href="http://llvm.org/bugs/show_bug.cgi?id=22806">22806</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Move from destroyed object in tuple_cat of nested tuples
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libc++
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>3.6
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>Macintosh
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>MacOS X
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>All Bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>ldionne.2@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvmbugs@cs.uiuc.edu, mclow.lists@gmail.com
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>This bug concerns libc++ trunk (git-svn ID 230867).

In the following code, `Tracked{}` is destroyed and is then moved-from.

    std::tuple_cat(std::make_tuple(std::make_tuple(Tracked{})));

Here's a self-contained test program:

    #include <cassert>
    #include <tuple>

    struct Tracked {
        enum class State { CONSTRUCTED, MOVED_FROM, DESTROYED };
        State state;

        Tracked() : state{State::CONSTRUCTED} { }

        Tracked(Tracked const& t) : state{State::CONSTRUCTED} {
            assert(t.state != State::MOVED_FROM && "copying a moved-from
object");
            assert(t.state != State::DESTROYED && "copying a destroyed
object");
        }

        Tracked(Tracked&& t) : state{State::CONSTRUCTED} {
            assert(t.state != State::MOVED_FROM && "double moving from an
object");
            assert(t.state != State::DESTROYED && "moving from a destroyed
object");
            t.state = State::MOVED_FROM;
        }

        ~Tracked() {
            assert(state != State::DESTROYED && "double-destroying an object");
            state = State::DESTROYED;
        }
    };

    int main() {
        std::tuple_cat(std::make_tuple(std::make_tuple(Tracked{})));
    }

Compiling and then running this will produce:

    Assertion failed: (t.state != State::DESTROYED && "moving from a destroyed
object")

I don't have the time to investigate this further right now, unfortunately.</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>