git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 1/5] compat/obstack: fix -Wcast-function-type warnings

From
SZEDER Gábor <szeder.dev@gmail.com>
Date
Dec 20, 2018, 16:24 UTC
Message-ID
<20181220162452.17732-2-szeder.dev@gmail.com>
In-Reply-To
<20181220162452.17732-1-szeder.dev@gmail.com>

When building Git with GCC 8.2.0 (at least from Homebrew on macOS, DEVELOPER flags enabled) one is greeted with a screenful of compiler errors:

  compat/obstack.c: In function '_obstack_begin':
  compat/obstack.c:162:17: error: cast between incompatible function types from 'void * (*)(long int)' to 'struct _obstack_chunk * (*)(void *, long int)' [-Werror=cast-function-type]
     h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
                   ^
  compat/obstack.c:163:16: error: cast between incompatible function types from 'void (*)(void *)' to 'void (*)(void *, struct _obstack_chunk *)' [-Werror=cast-function-type]
     h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
                  ^
  compat/obstack.c:116:8: error: cast between incompatible function types from 'struct _obstack_chunk * (*)(void *, long int)' to 'struct _obstack_chunk * (*)(long int)' [-Werror=cast-function-type]
      : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
          ^
  compat/obstack.c:168:22: note: in expansion of macro 'CALL_CHUNKFUN'
     chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
                        ^~~~~~~~~~~~~
  <snip>

'struct obstack' stores pointers to two functions to allocate and free "chunks", and depending on how obstack is used, these functions take either one parameter (like standard malloc() and free() do; this is how we use it) or two parameters. Presumably to reduce memory footprint, a single field is used to store the function pointer for both signatures, and then it's casted to the appropriate signature when the function pointer is accessed. These casts between function pointers with different number of parameters are what trigger those compiler errors.

Modify 'struct obstack' to use unions to store function pointers with different signatures, and then use the union member with the appropriate signature when accessing these function pointers. This eliminates the need for those casts, and thus avoids this compiler error.

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
---
 compat/obstack.c | 17 +++++++++--------
 compat/obstack.h | 18 +++++++++++-------
 2 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/compat/obstack.c b/compat/obstack.c
index 4d1d95beeb..dd9504c684 100644
--- a/compat/obstack.c
+++ b/compat/obstack.c
@@ -112,15 +112,15 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
 
 # define CALL_CHUNKFUN(h, size) \
   (((h) -> use_extra_arg) \
-   ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
-   : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
+   ? (*(h)->chunkfun.fn_extra_arg) ((h)->extra_arg, (size)) \
+   : (*(h)->chunkfun.fn) ((size)))
 
 # define CALL_FREEFUN(h, old_chunk) \
   do { \
     if ((h) -> use_extra_arg) \
-      (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
+      (*(h)->freefun.fn_extra_arg) ((h)->extra_arg, (old_chunk)); \
     else \
-      (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
+      (*(h)->freefun.fn) ((old_chunk)); \
   } while (0)
 
 
@@ -159,8 +159,8 @@ _obstack_begin (struct obstack *h,
       size = 4096 - extra;
     }
 
-  h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
-  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+  h->chunkfun.fn = chunkfun;
+  h->freefun.fn = freefun;
   h->chunk_size = size;
   h->alignment_mask = alignment - 1;
   h->use_extra_arg = 0;
@@ -206,8 +206,9 @@ _obstack_begin_1 (struct obstack *h, int size, int alignment,
       size = 4096 - extra;
     }
 
-  h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
-  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+  h->chunkfun.fn_extra_arg = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
+  h->freefun.fn_extra_arg = (void (*) (void *, struct _obstack_chunk *)) freefun;
+
   h->chunk_size = size;
   h->alignment_mask = alignment - 1;
   h->extra_arg = arg;
diff --git a/compat/obstack.h b/compat/obstack.h
index 6bc24b7644..0f9b2232a9 100644
--- a/compat/obstack.h
+++ b/compat/obstack.h
@@ -160,11 +160,15 @@ struct obstack		/* control current object in current chunk */
     void *tempptr;
   } temp;			/* Temporary for some macros.  */
   int   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 *, long);
-  void (*freefun) (void *, struct _obstack_chunk *);
+  /* These prototypes vary based on `use_extra_arg'. */
+  union {
+    struct _obstack_chunk *(*fn_extra_arg) (void *, long);
+    void *(*fn) (long);
+  } chunkfun;
+  union {
+    void (*fn_extra_arg) (void *, struct _obstack_chunk *);
+    void (*fn) (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
@@ -235,10 +239,10 @@ extern void (*obstack_alloc_failed_handler) (void);
 		    (void (*) (void *, void *)) (freefun), (arg))
 
 #define obstack_chunkfun(h, newchunkfun) \
-  ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun))
+  ((h)->chunkfun.fn_extra_arg = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun))
 
 #define obstack_freefun(h, newfreefun) \
-  ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun))
+  ((h)->freefun.fn_extra_arg = (void (*)(void *, struct _obstack_chunk *)) (newfreefun))
 
 #define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = (achar))
 
-- 
2.20.1.151.gec613c4b75
Previous: SZEDER GáborNext: Ævar Arnfjörð Bjarmason
Message 9 of 33 in “On overriding make variables from the environment...”
  1. SZEDER GáborOct 16, 2018
  2. Jonathan NiederOct 16, 2018
  3. SZEDER GáborOct 16, 2018
  4. Jonathan NiederOct 16, 2018
  5. SZEDER GáborOct 17, 2018
  6. Johannes SchindelinOct 18, 2018
  7. Junio C HamanoOct 18, 2018
  8. 0/5 travis-ci: build with the right compilerSZEDER Gábor, Dec 20, 2018
  9. 1/5 compat/obstack: fix -Wcast-function-type warningsSZEDER Gábor, Dec 20, 2018
  10. Ævar Arnfjörð BjarmasonDec 20, 2018
  11. Junio C HamanoJan 10, 2019
  12. SZEDER GáborJan 11, 2019
  13. Junio C HamanoJan 11, 2019
  14. SZEDER GáborJan 11, 2019
  15. SZEDER GáborJan 15, 2019
  16. Jonathan NiederJan 16, 2019
  17. SZEDER GáborJan 17, 2019
  18. Junio C HamanoJan 16, 2019
  19. 2/5 .gitignore: ignore external debug symbols from GCC on macOSSZEDER Gábor, Dec 20, 2018
  20. 3/5 travis-ci: don't be '--quiet' when running the testsSZEDER Gábor, Dec 20, 2018
  21. 5/5 travis-ci: build with the right compilerSZEDER Gábor, Dec 20, 2018
  22. Johannes SchindelinJan 3, 2019
  23. 4/5 travis-ci: switch to Xcode 10.1 macOS imageSZEDER Gábor, Dec 20, 2018
  24. 0/5 travis-ci: build with the right compilerSZEDER Gábor, Jan 17, 2019
  25. 1/5 compat/obstack: fix -Wcast-function-type warningsSZEDER Gábor, Jan 17, 2019
  26. 2/5 .gitignore: ignore external debug symbols from GCC on macOSSZEDER Gábor, Jan 17, 2019
  27. 3/5 travis-ci: don't be '--quiet' when running the testsSZEDER Gábor, Jan 17, 2019
  28. Johannes SchindelinJan 17, 2019
  29. 4/5 travis-ci: switch to Xcode 10.1 macOS imageSZEDER Gábor, Jan 17, 2019
  30. 5/5 travis-ci: build with the right compilerSZEDER Gábor, Jan 17, 2019
  31. Johannes SchindelinJan 17, 2019
  32. SZEDER GáborJan 17, 2019
  33. Johannes SchindelinJan 18, 2019

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.