]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Core 975
authorJason Merrill <jason@redhat.com>
Tue, 23 Aug 2011 16:03:15 +0000 (12:03 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 23 Aug 2011 16:03:15 +0000 (12:03 -0400)
Core 975
* decl.c (cxx_init_decl_processing): Initialize
dependent_lambda_return_type_node.
* cp-tree.h (cp_tree_index): Add CPTI_DEPENDENT_LAMBDA_RETURN_TYPE.
(dependent_lambda_return_type_node): Define.
(DECLTYPE_FOR_LAMBDA_RETURN): Remove.
* semantics.c (lambda_return_type): Handle overloaded function.
Use dependent_lambda_return_type_node instead of
DECLTYPE_FOR_LAMBDA_RETURN.
(apply_lambda_return_type): Don't check dependent_type_p.
* pt.c (tsubst_copy_and_build): Handle lambda return type deduction.
(instantiate_class_template_1): Likewise.
(tsubst): Don't use DECLTYPE_FOR_LAMBDA_RETURN.
* mangle.c (write_type): Likewise.
* typeck.c (structural_comptypes): Likewise.
(check_return_expr): Handle dependent_lambda_return_type_node.

From-SVN: r177995

12 files changed:
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/mangle.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg.C
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg2.C
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-neg.C
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce2.C

index 0f60bcb313a0e74eda4adfe06322a9b7e7d3cd5f..0f325a8936740ce43ad316262d99750db478b1bc 100644 (file)
@@ -1,3 +1,22 @@
+2011-08-23  Jason Merrill  <jason@redhat.com>
+
+       Core 975
+       * decl.c (cxx_init_decl_processing): Initialize
+       dependent_lambda_return_type_node.
+       * cp-tree.h (cp_tree_index): Add CPTI_DEPENDENT_LAMBDA_RETURN_TYPE.
+       (dependent_lambda_return_type_node): Define.
+       (DECLTYPE_FOR_LAMBDA_RETURN): Remove.
+       * semantics.c (lambda_return_type): Handle overloaded function.
+       Use dependent_lambda_return_type_node instead of
+       DECLTYPE_FOR_LAMBDA_RETURN.
+       (apply_lambda_return_type): Don't check dependent_type_p.
+       * pt.c (tsubst_copy_and_build): Handle lambda return type deduction.
+       (instantiate_class_template_1): Likewise.
+       (tsubst): Don't use DECLTYPE_FOR_LAMBDA_RETURN.
+       * mangle.c (write_type): Likewise.
+       * typeck.c (structural_comptypes): Likewise.
+       (check_return_expr): Handle dependent_lambda_return_type_node.
+
 2011-08-23  Jason Merrill  <jason@redhat.com>
 
        PR c++/50024
index ff5509e5b3f58d78c35ade379215e1d34bb5ce0e..859594393979bdc5bb0c653b846835720166bd56 100644 (file)
@@ -83,7 +83,6 @@ c-common.h, not after.
       STMT_IS_FULL_EXPR_P (in _STMT)
       TARGET_EXPR_LIST_INIT_P (in TARGET_EXPR)
       LAMBDA_EXPR_MUTABLE_P (in LAMBDA_EXPR)
-      DECLTYPE_FOR_LAMBDA_RETURN (in DECLTYPE_TYPE)
       DECL_FINAL_P (in FUNCTION_DECL)
       QUALIFIED_NAME_IS_TEMPLATE (in SCOPE_REF)
    2: IDENTIFIER_OPNAME_P (in IDENTIFIER_NODE)
@@ -775,6 +774,7 @@ enum cp_tree_index
     CPTI_CLASS_TYPE,
     CPTI_UNKNOWN_TYPE,
     CPTI_INIT_LIST_TYPE,
+    CPTI_DEPENDENT_LAMBDA_RETURN_TYPE,
     CPTI_VTBL_TYPE,
     CPTI_VTBL_PTR_TYPE,
     CPTI_STD,
@@ -846,6 +846,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
 #define class_type_node                        cp_global_trees[CPTI_CLASS_TYPE]
 #define unknown_type_node              cp_global_trees[CPTI_UNKNOWN_TYPE]
 #define init_list_type_node            cp_global_trees[CPTI_INIT_LIST_TYPE]
+#define dependent_lambda_return_type_node cp_global_trees[CPTI_DEPENDENT_LAMBDA_RETURN_TYPE]
 #define vtbl_type_node                 cp_global_trees[CPTI_VTBL_TYPE]
 #define vtbl_ptr_type_node             cp_global_trees[CPTI_VTBL_PTR_TYPE]
 #define std_node                       cp_global_trees[CPTI_STD]
@@ -3425,12 +3426,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
   (DECLTYPE_TYPE_CHECK (NODE))->type_common.string_flag
 
 /* These flags indicate that we want different semantics from normal
-   decltype: lambda capture just drops references, lambda return also does
-   type decay, lambda proxies look through implicit dereference.  */
+   decltype: lambda capture just drops references, lambda proxies look
+   through implicit dereference.  */
 #define DECLTYPE_FOR_LAMBDA_CAPTURE(NODE) \
   TREE_LANG_FLAG_0 (DECLTYPE_TYPE_CHECK (NODE))
-#define DECLTYPE_FOR_LAMBDA_RETURN(NODE) \
-  TREE_LANG_FLAG_1 (DECLTYPE_TYPE_CHECK (NODE))
 #define DECLTYPE_FOR_LAMBDA_PROXY(NODE) \
   TREE_LANG_FLAG_2 (DECLTYPE_TYPE_CHECK (NODE))
 
index c125f05478e97b957c6b3d7239b6792b6017f5ab..c375cf7a78df1794732a0d99b2b122f28cbd4676 100644 (file)
@@ -3597,6 +3597,10 @@ cxx_init_decl_processing (void)
   init_list_type_node = make_node (LANG_TYPE);
   record_unknown_type (init_list_type_node, "init list");
 
+  dependent_lambda_return_type_node = make_node (LANG_TYPE);
+  record_unknown_type (dependent_lambda_return_type_node,
+                      "undeduced lambda return type");
+
   {
     /* Make sure we get a unique function type, so we can give
        its pointer type a name.  (This wins for gdb.) */
index 53d4bc648ae613e324520e545e5da126d463d368..4c7cc79d4e34b892387c4dc370508339f12dfc35 100644 (file)
@@ -1953,7 +1953,7 @@ write_type (tree type)
             case DECLTYPE_TYPE:
              /* These shouldn't make it into mangling.  */
              gcc_assert (!DECLTYPE_FOR_LAMBDA_CAPTURE (type)
-                         && !DECLTYPE_FOR_LAMBDA_RETURN (type));
+                         && !DECLTYPE_FOR_LAMBDA_PROXY (type));
 
              /* In ABI <5, we stripped decltype of a plain decl.  */
              if (!abi_version_at_least (5)
index 3f9a4c042243acfa8b6536100332fc08d34dfa82..6b970f97777c4b6d03bccef92f228bbce9cbf562 100644 (file)
@@ -8887,7 +8887,16 @@ instantiate_class_template_1 (tree type)
     }
 
   if (CLASSTYPE_LAMBDA_EXPR (type))
-    maybe_add_lambda_conv_op (type);
+    {
+      tree lambda = CLASSTYPE_LAMBDA_EXPR (type);
+      if (LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda))
+       {
+         apply_lambda_return_type (lambda, void_type_node);
+         LAMBDA_EXPR_RETURN_TYPE (lambda) = NULL_TREE;
+       }
+      instantiate_decl (lambda_function (type), false, false);
+      maybe_add_lambda_conv_op (type);
+    }
 
   /* Set the file and line number information to whatever is given for
      the class itself.  This puts error messages involving generated
@@ -11420,8 +11429,6 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 
        if (DECLTYPE_FOR_LAMBDA_CAPTURE (t))
          type = lambda_capture_field_type (type);
-       else if (DECLTYPE_FOR_LAMBDA_RETURN (t))
-         type = lambda_return_type (type);
        else if (DECLTYPE_FOR_LAMBDA_PROXY (t))
          type = lambda_proxy_type (type);
        else
@@ -13882,10 +13889,17 @@ tsubst_copy_and_build (tree t,
        LAMBDA_EXPR_MUTABLE_P (r) = LAMBDA_EXPR_MUTABLE_P (t);
        LAMBDA_EXPR_DISCRIMINATOR (r)
          = (LAMBDA_EXPR_DISCRIMINATOR (t));
-       LAMBDA_EXPR_CAPTURE_LIST (r)
-         = RECUR (LAMBDA_EXPR_CAPTURE_LIST (t));
        LAMBDA_EXPR_EXTRA_SCOPE (r)
          = RECUR (LAMBDA_EXPR_EXTRA_SCOPE (t));
+       if (LAMBDA_EXPR_RETURN_TYPE (t) == dependent_lambda_return_type_node)
+         {
+           LAMBDA_EXPR_RETURN_TYPE (r) = dependent_lambda_return_type_node;
+           LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (r) = true;
+         }
+       else
+         LAMBDA_EXPR_RETURN_TYPE (r)
+           = tsubst (LAMBDA_EXPR_RETURN_TYPE (t), args, complain, in_decl);
+
        gcc_assert (LAMBDA_EXPR_THIS_CAPTURE (t) == NULL_TREE
                    && LAMBDA_EXPR_PENDING_PROXIES (t) == NULL);
 
@@ -13895,9 +13909,10 @@ tsubst_copy_and_build (tree t,
           declaration of the op() for later calls to lambda_function.  */
        complete_type (type);
 
