[PR c++/83406] deducing lambda type
authorNathan Sidwell <nathan@acm.org>
Thu, 21 Dec 2017 19:16:01 +0000 (19:16 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Thu, 21 Dec 2017 19:16:01 +0000 (19:16 +0000)
https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01432.html
PR c++/83406
* parser.c (cp_parser_lambda_body): Remove obsolete
single-return-statement handling.

PR c++/83406
* g++.dg/cpp0x/lambda/lambda-ice15.C: Adjust error.
* g++.dg/cpp1y/pr83406.C: New.

From-SVN: r255950

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice15.C
gcc/testsuite/g++.dg/cpp1y/pr83406.C [new file with mode: 0644]

index 92a8ac6261355e2579206b3edb02d8b0df714768..e8295507c56ba809711b9af4068ab98a0e27470c 100644 (file)
@@ -1,3 +1,9 @@
+2017-12-21  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/83406
+       * parser.c (cp_parser_lambda_body): Remove obsolete
+       single-return-statement handling.
+
 2017-12-21  Richard Sandiford  <richard.sandiford@linaro.org>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index 35f4e367595a7b8be3076a6b9e864e3818ada25f..57467bda59603d9353852d3fdf7625e4786037ba 100644 (file)
@@ -10578,98 +10578,42 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
   bool nested = (current_function_decl != NULL_TREE);
   bool local_variables_forbidden_p = parser->local_variables_forbidden_p;
   bool in_function_body = parser->in_function_body;
+
   if (nested)
     push_function_context ();
   else
     /* Still increment function_depth so that we don't GC in the
        middle of an expression.  */
     ++function_depth;
+
   vec<tree> omp_privatization_save;
   save_omp_privatization_clauses (omp_privatization_save);
   /* Clear this in case we're in the middle of a default argument.  */
   parser->local_variables_forbidden_p = false;
   parser->in_function_body = true;
 
-  /* Finish the function call operator
-     - class_specifier
-     + late_parsing_for_member
-     + function_definition_after_declarator
-     + ctor_initializer_opt_and_function_body  */
   {
     local_specialization_stack s (lss_copy);
-
     tree fco = lambda_function (lambda_expr);
     tree body = start_lambda_function (fco, lambda_expr);
-    bool done = false;
-    tree compound_stmt;
-
     matching_braces braces;
-    if (!braces.require_open (parser))
-      goto out;
 
-    compound_stmt = begin_compound_stmt (0);
-
-    /* 5.1.1.4 of the standard says:
-         If a lambda-expression does not include a trailing-return-type, it
-         is as if the trailing-return-type denotes the following type:
-         * if the compound-statement is of the form
-               { return attribute-specifier [opt] expression ; }
-             the type of the returned expression after lvalue-to-rvalue
-             conversion (_conv.lval_ 4.1), array-to-pointer conversion
-             (_conv.array_ 4.2), and function-to-pointer conversion
-             (_conv.func_ 4.3);
-          * otherwise, void.  */
-
-    /* In a lambda that has neither a lambda-return-type-clause
-       nor a deducible form, errors should be reported for return statements
-       in the body.  Since we used void as the placeholder return type, parsing
-       the body as usual will give such desired behavior.  */
-    if (is_auto (TREE_TYPE (TREE_TYPE (fco)))
-        && cp_lexer_peek_nth_token (parser->lexer, 1)->keyword == RID_RETURN
-        && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_SEMICOLON)
+    if (braces.require_open (parser))
       {
-       tree expr = NULL_TREE;
-       cp_id_kind idk = CP_ID_KIND_NONE;
-
-       /* Parse tentatively in case there's more after the initial return
-          statement.  */
-       cp_parser_parse_tentatively (parser);
-
-       cp_parser_require_keyword (parser, RID_RETURN, RT_RETURN);
-
-       expr = cp_parser_expression (parser, &idk);
-
-       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
-       braces.require_close (parser);
+       tree compound_stmt = begin_compound_stmt (0);
 
-       if (cp_parser_parse_definitely (parser))
-         {
-           if (!processing_template_decl)
-             {
-               tree type = lambda_return_type (expr);
-               apply_deduced_return_type (fco, type);
-               if (type == error_mark_node)
-                 expr = error_mark_node;
-             }
-
-           /* Will get error here if type not deduced yet.  */
-           finish_return_stmt (expr);
-
-           done = true;
-         }
-      }
+       /* Originally C++11 required us to peek for 'return expr'; and
+          process it specially here to deduce the return type.  N3638
+          removed the need for that.  */
 
-    if (!done)
-      {
        while (cp_lexer_next_token_is_keyword (parser->lexer, RID_LABEL))
          cp_parser_label_declaration (parser);
        cp_parser_statement_seq_opt (parser, NULL_TREE);
        braces.require_close (parser);
-      }
 
-    finish_compound_stmt (compound_stmt);
+       finish_compound_stmt (compound_stmt);
+      }
 
-  out:
     finish_lambda_function (body);
   }
 
index 2696f5e86555bdcf897559f66bd7b51e09ad191b..d6928f00fbd203eabb78c25ffbd292b3ad907030 100644 (file)
@@ -1,3 +1,9 @@
+2017-12-21  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/83406
+       * g++.dg/cpp0x/lambda/lambda-ice15.C: Adjust error.
+       * g++.dg/cpp1y/pr83406.C: New.
+
 2017-12-21  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/83467
index 7c4c18db8733813117e0feb10485026c6cc71150..7a04bb5a51629ddb86488fb607cf7c5f4538f990 100644 (file)
@@ -5,6 +5,11 @@ class A
 {
   void foo ()
   {
-    [=] { return foo; };  // { dg-error "invalid use of member function" }
+    [=] { return foo; };  // { dg-error "cannot convert" }
+  }
+  void bar () const;
+  void bar ()
+  {
+    [=] { return bar; };  // { dg-error "unable to deduce" }
   }
 };
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr83406.C b/gcc/testsuite/g++.dg/cpp1y/pr83406.C
new file mode 100644 (file)
index 0000000..c348968
--- /dev/null
@@ -0,0 +1,41 @@
+// { dg-do compile { target c++14 } }
+// PR 83406, lambda late returns are not the same as missing returns
+
+class Bar
+{
+public:
+  const int& getter() const;
+  int& getter();
+};
+
+auto one = [](const Bar& bar) -> decltype(auto)
+{
+  return bar.getter();
+};
+
+auto two = [](const Bar& bar) -> auto
+{
+  return bar.getter();
+};
+
+auto three = [](const Bar& bar)
+{
+  return bar.getter();
+};
+
+template <typename T, typename U> struct X 
+{
+  static const bool same = false;
+};
+
+template <typename T> struct X<T,T>
+{
+  static const bool same = true;
+};
+
+void frob (Bar &x)
+{
+  static_assert (X<const int &, decltype (one (x))>::same, "not const int &");
+  static_assert (X<int, decltype (two (x))>::same, "not int");
+  static_assert (X<int, decltype (three (x))>::same, "not int");
+}