dmd.clone
Define the implicit opEquals, opAssign, post blit, copy constructor and destructor for structs.
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 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.
-
Declaration
FuncDeclarationbuildXopCmp(StructDeclarationsd, 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.
-
Declaration
FuncDeclarationbuildXtoHash(StructDeclarationsd, Scope*sc);Build _xtoHash for non-bitwise hashing static hash_t xtoHash(ref const S p) nothrow @trusted;
-
Declaration
DtorDeclarationbuildDtor(AggregateDeclarationad, Scope*sc);Create inclusive destructor for struct/class by aggregating all the destructors in dtors[] with the destructors for all the members.
Parameters
AggregateDeclarationadstruct or class to build destructor for
Scope*sccontext
Return Value
generated function,
nullif none neededNote: Close similarity with StructDeclaration::buildPostBlit(), and the ordering changes (runs backward instead of forwards).
-
Declaration
DtorDeclarationbuildExternDDtor(AggregateDeclarationad, Scope*sc);build a shim function around the compound dtor that translates a C++ destructor to a destructor with extern(D) calling convention
Parameters
AggregateDeclarationadthe aggregate that contains the destructor to wrap
Scope*scthe scope in which to analyze the new function
Return Value
the shim destructor, semantically analyzed and added to the class as a member
-
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](), ...; }