diff --git a/configure b/configure index 5271a50ed487..cf5b9d65ee74 100755 --- a/configure +++ b/configure @@ -15577,6 +15577,51 @@ fi done +# Use -Wsuggest-attribute=attribute_name if supported +# Don't apply pure to primitives. const has some false-positive suggestions. +for attribute_name in noreturn malloc format; do + as_CACHEVAR=`printf "%s\n" "ax_cv_check_cflags_$warn_error_flag_-Wsuggest-attribute=$attribute_name" | $as_tr_sh` +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler accepts -Wsuggest-attribute=$attribute_name" >&5 +printf %s "checking whether the C compiler accepts -Wsuggest-attribute=$attribute_name... " >&6; } +if eval test \${$as_CACHEVAR+y} +then : + printf %s "(cached) " >&6 +else $as_nop + + ax_check_save_flags=$CFLAGS + CFLAGS="$CFLAGS $warn_error_flag -Wsuggest-attribute=$attribute_name" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval "$as_CACHEVAR=yes" +else $as_nop + eval "$as_CACHEVAR=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + CFLAGS=$ax_check_save_flags +fi +eval ac_res=\$$as_CACHEVAR + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } +if eval test \"x\$"$as_CACHEVAR"\" = x"yes" +then : + cc_warnings="$cc_warnings -Wsuggest-attribute=$attribute_name" +else $as_nop + : +fi + +done + case $enable_warn_error,true in #( yes,*|,true) : cc_warnings="$cc_warnings $warn_error_flag" ;; #( diff --git a/configure.ac b/configure.ac index 016998ce8c69..7ea8fc55f9cd 100644 --- a/configure.ac +++ b/configure.ac @@ -1066,6 +1066,14 @@ for flag in '-Wimplicit-fallthrough=5' '-Wimplicit-fallthrough'; do [cc_warnings="$cc_warnings $flag"; break], [], [$warn_error_flag]) done +# Use -Wsuggest-attribute=attribute_name if supported +# Don't apply pure to primitives. const has some false-positive suggestions. +for attribute_name in noreturn malloc format; do + AX_CHECK_COMPILE_FLAG([-Wsuggest-attribute=$attribute_name], + [cc_warnings="$cc_warnings -Wsuggest-attribute=$attribute_name"], [], + [$warn_error_flag]) +done + AS_CASE([$enable_warn_error,OCAML__DEVELOPMENT_VERSION], [yes,*|,true], [cc_warnings="$cc_warnings $warn_error_flag"]) diff --git a/ocamltest/run.h b/ocamltest/run.h index 7c13212e1154..ee6730766532 100644 --- a/ocamltest/run.h +++ b/ocamltest/run.h @@ -25,6 +25,7 @@ typedef char_os **array; typedef void Logger(void *, const char *, va_list ap); +#define Logger CAMLformat(__printf__, 2, 0) Logger typedef struct { char_os *program; diff --git a/ocamltest/run_common.h b/ocamltest/run_common.h index 3d02bfa48b62..448feb7dc621 100644 --- a/ocamltest/run_common.h +++ b/ocamltest/run_common.h @@ -25,11 +25,13 @@ static int is_defined(const char_os *str) return (str != NULL) && (*str != 0); } +CAMLformat(__printf__, 2, 0) static void defaultLogger(void *where, const char *format, va_list ap) { vfprintf(stderr, format, ap); } +CAMLformat(__printf__, 3, 4) static void mylog(Logger *logger, void *loggerData, const char *fmt, ...) { va_list ap; @@ -38,6 +40,7 @@ static void mylog(Logger *logger, void *loggerData, const char *fmt, ...) va_end(ap); } +CAMLformat(__printf__, 4, 5) static void error_with_location( const char *file, int line, const command_settings *settings, diff --git a/ocamltest/run_stubs.c b/ocamltest/run_stubs.c index b1fca0386b8c..38d622d27c80 100644 --- a/ocamltest/run_stubs.c +++ b/ocamltest/run_stubs.c @@ -58,6 +58,7 @@ static void free_cstringvect(array v) caml_stat_free(v); } +CAMLformat(__printf__, 2, 0) static void logToChannel(void *voidchannel, const char *fmt, va_list ap) { struct channel *channel = (struct channel *) voidchannel; diff --git a/ocamltest/run_unix.c b/ocamltest/run_unix.c index c4fd6115a2a0..8da110085a7f 100644 --- a/ocamltest/run_unix.c +++ b/ocamltest/run_unix.c @@ -46,7 +46,7 @@ error_with_location(__FILE__, __LINE__, settings, msg, ## __VA_ARGS__) For a more portable (but also more complex) solution, see http://stackoverflow.com/questions/20818800/variadic-macro-and-trailing-comma */ - +CAMLformat(__printf__, 4, 5) static void myperror_with_location( const char *file, int line, const command_settings *settings, diff --git a/otherlibs/unix/execv.c b/otherlibs/unix/execv.c index 5996a9aca758..d11b81a71326 100644 --- a/otherlibs/unix/execv.c +++ b/otherlibs/unix/execv.c @@ -20,7 +20,7 @@ #include #include "caml/unixsupport.h" -CAMLprim value caml_unix_execv(value path, value args) +CAMLnoret CAMLprim void caml_unix_execv(value path, value args) { char_os * wpath; char_os ** argv; @@ -31,6 +31,4 @@ CAMLprim value caml_unix_execv(value path, value args) caml_stat_free(wpath); caml_unix_cstringvect_free(argv); caml_uerror("execv", path); - return Val_unit; /* never reached, but suppress warnings */ - /* from smart compilers */ } diff --git a/otherlibs/unix/execve.c b/otherlibs/unix/execve.c index 29b4d3395a63..5cc2f6446321 100644 --- a/otherlibs/unix/execve.c +++ b/otherlibs/unix/execve.c @@ -20,7 +20,7 @@ #include #include "caml/unixsupport.h" -CAMLprim value caml_unix_execve(value path, value args, value env) +CAMLnoret CAMLprim void caml_unix_execve(value path, value args, value env) { char_os ** argv; char_os ** envp; @@ -34,6 +34,4 @@ CAMLprim value caml_unix_execve(value path, value args, value env) caml_unix_cstringvect_free(argv); caml_unix_cstringvect_free(envp); caml_uerror("execve", path); - return Val_unit; /* never reached, but suppress warnings */ - /* from smart compilers */ } diff --git a/otherlibs/unix/execvp.c b/otherlibs/unix/execvp.c index 8fff5db39156..cefbb824749f 100644 --- a/otherlibs/unix/execvp.c +++ b/otherlibs/unix/execvp.c @@ -22,7 +22,7 @@ #include #include "caml/unixsupport.h" -CAMLprim value caml_unix_execvp(value path, value args) +CAMLnoret CAMLprim void caml_unix_execvp(value path, value args) { char_os ** argv; char_os * wpath; @@ -33,8 +33,6 @@ CAMLprim value caml_unix_execvp(value path, value args) caml_stat_free(wpath); caml_unix_cstringvect_free(argv); caml_uerror("execvp", path); - return Val_unit; /* never reached, but suppress warnings */ - /* from smart compilers */ } #ifndef HAS_EXECVPE @@ -43,7 +41,7 @@ int caml_unix_execvpe_emulation(const char * name, char * const envp[]); #endif -CAMLprim value caml_unix_execvpe(value path, value args, value env) +CAMLnoret CAMLprim void caml_unix_execvpe(value path, value args, value env) { char_os ** argv; char_os ** envp; @@ -63,8 +61,6 @@ CAMLprim value caml_unix_execvpe(value path, value args, value env) caml_unix_cstringvect_free(argv); caml_unix_cstringvect_free(envp); caml_unix_error(err, "execvpe", path); - return Val_unit; /* never reached, but suppress warnings */ - /* from smart compilers */ } #ifndef HAS_EXECVPE diff --git a/otherlibs/unix/exit.c b/otherlibs/unix/exit.c index d7fcb319fed8..02fb6df432b8 100644 --- a/otherlibs/unix/exit.c +++ b/otherlibs/unix/exit.c @@ -16,9 +16,7 @@ #include #include "caml/unixsupport.h" -CAMLprim value caml_unix_exit(value n) +CAMLnoret CAMLprim void caml_unix_exit(value n) { _exit(Int_val(n)); - return Val_unit; /* never reached, but suppress warnings */ - /* from smart compilers */ } diff --git a/runtime/caml/addrmap.h b/runtime/caml/addrmap.h index e9861a491492..c8bd9f40fd2b 100644 --- a/runtime/caml/addrmap.h +++ b/runtime/caml/addrmap.h @@ -36,7 +36,8 @@ value caml_addrmap_lookup(struct addrmap* t, value k); #define ADDRMAP_NOT_PRESENT ((value)(0)) #define ADDRMAP_INVALID_KEY ((value)(0)) -value* caml_addrmap_insert_pos(struct addrmap* t, value k); +value* caml_addrmap_insert_pos(struct addrmap* t, value k) + CAMLreturns_nonnull; /* must not already be present */ void caml_addrmap_insert(struct addrmap* t, value k, value v); diff --git a/runtime/caml/alloc.h b/runtime/caml/alloc.h index 0e17f17cc10f..3ffcce5da182 100644 --- a/runtime/caml/alloc.h +++ b/runtime/caml/alloc.h @@ -56,10 +56,7 @@ CAMLextern value caml_copy_nativeint (intnat); /* defined in [ints.c] */ CAMLextern value caml_alloc_array (value (*funct) (char const *), char const * const * array); CAMLextern value caml_alloc_sprintf(const char * format, ...) -#if __has_attribute(format) || defined(__GNUC__) - __attribute__ ((format (printf, 1, 2))) -#endif -; + CAMLformat(__printf__, 1, 2); CAMLextern value caml_alloc_some(value); typedef void (*final_fun)(value); diff --git a/runtime/caml/custom.h b/runtime/caml/custom.h index f304470505bd..b0ead559483b 100644 --- a/runtime/caml/custom.h +++ b/runtime/caml/custom.h @@ -83,7 +83,8 @@ CAMLextern mlsize_t caml_custom_get_max_major (void); extern struct custom_operations * caml_find_custom_operations(const char * ident); extern struct custom_operations * - caml_final_custom_operations(void (*fn)(value)); + caml_final_custom_operations(void (*fn)(value)) + CAMLreturns_nonnull; extern void caml_init_custom_operations(void); diff --git a/runtime/caml/debugger.h b/runtime/caml/debugger.h index a5f90226a6b9..35f85ec9b711 100644 --- a/runtime/caml/debugger.h +++ b/runtime/caml/debugger.h @@ -37,7 +37,12 @@ void caml_debugger_init (void); void caml_debugger (enum event_kind event, value param); CAMLextern void caml_debugger_cleanup_fork (void); -opcode_t caml_debugger_saved_instruction(code_t pc); +#if !defined(HAS_SOCKETS) || defined(NATIVE_CODE) +CAMLnoret void +#else +opcode_t +#endif +caml_debugger_saved_instruction(code_t pc); /* Communication protocol */ diff --git a/runtime/caml/domain_state.h b/runtime/caml/domain_state.h index 392c3deaf95b..858e44bcd92e 100644 --- a/runtime/caml/domain_state.h +++ b/runtime/caml/domain_state.h @@ -51,7 +51,7 @@ enum { #define Caml_state_opt caml_state #else #if __has_attribute(pure) || defined(__GNUC__) - __attribute__((pure)) + __attribute__((__pure__)) #endif CAMLextern caml_domain_state* caml_get_domain_state(void); #define Caml_state_opt (caml_get_domain_state()) diff --git a/runtime/caml/dynlink.h b/runtime/caml/dynlink.h index a7441fcc0e4f..f90326cfffae 100644 --- a/runtime/caml/dynlink.h +++ b/runtime/caml/dynlink.h @@ -44,7 +44,8 @@ extern void caml_free_shared_libs(void); /* If found, parse $OCAMLLIB/ld.conf, $CAMLLIB/ld.conf and stdlib/ld.conf in that order and add the lines read to table. */ extern char_os * caml_parse_ld_conf(const char_os * stdlib, - struct ext_table * table); + struct ext_table * table) + CAMLreturns_nonnull; #endif /* CAML_INTERNALS */ diff --git a/runtime/caml/io.h b/runtime/caml/io.h index 8c0e001801fe..364f77d7eea2 100644 --- a/runtime/caml/io.h +++ b/runtime/caml/io.h @@ -66,9 +66,9 @@ enum { /* Creating and closing channels from C */ CAMLextern void caml_close_channel (struct channel *); -CAMLalloc(caml_close_channel, 1) CAMLreturns_nonnull() +CAMLalloc(caml_close_channel, 1) CAMLreturns_nonnull CAMLextern struct channel * caml_open_descriptor_in (int); -CAMLalloc(caml_close_channel, 1) CAMLreturns_nonnull() +CAMLalloc(caml_close_channel, 1) CAMLreturns_nonnull CAMLextern struct channel * caml_open_descriptor_out (int); CAMLextern file_offset caml_channel_size (struct channel *); CAMLextern void caml_seek_in (struct channel *, file_offset); diff --git a/runtime/caml/memory.h b/runtime/caml/memory.h index 085c5bd57e8a..e0e80ff5f3a0 100644 --- a/runtime/caml/memory.h +++ b/runtime/caml/memory.h @@ -86,7 +86,7 @@ CAMLextern void caml_stat_free(caml_stat_block); (in bytes) and returns a pointer to it. It throws an OCaml exception in case the request fails, and so requires the runtime lock to be held. */ -CAMLmalloc(caml_stat_free, 1, 1) CAMLreturns_nonnull() +CAMLmalloc(caml_stat_free, 1, 1) CAMLreturns_nonnull CAMLextern caml_stat_block caml_stat_alloc(asize_t); /* [caml_stat_alloc_noexc(size)] allocates a memory block of the requested @@ -102,7 +102,7 @@ CAMLextern caml_stat_block caml_stat_alloc_noexc(asize_t); well as the unaligned [block] (as an output parameter). It throws an OCaml exception in case the request fails, and so requires the runtime lock. */ -CAMLaligned_alloc(caml_stat_free, 1, 1, 2) CAMLreturns_nonnull() +CAMLaligned_alloc(caml_stat_free, 1, 1, 2) CAMLreturns_nonnull CAMLextern void* caml_stat_alloc_aligned(asize_t, int modulo, caml_stat_block*); /* [caml_stat_alloc_aligned_noexc] is a variant of [caml_stat_alloc_aligned] @@ -129,7 +129,7 @@ CAMLextern caml_stat_block caml_stat_calloc_noexc(asize_t, asize_t); portion is indeterminate. The function throws an OCaml exception in case the request fails, and so requires the runtime lock to be held. */ -CAMLrealloc(2) CAMLreturns_nonnull() +CAMLrealloc(2) CAMLreturns_nonnull CAMLextern caml_stat_block caml_stat_resize(caml_stat_block, asize_t); /* [caml_stat_resize_noexc] is a variant of [caml_stat_resize] that returns NULL @@ -146,7 +146,7 @@ typedef char* caml_stat_string; copy of the null-terminated string [s]. It throws an OCaml exception in case the request fails, and so requires the runtime lock to be held. */ -CAMLalloc(caml_stat_free, 1) CAMLreturns_nonnull() +CAMLalloc(caml_stat_free, 1) CAMLreturns_nonnull CAMLextern caml_stat_string caml_stat_strdup(const char *s); /* [caml_stat_strdup_noexc] is a variant of [caml_stat_strdup] that returns NULL @@ -160,7 +160,7 @@ CAMLextern caml_stat_string caml_stat_strdup_noexc(const char *s); * obvious equivalents of [caml_stat_strdup] and * [caml_stat_strdup_noexc] for wide characters. */ -CAMLalloc(caml_stat_free, 1) CAMLreturns_nonnull() +CAMLalloc(caml_stat_free, 1) CAMLreturns_nonnull CAMLextern wchar_t* caml_stat_wcsdup(const wchar_t *s); CAMLalloc(caml_stat_free, 1) CAMLextern wchar_t* caml_stat_wcsdup_noexc(const wchar_t *s); @@ -172,7 +172,7 @@ CAMLextern wchar_t* caml_stat_wcsdup_noexc(const wchar_t *s); implementation of the Windows-only functions caml_stat_char_array_{to,from}_utf16. */ -CAMLmalloc(caml_stat_free, 1, 2) CAMLreturns_nonnull() +CAMLmalloc(caml_stat_free, 1, 2) CAMLreturns_nonnull CAMLextern caml_stat_string caml_stat_memdup(const char *s, asize_t size, asize_t *out_size); @@ -181,10 +181,10 @@ CAMLextern caml_stat_string caml_stat_memdup(const char *s, asize_t size, except for the very last one. It throws an OCaml exception in case the request fails, and so requires the runtime lock to be held. */ -CAMLalloc(caml_stat_free, 1) CAMLreturns_nonnull() +CAMLalloc(caml_stat_free, 1) CAMLreturns_nonnull CAMLextern caml_stat_string caml_stat_strconcat(int n, ...); #ifdef _WIN32 -CAMLalloc(caml_stat_free, 1) CAMLreturns_nonnull() +CAMLalloc(caml_stat_free, 1) CAMLreturns_nonnull CAMLextern wchar_t* caml_stat_wcsconcat(int n, ...); #endif diff --git a/runtime/caml/misc.h b/runtime/caml/misc.h index 327245dcb3fe..f5627bc7b432 100644 --- a/runtime/caml/misc.h +++ b/runtime/caml/misc.h @@ -45,8 +45,8 @@ #if __has_attribute(deprecated) || defined(__GNUC__) /* Supported since at least GCC 3.1 */ - #define CAMLdeprecated_typedef(name, type) \ - typedef type name __attribute__ ((deprecated)) + #define CAMLdeprecated_typedef(name, type) \ + typedef type name __attribute__((__deprecated__)) #elif defined(_MSC_VER) #define CAMLdeprecated_typedef(name, type) \ typedef __declspec(deprecated) type name @@ -117,14 +117,14 @@ CAMLdeprecated_typedef(addr, char *); #define CAMLnoreturn_start CAMLnoret #define CAMLnoreturn_end #ifdef __GNUC__ - #define Noreturn __attribute__ ((noreturn)) + #define Noreturn __attribute__((__noreturn__)) #else #define Noreturn #endif /* Manually preventing inlining */ #if defined(__GNUC__) - #define Caml_noinline __attribute__ ((noinline)) + #define Caml_noinline __attribute__((__noinline__)) #elif defined(_MSC_VER) #define Caml_noinline __declspec(noinline) #else @@ -149,7 +149,7 @@ CAMLdeprecated_typedef(addr, char *); /* Weak function definitions that can be overridden by external libs */ /* Conservatively restricted to ELF and MacOSX platforms */ #if defined(__GNUC__) && (defined (__ELF__) || defined(__APPLE__)) -#define CAMLweakdef __attribute__((weak)) +#define CAMLweakdef __attribute__((__weak__)) #else #define CAMLweakdef #endif @@ -202,7 +202,7 @@ CAMLdeprecated_typedef(addr, char *); #define CAMLunused_start CAMLunused #define CAMLunused_end #elif __has_attribute(unused) || defined(__GNUC__) - #define CAMLunused __attribute__ ((unused)) + #define CAMLunused __attribute__((__unused__)) #define CAMLunused_start CAMLunused #define CAMLunused_end #elif defined(_MSC_VER) @@ -221,7 +221,7 @@ CAMLdeprecated_typedef(addr, char *); defined(__cplusplus) && __cplusplus >= 201703L #define fallthrough [[fallthrough]] #elif __has_attribute(fallthrough) - #define fallthrough __attribute__ ((fallthrough)) + #define fallthrough __attribute__((__fallthrough__)) #else #define fallthrough ((void) 0) #endif @@ -240,23 +240,24 @@ CAMLdeprecated_typedef(addr, char *); defined(__llvm__)) /* Indicates that a particular function always returns a non-null pointer. */ -#define CAMLreturns_nonnull() __attribute__ ((returns_nonnull)) +#define CAMLreturns_nonnull __attribute__ ((__returns_nonnull__)) /* [CAMLrealloc(n)] indicates that the function is [realloc]-like, and implies that the [n]-th argument number equals the number of available bytes at the returned pointer. */ #define CAMLrealloc(alloc_size_N) \ - __attribute__ ((warn_unused_result,alloc_size(alloc_size_N))) + __attribute__((__warn_unused_result__,__alloc_size__(alloc_size_N))) /* [CAMLalloc(dealloc, p)] indicates that the function allocates a resource, which must be deallocated by passing it as the [p]-th argument of the function [dealloc]. */ #if defined(__GNUC__) && !defined(__llvm__) #define CAMLalloc(deallocator,ptr_index) \ - __attribute__ ((malloc,malloc(deallocator,ptr_index),warn_unused_result)) + __attribute__((__malloc__,__malloc__(deallocator,ptr_index), \ + __warn_unused_result__)) #else -#define CAMLalloc(deallocator,ptr_index) \ - __attribute__ ((malloc,warn_unused_result)) +#define CAMLalloc(deallocator,ptr_index) \ + __attribute__((__malloc__,__warn_unused_result__)) #endif /* [CAMLmalloc(dealloc, p, n)] indicates that the function is [malloc]-like, and @@ -265,7 +266,7 @@ CAMLdeprecated_typedef(addr, char *); argument of the function [dealloc]. */ #define CAMLmalloc(deallocator,ptr_index,alloc_size_N) \ CAMLalloc(deallocator,ptr_index) \ - __attribute__ ((alloc_size(alloc_size_N))) + __attribute__((__alloc_size__(alloc_size_N))) /* [CAMLcalloc(dealloc, p, n, m)] indicates that the function is [calloc]-like, and implies that it allocates a memory block whose size is set by the product @@ -273,7 +274,7 @@ CAMLdeprecated_typedef(addr, char *); by passing it as the [p]-th argument of the function [dealloc]. */ #define CAMLcalloc(deallocator,ptr_index,alloc_size_N,alloc_size_M) \ CAMLalloc(deallocator,ptr_index) \ - __attribute__ ((alloc_size(alloc_size_N,alloc_size_M))) + __attribute__((__alloc_size__(alloc_size_N,alloc_size_M))) /* [CAMLaligned_alloc(dealloc, p, n, a)] indicates that the function is [aligned_alloc]-like, and implies that it allocates a memory block whose size @@ -282,10 +283,10 @@ CAMLdeprecated_typedef(addr, char *); the [p]-th argument of the function [dealloc]. */ #define CAMLaligned_alloc(deallocator,ptr_index,alloc_size_N,alloc_align_) \ CAMLmalloc(deallocator,ptr_index,alloc_size_N) \ - __attribute__ ((alloc_align(alloc_align_))) + __attribute__((__alloc_align__(alloc_align_))) #else -#define CAMLreturns_nonnull() +#define CAMLreturns_nonnull #define CAMLrealloc(asN) #define CAMLalloc(d,pi) #define CAMLmalloc(d,pi,asN) @@ -359,7 +360,7 @@ CAMLextern void caml_failed_assert (const char *, const char_os *, int) /* However, we do inform clang-analyzer that this function never returns, since that improves analysis without breaking debugging */ #if __has_feature(attribute_analyzer_noreturn) - __attribute__((analyzer_noreturn)) + __attribute__((__analyzer_noreturn__)) #endif #endif ; @@ -397,6 +398,13 @@ CAMLnoret CAMLextern void caml_debug_abort(const char_os *, int); #define CAMLunlikely(e) (e) #endif +#if __has_attribute(format) || defined(__GNUC__) +#define CAMLformat(archetype, string_index, first_to_check) \ + __attribute__((__format__(archetype, string_index, first_to_check))) +#else +#define CAMLformat(a, si, ftc) +#endif + #ifdef CAML_INTERNALS /* GC status assertions. @@ -408,9 +416,9 @@ CAMLnoret CAMLextern void caml_debug_abort(const char_os *, int); int caml_noalloc_begin(void); void caml_noalloc_end(int*); void caml_alloc_point_here(void); -#define CAMLnoalloc \ - int caml__noalloc \ - __attribute__((cleanup(caml_noalloc_end),unused)) \ +#define CAMLnoalloc \ + int caml__noalloc \ + __attribute__((__cleanup__(caml_noalloc_end),__unused__)) \ = caml_noalloc_begin() #define CAMLalloc_point_here (caml_alloc_point_here()) #else @@ -437,10 +445,7 @@ extern _Atomic fatal_error_hook caml_fatal_error_hook; #endif CAMLnoret CAMLextern void caml_fatal_error (const char *, ...) -#if __has_attribute(format) || defined(__GNUC__) - __attribute__ ((format (printf, 1, 2))) -#endif -; + CAMLformat(__printf__, 1, 2); /* Integer arithmetic with overflow detection. The functions return 0 if no overflow, 1 if overflow. @@ -679,10 +684,7 @@ extern atomic_uintnat caml_verb_gc; /* output message if caml_verb_gc includes any bits in `category`. */ void caml_gc_message (int category, const char *, ...) -#if __has_attribute(format) || defined(__GNUC__) - __attribute__ ((format (printf, 2, 3))) -#endif -; + CAMLformat(__printf__, 2, 3); /* Short-hand for calls to `caml_gc_message` */ @@ -691,11 +693,7 @@ void caml_gc_message (int category, const char *, ...) /* Output message if CAML_GC_MSG_DEBUG is set */ -void caml_gc_log (const char *, ...) -#if __has_attribute(format) || defined(__GNUC__) - __attribute__ ((format (printf, 1, 2))) -#endif -; +void caml_gc_log (const char *, ...) CAMLformat(__printf__, 1, 2); /* Runtime warnings */ extern uintnat caml_runtime_warnings; @@ -747,13 +745,14 @@ CAMLextern int caml_runtime_warnings_active(void); #ifdef _WIN32 #ifndef _UCRT -extern int caml_snprintf(char * buf, size_t size, const char * format, ...); +extern int caml_snprintf(char * buf, size_t size, const char * format, ...) + CAMLformat(__printf__, 3, 4); #define snprintf caml_snprintf #endif -CAMLextern int caml_snwprintf(wchar_t * buf, - size_t size, - const wchar_t * format, ...); +CAMLextern int caml_snwprintf(wchar_t * buf, size_t size, + const wchar_t * format, ...) + /* CAMLformat(wprintf, 3, 4) */; #define snprintf_os caml_snwprintf #else #define snprintf_os snprintf @@ -768,7 +767,7 @@ CAMLextern int caml_snwprintf(wchar_t * buf, #if defined(__has_feature) # if __has_feature(address_sanitizer) # undef CAMLno_asan -# define CAMLno_asan __attribute__((no_sanitize("address"))) +# define CAMLno_asan __attribute__((__no_sanitize__("address"))) # endif #else # if defined(__SANITIZE_ADDRESS__) @@ -776,7 +775,7 @@ CAMLextern int caml_snwprintf(wchar_t * buf, # if (defined(_MSC_VER) && !defined(__clang__)) # define CAMLno_asan __declspec(no_sanitize_address) # else -# define CAMLno_asan __attribute__((no_sanitize_address)) +# define CAMLno_asan __attribute__((__no_sanitize_address__)) # endif # endif #endif diff --git a/runtime/caml/osdeps.h b/runtime/caml/osdeps.h index ab4c11d33724..46455aeba7ba 100644 --- a/runtime/caml/osdeps.h +++ b/runtime/caml/osdeps.h @@ -225,7 +225,7 @@ CAMLextern wchar_t* caml_stat_strdup_noexc_to_utf16(const char *s); If allocation fails, this raises Out_of_memory. This function may also raise [Sys_error] if [s] is not valid UTF-8. */ -CAMLalloc(caml_stat_free, 1) CAMLreturns_nonnull() +CAMLalloc(caml_stat_free, 1) CAMLreturns_nonnull CAMLextern wchar_t* caml_stat_strdup_to_utf16(const char *s); /* [caml_stat_strdup_noexc_of_utf16(s)] returns a NUL-terminated copy of [s], @@ -251,7 +251,7 @@ CAMLextern char* caml_stat_strdup_noexc_of_utf16(const wchar_t *s); If allocation fails, this raises Out_of_memory. This function may also raise [Sys_error] if [s] is not valid UTF-16. */ -CAMLalloc(caml_stat_free, 1) CAMLreturns_nonnull() +CAMLalloc(caml_stat_free, 1) CAMLreturns_nonnull CAMLextern char* caml_stat_strdup_of_utf16(const wchar_t *s); /* [caml_stat_char_array_to_utf16(s, size, &out_size)] returns a copy of the @@ -270,7 +270,7 @@ CAMLextern char* caml_stat_strdup_of_utf16(const wchar_t *s); If allocation fails, this raises Out_of_memory. This function may also raise [Sys_error] if [s] is not valid UTF-8. */ -CAMLmalloc(caml_stat_free, 1, 2) CAMLreturns_nonnull() +CAMLmalloc(caml_stat_free, 1, 2) CAMLreturns_nonnull CAMLextern wchar_t *caml_stat_char_array_to_utf16(const char *s, size_t size, size_t *out_size); @@ -289,7 +289,7 @@ CAMLextern wchar_t *caml_stat_char_array_to_utf16(const char *s, size_t size, If allocation fails, this raises Out_of_memory. This function may also raise [Sys_error] if [s] is not valid UTF-16. */ -CAMLalloc(caml_stat_free, 1) CAMLreturns_nonnull() +CAMLalloc(caml_stat_free, 1) CAMLreturns_nonnull CAMLextern char *caml_stat_char_array_of_utf16(const wchar_t *s, size_t size, size_t *out_size); diff --git a/runtime/caml/runtime_events.h b/runtime/caml/runtime_events.h index a230171eaaae..fff36f01b318 100644 --- a/runtime/caml/runtime_events.h +++ b/runtime/caml/runtime_events.h @@ -29,6 +29,7 @@ #define CAML_RUNTIME_EVENTS_H #include "mlvalues.h" +#include "memory.h" #ifdef CAML_INSTR #define CAML_EV_ALLOC(s) caml_ev_alloc(s) @@ -216,7 +217,7 @@ CAMLextern int caml_runtime_events_are_active(void); isn't enough to silence the note. */ #if defined(__GNUC__) && __has_attribute(aligned) #undef CAMLalign -#define CAMLalign(n) __attribute__ ((aligned(n))) +#define CAMLalign(n) __attribute__((__aligned__(n))) #endif struct runtime_events_buffer_header { @@ -319,7 +320,8 @@ CAMLextern void caml_runtime_events_post_fork(void); if runtime events are not enabled. This is used in the consumer to read the ring buffers of the current process. Always returns a freshly-allocated string. */ -CAMLextern char_os* caml_runtime_events_current_location(void); +CAMLextern char_os* caml_runtime_events_current_location(void) + CAMLalloc(caml_stat_free, 1); /* Functions for putting runtime data on to the runtime_events. These are all internal to the runtime, except for caml_ev_lifecycle which is needed in diff --git a/runtime/caml/tsan.h b/runtime/caml/tsan.h index 74e60d5cd42e..fdfb1354d42b 100644 --- a/runtime/caml/tsan.h +++ b/runtime/caml/tsan.h @@ -34,18 +34,18 @@ extern "C" { # if defined(__has_attribute) # if __has_attribute(disable_sanitizer_instrumentation) # define CAMLno_tsan \ - __attribute__((disable_sanitizer_instrumentation)) + __attribute__((__disable_sanitizer_instrumentation__)) # else -# define CAMLno_tsan __attribute__((no_sanitize("thread"))) +# define CAMLno_tsan __attribute__((__no_sanitize__("thread"))) # endif # else -# define CAMLno_tsan __attribute__((no_sanitize("thread"))) +# define CAMLno_tsan __attribute__((__no_sanitize__("thread"))) # endif # endif #else # if defined(__SANITIZE_THREAD__) # undef CAMLno_tsan -# define CAMLno_tsan __attribute__((no_sanitize_thread)) +# define CAMLno_tsan __attribute__((__no_sanitize_thread__)) # endif #endif diff --git a/runtime/debugger.c b/runtime/debugger.c index 83301b1e6c42..fabc2df256e4 100644 --- a/runtime/debugger.c +++ b/runtime/debugger.c @@ -43,14 +43,13 @@ void caml_debugger_init(void) { } -opcode_t caml_debugger_saved_instruction(code_t pc) +void caml_debugger_saved_instruction(code_t pc) { /* Raise a fatal error in the should-not-happen case where this function * would be called without a socket, so that the execution does not branch * to opcode 0 */ caml_fatal_error("cannot execute debugger instructions" " without a debugger connection socket\n"); - return 0; } void caml_debugger(enum event_kind event, value param) diff --git a/runtime/dynlink.c b/runtime/dynlink.c index f9ad021bd644..add8f11d7000 100644 --- a/runtime/dynlink.c +++ b/runtime/dynlink.c @@ -472,22 +472,19 @@ CAMLprim value caml_dynlink_get_current_libs(value unit) #else -value caml_dynlink_add_primitive(value handle) +CAMLnoret void caml_dynlink_add_primitive(value handle) { caml_invalid_argument("dynlink_add_primitive"); - return Val_unit; /* not reached */ } -value caml_dynlink_get_current_libs(value unit) +CAMLnoret void caml_dynlink_get_current_libs(value unit) { caml_invalid_argument("dynlink_get_current_libs"); - return Val_unit; /* not reached */ } -value caml_dynlink_get_bytecode_sections(value unit) +CAMLnoret void caml_dynlink_get_bytecode_sections(value unit) { caml_invalid_argument("dynlink_get_bytecode_sections"); - return Val_unit; /* not reached */ } #endif /* NATIVE_CODE */ diff --git a/runtime/fail_nat.c b/runtime/fail_nat.c index 4db291e86acb..ac074add5d2a 100644 --- a/runtime/fail_nat.c +++ b/runtime/fail_nat.c @@ -166,6 +166,9 @@ value caml_exception_array_bound_error(void) return *exn; } +#if !defined(WITH_THREAD_SANITIZER) +CAMLnoret +#endif void caml_array_bound_error_asm(void) { #if defined(WITH_THREAD_SANITIZER) diff --git a/runtime/gen_primitives.sh b/runtime/gen_primitives.sh index bf41dd45982d..6e5f2847744e 100755 --- a/runtime/gen_primitives.sh +++ b/runtime/gen_primitives.sh @@ -49,7 +49,7 @@ tmp_primitives="$primitives.tmp$$" # The tr -d '\r' is _after_ the call to sort just in case sort happens to be the # Windows version. -sed -n -e 's/^CAMLprim value \([a-z][a-z0-9_]*\).*$/\1/p' "$@" | \ +sed -E -n -e 's/^CAMLprim (value|void) ([a-z][a-z0-9_]*).*$/\2/p' "$@" | \ sort | tr -d '\r' | uniq > "$tmp_primitives" # To speed up builds, we avoid changing "primitives" when files diff --git a/runtime/meta.c b/runtime/meta.c index 40cb506f7266..6460db9190b4 100644 --- a/runtime/meta.c +++ b/runtime/meta.c @@ -202,34 +202,29 @@ CAMLprim value caml_invoke_traced_function(value codeptr, value env, value arg) /* Dummy definitions to support compilation of ocamlc.opt */ -value caml_get_global_data(value unit) +CAMLnoret void caml_get_global_data(value unit) { caml_invalid_argument("Meta.get_global_data"); - return Val_unit; /* not reached */ } -value caml_realloc_global(value size) +CAMLnoret void caml_realloc_global(value size) { caml_invalid_argument("Meta.realloc_global"); - return Val_unit; /* not reached */ } -value caml_invoke_traced_function(value codeptr, value env, value arg) +CAMLnoret void caml_invoke_traced_function(value codeptr, value env, value arg) { caml_invalid_argument("Meta.invoke_traced_function"); - return Val_unit; /* not reached */ } -value caml_reify_bytecode(value prog, value len) +CAMLnoret void caml_reify_bytecode(value prog, value len) { caml_invalid_argument("Meta.reify_bytecode"); - return Val_unit; /* not reached */ } -value caml_static_release_bytecode(value prog, value len) +CAMLnoret void caml_static_release_bytecode(value prog, value len) { caml_invalid_argument("Meta.static_release_bytecode"); - return Val_unit; /* not reached */ } #endif diff --git a/runtime/misc.c b/runtime/misc.c index 89e4e3266361..91d4878d4c3f 100644 --- a/runtime/misc.c +++ b/runtime/misc.c @@ -43,7 +43,8 @@ void caml_print_loc(const char_os *file_os, int line) { caml_stat_free(file); } -void caml_failed_assert (const char * expr, const char_os * file_os, int line) +CAMLnoret void caml_failed_assert(const char * expr, const char_os * file_os, + int line) { caml_print_loc(file_os, line); fprintf(stderr, "Assertion failed: %s\n", expr); @@ -127,14 +128,14 @@ CAMLexport void caml_fatal_error (const char *msg, ...) abort(); } -CAMLexport void caml_fatal_error_arg (const char *fmt, const char *arg) +CAMLnoret CAMLexport void caml_fatal_error_arg(const char *fmt, const char *arg) { fprintf (stderr, fmt, arg); exit(2); } -CAMLexport void caml_fatal_error_arg2 (const char *fmt1, const char *arg1, - const char *fmt2, const char *arg2) +CAMLnoret CAMLexport void caml_fatal_error_arg2 ( + const char *fmt1, const char *arg1, const char *fmt2, const char *arg2) { fprintf (stderr, fmt1, arg1); fprintf (stderr, fmt2, arg2); diff --git a/runtime/parsing.c b/runtime/parsing.c index 0ca0cd61eb4b..5a39c3df2872 100644 --- a/runtime/parsing.c +++ b/runtime/parsing.c @@ -142,6 +142,7 @@ static int trace(void) return caml_params->parser_trace || Caml_state->parser_trace; } +CAMLformat(__printf__, 1, 2) static void print_trace (const char *template, ...){ va_list ap; if(trace()) { diff --git a/runtime/startup_byt.c b/runtime/startup_byt.c index d438d7e8a8df..301e3b10c212 100644 --- a/runtime/startup_byt.c +++ b/runtime/startup_byt.c @@ -76,6 +76,7 @@ const char_os * caml_runtime_standard_library_effective = NULL; static char magicstr[EXEC_MAGIC_LENGTH+1]; /* Print the specified error message followed by an end-of-line and exit */ +CAMLformat(__printf__, 1, 2) static void error(const char *msg, ...) { va_list ap; diff --git a/runtime/sys.c b/runtime/sys.c index 606b87f90c8f..9dc86ce18910 100644 --- a/runtime/sys.c +++ b/runtime/sys.c @@ -193,7 +193,8 @@ CAML_RUNTIME_EVENTS_DESTROY(); exit(retcode); } -CAMLprim value caml_sys_exit(value retcode) +CAMLnoret +CAMLprim void caml_sys_exit(value retcode) { caml_do_exit(Int_val(retcode)); } diff --git a/yacc/defs.h b/yacc/defs.h index 344af5ae89a9..05512d890640 100644 --- a/yacc/defs.h +++ b/yacc/defs.h @@ -343,7 +343,7 @@ CAMLnoret extern void open_error (const char_os *filename); extern void output (void); extern void prec_redeclared (void); CAMLnoret extern void polymorphic_entry_point(char *s); -extern void forbidden_conflicts (void); +CAMLnoret extern void forbidden_conflicts (void); extern void reader (void); extern void reflexive_transitive_closure (unsigned int *R, int n); extern void reprec_warning (char *s); @@ -355,8 +355,8 @@ CAMLnoret extern void terminal_lhs (int s_lineno); CAMLnoret extern void terminal_start (char *s); CAMLnoret extern void tokenized_start (char *s); CAMLnoret extern void too_many_entries (void); -extern void undefined_goal (char *s); -extern void undefined_symbol (char *s); +CAMLnoret extern void undefined_goal (char *s); +CAMLnoret extern void undefined_symbol (char *s); CAMLnoret extern void unexpected_EOF (void); CAMLnoret extern void unknown_rhs (int i); CAMLnoret extern void unterminated_action (int a_lineno, char *a_line, char *a_cptr); diff --git a/yacc/main.c b/yacc/main.c index 59cf02d5c223..aa5211dfa0b5 100644 --- a/yacc/main.c +++ b/yacc/main.c @@ -160,7 +160,7 @@ static void set_signals(void) } -void usage(void) +CAMLnoret void usage(void) { fprintf(stderr, "usage: %s [-v] [--strict] [-q] [-b file_prefix] filename\n", myname); @@ -267,7 +267,7 @@ no_more_options:; } } - +CAMLmalloc(free, 1, 1) char * allocate(unsigned int n) {