# dmd.clone

Builds struct member functions if needed and not defined by the user. Includes `opEquals`, `opAssign`, post blit, copy constructor and destructor.

#### Authors

Walter Bright

#### License

Boost License 1.0

Source: clone.d

Documentation: https://dlang.org/phobos/dmd_clone.html

Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/clone.d

- `mergeFuncAttrs`

  #### Declaration

  `pure StorageClass `mergeFuncAttrs`(StorageClass `s1`, const FuncDeclaration `f`);`

  Merge function attributes pure, nothrow, @safe, @nogc, and @disable from `f` into `s1`.

  #### Parameters

  `StorageClass `s1`` | storage class to merge into
  `FuncDeclaration `f`` | function

  #### Return Value

  merged storage class

- `hasIdentityOpAssign`

  #### Declaration

  `FuncDeclaration `hasIdentityOpAssign`(AggregateDeclaration `ad`, Scope* `sc`);`

  Check given aggregate actually has an identity opAssign or not.

  #### Parameters

  `AggregateDeclaration `ad`` | struct or class
  `Scope* `sc`` | current scope

  #### Return Value

  if found, returns FuncDeclaration of opAssign, otherwise `null`

- `buildOpAssign`

  #### Declaration

  `FuncDeclaration `buildOpAssign`(StructDeclaration `sd`, Scope* `sc`);`

  Build opAssign for a `struct`.

  #### Discussion

  The generated `opAssign` function has the following signature:

  1. `ref S opAssign(S s) // S is the name of the `struct``
  The opAssign function will be built for a struct `S` if the following constraints are met:
  1. `S` does not have an identity `opAssign` defined.
  2. `S` has at least one of the following members: a postblit (user-defined or)
  generated for fields that have a defined postblit
  , a destructor (user-defined or generated for fields that have a defined destructor) or at least one field that has a defined `opAssign`.
  3. `S` does not have any non-mutable fields.
  If `S` has a disabled destructor or at least one field that has a disabled `opAssign`, `S.opAssign` is going to be generated, but marked with `@disable`
  If `S` defines a destructor, the generated code for `opAssign` is:
  1. `S __swap = void; __swap = this; // bit copy this = s; // bit copy __swap.dtor();`
  Otherwise, if `S` defines a postblit, the generated code for `opAssign` is:
  1. `this = s;`
  Note that the parameter to the generated `opAssign` is passed by value, which means that the postblit is going to be called (if it is defined) in both of the above situations before entering the body of `opAssign`. The assignments in the above generated function bodies are blit expressions, so they can be regarded as `memcpy`s (`opAssign` is not called as this will result in an infinite recursion; the postblit is not called because it has already been called when the parameter was passed by value).
  If `S` does not have a postblit or a destructor, but contains at least one field that defines an `opAssign` function (which is not disabled), then the body will make member-wise assignments:
  1. `this.field1 = s.field1; this.field2 = s.field2; ...;`
  In this situation, the assignemnts are actual assign expressions (`opAssign` is used if defined).

  References: https://dlang.org/spec/struct.html#assign-overload

  #### Parameters

  `StructDeclaration `sd`` | struct to generate opAssign for
  `Scope* `sc`` | context

  #### Return Value

  generated `opAssign` function

- `needOpEquals`

  #### Declaration

  `bool `needOpEquals`(StructDeclaration `sd`);`

  We need an opEquals for the struct if any fields has an opEquals. Generate one if a user-specified one does not exist.

- `buildOpEquals`

  #### Declaration

  `FuncDeclaration `buildOpEquals`(StructDeclaration `sd`, Scope* `sc`);`

  Build opEquals for struct. const bool opEquals(const S s) { ... }

  #### Discussion

  By fixing https://issues.dlang.org/show_bug.cgi?id=3789 opEquals is changed to be never implicitly generated. Now, struct objects comparison s1 == s2 is translated to: s1.tupleof == s2.tupleof to calculate structural equality. See EqualExp.op_overload.

- `buildXopEquals`

  #### Declaration

  `FuncDeclaration `buildXopEquals`(StructDeclaration `sd`, Scope* `sc`);`

  Build __xopEquals for TypeInfo_Struct bool __xopEquals(ref const S p) const { return this == p; }

  #### Discussion

  This is called by TypeInfo.equals(p1, p2). If the struct does not support const objects comparison, it will throw "not implemented" Error in runtime.

- `buildXopCmp`

  #### Declaration

  `FuncDeclaration `buildXopCmp`(StructDeclaration `sd`, Scope* `sc`);`

  Build __xopCmp for TypeInfo_Struct int __xopCmp(ref const S p) const { return this.opCmp(p); }

  #### Discussion

  This is called by TypeInfo.compare(p1, p2). If the struct does not support const objects comparison, it will throw "not implemented" Error in runtime.

- `buildXtoHash`

  #### Declaration

  `FuncDeclaration `buildXtoHash`(StructDeclaration `sd`, Scope* `sc`);`

  Build _xtoHash for non-bitwise hashing static hash_t xtoHash(ref const S p) nothrow @trusted;

- `buildDtors`

  #### Declaration

  `void `buildDtors`(AggregateDeclaration `ad`, Scope* `sc`);`

  Create aggregate destructor for struct/class by aggregating all the destructors in userDtors[] with the destructors for all the members. Sets `ad`'s fieldDtor, aggrDtor, dtor and tidtor fields.

  #### Parameters

  `AggregateDeclaration `ad`` | struct or class to build destructor for
  `Scope* `sc`` | context

  Note: Close similarity with StructDeclaration::buildPostBlit(), and the ordering changes (runs backward instead of forwards).

- `buildInv`

  #### Declaration

  `FuncDeclaration `buildInv`(AggregateDeclaration `ad`, Scope* `sc`);`

  Create inclusive invariant for struct/class by aggregating all the invariants in invs[].

  1. `void __invariant() const [pure nothrow @trusted] { invs[0](), invs[1](), ...; }`
- `buildPostBlit`

  #### Declaration

  `FuncDeclaration `buildPostBlit`(StructDeclaration `sd`, Scope* `sc`);`

  Create inclusive postblit for struct by aggregating all the postblits in postblits[] with the postblits for all the members. Note the close similarity with AggregateDeclaration::buildDtor(), and the ordering changes (runs forward instead of backwards).

- `buildCopyCtor`

  #### Declaration

  `bool `buildCopyCtor`(StructDeclaration `sd`, Scope* `sc`);`

  Generates a copy constructor if needCopyCtor() returns `true`. The generated copy constructor will be of the form: this(ref return scope inout(S) rhs) inout { this.field1 = rhs.field1; this.field2 = rhs.field2; ... }

  #### Parameters

  `StructDeclaration `sd`` | the `struct` for which the copy constructor is generated
  `Scope* `sc`` | the scope where the copy constructor is generated

  #### Return Value

  `true` if `struct` `sd` defines a copy constructor (explicitly or generated), `false` otherwise.