1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-04-27 08:43:40 -07:00

Explain how to call mps_root_create_table() safely (avoiding type punning). fix example for mps_root_create_table_masked(). use the recommended approach in qs.c.

Copied from Perforce
 Change: 185223
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2014-04-04 11:49:19 +01:00
parent feaa22a74f
commit 6ef4b6e0c6
4 changed files with 36 additions and 9 deletions

View file

@ -334,7 +334,6 @@ static void *go(void *p, size_t s)
mps_fmt_t format;
mps_chain_t chain;
mps_addr_t base;
mps_addr_t *addr;
testlib_unused(p);
testlib_unused(s);
@ -357,9 +356,7 @@ static void *go(void *p, size_t s)
"RootCreateTable");
base = &activationStack;
addr = base;
die(mps_root_create_table(&actroot, arena, mps_rank_ambig(), 0,
addr, sizeof(QSCell)/sizeof(mps_addr_t)),
die(mps_root_create_table(&actroot, arena, mps_rank_ambig(), 0, base, 1),
"RootCreateTable");
/* makes a random list */

View file

@ -905,6 +905,10 @@ changes size::
3. The order of operations at the end is important: the old root
must be de-registered before its memory is freed.
4. When calling :c:func:`mps_root_create_table`, take care to
avoid undefined behaviour due to :term:`type punning`. See the
:ref:`warning <topic-root-type-pun>`.
.. topics::
:ref:`topic-root`.

View file

@ -205,11 +205,11 @@ Instead, we recommend this approach::
struct foo *fp;
res = mps_alloc(&p, pool, sizeof(struct foo));
if(res) /* handle error case */;
fp = (struct foo *)p;
fp = p;
This is portable because conversion from ``void *`` to any other
:term:`object pointer` type is defined by :ref:`ISO/IEC 9899:1990
<ISO90>` §6.3.2.3.1.
This has defined behaviour because conversion from ``void *`` to any
other :term:`object pointer` type is defined by :ref:`ISO/IEC
9899:1990 <ISO90>` §6.3.2.3.1.
.. index::

View file

@ -514,6 +514,28 @@ Root interface
The registered root description persists until it is destroyed by
calling :c:func:`mps_root_destroy`.
.. _topic-root-type-pun:
.. warning::
The ``base`` argument has type ``mps_addr_t *`` (a typedef for
``void **``) but the table of references most likely has some
other pointer type, ``my_object *`` say. It is tempting to
write::
mps_root_create_table(..., (mps_addr_t *)my_table, ...)
but this is :term:`type punning`, and its behaviour is not
defined in ANSI/ISO Standard C. (GCC and Clang have a warning
flag ``-Wstrict-aliasing`` which detects some errors of this
form.)
To ensure well-defined behaviour, the pointer must be
converted via ``void *`` (or via :c:type:`mps_addr_t`, which
is a typedef for ``void *``), like this::
mps_addr_t base = my_table;
mps_root_create_table(..., base, ...)
.. c:function:: mps_res_t mps_root_create_table_masked(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_addr_t *base, size_t count, mps_word_t mask)
@ -558,13 +580,17 @@ Root interface
mps_res_t res;
mps_root_t root;
mps_addr_t base = symtab;
res = mps_root_create_table_masked(&root, arena,
mps_rank_exact(),
(mps_rm_t)0,
symtab, symtab_size * 2,
base, symtab_size * 2,
(mps_word_t)TAG_MASK);
if (res != MPS_RES_OK) errror("can't create symtab root");
.. warning::
See the warning for :c:func:`mps_root_create_table` above.
.. c:function:: void mps_root_destroy(mps_root_t root)