This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Remake initial changes from old lambda branch to support explicit lambda template support and fixup against mainline gcc/cp changes.
- From: Adam Butcher <adam at jessamine dot co dot uk>
- To: GCC <gcc at gcc dot gnu dot org>
- Cc: Adam Butcher <adam at jessamine dot co dot uk>
- Date: Wed, 12 Jun 2013 11:45:53 +0100
- Subject: [PATCH] Remake initial changes from old lambda branch to support explicit lambda template support and fixup against mainline gcc/cp changes.
- References: <fb59cf27f3dd8330fa2710b7f435e2b5 at imap dot force9 dot net> <1371033953-8131-1-git-send-email-adam at jessamine dot co dot uk>
This only supports the explicit template parameter syntax and does not
correctly support conversion to static ptr-to-function for generic
stateless lambdas.
---
gcc/cp/mangle.c | 2 ++
gcc/cp/parser.c | 43 +++++++++++++++++++++++++++++++++++++++++--
gcc/cp/semantics.c | 24 ++++++++++++++++++++----
3 files changed, 63 insertions(+), 6 deletions(-)
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 8da62b5..4d4c0fd 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -1438,6 +1438,8 @@ write_closure_type_name (const tree type)
MANGLE_TRACE_TREE ("closure-type-name", type);
write_string ("Ul");
+ if (TREE_CODE (fn) == TEMPLATE_DECL) // XXX: should we bother mangling generic lambdas?
+ fn = DECL_TEMPLATE_RESULT (fn);
write_method_parms (parms, /*method_p=*/1, fn);
write_char ('E');
write_compact_number (LAMBDA_EXPR_DISCRIMINATOR (lambda));
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 319da21..407dca3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -8668,6 +8668,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
/* Parse the (optional) middle of a lambda expression.
lambda-declarator:
+ < template-parameter-list [opt] >
( parameter-declaration-clause [opt] )
attribute-specifier [opt]
mutable [opt]
@@ -8687,10 +8688,26 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
tree param_list = void_list_node;
tree attributes = NULL_TREE;
tree exception_spec = NULL_TREE;
+ tree template_param_list = NULL_TREE;
tree t;
- /* The lambda-declarator is optional, but must begin with an opening
- parenthesis if present. */
+ /* The template-parameter-list is optional, but must begin with
+ an opening angle if present. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
+ {
+ cp_lexer_consume_token (parser->lexer);
+
+ template_param_list = cp_parser_template_parameter_list (parser);
+
+ cp_parser_skip_to_end_of_template_parameter_list (parser);
+
+ /* We just processed one more parameter list. */
+ ++parser->num_template_parameter_lists;
+ }
+
+ /* The parameter-declaration-clause is optional (unless
+ template-parameter-list was given), but must begin with an
+ opening parenthesis if present. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{
cp_lexer_consume_token (parser->lexer);
@@ -8736,6 +8753,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
leave_scope ();
}
+ else if (template_param_list != NULL_TREE) // generate diagnostic
+ cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
/* Create the function call operator.
@@ -8779,6 +8798,23 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
DECL_ARTIFICIAL (fco) = 1;
/* Give the object parameter a different name. */
DECL_NAME (DECL_ARGUMENTS (fco)) = get_identifier ("__closure");
+ if (template_param_list != NULL_TREE)
+ {
+ tree saved_current_function_decl = current_function_decl;
+
+ /* Clear current function decl to allow check_member_template
+ to pass. Currently it rejects templates inside functions.
+ Couldn't figure out a clean way to test for lambda inside
+ check_member_template. */
+ current_function_decl = NULL_TREE;
+ fco = finish_member_template_decl (fco);
+ current_function_decl = saved_current_function_decl;
+
+ --parser->num_template_parameter_lists;
+
+ finish_template_decl (template_param_list);
+
+ }
}
finish_member_declaration (fco);
@@ -8822,6 +8858,9 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
tree compound_stmt;
tree cap;
+ if (TREE_CODE (fco) == TEMPLATE_DECL)
+ fco = DECL_TEMPLATE_RESULT (fco);
+
/* Let the front end know that we are going to be defining this
function. */
start_preparsed_function (fco,
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index b5c3b0a..db5ba7b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -9135,7 +9135,7 @@ lambda_function (tree lambda)
/*protect=*/0, /*want_type=*/false,
tf_warning_or_error);
if (lambda)
- lambda = BASELINK_FUNCTIONS (lambda);
+ lambda = OVL_CURRENT (BASELINK_FUNCTIONS (lambda));
return lambda;
}
@@ -9381,6 +9381,8 @@ build_capture_proxy (tree member)
closure = DECL_CONTEXT (member);
fn = lambda_function (closure);
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ fn = DECL_TEMPLATE_RESULT (fn);
lam = CLASSTYPE_LAMBDA_EXPR (closure);
/* The proxy variable forwards to the capture field. */
@@ -9795,7 +9797,8 @@ maybe_add_lambda_conv_op (tree type)
if (processing_template_decl)
return;
- if (DECL_INITIAL (callop) == NULL_TREE)
+ if (TREE_CODE (callop) != TEMPLATE_DECL
+ && DECL_INITIAL (callop) == NULL_TREE)
{
/* If the op() wasn't instantiated due to errors, give up. */
gcc_assert (errorcount || sorrycount);
@@ -9830,6 +9833,10 @@ maybe_add_lambda_conv_op (tree type)
if (nested)
DECL_INTERFACE_KNOWN (fn) = 1;
+ // FIXME: generalize/respell add_inherited_template_parms
+ if (TREE_CODE (callop) == TEMPLATE_DECL)
+ fn = add_inherited_template_parms (fn, callop);
+
add_method (type, fn, NULL_TREE);
/* Generic thunk code fails for varargs; we'll complain in mark_used if
@@ -9856,7 +9863,11 @@ 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)));
+ if (TREE_CODE (callop) == TEMPLATE_DECL)
+ DECL_ARGUMENTS (fn) =
+ copy_list (DECL_CHAIN (DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (callop))));
+ else
+ DECL_ARGUMENTS (fn) = copy_list (DECL_CHAIN (DECL_ARGUMENTS (callop)));
for (arg = DECL_ARGUMENTS (fn); arg; arg = DECL_CHAIN (arg))
{
/* Avoid duplicate -Wshadow warnings. */
@@ -9866,6 +9877,11 @@ maybe_add_lambda_conv_op (tree type)
if (nested)
DECL_INTERFACE_KNOWN (fn) = 1;
+ // FIXME: refactor/respell add_inherited_template_parms... it is
+ // FIXME: functionally what we want here
+ if (TREE_CODE (callop) == TEMPLATE_DECL)
+ fn = add_inherited_template_parms (fn, callop);
+
add_method (type, fn, NULL_TREE);
if (nested)
@@ -9889,7 +9905,7 @@ 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)),
+ arg = build1 (NOP_EXPR, TREE_TYPE (DECL_ARGUMENTS (statfn)),
null_pointer_node);
argvec = make_tree_vector ();
argvec->quick_push (arg);
--
1.8.3