Following r1543145, the attached patch adds __attribute__((sentinel)) to functions that require a null sentinel argument, to make GCC warn if the argument is missing. Via a macro so only for GCC >= 4.0. (I don't see an equivalent attribute for MSC but if there is one we can add it.)
The patch also changes SVN_NO_ERROR from "0" to "((svn_error_t *)0)". This has the side effect of detecting other mis-uses: I committed two such fixes as http://svn.apache.org/r1543193 and http://svn.apache.org/r1543216 . I can't think of any negative consequences but shout out if you can. If no objections I'll commit tomorrow. - Julian
Following r1543145 (fixing a 'strange error' caused by a missing sentinel argument), tag the functions that require a null sentinel value at the end of their argument list such that GCC will warn if the sentinel argument is missing. I enabled this for GCC >= 4.0, according to anecdotal evidence. I don't see an equivalent attribute for MSC but if there is one we can add it. * subversion/include/svn_types.h (SVN_SENTINEL_NULL): Define. * subversion/include/svn_dirent_uri.h (svn_dirent_join_many): Tag. * subversion/include/svn_path.h (svn_path_join_many): Tag. * subversion/include/svn_xml.h (svn_xml_make_open_tag): Tag. * subversion/libsvn_ra_serf/ra_serf.h (svn_ra_serf__add_open_tag_buckets): Tag. * subversion/svn/cl.h (svn_cl__try): Tag. * subversion/include/svn_error.h (SVN_NO_ERROR): Define as a pointer type so that it can be detected as a valid sentinel argument (with svn_cl__try). This will also help to detect mis-use in other contexts. --This line, and those below, will be ignored-- Index: subversion/include/svn_dirent_uri.h =================================================================== --- subversion/include/svn_dirent_uri.h (revision 1543175) +++ subversion/include/svn_dirent_uri.h (working copy) @@ -215,13 +215,13 @@ svn_dirent_join(const char *base, * * @since New in 1.6. */ char * svn_dirent_join_many(apr_pool_t *result_pool, const char *base, - ...); + ...) SVN_SENTINEL_NULL; /** Join a base relpath (@a base) with a component (@a component). * @a component need not be a single component. * * If either @a base or @a component is the empty path, then the other * argument will be copied and returned. If both are the empty path the Index: subversion/include/svn_error.h =================================================================== --- subversion/include/svn_error.h (revision 1543175) +++ subversion/include/svn_error.h (working copy) @@ -48,13 +48,13 @@ extern "C" { #ifdef SVN_DEBUG #define SVN_ERR__TRACING #endif /** the best kind of (@c svn_error_t *) ! */ -#define SVN_NO_ERROR 0 +#define SVN_NO_ERROR ((svn_error_t *)0) /* The actual error codes are kept in a separate file; see comments there for the reasons why. */ #include "svn_error_codes.h" /** Put an English description of @a statcode into @a buf and return @a buf, Index: subversion/include/svn_path.h =================================================================== --- subversion/include/svn_path.h (revision 1543175) +++ subversion/include/svn_path.h (working copy) @@ -128,13 +128,13 @@ svn_path_join(const char *base, const ch * @deprecated Provided for backward compatibility with the 1.6 API. * For new code, consider using svn_dirent_join_many() or a sequence of * calls to one of the *_join() functions. */ SVN_DEPRECATED char * -svn_path_join_many(apr_pool_t *pool, const char *base, ...); +svn_path_join_many(apr_pool_t *pool, const char *base, ...) SVN_SENTINEL_NULL; /** Get the basename of the specified canonicalized @a path. The * basename is defined as the last component of the path (ignoring any * trailing slashes). If the @a path is root ("/"), then that is * returned. Otherwise, the returned value will have no slashes in Index: subversion/include/svn_types.h =================================================================== --- subversion/include/svn_types.h (revision 1543175) +++ subversion/include/svn_types.h (working copy) @@ -86,12 +86,34 @@ extern "C" { # endif # else # define SVN_EXPERIMENTAL # endif #endif +/** Macro used to mark functions that require a final null sentinel argument. + * + * @since New in 1.9. + */ +#ifndef SVN_SENTINEL_NULL +# if !defined(SWIGPERL) && !defined(SWIGPYTHON) && !defined(SWIGRUBY) +# if defined(__has_attribute) +# if __has_attribute(__sentinel__) +# define SVN_SENTINEL_NULL __attribute__((sentinel)) +# else +# define SVN_SENTINEL_NULL +# endif +# elif defined(__GNUC__) && (__GNUC__ >= 4) +# define SVN_SENTINEL_NULL __attribute__((sentinel)) +# else +# define SVN_SENTINEL_NULL +# endif +# else +# define SVN_SENTINEL_NULL +# endif +#endif + /** Indicate whether the current platform supports unaligned data access. * * On the majority of machines running SVN (x86 / x64), unaligned access * is much cheaper than repeated aligned access. Define this macro to 1 * on those machines. Index: subversion/include/svn_xml.h =================================================================== --- subversion/include/svn_xml.h (revision 1543175) +++ subversion/include/svn_xml.h (working copy) @@ -320,13 +320,13 @@ svn_xml_make_header(svn_stringbuf_t **st */ void svn_xml_make_open_tag(svn_stringbuf_t **str, apr_pool_t *pool, enum svn_xml_open_tag_style style, const char *tagname, - ...); + ...) SVN_SENTINEL_NULL; /** Like svn_xml_make_open_tag(), but takes a @c va_list instead of being * variadic. */ void Index: subversion/libsvn_ra_serf/ra_serf.h =================================================================== --- subversion/libsvn_ra_serf/ra_serf.h (revision 1543175) +++ subversion/libsvn_ra_serf/ra_serf.h (working copy) @@ -1052,13 +1052,13 @@ svn_ra_serf__add_xml_header_buckets(serf * The bucket will be allocated from BKT_ALLOC. */ void svn_ra_serf__add_open_tag_buckets(serf_bucket_t *agg_bucket, serf_bucket_alloc_t *bkt_alloc, const char *tag, - ...); + ...) SVN_SENTINEL_NULL; /* * Add the appropriate serf buckets to AGG_BUCKET representing xml tag close * with name TAG. * * The bucket will be allocated from BKT_ALLOC. Index: subversion/svn/cl.h =================================================================== --- subversion/svn/cl.h (revision 1543175) +++ subversion/svn/cl.h (working copy) @@ -323,13 +323,13 @@ extern const apr_getopt_option_t svn_cl_ * forget to terminate the argument list with SVN_NO_ERROR. */ svn_error_t * svn_cl__try(svn_error_t *err, apr_array_header_t *errors_seen, svn_boolean_t quiet, - ...); + ...) SVN_SENTINEL_NULL; /* Our cancellation callback. */ svn_error_t * svn_cl__check_cancel(void *baton);