public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PR69315] enable finish_function to recurse for constexpr functions
@ 2016-01-26 17:12 Alexandre Oliva
  2016-02-10 21:22 ` Alexandre Oliva
  2016-03-22 21:36 ` Jason Merrill
  0 siblings, 2 replies; 7+ messages in thread
From: Alexandre Oliva @ 2016-01-26 17:12 UTC (permalink / raw)
  To: gcc-patches

We don't want finish_function to be called recursively from mark_used.
However, it's desirable and necessary to call itself recursively when
performing delayed folding, because that may have to instantiate and
evaluate constexpr template functions.

So, arrange for finish_function to accept being called recursively
during delayed folding, save and restore the controlling variables,
and process the deferred mark_used calls only when the outermost call
completes.

Regstrapped on x86_64-linux-gnu and i686-linux-gnu.  Ok to install?

for  gcc/cp/ChangeLog

	PR c++/69315
	* decl.c (is_folding_function): New variable.
	(finish_function): Test, save and set it.

for  gcc/testsuite/ChangeLog

	PR c++/69315
	* g++.dg/pr69315.C: New.
---
 gcc/cp/decl.c                  |   31 +++++++++++++++++++++++++------
 gcc/testsuite/g++.dg/pr69315.C |   34 ++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/pr69315.C

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index f4604b6..65eff2f 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -227,10 +227,14 @@ struct GTY((for_user)) named_label_entry {
    function, two inside the body of a function in a local class, etc.)  */
 int function_depth;
 
-/* To avoid unwanted recursion, finish_function defers all mark_used calls
-   encountered during its execution until it finishes.  */
+/* To avoid unwanted recursion, finish_function defers all mark_used
+   calls encountered during its execution until it finishes.
+   finish_function refuses to be called recursively, unless the
+   recursion occurs during folding, which often requires instantiating
+   and evaluating template functions.  */
 bool defer_mark_used_calls;
 vec<tree, va_gc> *deferred_mark_used_calls;
+static bool is_folding_function;
 
 /* States indicating how grokdeclarator() should handle declspecs marked
    with __attribute__((deprecated)).  An object declared as
@@ -14528,8 +14532,11 @@ finish_function (int flags)
   if (c_dialect_objc ())
     objc_finish_function ();
 
-  gcc_assert (!defer_mark_used_calls);
+  gcc_assert (!defer_mark_used_calls
+	      || (is_folding_function && DECL_DECLARED_CONSTEXPR_P (fndecl)));
   defer_mark_used_calls = true;
+  bool save_folding_function = is_folding_function;
+  is_folding_function = false;
 
   record_key_method_defined (fndecl);
 
@@ -14636,7 +14643,14 @@ finish_function (int flags)
 
   /* Perform delayed folding before NRV transformation.  */
   if (!processing_template_decl)
-    cp_fold_function (fndecl);
+    {
+      is_folding_function = true;
+      cp_fold_function (fndecl);
+      /* Check that our controlling variables were restored to the
+	 expect state.  */
+      gcc_assert (is_folding_function && defer_mark_used_calls);
+      is_folding_function = false;
+    }
 
   /* Set up the named return value optimization, if we can.  Candidate
      variables are selected in check_return_expr.  */
@@ -14780,8 +14794,13 @@ finish_function (int flags)
   /* Clean up.  */
   current_function_decl = NULL_TREE;
 
-  defer_mark_used_calls = false;
-  if (deferred_mark_used_calls)
+  is_folding_function = save_folding_function;
+  /* Iff we were called recursively for a constexpr function,
+     is_folding_function was just restored to TRUE.  If we weren't
+     called recursively, it was restored to FALSE.  That's just how
+     defer_mark_used_call ought to be set.  */
+  defer_mark_used_calls = is_folding_function;
+  if (!defer_mark_used_calls && deferred_mark_used_calls)
     {
       unsigned int i;
       tree decl;
diff --git a/gcc/testsuite/g++.dg/pr69315.C b/gcc/testsuite/g++.dg/pr69315.C
new file mode 100644
index 0000000..28975b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr69315.C
@@ -0,0 +1,34 @@
+// { dg-do compile }
+// { dg-options "-std=c++11" }
+
+// Template instantiation and evaluation for folding within
+// finish_function may call finish_function recursively.
+// Make sure we don't reject or delay that sort of recursion.
+
+template <bool> struct Iter;
+
+struct Arg {
+  Iter<true> begin();
+  Iter<true> end();
+};
+
+template <bool> struct Iter {
+  int operator*();
+  Iter operator++();
+  template <bool C1, bool C2> friend constexpr bool operator==(Iter<C1>, Iter<C2>);
+  template <bool C1, bool C2> friend constexpr bool operator!=(Iter<C1>, Iter<C2>);
+};
+
+void func(Arg a) {
+  for (auto ch : a) {
+    a.begin() == a.end();
+  }
+}
+
+template <bool C1, bool C2> constexpr bool operator==(Iter<C1>, Iter<C2>) {
+  return true;
+}
+
+template <bool C1, bool C2> constexpr bool operator!=(Iter<C1> a, Iter<C2> b) {
+  return a == b;
+}

-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PR69315] enable finish_function to recurse for constexpr functions
  2016-01-26 17:12 [PR69315] enable finish_function to recurse for constexpr functions Alexandre Oliva
