Compiler implementation of the D programming language.
Merge function attributes pure, nothrow, @safe, @nogc, and @disable from f into s1.
StorageClass s1
| storage class to merge into |
FuncDeclaration f
| function |
Check given aggregate actually has an identity opAssign or not.
AggregateDeclaration ad
| struct or class |
Scope* sc
| current scope |
Build opAssign for a struct
.
The generated opAssign
function has the following signature:
ref S opAssign(S s) // S is the name of the `struct`
S
if the following constraints are met: S
does not have an identity opAssign
defined. 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
. S
does not have any non-mutable fields. 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
S
defines a destructor, the generated code for opAssign
is: S __swap = void; __swap = this; // bit copy this = s; // bit copy __swap.dtor();
S
defines a postblit, the generated code for opAssign
is: this = s;
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). 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: this.field1 = s.field1; this.field2 = s.field2; ...;
opAssign
is used if defined). StructDeclaration sd
| struct to generate opAssign for |
Scope* sc
| context |
opAssign
functionWe need an opEquals for the struct if any fields has an opEquals. Generate one if a user-specified one does not exist.
Build opEquals for struct. const bool opEquals(const S s) { ... }
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.
Build __xopEquals for TypeInfo_Struct static bool __xopEquals(ref const S p, ref const S q) { return p == q; }
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.
Build __xopCmp for TypeInfo_Struct static bool __xopCmp(ref const S p, ref const S q) { return p.opCmp(q); }
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.
Build _xtoHash for non-bitwise hashing static hash_t xtoHash(ref const S p) nothrow @trusted;
Create inclusive destructor for struct/class by aggregating all the destructors in dtors[] with the destructors for all the members.
AggregateDeclaration ad
| struct or class to build destructor for |
Scope* sc
| context |
build a shim function around the compound dtor that translates a C++ destructor to a destructor with extern(D) calling convention
AggregateDeclaration ad
| the aggregate that contains the destructor to wrap |
Scope* sc
| the scope in which to analyze the new function |
Create inclusive invariant for struct/class by aggregating all the invariants in invs[]. void __invariant() const [pure nothrow @trusted] { invs[0](), invs[1](), ...; }
© 1999–2019 The D Language Foundation
Licensed under the Boost License 1.0.
https://dlang.org/phobos/dmd_clone.html