Commit 14a249cb authored by Kirill Smelkov's avatar Kirill Smelkov

libgolang: Fix double C++ defer

If defer was used multiple times in one function it was failing to
compile. For example added test is failing like this:

    In file included from golang/runtime/libgolang_test.cpp:22:
    golang/runtime/libgolang_test.cpp: In function ‘void __test_defer(int*)’:
    ./golang/libgolang.h:457:59: error: redeclaration of ‘golang::_deferred _defer___COUNTER__’
     #define defer(f) golang::_deferred _defer_ ## __COUNTER__ (f)
                                                               ^
    golang/runtime/libgolang_test.cpp:473:5: note: in expansion of macro ‘defer’
         defer([&]() {
         ^~~~~
    ./golang/libgolang.h:457:36: note: ‘golang::_deferred _defer___COUNTER__’ previously declared here
     #define defer(f) golang::_deferred _defer_ ## __COUNTER__ (f)
                                        ^~~~~~~
    golang/runtime/libgolang_test.cpp:470:5: note: in expansion of macro ‘defer’
         defer([&]() {
         ^~~~~

It turns out the __COUNTER__ was not expanded and they say you have to
use 3 level of macro calls. Oh well...

https://stackoverflow.com/a/27611869/9456786
parent de269272
...@@ -454,7 +454,9 @@ int select(const std::vector<_selcase> &casev) { ...@@ -454,7 +454,9 @@ int select(const std::vector<_selcase> &casev) {
// defer(f) mimics `defer f()` from golang. // defer(f) mimics `defer f()` from golang.
// NOTE contrary to Go f is called at end of current scope, not function. // NOTE contrary to Go f is called at end of current scope, not function.
#define defer(f) golang::_deferred _defer_ ## __COUNTER__ (f) #define defer(f) golang::_deferred _defer_(__COUNTER__) (f)
#define _defer_(counter) _defer_2(counter)
#define _defer_2(counter) _defer_##counter
struct _deferred { struct _deferred {
typedef func<void()> F; typedef func<void()> F;
F f; F f;
......
...@@ -27,9 +27,11 @@ ...@@ -27,9 +27,11 @@
#include <tuple> #include <tuple>
#include <utility> #include <utility>
#include <string.h> #include <string.h>
#include <vector>
using namespace golang; using namespace golang;
using std::move; using std::move;
using std::tie; using std::tie;
using std::vector;
#define __STR(X) #X #define __STR(X) #X
#define STR(X) __STR(X) #define STR(X) __STR(X)
...@@ -466,16 +468,19 @@ void _test_select_inplace() { ...@@ -466,16 +468,19 @@ void _test_select_inplace() {
// verify that defer works. // verify that defer works.
void __test_defer(bool *pcalled) { void __test_defer(vector<int> *pcalled) {
defer([&]() { defer([&]() {
*pcalled = true; pcalled->push_back(1);
});
defer([&]() {
pcalled->push_back(2);
}); });
return; return;
} }
void _test_defer() { void _test_defer() {
bool called = false; vector<int> called, ok({2, 1});
__test_defer(&called); __test_defer(&called);
ASSERT(called); ASSERT(called == ok);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment