Commit a6846853 by Jason Merrill Committed by Jason Merrill

re PR c++/43856 ([C++0x] gcc-4.5.0 fails to transform id-expression into class…

re PR c++/43856 ([C++0x] gcc-4.5.0 fails to transform id-expression into class member access in lambda compound-statement)

	PR c++/43856
	* name-lookup.c (qualify_lookup): Disqualify lambda op().
	* class.c (current_nonlambda_class_type): New fn.
	* semantics.c (nonlambda_method_basetype): New.
	* cp-tree.h: Declare them.
	* tree.c (maybe_dummy_object): Handle implicit 'this' capture.

From-SVN: r158807
parent 16de17ae
2010-04-27 Jason Merrill <jason@redhat.com> 2010-04-27 Jason Merrill <jason@redhat.com>
PR c++/43856
* name-lookup.c (qualify_lookup): Disqualify lambda op().
* class.c (current_nonlambda_class_type): New fn.
* semantics.c (nonlambda_method_basetype): New.
* cp-tree.h: Declare them.
* tree.c (maybe_dummy_object): Handle implicit 'this' capture.
* semantics.c (baselink_for_fns): Correct BASELINK_BINFO. * semantics.c (baselink_for_fns): Correct BASELINK_BINFO.
PR c++/43875 PR c++/43875
......
...@@ -5971,6 +5971,34 @@ currently_open_derived_class (tree t) ...@@ -5971,6 +5971,34 @@ currently_open_derived_class (tree t)
return NULL_TREE; return NULL_TREE;
} }
/* Returns the innermost class type which is not a lambda closure type. */
tree
current_nonlambda_class_type (void)
{
int i;
/* We start looking from 1 because entry 0 is from global scope,
and has no type. */
for (i = current_class_depth; i > 0; --i)
{
tree c;
if (i == current_class_depth)
c = current_class_type;
else
{
if (current_class_stack[i].hidden)
break;
c = current_class_stack[i].type;
}
if (!c)
continue;
if (!LAMBDA_TYPE_P (c))
return c;
}
return NULL_TREE;
}
/* When entering a class scope, all enclosing class scopes' names with /* When entering a class scope, all enclosing class scopes' names with
static meaning (static variables, static functions, types and static meaning (static variables, static functions, types and
enumerators) have to be visible. This recursive function calls enumerators) have to be visible. This recursive function calls
......
...@@ -4580,6 +4580,7 @@ extern void resort_type_method_vec (void *, void *, ...@@ -4580,6 +4580,7 @@ extern void resort_type_method_vec (void *, void *,
extern bool add_method (tree, tree, tree); extern bool add_method (tree, tree, tree);
extern bool currently_open_class (tree); extern bool currently_open_class (tree);
extern tree currently_open_derived_class (tree); extern tree currently_open_derived_class (tree);
extern tree current_nonlambda_class_type (void);
extern tree finish_struct (tree, tree); extern tree finish_struct (tree, tree);
extern void finish_struct_1 (tree); extern void finish_struct_1 (tree);
extern int resolves_to_fixed_type_p (tree, int *); extern int resolves_to_fixed_type_p (tree, int *);
...@@ -5212,6 +5213,7 @@ extern tree add_capture (tree, tree, tree, bool, bool); ...@@ -5212,6 +5213,7 @@ extern tree add_capture (tree, tree, tree, bool, bool);
extern tree add_default_capture (tree, tree, tree); extern tree add_default_capture (tree, tree, tree);
extern void register_capture_members (tree); extern void register_capture_members (tree);
extern tree lambda_expr_this_capture (tree); extern tree lambda_expr_this_capture (tree);
extern tree nonlambda_method_basetype (void);
extern void maybe_add_lambda_conv_op (tree); extern void maybe_add_lambda_conv_op (tree);
/* in tree.c */ /* in tree.c */
......
...@@ -3807,6 +3807,10 @@ qualify_lookup (tree val, int flags) ...@@ -3807,6 +3807,10 @@ qualify_lookup (tree val, int flags)
if (cp_unevaluated_operand && TREE_CODE (val) == FIELD_DECL if (cp_unevaluated_operand && TREE_CODE (val) == FIELD_DECL
&& DECL_NORMAL_CAPTURE_P (val)) && DECL_NORMAL_CAPTURE_P (val))
return false; return false;
/* None of the lookups that use qualify_lookup want the op() from the
lambda; they want the one from the enclosing class. */
if (TREE_CODE (val) == FUNCTION_DECL && LAMBDA_FUNCTION_P (val))
return false;
return true; return true;
} }
......
...@@ -5869,6 +5869,32 @@ lambda_expr_this_capture (tree lambda) ...@@ -5869,6 +5869,32 @@ lambda_expr_this_capture (tree lambda)
return result; return result;
} }
/* Returns the method basetype of the innermost non-lambda function, or
NULL_TREE if none. */
tree
nonlambda_method_basetype (void)
{
tree fn, type;
if (!current_class_ref)
return NULL_TREE;
type = current_class_type;
if (!LAMBDA_TYPE_P (type))
return type;
/* Find the nearest enclosing non-lambda function. */
fn = TYPE_NAME (type);
do
fn = decl_function_context (fn);
while (fn && LAMBDA_FUNCTION_P (fn));
if (!fn || !DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
return NULL_TREE;
return TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
}
/* If the closure TYPE has a static op(), also add a conversion to function /* If the closure TYPE has a static op(), also add a conversion to function
pointer. */ pointer. */
......
...@@ -2293,11 +2293,11 @@ maybe_dummy_object (tree type, tree* binfop) ...@@ -2293,11 +2293,11 @@ maybe_dummy_object (tree type, tree* binfop)
{ {
tree decl, context; tree decl, context;
tree binfo; tree binfo;
tree current = current_nonlambda_class_type ();
if (current_class_type if (current
&& (binfo = lookup_base (current_class_type, type, && (binfo = lookup_base (current, type, ba_any, NULL)))
ba_unique | ba_quiet, NULL))) context = current;
context = current_class_type;
else else
{ {
/* Reference from a nested class member function. */ /* Reference from a nested class member function. */
...@@ -2315,6 +2315,13 @@ maybe_dummy_object (tree type, tree* binfop) ...@@ -2315,6 +2315,13 @@ maybe_dummy_object (tree type, tree* binfop)
&& same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)), && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)),
current_class_type)) current_class_type))
decl = current_class_ref; decl = current_class_ref;
else if (current != current_class_type
&& context == nonlambda_method_basetype ())
/* In a lambda, need to go through 'this' capture. */
decl = (cp_build_indirect_ref
((lambda_expr_this_capture
(CLASSTYPE_LAMBDA_EXPR (current_class_type))),
RO_NULL, tf_warning_or_error));
else else
decl = build_dummy_object (context); decl = build_dummy_object (context);
......
2010-04-27 Jason Merrill <jason@redhat.com> 2010-04-27 Jason Merrill <jason@redhat.com>
PR c++/43856
* g++.dg/cpp0x/lambda/lambda-this2.C: New.
PR c++/43875 PR c++/43875
* g++.dg/cpp0x/lambda/lambda-deduce2.C: New. * g++.dg/cpp0x/lambda/lambda-deduce2.C: New.
......
// PR c++/43856
// Test for implicit 'this' capture via rewriting.
// { dg-options "-std=c++0x" }
struct S1 {
int operator()(int);
int i;
void g();
void f() {
[=]() {
i;
g();
operator()(42);
};
}
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment