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

    <tr>
        <th>Summary</th>
        <td>
            SIGFPE from -O2 compilation combining array division, float->double assignment ... and iostream?
        </td>
    </tr>

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

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

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

<pre>
    It took me a while to boil down a much larger code to the point where I'm becoming confident there's no Undefined Behavior here:

```
#include <fenv.h>
#include <iostream>

template <typename T, typename D>
struct DualNumber

  DualNumber () : val(0), deriv(0) {}
  
  template <typename T2, typename D2>
 DualNumber (DualNumber<T2,D2>& a) :
    val(a.val), deriv(a.deriv) {}
 
  T val;
  D deriv;
};


template <std::size_t N, typename T>
struct NumberArray

  NumberArray (T a)
    { for (std::size_t i=0; i != N; ++i) _data[i] = a; }
  
  // Access a[i] via a._data[i] and no more SIGFPE!
  template <typename T2>
  NumberArray (NumberArray<N,T2>& a)
    { for (std::size_t i=0; i != N; ++i) _data[i] = a[i]; }
  
  T& operator[](std::size_t i)
    {
      // Remove this assert, even just std::endl, and no more SIGFPE!
      if (!(i < N)) { std::cerr << "Assert failed." << std::endl; }
      return _data[i]; }
  
  NumberArray<N,T>& operator/= (const T& a)
    { for (std::size_t i=0; i != N; ++i) _data[i] /= a; return *this; }
  
  T _data[N];
};

static const unsigned int N = 9; // 9 or 10 SIGFPEs
// static const unsigned int N = 8; // 8 or fewer doesn't SIGFPE

int main(int, char *[])
{
 feenableexcept(FE_INVALID);
  
  typedef float Scalar;  // double doesn't SIGFPE!
  DualNumber<Scalar, NumberArray<N, Scalar>> dn;
  
 // No copy made, no SIGFPE!
  DualNumber<Scalar, NumberArray<N, Scalar>> dncopy{dn};
  
  // Changing only one member doesn't SIGFPE!
  // 2 (or 2.0) in both denominators doesn't SIGFPE!
  // Modifying dn *or* dncopy gives a SIGFPE!
  dncopy.val /= 3.0;
  dncopy.deriv /= 3.0;
 
  DualNumber<double, NumberArray<N, double>> broken_conversion{dn};
 
  return 0;

```

Trying out all the clang++ versions I have handy on Ubuntu 23.10:

clang++ 16.0.6 or 15.0.7 -O2 give a SIGFPE when running this
clang++ -O1, -O0, or -O3 give no SIGFPE
clang++ 14.0.6 or 13.0.1 give no SIGFPE
`clang++ -fsanitize=undefined,address -O2` gives no warnings ... and no SIGFPE!

