--- gcc/cp/mangle.c | 2 ++ gcc/cp/parser.c | 43 +++++++++++++++++++++++++++++++++++++++++-- gcc/cp/semantics.c | 10 +++++++++- 3 files changed, 52 insertions(+), 3 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 6e8293b..d0867c7 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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, diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index f821754..792c385 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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. */ -- 1.8.3