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

    <tr>
        <th>Summary</th>
        <td>
            [clang] consteval constructor executes at runtime when invoked by escalated immediate function (or fails to link)
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang
      </td>
    </tr>

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

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

<pre>
    Consider the following code:

```c++
#include <iostream>
#include <optional>


class ConstEval {
 public:
  consteval ConstEval(const char* value) {
    const char* current_char = value;
 while (*current_char) {
      if (*current_char == 'a') {
 throw "Disallowed character!";
      }
      ++current_char;
 }
    value_ = value;
  }
  constexpr const char* value() { return value_; }
 private:
  const char* value_;
};

void TakesOptional(std::optional<ConstEval> maybe_value) {
  if (maybe_value.has_value()) {
    std::cout << "Value: " << maybe_value->value() << std::endl;
  } else {
    std::cout << "No value" << std::endl;
  }
}

int main(int argc, const char*argv[]) {
  // 1
  TakesOptional("testing 123");
  // 2
 std::optional<ConstEval> foo2 = "testing 123";
  // 3
  constexpr std::optional<ConstEval> foo3 = "testing 123";
  // 4
 TakesOptional(ConstEval{"testing 123"});
}

// 5
std::optional<ConstEval> foo5 = "testing 123";
// 6
constinit std::optional<ConstEval> foo6 = "testing 123";
```

Assuming I'm reading things correctly, I would expect the `std::optional` constructor to be an immediate-escalating function (because it is "a function that results from the instantiation of a templated entity defined with the constexpr specifier"), and a contained call to `ConstEval`'s constructor to be an immediate-escalating expression, causing the `std::optional` constructor to become an immediate function.

Thus, I would expect lines 1, 2, 3, 5, and 6 all to immediately invoke the `std::optional` constructor to create a compile-time constant `std::optional` (indirectly invoking the `ConstEval` constructor), while 4 would immediately invoke the `ConstEval` to create a constant `ConstEval`, which would then passed to the (not immediate, in this case) `std::optional` constructor.

Given that, I would further expect that changing "testing" to "tasting" on any of the 6 lines would result in a compiler failure (specifically, one informing me that `throw "Disallowed character!"` is not valid in a constant expression).

However, with clang built from revision 3dbd929ea6af134650dd1d91baeb61a4fc1b0eb8, only lines 3, 4, and 6 fail to compile if "testing" is changed to "tasting". Lines 1, 2, and 5 unexpectedly continue to compile if "testing" in changed to "tasting", and instead cause an abort at runtime due to the uncaught exception. Thus, it appears that while clang properly considers the invocation of the explicitly-immediate `ConstEval` constructor to be a constant expression in 4, it erroneously does _not_ consider the invocation of the escalated-to-immediate `std::optional` constructor to be a constant expression in 1, 2, and 5. Meanwhile, 3 and 6 invoke the constructor within an explicit constant expression, so those work as expected.

