zyn0217 wrote:

@mizvekov
The nuance is right here, where we tackle local lambdas and member functions 
separately:

https://github.com/llvm/llvm-project/blob/404f94ac7d8c368fba8ad1f97512c26efd5ec965/clang/lib/Sema/SemaExpr.cpp#L18273-L18282

```cpp

template<typename F> constexpr int visit(F f) { return f(0); }

template <class T> int G(T t);

int main() { return visit([](auto s) -> int { return G(s); }); }

template <class T> int G(T t) {
  return 0;
}

```
So basically, we perform the instantiation as follows.

- The lambda case:

1. We instantiate `visit` once we call it because it's constexpr, with a 
`LocalEagerInstantiationScope` (L1) and `GlobalEagerInstantiationScope` (G1)
2. G1 is disabled because it's called from `MarkFunctionReferenced()`
3. We need to instantiate the lambda expression
4. As the lambda expression is defined *locally*, we fall into the first branch 
so that the lambda expression is pushed into L1.
5. We try to instantiate anything inside L1 after the instantiation of `visit`, 
creating a `LocalEagerInstantiationScope` (L2) and 
`GlobalEagerInstantiationScope` (G2).
6. G2 is enabled because `InstantiateFunctionDefinition` called from 
`PerformPendingInstantiations` goes with `Recursive=true`
7. We meet `G(s)`, and it isn't constexpr, so we defer its instantiation and 
track it in `GlobalEagerInstantiationScope`, which is G2.
8. When we finished the lambda body, we try to instantiate `G` in `G2`, which 
fails because we don't have a definition at the moment.
9. We drop it forever because we assume we're at end of the TU (which isn't the 
case)

- The member function case
1. We instantiate `visit` with a `LocalEagerInstantiationScope` (L1) and 
`GlobalEagerInstantiationScope` (G1), with G1 being disabled.
2. We need to instantiate the member function `operator()`
3. As it is a non-local constexpr function, we instantiate it immediately from 
the second branch I referenced, which creates `LocalEagerInstantiationScope` 
(L2) and `GlobalEagerInstantiationScope` (G2)
4. G2 is disabled because `Recursive=false` which is called from 
`MarkFunctionReferenced()`
5. We return back until we reach the end of TU, where we see the body of G, and 
we instantiate it happily.

https://github.com/llvm/llvm-project/pull/126723
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to