This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH 2/4] [lambda] Support implicit conversion of a stateless generic lambda to a function pointer.
- From: Adam Butcher <adam at jessamine dot co dot uk>
- To: Jason Merrill <jason at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org, Gabriel Dos Reis <gdr at integrable-solutions dot net>, Andrew Sutton <andrew dot n dot sutton at gmail dot com>, Adam Butcher <adam at jessamine dot co dot uk>
- Date: Thu, 1 Aug 2013 13:25:28 +0100
- Subject: [PATCH 2/4] [lambda] Support implicit conversion of a stateless generic lambda to a function pointer.
- References: <51E96FB9 dot 6090108 at redhat dot com> <1375359930-12871-1-git-send-email-adam at jessamine dot co dot uk>
---
gcc/cp/lambda.c | 77 ++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 57 insertions(+), 20 deletions(-)
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 98a7925..cf662bb 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -759,12 +759,9 @@ maybe_add_lambda_conv_op (tree type)
if (processing_template_decl)
return;
- if (DECL_TEMPLATE_INFO (callop) && DECL_TEMPLATE_RESULT
- (DECL_TI_TEMPLATE (callop)) == callop)
- {
- warning (0, "Conversion of a generic lambda to a function pointer is not currently implemented.");
- return;
- }
+ bool generic_lambda_p
+ = DECL_TEMPLATE_INFO (callop)
+ && DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop)) == callop;
if (DECL_INITIAL (callop) == NULL_TREE)
{
@@ -773,7 +770,38 @@ maybe_add_lambda_conv_op (tree type)
return;
}
- stattype = build_function_type (TREE_TYPE (TREE_TYPE (callop)),
+ tree fn_result = TREE_TYPE (TREE_TYPE (callop));
+ tree fn_args = copy_list (DECL_CHAIN (DECL_ARGUMENTS (callop)));
+
+ if (generic_lambda_p)
+ {
+ /* Construct the dependent member call for the static member function
+ '_FUN' and remove 'auto' from it's return type to allow for simple
+ implementation of the conversion operator. */
+
+ tree instance = build_nop (type, null_pointer_node);
+ argvec = make_tree_vector ();
+ for (arg = fn_args; arg; arg = DECL_CHAIN (arg))
+ {
+ mark_exp_read (arg);
+ vec_safe_push (argvec, arg);
+ }
+
+ tree objfn = build_min (COMPONENT_REF, NULL_TREE,
+ instance, DECL_NAME (callop), NULL_TREE);
+ call = build_nt_call_vec (objfn, argvec);
+
+ if (type_uses_auto (fn_result))
+ {
+ ++processing_template_decl;
+ fn_result = finish_decltype_type
+ (call, /*id_expression_or_member_access_p=*/false,
+ tf_warning_or_error);
+ --processing_template_decl;
+ }
+ }
+
+ stattype = build_function_type (fn_result,
FUNCTION_ARG_CHAIN (callop));
/* First build up the conversion op. */
@@ -801,6 +829,9 @@ maybe_add_lambda_conv_op (tree type)
if (nested)
DECL_INTERFACE_KNOWN (fn) = 1;
+ if (generic_lambda_p)
+ fn = add_inherited_template_parms (fn, DECL_TI_TEMPLATE (callop));
+
add_method (type, fn, NULL_TREE);
/* Generic thunk code fails for varargs; we'll complain in mark_used if
@@ -827,8 +858,8 @@ maybe_add_lambda_conv_op (tree type)
DECL_NOT_REALLY_EXTERN (fn) = 1;
DECL_DECLARED_INLINE_P (fn) = 1;
DECL_STATIC_FUNCTION_P (fn) = 1;
- DECL_ARGUMENTS (fn) = copy_list (DECL_CHAIN (DECL_ARGUMENTS (callop)));
- for (arg = DECL_ARGUMENTS (fn); arg; arg = DECL_CHAIN (arg))
+ DECL_ARGUMENTS (fn) = fn_args;
+ for (arg = fn_args; arg; arg = DECL_CHAIN (arg))
{
/* Avoid duplicate -Wshadow warnings. */
DECL_NAME (arg) = NULL_TREE;
@@ -837,6 +868,9 @@ maybe_add_lambda_conv_op (tree type)
if (nested)
DECL_INTERFACE_KNOWN (fn) = 1;
+ if (generic_lambda_p)
+ fn = add_inherited_template_parms (fn, DECL_TI_TEMPLATE (callop));
+
add_method (type, fn, NULL_TREE);
if (nested)
@@ -860,19 +894,22 @@ maybe_add_lambda_conv_op (tree type)
body = begin_function_body ();
compound_stmt = begin_compound_stmt (0);
- arg = build1 (NOP_EXPR, TREE_TYPE (DECL_ARGUMENTS (callop)),
- null_pointer_node);
- argvec = make_tree_vector ();
- argvec->quick_push (arg);
- for (arg = DECL_ARGUMENTS (statfn); arg; arg = DECL_CHAIN (arg))
+ if (!generic_lambda_p)
{
- mark_exp_read (arg);
- vec_safe_push (argvec, arg);
+ arg = build1 (NOP_EXPR, TREE_TYPE (DECL_ARGUMENTS (callop)),
+ null_pointer_node);
+ argvec = make_tree_vector ();
+ argvec->quick_push (arg);
+ for (arg = DECL_ARGUMENTS (statfn); arg; arg = DECL_CHAIN (arg))
+ {
+ mark_exp_read (arg);
+ vec_safe_push (argvec, arg);
+ }
+ call = build_call_a (callop, argvec->length (), argvec->address ());
+ CALL_FROM_THUNK_P (call) = 1;
+ if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call)))
+ call = build_cplus_new (TREE_TYPE (call), call, tf_warning_or_error);
}
- call = build_call_a (callop, argvec->length (), argvec->address ());
- CALL_FROM_THUNK_P (call) = 1;
- if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call)))
- call = build_cplus_new (TREE_TYPE (call), call, tf_warning_or_error);
call = convert_from_reference (call);
finish_return_stmt (call);
--
1.8.3