<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/61718>61718</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            std::uninitialized_copy_n does not seem to handle exceptions correctly
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          Akashprem
      </td>
    </tr>
</table>

<pre>
    This is a sample example to trigger this issue:

```
#include <cassert>
#include <memory>
#include <string>

template <typename T>
struct Iterator final
{
 using value_type = T;
    using difference_type = std::ptrdiff_t;
 using reference = value_type const &;
    using pointer = value_type const *;
    using iterator_category = std::input_iterator_tag;

 Iterator(
        std::size_t index,
        std::size_t exception_index,
        T const &obj)
        : index{index}, exception_index{exception_index}, obj{obj}
    {
    }

 Iterator &operator++()
    {
        this->index += 1;
        if (this->index >= this->exception_index)
        {
            throw std::exception{};
        }
        return *this;
    }

 Iterator operator++(int)
    {
        Iterator temp = *this;
 ++(*this);
        return temp;
    }

    reference operator*()
    {
        return this->obj;
    }

 std::size_t index;
    std::size_t exception_index;
    T obj;
};

int main()
{
    using InIt = Iterator<std::shared_ptr<std::string>>;
    auto obj = std::make_shared<std::string>("Hello World");
    {
 std::size_t start_index = 0;
        std::size_t exception_index = 1;
 std::size_t end_index = 2;
        InIt const start{start_index, exception_index, obj};
        std::shared_ptr<std::string> *p;
 std::size_t sz;
        std::tie(p, sz) = std::get_temporary_buffer<std::shared_ptr<std::string>>(end_index - start_index);
        assert(sz == end_index - start_index);
 try
        {
            std::uninitialized_copy_n(start, sz, p);
 }
        catch (...)
        {
        }
    }
 assert(obj.use_count() == 1);
}
```

The `assert(obj.use_count() == 1);` at the end, fails:
```
Assertion failed: (obj.use_count() == 1), function main, file test.cpp, line 70.
zsh: abort ./a.out
```
because `obj.use_count()` is actually `2`.

The compiler flags I used:
```
clang++ -nostdinc++ -nostdlib++ -isystem llvm-project-install/usr/local/include/c++/v1 -L llvm-project-install/usr/local/lib -Wl,-rpath,llvm-project-install/usr/local/lib -lc++ -g3 test.cpp
```

I was able to track the reason for the issue to here:
```
template <class _ValueType, class _InputIterator, class _Size, class _ForwardIterator, class _Sentinel>
inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator>
__uninitialized_copy_n(_InputIterator __ifirst, _Size __n,
                       _ForwardIterator __ofirst, _Sentinel __olast) {
  _ForwardIterator __idx = __ofirst;
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
  try {
#endif
    for (; __n > 0 && __idx != __olast; ++__ifirst, (void)++__idx, (void)--__n)
      ::new (_VSTD::__voidify(*__idx)) _ValueType(*__ifirst);
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
  } catch (...) {
 _VSTD::__destroy(__ofirst, __idx);
    throw;
  }
#endif

 return pair<_InputIterator, _ForwardIterator>(_VSTD::move(__ifirst), _VSTD::move(__idx));
}
```

Given that `++__ifirst` can fail in `for (; __n > 0 && __idx != __olast; ++__ifirst, (void)++__idx, (void)--__n)`; and `_VSTD::__destroy(__ofirst, __idx);` is how the destruction of already-constructed objects is handled in the case of an exception, it seems to be that the order of `++__ifirst` and `(void)++__idx` must be swapped, like:
`for (; __n > 0 && __idx != __olast; (void)++__idx, ++__ifirst, (void)--__n)`.

