From 1a9de5b6b56a726313069f4447fbbbee469e99dc Mon Sep 17 00:00:00 2001
From: Jason Merrill <jason@redhat.com>
Date: Tue, 29 Aug 2017 15:40:55 -0400
Subject: [PATCH] PR c++/80767 - unnecessary instantiation of generic lambda

	* call.c (convert_like_real): Call build_user_type_conversion_1 if
	cand is null.
	(add_conv_candidate): Build a ck_user conversion with no candidate.

From-SVN: r251427
---
 gcc/cp/ChangeLog                             |  5 +++++
 gcc/cp/call.c                                | 13 +++++++++--
 gcc/testsuite/g++.dg/cpp1z/lambda-inherit1.C | 23 ++++++++++++++++++++
 3 files changed, 39 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/lambda-inherit1.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1e68776fe03e..a60f2ad9679e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
 2017-08-29  Jason Merrill  <jason@redhat.com>
 
+	PR c++/80767 - unnecessary instantiation of generic lambda
+	* call.c (convert_like_real): Call build_user_type_conversion_1 if
+	cand is null.
+	(add_conv_candidate): Build a ck_user conversion with no candidate.
+
 	Fix lambdas in template default argument of inherited ctor.
 	* method.c (synthesized_method_base_walk): Replace an inherited
 	template with its specialization.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index cfedd30cea35..f7f929780529 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -2278,8 +2278,10 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
 
       if (i == 0)
 	{
-	  t = implicit_conversion (totype, argtype, arg, /*c_cast_p=*/false,
-				   flags, complain);
+	  t = build_identity_conv (argtype, NULL_TREE);
+	  t = build_conv (ck_user, totype, t);
+	  /* Leave the 'cand' field null; we'll figure out the conversion in
+	     convert_like_real if this candidate is chosen.  */
 	  convert_type = totype;
 	}
       else if (parmnode == void_list_node)
@@ -6692,6 +6694,13 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
     case ck_user:
       {
 	struct z_candidate *cand = convs->cand;
+
+	if (cand == NULL)
+	  /* We chose the surrogate function from add_conv_candidate, now we
+	     actually need to build the conversion.  */
+	  cand = build_user_type_conversion_1 (totype, expr,
+					       LOOKUP_NO_CONVERSION, complain);
+
 	tree convfn = cand->fn;
 
 	/* When converting from an init list we consider explicit
diff --git a/gcc/testsuite/g++.dg/cpp1z/lambda-inherit1.C b/gcc/testsuite/g++.dg/cpp1z/lambda-inherit1.C
new file mode 100644
index 000000000000..75ef586b542e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/lambda-inherit1.C
@@ -0,0 +1,23 @@
+// PR c++/80767
+// { dg-options -std=c++17 }
+
+template <typename... Fs> 
+struct overloader : Fs...
+{
+    overloader(Fs... fs) 
+        : Fs(fs)...
+    { } 
+
+    using Fs::operator()...;
+};
+
+struct a { void foo() { } };
+struct b { void bar() { } };
+struct c { void bar() { } };
+
+int main() {
+    overloader{
+        [](a x) { x.foo(); },
+        [](auto x) { x.bar(); }
+    }(a{});
+}
-- 
GitLab