From 02488ab530d65d039672a5bc3cd42391b05f5ba0 Mon Sep 17 00:00:00 2001 From: Adam Butcher Date: Tue, 4 Aug 2009 13:42:25 +0100 Subject: [PATCH 1/2] First pass polymorphic lambda support. This commit adds experimental support for an optional template-parameter-list in angle-brackets at the start of a lambda-parameter-declaration. --- gcc/cp/parser.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- gcc/cp/semantics.c | 3 +++ 2 files changed, 50 insertions(+), 1 deletions(-) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index af8fe01..b56ee7c 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -7163,9 +7163,13 @@ cp_parser_lambda_introducer (cp_parser* parser, /* Parse the (optional) middle of a lambda expression. lambda-parameter-declaration: + lambda-template-param-decl [opt] ( lambda-parameter-declaration-list [opt] ) exception-specification [opt] lambda-return-type-clause [opt] + lambda-template-param-decl: + < template-parameter-list > + LAMBDA_EXPR is the current representation of the lambda expression. */ static void @@ -7174,8 +7178,30 @@ cp_parser_lambda_parameter_declaration_opt (cp_parser* parser, { tree param_list = NULL_TREE; tree exception_spec = NULL_TREE; + tree template_param_list = NULL_TREE; - if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) + if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)) + { + VEC (deferred_access_check,gc) *checks; + + cp_parser_require (parser, CPP_LESS, "%<<%>"); + + push_deferring_access_checks (dk_deferred); + + template_param_list = cp_parser_template_parameter_list (parser); + + /* TODO: Actually use this at the pop site. */ + checks = get_deferred_access_checks (); + + cp_parser_skip_to_end_of_template_parameter_list (parser); + + /* We just processed one more parameter list. */ + ++parser->num_template_parameter_lists; + + push_deferring_access_checks (dk_no_check); + } + + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN) || template_param_list != NULL_TREE) { cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"); @@ -7280,6 +7306,23 @@ cp_parser_lambda_parameter_declaration_opt (cp_parser* parser, DECL_INITIALIZED_IN_CLASS_P (fco) = 1; finish_method (fco); + if (template_param_list != NULL_TREE) + { + tree saved_current_function_decl = current_function_decl; + pop_deferring_access_checks (); + + /* 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; + pop_deferring_access_checks (); + finish_template_decl (template_param_list); + } finish_member_declaration (fco); LAMBDA_EXPR_FUNCTION (lambda_expr) = fco; @@ -7318,6 +7361,9 @@ cp_parser_lambda_body (cp_parser* parser, tree fco = LAMBDA_EXPR_FUNCTION (lambda_expr); tree body; + if (DECL_FUNCTION_TEMPLATE_P (fco)) + 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 ed9ec25..e088690 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -5272,6 +5272,9 @@ deduce_lambda_return_type (tree lambda, tree expr) tree return_type; tree result; + if( TREE_CODE (fco) == TEMPLATE_DECL ) + fco = DECL_TEMPLATE_RESULT (fco); + return_type = finish_decltype_type (expr, /*id_expression_or_member_access_p=*/false); -- 1.6.2.5