I'm noticing that a lot of slightly-similar issues are getting marked as duplicates of #6422 or #8472, but nothing here is touching the rounding mode and nothing here *should* be triggering a FP exception, so this may be an independent bug.  I do need that `endl`-emitting assertion in the code path, or the bug doesn't trigger, which confuses me further.  I'm not sure what FP shenanigans iostream (from libstdc++, not libc++, in my Ubuntu clang packages) might be pulling ... or that might be an obvious red herring, since that assertion never fails in this code, and so iostream functions should never be getting called.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0V91y6jgSfhrlpguXkRPAF1xACFup2s05tZPZ21Oy1diaI0uUJJNlnn6rJZufQGb2YiaVAuxW_3361N0S3qvGIC7Z05o9bR5EH1rrls4efWiMe6isPC5fAwRrf0KHIOCjVRohWKis0iDthwEBXV-3oIVr0EFtZZSHFmFvlQnw0aJDeGV83kGFte2UaaC2ZqckmkALHTI-92As_Gok7pRBCWtsxUFZB1FcrFi-Yfn4OcuH__TIC2Vq3UsEVjzv0ByylhUv94TK-uBQdGdx_AzY7bUIcUk47tGIDuGd8Wc4PW1OKj64vg6w6YV-67sK3WBpvob0Cy5kwPiC8RJYsYKD0IwvcsZLsizRqcPwDGy-ZvPNqD5-3w-LX8fFT4F9cnsRYPEctdJaPgMxhDQ6giE2kcXvq_hENvz6FOWo-x51i_Up90FzfEMap99fYO6DpGiKlVe_448Ab1cpvn-GPmW1ck4cb7G_EBIK7zHZc6K0dGcjQJ-9KlZsclasQQHjU1Zs4I2eGF8zvlYEwA8pgmBPa8WeNkALRFxwu3OMbxnfwqqu0Xs4qRyUAJFdWRFGEvE76xB-ef3H9vsL-f4TApx2_HO2l8gUzwTj--We_30wpIcv0Hgn_3aPTgTrUqm56_dTgOeHE6D_xs4eEEKrPAjv0QViCh7QwG-9D3CyiUZqEv0hvPSndumIThlfKMKZyFcObD_bq9E5ktICxvkq-oadUBplxjgfZdcBXMNBfw5D78wVgl-Admcrh508Icm3BD7ji9oaHxLMf9s2J2eR8EMSjK9oI77a9JP-W0ryq3LggwiqhpRDb2JHkkCd4y2Sq0xhxf0vwTqY5sNW-rHER9mf2Vlc2FmQnR1-oANp0RvG52Hkx0VopNwJZYgbJlKtbgWhuRpZXJ4K0JD3DtGISiP-t8Z9YHyxffnx-vaf1T9f4-pznTyd8eMeJe5gp60I8EsttHAU6RiqtH2l8TbMM42vCv1ggD_fIdDJ-gsrXkCa22gGn28Wars_Qickkp6xf6FXsszma2kuqXBTOp9bYRqaFKzRR7AGocPY2f4AiEGVE92tA57F3qoMVDa0INHQ7EEnx_8fVv5lpdodKQIZqU7nbTWED406oAdxq5zk1EbHE1Nk-UWWgzy2yLsr7sKbOPAFvIMwwVs5-xPNj9qaAzqvrLlFevQwnOL88mjC_QErfr67iIbtAwit44BXa2GaVDFg8OfhFVpxQGiFkbRx8GvVm9ADL7Jp_mmQu9SfzrI8m8Xz_ZTl2Rwm33jE-QQzTZIGXG8MxRFLz42VybcpYTL5ltOXdTD5ViQrZw7fun48uS6yPJveVWCz_MrRzgujgvodWbHpx7GV8WchpaOmP_nG2SwfmGIsfAhHcXvIsmxsS5_okz7TpGxsUHXKUwQQoG0AuwOvVdMGfZx41SktHCjve6KiQ2gwBNLohPuJEoQH2e-1qkVAT7qMF7NHziH2g2LxOI-TZNUHctaSZpzUlYdg-7pNzhGc7Y2Mdmm0T5FfLGd85Vvba0nHo0IITjUNOpIL2H6HVAiJifwZvE29uxNHWisMKCNxjyZeBaq-yQBeQVowiDKlzmZ57KWzfIKdShmm1q8sqSciUmh7Edph1-ld1TcXx3wIi-QfrarbeAPpPXq61-x6R9cQcj6CD753CB8UwfY7-BaNMKoRxsN4h6Aqs3O2A60qH2SdiJHKZaCXF2-Uge44noRII9iL-qdo0FOJ6mhTCZB9rzUlSByJaYhwFgoDtjoo23twKAl9QjnCqkyNA1NO0Bg8oIsjik8wKR9xGscib8-p7HpTh3h6014OytWZVLXQNOo8yGUhy6IUD7iczsqyKMrFYv7QLvkjL8v5YloWi_ppOi-LEst6kS9EXcweC5QPaslzXkyn-TyfPU35PJuVEmeLvCqqaj4Ti5I95tgJpTOtD11mXfMQub2cTx9L_qBFhdrHiyrnBj8S8RnndG91S9KZVH3j2WOulQ_-bCWooHE5lJC4YVRZatvtlRYRqdp2lYpFRcRBWqqD8gNjY1uesOJl6MPpytwRXceDfL5Ubh96p5dtCHtPlS42kkaFtq-y2naMbymo4Wuyd_Y3rAPj23SGGd_GVP8XAAD__5Txl7U">