https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83470
Bug ID: 83470 Summary: Type morphing nested lambda capture Product: gcc Version: 7.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: patrick.a.moran at gmail dot com Target Milestone: --- Created attachment 42908 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=42908&action=edit The minimal reproduction as a separate file I found this compiling with gcc 7.2.0 with --std=c++1z -Wall -Wextra Including my very-minimal repro inline here because I don't know how else to explain the issue. -------------- #include <type_traits> // This has to be templated, but the argument doesn't need to be // used for anything template <class T> double& g(); template <class T> int f() { auto& v = g<T>(); static_assert(std::is_same<decltype(v), T&>::value); [](auto inner) { inner(true); }([&](auto) { static_assert(std::is_same<decltype(v), bool&>::value); }); return 0; } int dummy = f<double>(); -------------- As you can see, in this very specific circumstance, the type of v morphs from double& to bool& in the inner lambda. It isn't that bool is special - whatever type we pass as the ignored argument to the inner lambda, v will become that type (lvalue-ref'ed). Changing any of the following will cause the bug to go away: * Making f() not a template * Making g() not a template, or giving g() a template argument that isn't the template argument to f(). * Changing the declaration of v to explicitly spell out double& rather than letting auto& deduce it. * Eliminating the lambda-wrapping. If you directly call the inner lambda, it won't reproduce.