-       type = tsubst (LAMBDA_EXPR_RETURN_TYPE (t), args, complain, in_decl);
-       if (type)
-         apply_lambda_return_type (r, type);
+       /* The capture list refers to closure members, so this needs to
+          wait until after we finish instantiating the type.  */
+       LAMBDA_EXPR_CAPTURE_LIST (r)
+         = RECUR (LAMBDA_EXPR_CAPTURE_LIST (t));
 
        return build_lambda_object (r);
       }
index 2f62e351139dba3b4666848969acabb4cb69202f..5deb2ebfbd168381e6fd71ac9572c9cce4ac8f1b 100644 (file)
@@ -8323,18 +8323,14 @@ tree
 lambda_return_type (tree expr)
 {
   tree type;
-  if (BRACE_ENCLOSED_INITIALIZER_P (expr))
+  if (type_unknown_p (expr)
+      || BRACE_ENCLOSED_INITIALIZER_P (expr))
     {
-      warning (0, "cannot deduce lambda return type from a braced-init-list");
+      cxx_incomplete_type_error (expr, TREE_TYPE (expr));
       return void_type_node;
     }
   if (type_dependent_expression_p (expr))
-    {
-      type = cxx_make_type (DECLTYPE_TYPE);
-      DECLTYPE_TYPE_EXPR (type) = expr;
-      DECLTYPE_FOR_LAMBDA_RETURN (type) = true;
-      SET_TYPE_STRUCTURAL_EQUALITY (type);
-    }
+    type = dependent_lambda_return_type_node;
   else
     type = cv_unqualified (type_decays_to (unlowered_expr_type (expr)));
   return type;
@@ -8394,12 +8390,10 @@ apply_lambda_return_type (tree lambda, tree return_type)
 
   LAMBDA_EXPR_RETURN_TYPE (lambda) = return_type;
 
-  /* If we got a DECLTYPE_TYPE, don't stick it in the function yet,
-     it would interfere with instantiating the closure type.  */
-  if (dependent_type_p (return_type))
-    return;
   if (return_type == error_mark_node)
     return;
+  if (TREE_TYPE (TREE_TYPE (fco)) == return_type)
+    return;
 
   /* TREE_TYPE (FUNCTION_DECL) == METHOD_TYPE
      TREE_TYPE (METHOD_TYPE)   == return-type  */
@@ -8412,6 +8406,7 @@ apply_lambda_return_type (tree lambda, tree return_type)
   /* We already have a DECL_RESULT from start_preparsed_function.
      Now we need to redo the work it and allocate_struct_function
      did to reflect the new type.  */
+  gcc_assert (current_function_decl == fco);
   result = build_decl (input_location, RESULT_DECL, NULL_TREE,
                       TYPE_MAIN_VARIANT (return_type));
   DECL_ARTIFICIAL (result) = 1;
index 4c130eee9246c80a6d5ec8ae9dec61be94ee34c7..9db0ce34214fe75ff1325a41a34df7ad7c6a78b4 100644 (file)
@@ -1331,8 +1331,8 @@ structural_comptypes (tree t1, tree t2, int strict)
           != DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t2)
          || (DECLTYPE_FOR_LAMBDA_CAPTURE (t1)
              != DECLTYPE_FOR_LAMBDA_CAPTURE (t2))
-         || (DECLTYPE_FOR_LAMBDA_RETURN (t1)
-             != DECLTYPE_FOR_LAMBDA_RETURN (t2))
+         || (DECLTYPE_FOR_LAMBDA_PROXY (t1)
+             != DECLTYPE_FOR_LAMBDA_PROXY (t2))
           || !cp_tree_equal (DECLTYPE_TYPE_EXPR (t1), 
                              DECLTYPE_TYPE_EXPR (t2)))
         return false;
@@ -7657,15 +7657,14 @@ check_return_expr (tree retval, bool *no_warning)
          tree type = lambda_return_type (retval);
          tree oldtype = LAMBDA_EXPR_RETURN_TYPE (lambda);
 
-         if (VOID_TYPE_P (type))
-           { /* Nothing.  */ }
-         else if (oldtype == NULL_TREE)
-           {
-             pedwarn (input_location, OPT_pedantic, "lambda return type "
-                      "can only be deduced when the return statement is "
-                      "the only statement in the function body");
-             apply_lambda_return_type (lambda, type);
-           }
+         if (oldtype == NULL_TREE)
+           apply_lambda_return_type (lambda, type);
+         /* If one of the answers is type-dependent, we can't do any
+            better until instantiation time.  */
+         else if (oldtype == dependent_lambda_return_type_node)
+           /* Leave it.  */;
+         else if (type == dependent_lambda_return_type_node)
+           apply_lambda_return_type (lambda, type);
          else if (!same_type_p (type, oldtype))
            error ("inconsistent types %qT and %qT deduced for "
                   "lambda return type", type, oldtype);
