diff options
author | Jason Merrill <jason@redhat.com> | 2011-08-23 12:03:15 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-08-23 12:03:15 -0400 |
commit | 9b8662c2b04820f6024648ff863b83dbbf07844f (patch) | |
tree | 095408f307618afaaf5d92253bb0546486159200 | |
parent | 2787914706395bf7864bdc76491ada1b0a552cae (diff) | |
download | gcc-9b8662c2b04820f6024648ff863b83dbbf07844f.zip gcc-9b8662c2b04820f6024648ff863b83dbbf07844f.tar.gz gcc-9b8662c2b04820f6024648ff863b83dbbf07844f.tar.bz2 |
Core 975
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
-rw-r--r-- | gcc/cp/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 9 | ||||
-rw-r--r-- | gcc/cp/decl.c | 4 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 2 | ||||
-rw-r--r-- | gcc/cp/pt.c | 31 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 19 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 21 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg.C | 28 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg2.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-neg.C | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce2.C | 6 |
12 files changed, 97 insertions, 58 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0f60bcb..0f325a8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,24 @@ 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 * semantics.c (maybe_constant_value): Don't try to fold { }. * pt.c (build_non_dependent_expr): Don't wrap { }. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ff5509e..8595943 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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)) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c125f05..c375cf7 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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.) */ diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 53d4bc6..4c7cc79 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -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) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3f9a4c0..6b970f9 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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); } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 2f62e35..5deb2eb 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 4c130ee..9db0ce3 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fe36888..9dfa4d3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,13 @@ 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 * g++.dg/cpp0x/constexpr-initlist5.C: New. diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg.C index bfe7aca..f93e78a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg.C @@ -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 } diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg2.C index a236e6d..5c63409 100644 --- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg2.C +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg2.C @@ -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; }(); } diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-neg.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-neg.C index 4abdf59..c932c09 100644 --- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce-neg.C @@ -1,5 +1,4 @@ // { dg-options "-std=c++0x" } -#include <cassert> int main() { int i = 0; diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce2.C index 718d49c..eeb9814 100644 --- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce2.C +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-deduce2.C @@ -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" } } |