@ 2016-02-10 21:22 ` Alexandre Oliva
  2016-02-24 12:56   ` Alexandre Oliva
  2016-03-22 21:36 ` Jason Merrill
  1 sibling, 1 reply; 7+ messages in thread
From: Alexandre Oliva @ 2016-02-10 21:22 UTC (permalink / raw)
  To: gcc-patches; +Cc: jason

On Jan 26, 2016, Alexandre Oliva <aoliva@redhat.com> wrote:

> We don't want finish_function to be called recursively from mark_used.
> However, it's desirable and necessary to call itself recursively when
> performing delayed folding, because that may have to instantiate and
> evaluate constexpr template functions.

> So, arrange for finish_function to accept being called recursively
> during delayed folding, save and restore the controlling variables,
> and process the deferred mark_used calls only when the outermost call
> completes.

> Regstrapped on x86_64-linux-gnu and i686-linux-gnu.  Ok to install?

Ping?

https://gcc.gnu.org/ml/gcc-patches/2016-01/msg02010.html

-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PR69315] enable finish_function to recurse for constexpr functions
  2016-02-10 21:22 ` Alexandre Oliva
@ 2016-02-24 12:56   ` Alexandre Oliva
  0 siblings, 0 replies; 7+ messages in thread
From: Alexandre Oliva @ 2016-02-24 12:56 UTC (permalink / raw)
  To: jason; +Cc: gcc-patches

On Feb 10, 2016, Alexandre Oliva <aoliva@redhat.com> wrote:

> On Jan 26, 2016, Alexandre Oliva <aoliva@redhat.com> wrote:
>> We don't want finish_function to be called recursively from mark_used.
>> However, it's desirable and necessary to call itself recursively when
>> performing delayed folding, because that may have to instantiate and
>> evaluate constexpr template functions.

>> So, arrange for finish_function to accept being called recursively
>> during delayed folding, save and restore the controlling variables,
>> and process the deferred mark_used calls only when the outermost call
>> completes.

>> Regstrapped on x86_64-linux-gnu and i686-linux-gnu.  Ok to install?

> Ping?

> https://gcc.gnu.org/ml/gcc-patches/2016-01/msg02010.html

Ping?

-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PR69315] enable finish_function to recurse for constexpr functions
  2016-01-26 17:12 [PR69315] enable finish_function to recurse for constexpr functions Alexandre Oliva
  2016-02-10 21:22 ` Alexandre Oliva
@ 2016-03-22 21:36 ` Jason Merrill
  2016-03-23 14:01   ` Jakub Jelinek
  1 sibling, 1 reply; 7+ messages in thread
From: Jason Merrill @ 2016-03-22 21:36 UTC (permalink / raw)
  To: Alexandre Oliva, gcc-patches, Jakub Jelinek

On 01/26/2016 12:11 PM, Alexandre Oliva wrote:
> We don't want finish_function to be called recursively from mark_used.
> However, it's desirable and necessary to call itself recursively when
> performing delayed folding, because that may have to instantiate and
> evaluate constexpr template functions.

Hmm.  If recursion is problematic, we shouldn't do it.  If it isn't 
problematic, we can do away with defer_mark_used_calls.  It doesn't make 
sense to me to allow recursion some of the time.

I tried disabling defer_mark_used_calls, and the only new testsuite 
failure turned out to be fixing a bug on variadic122.C: we were 
deferring a mark_used call in unevaluated context and then calling it in 
evaluated context.

Jakub, you added defer_mark_used_calls for BZ 37189, do you think it's 
still needed?  The testcase passes without it now.

Jason

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PR69315] enable finish_function to recurse for constexpr functions
  2016-03-22 21:36 ` Jason Merrill
@ 2016-03-23 14:01   ` Jakub Jelinek
  2016-03-23 16:24     ` Jakub Jelinek
  0 siblings, 1 reply; 7+ messages in thread
From: Jakub Jelinek @ 2016-03-23 14:01 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Alexandre Oliva, gcc-patches

On Tue, Mar 22, 2016 at 05:28:10PM -0400, Jason Merrill wrote:
> Jakub, you added defer_mark_used_calls for BZ 37189, do you think it's still
> needed?  The testcase passes without it now.

That's a question.  Digging through history, I found:
1) r149750 aka gimplification unit-at-a-time
2) PR48869 that fixed the regression caused by that; so we now should be
   trying to get_copy_ctor/get_dtor for parallel/task already during
   cp-genericize.c
But, looking at this function, e.g. taskloop construct isn't handled,
will try to construct a testcase where it could matter.  Dunno about OpenACC
or Cilk+ constructs, those aren't handled during cp-gimplify.c either.
Though, as we have gimplification unit-at-a-time, I'd say that even if we
synthetize_method during gimplification of something, we'd still enqueue it
in cgraph for later analysis instead of gimplification right away.
The gimplifier still asserts that it isn't called recursively, so I'd hope
the patch can be reverted (test kept).

	Jakub

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PR69315] enable finish_function to recurse for constexpr functions
  2016-03-23 14:01   ` Jakub Jelinek
@ 2016-03-23 16:24     ` Jakub Jelinek
  2016-03-23 18:22       ` Jason Merrill
  0 siblings, 1 reply; 7+ messages in thread
From: Jakub Jelinek @ 2016-03-23 16:24 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Alexandre Oliva, gcc-patches

On Wed, Mar 23, 2016 at 02:57:36PM +0100, Jakub Jelinek wrote:
> On Tue, Mar 22, 2016 at 05:28:10PM -0400, Jason Merrill wrote:
> > Jakub, you added defer_mark_used_calls for BZ 37189, do you think it's still
> > needed?  The testcase passes without it now.
> 
> That's a question.  Digging through history, I found:
> 1) r149750 aka gimplification unit-at-a-time
> 2) PR48869 that fixed the regression caused by that; so we now should be
>    trying to get_copy_ctor/get_dtor for parallel/task already during
>    cp-genericize.c
> But, looking at this function, e.g. taskloop construct isn't handled,
> will try to construct a testcase where it could matter.  Dunno about OpenACC
> or Cilk+ constructs, those aren't handled during cp-gimplify.c either.
> Though, as we have gimplification unit-at-a-time, I'd say that even if we
> synthetize_method during gimplification of something, we'd still enqueue it
> in cgraph for later analysis instead of gimplification right away.
> The gimplifier still asserts that it isn't called recursively, so I'd hope
> the patch can be reverted (test kept).

I'll test then following (had to tweak the testcase a little bit, put c++11
into target, move it to proper dir, and build with -O2 (as starting with
r233671 we don't ICE on the testcase when -fno-inline, which is the default
at -O0).

2016-03-23  Alexandre Oliva  <aoliva@redhat.com>
	    Jason Merrill  <jason@redhat.com>
	    Jakub Jelinek  <jakub@redhat.com>

	PR c++/69315
	* cp-tree.h (defer_mark_used_calls, deferred_mark_used_calls): Remove.
	* decl.c (defer_mark_used_calls, deferred_mark_used_calls): Remove.
	(finish_function): Don't set or test them.
	* decl2.c (mark_used): Don't handle defer_mark_used_calls.

	* g++.dg/cpp0x/constexpr-69315.C: New test.
	* g++.dg/cpp0x/variadic122.C: Change one dg-warning into dg-bogus.

--- gcc/cp/cp-tree.h.jj	2016-03-21 10:12:31.000000000 +0100
+++ gcc/cp/cp-tree.h	2016-03-23 16:38:46.193501388 +0100
@@ -5846,8 +5846,6 @@ extern tree fndecl_declared_return_type
 extern bool undeduced_auto_decl			(tree);
 extern void require_deduced_type		(tree);
 
-extern bool defer_mark_used_calls;
-extern GTY(()) vec<tree, va_gc> *deferred_mark_used_calls;
 extern tree finish_case_label			(location_t, tree, tree);
 extern tree cxx_maybe_build_cleanup		(tree, tsubst_flags_t);
 
--- gcc/cp/decl.c.jj	2016-03-22 09:05:31.000000000 +0100
+++ gcc/cp/decl.c	2016-03-23 16:39:11.563158827 +0100
@@ -227,11 +227,6 @@ struct GTY((for_user)) named_label_entry
    function, two inside the body of a function in a local class, etc.)  */
 int function_depth;
 
