Skip to content

[clang] failure to instantiate template specialization defined after use when used from generic lambda #125747

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
zygoloid opened this issue Feb 4, 2025 · 2 comments · Fixed by #126723
Labels
accepts-invalid c++11 clang:frontend Language frontend issues, e.g. anything involving "Sema" diverges-from:edg Does the clang frontend diverge from edg compiler diverges-from:gcc Does the clang frontend diverge from gcc on this issue diverges-from:msvc Does the clang frontend diverge from msvc on this issue rejects-valid

Comments

@zygoloid
Copy link
Collaborator

zygoloid commented Feb 4, 2025

Reduced testcase:

template<typename F> constexpr void visit(F f) { f(0); }
template <class T> void G(T t);
int main() { visit([](auto s) -> void { G(s); }); }
template <class T> void G(T t) {}

This should compile and link, but does not, because Clang fails to instantiate G<int> at the end of the TU. (Accepts-invalid version for testsuite).

Because visit and the lambda's call operator are constexpr, they'll get instantiated immediately, which will trigger an attempt to instantiate G<int>, which will fail because it's not defined yet. But it should then get added to the pending instantiations list to be retried at the end of the translation unit, which appears to not be happening in this case.

Curiously, this bug seems to require a lambda -- if the lambda is replaced by an equivalent struct, the bug disappears. Also, a direct call to the lambda does not trigger the bug; it must be indirectly called via another constexpr function.

@zygoloid zygoloid added accepts-invalid c++11 clang:frontend Language frontend issues, e.g. anything involving "Sema" diverges-from:edg Does the clang frontend diverge from edg compiler diverges-from:gcc Does the clang frontend diverge from gcc on this issue diverges-from:msvc Does the clang frontend diverge from msvc on this issue rejects-valid labels Feb 4, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 4, 2025

@llvm/issue-subscribers-c-11

Author: Richard Smith (zygoloid)

Reduced testcase: ```c++ template<typename F> constexpr void visit(F f) { f(0); } template <class T> void G(T t); int main() { visit([](auto s) -> void { G(s); }); } template <class T> void G(T t) {} ``` This should compile and link, but [does not](https://godbolt.org/z/94xY8eGWe), because Clang fails to instantiate `G<int>` at the end of the TU. ([Accepts-invalid version](https://godbolt.org/z/hEfdjxT8z) for testsuite).

Because visit and the lambda's call operator are constexpr, they'll get instantiated immediately, which will trigger an attempt to instantiate G&lt;int&gt;, which will fail because it's not defined yet. But it should then get added to the pending instantiations list to be retried at the end of the translation unit, which appears to not be happening in this case.

Curiously, this bug seems to require a lambda -- if the lambda is replaced by an equivalent struct, the bug disappears. Also, a direct call to the lambda does not trigger the bug; it must be indirectly called via another constexpr function.

@llvmbot
Copy link
Member

llvmbot commented Feb 4, 2025

@llvm/issue-subscribers-clang-frontend

Author: Richard Smith (zygoloid)

Reduced testcase: ```c++ template<typename F> constexpr void visit(F f) { f(0); } template <class T> void G(T t); int main() { visit([](auto s) -> void { G(s); }); } template <class T> void G(T t) {} ``` This should compile and link, but [does not](https://godbolt.org/z/94xY8eGWe), because Clang fails to instantiate `G<int>` at the end of the TU. ([Accepts-invalid version](https://godbolt.org/z/hEfdjxT8z) for testsuite).

Because visit and the lambda's call operator are constexpr, they'll get instantiated immediately, which will trigger an attempt to instantiate G&lt;int&gt;, which will fail because it's not defined yet. But it should then get added to the pending instantiations list to be retried at the end of the translation unit, which appears to not be happening in this case.

Curiously, this bug seems to require a lambda -- if the lambda is replaced by an equivalent struct, the bug disappears. Also, a direct call to the lambda does not trigger the bug; it must be indirectly called via another constexpr function.

@zyn0217 zyn0217 closed this as completed in c1468e9 Mar 5, 2025
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this issue Mar 5, 2025
…ation (#126723)

For constexpr function templates, we immediately instantiate them upon
reference. However, if the function isn't defined at the time of
instantiation, even though it might be defined later, the instantiation
would forever fail.

This patch corrects the behavior by popping up failed instantiations
through PendingInstantiations, so that we are able to instantiate them
again in the future (e.g. at the end of TU.)

Fixes llvm/llvm-project#125747
jph-13 pushed a commit to jph-13/llvm-project that referenced this issue Mar 21, 2025
…#126723)

For constexpr function templates, we immediately instantiate them upon
reference. However, if the function isn't defined at the time of
instantiation, even though it might be defined later, the instantiation
would forever fail.

This patch corrects the behavior by popping up failed instantiations
through PendingInstantiations, so that we are able to instantiate them
again in the future (e.g. at the end of TU.)

Fixes llvm#125747
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepts-invalid c++11 clang:frontend Language frontend issues, e.g. anything involving "Sema" diverges-from:edg Does the clang frontend diverge from edg compiler diverges-from:gcc Does the clang frontend diverge from gcc on this issue diverges-from:msvc Does the clang frontend diverge from msvc on this issue rejects-valid
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants