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

login
register
mail settings
Submitter Jason Merrill
Date Jan. 31, 2014, 3:46 a.m.
Message ID <52EB1CB3.9040601@redhat.com>
Download mbox | patch
Permalink /patch/315505/
State New
Headers show

Comments

Jason Merrill - Jan. 31, 2014, 3:46 a.m.
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).

Patch

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);
+}