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 StorageClass
mergeFuncAttrs
(StorageClasss1
, const FuncDeclarationf
);Merge function attributes pure, nothrow, @safe, @nogc, and @disable from
f
intos1
.Parameters
StorageClass
s1
storage class to merge into
FuncDeclaration
f
function
Return Value
merged storage class
-
Declaration
FuncDeclaration
hasIdentityOpAssign
(AggregateDeclarationad
, 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
-
Declaration
FuncDeclaration
buildOpAssign
(StructDeclarationsd
, Scope*sc
);Build opAssign for a
struct
.Discussion
The generated
opAssign
function has the following signature:ref S opAssign(S s) // S is the name of the `struct`
The opAssign function will be built for a structS
if the following constraints are met:S
does not have an identityopAssign
defined.S
has at least one of the following members: a postblit (user-defined or)
generated for fields that have a defined postblit
opAssign
.S
does not have any non-mutable fields.
S
has a disabled destructor or at least one field that has a disabledopAssign
,S.opAssign
is going to be generated, but marked with@disable
IfS
defines a destructor, the generated code foropAssign
is:
S __swap = void; __swap = this; // bit copy this = s; // bit copy __swap.dtor();
Otherwise, ifS
defines a postblit, the generated code foropAssign
is:
this = s;
Note that the parameter to the generatedopAssign
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 ofopAssign
. The assignments in the above generated function bodies are blit expressions, so they can be regarded asmemcpy
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).
IfS
does not have a postblit or a destructor, but contains at least one field that defines anopAssign
function (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 (opAssign
is used if defined).Parameters
StructDeclaration
sd
struct to generate opAssign for
Scope*
sc
context
Return Value
generated
opAssign
function -
Declaration
bool
needOpEquals
(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
FuncDeclaration
buildOpEquals
(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
FuncDeclaration
buildXopEquals
(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
FuncDeclaration
buildXopCmp
(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
FuncDeclaration
buildXtoHash
(StructDeclarationsd
, Scope*sc
);Build _xtoHash for non-bitwise hashing static hash_t xtoHash(ref const S p) nothrow @trusted;
-
Declaration
DtorDeclaration
buildDtor
(AggregateDeclarationad
, 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 neededNote: Close similarity with StructDeclaration::buildPostBlit(), and the ordering changes (runs backward instead of forwards).
-
Declaration
DtorDeclaration
buildExternDDtor
(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
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
-
Declaration
FuncDeclaration
buildInv
(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](), ...; }