This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFA (pointer-set): PATCH for c++/57899 (infinite recursion with std::bind)


On 01/30/2014 04:00 PM, Jason Merrill wrote:
Also, in the past we've had issues with nested functions in templates
being able to refer to static/const variables from the enclosing
context; we've dealt with that by forcing repeated lookup, but it would
be better to keep the local_specializations from the enclosing function
around so we can find them the usual way.  To that end, I've added a
pointer_map_copy.

It occurs to me that I don't really need to do this to fix the bug, and perhaps this sort of change should wait for stage 1. So I'm checking in this subset of the patch.

The second patch is the version I'm applying to 4.8, which has more limited effect (and works with 4.8, which the trunk patch does not).


commit 4b96fc3d027078734055395f70b6ca81c2b661c6
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Jan 30 13:13:55 2014 -0500

    	PR c++/57899
    	* cp-tree.h (struct saved_scope): Add x_local_specializations.
    	(local_specializations): New macro.
    	* pt.c (local_specializations): Remove variable.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7f46499..7681b27 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1049,6 +1049,8 @@ struct GTY(()) saved_scope {
   cp_binding_level *class_bindings;
   cp_binding_level *bindings;
 
+  struct pointer_map_t *x_local_specializations;
+
   struct saved_scope *prev;
 };
 
@@ -1098,6 +1100,12 @@ struct GTY(()) saved_scope {
 
 #define previous_class_level scope_chain->x_previous_class_level
 
+/* A map from local variable declarations in the body of the template
+   presently being instantiated to the corresponding instantiated
+   local variables.  */
+
+#define local_specializations scope_chain->x_local_specializations
+
 /* A list of private types mentioned, for deferred access checking.  */
 
 extern GTY(()) struct saved_scope *scope_chain;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 4a5b6cc..981e2e0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -78,11 +78,6 @@ static GTY(()) tree saved_access_scope;
    to the EXPR_STMT that is its result.  */
 static tree cur_stmt_expr;
 
-/* A map from local variable declarations in the body of the template
-   presently being instantiated to the corresponding instantiated
-   local variables.  */
-static struct pointer_map_t *local_specializations;
-
 /* True if we've recursed into fn_type_unification too many times.  */
 static bool excessive_deduction_depth;
 
diff --git a/libstdc++-v3/testsuite/20_util/bind/57899.cc b/libstdc++-v3/testsuite/20_util/bind/57899.cc
new file mode 100644
index 0000000..d46d53e
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bind/57899.cc
@@ -0,0 +1,48 @@
+// Copyright (C) 2010-2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 20.7.11 Function template bind
+
+// PR c++/57899
+// { dg-do compile }
+// { dg-options -std=c++11 }
+
+#include <functional>
+using std::bind;
+using std::placeholders::_1;
+
+struct S { int i; };
+
+struct P { S s; };
+
+struct get_s
+{
+  const S& operator()(const P& p) const { return p.s; }
+} gs;
+
+int gi(const S& s) { return s.i; }
+
+bool cmp(int, int) { return true; }
+
+int main()
+{
+  P p{};
+  auto f1 = bind(gs, _1);
+  auto f2 = bind(gi, f1);
+  auto f3 = bind(cmp, f2, 5);
+  f3(p);
+}
commit 1ef391f60fd02b7698cb8adaa606c4c9d37d245d
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Jan 30 13:13:55 2014 -0500

    	PR c++/57899
    	* pt.c (instantiate_template_1): Save/restore local_specializations.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e47c2a4..f07b935 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -14784,6 +14784,8 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
   /* Instantiation of the function happens in the context of the function
      template, not the context of the overload resolution we're doing.  */
   push_to_top_level ();
+  struct pointer_map_t *saved_local_specializations = local_specializations;
+  local_specializations = NULL;
   /* If there are dependent arguments, e.g. because we're doing partial
      ordering, make sure processing_template_decl stays set.  */
   if (uses_template_parms (targ_ptr))
@@ -14799,6 +14801,7 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
 		   targ_ptr, complain, gen_tmpl);
   if (DECL_CLASS_SCOPE_P (gen_tmpl))
     pop_nested_class ();
+  local_specializations = saved_local_specializations;
   pop_from_top_level ();
 
   if (fndecl == error_mark_node)
diff --git a/libstdc++-v3/testsuite/20_util/bind/57899.cc b/libstdc++-v3/testsuite/20_util/bind/57899.cc
new file mode 100644
index 0000000..d46d53e
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/bind/57899.cc
@@ -0,0 +1,48 @@
+// Copyright (C) 2010-2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 20.7.11 Function template bind
+
+// PR c++/57899
+// { dg-do compile }
+// { dg-options -std=c++11 }
+
+#include <functional>
+using std::bind;
+using std::placeholders::_1;
+
+struct S { int i; };
+
+struct P { S s; };
+
+struct get_s
+{
+  const S& operator()(const P& p) const { return p.s; }
+} gs;
+
+int gi(const S& s) { return s.i; }
+
+bool cmp(int, int) { return true; }
+
+int main()
+{
+  P p{};
+  auto f1 = bind(gs, _1);
+  auto f2 = bind(gi, f1);
+  auto f3 = bind(cmp, f2, 5);
+  f3(p);
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]