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

    <tr>
        <th>Summary</th>
        <td>
            False positive on [[lifetimebound]] when returning a prvalue
        </td>
    </tr>

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

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

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

<pre>
    Consider this example:

```cpp
template <class T>
struct Optional {
    bool flag;
    union { T val; };

    auto value() && [[clang::lifetimebound]] -> T&&;

    template <class U>
    auto value_or(U&& rhs) && [[clang::lifetimebound]] -> decltype(auto) {
 return flag ? (T&&)val : (U&&)rhs;
    }
};

auto f() -> Optional<int const>;

auto g() -> int {
    auto&& r1 = f().value();
    auto&& r2 = f().value_or(-1);
    auto&& r3 = f().value_or(42.0);
    return r1 + r2 + r3;
}
```

This is a very reduced implementation of `Optional`. In the usage in `g`, `r1` and `r2` are dangling references but `r3` is not (it's a reference bound to a temporary of type `double` so it's lifetime extended). gcc's `-Wdangling-reference` warning correctly diagnoses `r1` and `r2` as problematic and correctly does not diagnose `r3`. 

clang doesn't have `-Wdangling-reference`, but I can add `[[clang::lifetimebound]]` to get the same behavior. The problem is that it over-diagnoses:

```console
<source>:17:17: warning: temporary bound to local reference 'r1' will be destroyed at the end of the full-expression [-Wdangling]
   17 |     auto&& r1 = f().value();
      | ^~~
<source>:18:17: warning: temporary bound to local reference 'r2' will be destroyed at the end of the full-expression [-Wdangling]
   18 | auto&& r2 = f().value_or(-1);
      | ^~~
<source>:19:17: warning: temporary bound to local reference 'r3' will be destroyed at the end of the full-expression [-Wdangling]
   19 | auto&& r3 = f().value_or(42.0);
      | ^~~
```

`r3` isn't a problem though, because that specialization of `value_or()` returns `double`. 
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJysVsuO4jgU_RqzuQIlNiFkkUUBhdSr2VRrliPHuSQeGTuyHaroRX_7yA4JqamqnunqlhB5-D7OOfehcOdkoxFLku1Idljw3rfGlpXFyzepF5Wpr-XeaCdrtOBb6QBf-LlTSNgDSQ4kGf83yfATXTe88XjuFPcIhO2F4s7BE2GPw5nzthce_ui8NJorIPluOAAAqIxRcFK8IWz2ttfS6GAIT3DhirAdkPwwmdwNee9NsOiR0C2hBRC6IXQDkeBOKK6bgJ09KHlCL89YmV7XJDuQ7ABLwh7hafB4J_ZbTl8nTq9z_2Usoduvt9y2dZ9CUqNQ_toFJiF0jDFJZdH3VkelgLAjELodkdPiElRlD3AHQWgRYMw1DQIODN8oGZmcbgpGLGOxCNtL7UEY7Xwg_45fM_cLxq_qOzAZdEmBsMOYZzWr2iuccw_61mPQepn-yI195Lamq-TfjjdlAzq6iynDhd2pTrqNXT-X4ClMiXTA4YL2ChbrXmANMkzNGbXnQUcwJyCbZBJ1k6zgiwbfIvSONwhSh_MmxKb7cGtTskmA6zo-0PhgEWquGyV1AxZPaFELdFD1PhqxYCQdaONDI0hPaB5wTaYQOw68AR5721hurwFaaLoQojZ9pTCEcQZu_mO3Ar541DXWQVFohIinZJMs_xxBLadMIcQztzogFcZaFF5doZa80cah-4igg86aSuGZeyni2czZ4EBtjDJxXsG8HnHQorUmNPfQ8gv-AGaQOwj4BQTXwOsI5_-MbAAcmh99LKPjZ4QKW36Rxq7gqcWRSyiJb7kH6cFc0C4nGT5cqkY7o_D2lu2d6a3AOH0PaT7-jQKH23s1pxIrI7ia1Z7Q3KaE5vAslYIKoUbnrbliDXyggLqOzdAinHqllvjSWXQuLuJsd9cvkB-HJ82B5Hv43KBD9CXZ4_fv73Pd_gJX-vu5biPeT66n_yRb_AJZ9vvJFm_I_tRSfUv3veU5W1vDtPJpanxr-qaN44mC9w6HIXIdCsmV_DbfqzMsAccmue1092qprWBRl6wuWMEXWKY5LTbFtsjyRVuiWDPGqiw7pacsSTfZiWbbrMpqWtUpr7cLWdKErtOEsjTLsixfJcmarlO2FhuRrtcFI-sEz1yqlVKX88rYZiGd67FMU7bO6ULxCpWLn12UanyGeEooDV9htgxOy6pvHFknSjrv7mG89ArLI1cOoTNOenlBGCpHst173xLPLeqbAGH_BkmjQIveqrL1vouLhx4JPTbSt321EuZM6DGkvF2WnTV_o_CEHiNQR-jxxuRS0n8CAAD__wKvBeA">