From: Jason Merrill Date: Wed, 29 Jun 2011 17:15:06 +0000 (-0400) Subject: re PR c++/49554 ([C++0x] lambda capture causes "cannot call member function ... witho... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=40d55020a382cc1836911b9702f6880b49c1d955;p=gcc.git re PR c++/49554 ([C++0x] lambda capture causes "cannot call member function ... without object") PR c++/49554 * semantics.c (lambda_proxy_type): New. (build_capture_proxy): Use it. * cp-tree.h (DECLTYPE_FOR_LAMBDA_PROXY): New. * pt.c (tsubst) [DECLTYPE_TYPE]: Use them. From-SVN: r175657 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index db0478a6285..083d5459662 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2011-06-29 Jason Merrill + PR c++/49554 + * semantics.c (lambda_proxy_type): New. + (build_capture_proxy): Use it. + * cp-tree.h (DECLTYPE_FOR_LAMBDA_PROXY): New. + * pt.c (tsubst) [DECLTYPE_TYPE]: Use them. + PR c++/45923 * class.c (explain_non_literal_class): New. (finalize_literal_type_property): Call it. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 7244cc88d4a..55c88e38482 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3418,11 +3418,13 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) /* These flags indicate that we want different semantics from normal decltype: lambda capture just drops references, lambda return also does - type decay. */ + type decay, 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)) /* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was specified in its declaration. This can also be set for an @@ -5455,6 +5457,7 @@ extern tree build_lambda_object (tree); extern tree begin_lambda_type (tree); extern tree lambda_capture_field_type (tree); extern tree lambda_return_type (tree); +extern tree lambda_proxy_type (tree); extern tree lambda_function (tree); extern void apply_lambda_return_type (tree, tree); extern tree add_capture (tree, tree, tree, bool, bool); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b3dd85f04a7..d1d8336b1bd 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -11108,6 +11108,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) 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 type = finish_decltype_type (type, DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t), complain); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 458172980b4..fb984d4799a 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -8489,6 +8489,27 @@ insert_pending_capture_proxies (void) LAMBDA_EXPR_PENDING_PROXIES (lam) = NULL; } +/* Given REF, a COMPONENT_REF designating a field in the lambda closure, + return the type we want the proxy to have: the type of the field itself, + with added const-qualification if the lambda isn't mutable and the + capture is by value. */ + +tree +lambda_proxy_type (tree ref) +{ + tree type; + if (REFERENCE_REF_P (ref)) + ref = TREE_OPERAND (ref, 0); + type = TREE_TYPE (ref); + if (!dependent_type_p (type)) + return type; + type = cxx_make_type (DECLTYPE_TYPE); + DECLTYPE_TYPE_EXPR (type) = ref; + DECLTYPE_FOR_LAMBDA_PROXY (type) = true; + SET_TYPE_STRUCTURAL_EQUALITY (type); + return type; +} + /* MEMBER is a capture field in a lambda closure class. Now that we're inside the operator(), build a placeholder var for future lookups and debugging. */ @@ -8496,7 +8517,7 @@ insert_pending_capture_proxies (void) tree build_capture_proxy (tree member) { - tree var, object, fn, closure, name, lam; + tree var, object, fn, closure, name, lam, type; closure = DECL_CONTEXT (member); fn = lambda_function (closure); @@ -8511,7 +8532,8 @@ build_capture_proxy (tree member) /* Remove the __ inserted by add_capture. */ name = get_identifier (IDENTIFIER_POINTER (DECL_NAME (member)) + 2); - var = build_decl (input_location, VAR_DECL, name, TREE_TYPE (object)); + type = lambda_proxy_type (object); + var = build_decl (input_location, VAR_DECL, name, type); SET_DECL_VALUE_EXPR (var, object); DECL_HAS_VALUE_EXPR_P (var) = 1; DECL_ARTIFICIAL (var) = 1; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d30d8b053c2..522c41cac6b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,7 @@ 2011-06-29 Jason Merrill + * g++.dg/cpp0x/lambda/lambda-template3.C: New. + PR c++/45923 * g++.dg/cpp0x/constexpr-diag3.C: New. * g++.dg/cpp0x/constexpr-diag1.C: Adjust error message. diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template3.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template3.C new file mode 100644 index 00000000000..fd6f1d3192f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template3.C @@ -0,0 +1,33 @@ +// PR c++/49554 +// { dg-options -std=c++0x } + +template + struct base + { + struct iterator { }; + + iterator begin(); + }; + +template +class flist : public base +{ + typedef base Base; + + typedef typename Base::iterator Base_iterator; +public: + + void + resize() + { + Base_iterator b = Base::begin(); + + [b](int i) { return i; }; + } +}; + +void test01() +{ + flist fl; + fl.resize(); +}