mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-04-12 18:40:23 +08:00
config.h: separate function and function pointer attributes; automate
Separate out function and function pointer attributes, as not all versions of all compilers support both. Have macros related to function attributes auto-generated by autoheader. As a result, rename config.h.in to unconfig.h, to make it more obvious that it is really intended to be included from some C programs. Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
parent
9fbd9fb859
commit
8b6e6bf04f
2
.gitignore
vendored
2
.gitignore
vendored
@ -50,7 +50,7 @@ TAGS
|
||||
/asm/tokhash.c
|
||||
/asm/warnings.c
|
||||
/config/config.h
|
||||
/config/config.h.in
|
||||
/config/unconfig.h
|
||||
/config.log
|
||||
/config.status
|
||||
/configure
|
||||
|
@ -102,7 +102,7 @@ struct lfmt {
|
||||
/*
|
||||
* Called on a warning or error, with the error message.
|
||||
*/
|
||||
void printf_func(2, 3) (*error)(errflags severity, const char *fmt, ...);
|
||||
void printf_func_ptr(2, 3) (*error)(errflags severity, const char *fmt, ...);
|
||||
|
||||
/*
|
||||
* Update the current offset. Used to give the listing generator
|
||||
|
@ -1,10 +0,0 @@
|
||||
/autoconf/aclocal.m4
|
||||
/autoconf/compile
|
||||
/autoconf/config.*
|
||||
/autoconf/install-sh
|
||||
/config/config.h
|
||||
/config/config.h.in
|
||||
/config.log
|
||||
/config.status
|
||||
/configure
|
||||
/Makefile
|
@ -4,14 +4,23 @@ dnl
|
||||
dnl See if this compiler supports the equivalent of a specific gcc
|
||||
dnl attribute on a function, using the __attribute__(()) syntax.
|
||||
dnl All arguments except the attribute name are optional.
|
||||
dnl
|
||||
dnl PA_FUNC_ATTRIBUTE(attribute, attribute_opts, return_type,
|
||||
dnl prototype_args, call_args)
|
||||
dnl prototype_args, call_args, altname)
|
||||
dnl
|
||||
dnl This tests the attribute both on a function pointer and on a
|
||||
dnl direct function, as some gcc [and others?] versions have problems
|
||||
dnl with attributes on function pointers, and we might as well check both.
|
||||
dnl --------------------------------------------------------------------------
|
||||
AC_DEFUN([PA_FUNC_ATTRIBUTE],
|
||||
AC_DEFUN([_PA_FUNC_ATTRIBUTE],
|
||||
[AC_MSG_CHECKING([if $CC supports the $1 function attribute])
|
||||
m4_define([_pa_faa],ifelse([$2],[],[],[($2)]))
|
||||
m4_define([_pa_fam],ifelse([$2],[],[],[(m4_join([,],m4_for(_pa_n,1,m4_count($2),1,[m4_quote([x]_pa_n),])))]))
|
||||
m4_define([_pa_suf],ifelse([$2],[],[],[m4_count($2)]))
|
||||
m4_define([_pa_mac],ifelse([$6],[],[$1_func]_pa_suf,[$6]))
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||
AC_INCLUDES_DEFAULT
|
||||
extern ifelse([$3],[],[void *],[$3]) __attribute__(($1$2))
|
||||
extern ifelse([$3],[],[void *],[$3]) __attribute__(([$1]_pa_faa))
|
||||
bar(ifelse([$4],[],[int],[$4]));
|
||||
ifelse([$3],[],[void *],[$3]) foo(void);
|
||||
ifelse([$3],[],[void *],[$3]) foo(void)
|
||||
@ -21,7 +30,60 @@ ifelse([$3],[],[void *],[$3]) foo(void)
|
||||
}
|
||||
])],
|
||||
[AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(PA_SYM([HAVE_FUNC_ATTRIBUTE_],[$1]), 1,
|
||||
AC_DEFINE(PA_SYM([HAVE_FUNC_ATTRIBUTE],_pa_suf,[_$1]), 1,
|
||||
[Define to 1 if your compiler supports __attribute__(($1)) on functions])],
|
||||
[AC_MSG_RESULT([no])])
|
||||
AH_BOTTOM(m4_quote(m4_join([],
|
||||
[#ifndef ],_pa_mac,[
|
||||
# ifdef ],PA_SYM([HAVE_FUNC_ATTRIBUTE],_pa_suf,[_$1]),[
|
||||
# define ],_pa_mac,m4_quote(_pa_fam),[ __attribute__(($1],m4_quote(_pa_fam),[))
|
||||
# else
|
||||
# define ],_pa_mac,m4_quote(_pa_fam),[
|
||||
# endif
|
||||
#endif])))
|
||||
])
|
||||
|
||||
AC_DEFUN([_PA_FUNC_PTR_ATTRIBUTE],
|
||||
[AC_MSG_CHECKING([if $CC supports the $1 function attribute on pointers])
|
||||
m4_define([_pa_faa],ifelse([$2],[],[],[($2)]))
|
||||
m4_define([_pa_fam],ifelse([$2],[],[],[(m4_join([,],m4_for(_pa_n,1,m4_count($2),1,[m4_quote([x]_pa_n),])))]))
|
||||
m4_define([_pa_suf],ifelse([$2],[],[],[m4_count($2)]))
|
||||
m4_define([_pa_mac],ifelse([$6],[],[$1_func]_pa_suf,[$6])_ptr)
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||
AC_INCLUDES_DEFAULT
|
||||
extern ifelse([$3],[],[void *],[$3]) __attribute__(([$1]_pa_faa))
|
||||
(*bar1)(ifelse([$4],[],[int],[$4]));
|
||||
ifelse([$3],[],[void *],[$3]) foo1(void);
|
||||
ifelse([$3],[],[void *],[$3]) foo1(void)
|
||||
{
|
||||
ifelse([$3],[void],[],[return])
|
||||
bar1(ifelse([$5],[],[1],[$5]));
|
||||
}
|
||||
|
||||
typedef ifelse([$3],[],[void *],[$3]) __attribute__(([$1]_pa_faa))
|
||||
(*bar_t)(ifelse([$4],[],[int],[$4]));
|
||||
extern bar_t bar2;
|
||||
ifelse([$3],[],[void *],[$3]) foo2(void);
|
||||
ifelse([$3],[],[void *],[$3]) foo2(void)
|
||||
{
|
||||
ifelse([$3],[void],[],[return])
|
||||
bar2(ifelse([$5],[],[1],[$5]));
|
||||
}
|
||||
])],
|
||||
[AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(PA_SYM([HAVE_FUNC_PTR_ATTRIBUTE],_pa_suf,[_$1]), 1,
|
||||
[Define to 1 if your compiler supports __attribute__(($1)) on function pointers])],
|
||||
[AC_MSG_RESULT([no])])
|
||||
AH_BOTTOM(m4_quote(m4_join([],
|
||||
[#ifndef ],_pa_mac,[
|
||||
# ifdef ],PA_SYM([HAVE_FUNC_PTR_ATTRIBUTE],_pa_suf,[_$1]),[
|
||||
# define ],_pa_mac,m4_quote(_pa_fam),[ __attribute__(($1],m4_quote(_pa_fam),[))
|
||||
# else
|
||||
# define ],_pa_mac,m4_quote(_pa_fam),[
|
||||
# endif
|
||||
#endif])))
|
||||
])
|
||||
|
||||
AC_DEFUN([PA_FUNC_ATTRIBUTE],
|
||||
[_PA_FUNC_ATTRIBUTE([$1],[$2],[$3],[$4],[$5],[$6])
|
||||
_PA_FUNC_PTR_ATTRIBUTE([$1],[$2],[$3],[$4],[$5],[$6])])
|
||||
|
@ -4,6 +4,9 @@ dnl
|
||||
dnl See if this compiler supports __attribute__((error("foo")))
|
||||
dnl The generic version of this doesn't work as it makes the compiler
|
||||
dnl throw an error by design.
|
||||
dnl
|
||||
dnl This doesn't use a function pointer because there is no need:
|
||||
dnl the error function will never be a function pointer.
|
||||
dnl --------------------------------------------------------------------------
|
||||
AC_DEFUN([PA_FUNC_ATTRIBUTE_ERROR],
|
||||
[AC_MSG_CHECKING([if $CC supports the error function attribute])
|
||||
|
@ -4,4 +4,5 @@ dnl
|
||||
dnl Convert a (semi-) arbitrary string to a CPP symbol
|
||||
dnl --------------------------------------------------------------------------
|
||||
AC_DEFUN([PA_SYM],
|
||||
[m4_normalize([$1])m4_bpatsubsts(m4_toupper([$2]),[[^ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]+],[_],[^._?\(.*\)_.$],[[\1]])])
|
||||
[m4_bpatsubsts(m4_quote(m4_toupper([$*])),
|
||||
[,],[],[[^ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]+],[_],[^._?\(.*\)_.$],[[\1]])])
|
||||
|
@ -35,7 +35,7 @@
|
||||
* config/msvc.h
|
||||
*
|
||||
* Compiler definitions for Microsoft Visual C++;
|
||||
* instead of config.h.in. See config.h.in for the
|
||||
* instead of unconfig.h. See config.h.in for the
|
||||
* variables which can be defined here.
|
||||
*
|
||||
* MSDN seems to have information back to Visual Studio 2003, so aim
|
||||
|
15
configure.ac
15
configure.ac
@ -1,8 +1,8 @@
|
||||
dnl Process this file with autoconf 2.69 or later to produce
|
||||
dnl a configure script.
|
||||
AC_PREREQ(2.69)
|
||||
AC_INIT(config/config.h.in)
|
||||
AC_CONFIG_HEADERS(config/config.h)
|
||||
AC_INIT([config/undef.h])
|
||||
AC_CONFIG_HEADERS([config/config.h:config/unconfig.h])
|
||||
AC_PREFIX_PROGRAM(nasm)
|
||||
AC_CONFIG_AUX_DIR(autoconf/helpers)
|
||||
|
||||
@ -225,14 +225,15 @@ dnl some other features of gcc.
|
||||
dnl
|
||||
PA_ADD_CFLAGS([-Werror=attributes])
|
||||
PA_FUNC_ATTRIBUTE(noreturn)
|
||||
PA_FUNC_ATTRIBUTE(returns_nonnull)
|
||||
PA_FUNC_ATTRIBUTE(returns_nonnull,,,,,never_null)
|
||||
PA_FUNC_ATTRIBUTE(malloc)
|
||||
PA_FUNC_ATTRIBUTE(alloc_size, (1))
|
||||
PA_FUNC_ATTRIBUTE(sentinel,,, [const char *, ...], ["a","b",NULL])
|
||||
PA_FUNC_ATTRIBUTE(format, [(printf,1,2)], int, [const char *, ...], ["%d",1])
|
||||
PA_FUNC_ATTRIBUTE(alloc_size,[1])
|
||||
PA_FUNC_ATTRIBUTE(alloc_size,[1,2])
|
||||
PA_FUNC_ATTRIBUTE(sentinel,,, [const char *, ...], ["a","b",NULL],end_with_null)
|
||||
PA_FUNC_ATTRIBUTE(format, [printf,1,2], int, [const char *, ...], ["%d",1])
|
||||
PA_FUNC_ATTRIBUTE(const)
|
||||
PA_FUNC_ATTRIBUTE(pure)
|
||||
PA_FUNC_ATTRIBUTE(cold)
|
||||
PA_FUNC_ATTRIBUTE(cold,,,,,unlikely_func)
|
||||
PA_FUNC_ATTRIBUTE_ERROR
|
||||
|
||||
dnl
|
||||
|
@ -56,12 +56,16 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config/config.h"
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1310)
|
||||
# include "config/msvc.h"
|
||||
#elif defined(__WATCOMC__)
|
||||
# include "config/watcom.h"
|
||||
#else
|
||||
# include "config/unknown.h"
|
||||
# if defined(_MSC_VER) && (_MSC_VER >= 1310)
|
||||
# include "config/msvc.h"
|
||||
# elif defined(__WATCOMC__)
|
||||
# include "config/watcom.h"
|
||||
# else
|
||||
# include "config/unknown.h"
|
||||
# endif
|
||||
/* This unconditionally defines some macros we really want */
|
||||
# include "config/unconfig.h"
|
||||
#endif /* Configuration file */
|
||||
|
||||
/* This is required to get the standard <inttypes.h> macros when compiling
|
||||
@ -271,36 +275,15 @@ static inline void *mempcpy(void *dst, const void *src, size_t n)
|
||||
# define unlikely(x) (!!(x))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Hints about malloc-like functions that never return NULL
|
||||
*/
|
||||
#ifdef HAVE_FUNC_ATTRIBUTE_RETURNS_NONNULL
|
||||
# define never_null __attribute__((returns_nonnull))
|
||||
#else
|
||||
# define never_null
|
||||
#endif
|
||||
#define safe_alloc never_null malloc_func
|
||||
#define safe_alloc_ptr never_null_ptr malloc_func_ptr
|
||||
|
||||
#ifdef HAVE_FUNC_ATTRIBUTE_MALLOC
|
||||
# define safe_alloc never_null __attribute__((malloc))
|
||||
#else
|
||||
# define safe_alloc never_null
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FUNC_ATTRIBUTE_ALLOC_SIZE
|
||||
# define safe_malloc(s) safe_alloc __attribute__((alloc_size(s)))
|
||||
# define safe_malloc2(s1,s2) safe_alloc __attribute__((alloc_size(s1,s2)))
|
||||
# define safe_realloc(s) never_null __attribute__((alloc_size(s)))
|
||||
#else
|
||||
# define safe_malloc(s) safe_alloc
|
||||
# define safe_malloc2(s1,s2) safe_alloc
|
||||
# define safe_realloc(s) never_null
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FUNC_ATTRIBUTE_SENTINEL
|
||||
# define end_with_null __attribute__((sentinel))
|
||||
#else
|
||||
# define end_with_null
|
||||
#endif
|
||||
#define safe_malloc(s) safe_alloc alloc_size_func1(s)
|
||||
#define safe_malloc2(s1,s2) safe_alloc alloc_size_func2(s1,s2)
|
||||
#define safe_realloc(s) never_null alloc_size_func1(s)
|
||||
#define safe_malloc_ptr(s) safe_alloc_ptr alloc_size_func1_ptr(s)
|
||||
#define safe_malloc2_ptr(s1,s2) safe_alloc_ptr alloc_size_func2_ptr(s1,s2)
|
||||
#define safe_realloc_ptr(s) never_null_ptr alloc_size_func1_ptr(s)
|
||||
|
||||
/*
|
||||
* How to tell the compiler that a function doesn't return
|
||||
@ -308,59 +291,23 @@ static inline void *mempcpy(void *dst, const void *src, size_t n)
|
||||
#ifdef HAVE_STDNORETURN_H
|
||||
# include <stdnoreturn.h>
|
||||
# define no_return noreturn void
|
||||
#elif defined(HAVE_FUNC_ATTRIBUTE_NORETURN)
|
||||
# define no_return void __attribute__((noreturn))
|
||||
#elif defined(_MSC_VER)
|
||||
# define no_return __declspec(noreturn) void
|
||||
#else
|
||||
# define no_return void
|
||||
#endif
|
||||
|
||||
/*
|
||||
* How to tell the compiler that a function is unlikely to be executed.
|
||||
* This differs from unlikely() in that it is applied to a function call,
|
||||
* not a boolean condition.
|
||||
*/
|
||||
#ifdef HAVE_FUNC_ATTRIBUTE_COLD
|
||||
# define unlikely_func __attribute__((cold))
|
||||
#else
|
||||
# define unlikely_func
|
||||
# define no_return void noreturn_func
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A fatal function is both unlikely and no_return
|
||||
*/
|
||||
#define fatal_func no_return unlikely_func
|
||||
#define fatal_func no_return unlikely_func
|
||||
#define fatal_func_ptr no_return unlikely_func_ptr
|
||||
|
||||
/*
|
||||
* How to tell the compiler that a function takes a printf-like string
|
||||
*/
|
||||
#ifdef HAVE_FUNC_ATTRIBUTE_FORMAT
|
||||
# define printf_func(fmt, list) __attribute__((format(printf, fmt, list)))
|
||||
#else
|
||||
# define printf_func(fmt, list)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* How to tell the compiler that a function is pure arithmetic
|
||||
*/
|
||||
#ifdef HAVE_FUNC_ATTRIBUTE_CONST
|
||||
# define const_func __attribute__((const))
|
||||
#else
|
||||
# define const_func
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function has no side effects, but depends on its arguments,
|
||||
* memory pointed to by its arguments, or global variables.
|
||||
* NOTE: functions that return a value by modifying memory pointed to
|
||||
* by a pointer argument are *NOT* considered pure.
|
||||
*/
|
||||
#ifdef HAVE_FUNC_ATTRIBUTE_PURE
|
||||
# define pure_func __attribute__((pure))
|
||||
#else
|
||||
# define pure_func
|
||||
#endif
|
||||
#define printf_func(fmt, list) format_func3(printf,fmt,list)
|
||||
#define printf_func_ptr(fmt, list) format_func3_ptr(printf,fmt,list)
|
||||
|
||||
/* Determine probabilistically if something is a compile-time constant */
|
||||
#ifdef HAVE___BUILTIN_CONSTANT_P
|
||||
|
Loading…
x
Reference in New Issue
Block a user