coroutines: Handle namespaces while scanning local vars [PR95711].
authorIain Sandoe <iain@sandoe.co.uk>
Sun, 28 Jun 2020 11:29:11 +0000 (12:29 +0100)
committerIain Sandoe <iain@sandoe.co.uk>
Sun, 28 Jun 2020 12:52:25 +0000 (13:52 +0100)
We need to skip past namespace decls when scanning the bind
expression var lists checking for local vars.

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
gcc/testsuite/g++.dg/coroutines/pr95711.C [new file with mode: 0644]

index bab03d448637291d1a62b252589bb2a89bd3fab5..54f9cb3b4e4576bcf7dde64115f88fa0396db639 100644 (file)
@@ -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 (file)
index 0000000..f6aedb1
--- /dev/null
@@ -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;
+}