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