Patchwork [C++] PR 51494 (and 52183)

login
register
mail settings
Submitter Paolo Carlini
Date Feb. 9, 2012, 1:21 p.m.
Message ID <4F33C854.6080004@oracle.com>
Download mbox | patch
Permalink /patch/140377/
State New
Headers show

Comments

Paolo Carlini - Feb. 9, 2012, 1:21 p.m.
Hi,

a related/duplicate issue went into Bugzilla today, thus I decided to 
return to the RFC/Patch which I posted back in December 
(http://gcc.gnu.org/ml/gcc-patches/2011-12/msg01593.html): as far as I 
can see my analysis still stands and, to be clear, I'm proposing this 
kind of patch for post-4.7.0, at this point. The below, compared to the 
old draft proposal is a bit tidier, but should still do the right thing, 
it fixes the new more involved testcase too.

Tested x86_64-linux.

Thanks,
Paolo.

////////////////////
/cp
2012-02-09  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/51494
	PR c++/52183
	* tree.c (maybe_dummy_object): Add a bool parameter.
	* cp-tree.h (maybe_dummy_object): Update.
	* semantics.c (finish_call_expr): Adjust call, pass
	non_static_member_function_p (fn) as boolean argument.
	(finish_non_static_data_member, finish_qualified_id_expr,
	finish_id_expression): Adjust calls.
	* typeck.c (convert_member_func_to_ptr): Likewise.
	* init.c (build_offset_ref): Likewise.

/testsuite
2012-02-09  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/51494
	PR c++/52183
	* g++.dg/cpp0x/lambda/lambda-51494.C: New.
Jason Merrill - Feb. 14, 2012, 12:56 a.m.
This patch fixes this particular bug, but there are some issues.

First, non_static_member_function_p only checks the first function in 
the overload set, which may not be representative of all of them.  It 
really shouldn't look through OVERLOADs, we need to defer this decision 
until build_over_call.

Second, the uses of maybe_dummy_object in build_offset_ref, 
finish_qualified_id_expr and finish_id_expression could also be dealing 
with static member functions.

The underlying problem here is that we're only supposed to capture a 
variable/this when it is odr-used, which we can't know until we finish 
overload resolution.

Jason
Paolo Carlini - Feb. 14, 2012, 11 a.m.
Hi,
> This patch fixes this particular bug, but there are some issues.
>
> First, non_static_member_function_p only checks the first function in 
> the overload set, which may not be representative of all of them.  It 
> really shouldn't look through OVERLOADs, we need to defer this 
> decision until build_over_call.
>
> Second, the uses of maybe_dummy_object in build_offset_ref, 
> finish_qualified_id_expr and finish_id_expression could also be 
> dealing with static member functions.
>
> The underlying problem here is that we're only supposed to capture a 
> variable/this when it is odr-used, which we can't know until we finish 
> overload resolution.
Ah, thanks for your explanations, let's see if I can make some progress. 
Or maybe Dodji can kick in?

Thanks,
Paolo.

Patch

Index: testsuite/g++.dg/cpp0x/lambda/lambda-51494.C
===================================================================
--- testsuite/g++.dg/cpp0x/lambda/lambda-51494.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/lambda/lambda-51494.C	(revision 0)
@@ -0,0 +1,12 @@ 
+// PR c++/51494
+// { dg-options -std=c++0x }
+
+struct A
+{
+  static void f() {}
+
+  void foo()
+  {
+    [] () { f(); };
+  }
+};
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 184041)
+++ cp/typeck.c	(working copy)
@@ -6112,7 +6112,7 @@  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, true);
       decl = build_address (decl);
       expr = get_member_function_from_ptrfunc (&decl, expr);
     }
Index: cp/init.c
===================================================================
--- cp/init.c	(revision 184041)
+++ cp/init.c	(working copy)
@@ -1,7 +1,7 @@ 
 /* Handle initialization things in C++.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
    1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-   2011 Free Software Foundation, Inc.
+   2011, 2012 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -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, true);
 
   /* A lot of this logic is now handled in lookup_member.  */
   if (BASELINK_P (member))
Index: cp/tree.c
===================================================================
--- cp/tree.c	(revision 184041)
+++ cp/tree.c	(working copy)
@@ -1,6 +1,7 @@ 
 /* Language-dependent node constructors for parse phase of GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011,
+   2012
    Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
@@ -2553,10 +2554,11 @@  build_dummy_object (tree type)
 
 /* We've gotten a reference to a member of TYPE.  Return *this if appropriate,
    or a dummy object otherwise.  If BINFOP is non-0, it is filled with the
-   binfo path from current_class_type to TYPE, or 0.  */
+   binfo path from current_class_type to TYPE, or 0.  If MAYBE_CAPTURE_THIS
+   is false, in a lambda we don't want to capture 'this'.  */
 
 tree
-maybe_dummy_object (tree type, tree* binfop)
+maybe_dummy_object (tree type, tree* binfop, bool maybe_capture_this)
 {
   tree decl, context;
   tree binfo;
@@ -2583,7 +2585,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 ()
+	   && maybe_capture_this)
     /* In a lambda, need to go through 'this' capture.  */
     decl = (build_x_indirect_ref
 	    ((lambda_expr_this_capture
Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 184041)
+++ cp/semantics.c	(working copy)
@@ -1538,7 +1538,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, true);
     }
 
   if (object == error_mark_node)
@@ -1780,7 +1780,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, true),
 	      !is_dummy_object (ob)))
 	expr = (build_class_member_access_expr
 		(ob,
@@ -2132,7 +2132,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, non_static_member_function_p (fn));
 
       if (processing_template_decl)
 	{
@@ -3312,7 +3312,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, true);
 	      return finish_class_member_access_expr (decl, id_expression,
 						      /*template_p=*/false,
 						      tf_warning_or_error);
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 184041)
+++ cp/cp-tree.h	(working copy)
@@ -1,6 +1,7 @@ 
 /* Definitions for C++ parsing and type checking.
    Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
+   2012
    Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
@@ -5704,7 +5705,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 *, bool);
 extern int is_dummy_object			(const_tree);
 extern const struct attribute_spec cxx_attribute_table[];
 extern tree make_ptrmem_cst			(tree, tree);