index fe3688826e134e9515533a9e8c5892b3249ede8c..9dfa4d3eb2939be4f8694afe29b31d3f52297566 100644 (file)
@@ -1,3 +1,11 @@
+2011-08-23  Jason Merrill  <jason@redhat.com>
+
+       Core 975
+       * g++.dg/cpp0x/lambda/lambda-deduce-ext-neg2.C: Now accepted.
+       * g++.dg/cpp0x/lambda/lambda-deduce-ext-neg.C: Adjust.
+       * g++.dg/cpp0x/lambda/lambda-deduce2.C: Test returning overload.
+       * g++.dg/cpp0x/lambda/lambda-deduce-neg.C: Remove #include.
+
 2011-08-23  Jason Merrill  <jason@redhat.com>
 
        PR c++/50024
index bfe7acab69bced42b4947f631c0c658c05cf0bd1..f93e78a27c4e802debdf9c35a9398a7bf47d8c4d 100644 (file)
@@ -1,24 +1,22 @@
-// Testcase for an extension to allow return type deduction when the lambda
-// contains more than just a single return-statement.
+// Testcase for DR 975.
 
 // { dg-options -std=c++0x }
 
 bool b;
-template <class T>
-T f (T t)
-{
-  return [=]
-    {
-      auto i = t+1;
-      if (b)
-       return i+1;
-      else
-       return i+2;             // { dg-error "lambda return type" }
-    }();
+struct A { int fn1(); const int& fn2(); };
+struct B { int fn1(); long fn2(); };
+
+template <class T> int f (T t) {
+  return [](T t){
+    if (b)
+      return t.fn1();
+    else
+      return t.fn2();          // { dg-error "inconsistent types" }
+  }(t);
 }
 
 int main()
 {
-  if (f(1) != 3)
-    return 1;
+  f(A());                      // { dg-bogus "" } int and const int& are compatible
+  f(B());                      // { dg-message "from here" } int and long are not
 }
index a236e6d116e282ac5773151e1d85992d2c09bbf6..5c63409b6815e4b9b0bdfb453bf271a0e9a9b4e9 100644 (file)
@@ -1,6 +1,5 @@
-// Test that in pedantic mode, we warn about the extension to allow return
-// type deduction when the lambda contains more than just a single
-// return-statement.
+// Test that this is accepted even when pedantic now that it's part
+// of the standard.
 
 // { dg-options "-std=c++0x -pedantic" }
 
@@ -11,7 +10,7 @@ T f (T t)
   [=] { return t+1; };         // OK
   return [=] {
     auto i = t+1;
-    return i+1;                        // { dg-warning "only statement" }
+    return i+1;
   }();
 }
 
index 4abdf59a6926fe117c6f867005c45e701e709f8f..c932c09db3c29e20537eea188e0c0792d7cf9828 100644 (file)
@@ -1,5 +1,4 @@
 // { dg-options "-std=c++0x" }
-#include <cassert>
 
 int main() {
   int i = 0;
index 718d49cd9bcb44139d3e37b22dc457da5f640c41..eeb9814a05439249171ff33b4cb14adf25a68edd 100644 (file)
@@ -1,7 +1,11 @@
 // PR c++/43875
 // { dg-options "-std=c++0x" }
 
+void f();
+void f(int);
+
 int main()
 {
-   auto x2 = []{ return { 1, 2 }; }; // { dg-message "return" }
+  auto x1 = []{ return f; };       // { dg-error "return|overloaded" }
+  auto x2 = []{ return { 1, 2 }; }; // { dg-error "return|list" }
 }