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);