In this testcase, determine_visibility was relying on the template argument handling to constrain the lambda in h to internal linkage. In the new lambda model, the local lambda has no template info, so that was breaking. So we shouldn't rely on the decl itself to trigger checking the containing function template arguments.
I initially just took the internal linkage from the containing function and cleared template_decl, but that seems like it could break -fvisibility-inlines-hidden. Tested x86_64-pc-linux-gnu, applying to trunk.
2018-01-22 Jason Merrill <ja...@redhat.com> PR c++/83720 * decl2.c (determine_visibility): Fix template_decl handling for local lambda. diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index a2b2e2892b8..ef7e6de41c3 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -2416,7 +2416,7 @@ determine_visibility (tree decl) but have no TEMPLATE_INFO. Their containing template function does, and the local class could be constrained by that. */ - if (template_decl) + if (DECL_LANG_SPECIFIC (fn) && DECL_USE_TEMPLATE (fn)) template_decl = fn; } else if (VAR_P (decl) && DECL_TINFO_P (decl) diff --git a/gcc/testsuite/g++.dg/lto/pr83720_0.C b/gcc/testsuite/g++.dg/lto/pr83720_0.C new file mode 100644 index 00000000000..4e63c9be7cd --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/pr83720_0.C @@ -0,0 +1,55 @@ +// PR c++/83720 +// { dg-lto-do assemble } + +#pragma GCC diagnostic ignored "-Wreturn-type" + +namespace b { +class h { +public: + template <typename ae, typename af> h(ae af::*...) { + [] {}; + } +}; +class ai {}; +template <typename> class c { +public: + template <typename ag> void aj(const char *, ag f) { h(f, int()); } +}; +} +template <typename> class al; +template <typename e> class i { +protected: + static e g(const int) { } +}; +template <typename, typename> class j; +template <typename an, typename e, typename... ao> +class j<an(ao...), e> : i<e> { + typedef i<e> ap; + +public: + static an aq(const int &ar, ao... as) { ap::g(ar)(as...); } +}; +template <typename an, typename... ao> class al<an(ao...)> { + template <typename, typename a> using ax = a; + +public: + template <typename e, typename = ax<int, void>, typename = ax<int, void>> + al(e); + using ay = an (*)(const int &, ao...); + ay az; +}; +template <typename an, typename... ao> +template <typename e, typename, typename> +al<an(ao...)>::al(e) { + az = j<an(ao...), e>::aq; +} +class k { +public: + k(al<void(b::ai)>); +} d([](b::ai) { + struct be { + virtual void f(); + }; + struct bf; + b::c<bf>().aj("", &be::f); +});