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);
+});

Reply via email to