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

    <tr>
        <th>Summary</th>
        <td>
            A constexpr virtual function rejects valid usage of CRTP type as "incomplete type" - compiles with gcc
        </td>
    </tr>

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

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

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

<pre>
    C++20 allows constexpr virtual functions.

The [following code](https://godbolt.org/z/T1TfxjhPK) fails to compile with clang but passes with gcc.
Turning the function `foo` to be non-virtual or removing the constexpr make it compile. But it should be valid also as virtual constexpr, and the type A shall be complete by the time the template argument is being used.

```
class Base {
 constexpr virtual void foo(const Base& b) const {}
};

template<typename ActualType, typename Base>
class CRTP: public Base {
    constexpr void foo(const Base& b) const override {
 // assume we know here for sure that b is of type const ActualType& 
 const auto& other_s = static_cast<const ActualType&>(b);
        // dynamic_cast also fails to compile in this case
        const auto& other_d = dynamic_cast<const ActualType&>(b);
        // do something with other
    }
};

class A: public CRTP<A, Base> { };

int main() {
    constexpr A a1;
}

```

Compilation error:

```
<source>:11:31: error: no viable conversion from 'const Base' to incomplete type 'const A'
   11 |         const auto& other_s = static_cast<const ActualType&>(b);
      |                               ^ ~
<source>:18:17: note: in instantiation of member function 'CRTP<A, Base>::foo' requested here
   18 | class A: public CRTP<A, Base> {
      |                 ^
<source>:18:17: note: in instantiation of template class 'CRTP<A, Base>' requested here
<source>:18:7: note: definition of 'A' is not complete until the closing '}'
   18 | class A: public CRTP<A, Base> {
      | ^
<source>:13:31: error: 'const A' is an incomplete type
   13 | const auto& other_d = dynamic_cast<const ActualType&>(b);
      | ^           ~~~~~~~~~~~~~~~~~~~
<source>:18:7: note: definition of 'A' is not complete until the closing '}'
   18 | class A: public CRTP<A, Base> {
      |       ^
2 errors generated.
```

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzUVkGT2jgT_TXi0jWULQ0YDj4YCJfvkvqKe0qW21iJLLGSzGT2kN--1TYYM8NkU5vaw7qmPCDTr1-_fmpLhqCPFjFniw1b7Gayi43z-TftQyNb7Welq17zLeMbxjc8AWmMewmgnA0Rv588nLWPnTRQd1ZF7WyYs2THkmK4HxoEttjUjsK0PYJyFbLFjvFVE-MpMFEwvmd8f3RV6UycO39kfP8n4_tDeqi_f20-_4_xNdRSmwDRgXLtSRuEFx0bUEbaI5RdhJMMAcOwelTqwuHQeUtJY4MjP2DLpHaOLROCKxGss0_XIpwHj607X4NuZbbyG4KO1_xz2HSRvofGdaYinLM0ugJpggMZRllGBMa3IG3Vw8bXE0IBoZHGUCiBGowI5evwXLc4fMD2ZGREkP7YtWgj6AAlEr0uYHUnNVsml7_-qzIyBNjIgMCyzbD2oG1npysgPfiqf9hHML6EkmQflig-212yZDsmNtO8V45MbKkuK1uEQhH44fWEVPa43GOLT1OC2_8fPjNRwKkrjVZv-QJMKf8CVXdG73U1xRj8BTKErkV4Qfhm3Qs06BFq5yF0nrSWEUoS19VDdwa4aR1LmIoIsouOFl1s0H8JwMQOQpRRqy9KhsjE9gEEFc9XxHcUES7XhWb1amV7wRjM9M762kJsdABF5d9hPGJW9cymsP-YmoPgWowN2a_faX2G229_YpKh2cWk00PjtwUZ5OILahq8j9U2Qiu1ZXxFjf7AHQXI9BY4Mnm0NYb7tpdT9jMBvXeeZtFPgsQ2uM6r3sCiSFMmCkG3MRisg7OWpendc0YfCLr2rgXGs6llM2qntuO27x03_qZgPBsrTFNg2RZ-1uHf9d4U__HFFp_gx2MZVnTLhuppBhRkT21DlDbqQVxXQ4ttiX4yg3n2oP_UAFH0OzwDj390GCJW_Va96bHq-f6yn_6uULb49DuFjQN6IPRBXR-U8yjlXcYKa231NRfjGVmDppR18fbS6GzUZnhdGRdoc5KBst2djX5Ttg9lEu-3wZ2Ria20b81-4yUGXv_G4LrwnjT7x_vrP9eJN7blg-4BjmjRy3g7FNyPr1mVi2ot1nKGeZqJJOEZF-tZk-NCKSkUr2WCol5nSqWqUovnZCF5VYpkpnOe8Oc04VmaJlm6nvNlva4TucK6UjyrBHtOsJXazI05t3SAm-kQOszTVKySdGZkiSb050vOLb5A_5RxTsdNn1PQU9kdA3tOjA4x3GCijgbzR6eWcZB4_IoqhsvhqwvyiNQg0nKYqpI2JX9rP87h6fo-vZ0aZ503-ZtjqY5NV86VaxnfE7HLv6eTd5SZ8X1fTmB8f6n3nPO_AgAA__-0emjO">