@@ -627,6 +627,19 @@ Object *object_new_with_class(ObjectClass *klass);
*/
Object *object_new(const char *typename);
+/**
+ * object_new_allowed:
+ * @klass: The class to instantiate, or fetch instance from.
+ * @errp: The pointer to an Error* that might be filled
+ *
+ * This function detects whether creating a new object of specificed class
+ * is allowed. For example, we do not allow initiations of abstract class.
+ *
+ * Returns: True if new objects allowed, false otherwise. When false is
+ * returned, errp will be set with a proper error message.
+ */
+bool object_new_allowed(ObjectClass *klass, Error **errp);
+
/**
* object_new_with_props:
* @typename: The name of the type of the object to instantiate.
@@ -533,9 +533,7 @@ static const ChardevClass *char_get_class(const char *driver, Error **errp)
return NULL;
}
- if (object_class_is_abstract(oc)) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
- "a non-abstract device type");
+ if (!object_new_allowed(oc, errp)) {
return NULL;
}
@@ -154,12 +154,17 @@ ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model)
assert(cc->class_by_name);
assert(cpu_model);
oc = cc->class_by_name(cpu_model);
- if (object_class_dynamic_cast(oc, typename) &&
- !object_class_is_abstract(oc)) {
- return oc;
+
+ if (!object_class_dynamic_cast(oc, typename)) {
+ return NULL;
}
- return NULL;
+ /* TODO: allow error message to be passed to the callers */
+ if (!object_new_allowed(oc, NULL)) {
+ return NULL;
+ }
+
+ return oc;
}
static void cpu_common_parse_features(const char *typename, char *features,
@@ -797,6 +797,19 @@ Object *object_new(const char *typename)
return object_new_with_type(ti);
}
+bool object_new_allowed(ObjectClass *klass, Error **errp)
+{
+ ERRP_GUARD();
+
+ /* Abstract classes are not instantiable */
+ if (object_class_is_abstract(klass)) {
+ error_setg(errp, "Object type '%s' is abstract",
+ klass->type->name);
+ return false;
+ }
+
+ return true;
+}
Object *object_new_with_props(const char *typename,
Object *parent,
@@ -831,10 +844,10 @@ Object *object_new_with_propv(const char *typename,
return NULL;
}
- if (object_class_is_abstract(klass)) {
- error_setg(errp, "object type '%s' is abstract", typename);
+ if (!object_new_allowed(klass, errp)) {
return NULL;
}
+
obj = object_new_with_type(klass->type);
if (!object_set_propv(obj, errp, vargs)) {
@@ -102,8 +102,7 @@ Object *user_creatable_add_type(const char *type, const char *id,
return NULL;
}
- if (object_class_is_abstract(klass)) {
- error_setg(errp, "object type '%s' is abstract", type);
+ if (!object_new_allowed(klass, errp)) {
return NULL;
}
@@ -255,9 +255,7 @@ static DeviceClass *qdev_get_device_class(const char **driver, Error **errp)
return NULL;
}
- if (object_class_is_abstract(oc)) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
- "a non-abstract device type");
+ if (!object_new_allowed(oc, errp)) {
return NULL;
}
Add a helper object_new_allowed(), use it to track all the places in QEMU where a new (and especially, random) object can be created. Currently, it is some form of a cleanup, just to put together all the errors where QEMU wants to avoid instantiations of abstract classes. The follow up patch will add more restriction on what object we can create. A side effect of the cleanup: we could have reported the error message in different ways even if the reason is always the same (attempts to create an instance for an abstract class). Now we always report the same message, could be different from before, but hopefully still worthwhile to change. Signed-off-by: Peter Xu <peterx@redhat.com> --- include/qom/object.h | 13 +++++++++++++ chardev/char.c | 4 +--- hw/core/cpu-common.c | 13 +++++++++---- qom/object.c | 17 +++++++++++++++-- qom/object_interfaces.c | 3 +-- system/qdev-monitor.c | 4 +--- 6 files changed, 40 insertions(+), 14 deletions(-)