On 05/03/2016 05:53 AM, Markus Armbruster wrote:
> Okay, I'm confused.
> 
> Consider BlockdevRef, defined as
> 
>     { 'alternate': 'BlockdevRef',
>       'data': { 'definition': 'BlockdevOptions',
>                 'reference': 'str' } }
> 
> where BlockdevOptions is a (flat) union.  Let's clone a BlockdevRef
> holding a str.  Sequence of calls:
> 
>     qapi_BlockdevRef_clone(src)
>         qapi_clone_visitor_new(src)
>         // qcv->depth is now 0
>         visit_type_BlockdevRef(v, NULL, &dst, &error_abort)
>             visit_start_alternate(v, NULL, &dst,
>                                   sizeof(BlockdevRef), true, &error_abort)
>                 qapi_clone_start_alternate(v, NULL, &dst,
>                                   sizeof(BlockdevRef), true, &error_abort)

so far, so good,

>                     qapi_clone_start_struct(v, NULL, &dst,
>                                   sizeof(BlockdevRef), &error_abort)

Not reached if it holds a string. qapi_clone_start_alternate() sets
dst->type to QTYPE_QSTRING, but qapi_clone_start_struct() is only used
for QTYPE_QDICT.

>                         // does not increment qcv->depth
>         visit_type_str(v, NULL, &dst->u.references, &error_abort)
>             qapi_clone_type_str(v, NULL, &dst->u.references, &error_abort)
>                 assert(qcv->depth)  // why does this hold?

Either we call:

visit_start_alternate()
  visit_start_struct(NULL)
  visit_end_struct()
visit_end_alternate()

or we elide the inner struct visit because the alternate's branch is
scalar.  Either way, we only need +1 to the depth over the entire
alternate, because we only need 1 level of g_memdup() at the time we
first enter the alternate.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to