[PATCH 1/3] [lambda] Support template-parameter-list in lambda-declarator.
Adam Butcher
adam@jessamine.co.uk
Fri Jul 19 09:01:00 GMT 2013
---
gcc/cp/decl2.c | 5 +++--
gcc/cp/lambda.c | 9 ++++++++-
gcc/cp/parser.c | 36 ++++++++++++++++++++++++++++++++++--
gcc/cp/pt.c | 4 +++-
4 files changed, 48 insertions(+), 6 deletions(-)
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 1573ced..c166f6e 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -507,8 +507,9 @@ check_member_template (tree tmpl)
|| (TREE_CODE (decl) == TYPE_DECL
&& MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))))
{
- /* The parser rejects template declarations in local classes. */
- gcc_assert (!current_function_decl);
+ /* The parser rejects template declarations in local classes
+ (with the exception of generic lambdas). */
+ gcc_assert (!current_function_decl || LAMBDA_FUNCTION_P (decl));
/* The parser rejects any use of virtual in a function template. */
gcc_assert (!(TREE_CODE (decl) == FUNCTION_DECL
&& DECL_VIRTUAL_P (decl)));
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index a53e692..98a7925 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -196,7 +196,7 @@ lambda_function (tree lambda)
/*protect=*/0, /*want_type=*/false,
tf_warning_or_error);
if (lambda)
- lambda = BASELINK_FUNCTIONS (lambda);
+ lambda = STRIP_TEMPLATE (get_first_fn (lambda));
return lambda;
}
@@ -759,6 +759,13 @@ 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;
+ }
+
if (DECL_INITIAL (callop) == NULL_TREE)
{
/* If the op() wasn't instantiated due to errors, give up. */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4b683bf..48c95e6 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -8790,6 +8790,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]
@@ -8809,10 +8810,32 @@ 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);
+
+ if (cxx_dialect < cxx1y)
+ cp_parser_error (parser,
+ "Generic lambdas are only supported in C++1y mode.");
+
+ push_deferring_access_checks (dk_deferred);
+
+ 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);
@@ -8858,6 +8881,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.
@@ -8901,6 +8926,13 @@ 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)
+ {
+ pop_deferring_access_checks ();
+ fco = finish_member_template_decl (fco);
+ finish_template_decl (template_param_list);
+ --parser->num_template_parameter_lists;
+ }
}
finish_member_declaration (fco);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index de054ac..3694ccc 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -9028,7 +9028,9 @@ instantiate_class_template_1 (tree type)
tree decl = lambda_function (type);
if (decl)
{
- instantiate_decl (decl, false, false);
+ if (!DECL_TEMPLATE_INFO (decl) || DECL_TEMPLATE_RESULT
+ (DECL_TI_TEMPLATE (decl)) != decl)
+ instantiate_decl (decl, false, false);
/* We need to instantiate the capture list from the template
after we've instantiated the closure members, but before we
--
1.8.3
More information about the Gcc-patches
mailing list