+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
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 */
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,
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
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
/* 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;
h->alignment_mask)))
{
new_chunk->prev = old_chunk->prev;
- CALL_FREEFUN (h, old_chunk);
+ call_freefun (h, old_chunk);
}
h->object_base = object_base;
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. */
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
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
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__;
/* 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)))