• E
    qapi: Prefer typesafe upcasts to qapi base classes · 30594fe1
    Eric Blake 提交于
    A previous patch (commit 1e6c1616) made it possible to
    directly cast from a qapi flat union type to its base type.
    However, it requires the use of a C cast, which turns off
    compiler type-safety checks.  Fortunately, no such casts
    exist, just yet.
    
    Regardless, add inline type-safe wrappers named
    qapi_FOO_base() for any union type FOO that has a base,
    which can be used for a safer upcast, and enhance the
    testsuite to cover the new functionality.
    
    A future patch will extend the upcast support to structs,
    where such conversions do exist already.
    
    Note that C makes const-correct upcasts annoying because
    it lacks overloads; these functions cast away const so that
    they can accept user pointers whether const or not, and the
    result in turn can be assigned to normal or const pointers.
    Alternatively, this could have been done with macros, but
    type-safe macros are hairy, and not worthwhile here.
    
    This patch just adds upcasts.  None of our code needed to
    downcast from a base qapi class to a child.  Also, in the
    case of grandchildren (such as BlockdevOptionsQcow2), the
    caller will need to call two functions to get to the inner
    base (although it wouldn't be too hard to generate a
    qapi_FOO_base_base() if desired).  If a user changes qapi
    to alter the base class hierarchy, such as going from
    'A -> C' to 'A -> B -> C', it will change the type of
    'qapi_C_base()', and the compiler will point out the places
    that are affected by the new base.
    
    One alternative was proposed, but was deemed too ugly to use
    in practice: the generators could output redundant
    information using anonymous types:
    | struct Child {
    |     union {
    |         struct {
    |             Type1 parent_member1;
    |             Type2 parent_member2;
    |         };
    |         Parent base;
    |     };
    | };
    With that ugly proposal, for a given qapi type, obj->member
    and obj->base.member would refer to the same storage; allowing
    convenience in working with members without needing 'base.'
    allowing typesafe upcast without needing a C cast by accessing
    '&obj->base', and allowing downcasts from the parent back to
    the child possible through container_of(obj, Child, base).
    Signed-off-by: NEric Blake <eblake@redhat.com>
    Message-Id: <1445898903-12082-10-git-send-email-eblake@redhat.com>
    [Commit message tweaked]
    Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
    30594fe1
test-qmp-input-visitor.c 28.6 KB