Eo: Remove GCCism and make it more portable.

This affects eo_do() and eo_add() that used to use the ({}) GCCism.
Following a discussion with Peter de Ridder after my talk at FOSDEM,
we've decided to reopen the GCCism (works with other gcc compatible
compilers like clang and intelc) discussion, and after a bit of back and
forth it was decided to make things more portable, at the cost of ease
of use.

For example:
if (eo_do(obj, visible_get()))
is no longer allowed, the portable alternative
Eina_Bool tmp;
if (eo_do_ret(obj, tmp, visible_get()))
is to be used instead.

However:
eo_do(obj, a = a_get(), b = b_get(), bool_set(!bool_get))
are still allowed and OK.

eo_do(obj, if (a_get()) return;);
is no longer allowed, but:
eo_do(obj, if (a_get()) something());
is still allowed.

For clarity, this commit only incorporates the Eo changes, and not the
EFL changes to make the efl conform with this change.

Thanks again to Peter de Ridder for triggering this important discussion
which led to this change.
This commit is contained in:
Tom Hacohen 2015-02-23 16:06:40 +00:00
parent 272e8b70ff
commit a791d97bfc
7 changed files with 64 additions and 46 deletions

View File

@ -576,24 +576,35 @@ EAPI Eina_Bool _eo_call_resolve(const char *func_name, const Eo_Op op, Eo_Op_Cal
EAPI Eina_Bool _eo_do_start(const Eo *obj, const Eo_Class *cur_klass, Eina_Bool is_super, const char *file, const char *func, int line);
// end of the eo_do barrier, unref the obj, move the stack pointer
EAPI void _eo_do_end(const Eo **ojb);
EAPI void _eo_do_end(void);
#define EO_DO_CLEANUP __attribute__((cleanup(_eo_do_end)))
// end of the eo_add. Calls finalize among others
EAPI Eo * _eo_add_end(void);
// eo object method calls batch,
#define _eo_do_common(eoid, clsid, is_super, ...) \
({ \
const Eo *_eoid_ EO_DO_CLEANUP = eoid; \
_eo_do_start(_eoid_, clsid, is_super, __FILE__, __FUNCTION__, __LINE__); \
do { \
_eo_do_start(eoid, clsid, is_super, __FILE__, __FUNCTION__, __LINE__); \
__VA_ARGS__; \
})
_eo_do_end(); \
} while (0)
#define _eo_do_common_ret(eoid, clsid, is_super, ret_tmp, func) \
( \
_eo_do_start(eoid, clsid, is_super, __FILE__, __FUNCTION__, __LINE__), \
ret_tmp = func, \
_eo_do_end(), \
ret_tmp \
)
#define eo_do(eoid, ...) _eo_do_common(eoid, NULL, EINA_FALSE, __VA_ARGS__)
#define eo_do_super(eoid, clsid, func) _eo_do_common(eoid, clsid, EINA_TRUE, func)
#define eo_do_ret(eoid, ret_tmp, func) _eo_do_common_ret(eoid, NULL, EINA_FALSE, ret_tmp, func)
/*****************************************************************************/
/**
@ -618,6 +629,14 @@ EAPI const Eo_Class *eo_class_get(const Eo *obj);
EAPI void eo_error_set_internal(const Eo *obj, const char *file, int line);
/* @endcond */
#define _eo_add_common(klass, parent, is_ref, ...) \
( \
_eo_do_start(_eo_add_internal_start(__FILE__, __LINE__, klass, parent, is_ref), \
klass, EINA_FALSE, __FILE__, __FUNCTION__, __LINE__), \
eo_constructor(), ##__VA_ARGS__, \
(Eo *) _eo_add_end() \
)
/**
* @def eo_add
* @brief Create a new object with the default constructor.
@ -633,17 +652,7 @@ EAPI void eo_error_set_internal(const Eo *obj, const char *file, int line);
* @param ... The ops to run.
* @return An handle to the new object on success, NULL otherwise.
*/
#define eo_add(klass, parent, ...) \
({ \
const Eo_Class *_tmp_klass = klass; \
Eo *_tmp_obj = _eo_add_internal_start(__FILE__, __LINE__, _tmp_klass, parent, EINA_FALSE); \
eo_do(_tmp_obj, \
eo_constructor(); \
__VA_ARGS__; \
_tmp_obj = eo_finalize(); \
); \
_tmp_obj; \
})
#define eo_add(klass, parent, ...) _eo_add_common(klass, parent, EINA_FALSE, ##__VA_ARGS__)
/**
* @def eo_add_ref
@ -657,17 +666,7 @@ EAPI void eo_error_set_internal(const Eo *obj, const char *file, int line);
* @param ... The ops to run.
* @return An handle to the new object on success, NULL otherwise.
*/
#define eo_add_ref(klass, parent, ...) \
({ \
const Eo_Class *_tmp_klass = klass; \
Eo *_tmp_obj = _eo_add_internal_start(__FILE__, __LINE__, _tmp_klass, parent, EINA_TRUE); \
eo_do(_tmp_obj, \
eo_constructor(); \
__VA_ARGS__; \
_tmp_obj = eo_finalize(); \
); \
_tmp_obj; \
})
#define eo_add_ref(klass, parent, ...) _eo_add_common(klass, parent, EINA_TRUE, ##__VA_ARGS__)
EAPI Eo * _eo_add_internal_start(const char *file, int line, const Eo_Class *klass_id, Eo *parent, Eina_Bool ref);

View File

@ -533,7 +533,7 @@ _eo_do_start(const Eo *eo_id, const Eo_Class *cur_klass_id, Eina_Bool is_super,
}
EAPI void
_eo_do_end(const Eo **eo_id EINA_UNUSED)
_eo_do_end(void)
{
Eo_Stack_Frame *fptr;
Eo_Call_Stack *stack = _eo_call_stack_get(eina_main_loop_is()); // Is it possible to extract information from the scope ?
@ -910,9 +910,12 @@ _eo_add_internal_start(const char *file, int line, const Eo_Class *klass_id, Eo
/* If there's a parent. Unref. Eo_add should return an object with either a
* parent ref, or with the lack of, just a ref. */
if (!ref && eo_do(eo_id, eo_parent_get()))
{
_eo_unref(obj);
Eo *parent_tmp;
if (!ref && eo_do_ret(eo_id, parent_tmp, eo_parent_get()))
{
_eo_unref(obj);
}
}
return eo_id;
@ -957,6 +960,14 @@ _eo_add_internal_end(Eo *eo_id)
return (Eo *)eo_id;
}
EAPI Eo *
_eo_add_end(void)
{
Eo *ret = eo_finalize();
_eo_do_end();
return ret;
}
/*****************************************************************************/
#define _EO_OP_ERR_NO_OP_PRINT(file, line, op, klass) \
@ -1544,7 +1555,8 @@ eo_unref(const Eo *obj_id)
EAPI void
eo_del(const Eo *obj)
{
if (eo_do(obj, eo_parent_get()))
Eo *parent_tmp;
if (eo_do_ret(obj, parent_tmp, eo_parent_get()))
{
eo_do(obj, eo_parent_set(NULL));
}

View File

@ -101,10 +101,11 @@ _eo_base_key_data_get(Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *key)
EOLIAN static void
_eo_base_parent_set(Eo *obj, Eo_Base_Data *pd, Eo *parent_id)
{
Eina_Bool tmp;
if (pd->parent == parent_id)
return;
if (eo_do(obj, eo_composite_part_is()) && pd->parent)
if (eo_do_ret(obj, tmp, eo_composite_part_is()) && pd->parent)
{
eo_do(pd->parent, eo_composite_detach(obj));
}

View File

@ -22,14 +22,15 @@ _a_get(Eo *obj, void *class_data EINA_UNUSED)
static void
_constructor(Eo *obj, void *class_data EINA_UNUSED)
{
Eina_Bool tmp;
eo_do_super(obj, MY_CLASS, eo_constructor());
Eo *simple = eo_add(SIMPLE_CLASS, obj);
eo_do(obj, eo_composite_attach(simple));
eo_do(simple, eo_event_callback_forwarder_add(EV_A_CHANGED, obj));
fail_if(eo_do(obj, eo_composite_part_is()));
fail_if(!eo_do(simple, eo_composite_part_is()));
fail_if(eo_do_ret(obj, tmp, eo_composite_part_is()));
fail_if(!eo_do_ret(simple, tmp, eo_composite_part_is()));
eo_do(obj, eo_key_data_set("simple-obj", simple, NULL));
}

View File

@ -26,6 +26,7 @@ _a_changed_cb(void *data, Eo *obj, const Eo_Event_Description *desc, void *event
int
main(int argc, char *argv[])
{
Eina_Bool tmp;
(void) argc;
(void) argv;
eo_init();
@ -65,15 +66,15 @@ main(int argc, char *argv[])
eo_do(obj, simple_a_set(2));
fail_if(cb_called);
fail_if(!eo_do(simple, eo_composite_part_is()));
fail_if(!eo_do(obj, eo_composite_detach(simple)));
fail_if(eo_do(obj, eo_composite_detach(simple)));
fail_if(eo_do(simple, eo_composite_part_is()));
fail_if(!eo_do(obj, eo_composite_attach(simple)));
fail_if(!eo_do(simple, eo_composite_part_is()));
fail_if(eo_do(obj, eo_composite_attach(simple)));
fail_if(!eo_do_ret(simple, tmp,eo_composite_part_is()));
fail_if(!eo_do_ret(obj, tmp,eo_composite_detach(simple)));
fail_if(eo_do_ret(obj, tmp,eo_composite_detach(simple)));
fail_if(eo_do_ret(simple, tmp,eo_composite_part_is()));
fail_if(!eo_do_ret(obj, tmp,eo_composite_attach(simple)));
fail_if(!eo_do_ret(simple, tmp,eo_composite_part_is()));
fail_if(eo_do_ret(obj, tmp,eo_composite_attach(simple)));
fail_if(eo_do(simple, eo_composite_attach(obj)));
fail_if(eo_do_ret(simple, tmp,eo_composite_attach(obj)));
eo_unref(simple);
eo_unref(obj);

View File

@ -50,11 +50,14 @@ _constructor(Eo *obj, void *class_data EINA_UNUSED)
static Eo*
_finalize(Eo *obj, void *class_data EINA_UNUSED)
{
Eo *ret;
Private_Data *pd = class_data;
if (pd->a < 0) eo_error_set(obj);
return eo_do_super(obj, MY_CLASS, eo_finalize());
eo_do_super(obj, MY_CLASS, ret = eo_finalize());
return ret;
}
static void

View File

@ -271,6 +271,7 @@ END_TEST
START_TEST(eo_composite_tests)
{
Eina_Bool tmp;
eo_init();
Eo *obj = eo_add(SIMPLE_CLASS, NULL);
@ -280,7 +281,7 @@ START_TEST(eo_composite_tests)
eo_do(obj, eo_composite_attach(obj2));
eo_do(obj2, eo_parent_set(NULL));
fail_if(eo_do(obj2, eo_composite_part_is()));
fail_if(eo_do_ret(obj2, tmp, eo_composite_part_is()));
eo_unref(obj2);
eo_unref(obj);
@ -803,7 +804,7 @@ START_TEST(eo_add_do_and_custom)
obj = eo_add(SIMPLE_CLASS, NULL, finalized = eo_finalized_get());
fail_if(finalized);
finalized = eo_do(obj, eo_finalized_get());
eo_do(obj, finalized = eo_finalized_get());
fail_if(!finalized);
eo_unref(obj);