mirror of
https://github.com/isar/libmdbx.git
synced 2025-11-07 07:18:56 +08:00
mdbx: изменение log_if_error() ради устранения ложных "may be used uninitialized" предупреждений в LTO-сборках.
При включении LTO анализатор путей выполнения внутри GCC начинает укачивать из-за выражений вида `return LOG_IFERR(MDBX_EINVAL);`
Проблема в том, что несмотря на __builtin_assume() и __builtin_unreachable(), комплятор не хочет
видеть что функция log_if_error() всегда возвращает получаемое значение. А если допустить что значение
будет изменено, то вместо ошибки может быть MDBX_SUCCESS, и тогда в вызывающем как-бы может произойти
обращение к неинициализированным данным, что и беспокоит компилятор.
Например, при сборке mdbx_load:
‘txn_info.txn_space_dirty’ may be used uninitialized [-Wmaybe-uninitialized]
Проэтому проще пойти анализатору навстречу и упростить исходный код.
Теперь код ошибки явно пробрасывается через тело inline-функции, но это
требует 1-2 дополнительных процессорных инструкции на каждое применение
макроса LOG_IFERROR.
Также здесь откатывается коммит 81a8127084.
This commit is contained in:
@@ -197,22 +197,16 @@ int mdbx_dbi_close(MDBX_env *env, MDBX_dbi dbi) {
|
||||
}
|
||||
|
||||
int mdbx_dbi_flags_ex(const MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags, unsigned *state) {
|
||||
if (unlikely(!flags || !state))
|
||||
return LOG_IFERR(MDBX_EINVAL);
|
||||
|
||||
int rc = check_txn(txn, MDBX_TXN_BLOCKED - MDBX_TXN_ERROR - MDBX_TXN_PARKED);
|
||||
if (unlikely(rc != MDBX_SUCCESS)) {
|
||||
*flags = 0;
|
||||
*state = 0;
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
return LOG_IFERR(rc);
|
||||
}
|
||||
|
||||
rc = dbi_check(txn, dbi);
|
||||
if (unlikely(rc != MDBX_SUCCESS)) {
|
||||
*flags = 0;
|
||||
*state = 0;
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
return LOG_IFERR(rc);
|
||||
}
|
||||
|
||||
if (unlikely(!flags || !state))
|
||||
return LOG_IFERR(MDBX_EINVAL);
|
||||
|
||||
*flags = txn->dbs[dbi].flags & DB_PERSISTENT_FLAGS;
|
||||
*state = txn->dbi_state[dbi] & (DBI_FRESH | DBI_CREAT | DBI_DIRTY | DBI_STALE);
|
||||
@@ -230,41 +224,33 @@ static void stat_get(const tree_t *db, MDBX_stat *st, size_t bytes) {
|
||||
}
|
||||
|
||||
__cold int mdbx_dbi_stat(const MDBX_txn *txn, MDBX_dbi dbi, MDBX_stat *dest, size_t bytes) {
|
||||
if (unlikely(!dest))
|
||||
return LOG_IFERR(MDBX_EINVAL);
|
||||
|
||||
int rc = check_txn(txn, MDBX_TXN_BLOCKED);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
goto bailout;
|
||||
return LOG_IFERR(rc);
|
||||
|
||||
rc = dbi_check(txn, dbi);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
goto bailout;
|
||||
return LOG_IFERR(rc);
|
||||
|
||||
const size_t size_before_modtxnid = offsetof(MDBX_stat, ms_mod_txnid);
|
||||
if (unlikely(bytes != sizeof(MDBX_stat)) && bytes != size_before_modtxnid) {
|
||||
rc = MDBX_EINVAL;
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
if (unlikely(txn->flags & MDBX_TXN_BLOCKED)) {
|
||||
rc = MDBX_BAD_TXN;
|
||||
goto bailout;
|
||||
}
|
||||
if (unlikely(txn->flags & MDBX_TXN_BLOCKED))
|
||||
return LOG_IFERR(MDBX_BAD_TXN);
|
||||
|
||||
if (unlikely(txn->dbi_state[dbi] & DBI_STALE)) {
|
||||
rc = tbl_fetch((MDBX_txn *)txn, dbi);
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
goto bailout;
|
||||
return LOG_IFERR(rc);
|
||||
}
|
||||
|
||||
if (unlikely(!dest))
|
||||
return LOG_IFERR(MDBX_EINVAL);
|
||||
|
||||
const size_t size_before_modtxnid = offsetof(MDBX_stat, ms_mod_txnid);
|
||||
if (unlikely(bytes != sizeof(MDBX_stat)) && bytes != size_before_modtxnid)
|
||||
return LOG_IFERR(MDBX_EINVAL);
|
||||
|
||||
dest->ms_psize = txn->env->ps;
|
||||
stat_get(&txn->dbs[dbi], dest, bytes);
|
||||
return MDBX_SUCCESS;
|
||||
|
||||
bailout:
|
||||
memset(dest, 0, bytes);
|
||||
return LOG_IFERR(rc);
|
||||
}
|
||||
|
||||
__cold int mdbx_enumerate_tables(const MDBX_txn *txn, MDBX_table_enum_func *func, void *ctx) {
|
||||
|
||||
Reference in New Issue
Block a user