This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/69842 (wrong error with generic lambda)


The problem here was that the call from the stub returned by the conversion function to the op() was changing an xvalue to an lvalue, leading to a parameter of the wrong type in the op().

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 54448906d76dd9df2523e6c3950ed368cb63b4de
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Feb 17 15:20:02 2016 -0500

    	PR c++/69842
    	* method.c (forward_parm): Split out from...
    	(add_one_base_init): ...here.
    	* lambda.c (maybe_add_lambda_conv_op): Use it.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3b91089..7800ae8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6013,6 +6013,7 @@ extern tree make_thunk				(tree, bool, tree, tree);
 extern void finish_thunk			(tree);
 extern void use_thunk				(tree, bool);
 extern bool trivial_fn_p			(tree);
+extern tree forward_parm			(tree);
 extern bool is_trivially_xible			(enum tree_code, tree, tree);
 extern tree get_defaulted_eh_spec		(tree);
 extern tree unevaluated_noexcept_spec		(void);
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 93b192c..296c6f7 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -962,7 +962,9 @@ maybe_add_lambda_conv_op (tree type)
 	      }
 	    else
 	      {
-		tree a = convert_from_reference (tgt);
+		++processing_template_decl;
+		tree a = forward_parm (tgt);
+		--processing_template_decl;
 		CALL_EXPR_ARG (call, ix) = a;
 		if (decltype_call)
 		  CALL_EXPR_ARG (decltype_call, ix) = copy_node (a);
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index e358ebd..f455b32 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -474,6 +474,19 @@ trivial_fn_p (tree fn)
   return type_has_trivial_fn (DECL_CONTEXT (fn), special_function_p (fn));
 }
 
+/* PARM is a PARM_DECL for a function which we want to forward to another
+   function without changing its value category, a la std::forward.  */
+
+tree
+forward_parm (tree parm)
+{
+  tree exp = convert_from_reference (parm);
+  if (TREE_CODE (TREE_TYPE (parm)) != REFERENCE_TYPE
+      || TYPE_REF_IS_RVALUE (TREE_TYPE (parm)))
+    exp = move (exp);
+  return exp;
+}
+
 /* Subroutine of do_build_copy_constructor: Add a mem-initializer for BINFO
    given the parameter or parameters PARM, possibly inherited constructor
    base INH, or move flag MOVE_P.  */
@@ -494,10 +507,7 @@ add_one_base_init (tree binfo, tree parm, bool move_p, tree inh,
       init = NULL_TREE;
       for (; parm; parm = DECL_CHAIN (parm))
 	{
-	  tree exp = convert_from_reference (parm);
-	  if (TREE_CODE (TREE_TYPE (parm)) != REFERENCE_TYPE
-	      || TYPE_REF_IS_RVALUE (TREE_TYPE (parm)))
-	    exp = move (exp);
+	  tree exp = forward_parm (parm);
 	  *p = build_tree_list (NULL_TREE, exp);
 	  p = &TREE_CHAIN (*p);
 	}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-conv1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-conv1.C
new file mode 100644
index 0000000..6569af4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-conv1.C
@@ -0,0 +1,14 @@
+// PR c++/69842
+// { dg-do compile { target c++14 } }
+
+template <class T, class U> struct same;
+template <class T> struct same<T,T> {};
+
+int main()
+{
+  auto g = [](auto && _var) {
+    same<int&&,decltype(_var)>();
+  };
+
+  g(0);
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]