# dmd.clone

Define the implicit `opEquals`, `opAssign`, post blit, copy constructor and destructor for structs.

#### 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 static bool __xopEquals(ref const S p, ref const S q) { return p == q; }

  #### 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 static bool __xopCmp(ref const S p, ref const S q) { return p.opCmp(q); }

  #### 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;

- `buildDtor`

  #### Declaration

  `DtorDeclaration `buildDtor`(AggregateDeclaration `ad`, Scope* `sc`);`

  Create inclusive destructor for struct/class by aggregating all the destructors in dtors[] with the destructors for all the members.

  #### Parameters

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

  #### Return Value

  generated function, `null` if none needed

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

- `buildExternDDtor`

  #### Declaration

  `DtorDeclaration `buildExternDDtor`(AggregateDeclaration `ad`, Scope* `sc`);`

  build a shim function around the compound dtor that translates a C++ destructor to a destructor with extern(D) calling convention

  #### Parameters

  `AggregateDeclaration `ad`` | the aggregate that contains the destructor to wrap
  `Scope* `sc`` | the scope in which to analyze the new function

  #### Return Value

  the shim destructor, semantically analyzed and added to the class as a member

- `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](), ...; }`