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
This commit is contained in:
parent
2787914706
commit
9b8662c2b0
@ -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
|
||||
|
@ -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))
|
||||
|
||||
|
@ -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.) */
|
||||
|
@ -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)
|
||||
|
31
gcc/cp/pt.c
31
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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
}();
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
// { dg-options "-std=c++0x" }
|
||||
#include <cassert>
|
||||
|
||||
int main() {
|
||||
int i = 0;
|
||||
|
@ -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" }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user