@@ -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));
@@ -8783,6 +8783,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]
@@ -8802,10 +8803,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);
@@ -8851,6 +8868,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.
@@ -8894,6 +8913,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);
@@ -8937,6 +8973,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,
@@ -9146,7 +9146,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;
}
@@ -9392,6 +9392,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. */
@@ -9808,6 +9810,12 @@ maybe_add_lambda_conv_op (tree type)
if (processing_template_decl)
return;
+ if (TREE_CODE (callop) == TEMPLATE_DECL)
+ {
+ warning (0, "Conversion of a generic lambda to a function pointer is not currently implemented.");
+ return;
+ }
+
if (DECL_INITIAL (callop) == NULL_TREE)
{
/* If the op() wasn't instantiated due to errors, give up. */