This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Remake initial changes from old lambda branch to support explicit lambda template support and fixup against mainline gcc/cp changes.


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]