PR c++/83720 - ICE with lambda and LTO.
authorJason Merrill <jason@redhat.com>
Mon, 22 Jan 2018 21:51:53 +0000 (16:51 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 22 Jan 2018 21:51:53 +0000 (16:51 -0500)
* decl2.c (determine_visibility): Clear template_decl for
function-scope decls.  Propagate anonymous linkage from containing
function.

From-SVN: r256964

gcc/cp/ChangeLog
gcc/cp/decl2.c
gcc/testsuite/g++.dg/lto/pr83720_0.C [new file with mode: 0644]

index 3cbb2a4..8ec76a4 100644 (file)
@@ -1,9 +1,16 @@
+2018-01-22  Jason Merrill  <jason@redhat.com>
+
+       PR c++/83720 - ICE with lambda and LTO.
+       * decl2.c (determine_visibility): Clear template_decl for
+       function-scope decls.  Propagate anonymous linkage from containing
+       function.
+
 2018-01-22  Marek Polacek  <polacek@redhat.com>
 
        PR c++/81933
        * typeck2.c (split_nonconstant_init_1): Return false if we didn't
        split out anything.
-       
+
 2018-01-22  Ville Voutilainen  <ville.voutilainen@gmail.com>
 
        PR c++/83895
index a2b2e28..6324c55 100644 (file)
@@ -2388,7 +2388,9 @@ determine_visibility (tree decl)
             containing function by default, except that
             -fvisibility-inlines-hidden doesn't affect them.  */
          tree fn = DECL_CONTEXT (decl);
-         if (DECL_VISIBILITY_SPECIFIED (fn))
+         if (! TREE_PUBLIC (fn))
+           constrain_visibility (decl, VISIBILITY_ANON, false);
+         else if (DECL_VISIBILITY_SPECIFIED (fn))
            {
              DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn);
              DECL_VISIBILITY_SPECIFIED (decl) = 
@@ -2414,10 +2416,9 @@ determine_visibility (tree decl)
 
          /* Local classes in templates have CLASSTYPE_USE_TEMPLATE set,
             but have no TEMPLATE_INFO.  Their containing template
-            function does, and the local class could be constrained
-            by that.  */
-         if (template_decl)
-           template_decl = fn;
+            function determines their visibility, so we neither
+            need nor want the template_decl handling.  */
+         template_decl = NULL_TREE;
        }
       else if (VAR_P (decl) && DECL_TINFO_P (decl)
               && flag_visibility_ms_compat)
diff --git a/gcc/testsuite/g++.dg/lto/pr83720_0.C b/gcc/testsuite/g++.dg/lto/pr83720_0.C
new file mode 100644 (file)
index 0000000..4e63c9b
--- /dev/null
@@ -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);
+});