summary refs log tree commit diff stats
path: root/include/qapi
diff options
context:
space:
mode:
Diffstat (limited to 'include/qapi')
-rw-r--r--include/qapi/clone-visitor.h8
-rw-r--r--include/qapi/error.h261
-rw-r--r--include/qapi/visitor-impl.h26
-rw-r--r--include/qapi/visitor.h102
4 files changed, 307 insertions, 90 deletions
diff --git a/include/qapi/clone-visitor.h b/include/qapi/clone-visitor.h
index 5b665ee38c..adf9a788e2 100644
--- a/include/qapi/clone-visitor.h
+++ b/include/qapi/clone-visitor.h
@@ -20,10 +20,10 @@
  */
 typedef struct QapiCloneVisitor QapiCloneVisitor;
 
-void *qapi_clone(const void *src, void (*visit_type)(Visitor *, const char *,
+void *qapi_clone(const void *src, bool (*visit_type)(Visitor *, const char *,
                                                      void **, Error **));
 void qapi_clone_members(void *dst, const void *src, size_t sz,
-                        void (*visit_type_members)(Visitor *, void *,
+                        bool (*visit_type_members)(Visitor *, void *,
                                                    Error **));
 
 /*
@@ -34,7 +34,7 @@ void qapi_clone_members(void *dst, const void *src, size_t sz,
  */
 #define QAPI_CLONE(type, src)                                           \
     ((type *)qapi_clone(src,                                            \
-                        (void (*)(Visitor *, const char *, void**,      \
+                        (bool (*)(Visitor *, const char *, void **,     \
                                   Error **))visit_type_ ## type))
 
 /*
@@ -45,7 +45,7 @@ void qapi_clone_members(void *dst, const void *src, size_t sz,
  */
 #define QAPI_CLONE_MEMBERS(type, dst, src)                              \
     qapi_clone_members(dst, src, sizeof(type),                          \
-                       (void (*)(Visitor *, void *,                     \
+                       (bool (*)(Visitor *, void *,                     \
                                  Error **))visit_type_ ## type ## _members)
 
 #endif
diff --git a/include/qapi/error.h b/include/qapi/error.h
index ad5b6e896d..7932594dce 100644
--- a/include/qapi/error.h
+++ b/include/qapi/error.h
@@ -15,18 +15,55 @@
 /*
  * Error reporting system loosely patterned after Glib's GError.
  *
+ * = Rules =
+ *
+ * - Functions that use Error to report errors have an Error **errp
+ *   parameter.  It should be the last parameter, except for functions
+ *   taking variable arguments.
+ *
+ * - You may pass NULL to not receive the error, &error_abort to abort
+ *   on error, &error_fatal to exit(1) on error, or a pointer to a
+ *   variable containing NULL to receive the error.
+ *
+ * - Separation of concerns: the function is responsible for detecting
+ *   errors and failing cleanly; handling the error is its caller's
+ *   job.  Since the value of @errp is about handling the error, the
+ *   function should not examine it.
+ *
+ * - The function may pass @errp to functions it calls to pass on
+ *   their errors to its caller.  If it dereferences @errp to check
+ *   for errors, it must use ERRP_GUARD().
+ *
+ * - On success, the function should not touch *errp.  On failure, it
+ *   should set a new error, e.g. with error_setg(errp, ...), or
+ *   propagate an existing one, e.g. with error_propagate(errp, ...).
+ *
+ * - Whenever practical, also return a value that indicates success /
+ *   failure.  This can make the error checking more concise, and can
+ *   avoid useless error object creation and destruction.  Note that
+ *   we still have many functions returning void.  We recommend
+ *   • bool-valued functions return true on success / false on failure,
+ *   • pointer-valued functions return non-null / null pointer, and
+ *   • integer-valued functions return non-negative / negative.
+ *
+ * = Creating errors =
+ *
  * Create an error:
- *     error_setg(&err, "situation normal, all fouled up");
+ *     error_setg(errp, "situation normal, all fouled up");
+ * where @errp points to the location to receive the error.
  *
  * Create an error and add additional explanation:
- *     error_setg(&err, "invalid quark");
- *     error_append_hint(&err, "Valid quarks are up, down, strange, "
+ *     error_setg(errp, "invalid quark");
+ *     error_append_hint(errp, "Valid quarks are up, down, strange, "
  *                       "charm, top, bottom.\n");
+ * This may require use of ERRP_GUARD(); more on that below.
  *
  * Do *not* contract this to
- *     error_setg(&err, "invalid quark\n"
+ *     error_setg(errp, "invalid quark\n" // WRONG!
  *                "Valid quarks are up, down, strange, charm, top, bottom.");
  *
+ * = Reporting and destroying errors =
+ *
  * Report an error to the current monitor if we have one, else stderr:
  *     error_report_err(err);
  * This frees the error object.
@@ -40,6 +77,30 @@
  *     error_free(err);
  * Note that this loses hints added with error_append_hint().
  *
+ * Call a function ignoring errors:
+ *     foo(arg, NULL);
+ * This is more concise than
+ *     Error *err = NULL;
+ *     foo(arg, &err);
+ *     error_free(err); // don't do this
+ *
+ * Call a function aborting on errors:
+ *     foo(arg, &error_abort);
+ * This is more concise and fails more nicely than
+ *     Error *err = NULL;
+ *     foo(arg, &err);
+ *     assert(!err); // don't do this
+ *
+ * Call a function treating errors as fatal:
+ *     foo(arg, &error_fatal);
+ * This is more concise than
+ *     Error *err = NULL;
+ *     foo(arg, &err);
+ *     if (err) { // don't do this
+ *         error_report_err(err);
+ *         exit(1);
+ *     }
+ *
  * Handle an error without reporting it (just for completeness):
  *     error_free(err);
  *
@@ -47,57 +108,73 @@
  * reporting it (primarily useful in testsuites):
  *     error_free_or_abort(&err);
  *
- * Pass an existing error to the caller:
- *     error_propagate(errp, err);
- * where Error **errp is a parameter, by convention the last one.
+ * = Passing errors around =
  *
- * Pass an existing error to the caller with the message modified:
- *     error_propagate_prepend(errp, err);
- *
- * Avoid
- *     error_propagate(errp, err);
- *     error_prepend(errp, "Could not frobnicate '%s': ", name);
- * because this fails to prepend when @errp is &error_fatal.
+ * Errors get passed to the caller through the conventional @errp
+ * parameter.
  *
  * Create a new error and pass it to the caller:
  *     error_setg(errp, "situation normal, all fouled up");
  *
- * Call a function and receive an error from it:
- *     Error *err = NULL;
- *     foo(arg, &err);
- *     if (err) {
+ * Call a function, receive an error from it, and pass it to the caller
+ * - when the function returns a value that indicates failure, say
+ *   false:
+ *     if (!foo(arg, errp)) {
  *         handle the error...
  *     }
+ * - when it does not, say because it is a void function:
+ *     ERRP_GUARD();
+ *     foo(arg, errp);
+ *     if (*errp) {
+ *         handle the error...
+ *     }
+ * More on ERRP_GUARD() below.
  *
- * Call a function ignoring errors:
- *     foo(arg, NULL);
- *
- * Call a function aborting on errors:
- *     foo(arg, &error_abort);
- *
- * Call a function treating errors as fatal:
- *     foo(arg, &error_fatal);
- *
- * Receive an error and pass it on to the caller:
+ * Code predating ERRP_GUARD() still exists, and looks like this:
  *     Error *err = NULL;
  *     foo(arg, &err);
  *     if (err) {
  *         handle the error...
- *         error_propagate(errp, err);
+ *         error_propagate(errp, err); // deprecated
  *     }
- * where Error **errp is a parameter, by convention the last one.
- *
- * Do *not* "optimize" this to
+ * Avoid in new code.  Do *not* "optimize" it to
  *     foo(arg, errp);
  *     if (*errp) { // WRONG!
  *         handle the error...
  *     }
- * because errp may be NULL!
+ * because errp may be NULL without the ERRP_GUARD() guard.
  *
  * But when all you do with the error is pass it on, please use
  *     foo(arg, errp);
  * for readability.
  *
+ * Receive an error, and handle it locally
+ * - when the function returns a value that indicates failure, say
+ *   false:
+ *     Error *err = NULL;
+ *     if (!foo(arg, &err)) {
+ *         handle the error...
+ *     }
+ * - when it does not, say because it is a void function:
+ *     Error *err = NULL;
+ *     foo(arg, &err);
+ *     if (err) {
+ *         handle the error...
+ *     }
+ *
+ * Pass an existing error to the caller:
+ *     error_propagate(errp, err);
+ * This is rarely needed.  When @err is a local variable, use of
+ * ERRP_GUARD() commonly results in more readable code.
+ *
+ * Pass an existing error to the caller with the message modified:
+ *     error_propagate_prepend(errp, err,
+ *                             "Could not frobnicate '%s': ", name);
+ * This is more concise than
+ *     error_propagate(errp, err); // don't do this
+ *     error_prepend(errp, "Could not frobnicate '%s': ", name);
+ * and works even when @errp is &error_fatal.
+ *
  * Receive and accumulate multiple errors (first one wins):
  *     Error *err = NULL, *local_err = NULL;
  *     foo(arg, &err);
@@ -108,12 +185,88 @@
  *     }
  *
  * Do *not* "optimize" this to
+ *     Error *err = NULL;
  *     foo(arg, &err);
  *     bar(arg, &err); // WRONG!
  *     if (err) {
  *         handle the error...
  *     }
  * because this may pass a non-null err to bar().
+ *
+ * Likewise, do *not*
+ *     Error *err = NULL;
+ *     if (cond1) {
+ *         error_setg(&err, ...);
+ *     }
+ *     if (cond2) {
+ *         error_setg(&err, ...); // WRONG!
+ *     }
+ * because this may pass a non-null err to error_setg().
+ *
+ * = Why, when and how to use ERRP_GUARD() =
+ *
+ * Without ERRP_GUARD(), use of the @errp parameter is restricted:
+ * - It must not be dereferenced, because it may be null.
+ * - It should not be passed to error_prepend() or
+ *   error_append_hint(), because that doesn't work with &error_fatal.
+ * ERRP_GUARD() lifts these restrictions.
+ *
+ * To use ERRP_GUARD(), add it right at the beginning of the function.
+ * @errp can then be used without worrying about the argument being
+ * NULL or &error_fatal.
+ *
+ * Using it when it's not needed is safe, but please avoid cluttering
+ * the source with useless code.
+ *
+ * = Converting to ERRP_GUARD() =
+ *
+ * To convert a function to use ERRP_GUARD():
+ *
+ * 0. If the Error ** parameter is not named @errp, rename it to
+ *    @errp.
+ *
+ * 1. Add an ERRP_GUARD() invocation, by convention right at the
+ *    beginning of the function.  This makes @errp safe to use.
+ *
+ * 2. Replace &err by errp, and err by *errp.  Delete local variable
+ *    @err.
+ *
+ * 3. Delete error_propagate(errp, *errp), replace
+ *    error_propagate_prepend(errp, *errp, ...) by error_prepend(errp, ...)
+ *
+ * 4. Ensure @errp is valid at return: when you destroy *errp, set
+ *    errp = NULL.
+ *
+ * Example:
+ *
+ *     bool fn(..., Error **errp)
+ *     {
+ *         Error *err = NULL;
+ *
+ *         foo(arg, &err);
+ *         if (err) {
+ *             handle the error...
+ *             error_propagate(errp, err);
+ *             return false;
+ *         }
+ *         ...
+ *     }
+ *
+ * becomes
+ *
+ *     bool fn(..., Error **errp)
+ *     {
+ *         ERRP_GUARD();
+ *
+ *         foo(arg, errp);
+ *         if (*errp) {
+ *             handle the error...
+ *             return false;
+ *         }
+ *         ...
+ *     }
+ *
+ * For mass-conversion, use scripts/coccinelle/errp-guard.cocci.
  */
 
 #ifndef ERROR_H
@@ -214,6 +367,7 @@ void error_setg_win32_internal(Error **errp,
  * the error object.
  * Else, move the error object from @local_err to *@dst_errp.
  * On return, @local_err is invalid.
+ * Please use ERRP_GUARD() instead when possible.
  * Please don't error_propagate(&error_fatal, ...), use
  * error_report_err() and exit(), because that's more obvious.
  */
@@ -225,6 +379,7 @@ void error_propagate(Error **dst_errp, Error *local_err);
  * Behaves like
  *     error_prepend(&local_err, fmt, ...);
  *     error_propagate(dst_errp, local_err);
+ * Please use ERRP_GUARD() and error_prepend() instead when possible.
  */
 void error_propagate_prepend(Error **dst_errp, Error *local_err,
                              const char *fmt, ...);
@@ -323,6 +478,46 @@ void error_set_internal(Error **errp,
     GCC_FMT_ATTR(6, 7);
 
 /*
+ * Make @errp parameter easier to use regardless of argument value
+ *
+ * This macro is for use right at the beginning of a function that
+ * takes an Error **errp parameter to pass errors to its caller.  The
+ * parameter must be named @errp.
+ *
+ * It must be used when the function dereferences @errp or passes
+ * @errp to error_prepend(), error_vprepend(), or error_append_hint().
+ * It is safe to use even when it's not needed, but please avoid
+ * cluttering the source with useless code.
+ *
+ * If @errp is NULL or &error_fatal, rewrite it to point to a local
+ * Error variable, which will be automatically propagated to the
+ * original @errp on function exit.
+ *
+ * Note: &error_abort is not rewritten, because that would move the
+ * abort from the place where the error is created to the place where
+ * it's propagated.
+ */
+#define ERRP_GUARD()                                            \
+    g_auto(ErrorPropagator) _auto_errp_prop = {.errp = errp};   \
+    do {                                                        \
+        if (!errp || errp == &error_fatal) {                    \
+            errp = &_auto_errp_prop.local_err;                  \
+        }                                                       \
+    } while (0)
+
+typedef struct ErrorPropagator {
+    Error *local_err;
+    Error **errp;
+} ErrorPropagator;
+
+static inline void error_propagator_cleanup(ErrorPropagator *prop)
+{
+    error_propagate(prop->errp, prop->local_err);
+}
+
+G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ErrorPropagator, error_propagator_cleanup);
+
+/*
  * Special error destination to abort on error.
  * See error_setg() and error_propagate() for details.
  */
diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index 98dc533d39..7362c043be 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -48,31 +48,31 @@ struct Visitor
      */
 
     /* Must be set to visit structs */
-    void (*start_struct)(Visitor *v, const char *name, void **obj,
+    bool (*start_struct)(Visitor *v, const char *name, void **obj,
                          size_t size, Error **errp);
 
     /* Optional; intended for input visitors */
-    void (*check_struct)(Visitor *v, Error **errp);
+    bool (*check_struct)(Visitor *v, Error **errp);
 
     /* Must be set to visit structs */
     void (*end_struct)(Visitor *v, void **obj);
 
     /* Must be set; implementations may require @list to be non-null,
      * but must document it. */
-    void (*start_list)(Visitor *v, const char *name, GenericList **list,
+    bool (*start_list)(Visitor *v, const char *name, GenericList **list,
                        size_t size, Error **errp);
 
     /* Must be set */
     GenericList *(*next_list)(Visitor *v, GenericList *tail, size_t size);
 
     /* Optional; intended for input visitors */
-    void (*check_list)(Visitor *v, Error **errp);
+    bool (*check_list)(Visitor *v, Error **errp);
 
     /* Must be set */
     void (*end_list)(Visitor *v, void **list);
 
     /* Must be set by input and clone visitors to visit alternates */
-    void (*start_alternate)(Visitor *v, const char *name,
+    bool (*start_alternate)(Visitor *v, const char *name,
                             GenericAlternate **obj, size_t size,
                             Error **errp);
 
@@ -80,33 +80,33 @@ struct Visitor
     void (*end_alternate)(Visitor *v, void **obj);
 
     /* Must be set */
-    void (*type_int64)(Visitor *v, const char *name, int64_t *obj,
+    bool (*type_int64)(Visitor *v, const char *name, int64_t *obj,
                        Error **errp);
 
     /* Must be set */
-    void (*type_uint64)(Visitor *v, const char *name, uint64_t *obj,
+    bool (*type_uint64)(Visitor *v, const char *name, uint64_t *obj,
                         Error **errp);
 
     /* Optional; fallback is type_uint64() */
-    void (*type_size)(Visitor *v, const char *name, uint64_t *obj,
+    bool (*type_size)(Visitor *v, const char *name, uint64_t *obj,
                       Error **errp);
 
     /* Must be set */
-    void (*type_bool)(Visitor *v, const char *name, bool *obj, Error **errp);
+    bool (*type_bool)(Visitor *v, const char *name, bool *obj, Error **errp);
 
     /* Must be set */
-    void (*type_str)(Visitor *v, const char *name, char **obj, Error **errp);
+    bool (*type_str)(Visitor *v, const char *name, char **obj, Error **errp);
 
     /* Must be set to visit numbers */
-    void (*type_number)(Visitor *v, const char *name, double *obj,
+    bool (*type_number)(Visitor *v, const char *name, double *obj,
                         Error **errp);
 
     /* Must be set to visit arbitrary QTypes */
-    void (*type_any)(Visitor *v, const char *name, QObject **obj,
+    bool (*type_any)(Visitor *v, const char *name, QObject **obj,
                      Error **errp);
 
     /* Must be set to visit explicit null values.  */
-    void (*type_null)(Visitor *v, const char *name, QNull **obj,
+    bool (*type_null)(Visitor *v, const char *name, QNull **obj,
                       Error **errp);
 
     /* Must be set for input visitors to visit structs, optional otherwise.
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 5573906966..ebc19ede7f 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -60,7 +60,7 @@
  * All QAPI types have a corresponding function with a signature
  * roughly compatible with this:
  *
- * void visit_type_FOO(Visitor *v, const char *name, T obj, Error **errp);
+ * bool visit_type_FOO(Visitor *v, const char *name, T obj, Error **errp);
  *
  * where T is FOO for scalar types, and FOO * otherwise.  The scalar
  * visitors are declared here; the remaining visitors are generated in
@@ -95,14 +95,16 @@
  * incomplete object, such an object is possible only by manual
  * construction.
  *
+ * visit_type_FOO() returns true on success, false on error.
+ *
  * For the QAPI object types (structs, unions, and alternates), there
  * is an additional generated function in qapi-visit-MODULE.h
  * compatible with:
  *
- * void visit_type_FOO_members(Visitor *v, FOO *obj, Error **errp);
+ * bool visit_type_FOO_members(Visitor *v, FOO *obj, Error **errp);
  *
  * for visiting the members of a type without also allocating the QAPI
- * struct.
+ * struct.  It also returns true on success, false on error.
  *
  * Additionally, QAPI pointer types (structs, unions, alternates, and
  * lists) have a generated function in qapi-types-MODULE.h compatible
@@ -131,8 +133,7 @@
  *  Visitor *v;
  *
  *  v = FOO_visitor_new(...);
- *  visit_type_Foo(v, NULL, &f, &err);
- *  if (err) {
+ *  if (!visit_type_Foo(v, NULL, &f, &err)) {
  *      ...handle error...
  *  } else {
  *      ...use f...
@@ -148,8 +149,7 @@
  *  Visitor *v;
  *
  *  v = FOO_visitor_new(...);
- *  visit_type_FooList(v, NULL, &l, &err);
- *  if (err) {
+ *  if (!visit_type_FooList(v, NULL, &l, &err)) {
  *      ...handle error...
  *  } else {
  *      for ( ; l; l = l->next) {
@@ -186,34 +186,32 @@
  * <example>
  *  Visitor *v;
  *  Error *err = NULL;
+ *  bool ok = false;
  *  int value;
  *
  *  v = FOO_visitor_new(...);
- *  visit_start_struct(v, NULL, NULL, 0, &err);
- *  if (err) {
+ *  if (!visit_start_struct(v, NULL, NULL, 0, &err)) {
  *      goto out;
  *  }
- *  visit_start_list(v, "list", NULL, 0, &err);
- *  if (err) {
+ *  if (!visit_start_list(v, "list", NULL, 0, &err)) {
  *      goto outobj;
  *  }
  *  value = 1;
- *  visit_type_int(v, NULL, &value, &err);
- *  if (err) {
+ *  if (!visit_type_int(v, NULL, &value, &err)) {
  *      goto outlist;
  *  }
  *  value = 2;
- *  visit_type_int(v, NULL, &value, &err);
- *  if (err) {
+ *  if (!visit_type_int(v, NULL, &value, &err)) {
  *      goto outlist;
  *  }
+ *  ok = true;
  * outlist:
- *  if (!err) {
- *      visit_check_list(v, &err);
+ *  if (ok) {
+ *      ok = visit_check_list(v, &err);
  *  }
  *  visit_end_list(v, NULL);
- *  if (!err) {
- *      visit_check_struct(v, &err);
+ *  if (ok) {
+ *      ok = visit_check_struct(v, &err);
  *  }
  * outobj:
  *  visit_end_struct(v, NULL);
@@ -286,6 +284,8 @@ void visit_free(Visitor *v);
  * On failure, set *@obj to NULL and store an error through @errp.
  * Can happen only when @v is an input visitor.
  *
+ * Return true on success, false on failure.
+ *
  * After visit_start_struct() succeeds, the caller may visit its
  * members one after the other, passing the member's name and address
  * within the struct.  Finally, visit_end_struct() needs to be called
@@ -295,7 +295,7 @@ void visit_free(Visitor *v);
  * FIXME Should this be named visit_start_object, since it is also
  * used for QAPI unions, and maps to JSON objects?
  */
-void visit_start_struct(Visitor *v, const char *name, void **obj,
+bool visit_start_struct(Visitor *v, const char *name, void **obj,
                         size_t size, Error **errp);
 
 /*
@@ -304,12 +304,14 @@ void visit_start_struct(Visitor *v, const char *name, void **obj,
  * On failure, store an error through @errp.  Can happen only when @v
  * is an input visitor.
  *
+ * Return true on success, false on failure.
+ *
  * Should be called prior to visit_end_struct() if all other
  * intermediate visit steps were successful, to allow the visitor one
  * last chance to report errors.  May be skipped on a cleanup path,
  * where there is no need to check for further errors.
  */
-void visit_check_struct(Visitor *v, Error **errp);
+bool visit_check_struct(Visitor *v, Error **errp);
 
 /*
  * Complete an object visit started earlier.
@@ -341,6 +343,8 @@ void visit_end_struct(Visitor *v, void **obj);
  * On failure, set *@list to NULL and store an error through @errp.
  * Can happen only when @v is an input visitor.
  *
+ * Return true on success, false on failure.
+ *
  * After visit_start_list() succeeds, the caller may visit its members
  * one after the other.  A real visit (where @list is non-NULL) uses
  * visit_next_list() for traversing the linked list, while a virtual
@@ -351,7 +355,7 @@ void visit_end_struct(Visitor *v, void **obj);
  * same @list to clean up, even if intermediate visits fail.  See the
  * examples above.
  */
-void visit_start_list(Visitor *v, const char *name, GenericList **list,
+bool visit_start_list(Visitor *v, const char *name, GenericList **list,
                       size_t size, Error **errp);
 
 /*
@@ -376,12 +380,14 @@ GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size);
  * On failure, store an error through @errp.  Can happen only when @v
  * is an input visitor.
  *
+ * Return true on success, false on failure.
+ *
  * Should be called prior to visit_end_list() if all other
  * intermediate visit steps were successful, to allow the visitor one
  * last chance to report errors.  May be skipped on a cleanup path,
  * where there is no need to check for further errors.
  */
-void visit_check_list(Visitor *v, Error **errp);
+bool visit_check_list(Visitor *v, Error **errp);
 
 /*
  * Complete a list visit started earlier.
@@ -412,11 +418,13 @@ void visit_end_list(Visitor *v, void **list);
  * On failure, set *@obj to NULL and store an error through @errp.
  * Can happen only when @v is an input visitor.
  *
+ * Return true on success, false on failure.
+ *
  * If successful, this must be paired with visit_end_alternate() with
  * the same @obj to clean up, even if visiting the contents of the
  * alternate fails.
  */
-void visit_start_alternate(Visitor *v, const char *name,
+bool visit_start_alternate(Visitor *v, const char *name,
                            GenericAlternate **obj, size_t size,
                            Error **errp);
 
@@ -468,12 +476,14 @@ bool visit_optional(Visitor *v, const char *name, bool *present);
  * On failure, store an error through @errp.  Can happen only when @v
  * is an input visitor.
  *
+ * Return true on success, false on failure.
+ *
  * May call visit_type_str() under the hood, and the enum visit may
  * fail even if the corresponding string visit succeeded; this implies
  * that an input visitor's visit_type_str() must have no unwelcome
  * side effects.
  */
-void visit_type_enum(Visitor *v, const char *name, int *obj,
+bool visit_type_enum(Visitor *v, const char *name, int *obj,
                      const QEnumLookup *lookup, Error **errp);
 
 /*
@@ -499,28 +509,30 @@ bool visit_is_dealloc(Visitor *v);
  *
  * On failure, store an error through @errp.  Can happen only when @v
  * is an input visitor.
+ *
+ * Return true on success, false on failure.
  */
-void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp);
+bool visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp);
 
 /*
  * Visit a uint8_t value.
  * Like visit_type_int(), except clamps the value to uint8_t range.
  */
-void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
+bool visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
                       Error **errp);
 
 /*
  * Visit a uint16_t value.
  * Like visit_type_int(), except clamps the value to uint16_t range.
  */
-void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
+bool visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
                        Error **errp);
 
 /*
  * Visit a uint32_t value.
  * Like visit_type_int(), except clamps the value to uint32_t range.
  */
-void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj,
+bool visit_type_uint32(Visitor *v, const char *name, uint32_t *obj,
                        Error **errp);
 
 /*
@@ -528,34 +540,34 @@ void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj,
  * Like visit_type_int(), except clamps the value to uint64_t range,
  * that is, ensures it is unsigned.
  */
-void visit_type_uint64(Visitor *v, const char *name, uint64_t *obj,
+bool visit_type_uint64(Visitor *v, const char *name, uint64_t *obj,
                        Error **errp);
 
 /*
  * Visit an int8_t value.
  * Like visit_type_int(), except clamps the value to int8_t range.
  */
-void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp);
+bool visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp);
 
 /*
  * Visit an int16_t value.
  * Like visit_type_int(), except clamps the value to int16_t range.
  */
-void visit_type_int16(Visitor *v, const char *name, int16_t *obj,
+bool visit_type_int16(Visitor *v, const char *name, int16_t *obj,
                       Error **errp);
 
 /*
  * Visit an int32_t value.
  * Like visit_type_int(), except clamps the value to int32_t range.
  */
-void visit_type_int32(Visitor *v, const char *name, int32_t *obj,
+bool visit_type_int32(Visitor *v, const char *name, int32_t *obj,
                       Error **errp);
 
 /*
  * Visit an int64_t value.
  * Identical to visit_type_int().
  */
-void visit_type_int64(Visitor *v, const char *name, int64_t *obj,
+bool visit_type_int64(Visitor *v, const char *name, int64_t *obj,
                       Error **errp);
 
 /*
@@ -564,7 +576,7 @@ void visit_type_int64(Visitor *v, const char *name, int64_t *obj,
  * recognize additional syntax, such as suffixes for easily scaling
  * values.
  */
-void visit_type_size(Visitor *v, const char *name, uint64_t *obj,
+bool visit_type_size(Visitor *v, const char *name, uint64_t *obj,
                      Error **errp);
 
 /*
@@ -578,8 +590,10 @@ void visit_type_size(Visitor *v, const char *name, uint64_t *obj,
  *
  * On failure, store an error through @errp.  Can happen only when @v
  * is an input visitor.
+ *
+ * Return true on success, false on failure.
  */
-void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp);
+bool visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp);
 
 /*
  * Visit a string value.
@@ -598,9 +612,11 @@ void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp);
  * On failure, set *@obj to NULL and store an error through @errp.
  * Can happen only when @v is an input visitor.
  *
+ * Return true on success, false on failure.
+ *
  * FIXME: Callers that try to output NULL *obj should not be allowed.
  */
-void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp);
+bool visit_type_str(Visitor *v, const char *name, char **obj, Error **errp);
 
 /*
  * Visit a number (i.e. double) value.
@@ -614,8 +630,10 @@ void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp);
  *
  * On failure, store an error through @errp.  Can happen only when @v
  * is an input visitor.
+ *
+ * Return true on success, false on failure.
  */
-void visit_type_number(Visitor *v, const char *name, double *obj,
+bool visit_type_number(Visitor *v, const char *name, double *obj,
                        Error **errp);
 
 /*
@@ -631,11 +649,13 @@ void visit_type_number(Visitor *v, const char *name, double *obj,
  * On failure, set *@obj to NULL and store an error through @errp.
  * Can happen only when @v is an input visitor.
  *
+ * Return true on success, false on failure.
+ *
  * Note that some kinds of input can't express arbitrary QObject.
  * E.g. the visitor returned by qobject_input_visitor_new_keyval()
  * can't create numbers or booleans, only strings.
  */
-void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp);
+bool visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp);
 
 /*
  * Visit a JSON null value.
@@ -648,8 +668,10 @@ void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp);
  *
  * On failure, set *@obj to NULL and store an error through @errp.
  * Can happen only when @v is an input visitor.
+ *
+ * Return true on success, false on failure.
  */
-void visit_type_null(Visitor *v, const char *name, QNull **obj,
+bool visit_type_null(Visitor *v, const char *name, QNull **obj,
                      Error **errp);
 
 #endif