I tried this solution. It does solve the issue, i.e. `assert(obj.use_count() == 1);`, in the original program, succeeds.

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy8WFuP4joS_jXmxQIFZxrIAw9cmj1IZ8-Mdlrn7Ftkkgp4xrEj2-ke-tevyklIAqEv87AIQceuy-evylXVcGvFUQEsycOaPGxHvHQnbZarn9yeCgP56KDT8_LpJCwVlnJqeV5IoPCr-naaOiOORzDUVTK2BBKuSLAlQfM5C-p39chCoRJZpkBJuEm4tWAcCR-HdnPItTnf2bTOCHVsN_2ng7yQ3HkBdy5A8Rzo00XIOlMmju4dGO60oZlQXNb683X1By2tUEf6zGUJMdqgJNyijWaf0lokFVkGBlTSkbMuxfOHq8IZ3I9dq1hpGaiVvHzHTaKVdZSw2YCrQgvlwNxTWQ2oiPqQccIdHLU59_EJVZQuvgg5frzYqC01LBG2aG3j62LDileIHRUqhV-Ebd6Wgl8JFE5oFQ_LP7UE6MMPwqL-NglXtaP5uv7eEra5MTtf36x4ObQ5X_vPbWu5jbp_2A4S4CEVDRlr_170APbM4Atvw5iEjx4BRY1wS6e9KOFLZJSwxZVw-IjCzeINbde8XLuu3Bv90kbgYgOF59sbGD1K8GXAlUZhYiGMnvxdkm4YEsq9TdJFFW-tz84bhx26qx0W3aCvwaKRN5F60ebutWhX7wazcVBHBHPoLT_D16Or8d7V6Mo-0a6_bvSqT6EczblQ3VP0TlBVg73aO0_x5VZjBW1gnLiBNC5cf_VSYPHdschLpxFVv6Dk_CfElaVhKwiQ_QFSavqPNjIljF2HswV-TZF13Li4uSFbGtykwTuk0qsbeCOu0o4guzHvCawqlMdC5usOpqFK1BSd2_v2UeLxPhT3IdvX-5adAMIWBYKwr4RF_VgdwcV4X7Th5hwfSuxjn0wItmgZG9MeFbdXtO7ybGFfEQhi-Yi2M-cPFLsLvlIJJZzgUrxCGie6OMd4Lapw1URsaNFzcVP6Eu6SE1blyWTyfrG9aibNw-W8-vBjUlqIE11iNVzUkahysYOjrSFX05L_fDoBJbPgM1ZnAeWOuhMg0XjsjAtp29Gs72blLQutvBheYCy97_pBs6VKvGJVgzY0EzgXgnWTpPDpJ4UCOg8mladXe0Lj_KCNoxPCdnyiSzcI6gAJL60_-QAQPCGOpIkruZRnlGJk1rhpeUt0XggJhmaSHy3d09L68w26TCRXx6rn0LHS1qVCJb1nKQ7Ns7Bn6yCnUj7n48LoH5C4sVDWcSkJ25XWELaTOuH4VA-uhO2Spqftnqd0_OfH1KU40PE_krDN2BTcnQjbfFxPXo5wDNvQ3E-3PX3hlvJDM-Dz5KfPJAPcYopgxz5BNeyjxAkM3GO0O5AnkltL479xfn06F4DZUa_tcRptB87L-nfx2hXbafPCTTokCMoJBfIy6gvlEy_-c7_efPsW_7HfPsa7_3z9d7xa72nBBVa2W7c3HhpzcXynuvRt0DgWmTDW1xuPnsYotrktW53XtVcax7pjpT4arkqOi1G3EA0oi7TqYhczlzLDQpGpFLKWl9X3-K-v8eN_N4_fnvZf__remHX4D8O81QOViqw9RebH4gUJ13hAHFpp4P93YbMGAJvWGDzocF0Pc12GCFs8a5H6WlLvpb_6G-OxJ7BXiKtyr-AF5eK_vz9tq5U4RiWRnauBsbYWIWHdrKv3ahTR77BD5tvrTtGJSQ9SCtYZjZB6UW2wdVulH9s7K21X6PFfb9dj6adyuUdXrp_Bw2qpQLUhgYbHDzasf4lnwIGZO6zLV3GfBTThVaehQqHA_z-ZZjg_Uq5SdP_JcFWN56RffBX08mXVA3VGuTTA0_PYT4q4DilOgZA4_wvKiatUQornRuWEW_Baqp0e0Z1w1ALkFqvrASoiUV6bFAwqDLJaH2eYh1lA89I6NGdfeFFAWjXnn73S_XuRuMv7_RB1IjHp9x5nBKTVz0lWyxIpmdC9o6kGv_IMbffxXE1g8vnpyGuqmlRxFIpLWhh9NDz3o2KZJACprbGN0mWYRmHER7CczubRYhaxaTQ6LadRMIuyh4SlhyhbBBEL04eHKVtkYbBY8C9sJJYsYGEQshljLJhGkwxgzubhwzRih3k2S8mXAHIu5AT7-USb48ifbDmbzqeLkeQHkNb_OscYFrz62Iw8bEdm6WeAQ3m05EsghXW2teKEk7B8czauKFW6SjbfyX16trloaaKNgcTJ86g0cnlyrvBDJNsRtjsKdyoPk0TnOGnI5-armUpw7EG4lrCdP87_AgAA__-A8vZT">