A further note: the observed behavior of `ConstEval`'s constructor executing (and crashing if "testing" is changed to "tasting") at runtime for 1, 2, and 5 appears only to happen if it's small enough to inline into the generated `std::optional` specialization. If the constructor is more complicated and doesn't get inlined, lines 1, 2, and 5 will instead generate a linker error due to the symbol `ConstEval::ConstEval(char const*)` not being defined.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyUWE1v4zgS_TX0pRBDomzZPviQTrp3G9iPy2CvAUWWLE4o0iApp72_flCkbEv5mKQDQ7Ek8vHVe1VFySIEfbCIe7b-xtaPCzHEzvm9f_7TBrtonDrvH5wNWqGH2CG0zhj3ou0BpFPIqntWPLLicqyL_JGMf6NPvsorbaUZFAKrHrQL0aPoWfX9vdvuGLWzwtxuT47SiBCA-MTvJ2GAbcYl4Dg0RssrHQBJg5AGXYczvk1XQXbCM34PJ2EGZHw3wYFx5nWMHLxHG5_oHFj1OE6qLhNeOm0QGN8yfj8d-wYWQLfvjCNMgmV8IxjfzKfFzrsXYJw_6iBId1SJmJARPeMl4_zGJP2xzePsNNkw43UdPxuaonp6L8DpuCzqr6OHd4XcjuzBYxy8HUFZ9W2CcfT6JCK-dmoO9XRdniZev6fjyWkFf4hnDP-9pArfhqgIsbq_pc_DzffqO_Ti3ODTe4ZnVyb3l50IT5OI3jh5XUy6IVLOsuqBTPpfFu6evl8uT3DvWPV9JlQecUVDq8xcdkAT8Gtr_8ddTOBfAL5pOxFW2wi90JbxLX0V_iAZf5jbI_zhlBvFK1UY_8H4Dygv568NYpxHDJH6Rskrylu-m3LK0_l4_qmdrXMcctm8xn0DWr3N3q_gV1_FX43nr0O-AW6-vYXZPE4VeGXFiLzOZ19hu_6E7YhYj32UZmur45eUqD_DvnT9aQj3IQw9Df7J-KYHj0LRWey0PQSQznuU0Zwpw37CixuMAvx1RBnTLsPq4i2zusgW-kFG5yE6aBCEBd33qLSIeIdBCiMSx3awkuZRcTcoxRAQdAQdKBBxux07EcFjGEwM0HrXp_W1DVHYqEUa41oQELE_GhFRAdqo4xkUttqighcduzRpkl9HlLrV1KNTovMHEFaBoCFRpFlSGEMhsLq46V0XjG_Cb0RJq2EI2tlUqmIIWeTfUFC6fo5_1WY59fOPbgjvmGW0xQAl3eF0qOiwvgRcwxjlFdycQduTe8bfISk9Ei-Srz9qg3dR96PcwsYPUVIjUzonWl52os5U9emCo195X1-N0X7MfwYz53qjN3c4gctuhI4dWjiKEFDR_ATLt9bF26I0RVOq6gBShLyDfS7dzL9_6BPmbJ-62A4-duhvpSdSq7cHEupW8bSrUK5yHsX1grMg7JmKgzjXYypk3FxQRPpqmodWaDP4FN5YIFQEqQU4SzXXOp9aRo-ZCauLrzwB1QWVNSl2Ekary6qj_NMS2c0k-ad7wROhPOQalkbYAzSDNjF3Ao8nTROhUo3a8R2KWrRltarXhVKl2pWNwKYuxaqVZVNgs82hmPOoRSqG1a0YSICUI1mR_Ogx1Zj8JfVzKszkXsK_XpUaYa5hsNk7VOac2ou2A_79IvbDRS6w1P5QKMhtU1gQjfMRqFMONhWfyouQ84OVYjh0pLTElIlLuHQLHUEcjyh8yI7mqspCH707os-s0_tFGFvvyclr36Ur-OtotNTRnO9uTepvKvjSM9_LAYp-NTJD751FNwRzBuUwwJN18elK5yM2ufuiuotuzuerO9ZHvF5Zu4R_o7BJsdRZxySatJ8pNmUwJb69yvV-CTxAINtcQHhx_hlEgEsCzYrj_tobrEuP62lF1wT0J1TQYCdO2nlS5bMtDH-hHGLuKFsKQnoR6DngtwqAmt4kAVvn39TCJdVSCUYHHV2wtIqOiVXoaT9C64ZDl7YlS4UK2o6pfECLPu3xH9mZGpcw-v8iJ_rP9o0TOkDvPKYCNFomOOJHKWYZ30Q4YByXVkT-9R6ag3nRxlwL8UIMBI1-po7tvfPTMgznvnFmbkaiP3v_pTfORJbxe9rp6iI1zgbJjvGJZrlQ-0rtqp1Y4L7c8F25rjb1etHt5Vbumoq3pSjKjdoVlWg3xWq727WrndpKtdB7XvBVWZSbYst3fL0stlVdbbZl0ax4Xa9btiqwF9osjTn1S-cPCx3CgPuy5PVmszCiQRPSbxGcpzZBzq8fF35PE-6a4RDYqjA6xHCDiDqa9ANGnrF-nLz9v01EDNM8eqHtN9eUguZ8K-93Hogof13exwLJTlYwvlsM3uy7GI-BBE8P2gcdu6FZStcz_oN4jv_ujt79iTIy_iPFHRj_MYZ-2vO_AgAA___EypnE">