aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-08-23 12:03:15 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-08-23 12:03:15 -0400
commit9b8662c2b04820f6024648ff863b83dbbf07844f (patch)
tree095408f307618afaaf5d92253bb0546486159200 /gcc/cp
parent2787914706395bf7864bdc76491ada1b0a552cae (diff)
downloadgcc-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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog19
-rw-r--r--gcc/cp/cp-tree.h9
-rw-r--r--gcc/cp/decl.c4
-rw-r--r--gcc/cp/mangle.c2
-rw-r--r--gcc/cp/pt.c31
-rw-r--r--gcc/cp/semantics.c19
-rw-r--r--gcc/cp/typeck.c21
7 files changed, 68 insertions, 37 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);