llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.41k stars 12.15k forks source link

Clang: immediately-invoked lambda in template arg is not implicitly constexpr #114234

Open elbeno opened 1 month ago

elbeno commented 1 month ago

An IILE as a template argument inside some other templates; this is the smallest SSCCE I could find.

template <auto Arg>
auto g() { return Arg; }

template <typename>
auto f() {
    []<typename>() {
        // lambda is not treated as implicitly constexpr?
        g<[] { return 123; }()>();
        // explicit constexpr works
        // g<[] () constexpr { return 123; }()>();
    }.template operator()<int>();
}

int main() { f<int>(); }

produces:

<source>:8:9: error: no matching function for call to 'g'
    8 |         g<[] { return 123; }()>();
      |         ^~~~~~~~~~~~~~~~~~~~~~~
<source>:6:20: note: while substituting into a lambda expression here
    6 |     []<typename>() {
      |                    ^
<source>:14:14: note: in instantiation of function template specialization 'f<int>' requested here
   14 | int main() { f<int>(); }
      |              ^
<source>:2:6: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'Arg'
    2 | auto g() { return Arg; }
      |      ^
1 error generated.

https://godbolt.org/z/x6heGf38x

tbaederr commented 1 month ago

Yup, the operator() of the lambda is not constexpr:

CXXMethodDecl 0x7e0f6b6bf760 <./array.cpp:124:12, col:28> col:11 referenced operator() 'auto () const -> int' implicit_instantiation inline instantiated_from 0x7e0f6b6bc900
`-CompoundStmt 0x7e0f6b6bfa30 <col:14, col:28>
  `-ReturnStmt 0x7e0f6b6bfa18 <col:16, col:23>
    `-IntegerLiteral 0x7e0f6b6bcab8 <col:23> 'int' 123
llvmbot commented 1 month ago

@llvm/issue-subscribers-clang-frontend

Author: Ben Deane (elbeno)

An IILE as a template argument inside some other templates; this is the smallest SSCCE I could find. ```cpp template <auto Arg> auto g() { return Arg; } template <typename> auto f() { []<typename>() { // lambda is not treated as implicitly constexpr? g<[] { return 123; }()>(); // explicit constexpr works // g<[] () constexpr { return 123; }()>(); }.template operator()<int>(); } int main() { f<int>(); } ``` produces: ```console <source>:8:9: error: no matching function for call to 'g' 8 | g<[] { return 123; }()>(); | ^~~~~~~~~~~~~~~~~~~~~~~ <source>:6:20: note: while substituting into a lambda expression here 6 | []<typename>() { | ^ <source>:14:14: note: in instantiation of function template specialization 'f<int>' requested here 14 | int main() { f<int>(); } | ^ <source>:2:6: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'Arg' 2 | auto g() { return Arg; } | ^ 1 error generated. ``` https://godbolt.org/z/x6heGf38x
zyn0217 commented 1 week ago

Maybe related https://github.com/llvm/llvm-project/issues/97958