[pushed] coroutines: Handle namespaces while scanning local vars [PR95711].

Message ID 3652A84D-EA80-4D8A-9A36-408103BC1F8B@sandoe.co.uk
State New
Headers show
Series
  • [pushed] coroutines: Handle namespaces while scanning local vars [PR95711].
Related show

Commit Message

Iain Sandoe June 28, 2020, 12:55 p.m.
Hi,

We need to skip past namespace decls when scanning the bind
expression var lists checking for local vars.

The PR notes that this omission results in an ice-on-valid.

tested on x86_64-linux, darwin, powerpc64-linux,

applied to master as obvious (and will backport to 10.2).

thanks
Iain

gcc/cp/ChangeLog:

	PR c++/95711
	* coroutines.cc (register_local_var_uses): Skip past
	namespace decls.

gcc/testsuite/ChangeLog:

	PR c++/95711
	* g++.dg/coroutines/pr95711.C: New test.
---
 gcc/cp/coroutines.cc                      |  3 +-
 gcc/testsuite/g++.dg/coroutines/pr95711.C | 79 +++++++++++++++++++++++
 2 files changed, 81 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/coroutines/pr95711.C

-- 
2.24.1

Patch

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index bab03d44863..54f9cb3b4e4 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -3563,7 +3563,8 @@  register_local_var_uses (tree *stmt, int *do_subtree, void *d)
 	  local_var.field_idx = local_var.field_id = NULL_TREE;
 
 	  /* Make sure that we only present vars to the tests below.  */
-	  if (TREE_CODE (lvar) == TYPE_DECL)
+	  if (TREE_CODE (lvar) == TYPE_DECL
+	      || TREE_CODE (lvar) == NAMESPACE_DECL)
 	    continue;
 
 	  /* We don't move static vars into the frame. */
diff --git a/gcc/testsuite/g++.dg/coroutines/pr95711.C b/gcc/testsuite/g++.dg/coroutines/pr95711.C
new file mode 100644
index 00000000000..f6aedb16ebd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr95711.C
@@ -0,0 +1,79 @@ 
+//  { dg-do run }
+
+#if __has_include(<coroutine>)
+#include <coroutine>
+#else
+#include <experimental/coroutine>
+namespace std {
+    using namespace std::experimental;
+}
+#endif
+#include <cstdlib>
+
+template <typename T>
+struct generator{
+    struct promise_type;
+    using coro_handle = std::coroutine_handle<promise_type>;
+
+    struct promise_type{
+        std::suspend_always yield_value (T value){
+            value_ = value;
+            return {};
+        }
+        std::suspend_always initial_suspend (){
+            return {};
+        }
+        std::suspend_always final_suspend (){
+            return {};
+        }
+
+        std::suspend_never return_void()
+        {
+            return {};
+        }
+        generator get_return_object () {
+            return {coro_handle::from_promise(*this)};
+        }
+        void unhandled_exception () {
+            return;
+        }
+        T value_;
+    };
+    coro_handle handle;
+    generator(coro_handle h)
+        :handle(h)
+    {}
+    ~generator(){
+        if(handle)
+            handle.destroy();
+    }
+
+    bool resume(){
+        if(not handle.done())
+            handle.resume();
+        return not handle.done();
+    };
+
+    T get () {
+        return handle.promise().value_;
+    }
+};
+namespace A
+{
+}
+
+generator<int>
+parse()
+{
+    namespace B = A;
+    co_yield 1;
+}
+
+int main()
+{
+    auto gen = parse();
+    gen.handle.resume (); /* init suspend. */
+    if (gen.get() != 1)
+      abort ();
+  return 0;
+}