<html>
    <head>
      <base href="https://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 --- - std::string: append(first, last) error when aliasing"
   href="https://llvm.org/bugs/show_bug.cgi?id=30240">30240</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>std::string: append(first, last) error when aliasing
          </td>
        </tr>

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

        <tr>
          <th>Version</th>
          <td>unspecified
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </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>llvm-bugs@daryl.haresign.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org, mclow.lists@gmail.com
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>The standard says:

  | template<class InputIterator>
  | basic_string& append(InputIterator first, InputIterator last);
  |
  | Requires: [first, last) is a valid range.
  |
  | Effects: Equivalent to append(basic_string(first, last)).
  |
  | Returns: *this.

<a href="http://eel.is/c++draft/string::append#20">http://eel.is/c++draft/string::append#20</a>

Given that, I would expect the following to work:

  | std::string str("hello world//");
  |
  | str.append(str.begin(), str.end());
  | str.append(str.begin(), str.end());

And I should end up with 'str' containing:

  | hello world//hello world//hello world//hello world//

libcxx, however, appears to try to avoid creating a temporary string if it can:

<a href="https://github.com/llvm-mirror/libcxx/blob/master/include/string#L2159">https://github.com/llvm-mirror/libcxx/blob/master/include/string#L2159</a>

If the capacity is not enough for the new string, it will resize the storage:

<a href="https://github.com/llvm-mirror/libcxx/blob/master/include/string#L2175">https://github.com/llvm-mirror/libcxx/blob/master/include/string#L2175</a>

Unfortunately '__grow_by()' destroys the old storage before the string is
copied.

This means the above code doesn't work as expected.  You can see the result
of calling the above code here, compiled against libcxx and libstdc++:

<a href="http://coliru.stacked-crooked.com/a/b099fd5dada88798">http://coliru.stacked-crooked.com/a/b099fd5dada88798</a></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>