diff mbox

[RFC,/] PR 51494

Message ID 4EF299C0.4070004@oracle.com
State New
Headers show

Commit Message

Paolo Carlini Dec. 22, 2011, 2:45 a.m. UTC
Hi,

the issue is that we are rejecting:

struct A
{
     static void f() {}

     void foo()
     {
         [] () { f(); };
     }
};


because 'this' is not captured, but we are wrong because f is static.

The problem happens in maybe_dummy_object (called from finish_call_expr) 
because it cannot know that a function is static, thus proceeds 
unconditionally to call lambda_expr_this_capture.

That said, I'm trying to actually fix the issue it by passing an 
additional tree argument to maybe_dummy_object, which is the function 
for the case at issue, otherwise NULL_TREE. Then 
lambda_expr_this_capture etc is involved only if 
non_static_member_function_p. Appears to work, passes testing, should be 
in general rather safe. Looks like a sane approach?

Thanks,
Paolo.

///////////////////
diff mbox

Patch

Index: typeck.c
===================================================================
--- typeck.c	(revision 182605)
+++ typeck.c	(working copy)
@@ -6078,7 +6078,8 @@  convert_member_func_to_ptr (tree type, tree expr)
     expr = build_address (PTRMEM_CST_MEMBER (expr));
   else
     {
-      decl = maybe_dummy_object (TYPE_PTRMEM_CLASS_TYPE (intype), 0);
+      decl = maybe_dummy_object (TYPE_PTRMEM_CLASS_TYPE (intype), 0,
+				 NULL_TREE);
       decl = build_address (decl);
       expr = get_member_function_from_ptrfunc (&decl, expr);
     }
Index: init.c
===================================================================
--- init.c	(revision 182605)
+++ init.c	(working copy)
@@ -1847,7 +1847,7 @@  build_offset_ref (tree type, tree member, bool add
     }
 
   /* Set up BASEBINFO for member lookup.  */
-  decl = maybe_dummy_object (type, &basebinfo);
+  decl = maybe_dummy_object (type, &basebinfo, NULL_TREE);
 
   /* A lot of this logic is now handled in lookup_member.  */
   if (BASELINK_P (member))
Index: tree.c
===================================================================
--- tree.c	(revision 182605)
+++ tree.c	(working copy)
@@ -2521,7 +2521,7 @@  build_dummy_object (tree type)
    binfo path from current_class_type to TYPE, or 0.  */
 
 tree
-maybe_dummy_object (tree type, tree* binfop)
+maybe_dummy_object (tree type, tree* binfop, tree fn)
 {
   tree decl, context;
   tree binfo;
@@ -2548,7 +2548,8 @@  tree
 	  (TREE_TYPE (current_class_ref), context)))
     decl = current_class_ref;
   else if (current != current_class_type
-	   && context == nonlambda_method_basetype ())
+	   && context == nonlambda_method_basetype ()
+	   && (!fn || non_static_member_function_p (fn)))
     /* In a lambda, need to go through 'this' capture.  */
     decl = (build_x_indirect_ref
 	    ((lambda_expr_this_capture
Index: semantics.c
===================================================================
--- semantics.c	(revision 182605)
+++ semantics.c	(working copy)
@@ -1530,7 +1530,7 @@  finish_non_static_data_member (tree decl, tree obj
       tree scope = qualifying_scope;
       if (scope == NULL_TREE)
 	scope = context_for_name_lookup (decl);
-      object = maybe_dummy_object (scope, NULL);
+      object = maybe_dummy_object (scope, NULL, NULL_TREE);
     }
 
   if (object == error_mark_node)
@@ -1772,7 +1772,7 @@  finish_qualified_id_expr (tree qualifying_class,
       /* See if any of the functions are non-static members.  */
       /* If so, the expression may be relative to 'this'.  */
       if (!shared_member_p (expr)
-	  && (ob = maybe_dummy_object (qualifying_class, NULL),
+	  && (ob = maybe_dummy_object (qualifying_class, NULL, NULL_TREE),
 	      !is_dummy_object (ob)))
 	expr = (build_class_member_access_expr
 		(ob,
@@ -2124,7 +2124,7 @@  finish_call_expr (tree fn, VEC(tree,gc) **args, bo
 	part of the access, so we pass 'B' to maybe_dummy_object.  */
 
       object = maybe_dummy_object (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)),
-				   NULL);
+				   NULL, fn);
 
       if (processing_template_decl)
 	{
@@ -3321,7 +3321,7 @@  finish_id_expression (tree id_expression,
 	      && !shared_member_p (decl))
 	    {
 	      /* A set of member functions.  */
-	      decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0);
+	      decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0, NULL_TREE);
 	      return finish_class_member_access_expr (decl, id_expression,
 						      /*template_p=*/false,
 						      tf_warning_or_error);
Index: cp-tree.h
===================================================================
--- cp-tree.h	(revision 182605)
+++ cp-tree.h	(working copy)
@@ -5697,7 +5697,7 @@  extern bool cp_tree_equal			(tree, tree);
 extern tree no_linkage_check			(tree, bool);
 extern void debug_binfo				(tree);
 extern tree build_dummy_object			(tree);
-extern tree maybe_dummy_object			(tree, tree *);
+extern tree maybe_dummy_object			(tree, tree *, tree);
 extern int is_dummy_object			(const_tree);
 extern const struct attribute_spec cxx_attribute_table[];
 extern tree make_ptrmem_cst			(tree, tree);