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
-
Declaration
pure StorageClassmergeFuncAttrs(StorageClasss1, const FuncDeclarationf);Merge function attributes pure, nothrow, @safe, @nogc, and @disable from
fintos1.Parameters
StorageClasss1storage class to merge into
FuncDeclarationffunction
Return Value
merged storage class
-
Declaration
FuncDeclarationhasIdentityOpAssign(AggregateDeclarationad, Scope*sc);Check given aggregate actually has an identity opAssign or not.
Parameters
AggregateDeclarationadstruct or class
Scope*sccurrent scope
Return Value
if found, returns FuncDeclaration of opAssign, otherwise
null -
Declaration
FuncDeclarationbuildOpAssign(StructDeclarationsd, Scope*sc);Build opAssign for a
struct.Discussion
The 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 identityopAssigndefined.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).Parameters
StructDeclarationsdstruct to generate opAssign for
Scope*sccontext
Return Value
generated
opAssignfunction -
Declaration
boolneedOpEquals(StructDeclarationsd);We need an opEquals for the struct if any fields has an opEquals. Generate one if a user-specified one does not exist.
-
Declaration
FuncDeclarationbuildOpEquals(StructDeclarationsd, 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.
-
Declaration
FuncDeclarationbuildXopEquals(StructDeclarationsd, 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.
-
Declaration
FuncDeclarationbuildXopCmp(StructDeclarationsd, 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.
-
Declaration
FuncDeclarationbuildXtoHash(StructDeclarationsd, Scope*sc);Build _xtoHash for non-bitwise hashing static hash_t xtoHash(ref const S p) nothrow @trusted;
-
Declaration
voidbuildDtors(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.Parameters
AggregateDeclarationadstruct or class to build destructor for
Scope*sccontext
Note: Close similarity with StructDeclaration::buildPostBlit(), and the ordering changes (runs backward instead of forwards).
-
Declaration
FuncDeclarationbuildInv(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](), ...; }
-
Declaration
FuncDeclarationbuildPostBlit(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).
-
Declaration
boolbuildCopyCtor(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; ... }Parameters
StructDeclarationsdthe
structfor which the copy constructor is generatedScope*scthe scope where the copy constructor is generated
Return Value
trueifstructsddefines a copy constructor (explicitly or generated),falseotherwise.