From: Guy Harris Date: Sat, 19 Aug 2017 18:25:24 +0000 (-0700) Subject: Handle attributes for function pointers by checking the compiler version. X-Git-Tag: tcpdump-4.99-bp~2033 X-Git-Url: https://git.tcpdump.org/tcpdump/commitdiff_plain/3dc736d939536bcd843597cb655fcba28268705c Handle attributes for function pointers by checking the compiler version. Handle attributes for function pointers the same way we handle attributes for functions, by explicitly checking for the compiler version with #if rather than with a configure script check. That's one fewer thing that, if you're not using autoconf, has to be done in some other fashion. While we're at it, put NORETURN in the right place to have it work with Microsoft Visual Studio as well as various UN*X compilers. --- diff --git a/aclocal.m4 b/aclocal.m4 index cfd59afd..a0031412 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1233,96 +1233,6 @@ fi AC_MSG_RESULT($ac_cv___attribute___unused) ]) -dnl -dnl Test whether __attribute__((format)) can be used without warnings -dnl - -AC_DEFUN(AC_C___ATTRIBUTE___FORMAT, [ -AC_MSG_CHECKING([whether __attribute__((format)) can be used without warnings]) -AC_CACHE_VAL(ac_cv___attribute___format, [ -save_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors" -AC_COMPILE_IFELSE([ - AC_LANG_SOURCE([[ -#include - -extern int foo(const char *fmt, ...) - __attribute__ ((format (printf, 1, 2))); - -int -main(int argc, char **argv) -{ - foo("%s", "test"); -} - ]])], -ac_cv___attribute___format=yes, -ac_cv___attribute___format=no)]) -CFLAGS="$save_CFLAGS" -if test "$ac_cv___attribute___format" = "yes"; then - AC_DEFINE(__ATTRIBUTE___FORMAT_OK, 1, - [define if your compiler allows __attribute__((format)) without a warning]) -fi -AC_MSG_RESULT($ac_cv___attribute___format) -]) - -dnl -dnl Test whether __attribute__((format)) can be applied to function -dnl pointers -dnl - -AC_DEFUN(AC_C___ATTRIBUTE___FORMAT_FUNCTION_POINTER, [ -AC_MSG_CHECKING([whether __attribute__((format)) can be applied to function pointers]) -AC_CACHE_VAL(ac_cv___attribute___format_function_pointer, [ -AC_COMPILE_IFELSE([ - AC_LANG_SOURCE([[ -#include - -extern int (*foo)(const char *fmt, ...) - __attribute__ ((format (printf, 1, 2))); - -int -main(int argc, char **argv) -{ - (*foo)("%s", "test"); -} - ]])], -ac_cv___attribute___format_function_pointer=yes, -ac_cv___attribute___format_function_pointer=no)]) -if test "$ac_cv___attribute___format_function_pointer" = "yes"; then - AC_DEFINE(__ATTRIBUTE___FORMAT_OK_FOR_FUNCTION_POINTERS, 1, - [define if your compiler allows __attribute__((format)) to be applied to function pointers]) -fi -AC_MSG_RESULT($ac_cv___attribute___format_function_pointer) -]) - -AC_DEFUN(AC_C___ATTRIBUTE___NORETURN_FUNCTION_POINTER, [ -AC_MSG_CHECKING([whether __attribute__((noreturn)) can be applied to function pointers without warnings]) -AC_CACHE_VAL(ac_cv___attribute___noreturn_function_pointer, [ -save_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors" -AC_COMPILE_IFELSE([ - AC_LANG_SOURCE([[ -#include - -extern int (*foo)(int i) - __attribute__ ((noreturn)); - -int -main(int argc, char **argv) -{ - (*foo)(1); -} - ]])], -ac_cv___attribute___noreturn_function_pointer=yes, -ac_cv___attribute___noreturn_function_pointer=no)]) -CFLAGS="$save_CFLAGS" -if test "$ac_cv___attribute___noreturn_function_pointer" = "yes"; then - AC_DEFINE(__ATTRIBUTE___NORETURN_OK_FOR_FUNCTION_POINTERS, 1, - [define if your compiler allows __attribute__((noreturn)) to be applied to function pointers]) -fi -AC_MSG_RESULT($ac_cv___attribute___noreturn_function_pointer) -]) - dnl dnl Test whether __attribute__((fallthrough)) can be used without warnings dnl diff --git a/config.h.in b/config.h.in index 6388afdc..6adf589f 100644 --- a/config.h.in +++ b/config.h.in @@ -335,17 +335,6 @@ warning */ #undef __ATTRIBUTE___FALLTHROUGH_OK -/* define if your compiler allows __attribute__((format)) without a warning */ -#undef __ATTRIBUTE___FORMAT_OK - -/* define if your compiler allows __attribute__((format)) to be applied to - function pointers */ -#undef __ATTRIBUTE___FORMAT_OK_FOR_FUNCTION_POINTERS - -/* define if your compiler allows __attribute__((noreturn)) to be applied to - function pointers */ -#undef __ATTRIBUTE___NORETURN_OK_FOR_FUNCTION_POINTERS - /* to handle Ultrix compilers that don't support const in prototypes */ #undef const diff --git a/configure b/configure index a369590d..64b05e0e 100755 --- a/configure +++ b/configure @@ -3670,131 +3670,6 @@ fi $as_echo "$ac_cv___attribute___unused" >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __attribute__((noreturn)) can be applied to function pointers without warnings" >&5 -$as_echo_n "checking whether __attribute__((noreturn)) can be applied to function pointers without warnings... " >&6; } -if ${ac_cv___attribute___noreturn_function_pointer+:} false; then : - $as_echo_n "(cached) " >&6 -else - -save_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - -#include - -extern int (*foo)(int i) - __attribute__ ((noreturn)); - -int -main(int argc, char **argv) -{ - (*foo)(1); -} - -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv___attribute___noreturn_function_pointer=yes -else - ac_cv___attribute___noreturn_function_pointer=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi - -CFLAGS="$save_CFLAGS" -if test "$ac_cv___attribute___noreturn_function_pointer" = "yes"; then - -$as_echo "#define __ATTRIBUTE___NORETURN_OK_FOR_FUNCTION_POINTERS 1" >>confdefs.h - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv___attribute___noreturn_function_pointer" >&5 -$as_echo "$ac_cv___attribute___noreturn_function_pointer" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __attribute__((format)) can be used without warnings" >&5 -$as_echo_n "checking whether __attribute__((format)) can be used without warnings... " >&6; } -if ${ac_cv___attribute___format+:} false; then : - $as_echo_n "(cached) " >&6 -else - -save_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - -#include - -extern int foo(const char *fmt, ...) - __attribute__ ((format (printf, 1, 2))); - -int -main(int argc, char **argv) -{ - foo("%s", "test"); -} - -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv___attribute___format=yes -else - ac_cv___attribute___format=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi - -CFLAGS="$save_CFLAGS" -if test "$ac_cv___attribute___format" = "yes"; then - -$as_echo "#define __ATTRIBUTE___FORMAT_OK 1" >>confdefs.h - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv___attribute___format" >&5 -$as_echo "$ac_cv___attribute___format" >&6; } - - if test "$ac_cv___attribute___format" = "yes"; then - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __attribute__((format)) can be applied to function pointers" >&5 -$as_echo_n "checking whether __attribute__((format)) can be applied to function pointers... " >&6; } -if ${ac_cv___attribute___format_function_pointer+:} false; then : - $as_echo_n "(cached) " >&6 -else - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - -#include - -extern int (*foo)(const char *fmt, ...) - __attribute__ ((format (printf, 1, 2))); - -int -main(int argc, char **argv) -{ - (*foo)("%s", "test"); -} - -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv___attribute___format_function_pointer=yes -else - ac_cv___attribute___format_function_pointer=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi - -if test "$ac_cv___attribute___format_function_pointer" = "yes"; then - -$as_echo "#define __ATTRIBUTE___FORMAT_OK_FOR_FUNCTION_POINTERS 1" >>confdefs.h - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv___attribute___format_function_pointer" >&5 -$as_echo "$ac_cv___attribute___format_function_pointer" >&6; } - - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __attribute__((fallthrough)) can be used without warnings" >&5 $as_echo_n "checking whether __attribute__((fallthrough)) can be used without warnings... " >&6; } if ${ac_cv___attribute___fallthrough+:} false; then : diff --git a/configure.in b/configure.in index a7b879fc..b342468e 100644 --- a/configure.in +++ b/configure.in @@ -25,11 +25,6 @@ AC_LBL_C_INLINE AC_C___ATTRIBUTE__ if test "$ac_cv___attribute__" = "yes"; then AC_C___ATTRIBUTE___UNUSED - AC_C___ATTRIBUTE___NORETURN_FUNCTION_POINTER - AC_C___ATTRIBUTE___FORMAT - if test "$ac_cv___attribute___format" = "yes"; then - AC_C___ATTRIBUTE___FORMAT_FUNCTION_POINTER - fi AC_C___ATTRIBUTE___FALLTHROUGH fi diff --git a/funcattrs.h b/funcattrs.h index 63d3f565..bea98634 100644 --- a/funcattrs.h +++ b/funcattrs.h @@ -76,13 +76,25 @@ * HP aCC A.06.10 and later. */ #define NORETURN __attribute((noreturn)) + + /* + * However, GCC didn't support that for function *pointers* until GCC + * 4.1.0; see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3481. + */ + #if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) < 401)) + #define NORETURN_FUNCPTR + #else + #define NORETURN_FUNCPTR __attribute((noreturn)) + #endif #elif defined(_MSC_VER) /* * MSVC. */ #define NORETURN __declspec(noreturn) + #define NORETURN_FUNCPTR __declspec(noreturn) #else #define NORETURN + #define NORETURN_FUNCPTR #endif /* @@ -101,8 +113,19 @@ * or HP aCC A.06.10 and later. */ #define PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y))) + + /* + * However, GCC didn't support that for function *pointers* until GCC + * 4.1.0; see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3481. + */ + #if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) < 401)) + #define PRINTFLIKE_FUNCPTR(x,y) + #else + #define PRINTFLIKE_FUNCPTR(x,y) __attribute__((__format__(__printf__,x,y))) + #endif #else #define PRINTFLIKE(x,y) + #define PRINTFLIKE_FUNCPTR(x,y) #endif /* diff --git a/machdep.c b/machdep.c index 1f086161..df16c6e2 100644 --- a/machdep.c +++ b/machdep.c @@ -31,20 +31,12 @@ */ #include -#ifndef HAVE___ATTRIBUTE__ -#define __attribute__(x) -#endif /* HAVE___ATTRIBUTE__ */ - #ifdef __osf__ #include #include #if !defined(HAVE_SNPRINTF) -int snprintf(char *, size_t, const char *, ...) -#ifdef __ATTRIBUTE___FORMAT_OK - __attribute__((format(printf, 3, 4))) -#endif /* __ATTRIBUTE___FORMAT_OK */ - ; +int snprintf(char *, size_t, const char *, ...) PRINTFLIKE(3, 4); #endif /* !defined(HAVE_SNPRINTF) */ #endif /* __osf__ */ diff --git a/netdissect.h b/netdissect.h index 899e4b62..26d6d47b 100644 --- a/netdissect.h +++ b/netdissect.h @@ -186,27 +186,15 @@ struct netdissect_options { /* pointer to function to do regular output */ int (*ndo_printf)(netdissect_options *, const char *fmt, ...) -#ifdef __ATTRIBUTE___FORMAT_OK_FOR_FUNCTION_POINTERS - __attribute__ ((format (printf, 2, 3))) -#endif - ; + PRINTFLIKE_FUNCPTR(2, 3); /* pointer to function to output errors */ - void (*ndo_error)(netdissect_options *, - const char *fmt, ...) -#ifdef __ATTRIBUTE___NORETURN_OK_FOR_FUNCTION_POINTERS - __attribute__ ((noreturn)) -#endif /* __ATTRIBUTE___NORETURN_OK_FOR_FUNCTION_POINTERS */ -#ifdef __ATTRIBUTE___FORMAT_OK_FOR_FUNCTION_POINTERS - __attribute__ ((format (printf, 2, 3))) -#endif /* __ATTRIBUTE___FORMAT_OK_FOR_FUNCTION_POINTERS */ - ; + void NORETURN_FUNCPTR (*ndo_error)(netdissect_options *, + const char *fmt, ...) + PRINTFLIKE_FUNCPTR(2, 3); /* pointer to function to output warnings */ void (*ndo_warning)(netdissect_options *, const char *fmt, ...) -#ifdef __ATTRIBUTE___FORMAT_OK_FOR_FUNCTION_POINTERS - __attribute__ ((format (printf, 2, 3))) -#endif - ; + PRINTFLIKE_FUNCPTR(2, 3); }; #define PT_VAT 1 /* Visual Audio Tool */ diff --git a/print.c b/print.c index 15468d6f..20d8ab51 100644 --- a/print.c +++ b/print.c @@ -226,9 +226,9 @@ static const struct printer printers[] = { static void ndo_default_print(netdissect_options *ndo, const u_char *bp, u_int length); -static void ndo_error(netdissect_options *ndo, - FORMAT_STRING(const char *fmt), ...) - NORETURN PRINTFLIKE(2, 3); +static void NORETURN ndo_error(netdissect_options *ndo, + FORMAT_STRING(const char *fmt), ...) + PRINTFLIKE(2, 3); static void ndo_warning(netdissect_options *ndo, FORMAT_STRING(const char *fmt), ...) PRINTFLIKE(2, 3); diff --git a/tcpdump.c b/tcpdump.c index 86ccc50c..270f79b4 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -185,17 +185,17 @@ cap_channel_t *capdns; #endif /* Forwards */ -static void error(FORMAT_STRING(const char *), ...) NORETURN PRINTFLIKE(1, 2); +static NORETURN void error(FORMAT_STRING(const char *), ...) PRINTFLIKE(1, 2); static void warning(FORMAT_STRING(const char *), ...) PRINTFLIKE(1, 2); -static void exit_tcpdump(int) NORETURN; +static NORETURN void exit_tcpdump(int); static RETSIGTYPE cleanup(int); static RETSIGTYPE child_cleanup(int); static void print_version(void); static void print_usage(void); -static void show_tstamp_types_and_exit(pcap_t *, const char *device) NORETURN; -static void show_dlts_and_exit(pcap_t *, const char *device) NORETURN; +static NORETURN void show_tstamp_types_and_exit(pcap_t *, const char *device); +static NORETURN void show_dlts_and_exit(pcap_t *, const char *device); #ifdef HAVE_PCAP_FINDALLDEVS -static void show_devices_and_exit (void) NORETURN; +static NORETURN void show_devices_and_exit(void); #endif static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *);