diff --git a/Makefile b/Makefile index 66a8411eb7..c2e1fba788 100644 --- a/Makefile +++ b/Makefile @@ -184,7 +184,7 @@ ifeq ($(findstring -Wall,$(_ASTCFLAGS) $(ASTCFLAGS)),) _ASTCFLAGS+=-Wall 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= 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!" # 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)" \ $(MAKE) -C menuselect CONFIGURE_SILENT="--silent" diff --git a/configure b/configure index 3a681b564d..c7c0608c92 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac Revision: 431092 . +# From configure.ac Revision: 432281 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for asterisk trunk. # @@ -687,6 +687,8 @@ PBX_RTLD_NOLOAD PBX_GLOB_BRACE PBX_GLOB_NOMAGIC AST_RPATH +AST_CLANG_BLOCKS +AST_CLANG_BLOCKS_LIBS AST_NESTED_FUNCTIONS AST_NATIVE_ARCH AST_SHADOW_WARNINGS @@ -17305,7 +17307,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wtrampolines support" >&5 $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 "yes" >&6; } AST_TRAMPOLINES=-Wtrampolines @@ -17374,11 +17376,29 @@ $as_echo "no" >&6; } 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 /* 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 main () { @@ -17390,16 +17410,41 @@ _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - AST_NESTED_FUNCTIONS= + AST_NESTED_FUNCTIONS= else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: required" >&5 -$as_echo "required" >&6; } - AST_NESTED_FUNCTIONS=-fnested-functions + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + AST_NESTED_FUNCTIONS=-fnested-functions fi 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. if test "${enable_rpath+set}" = set; then : enableval=$enable_rpath; case "${enableval}" in diff --git a/configure.ac b/configure.ac index de90e6a324..edb4322b12 100644 --- a/configure.ac +++ b/configure.ac @@ -1078,7 +1078,7 @@ fi AC_SUBST(AST_DECLARATION_AFTER_STATEMENT) 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) AST_TRAMPOLINES=-Wtrampolines else @@ -1133,16 +1133,41 @@ fi AC_SUBST(AST_NATIVE_ARCH) dnl Nested functions required for RAII implementation -AC_MSG_CHECKING(for -fnested-functions) -AC_COMPILE_IFELSE( - 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_MSG_RESULT(no) - [AST_NESTED_FUNCTIONS=], - AC_MSG_RESULT(required) - [AST_NESTED_FUNCTIONS=-fnested-functions] +AC_LINK_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 + [AC_LANG_PROGRAM([], [auto void foo(void); void foo(void) {}])], + AC_MSG_RESULT(no) + [AST_NESTED_FUNCTIONS=], + AC_MSG_RESULT(yes) + [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 AC_ARG_ENABLE(rpath, diff --git a/include/asterisk/inline_api.h b/include/asterisk/inline_api.h index 5f6911d369..d76dfa0a52 100644 --- a/include/asterisk/inline_api.h +++ b/include/asterisk/inline_api.h @@ -25,12 +25,14 @@ Small API functions that are candidates for inlining need to be specially declared and defined, to ensure that the 'right thing' always happens. For example: - - there must _always_ be a non-inlined version of the function + - there must _always_ be a non-inlined version of the function available for modules compiled out of the tree to link to - references to a function that cannot be inlined (for any reason that the compiler deems proper) must devolve into an '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 completely, even if the compiler is configured to support it @@ -46,8 +48,12 @@ #if !defined(LOW_MEMORY) && !defined(DISABLE_INLINE) #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 -#else +#endif +#else /* if !defined(AST_API_MODULE) */ #define AST_INLINE_API(hdr, body) hdr; hdr body #endif diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h index a0e7cb6bf5..1dc351d0ac 100644 --- a/include/asterisk/utils.h +++ b/include/asterisk/utils.h @@ -1005,12 +1005,33 @@ char *ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size); * } * \endcode */ -#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); \ - void _dtor_ ## varname (vartype * v) { dtor(*v); } \ + +#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) \ + auto void _dtor_ ## varname (vartype * v); \ + void _dtor_ ## varname (vartype * v) { dtor(*v); } \ 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). * diff --git a/main/Makefile b/main/Makefile index 0fa219297f..0a63c01a04 100644 --- a/main/Makefile +++ b/main/Makefile @@ -40,6 +40,7 @@ AST_LIBS+=$(JANSSON_LIB) AST_LIBS+=$(URIPARSER_LIB) AST_LIBS+=$(UUID_LIB) AST_LIBS+=$(CRYPT_LIB) +AST_LIBS+=$(AST_CLANG_BLOCKS_LIBS) ifneq ($(findstring $(OSARCH), linux-gnu uclinux linux-uclibc kfreebsd-gnu),) ifneq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),) diff --git a/makeopts.in b/makeopts.in index a0faaee463..96b031bdd2 100644 --- a/makeopts.in +++ b/makeopts.in @@ -109,6 +109,8 @@ AST_TRAMPOLINES=@AST_TRAMPOLINES@ AST_NO_STRICT_OVERFLOW=@AST_NO_STRICT_OVERFLOW@ AST_SHADOW_WARNINGS=@AST_SHADOW_WARNINGS@ 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_FORTIFY_SOURCE=@AST_FORTIFY_SOURCE@ AST_MARCH_NATIVE=@AST_MARCH_NATIVE@