<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/58835>58835</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Unable to call method with forward-declared template variable: "implicit instantiation of undefined template"
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
danakj
</td>
</tr>
</table>
<pre>
These code examples compile in GCC and MSVC in C++11 or newer modes. They fail in Clang in C++11 and newer modes.
# Template methods with forward-declared templated type
Here two methods are templated to avoid knowing the full type of ForwardDecl in their definitions. The template has a default value which is the forward declared type.
Simply constructing the template type works ok, as in `works()`. However calling from one method to the other does not, it tries to instantiate the ForwarDecl template and fails. This works in GCC and MSVC.
```
<source>:8:16: error: implicit instantiation of undefined template 'ForwardDecl<int>'
return works();
^
<source>:2:7: note: template is declared here
class ForwardDecl;
^
1 error generated.
```
https://godbolt.org/z/53sf4Ed5T
```cpp
template <class T>
class ForwardDecl;
struct S {
template <class Alias = ForwardDecl<int>>
Alias doesntwork() {
// This fails to compile in Clang. Calling `works<Alias>()` succeeds.
return works();
}
template <class Alias = ForwardDecl<int>>
Alias works() {
return Alias();
}
};
template <class T>
class ForwardDecl {};
int main() {
S().doesntwork();
S().works();
}
```
# Template methods with forward-declared non-templated type
While minimizing the above, I noticed that the compiler error is different if the forward-declared type is not itself templated. In this case, it says `works()` has an incomplete return type. Again, this works in GCC and MSVC.
```
<source>:7:16: error: calling 'works<ForwardDecl>' with incomplete return type 'ForwardDecl'
return works();
^~~~~~~
<source>:11:11: note: 'works' declared here
Alias works() {
^
<source>:1:7: note: forward declaration of 'ForwardDecl'
class ForwardDecl;
^
1 error generated.
```
https://godbolt.org/z/sdsE49Mo3
```cpp
class ForwardDecl;
struct S {
template <class Alias = ForwardDecl>
Alias doesntwork() {
// This fails to compile in Clang. Calling `works<Alias>()` succeeds.
return works();
}
template <class Alias = ForwardDecl>
Alias works() {
return Alias();
}
};
class ForwardDecl {};
int main() {
S().doesntwork();
S().works();
}
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzlV0tzozgQ_jX40hUXCAP2gUPGSXbmMKdkd88yCKOJLLkkEW_m129LAmxsJzuzs6-qdWEZIdH9dX_9kDeqfi2fWmYYVKpmwH6ju71gBme7PRcMuISf1mugsobPj7-s3XwdkQ94JQkoDZIdmIYdvmvmgIJeoaFc-G2Cyu10v5Ny-kIU30XxbT-SFJ4YKqeWwY7ZVtUGDty20Ch9oLq-qVklqGY12H4b3r3u2amQj0wzsAc1CqBuftyugL4oXsOzVAeO6GzLoOmE8IJANfAQdN2hKgcd17mGmjVccsuVDDaOEqGlqMKt005YeKGiY3BoedUCN0F4kAdH7KhoYvcjR1mv6G9prO4qO8AadXhoB6WfDajniCAXxkGL8tg_jMgyIiuczeGjOrAXdG5FhXBiGq12oOTgTme-k6xwQKMUsiyVdRK5Bas5znEHRxxUWu5V4-7gEe-QEZLj0dHs3YGWBnRnoTJlN4_7K0zTtVGdrliU3kfp7RK_SY4DMK2VdjfOK7xCYEc86H9HUSc9HydxABEpTohD4VxaJ5kUQR30H81spyWc-i39MN3Sf6Ls_ipSgt_C4UPPMfc7YkA3jCSjf_uwxAfGwATcROGoJwmmw5ZJpl2wzq87zo-ttXuD2iPygNdW1Rsl7FzpLc6-4jdLTbO4r7OnqxRU-314cvRfug5An5yVfwA8jCFY4RGi4sSgS4m3gmO8RukdXGVoUOdeDltdXErrKAoMTRV4n3mrQ-T5KHRhe1KvfOGZw7rPgjFR0rXX4AOjzxkwXVUxVg-l6BsDJSruTn3xF1l-ou3S6B5RsOA9RHgzZeq7WPaKL0QgZNhRLq-BewwP5-e8TeANm6459Ah9CFD4k31BKnnzdm_4tXXxscNKvuNfhypLN-qFuRL4yWU0r9x7LbV-rQ8p3WemS3DeNJja6A3enJb3m0l5dztRGFZVw0RzbD9z-OQ6Cq5W1LC-7hr6ai5reWgsEqPZgRAMTe8DwPcPuN16NtZB3I-W3-Ky_A4tBEvokDyTKHa1NbBwHeJ5Sf6xSlxcXNfMSJJhGKvzCB_RXqnO35h7b7eD5LwdTPv92LPe8Ma_0x1Mbe4Xq88qfb87_M0d4H9X-P-pev_frOkzViZ5XhSrOCf5rC7TepWu6MxyK1j5s6QbpNCxidwNx9X3D_942tbcvRbynHzPgRG3zzotyrNMQX3dZo4BhRMhXoafm71WX1iFJ-UHbkzHjDthLZdpNmvLFVkykmyyzYY2CanyxaJZZOkyy6uqWKTLZCbohglTRhn-BSL43we8CLyPsrsZL0lMSJLERZwmMcnnyzpFacu4yUiekDyLFjFDksTc4XApPNOlh7TptgYXBTfWHBeReL6VjHl1KJ926Ehd1lTS5y8zr7n0yH8H4AAp-w">