From dfe3a4ad403c5d9219b3f383f8f8147907cff613 Mon Sep 17 00:00:00 2001 From: Gustavo Sverzut Barbieri Date: Fri, 2 Dec 2016 16:26:46 -0200 Subject: [PATCH] eo: improve logs by always showing event source, minor refactor. Instead of 2 sets of macro, one for HAVE_EO_ID and another without, use a single set of macros and have the implementation of _eo_class_pointer_get() and _eo_obj_pointer_get() to do the actual These functions now take the source information so the logs reflect that and not always the same function. --- src/lib/eo/eo.c | 55 +++++++---- src/lib/eo/eo_private.h | 23 ++--- src/lib/eo/eo_ptr_indirection.c | 34 +++++-- src/lib/eo/eo_ptr_indirection.h | 158 ++++++++++++++------------------ src/lib/eo/eo_ptr_indirection.x | 1 + 5 files changed, 148 insertions(+), 123 deletions(-) diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c index e86f0527de..ce28395d3f 100644 --- a/src/lib/eo/eo.c +++ b/src/lib/eo/eo.c @@ -249,11 +249,28 @@ _eo_is_a_class(const Eo *eo_id) } static inline _Efl_Class * -_eo_class_pointer_get(const Efl_Class *klass_id) +_eo_class_pointer_get(const Efl_Class *klass_id, const char *func_name, const char *file, int line) { #ifdef HAVE_EO_ID return ID_CLASS_GET((Eo_Id)klass_id); + (void)func_name; + (void)file; + (void)line; #else + Eo_Header *klass = (Eo_Header *)klass_id; + if (EINA_UNLIKELY(!klass)) + { + eina_log_print(_eo_log_dom, + EINA_LOG_LEVEL_DBG, + file, func_name, line, + "klass_id is NULL. Possibly unintended access?"); + return NULL; + } + if (EINA_UNLIKELY(!EINA_MAGIC_CHECK(klass, EO_CLASS_EINA_MAGIC))) + { + eina_magic_fail(klass, klass->__magic, EO_CLASS_EINA_MAGIC, file, func_name, line); + return NULL; + } return (_Efl_Class *) klass_id; #endif } @@ -369,7 +386,7 @@ _efl_object_call_resolve(Eo *eo_id, const char *func_name, Efl_Object_Op_Call_Da if (is_obj) { - EO_OBJ_POINTER_RETURN_VAL(eo_id, _obj, EINA_FALSE); + EO_OBJ_POINTER_RETURN_VAL_PROXY(eo_id, _obj, EINA_FALSE); obj = _obj; klass = _obj->klass; @@ -479,7 +496,7 @@ end: Eo *emb_obj_id; EINA_LIST_FOREACH(obj->composite_objects, itr, emb_obj_id) { - EO_OBJ_POINTER(emb_obj_id, emb_obj); + EO_OBJ_POINTER_PROXY(emb_obj_id, emb_obj); if (EINA_UNLIKELY(!emb_obj)) continue; func = _vtable_func_get(emb_obj->vtable, cache->op); @@ -543,7 +560,7 @@ ok_cur_klass: ok_klass: { - EO_CLASS_POINTER_GOTO(eo_id, _klass, err_klass); + EO_CLASS_POINTER_GOTO_PROXY(eo_id, _klass, err_klass); klass = _klass; vtable = &klass->vtable; call->obj = NULL; @@ -728,16 +745,17 @@ err_klass: EAPI Eo * _efl_add_internal_start(const char *file, int line, const Efl_Class *klass_id, Eo *parent_id, Eina_Bool ref EINA_UNUSED, Eina_Bool is_fallback) { + const char *func_name = __FUNCTION__; _Eo_Object *obj; Eo_Stack_Frame *fptr = NULL; if (is_fallback) fptr = _efl_add_fallback_stack_push(NULL); - EO_CLASS_POINTER_GOTO(klass_id, klass, err_klass); + EO_CLASS_POINTER_GOTO_PROXY(klass_id, klass, err_klass); if (parent_id) { - EO_OBJ_POINTER_GOTO(parent_id, parent, err_parent); + EO_OBJ_POINTER_GOTO_PROXY(parent_id, parent, err_parent); } // not likely so use goto to alleviate l1 instruction cache of rare code @@ -787,7 +805,7 @@ ok_nomatch_back: ok_nomatch: { - EO_OBJ_POINTER_GOTO(eo_id, new_obj, err_newid); + EO_OBJ_POINTER_GOTO_PROXY(eo_id, new_obj, err_newid); /* We have two refs at this point. */ _efl_unref(obj); efl_del((Eo *)obj->header.id); @@ -1171,18 +1189,17 @@ efl_class_new(const Efl_Class_Description *desc, const Efl_Class *parent_id, ... va_list p_list; size_t extn_sz, mro_sz, mixins_sz; Eina_List *extn_list, *mro, *mixins; + _Efl_Class *parent = NULL; EINA_SAFETY_ON_NULL_RETURN_VAL(desc, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(desc->name, NULL); - _Efl_Class *parent = _eo_class_pointer_get(parent_id); -#ifndef HAVE_EO_ID - if (parent && !EINA_MAGIC_CHECK((Eo_Header *) parent, EO_CLASS_EINA_MAGIC)) + if (parent_id) { - EINA_MAGIC_FAIL((Eo_Header *) parent, EO_CLASS_EINA_MAGIC); - return NULL; + parent = _eo_class_pointer_get(parent_id, __FUNCTION__, __FILE__, __LINE__); + if (!parent) + return NULL; } -#endif /* Check restrictions on Interface types. */ if (desc->type == EFL_CLASS_TYPE_INTERFACE) @@ -1231,7 +1248,7 @@ efl_class_new(const Efl_Class_Description *desc, const Efl_Class *parent_id, ... extn_id = va_arg(p_list, Eo_Id *); while (extn_id) { - extn = _eo_class_pointer_get((Efl_Class *)extn_id); + extn = _eo_class_pointer_get((Efl_Class *)extn_id, __FUNCTION__, __FILE__, __LINE__); switch (extn->desc->type) { case EFL_CLASS_TYPE_REGULAR_NO_INSTANT: @@ -1564,7 +1581,8 @@ efl_xref_internal(const char *file, int line, Eo *obj_id, const Eo *ref_obj_id) efl_ref(obj_id); #ifdef EO_DEBUG - EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, obj_id); + const char *func_name = __FUNCTION__; + EO_OBJ_POINTER_RETURN_VAL_PROXY(obj_id, obj, obj_id); Eo_Xref_Node *xref = calloc(1, sizeof(*xref)); xref->ref_obj = ref_obj_id; @@ -1848,13 +1866,14 @@ efl_data_xref_internal(const char *file, int line, const Eo *obj_id, const Efl_C { void *ret = NULL; _Efl_Class *klass = NULL; - EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL); - EO_OBJ_POINTER(ref_obj_id, ref_obj); + const char *func_name = __FUNCTION__; + EO_OBJ_POINTER_RETURN_VAL_PROXY(obj_id, obj, NULL); + EO_OBJ_POINTER_PROXY(ref_obj_id, ref_obj); if (ref_obj) { if (klass_id) { - EO_CLASS_POINTER_GOTO(klass_id, klass2, err_klass); + EO_CLASS_POINTER_GOTO_PROXY(klass_id, klass2, err_klass); klass = klass2; #ifdef EO_DEBUG // rare to use goto to keep instruction cache cleaner diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h index b79cbea32e..232fc05296 100644 --- a/src/lib/eo/eo_private.h +++ b/src/lib/eo/eo_private.h @@ -209,7 +209,7 @@ Eo *_eo_header_id_get(const Eo_Header *header) } /* Retrieves the pointer to the object from the id */ -_Eo_Object *_eo_obj_pointer_get(const Eo_Id obj_id); +_Eo_Object *_eo_obj_pointer_get(const Eo_Id obj_id, const char *func_name, const char *file, int line); void _eo_obj_pointer_done(const Eo_Id obj_id); static inline @@ -231,7 +231,7 @@ _eo_condtor_reset(_Eo_Object *obj) } static inline void -_efl_del_internal(const char *file, int line, _Eo_Object *obj) +_efl_del_internal(_Eo_Object *obj, const char *func_name, const char *file, int line) { /* We need that for the event callbacks that may ref/unref. */ obj->refcount++; @@ -246,8 +246,8 @@ _efl_del_internal(const char *file, int line, _Eo_Object *obj) if (!obj->condtor_done) { - ERR("in %s:%d: Object of class '%s' - Not all of the object destructors have been executed.", - file, line, klass->desc->name); + ERR("in %s:%d: func '%s' Object of class '%s' - Not all of the object destructors have been executed.", + file, line, func_name, klass->desc->name); } /*FIXME: add eo_class_unref(klass) ? - just to clear the caches. */ @@ -310,27 +310,28 @@ _efl_ref(_Eo_Object *obj) return obj; } +#define _efl_unref(obj) _efl_unref_internal(obj, __FUNCTION__, __FILE__, __LINE__) static inline void -_efl_unref(_Eo_Object *obj) +_efl_unref_internal(_Eo_Object *obj, const char *func_name, const char *file, int line) { --(obj->refcount); if (EINA_UNLIKELY(obj->refcount <= 0)) { if (obj->refcount < 0) { - ERR("Obj:%p. Refcount (%d) < 0. Too many unrefs.", obj, obj->refcount); + ERR("in %s:%d: func '%s' Obj:%p. Refcount (%d) < 0. Too many unrefs.", file, line, func_name, obj, obj->refcount); return; } if (obj->destructed) { - ERR("Object %p already destructed.", _eo_obj_id_get(obj)); + ERR("in %s:%d: func '%s' Object %p already destructed.", file, line, func_name, _eo_obj_id_get(obj)); return; } if (obj->del_triggered) { - ERR("Object %p deletion already triggered. You wrongly call efl_unref() within a destructor.", _eo_obj_id_get(obj)); + ERR("in %s:%d: func '%s' Object %p deletion already triggered. You wrongly call efl_unref() within a destructor.", file, line, func_name, _eo_obj_id_get(obj)); return; } @@ -344,12 +345,12 @@ _efl_unref(_Eo_Object *obj) obj->del_triggered = EINA_TRUE; - _efl_del_internal(__FILE__, __LINE__, obj); + _efl_del_internal(obj, func_name, file, line); #ifdef EO_DEBUG /* If for some reason it's not empty, clear it. */ while (obj->xrefs) { - ERR("obj->xrefs is not empty, possibly a bug, please report. - An error will be reported for each xref in the stack."); + ERR("in %s:%d: func '%s' obj->xrefs is not empty, possibly a bug, please report. - An error will be reported for each xref in the stack.", file, line, func_name); Eina_Inlist *nitr = obj->xrefs->next; eina_freeq_ptr_main_add(EINA_INLIST_CONTAINER_GET(obj->xrefs, Eo_Xref_Node), free, 0); obj->xrefs = nitr; @@ -358,7 +359,7 @@ _efl_unref(_Eo_Object *obj) { Eina_Inlist *nitr = obj->data_xrefs->next; Eo_Xref_Node *xref = EINA_INLIST_CONTAINER_GET(obj->data_xrefs, Eo_Xref_Node); - ERR("Data of object 0x%lx is still referenced by object %p", (unsigned long) _eo_obj_id_get(obj), xref->ref_obj); + ERR("in %s:%d: func '%s' Data of object 0x%lx is still referenced by object %p", file, line, func_name, (unsigned long) _eo_obj_id_get(obj), xref->ref_obj); eina_freeq_ptr_main_add(xref, free, sizeof(*xref)); obj->data_xrefs = nitr; diff --git a/src/lib/eo/eo_ptr_indirection.c b/src/lib/eo/eo_ptr_indirection.c index f8ccfe9922..e509512f6a 100644 --- a/src/lib/eo/eo_ptr_indirection.c +++ b/src/lib/eo/eo_ptr_indirection.c @@ -28,7 +28,10 @@ _eo_pointer_error(const char *func_name, const char *file, int line, const char static void _eo_obj_pointer_invalid(const Eo_Id obj_id, Eo_Id_Data *data, - unsigned char domain) + unsigned char domain, + const char *func_name, + const char *file, + int line) { Eina_Thread thread = eina_thread_self(); const char *tself = "main"; @@ -40,13 +43,14 @@ _eo_obj_pointer_invalid(const Eo_Id obj_id, snprintf(tbuf, sizeof(tbuf), "%p", (void *)thread); tself = tbuf; } - ERR("EOID %p is not a valid %s. " + eina_log_print(_eo_log_dom, EINA_LOG_LEVEL_ERR, + file, func_name, line, + "EOID %p is not a valid %s. " "EOID domain=%i, current_domain=%i, local_domain=%i. " "EOID generation=%lx, id=%lx, ref=%i, super=%i. " "Thread self=%s. " "Available domains [%s %s %s %s]. " "Maybe it has been deleted or does not belong to your thread?", - (void *)obj_id, type, (int)domain, @@ -66,7 +70,7 @@ _eo_obj_pointer_invalid(const Eo_Id obj_id, #endif _Eo_Object * -_eo_obj_pointer_get(const Eo_Id obj_id) +_eo_obj_pointer_get(const Eo_Id obj_id, const char *func_name, const char *file, int line) { #ifdef HAVE_EO_ID _Eo_Id_Entry *entry; @@ -168,14 +172,31 @@ _eo_obj_pointer_get(const Eo_Id obj_id) err_shared_null: eina_lock_release(&(_eo_table_data_shared_data->obj_lock)); err_null: - DBG("obj_id is NULL. Possibly unintended access?"); + eina_log_print(_eo_log_dom, + EINA_LOG_LEVEL_DBG, + file, func_name, line, + "obj_id is NULL. Possibly unintended access?"); return NULL; err_shared: eina_lock_release(&(_eo_table_data_shared_data->obj_lock)); err: - _eo_obj_pointer_invalid(obj_id, data, domain); + _eo_obj_pointer_invalid(obj_id, data, domain, func_name, file, line); return NULL; #else + Eo_Header *obj = (Eo_Header *)obj_id; + if (EINA_UNLIKELY(!obj)) + { + eina_log_print(_eo_log_dom, + EINA_LOG_LEVEL_DBG, + file, func_name, line, + "obj_id is NULL. Possibly unintended access?"); + return NULL; + } + if (EINA_UNLIKELY(!EINA_MAGIC_CHECK(obj, EO_EINA_MAGIC))) + { + eina_magic_fail(obj, obj->__magic, EO_EINA_MAGIC, file, func_name, line); + return NULL; + } return (_Eo_Object *) obj_id; #endif } @@ -188,4 +209,5 @@ _eo_obj_pointer_done(const Eo_Id obj_id) if (EINA_LIKELY(domain != EFL_ID_DOMAIN_SHARED)) return; eina_lock_release(&(_eo_table_data_shared_data->obj_lock)); #endif + (void)obj_id; } diff --git a/src/lib/eo/eo_ptr_indirection.h b/src/lib/eo/eo_ptr_indirection.h index b10a13e06b..dda0fa1fca 100644 --- a/src/lib/eo/eo_ptr_indirection.h +++ b/src/lib/eo/eo_ptr_indirection.h @@ -6,8 +6,6 @@ /* Macro used to obtain the object pointer and return if fails. */ -#ifdef HAVE_EO_ID - void _eo_pointer_error(const char *func_name, const char *file, int line, const char *fmt, ...); #define _EO_POINTER_ERR(fmt, ...) \ @@ -16,40 +14,84 @@ void _eo_pointer_error(const char *func_name, const char *file, int line, const #define EO_OBJ_POINTER(obj_id, obj) \ _Eo_Object *obj; \ do { \ - obj = _eo_obj_pointer_get((Eo_Id)obj_id); \ + obj = _eo_obj_pointer_get((Eo_Id)obj_id, __FUNCTION__, __FILE__, __LINE__); \ + } while (0) + +#define EO_OBJ_POINTER_PROXY(obj_id, obj) \ + _Eo_Object *obj; \ + do { \ + obj = _eo_obj_pointer_get((Eo_Id)obj_id, func_name, file, line); \ } while (0) #define EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, ret) \ _Eo_Object *obj; \ do { \ - obj = _eo_obj_pointer_get((Eo_Id)obj_id); \ + obj = _eo_obj_pointer_get((Eo_Id)obj_id, __FUNCTION__, __FILE__, __LINE__); \ + if (!obj) return (ret); \ + } while (0) + +/* reports as another function using func_name, file and line variables */ +#define EO_OBJ_POINTER_RETURN_VAL_PROXY(obj_id, obj, ret) \ + _Eo_Object *obj; \ + do { \ + obj = _eo_obj_pointer_get((Eo_Id)obj_id, func_name, file, line); \ if (!obj) return (ret); \ } while (0) #define EO_OBJ_POINTER_RETURN(obj_id, obj) \ _Eo_Object *obj; \ do { \ - obj = _eo_obj_pointer_get((Eo_Id)obj_id); \ + obj = _eo_obj_pointer_get((Eo_Id)obj_id, __FUNCTION__, __FILE__, __LINE__); \ + if (!obj) return; \ + } while (0) + +#define EO_OBJ_POINTER_RETURN_PROXY(obj_id, obj) \ + _Eo_Object *obj; \ + do { \ + obj = _eo_obj_pointer_get((Eo_Id)obj_id, func_name, file, line); \ if (!obj) return; \ } while (0) #define EO_OBJ_POINTER_GOTO(obj_id, obj, label) \ _Eo_Object *obj; \ do { \ - obj = _eo_obj_pointer_get((Eo_Id)obj_id); \ + obj = _eo_obj_pointer_get((Eo_Id)obj_id, __FUNCTION__, __FILE__, __LINE__); \ + if (!obj) goto label; \ + } while (0) + +#define EO_OBJ_POINTER_GOTO_PROXY(obj_id, obj, label) \ + _Eo_Object *obj; \ + do { \ + obj = _eo_obj_pointer_get((Eo_Id)obj_id, func_name, file, line); \ if (!obj) goto label; \ } while (0) #define EO_CLASS_POINTER(klass_id, klass) \ _Efl_Class *klass; \ do { \ - klass = _eo_class_pointer_get(klass_id); \ + klass = _eo_class_pointer_get(klass_id, __FUNCTION__, __FILE__, __LINE__); \ + } while (0) + +#define EO_CLASS_POINTER_PROXY(klass_id, klass) \ + _Efl_Class *klass; \ + do { \ + klass = _eo_class_pointer_get(klass_id, func_name, file, line); \ } while (0) #define EO_CLASS_POINTER_RETURN_VAL(klass_id, klass, ret) \ _Efl_Class *klass; \ do { \ - klass = _eo_class_pointer_get(klass_id); \ + klass = _eo_class_pointer_get(klass_id, __FUNCTION__, __FILE__, __LINE__); \ + if (!klass) { \ + _EO_POINTER_ERR("Class (%p) is an invalid ref.", klass_id); \ + return ret; \ + } \ + } while (0) + +#define EO_CLASS_POINTER_RETURN_VAL_PROXY(klass_id, klass, ret) \ + _Efl_Class *klass; \ + do { \ + klass = _eo_class_pointer_get(klass_id, func_name, file, line); \ if (!klass) { \ _EO_POINTER_ERR("Class (%p) is an invalid ref.", klass_id); \ return ret; \ @@ -59,7 +101,17 @@ void _eo_pointer_error(const char *func_name, const char *file, int line, const #define EO_CLASS_POINTER_RETURN(klass_id, klass) \ _Efl_Class *klass; \ do { \ - klass = _eo_class_pointer_get(klass_id); \ + klass = _eo_class_pointer_get(klass_id, __FUNCTION__, __FILE__, __LINE__); \ + if (!klass) { \ + _EO_POINTER_ERR("Class (%p) is an invalid ref.", klass_id); \ + return; \ + } \ + } while (0) + +#define EO_CLASS_POINTER_RETURN_PROXY(klass_id, klass) \ + _Efl_Class *klass; \ + do { \ + klass = _eo_class_pointer_get(klass_id, func_name, file, line); \ if (!klass) { \ _EO_POINTER_ERR("Class (%p) is an invalid ref.", klass_id); \ return; \ @@ -69,92 +121,22 @@ void _eo_pointer_error(const char *func_name, const char *file, int line, const #define EO_CLASS_POINTER_GOTO(klass_id, klass, label) \ _Efl_Class *klass; \ do { \ - klass = _eo_class_pointer_get(klass_id); \ + klass = _eo_class_pointer_get(klass_id, __FUNCTION__, __FILE__, __LINE__); \ + if (!klass) goto label; \ + } while (0) + +#define EO_CLASS_POINTER_GOTO_PROXY(klass_id, klass, label) \ + _Efl_Class *klass; \ + do { \ + klass = _eo_class_pointer_get(klass_id, func_name, file, line); \ if (!klass) goto label; \ } while (0) #define EO_OBJ_DONE(obj_id) \ _eo_obj_pointer_done((Eo_Id)obj_id) -#else - -#define EO_OBJ_POINTER(obj_id, obj) \ - _Eo_Object *obj; \ - do { \ - obj = _eo_obj_pointer_get((Eo_Id)obj_id); \ - if (obj && \ - !EINA_MAGIC_CHECK((Eo_Header *) obj, EO_EINA_MAGIC)) { \ - EINA_MAGIC_FAIL((Eo_Header *) obj, EO_EINA_MAGIC); \ - } \ - } while (0) - -#define EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, ret) \ - _Eo_Object *obj; \ - do { \ - obj = _eo_obj_pointer_get((Eo_Id)obj_id); \ - if (!obj) return (ret); \ - EO_MAGIC_RETURN_VAL((Eo_Header *) obj, EO_EINA_MAGIC, ret); \ - } while (0) - -#define EO_OBJ_POINTER_RETURN(obj_id, obj) \ - _Eo_Object *obj; \ - do { \ - obj = _eo_obj_pointer_get((Eo_Id)obj_id); \ - if (!obj) return; \ - EO_MAGIC_RETURN((Eo_Header *) obj, EO_EINA_MAGIC); \ - } while (0) - -#define EO_OBJ_POINTER_GOTO(obj_id, obj, label) \ - _Eo_Object *obj; \ - do { \ - obj = _eo_obj_pointer_get((Eo_Id)obj_id); \ - if (!obj || \ - !EINA_MAGIC_CHECK((Eo_Header *) obj, EO_EINA_MAGIC)) goto label; \ - } while (0) - -#define EO_CLASS_POINTER(klass_id, klass) \ - _Efl_Class *klass; \ - do { \ - klass = _eo_class_pointer_get(klass_id); \ - if (klass && \ - !EINA_MAGIC_CHECK((Eo_Header *) klas, EO_CLASS_EINA_MAGIC)) { \ - EO_MAGIC_FAIL((Eo_Header *) klass, EO_CLASS_EINA_MAGIC); \ - } \ - } while (0) - -#define EO_CLASS_POINTER_RETURN_VAL(klass_id, klass, ret) \ - _Efl_Class *klass; \ - do { \ - klass = _eo_class_pointer_get(klass_id); \ - if (!klass) return (ret); \ - EO_MAGIC_RETURN_VAL((Eo_Header *) klass, EO_CLASS_EINA_MAGIC, ret); \ - } while (0) - -#define EO_CLASS_POINTER_RETURN(klass_id, klass) \ - _Efl_Class *klass; \ - do { \ - klass = _eo_class_pointer_get(klass_id); \ - if (!klass) return; \ - EO_MAGIC_RETURN((Eo_Header *) klass, EO_CLASS_EINA_MAGIC); \ - } while (0) - -#define EO_CLASS_POINTER_GOTO(klass_id, klass, label) \ - _Efl_Class *klass; \ - do { \ - klass = _eo_class_pointer_get(klass_id); \ - if (!klass) goto label; \ - if (klass && \ - !EINA_MAGIC_CHECK((Eo_Header *) klas, EO_CLASS_EINA_MAGIC)) { \ - goto label; - } \ - } while (0) - -#define EO_OBJ_DONE(obj_id) - -#endif - #ifdef EFL_DEBUG -void _eo_print(); +static inline void _eo_print(Eo_Id_Table_Data *tdata); #endif extern Eina_TLS _eo_table_data; diff --git a/src/lib/eo/eo_ptr_indirection.x b/src/lib/eo/eo_ptr_indirection.x index ee965ee552..5e0f7bf376 100644 --- a/src/lib/eo/eo_ptr_indirection.x +++ b/src/lib/eo/eo_ptr_indirection.x @@ -557,6 +557,7 @@ shared_err: return id; #else (void) obj; + (void) parent_id; return MASK_OBJ_TAG; #endif }