C++ PATCH for c++/83270, ICE with lambda and LTO

Message ID CADzB+2m9qia4+HHz68BZcgq=TshqeWT46zpngg=eu9TtcX6Ehw@mail.gmail.com
State New
Headers show
Series
  • C++ PATCH for c++/83270, ICE with lambda and LTO
Related show

Commit Message

Jason Merrill Jan. 22, 2018, 10:41 p.m.
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  <jason@redhat.com>

	PR c++/83720
	* decl2.c (determine_visibility): Fix template_decl handling for
	local lambda.

Patch

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