Commit 127ed6a3 authored by Paul Eggert's avatar Paul Eggert

obstack: avoid potentially-nonportable function casts

* lib/obstack.c (CALL_CHUNKFUN, CALL_FREEFUN):
Remove, replacing with ...
(call_chunkfun, call_freefun): New static functions.
All uses changed.  Avoid potentially-nonportable casts.
(chunkfun_type, freefun_type): Remove typedefs; no longer used.
(_obstack_begin_worker): Omit last two args, since they
rely on potentially-nonportable casts.  All callers changed.
* lib/obstack.h (_OBSTACK_CAST): New macro.
Use it everywhere the old API used a potentially-nonportable cast.
The new API doesn't cast.
(struct obstack): Use unions rather than requiring
potentially-nonportable casts.
(obstack_chunkfun, obstack_freefun): Return void.
parent d15b2da0
2014-11-04 Paul Eggert <eggert@cs.ucla.edu>
obstack: avoid potentially-nonportable function casts
* lib/obstack.c (CALL_CHUNKFUN, CALL_FREEFUN):
Remove, replacing with ...
(call_chunkfun, call_freefun): New static functions.
All uses changed. Avoid potentially-nonportable casts.
(chunkfun_type, freefun_type): Remove typedefs; no longer used.
(_obstack_begin_worker): Omit last two args, since they
rely on potentially-nonportable casts. All callers changed.
* lib/obstack.h (_OBSTACK_CAST): New macro.
Use it everywhere the old API used a potentially-nonportable cast.
The new API doesn't cast.
(struct obstack): Use unions rather than requiring
potentially-nonportable casts.
(obstack_chunkfun, obstack_freefun): Return void.
2014-11-03 Alan Modra <amodra@gmail.com>
obstack: fix macro return values
......@@ -76,41 +76,38 @@
MAX (sizeof (uintmax_t), \
sizeof (void *)))
/* Define a macro that either calls functions with the traditional malloc/free
calling interface, or calls functions with the mmalloc/mfree interface
(that adds an extra first argument), based on the state of use_extra_arg.
For free, do not use ?:, since some compilers, like the MIPS compilers,
do not allow (expr) ? void : void. */
# define CALL_CHUNKFUN(h, size) \
(((h)->use_extra_arg) \
? (*(h)->chunkfun)((h)->extra_arg, (size)) \
: (*(struct _obstack_chunk *(*)(size_t))(h)->chunkfun)((size)))
# define CALL_FREEFUN(h, old_chunk) \
do { \
if ((h)->use_extra_arg) \
(*(h)->freefun)((h)->extra_arg, (old_chunk)); \
else \
(*(void (*)(void *))(h)->freefun)((old_chunk)); \
} while (0)
/* Call functions with either the traditional malloc/free calling
interface, or the mmalloc/mfree interface (that adds an extra first
argument), based on the value of use_extra_arg. */
static void *
call_chunkfun (struct obstack *h, size_t size)
{
if (h->use_extra_arg)
return h->chunkfun.extra (h->extra_arg, size);
else
return h->chunkfun.plain (size);
}
static void
call_freefun (struct obstack *h, void *old_chunk)
{
if (h->use_extra_arg)
h->freefun.extra (h->extra_arg, old_chunk);
else
h->freefun.plain (old_chunk);
}
/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
Objects start on multiples of ALIGNMENT (0 means use default).
CHUNKFUN is the function to use to allocate chunks,
and FREEFUN the function to free them.
Return nonzero if successful, calls obstack_alloc_failed_handler if
allocation fails. */
typedef struct _obstack_chunk * (*chunkfun_type) (void *, size_t);
typedef void (*freefun_type) (void *, struct _obstack_chunk *);
static int
_obstack_begin_worker (struct obstack *h,
_OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment,
chunkfun_type chunkfun, freefun_type freefun)
_OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment)
{
struct _obstack_chunk *chunk; /* points to new chunk */
......@@ -133,12 +130,10 @@ _obstack_begin_worker (struct obstack *h,
size = 4096 - extra;
}
h->chunkfun = chunkfun;
h->freefun = freefun;
h->chunk_size = size;
h->alignment_mask = alignment - 1;
chunk = h->chunk = CALL_CHUNKFUN (h, h->chunk_size);
chunk = h->chunk = call_chunkfun (h, h->chunk_size);
if (!chunk)
(*obstack_alloc_failed_handler) ();
h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
......@@ -157,10 +152,10 @@ _obstack_begin (struct obstack *h,
void *(*chunkfun) (size_t),
void (*freefun) (void *))
{
h->chunkfun.plain = chunkfun;
h->freefun.plain = freefun;
h->use_extra_arg = 0;
return _obstack_begin_worker (h, size, alignment,
(chunkfun_type) chunkfun,
(freefun_type) freefun);
return _obstack_begin_worker (h, size, alignment);
}
int
......@@ -170,11 +165,11 @@ _obstack_begin_1 (struct obstack *h,
void (*freefun) (void *, void *),
void *arg)
{
h->chunkfun.extra = chunkfun;
h->freefun.extra = freefun;
h->extra_arg = arg;
h->use_extra_arg = 1;
return _obstack_begin_worker (h, size, alignment,
(chunkfun_type) chunkfun,
(freefun_type) freefun);
return _obstack_begin_worker (h, size, alignment);
}
/* Allocate a new current chunk for the obstack *H
......@@ -202,7 +197,7 @@ _obstack_newchunk (struct obstack *h, _OBSTACK_SIZE_T length)
/* Allocate and initialize the new chunk. */
if (obj_size <= sum1 && sum1 <= sum2)
new_chunk = CALL_CHUNKFUN (h, new_size);
new_chunk = call_chunkfun (h, new_size);
if (!new_chunk)
(*obstack_alloc_failed_handler)();
h->chunk = new_chunk;
......@@ -225,7 +220,7 @@ _obstack_newchunk (struct obstack *h, _OBSTACK_SIZE_T length)
h->alignment_mask)))
{
new_chunk->prev = old_chunk->prev;
CALL_FREEFUN (h, old_chunk);
call_freefun (h, old_chunk);
}
h->object_base = object_base;
......@@ -276,7 +271,7 @@ _obstack_free (struct obstack *h, void *obj)
while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
{
plp = lp->prev;
CALL_FREEFUN (h, lp);
call_freefun (h, lp);
lp = plp;
/* If we switch chunks, we can't tell whether the new current
chunk contains an empty object, so assume that it may. */
......
......@@ -116,10 +116,12 @@
and "long" for these two types. */
# define _OBSTACK_SIZE_T unsigned int
# define _CHUNK_SIZE_T unsigned long
# define _OBSTACK_CAST(type, expr) ((type) (expr))
#else
/* Version 2 with sane types, especially for 64-bit hosts. */
# define _OBSTACK_SIZE_T size_t
# define _CHUNK_SIZE_T size_t
# define _OBSTACK_CAST(type, expr) (expr)
#endif
/* If B is the base of an object addressed by P, return the result of
......@@ -167,11 +169,19 @@ struct obstack /* control current object in current chunk */
void *p;
} temp; /* Temporary for some macros. */
_OBSTACK_SIZE_T alignment_mask; /* Mask of alignment for each object. */
/* These prototypes vary based on 'use_extra_arg', and we use
casts to the prototypeless function type in all assignments,
but having prototypes here quiets -Wstrict-prototypes. */
struct _obstack_chunk *(*chunkfun) (void *, size_t);
void (*freefun) (void *, struct _obstack_chunk *);
/* These prototypes vary based on 'use_extra_arg'. */
union
{
void *(*plain) (size_t);
void *(*extra) (void *, size_t);
} chunkfun;
union
{
void (*plain) (void *);
void (*extra) (void *, void *);
} freefun;
void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
unsigned use_extra_arg : 1; /* chunk alloc/dealloc funcs take extra arg */
unsigned maybe_empty_object : 1; /* There is a possibility that the current
......@@ -189,11 +199,11 @@ extern void _obstack_newchunk (struct obstack *, _OBSTACK_SIZE_T);
extern void _obstack_free (struct obstack *, void *);
extern int _obstack_begin (struct obstack *,
_OBSTACK_SIZE_T, _OBSTACK_SIZE_T,
void *(*)(size_t), void (*)(void *));
void *(*) (size_t), void (*) (void *));
extern int _obstack_begin_1 (struct obstack *,
_OBSTACK_SIZE_T, _OBSTACK_SIZE_T,
void *(*)(void *, size_t),
void (*)(void *, void *), void *);
void *(*) (void *, size_t),
void (*) (void *, void *), void *);
extern _OBSTACK_SIZE_T _obstack_memory_used (struct obstack *)
__attribute_pure__;
......@@ -228,29 +238,31 @@ extern int obstack_exit_failure;
/* To prevent prototype warnings provide complete argument list. */
#define obstack_init(h) \
_obstack_begin ((h), 0, 0, \
(void *(*)(size_t))obstack_chunk_alloc, \
(void (*)(void *))obstack_chunk_free)
_OBSTACK_CAST (void *(*) (size_t), obstack_chunk_alloc), \
_OBSTACK_CAST (void (*) (void *), obstack_chunk_free))
#define obstack_begin(h, size) \
_obstack_begin ((h), (size), 0, \
(void *(*)(size_t))obstack_chunk_alloc, \
(void (*)(void *))obstack_chunk_free)
_OBSTACK_CAST (void *(*) (size_t), obstack_chunk_alloc), \
_OBSTACK_CAST (void (*) (void *), obstack_chunk_free))
#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
_obstack_begin ((h), (size), (alignment), \
(void *(*)(size_t))(chunkfun), \
(void (*)(void *))(freefun))
_OBSTACK_CAST (void *(*) (size_t), chunkfun), \
_OBSTACK_CAST (void (*) (void *), freefun))
#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
_obstack_begin_1 ((h), (size), (alignment), \
(void *(*)(void *, size_t))(chunkfun), \
(void (*)(void *, void *))(freefun), (arg))
_OBSTACK_CAST (void *(*) (void *, size_t), chunkfun), \
_OBSTACK_CAST (void (*) (void *, void *), freefun), arg)
#define obstack_chunkfun(h, newchunkfun) \
((h)->chunkfun = (struct _obstack_chunk *(*)(void *, size_t))(newchunkfun))
((void) ((h)->chunkfun.extra = _OBSTACK_CAST (void *(*) (void *, size_t), \
newchunkfun)))
#define obstack_freefun(h, newfreefun) \
((h)->freefun = (void (*)(void *, struct _obstack_chunk *))(newfreefun))
((void) ((h)->freefun.extra = _OBSTACK_CAST (void (*) (void *, void *), \
newfreefun)))
#define obstack_1grow_fast(h, achar) ((void) (*((h)->next_free)++ = (achar)))
......
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