-/* To avoid unwanted recursion, finish_function defers all mark_used calls
-   encountered during its execution until it finishes.  */
-bool defer_mark_used_calls;
-vec<tree, va_gc> *deferred_mark_used_calls;
-
 /* States indicating how grokdeclarator() should handle declspecs marked
    with __attribute__((deprecated)).  An object declared as
    __attribute__((deprecated)) suppresses warnings of uses of other
@@ -14594,9 +14589,6 @@ finish_function (int flags)
   if (c_dialect_objc ())
     objc_finish_function ();
 
-  gcc_assert (!defer_mark_used_calls);
-  defer_mark_used_calls = true;
-
   record_key_method_defined (fndecl);
 
   fntype = TREE_TYPE (fndecl);
@@ -14846,17 +14838,6 @@ finish_function (int flags)
   /* Clean up.  */
   current_function_decl = NULL_TREE;
 
-  defer_mark_used_calls = false;
-  if (deferred_mark_used_calls)
-    {
-      unsigned int i;
-      tree decl;
-
-      FOR_EACH_VEC_SAFE_ELT (deferred_mark_used_calls, i, decl)
-	mark_used (decl);
-      vec_free (deferred_mark_used_calls);
-    }
-
   invoke_plugin_callbacks (PLUGIN_FINISH_PARSE_FUNCTION, fndecl);
   return fndecl;
 }
--- gcc/cp/decl2.c.jj	2016-02-19 08:55:04.000000000 +0100
+++ gcc/cp/decl2.c	2016-03-23 16:39:28.604928715 +0100
@@ -5140,14 +5140,6 @@ mark_used (tree decl, tsubst_flags_t com
   if (DECL_ODR_USED (decl))
     return true;
 
-  /* If within finish_function, defer the rest until that function
-     finishes, otherwise it might recurse.  */
-  if (defer_mark_used_calls)
-    {
-      vec_safe_push (deferred_mark_used_calls, decl);
-      return true;
-    }
-
   /* Normally, we can wait until instantiation-time to synthesize DECL.
      However, if DECL is a static data member initialized with a constant
      or a constexpr function, we need it right now because a reference to
--- gcc/testsuite/g++.dg/cpp0x/constexpr-69315.C.jj	2016-03-23 16:48:59.675217676 +0100
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-69315.C	2016-03-23 16:46:37.000000000 +0100
@@ -0,0 +1,35 @@
+// PR c++/69315
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2" }
+
+// Template instantiation and evaluation for folding within
+// finish_function may call finish_function recursively.
+// Make sure we don't reject or delay that sort of recursion.
+
+template <bool> struct Iter;
+
+struct Arg {
+  Iter<true> begin();
+  Iter<true> end();
+};
+
+template <bool> struct Iter {
+  int operator*();
+  Iter operator++();
+  template <bool C1, bool C2> friend constexpr bool operator==(Iter<C1>, Iter<C2>);
+  template <bool C1, bool C2> friend constexpr bool operator!=(Iter<C1>, Iter<C2>);
+};
+
+void func(Arg a) {
+  for (auto ch : a) {
+    a.begin() == a.end();
+  }
+}
+
+template <bool C1, bool C2> constexpr bool operator==(Iter<C1>, Iter<C2>) {
+  return true;
+}
+
+template <bool C1, bool C2> constexpr bool operator!=(Iter<C1> a, Iter<C2> b) {
+  return a == b;
+}
--- gcc/testsuite/g++.dg/cpp0x/variadic122.C.jj	2014-03-10 10:50:13.000000000 +0100
+++ gcc/testsuite/g++.dg/cpp0x/variadic122.C	2016-03-23 16:54:10.000000000 +0100
@@ -9,7 +9,7 @@ template < class T > struct Container
 
 template < class T >
 T deref (T)
-{}				// { dg-warning "no return" }
+{}				// { dg-bogus "no return" }
 
 template < class T, class ... Args >
 auto deref (T u, int, Args ... args)->decltype (deref (u.f (), args ...))


	Jakub

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PR69315] enable finish_function to recurse for constexpr functions
  2016-03-23 16:24     ` Jakub Jelinek
@ 2016-03-23 18:22       ` Jason Merrill
  0 siblings, 0 replies; 7+ messages in thread
From: Jason Merrill @ 2016-03-23 18:22 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Alexandre Oliva, gcc-patches

OK.

Jason

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2016-03-23 17:45 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-26 17:12 [PR69315] enable finish_function to recurse for constexpr functions Alexandre Oliva
2016-02-10 21:22 ` Alexandre Oliva
2016-02-24 12:56   ` Alexandre Oliva
2016-03-22 21:36 ` Jason Merrill
2016-03-23 14:01   ` Jakub Jelinek
2016-03-23 16:24     ` Jakub Jelinek
2016-03-23 18:22       ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).