Add support for the clang compiler; update RAII_VAR to use BlocksRuntime
RAII_VAR, which is used extensively in Asterisk to manage reference counted resources, uses a GCC extension to automatically invoke a cleanup function when a variable loses scope. While this functionality is incredibly useful and has prevented a large number of memory leaks, it also prevents Asterisk from being compiled with clang. This patch updates the RAII_VAR macro such that it can be compiled with clang. It makes use of the BlocksRuntime, which allows for a closure to be created that performs the actual cleanup. Note that this does not attempt to address the numerous warnings that the clang compiler catches in Asterisk. Much thanks for this patch goes to: * The folks on StackOverflow who asked this question and Leushenko for providing the answer that formed the basis of this code: http://stackoverflow.com/questions/24959440/rewrite-gcc-cleanup-macro-with-nested-function-for-clang * Diederik de Groot, who has been extremely patient in working on getting this patch into Asterisk. Review: https://reviewboard.asterisk.org/r/4370/ ASTERISK-24133 ASTERISK-23666 ASTERISK-20399 ASTERISK-20850 #close Reported by: Diederik de Groot patches: RAII_CLANG.patch uploaded by Diederik de Groot (License 6600) ........ Merged revisions 432807 from http://svn.asterisk.org/svn/asterisk/branches/11 ........ Merged revisions 432808 from http://svn.asterisk.org/svn/asterisk/branches/13 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@432809 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
parent
4115e327ac
commit
29304d10a0
4
Makefile
4
Makefile
|
@ -184,7 +184,7 @@ ifeq ($(findstring -Wall,$(_ASTCFLAGS) $(ASTCFLAGS)),)
|
||||||
_ASTCFLAGS+=-Wall
|
_ASTCFLAGS+=-Wall
|
||||||
endif
|
endif
|
||||||
|
|
||||||
_ASTCFLAGS+=-Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(AST_NESTED_FUNCTIONS) $(DEBUG)
|
_ASTCFLAGS+=-Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(AST_NESTED_FUNCTIONS) $(AST_CLANG_BLOCKS) $(DEBUG)
|
||||||
ADDL_TARGETS=
|
ADDL_TARGETS=
|
||||||
|
|
||||||
ifeq ($(AST_DEVMODE),yes)
|
ifeq ($(AST_DEVMODE),yes)
|
||||||
|
@ -931,7 +931,7 @@ nmenuselect: menuselect/nmenuselect menuselect-tree menuselect.makeopts
|
||||||
-@menuselect/nmenuselect menuselect.makeopts && (echo "menuselect changes saved!"; rm -f channels/h323/Makefile.ast main/asterisk) || echo "menuselect changes NOT saved!"
|
-@menuselect/nmenuselect menuselect.makeopts && (echo "menuselect changes saved!"; rm -f channels/h323/Makefile.ast main/asterisk) || echo "menuselect changes NOT saved!"
|
||||||
|
|
||||||
# options for make in menuselect/
|
# options for make in menuselect/
|
||||||
MAKE_MENUSELECT=CC="$(BUILD_CC)" CXX="" LD="" AR="" RANLIB="" \
|
MAKE_MENUSELECT=CC="$(CC)" CXX="$(CXX)" LD="" AR="" RANLIB="" \
|
||||||
CFLAGS="$(BUILD_CFLAGS)" LDFLAGS="$(BUILD_LDFLAGS)" \
|
CFLAGS="$(BUILD_CFLAGS)" LDFLAGS="$(BUILD_LDFLAGS)" \
|
||||||
$(MAKE) -C menuselect CONFIGURE_SILENT="--silent"
|
$(MAKE) -C menuselect CONFIGURE_SILENT="--silent"
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# From configure.ac Revision: 431093 .
|
# From configure.ac Revision: 432282 .
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.69 for asterisk trunk.
|
# Generated by GNU Autoconf 2.69 for asterisk trunk.
|
||||||
#
|
#
|
||||||
|
@ -687,6 +687,8 @@ PBX_RTLD_NOLOAD
|
||||||
PBX_GLOB_BRACE
|
PBX_GLOB_BRACE
|
||||||
PBX_GLOB_NOMAGIC
|
PBX_GLOB_NOMAGIC
|
||||||
AST_RPATH
|
AST_RPATH
|
||||||
|
AST_CLANG_BLOCKS
|
||||||
|
AST_CLANG_BLOCKS_LIBS
|
||||||
AST_NESTED_FUNCTIONS
|
AST_NESTED_FUNCTIONS
|
||||||
AST_NATIVE_ARCH
|
AST_NATIVE_ARCH
|
||||||
AST_SHADOW_WARNINGS
|
AST_SHADOW_WARNINGS
|
||||||
|
@ -17305,7 +17307,7 @@ fi
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wtrampolines support" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wtrampolines support" >&5
|
||||||
$as_echo_n "checking for -Wtrampolines support... " >&6; }
|
$as_echo_n "checking for -Wtrampolines support... " >&6; }
|
||||||
if $(${CC} -Wtrampolines -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then
|
if $(${CC} -Wtrampolines -Werror -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
$as_echo "yes" >&6; }
|
$as_echo "yes" >&6; }
|
||||||
AST_TRAMPOLINES=-Wtrampolines
|
AST_TRAMPOLINES=-Wtrampolines
|
||||||
|
@ -17374,11 +17376,29 @@ $as_echo "no" >&6; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fnested-functions" >&5
|
|
||||||
$as_echo_n "checking for -fnested-functions... " >&6; }
|
|
||||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
/* end confdefs.h. */
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
choke
|
||||||
|
#endif
|
||||||
|
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_c_try_link "$LINENO"; then :
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc -fnested-functions" >&5
|
||||||
|
$as_echo_n "checking for gcc -fnested-functions... " >&6; }
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
int
|
int
|
||||||
main ()
|
main ()
|
||||||
{
|
{
|
||||||
|
@ -17392,14 +17412,39 @@ if ac_fn_c_try_compile "$LINENO"; then :
|
||||||
$as_echo "no" >&6; }
|
$as_echo "no" >&6; }
|
||||||
AST_NESTED_FUNCTIONS=
|
AST_NESTED_FUNCTIONS=
|
||||||
else
|
else
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: required" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
$as_echo "required" >&6; }
|
$as_echo "yes" >&6; }
|
||||||
AST_NESTED_FUNCTIONS=-fnested-functions
|
AST_NESTED_FUNCTIONS=-fnested-functions
|
||||||
|
|
||||||
fi
|
fi
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for clang -fblocks" >&5
|
||||||
|
$as_echo_n "checking for clang -fblocks... " >&6; }
|
||||||
|
if test "`echo "int main(){return ^{return 42;}();}" | ${CC} -o /dev/null -fblocks -x c - 2>&1`" = ""; then
|
||||||
|
AST_CLANG_BLOCKS_LIBS=""
|
||||||
|
AST_CLANG_BLOCKS="-Wno-unknown-warning-option -fblocks"
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
|
$as_echo "yes" >&6; }
|
||||||
|
elif test "`echo "int main(){return ^{return 42;}();}" | ${CC} -o /dev/null -fblocks -x c -lBlocksRuntime - 2>&1`" = ""; then
|
||||||
|
AST_CLANG_BLOCKS_LIBS="-lBlocksRuntime"
|
||||||
|
AST_CLANG_BLOCKS="-fblocks"
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
|
$as_echo "yes" >&6; }
|
||||||
|
else
|
||||||
|
as_fn_error $? "\"BlocksRuntime is required for clang\"" "$LINENO" 5
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext \
|
||||||
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
|
||||||
# Check whether --enable-rpath was given.
|
# Check whether --enable-rpath was given.
|
||||||
if test "${enable_rpath+set}" = set; then :
|
if test "${enable_rpath+set}" = set; then :
|
||||||
enableval=$enable_rpath; case "${enableval}" in
|
enableval=$enable_rpath; case "${enableval}" in
|
||||||
|
|
35
configure.ac
35
configure.ac
|
@ -1078,7 +1078,7 @@ fi
|
||||||
AC_SUBST(AST_DECLARATION_AFTER_STATEMENT)
|
AC_SUBST(AST_DECLARATION_AFTER_STATEMENT)
|
||||||
|
|
||||||
AC_MSG_CHECKING(for -Wtrampolines support)
|
AC_MSG_CHECKING(for -Wtrampolines support)
|
||||||
if $(${CC} -Wtrampolines -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then
|
if $(${CC} -Wtrampolines -Werror -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
AST_TRAMPOLINES=-Wtrampolines
|
AST_TRAMPOLINES=-Wtrampolines
|
||||||
else
|
else
|
||||||
|
@ -1133,16 +1133,41 @@ fi
|
||||||
AC_SUBST(AST_NATIVE_ARCH)
|
AC_SUBST(AST_NATIVE_ARCH)
|
||||||
|
|
||||||
dnl Nested functions required for RAII implementation
|
dnl Nested functions required for RAII implementation
|
||||||
AC_MSG_CHECKING(for -fnested-functions)
|
AC_LINK_IFELSE(
|
||||||
AC_COMPILE_IFELSE(
|
[AC_LANG_PROGRAM([], [
|
||||||
|
#if defined(__clang__)
|
||||||
|
choke
|
||||||
|
#endif
|
||||||
|
])
|
||||||
|
],[
|
||||||
|
dnl Nested functions required for RAII implementation
|
||||||
|
AC_MSG_CHECKING(for gcc -fnested-functions)
|
||||||
|
AC_COMPILE_IFELSE(
|
||||||
dnl Prototype needed due to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36774
|
dnl Prototype needed due to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36774
|
||||||
[AC_LANG_PROGRAM([], [auto void foo(void); void foo(void) {}])],
|
[AC_LANG_PROGRAM([], [auto void foo(void); void foo(void) {}])],
|
||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
[AST_NESTED_FUNCTIONS=],
|
[AST_NESTED_FUNCTIONS=],
|
||||||
AC_MSG_RESULT(required)
|
AC_MSG_RESULT(yes)
|
||||||
[AST_NESTED_FUNCTIONS=-fnested-functions]
|
[AST_NESTED_FUNCTIONS=-fnested-functions]
|
||||||
|
)
|
||||||
|
AC_SUBST(AST_NESTED_FUNCTIONS)
|
||||||
|
],[
|
||||||
|
AC_MSG_CHECKING(for clang -fblocks)
|
||||||
|
if test "`echo "int main(){return ^{return 42;}();}" | ${CC} -o /dev/null -fblocks -x c - 2>&1`" = ""; then
|
||||||
|
[AST_CLANG_BLOCKS_LIBS=""]
|
||||||
|
[AST_CLANG_BLOCKS="-Wno-unknown-warning-option -fblocks"]
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
elif test "`echo "int main(){return ^{return 42;}();}" | ${CC} -o /dev/null -fblocks -x c -lBlocksRuntime - 2>&1`" = ""; then
|
||||||
|
[AST_CLANG_BLOCKS_LIBS="-lBlocksRuntime"]
|
||||||
|
[AST_CLANG_BLOCKS="-fblocks"]
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
else
|
||||||
|
AC_MSG_ERROR("BlocksRuntime is required for clang")
|
||||||
|
fi
|
||||||
|
AC_SUBST(AST_CLANG_BLOCKS_LIBS)
|
||||||
|
AC_SUBST(AST_CLANG_BLOCKS)
|
||||||
|
]
|
||||||
)
|
)
|
||||||
AC_SUBST(AST_NESTED_FUNCTIONS)
|
|
||||||
|
|
||||||
dnl Check to see if rpath should be set in LDFLAGS
|
dnl Check to see if rpath should be set in LDFLAGS
|
||||||
AC_ARG_ENABLE(rpath,
|
AC_ARG_ENABLE(rpath,
|
||||||
|
|
|
@ -30,7 +30,9 @@
|
||||||
- references to a function that cannot be inlined (for any
|
- references to a function that cannot be inlined (for any
|
||||||
reason that the compiler deems proper) must devolve into an
|
reason that the compiler deems proper) must devolve into an
|
||||||
'extern' reference, instead of 'static', so that multiple
|
'extern' reference, instead of 'static', so that multiple
|
||||||
copies of the function body are not built in different modules
|
copies of the function body are not built in different modules.
|
||||||
|
However, since this doesn't work for clang, we go with 'static'
|
||||||
|
anyway and hope for the best!
|
||||||
- when LOW_MEMORY is defined, inlining should be disabled
|
- when LOW_MEMORY is defined, inlining should be disabled
|
||||||
completely, even if the compiler is configured to support it
|
completely, even if the compiler is configured to support it
|
||||||
|
|
||||||
|
@ -46,8 +48,12 @@
|
||||||
#if !defined(LOW_MEMORY) && !defined(DISABLE_INLINE)
|
#if !defined(LOW_MEMORY) && !defined(DISABLE_INLINE)
|
||||||
|
|
||||||
#if !defined(AST_API_MODULE)
|
#if !defined(AST_API_MODULE)
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define AST_INLINE_API(hdr, body) static hdr; static inline hdr body
|
||||||
|
#else /* if defined(__clang__) */
|
||||||
#define AST_INLINE_API(hdr, body) hdr; extern inline hdr body
|
#define AST_INLINE_API(hdr, body) hdr; extern inline hdr body
|
||||||
#else
|
#endif
|
||||||
|
#else /* if !defined(AST_API_MODULE) */
|
||||||
#define AST_INLINE_API(hdr, body) hdr; hdr body
|
#define AST_INLINE_API(hdr, body) hdr; hdr body
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1005,12 +1005,33 @@ char *ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size);
|
||||||
* }
|
* }
|
||||||
* \endcode
|
* \endcode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
|
||||||
|
#if defined(__has_feature) && __has_feature(blocks)
|
||||||
|
typedef void (^_raii_cleanup_block_t)(void);
|
||||||
|
static inline void _raii_cleanup_block(_raii_cleanup_block_t *b) { (*b)(); }
|
||||||
|
|
||||||
|
#define RAII_VAR(vartype, varname, initval, dtor) \
|
||||||
|
_raii_cleanup_block_t _raii_cleanup_ ## varname __attribute__((cleanup(_raii_cleanup_block),unused)) = NULL; \
|
||||||
|
vartype varname = initval; \
|
||||||
|
_raii_cleanup_ ## varname = ^{ dtor(varname); }
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "CLANG must support the 'blocks' feature to compile Asterisk."
|
||||||
|
#endif /* #if defined(__has_feature) && __has_feature(blocks) */
|
||||||
|
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
|
||||||
#define RAII_VAR(vartype, varname, initval, dtor) \
|
#define RAII_VAR(vartype, varname, initval, dtor) \
|
||||||
/* Prototype needed due to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36774 */ \
|
|
||||||
auto void _dtor_ ## varname (vartype * v); \
|
auto void _dtor_ ## varname (vartype * v); \
|
||||||
void _dtor_ ## varname (vartype * v) { dtor(*v); } \
|
void _dtor_ ## varname (vartype * v) { dtor(*v); } \
|
||||||
vartype varname __attribute__((cleanup(_dtor_ ## varname))) = (initval)
|
vartype varname __attribute__((cleanup(_dtor_ ## varname))) = (initval)
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "Cannot compile Asterisk: unknown and unsupported compiler."
|
||||||
|
#endif /* #if __GNUC__ */
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Asterisk wrapper around crypt(3).
|
* \brief Asterisk wrapper around crypt(3).
|
||||||
*
|
*
|
||||||
|
|
|
@ -40,6 +40,7 @@ AST_LIBS+=$(JANSSON_LIB)
|
||||||
AST_LIBS+=$(URIPARSER_LIB)
|
AST_LIBS+=$(URIPARSER_LIB)
|
||||||
AST_LIBS+=$(UUID_LIB)
|
AST_LIBS+=$(UUID_LIB)
|
||||||
AST_LIBS+=$(CRYPT_LIB)
|
AST_LIBS+=$(CRYPT_LIB)
|
||||||
|
AST_LIBS+=$(AST_CLANG_BLOCKS_LIBS)
|
||||||
|
|
||||||
ifneq ($(findstring $(OSARCH), linux-gnu uclinux linux-uclibc kfreebsd-gnu),)
|
ifneq ($(findstring $(OSARCH), linux-gnu uclinux linux-uclibc kfreebsd-gnu),)
|
||||||
ifneq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),)
|
ifneq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),)
|
||||||
|
|
|
@ -109,6 +109,8 @@ AST_TRAMPOLINES=@AST_TRAMPOLINES@
|
||||||
AST_NO_STRICT_OVERFLOW=@AST_NO_STRICT_OVERFLOW@
|
AST_NO_STRICT_OVERFLOW=@AST_NO_STRICT_OVERFLOW@
|
||||||
AST_SHADOW_WARNINGS=@AST_SHADOW_WARNINGS@
|
AST_SHADOW_WARNINGS=@AST_SHADOW_WARNINGS@
|
||||||
AST_NESTED_FUNCTIONS=@AST_NESTED_FUNCTIONS@
|
AST_NESTED_FUNCTIONS=@AST_NESTED_FUNCTIONS@
|
||||||
|
AST_CLANG_BLOCKS=@AST_CLANG_BLOCKS@
|
||||||
|
AST_CLANG_BLOCKS_LIBS=@AST_CLANG_BLOCKS_LIBS@
|
||||||
AST_RPATH=@AST_RPATH@
|
AST_RPATH=@AST_RPATH@
|
||||||
AST_FORTIFY_SOURCE=@AST_FORTIFY_SOURCE@
|
AST_FORTIFY_SOURCE=@AST_FORTIFY_SOURCE@
|
||||||
AST_MARCH_NATIVE=@AST_MARCH_NATIVE@
|
AST_MARCH_NATIVE=@AST_MARCH_NATIVE@
|
||||||
|
|
Loading…
Reference in New Issue