Skip to content

Commit

Permalink
Handle attributes for function pointers by checking the compiler vers…
Browse files Browse the repository at this point in the history
…ion.

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.
  • Loading branch information
guyharris committed Aug 19, 2017
1 parent 297bf63 commit 3dc736d
Show file tree
Hide file tree
Showing 9 changed files with 37 additions and 265 deletions.
90 changes: 0 additions & 90 deletions aclocal.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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 <stdlib.h>
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 <stdlib.h>
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 <stdlib.h>
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
Expand Down
11 changes: 0 additions & 11 deletions config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
125 changes: 0 additions & 125 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -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 <stdlib.h>
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 <stdlib.h>
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 <stdlib.h>
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 :
Expand Down
5 changes: 0 additions & 5 deletions configure.in
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
23 changes: 23 additions & 0 deletions funcattrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

/*
Expand All @@ -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

/*
Expand Down
10 changes: 1 addition & 9 deletions machdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,12 @@
*/
#include <netdissect-stdinc.h>

#ifndef HAVE___ATTRIBUTE__
#define __attribute__(x)
#endif /* HAVE___ATTRIBUTE__ */

#ifdef __osf__
#include <sys/sysinfo.h>
#include <sys/proc.h>

#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__ */

Expand Down
22 changes: 5 additions & 17 deletions netdissect.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
6 changes: 3 additions & 3 deletions print.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 5 additions & 5 deletions tcpdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down

0 comments on commit 3dc736d

Please sign in to comment.