Menu

#968 Using TYPE() or BASE() on derived instance, implicit copy/construct only copies data members of topmost base

closed
nobody
None
compiler
2022-10-09
2022-08-26
No

By using TYPE (temporary) or BASE (initializer) keyword applied on a derived type instance, the implicit copy/construct (without explicit copy-constructor definition) only copies the data members of the topmost base of the derived instance (all other data members of the instance are ignored while implicit copy/construct).
Same behavior with or without explicit destructor defined in UDTs.
As soon as a corresponding explicit copy-constructor is defined, all works well.

Detail:

  • TYPE (temporary) with a simple parameter list of numeric values works well. But Type (temporary) with an UDT instance included in the parameter list or another Type (temporary) nested, both do not work well (without explicit copy-constructor definition).
  • BASE (initializer) calling the implicit copy-constructor of the base does not work well (without explicit copy-constructor definition), but if the implicit copy-assignment operator of the base is called instead (using the CAST keyword to up-cast THIS), this works well then (without explicit copy-assignment operator definition).

For more information and code examples (working well or not), see:
- the progress of the analysis in the dedicated thread (https://www.freebasic.net/forum/viewtopic.php?t=31830),
- and the final synthesis in the last post (https://www.freebasic.net/forum/viewtopic.php?p=294103#p294103).

Related

Bugs: #894

Discussion

  • fxm (freebasic.net)

    Some syntaxes involving TYPE (temporary) or BASE (initializer) keyword applied on a derived type instance, that are compatible with one default constructor in the topmost base, work then fine when that default constructor exists.

    I think when there is a default constructor, the implicit copy-construct is replaced by a default construct + implicit/explicit assignment (the latter working in all cases).
    This default constructor can be explicitly provided by the user (providing an explicit constructor body), or provided by the compiler itself if a data member has an initializer or a data member is a [pseudo] object (object having a default constructor like UDT or var-len string).

    Does not work with destructor or/and copy-let operator alone.

     

    Last edit: fxm (freebasic.net) 2022-09-21
  • Jeff Marshall

    Jeff Marshall - 2022-09-25

    Proposed changes at: Fix incorrect handling of initializers (typeini) #396

    fbc parser's handling of the initializer list elements and pairing of the initializers with UDT fields was not correctly synchronized - resulting in bad implicit copy construction.

    As reported:

    Changes/Fix:

    • fixes/changes how fbc handles pairing of a UDT's (internal) structure and the initializer list given by the user
    • new: track the overall initializer size in bytes
    • don't allow implicit casting to base types
    • pass back the initializer to a parent field for full initialization instead of truncated initialization
    • determine next field to initialize based on the overall bytes initialized instead of only the 'next field'
    • pair the next initializer (in user source) with the next best matched field (in UDT's symbol structure)
    • consider every field of the UDT including fields of hidden base types
    • initializer elements for TYPE's should pair with and initialize every member of the TYPE sequentially
    • initializer elements for UNION's should pair with only the first member of the UNION and skip the rest
    • don't implicitly cast parent types to base types; instead pass the initializer back up the parser and try to pair the initializer with a parent type
    • different handling (ideally better) of comma and parentheses initializer list delimeters so that next initializer is paired with correct UDT field.

    Background information (under the hood):

    • initializers for variables, BASE, NEW, anonymous types, fields, and optional parameters are all handled by a common parser entry point - internally in fbc sources 'cInitializer()
    • cInitializer() parsing routine is also the entry point for arrays. Array elements and UDT fields can contain each of the other, so it's a bit of a recursion nightmare to debug.
    • the shallow bit-wise copy is generated based on 1) the initializer list given in source by the user, and 2) the UDT's structure as stored in the internal symbol table
    • non-trivial types (i.e. having constructor procedures), are handled slightly differently in the parser (i.e. they have a different code path and checks).
     
  • Jeff Marshall

    Jeff Marshall - 2022-10-09

    I think this can be considered fixed in fbc 1.10.0 by changes merged in by [055e29a974d74d77e05f28bcb5c31b78d75bf013]

     

    Related

    Commit: [055e29]

  • Jeff Marshall

    Jeff Marshall - 2022-10-09
    • status: open --> closed
     

Log in to post a comment.

MongoDB Logo MongoDB