dmd.clone
    Builds struct member functions if needed and not defined by the user.
 Includes opEquals, opAssign, post blit, copy constructor and destructor.
  
License
Source: clone.d
Documentation: https://dlang.org/phobos/dmd_clone.html
- 
  Declarationpure StorageClassmergeFuncAttrs(StorageClasss1, const FuncDeclarationf);Merge function attributes pure, nothrow, @safe, @nogc, and @disable from fintos1.ParametersStorageClasss1storage class to merge into FuncDeclarationffunction Return Valuemerged storage class 
- 
  DeclarationFuncDeclarationhasIdentityOpAssign(AggregateDeclarationad, Scope*sc);Check given aggregate actually has an identity opAssign or not. ParametersAggregateDeclarationadstruct or class Scope*sccurrent scope Return Valueif found, returns FuncDeclaration of opAssign, otherwise null
- 
  DeclarationFuncDeclarationbuildOpAssign(StructDeclarationsd, Scope*sc);Build opAssign for a struct.DiscussionThe generated opAssignfunction has the following signature:- ref S opAssign(S s) // S is the name of the `struct`
 
 The opAssign function will be built for a structSif the following constraints are met:- Sdoes not have an identity- opAssigndefined.
- Shas at least one of the following members: a postblit (user-defined or) 
 generated for fields that have a defined postblit
 opAssign.- Sdoes not have any non-mutable fields.
 Shas a disabled destructor or at least one field that has a disabledopAssign,S.opAssignis going to be generated, but marked with@disable
 IfSdefines a destructor, the generated code foropAssignis:
 - S __swap = void; __swap = this; // bit copy this = s; // bit copy __swap.dtor();
 
 Otherwise, ifSdefines a postblit, the generated code foropAssignis:
 - this = s;
 
 Note that the parameter to the generatedopAssignis 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 ofopAssign. The assignments in the above generated function bodies are blit expressions, so they can be regarded asmemcpys (opAssignis 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).
 IfSdoes not have a postblit or a destructor, but contains at least one field that defines anopAssignfunction (which is not disabled), then the body will make member-wise assignments:
 - this.field1 = s.field1; this.field2 = s.field2; ...;
 
 In this situation, the assignemnts are actual assign expressions (opAssignis used if defined).ParametersStructDeclarationsdstruct to generate opAssign for Scope*sccontext Return Valuegenerated opAssignfunction
- 
  DeclarationboolneedOpEquals(StructDeclarationsd);We need an opEquals for the struct if any fields has an opEquals. Generate one if a user-specified one does not exist. 
- 
  DeclarationFuncDeclarationbuildOpEquals(StructDeclarationsd, Scope*sc);Build opEquals for struct. const bool opEquals(const S s) { ... } DiscussionBy 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. 
- 
  DeclarationFuncDeclarationbuildXopEquals(StructDeclarationsd, Scope*sc);Build __xopEquals for TypeInfo_Struct bool __xopEquals(ref const S p) const { return this == p; } DiscussionThis is called by TypeInfo.equals(p1, p2). If the struct does not support const objects comparison, it will throw "not implemented" Error in runtime. 
- 
  DeclarationFuncDeclarationbuildXopCmp(StructDeclarationsd, Scope*sc);Build __xopCmp for TypeInfo_Struct int __xopCmp(ref const S p) const { return this.opCmp(p); } DiscussionThis is called by TypeInfo.compare(p1, p2). If the struct does not support const objects comparison, it will throw "not implemented" Error in runtime. 
- 
  DeclarationFuncDeclarationbuildXtoHash(StructDeclarationsd, Scope*sc);Build _xtoHash for non-bitwise hashing static hash_t xtoHash(ref const S p) nothrow @trusted; 
- 
  DeclarationvoidbuildDtors(AggregateDeclarationad, 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.ParametersAggregateDeclarationadstruct or class to build destructor for Scope*sccontext Note: Close similarity with StructDeclaration::buildPostBlit(), and the ordering changes (runs backward instead of forwards). 
- 
  DeclarationFuncDeclarationbuildInv(AggregateDeclarationad, Scope*sc);Create inclusive invariant for struct/class by aggregating all the invariants in invs[]. - void __invariant() const [pure nothrow @trusted] { invs[0](), invs[1](), ...; }
 
- 
  DeclarationFuncDeclarationbuildPostBlit(StructDeclarationsd, 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). 
- 
  DeclarationboolbuildCopyCtor(StructDeclarationsd, 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; ... }ParametersStructDeclarationsdthe structfor which the copy constructor is generatedScope*scthe scope where the copy constructor is generated Return Valuetrueifstructsddefines a copy constructor (explicitly or generated),falseotherwise.