bool found = false;
for (size_t i = 0; i < global.params.imppath.length; i++)
{
- if (strcmp (path, global.params.imppath[i]) == 0)
+ if (strcmp (path, global.params.imppath[i].path) == 0)
{
found = true;
break;
/* Add import search paths. */
for (size_t i = 0; i < global.params.imppath.length; i++)
{
- const char *path = global.params.imppath[i];
+ const char *path = global.params.imppath[i].path;
if (path)
{
Strings array;
-c7902293d7df9d02546562cb09fc8439004a70d1
+d6f693b46a1565172cac7a1438905141783a164f
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
return null;
//printf("StructDeclaration::buildOpAssign() %s\n", sd.toChars());
- StorageClass stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
+ StorageClass stc = STC.safe;
Loc declLoc = sd.loc;
Loc loc; // internal code should have no loc to prevent coverage
const hasUserDefinedPosblit = sd.postblits.length && !sd.postblits[0].isDisabled ? true : false;
// by default, the storage class of the created postblit
- StorageClass stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
+ StorageClass stc = STC.safe;
Loc declLoc = sd.postblits.length ? sd.postblits[0].loc : sd.loc;
Loc loc; // internal code should have no loc to prevent coverage
// perform semantic on the member postblit in order to
// be able to aggregate it later on with the rest of the
// postblits
+ sdv.postblit.isGenerated = true;
functionSemantic(sdv.postblit);
stc = mergeFuncAttrs(stc, sdv.postblit);
*/
if (sdv.dtor)
{
+ sdv.dtor.isGenerated = true;
functionSemantic(sdv.dtor);
// keep a list of fields that need to be destroyed in case
}
/**
- * Generates a copy constructor declaration with the specified storage
+ * Generates a copy or move constructor declaration with the specified storage
* class for the parameter and the function.
*
* Params:
- * sd = the `struct` that contains the copy constructor
- * paramStc = the storage class of the copy constructor parameter
- * funcStc = the storage class for the copy constructor declaration
+ * sd = the `struct` that contains the constructor
+ * paramStc = the storage class of the constructor parameter
+ * funcStc = the storage class for the constructor declaration
+ * move = true for move constructor, false for copy constructor
*
* Returns:
* The copy constructor declaration for struct `sd`.
*/
-private CtorDeclaration generateCopyCtorDeclaration(StructDeclaration sd, const StorageClass paramStc, const StorageClass funcStc)
+private CtorDeclaration generateCtorDeclaration(StructDeclaration sd, const StorageClass paramStc, const StorageClass funcStc, bool move)
{
auto fparams = new Parameters();
auto structType = sd.type;
- fparams.push(new Parameter(Loc.initial, paramStc | STC.ref_ | STC.return_ | STC.scope_, structType, Id.p, null, null));
+ StorageClass stc = move ? 0 : STC.ref_; // the only difference between copy or move
+ fparams.push(new Parameter(Loc.initial, paramStc | stc, structType, Id.p, null, null));
ParameterList pList = ParameterList(fparams);
auto tf = new TypeFunction(pList, structType, LINK.d, STC.ref_);
- auto ccd = new CtorDeclaration(sd.loc, Loc.initial, STC.ref_, tf, true);
+ auto ccd = new CtorDeclaration(sd.loc, Loc.initial, STC.ref_, tf);
ccd.storage_class |= funcStc;
ccd.storage_class |= STC.inference;
ccd.isGenerated = true;
}
/**
- * Generates a trivial copy constructor body that simply does memberwise
- * initialization:
+ * Generates a trivial copy or move constructor body that simply does memberwise
+ * initialization.
*
+ * for copy construction:
* this.field1 = rhs.field1;
* this.field2 = rhs.field2;
* ...
+ * for move construction:
+ * this.field1 = __rvalue(rhs.field1);
+ * this.field2 = __rvalue(rhs.field2);
+ * ...
*
* Params:
- * sd = the `struct` declaration that contains the copy constructor
+ * sd = the `struct` declaration that contains the constructor
+ * move = true for move constructor, false for copy constructor
*
* Returns:
- * A `CompoundStatement` containing the body of the copy constructor.
+ * A `CompoundStatement` containing the body of the constructor.
*/
-private Statement generateCopyCtorBody(StructDeclaration sd)
+private Statement generateCtorBody(StructDeclaration sd, bool move)
{
Loc loc;
Expression e;
foreach (v; sd.fields)
{
+ Expression rhs = new DotVarExp(loc, new IdentifierExp(loc, Id.p), v);
+ if (move)
+ rhs.rvalue = true;
auto ec = new AssignExp(loc,
new DotVarExp(loc, new ThisExp(loc), v),
- new DotVarExp(loc, new IdentifierExp(loc, Id.p), v));
+ rhs);
e = Expression.combine(e, ec);
//printf("e.toChars = %s\n", e.toChars());
}
return new CompoundStatement(loc, s1);
}
-/**
- * Determine if a copy constructor is needed for struct sd,
- * if the following conditions are met:
- *
- * 1. sd does not define a copy constructor
- * 2. at least one field of sd defines a copy constructor
- *
+/******************************************
+ * Find root `this` constructor for struct sd.
+ * (root is starting position for overloaded constructors)
* Params:
- * sd = the `struct` for which the copy constructor is generated
- * hasCpCtor = set to true if a copy constructor is already present
- * hasMoveCtor = set to true if a move constructor is already present
- *
- * Returns:
- * `true` if one needs to be generated
- * `false` otherwise
+ * sd = the `struct` to be searched
+ * ctor = `this` if found, otherwise null
+ * Result:
+ * false means `this` found in overload set
*/
-bool needCopyCtor(StructDeclaration sd, out bool hasCpCtor, out bool hasMoveCtor)
+private bool findStructConstructorRoot(StructDeclaration sd, out Dsymbol ctor)
{
- //printf("needCopyCtor() %s\n", sd.toChars());
- if (global.errors)
- return false;
-
- auto ctor = sd.search(sd.loc, Id.ctor);
+ ctor = sd.search(sd.loc, Id.ctor); // Aggregate.searchCtor() ?
if (ctor)
{
if (ctor.isOverloadSet())
if (auto td = ctor.isTemplateDeclaration())
ctor = td.funcroot;
}
+ return true;
+}
- CtorDeclaration cpCtor;
- CtorDeclaration rvalueCtor;
-
- if (!ctor)
- goto LcheckFields;
-
+/***********************************************
+ * Find move and copy constructors (if any) starting at `ctor`
+ * Params:
+ * ctor = `this` constructor root
+ * copyCtor = set to first copy constructor found, or null
+ * moveCtor = set to first move constructor found, or null
+ */
+private void findMoveAndCopyConstructors(Dsymbol ctor, out CtorDeclaration copyCtor, out CtorDeclaration moveCtor)
+{
overloadApply(ctor, (Dsymbol s)
{
if (s.isTemplateDeclaration())
assert(ctorDecl);
if (ctorDecl.isCpCtor)
{
- if (!cpCtor)
- cpCtor = ctorDecl;
- return 0;
+ if (!copyCtor)
+ copyCtor = ctorDecl;
+ }
+ else if (ctorDecl.isMoveCtor)
+ {
+ if (!moveCtor)
+ moveCtor = ctorDecl;
}
-
- if (ctorDecl.isMoveCtor)
- rvalueCtor = ctorDecl;
return 0;
});
+}
+
+/**
+ * Determine if a copy constructor is needed for struct sd,
+ * if the following conditions are met:
+ *
+ * 1. sd does not define a copy constructor
+ * 2. at least one field of sd defines a copy constructor
+ *
+ * Params:
+ * sd = the `struct` for which the copy constructor is generated
+ * hasCopyCtor = set to true if a copy constructor is already present
+ * hasMoveCtor = set to true if a move constructor is already present
+ * needCopyCtor = set to true if a copy constructor is not present, but needed
+ * needMoveCtor = set to true if a move constructor is not present, but needed
+ *
+ * Returns:
+ * `true` if one needs to be generated
+ * `false` otherwise
+ */
+void needCopyOrMoveCtor(StructDeclaration sd, out bool hasCopyCtor, out bool hasMoveCtor, out bool needCopyCtor, out bool needMoveCtor)
+{
+ //printf("needCopyOrMoveCtor() %s\n", sd.toChars());
+ if (global.errors)
+ return;
+
+ Dsymbol ctor;
+ if (!findStructConstructorRoot(sd, ctor))
+ return;
+
+ CtorDeclaration copyCtor;
+ CtorDeclaration moveCtor;
+
+ if (ctor)
+ findMoveAndCopyConstructors(ctor, copyCtor, moveCtor);
- if (rvalueCtor)
+ if (moveCtor)
hasMoveCtor = true;
- if (cpCtor)
- {
- if (0 && rvalueCtor)
- {
- .error(sd.loc, "`struct %s` may not define both a rvalue constructor and a copy constructor", sd.toChars());
- errorSupplemental(rvalueCtor.loc,"rvalue constructor defined here");
- errorSupplemental(cpCtor.loc, "copy constructor defined here");
- }
- hasCpCtor = true;
- return false;
- }
+ if (copyCtor)
+ hasCopyCtor = true;
+
+ if (hasMoveCtor && hasCopyCtor)
+ return;
-LcheckFields:
VarDeclaration fieldWithCpCtor;
+ VarDeclaration fieldWithMoveCtor;
// see if any struct members define a copy constructor
foreach (v; sd.fields)
{
if (ts.sym.hasCopyCtor)
{
fieldWithCpCtor = v;
- break;
+ }
+ if (ts.sym.hasMoveCtor)
+ {
+ fieldWithMoveCtor = v;
}
}
- if (fieldWithCpCtor && rvalueCtor)
+ if (0 && fieldWithCpCtor && moveCtor)
{
.error(sd.loc, "`struct %s` may not define a rvalue constructor and have fields with copy constructors", sd.toChars());
- errorSupplemental(rvalueCtor.loc,"rvalue constructor defined here");
+ errorSupplemental(moveCtor.loc,"rvalue constructor defined here");
errorSupplemental(fieldWithCpCtor.loc, "field with copy constructor defined here");
- return false;
+ return;
}
- else if (!fieldWithCpCtor)
- return false;
- return true;
+
+ if (fieldWithCpCtor && !hasCopyCtor)
+ needCopyCtor = true;
+ if (fieldWithMoveCtor && !hasMoveCtor)
+ needMoveCtor = true;
}
/**
* }
*
* Params:
- * sd = the `struct` for which the copy constructor is generated
- * sc = the scope where the copy constructor is generated
- * hasMoveCtor = set to true when a move constructor is also detected
- *
- * Returns:
- * `true` if `struct` sd defines a copy constructor (explicitly or generated),
- * `false` otherwise.
+ * sd = the `struct` for which the constructor is generated
+ * sc = the scope where the constructor is generated
+ * move = true means generate the move constructor, otherwise copy constructor
* References:
* https://dlang.org/spec/struct.html#struct-copy-constructor
*/
-bool buildCopyCtor(StructDeclaration sd, Scope* sc, out bool hasMoveCtor)
+void buildCopyOrMoveCtor(StructDeclaration sd, Scope* sc, bool move)
{
- bool hasCpCtor;
- if (!needCopyCtor(sd, hasCpCtor, hasMoveCtor))
- return hasCpCtor;
-
- //printf("generating copy constructor for %s\n", sd.toChars());
+ //printf("buildCopyOrMoveCtor() generating %s constructor for %s\n", move ? "move".ptr : "copy".ptr, sd.toChars());
const MOD paramMod = MODFlags.wild;
const MOD funcMod = MODFlags.wild;
- auto ccd = generateCopyCtorDeclaration(sd, ModToStc(paramMod), ModToStc(funcMod));
- auto copyCtorBody = generateCopyCtorBody(sd);
- ccd.fbody = copyCtorBody;
+ auto ccd = generateCtorDeclaration(sd, ModToStc(paramMod), ModToStc(funcMod), move);
+ auto ctorBody = generateCtorBody(sd, move);
+ ccd.fbody = ctorBody;
sd.members.push(ccd);
ccd.addMember(sc, sd);
const errors = global.startGagging();
ccd.storage_class |= STC.disable;
ccd.fbody = null;
}
- return true;
}
{
return 1; // they are not equal
}
- else
- {
- return (r1 != r2);
- }
+ return (r1 != r2);
}
else if (e1.type.isComplex())
{
// For structs, we only need to return 0 or 1 (< and > aren't legal).
if (es1.sd != es2.sd)
return 1;
- else if ((!es1.elements || !es1.elements.length) && (!es2.elements || !es2.elements.length))
+ if ((!es1.elements || !es1.elements.length) && (!es2.elements || !es2.elements.length))
return 0; // both arrays are empty
- else if (!es1.elements || !es2.elements)
+ if (!es1.elements || !es2.elements)
return 1;
- else if (es1.elements.length != es2.elements.length)
+ if (es1.elements.length != es2.elements.length)
return 1;
- else
+ foreach (size_t i; 0 .. es1.elements.length)
{
- foreach (size_t i; 0 .. es1.elements.length)
- {
- Expression ee1 = (*es1.elements)[i];
- Expression ee2 = (*es2.elements)[i];
+ Expression ee1 = (*es1.elements)[i];
+ Expression ee2 = (*es2.elements)[i];
- // https://issues.dlang.org/show_bug.cgi?id=16284
- if (ee1.op == EXP.void_ && ee2.op == EXP.void_) // if both are VoidInitExp
- continue;
+ // https://issues.dlang.org/show_bug.cgi?id=16284
+ if (ee1.op == EXP.void_ && ee2.op == EXP.void_) // if both are VoidInitExp
+ continue;
- if (ee1 == ee2)
- continue;
- if (!ee1 || !ee2)
- return 1;
- const int cmp = ctfeRawCmp(loc, ee1, ee2, identity);
- if (cmp)
- return 1;
- }
- return 0; // All elements are equal
+ if (ee1 == ee2)
+ continue;
+ if (!ee1 || !ee2)
+ return 1;
+ const int cmp = ctfeRawCmp(loc, ee1, ee2, identity);
+ if (cmp)
+ return 1;
}
+ return 0; // All elements are equal
}
if (e1.op == EXP.assocArrayLiteral && e2.op == EXP.assocArrayLiteral)
{
if (t1.isString() && t2.isString())
return specificCmp(op, ctfeRawCmp(loc, e1, e2));
- else if (t1.isReal())
+ if (t1.isReal())
return realCmp(op, e1.toReal(), e2.toReal());
- else if (t1.isImaginary())
+ if (t1.isImaginary())
return realCmp(op, e1.toImaginary(), e2.toImaginary());
- else if (t1.isUnsigned() || t2.isUnsigned())
+ if (t1.isUnsigned() || t2.isUnsigned())
return intUnsignedCmp(op, e1.toInteger(), e2.toInteger());
else
return intSignedCmp(op, e1.toInteger(), e2.toInteger());
case Tint8:
if (ty == Tuns64 && value & ~0x7FU)
return MATCH.nomatch;
- else if (cast(byte)value != value)
+ if (cast(byte)value != value)
return MATCH.nomatch;
break;
{
if (from.mod == to.mod)
return MATCH.exact;
- else if (MODimplicitConv(from.mod, to.mod))
+ if (MODimplicitConv(from.mod, to.mod))
return MATCH.constant;
- else if (!((from.mod ^ to.mod) & MODFlags.shared_)) // for wild matching
+ if (!((from.mod ^ to.mod) & MODFlags.shared_)) // for wild matching
return MATCH.constant;
- else
- return MATCH.convert;
+ return MATCH.convert;
}
if (from.ty == Tvoid || to.ty == Tvoid)
// struct+struct, and class+class are errors
if (t1.ty == Tstruct && t2.ty == Tstruct)
return errorReturn();
- else if (t1.ty == Tclass && t2.ty == Tclass)
+ if (t1.ty == Tclass && t2.ty == Tclass)
return errorReturn();
- else if (t1.ty == Taarray && t2.ty == Taarray)
+ if (t1.ty == Taarray && t2.ty == Taarray)
return errorReturn();
}
VarDeclaration vd = e.var.isVarDeclaration();
if (vd && vd.range)
return vd.range._cast(e.type);
- else if (vd && vd._init && !vd.type.isMutable() && (ie = vd.getConstInitializer()) !is null)
+ if (vd && vd._init && !vd.type.isMutable() && (ie = vd.getConstInitializer()) !is null)
return getIntRange(ie);
- else
- return visit(e);
+ return visit(e);
}
IntRange visitComma(CommaExp e)
// import [aliasId] = std.stdio;
return aliasId;
}
- else if (packages.length > 0)
+ if (packages.length > 0)
{
// import [std].stdio;
return packages[0];
}
- else
- {
- // import [id];
- return id;
- }
+ // import [id];
+ return id;
}
super(loc, selectIdent());
packages ~= s.ident;
reverse(packages);
- if (Module.find(getFilename(packages, ident)))
- Module.load(Loc.initial, packages, this.ident);
+ ImportPathInfo pathThatFoundThis;
+ if (Module.find(getFilename(packages, ident), pathThatFoundThis))
+ Module.load(Loc.initial, packages, this.ident, pathThatFoundThis);
else
isPkgMod = PKG.package_;
}
static const(char)* find(const(char)* filename)
{
- return find(filename.toDString).ptr;
+ ImportPathInfo pathThatFoundThis; // is this needed? In fact is this function needed still???
+ return find(filename.toDString, pathThatFoundThis).ptr;
}
- extern (D) static const(char)[] find(const(char)[] filename)
+ extern (D) static const(char)[] find(const(char)[] filename, out ImportPathInfo pathThatFoundThis)
{
- return global.fileManager.lookForSourceFile(filename, global.path[]);
+ ptrdiff_t whichPathFoundThis;
+ const(char)[] ret = global.fileManager.lookForSourceFile(filename, global.path[], whichPathFoundThis);
+
+ if (whichPathFoundThis >= 0)
+ pathThatFoundThis = global.path[whichPathFoundThis];
+ return ret;
}
extern (C++) static Module load(const ref Loc loc, Identifiers* packages, Identifier ident)
return load(loc, packages ? (*packages)[] : null, ident);
}
- extern (D) static Module load(const ref Loc loc, Identifier[] packages, Identifier ident)
+ extern (D) static Module load(const ref Loc loc, Identifier[] packages, Identifier ident, ImportPathInfo pathInfo = ImportPathInfo.init)
{
//printf("Module::load(ident = '%s')\n", ident.toChars());
// Build module filename by turning:
// foo\bar\baz
const(char)[] filename = getFilename(packages, ident);
// Look for the source file
- if (const result = find(filename))
+ ImportPathInfo importPathThatFindUs;
+ if (const result = find(filename, importPathThatFindUs))
+ {
filename = result; // leaks
+ pathInfo = importPathThatFindUs;
+ }
auto m = new Module(loc, filename, ident, 0, 0);
+ // TODO: apply import path information (pathInfo) on to module
+
if (!m.read(loc))
return null;
if (global.params.v.verbose)
if (global.path.length)
{
foreach (i, p; global.path[])
- fprintf(stderr, "import path[%llu] = %s\n", cast(ulong)i, p);
+ fprintf(stderr, "import path[%llu] = %s\n", cast(ulong)i, p.path);
}
else
{
auto p = slice.ptr;
for (size_t j = 0; j < slice.length; j++)
{
- char c = p[j];
+ const c = p[j];
if (c == 0xFF && j + 1 < slice.length)
{
j++;
{
for (size_t u = start; u < buf.length; u++)
{
- char c = buf[u];
+ const c = buf[u];
switch (c)
{
case '$':
for (size_t u = buf.length; u > start;)
{
u--;
- char c = buf[u];
+ const c = buf[u];
switch (c)
{
case ')':
bool hasCpCtorLocal;
bool hasMoveCtorLocal;
- needCopyCtor(this, hasCpCtorLocal, hasMoveCtorLocal);
+ bool needCopyCtor;
+ bool needMoveCtor;
+ needCopyOrMoveCtor(this, hasCpCtorLocal, hasMoveCtorLocal, needCopyCtor, needMoveCtor);
if (enclosing || // is nested
search(this, loc, Id.postblit) || // has postblit
if (param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf())
{
//printf("copy constructor %p\n", ctd);
+ assert(!ctd.isCpCtor && !ctd.isMoveCtor);
if (param.storageClass & STC.ref_)
ctd.isCpCtor = true; // copy constructor
else
ctd.isMoveCtor = true; // move constructor
+ assert(!(ctd.isCpCtor && ctd.isMoveCtor));
}
}
}
buildDtors(sd, sc2);
+ bool hasCopyCtor;
bool hasMoveCtor;
- sd.hasCopyCtor = buildCopyCtor(sd, sc2, hasMoveCtor);
+ bool needCopyCtor;
+ bool needMoveCtor;
+ needCopyOrMoveCtor(sd, hasCopyCtor, hasMoveCtor, needCopyCtor, needMoveCtor);
+ //printf("%s hasCopy %d hasMove %d needCopy %d needMove %d\n", sd.toChars(), hasCopyCtor, hasMoveCtor, needCopyCtor, needMoveCtor);
+
+ /* When generating a move ctor, generate a copy ctor too, otherwise
+ * https://github.com/s-ludwig/taggedalgebraic/issues/75
+ */
+ if (0 && needMoveCtor && !hasCopyCtor)
+ {
+ needCopyCtor = true;
+ }
+
+ if (needCopyCtor)
+ {
+ assert(hasCopyCtor == false);
+ buildCopyOrMoveCtor(sd, sc2, false); // build copy constructor
+ hasCopyCtor = true;
+ }
+ if (needMoveCtor)
+ {
+ assert(hasMoveCtor == false);
+ buildCopyOrMoveCtor(sd, sc2, true); // build move constructor
+ hasMoveCtor = true;
+ }
+ sd.hasCopyCtor = hasCopyCtor;
sd.hasMoveCtor = hasMoveCtor;
sd.postblit = buildPostBlit(sd, sc2);
s = b.sym.search(loc, ident, flags);
if (!s)
continue;
- else if (s == cd) // happens if s is nested in this and derives from this
+ if (s == cd) // happens if s is nested in this and derives from this
s = null;
else if (!(flags & SearchOpt.ignoreVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(cd, s))
s = null;
fieldState.fieldSize = memsize;
else
{
- auto size = (pastField + 7) / 8;
+ const size = (pastField + 7) / 8;
fieldState.fieldSize = size;
//printf(" offset: %d, size: %d\n", offset, size);
if (isunion)
*/
extern (D) TemplateTupleParameter isVariadic()
{
- size_t dim = parameters.length;
+ const dim = parameters.length;
if (dim == 0)
return null;
return (*parameters)[dim - 1].isTemplateTupleParameter();
if (auto ttp = tp.isTemplateTypeParameter())
return matchArgType(ttp);
- else if (auto tvp = tp.isTemplateValueParameter())
+ if (auto tvp = tp.isTemplateValueParameter())
return matchArgValue(tvp);
- else if (auto tap = tp.isTemplateAliasParameter())
+ if (auto tap = tp.isTemplateAliasParameter())
return matchArgAlias(tap);
- else if (auto ttp = tp.isTemplateTupleParameter())
+ if (auto ttp = tp.isTemplateTupleParameter())
return matchArgTuple(ttp);
- else
- assert(0);
+ assert(0);
}
{
if (vd._init && !vd._init.isVoidInitializer())
return AST.initializerToExpression(vd._init);
- else if (auto ts = vd.type.isTypeStruct())
+ if (auto ts = vd.type.isTypeStruct())
{
if (!ts.sym.noDefaultCtor && !ts.sym.isUnionDeclaration())
{
va_end(ap);
}
+/// Callback for when the backend wants to report an error
+extern(C++) void errorBackend(const(char)* filename, uint linnum, uint charnum, const(char)* format, ...)
+{
+ const loc = Loc(filename, linnum, charnum);
+ va_list ap;
+ va_start(ap, format);
+ verrorReport(loc, format, ap, ErrorKind.error);
+ va_end(ap);
+}
+
/**
* Print additional details about an error message.
* Doesn't increase the error count or print an additional error prefix.
* p1 = additional message prefix
* p2 = additional message prefix
*/
-extern (C++) void verrorReport(const ref Loc loc, const(char)* format, va_list ap, ErrorKind kind, const(char)* p1 = null, const(char)* p2 = null);
+private extern(C++) void verrorReport(const ref Loc loc, const(char)* format, va_list ap, ErrorKind kind, const(char)* p1 = null, const(char)* p2 = null);
+
+/// ditto
+private extern(C++) void verrorReport(const SourceLoc loc, const(char)* format, va_list ap, ErrorKind kind, const(char)* p1 = null, const(char)* p2 = null);
/**
* Implements $(D errorSupplemental), $(D warningSupplemental), and
* ap = printf-style variadic arguments
* kind = kind of error being printed
*/
-extern (C++) void verrorReportSupplemental(const ref Loc loc, const(char)* format, va_list ap, ErrorKind kind);
+private extern(C++) void verrorReportSupplemental(const ref Loc loc, const(char)* format, va_list ap, ErrorKind kind);
+
+/// ditto
+private extern(C++) void verrorReportSupplemental(const SourceLoc loc, const(char)* format, va_list ap, ErrorKind kind);
/**
* The type of the fatal error handler
{
if (td)
return new FuncExp(loc, td.syntaxCopy(null));
- else if (fd.semanticRun == PASS.initial)
+ if (fd.semanticRun == PASS.initial)
return new FuncExp(loc, fd.syntaxCopy(null));
- else // https://issues.dlang.org/show_bug.cgi?id=13481
- // Prevent multiple semantic analysis of lambda body.
- return new FuncExp(loc, fd);
+ // https://issues.dlang.org/show_bug.cgi?id=13481
+ // Prevent multiple semantic analysis of lambda body.
+ return new FuncExp(loc, fd);
}
override const(char)* toChars() const
t = t.toBasetype();
if (auto tf = t.isTypeFunction())
return tf;
- else if (auto td = t.isTypeDelegate())
+ if (auto td = t.isTypeDelegate())
return td.nextOf().isTypeFunction();
- else
- return null;
+ return null;
}
FuncDeclaration isFuncAddress(Expression e, bool* hasOverloads = null) @safe
{
if (ad2 == ad)
return false;
- else if (ad2.isNested())
+ if (ad2.isNested())
continue;
- else
- return true;
+ return true;
}
if (FuncDeclaration f = s.isFuncDeclaration())
{
}
else if (auto oe = e1.isOverExp())
return handleOverloadSet(oe.vars);
- else if (auto dti = e1.isDotTemplateInstanceExp())
+ if (auto dti = e1.isDotTemplateInstanceExp())
{
if (dti.ti.tempdecl)
if (auto td = dti.ti.tempdecl.isTemplateDeclaration())
}
else if (auto dte = e1.isDotTemplateExp())
return handleTemplateDecl(dte.td);
- else if (auto se = e1.isScopeExp())
+ if (auto se = e1.isScopeExp())
{
Dsymbol s = se.sds;
TemplateInstance ti = s.isTemplateInstance();
}
else if (auto et = e1.isTemplateExp())
return handleTemplateDecl(et.td);
- else if (e1.isDotVarExp() && e1.type.isTypeFunction())
+ if (e1.isDotVarExp() && e1.type.isTypeFunction())
{
DotVarExp dve = e1.isDotVarExp();
return handleFuncDecl(dve.var.isFuncDeclaration());
if (sd.ctor)
{
auto ctor = sd.ctor.isCtorDeclaration();
- if (ctor && ctor.isCpCtor && ctor.isGenerated())
+ if (ctor && (ctor.isCpCtor || ctor.isMoveCtor) && ctor.isGenerated())
sd.ctor = null;
}
return no();
if (e.tok2 == TOK.package_ && p.isModule()) // Note that isModule() will return null for package modules because they're not actually instances of Module.
return no();
- else if(e.tok2 == TOK.module_ && !(p.isModule() || p.isPackageMod()))
+ if (e.tok2 == TOK.module_ && !(p.isModule() || p.isPackageMod()))
return no();
tded = e.targ;
return yes();
if (auto ctor = d.isCtorDeclaration())
{
+ //printf("checkDisabled() %s %s\n", ctor.toPrettyChars(), toChars(ctor.type));
if (ctor.isCpCtor && ctor.isGenerated())
{
.error(loc, "generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", d.parent.toPrettyChars());
* Does not open the file.
* Params:
* filename = as supplied by the user
- * paths = paths to look for filename
+ * pathsInfo = pathsInfo to look for filename with metadata
+ * whichPathFoundThis = Which path from `path` was used in determining the output path, or -1 if unknown.
* Returns:
* the found file name or
* `null` if it is not different from filename.
*/
- const(char)[] lookForSourceFile(const char[] filename, const char*[] paths)
+ const(char)[] lookForSourceFile(const char[] filename, const ImportPathInfo[] pathsInfo, out ptrdiff_t whichPathFoundThis)
{
//printf("lookForSourceFile(`%.*s`)\n", cast(int)filename.length, filename.ptr);
- /* Search along paths[] for .di file, then .d file.
+ /* Search along pathsInfo[] for .di file, then .d file.
*/
+
+ whichPathFoundThis = -1;
+
// see if we should check for the module locally.
bool checkLocal = pathCache.pathExists(filename);
const sdi = FileName.forceExt(filename, hdr_ext);
if (FileName.absolute(filename))
return null;
- if (!paths.length)
+ if (!pathsInfo.length)
return null;
- foreach (entry; paths)
+ foreach (pathIndex, entry; pathsInfo)
{
- const p = entry.toDString();
+ const p = entry.path.toDString();
const(char)[] n = FileName.combine(p, sdi);
n = FileName.combine(p, sd);
if (FileName.exists(n) == 1) {
+ whichPathFoundThis = pathIndex;
return n;
}
FileName.free(n.ptr);
if (pathCache.isExistingPath(n))
{
const n2i = FileName.combine(n, package_di);
- if (FileName.exists(n2i) == 1)
+ if (FileName.exists(n2i) == 1) {
+ whichPathFoundThis = pathIndex;
return n2i;
+ }
+
FileName.free(n2i.ptr);
const n2 = FileName.combine(n, package_d);
if (FileName.exists(n2) == 1) {
+ whichPathFoundThis = pathIndex;
return n2;
}
FileName.free(n2.ptr);
if (FileName.exists(sc) == 1)
return sc;
scope(exit) FileName.free(sc.ptr);
- foreach (entry; paths)
+ foreach (pathIndex, entry; pathsInfo)
{
- const p = entry.toDString();
+ const p = entry.path.toDString();
const(char)[] n = FileName.combine(p, si);
if (FileName.exists(n) == 1) {
+ whichPathFoundThis = pathIndex;
return n;
}
FileName.free(n.ptr);
n = FileName.combine(p, sc);
if (FileName.exists(n) == 1) {
+ whichPathFoundThis = pathIndex;
return n;
}
FileName.free(n.ptr);
{
bool isCpCtor; // copy constructor
bool isMoveCtor; // move constructor (aka rvalue constructor)
- extern (D) this(const ref Loc loc, const ref Loc endloc, StorageClass stc, Type type, bool isCpCtor = false, bool isMoveCtor = false)
+ extern (D) this(const ref Loc loc, const ref Loc endloc, StorageClass stc, Type type)
{
super(loc, endloc, Id.ctor, stc, type);
- this.isCpCtor = isCpCtor;
- this.isMoveCtor = isMoveCtor;
//printf("CtorDeclaration(loc = %s) %s %p\n", loc.toChars(), toChars(), this);
}
{
printedMain = true;
auto name = mod.srcfile.toChars();
- auto path = FileName.searchPath(global.path, name, true);
+ auto path = FileName.searchPath(global.importPaths, name, true);
message("entry %-10s\t%s", type, path ? path : name);
}
}
version (none)
{
- printf("resolveFuncCall('%s')\n", s.toChars());
+ printf("resolveFuncCall() %s)\n", s.toChars());
if (tthis)
printf("\tthis: %s\n", tthis.toChars());
if (fargs)
printf("\t%s: %s\n", arg.toChars(), arg.type.toChars());
}
}
- printf("\tfnames: %s\n", fnames ? fnames.toChars() : "null");
}
if (tiargs && arrayObjectIsError(*tiargs))
/**********************************
* Decide if attributes for this function can be inferred from examining
* the function body.
+ * Params:
+ * fd = function to infer attributes for
+ * sc = context
* Returns:
* true if can
*/
(!fd.isMember() || sc.func.isSafeBypassingInference() && !fd.isInstantiated()))
return true;
if (fd.isFuncLiteralDeclaration() || // externs are not possible with literals
- (fd.storage_class & STC.inference) || // do attribute inference
+ (fd.storage_class & STC.inference) || // do attribute inference
+ fd.isGenerated || // compiler generated function
(fd.inferRetType && !fd.isCtorDeclaration()))
return true;
if (fd.isInstantiated())
auto v = ve.var.isVarDeclaration();
if (!v || v.isReference())
return false;
- else if (fd.nrvo_var is null)
+ if (fd.nrvo_var is null)
{
// Variables in the data segment (e.g. globals, TLS or not),
// parameters and closure variables cannot be NRVOed.
}
}
+extern (C++) struct ImportPathInfo {
+ const(char)* path; // char*'s of where to look for import modules
+}
+
/// Put command line switches in here
extern (C++) struct Param
{
const(char)[] argv0; // program name
Array!(const(char)*) modFileAliasStrings; // array of char*'s of -I module filename alias strings
- Array!(const(char)*) imppath; // array of char*'s of where to look for import modules
+ Array!(ImportPathInfo) imppath; // array of import path information of where to look for import modules
Array!(const(char)*) fileImppath; // array of char*'s of where to look for file import modules
const(char)[] objdir; // .obj/.lib file output directory
const(char)[] objname; // .obj file output name
string copyright = "Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved";
string written = "written by Walter Bright";
- Array!(const(char)*) path; /// Array of char*'s which form the import lookup path
+ Array!(ImportPathInfo) path; /// Array of path informations which form the import lookup path
+ Array!(const(char)*) importPaths; /// Array of char*'s which form the import lookup path without metadata
Array!(const(char)*) filePath; /// Array of char*'s which form the file import lookup path
private enum string _version = import("VERSION");
unsigned errorSupplementCount();
};
+struct ImportPathInfo
+{
+ const char* path;
+
+ ImportPathInfo() : path(NULL) { }
+ ImportPathInfo(const char* p) : path(p) { }
+};
+
// Put command line switches in here
struct Param
{
DString argv0; // program name
Array<const char *> modFileAliasStrings; // array of char*'s of -I module filename alias strings
- Array<const char *> imppath; // array of char*'s of where to look for import modules
+ Array<ImportPathInfo> imppath; // array of import path information of where to look for import modules
Array<const char *> fileImppath; // array of char*'s of where to look for file import modules
DString objdir; // .obj/.lib file output directory
DString objname; // .obj file output name
const DString copyright;
const DString written;
- Array<const char *> path; // Array of char*'s which form the import lookup path
- Array<const char *> filePath; // Array of char*'s which form the file import lookup path
+ Array<ImportPathInfo> path; // Array of path informations which form the import lookup path
+ Array<const char *> importPaths; // Array of char*'s which form the import lookup path without metadata
+ Array<const char *> filePath; // Array of char*'s which form the file import lookup path
char datetime[26]; /// string returned by ctime()
CompileEnv compileEnv;
default:
if (auto be = e.isBinExp())
return visitBin(be);
- else if (auto ue = e.isUnaExp())
+ if (auto ue = e.isUnaExp())
return visitUna(ue);
- else if (auto de = e.isDefaultInitExp())
+ if (auto de = e.isDefaultInitExp())
return visitDefaultInit(e.isDefaultInitExp());
return visit(e);
arrayStart();
foreach (importPath; global.params.imppath[])
{
- item(importPath.toDString);
+ item(importPath.path.toDString);
}
arrayEnd();
if (isidchar(c))
continue;
- else if (c & 0x80)
+ if (c & 0x80)
{
const s = p;
const u = decodeUTF();
{
if (isImmutable())
return MODFlags.immutable_;
- else if (isWildConst())
+ if (isWildConst())
{
if (t.isWildConst())
return MODFlags.wild;
nextToken();
if (id == Id.Windows)
return returnLinkage(LINK.windows);
- else if (id == Id.D)
+ if (id == Id.D)
return returnLinkage(LINK.d);
- else if (id == Id.System)
+ if (id == Id.System)
return returnLinkage(LINK.system);
- else if (id == Id.Objective) // Looking for tokens "Objective-C"
+ if (id == Id.Objective) // Looking for tokens "Objective-C"
{
if (token.value != TOK.min)
return invalidLinkage();
const opt = e.toBool();
if (opt.isEmpty())
return PINLINE.default_;
- else if (opt.get())
+ if (opt.get())
return PINLINE.always;
- else
- return PINLINE.never;
+ return PINLINE.never;
}
/**
OutBuffer buf;
if (expressionsToString(buf, sc, args, loc, "while evaluating `pragma(msg, %s)`", false))
return false;
- else
- {
- buf.writestring("\n");
- fprintf(stderr, buf.extractChars);
- }
+
+ buf.writestring("\n");
+ fprintf(stderr, buf.extractChars);
return true;
}
// Don't allow D `immutable` and `shared` types to be interfaced with C++
if (type.isImmutable() || type.isShared())
return true;
- else if (Type cpptype = target.cpp.parameterType(type))
+ if (Type cpptype = target.cpp.parameterType(type))
type = cpptype;
if (origType is null)
Dsymbol s = ta.toDsymbol(sc);
if (s)
return s;
- else if (TypeInstance ti = ta.isTypeInstance())
+ if (TypeInstance ti = ta.isTypeInstance())
{
Type t;
const errors = global.errors;
// see https://issues.dlang.org/show_bug.cgi?id=16472
if (t)
return t.typeSemantic(loc, sc);
- else if (ea)
+ if (ea)
{
return eaCTFE();
}
- else if (s)
+ if (s)
return s;
- else
- assert(0);
+ assert(0);
}
else
return ta.typeSemantic(loc, sc);
if (ClassDeclaration cd = agg.isClassDeclaration())
return cd.com ? True() : False();
- else
- return False();
+ return False();
}
if (e.ident == Id.identifier)
{
{
if (cfd.isCpCtor && !arg.isLvalue())
return MATCH.nomatch; // copy constructor is only for lvalues
- else if (cfd.isMoveCtor && arg.isLvalue())
+ if (cfd.isMoveCtor && arg.isLvalue())
return MATCH.nomatch; // move constructor is only for rvalues
}
}
auto tb = t.toBasetype();
if (att && tb.equivalent(att))
return true;
- else if (!att && tb.checkAliasThisRec())
+ if (!att && tb.checkAliasThisRec())
att = tb;
return false;
}
* loc = the location for reporting line nunbers in errors
* t = the type to get the type of the `TypeInfo` object for
* sc = the scope
- * genObjCode = if true, object code will be generated for the obtained TypeInfo
* Returns:
* The type of the `TypeInfo` object associated with `t`
*/
--- /dev/null
+/* This used to not be allowed
+ * https://github.com/dlang/dmd/pull/20634
+ */
+
+struct A
+{
+ this (ref shared A a) immutable {}
+}
+
+struct B
+{
+ A a;
+ this(immutable B b) shared {}
+}
Agg s;
}
+void test18890()
+{
version (CppMangle_Itanium)
{
static assert(C18890.__dtor.mangleof == "_ZN6C18890D1Ev");
static assert(C18890_2.__xdtor.mangleof == "??_GC18890_2@@UEAAPEAXI@Z");
}
}
+}
/**************************************/
// https://issues.dlang.org/show_bug.cgi?id=18891
Agg s;
}
+void test18891()
+{
version (CppMangle_Itanium)
{
static assert(C18891.__dtor.mangleof == "_ZN6C18891D1Ev");
static assert(C18891.__xdtor.mangleof == "??_GC18891@@UEAAPEAXI@Z");
}
}
+}
/**************************************/
// Test C++ operator mangling
{}
}
-// Add more tests regarding inferences later.
+/***************************************************/
+// https://github.com/dlang/dmd/pull/20685
+
+struct T1
+{
+ int a;
+ inout this(ref inout T1 t) @nogc nothrow pure { a = t.a; }
+}
+
+struct S1
+{
+ T1 t; // generate copy constructor, infer @nogc nothrow pure
+}
+
+void test1() @nogc nothrow pure
+{
+ S1 s;
+ S1 t = s;
+}
+++ /dev/null
-/*
-TEST_OUTPUT:
----
-fail_compilation/failCopyCtor2.d(15): Error: `struct B` may not define a rvalue constructor and have fields with copy constructors
-fail_compilation/failCopyCtor2.d(18): rvalue constructor defined here
-fail_compilation/failCopyCtor2.d(17): field with copy constructor defined here
----
-*/
-
-struct A
-{
- this (ref shared A a) immutable {}
-}
-
-struct B
-{
- A a;
- this(immutable B b) shared {}
-}
fail_compilation/retscope2.d(1107): Error: returning scope variable `dg` is not allowed in a `@safe` function
fail_compilation/retscope2.d(1216): Error: returning `s.foo()` escapes a reference to local variable `s`
fail_compilation/retscope2.d(1233): Error: returning `t.foo()` escapes a reference to local variable `t`
-fail_compilation/retscope2.d(1306): Error: escaping a reference to local variable `i by copying `& i` into allocated memory is not allowed in a `@safe` function
+fail_compilation/retscope2.d(1306): Error: escaping a reference to local variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` function
---
*/
/*
TEST_OUTPUT:
---
-fail_compilation/retscope3.d(2008): Error: escaping a reference to local variable `i by copying `& i` into allocated memory is not allowed in a `@safe` function
-fail_compilation/retscope3.d(2017): Error: escaping a reference to local variable `i by copying `S2000(& i)` into allocated memory is not allowed in a `@safe` function
+fail_compilation/retscope3.d(2008): Error: escaping a reference to local variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` function
+fail_compilation/retscope3.d(2017): Error: escaping a reference to local variable `i` by copying `S2000(& i)` into allocated memory is not allowed in a `@safe` function
fail_compilation/retscope3.d(4003): Error: escaping a reference to parameter `u` by copying `u[]` into allocated memory is not allowed in a `@safe` function
fail_compilation/retscope3.d(4016): Error: storing reference to outer local variable `i` into allocated memory causes it to escape
fail_compilation/retscope3.d(4025): Error: escaping reference to stack allocated value returned by `makeSA()` into allocated memory
/*
TEST_OUTPUT:
---
-fail_compilation/retscope6.d(6007): Error: escaping a reference to local variable `i by copying `& i` into allocated memory is not allowed in a `@safe` function
+fail_compilation/retscope6.d(6007): Error: escaping a reference to local variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` function
---
*/
TEST_OUTPUT:
---
fail_compilation/test18282.d(25): Error: returning scope variable `aa` is not allowed in a `@safe` function
-fail_compilation/test18282.d(34): Error: escaping a reference to local variable `i by copying `& i` into allocated memory is not allowed in a `@safe` function
-fail_compilation/test18282.d(35): Error: escaping a reference to local variable `i by copying `& i` into allocated memory is not allowed in a `@safe` function
+fail_compilation/test18282.d(34): Error: escaping a reference to local variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` function
+fail_compilation/test18282.d(35): Error: escaping a reference to local variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` function
fail_compilation/test18282.d(36): Error: returning scope variable `staa` is not allowed in a `@safe` function
-fail_compilation/test18282.d(44): Error: escaping a reference to local variable `i by copying `S2000(& i)` into allocated memory is not allowed in a `@safe` function
-fail_compilation/test18282.d(53): Error: escaping a reference to local variable `i by copying `& i` into allocated memory is not allowed in a `@safe` function
-fail_compilation/test18282.d(53): Error: escaping a reference to local variable `c by copying `& c` into allocated memory is not allowed in a `@safe` function
+fail_compilation/test18282.d(44): Error: escaping a reference to local variable `i` by copying `S2000(& i)` into allocated memory is not allowed in a `@safe` function
+fail_compilation/test18282.d(53): Error: escaping a reference to local variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` function
+fail_compilation/test18282.d(53): Error: escaping a reference to local variable `c` by copying `& c` into allocated memory is not allowed in a `@safe` function
---
*/
/******************************
TEST_OUTPUT:
---
-fail_compilation/test18282.d(1007): Error: escaping a reference to local variable `foo by copying `& foo` into allocated memory is not allowed in a `@safe` function
-fail_compilation/test18282.d(1008): Error: escaping a reference to local variable `foo by copying `& foo` into allocated memory is not allowed in a `@safe` function
-fail_compilation/test18282.d(1009): Error: escaping a reference to local variable `foo by copying `& foo` into allocated memory is not allowed in a `@safe` function
+fail_compilation/test18282.d(1007): Error: escaping a reference to local variable `foo` by copying `& foo` into allocated memory is not allowed in a `@safe` function
+fail_compilation/test18282.d(1008): Error: escaping a reference to local variable `foo` by copying `& foo` into allocated memory is not allowed in a `@safe` function
+fail_compilation/test18282.d(1009): Error: escaping a reference to local variable `foo` by copying `& foo` into allocated memory is not allowed in a `@safe` function
fail_compilation/test18282.d(1016): Error: escaping a reference to parameter `this` by copying `&this` into allocated memory is not allowed in a `@safe` function
---
*/
/********************************/
+struct T9
+{
+ int i;
+ inout this(ref inout T9 t) { this.i = t.i - 1; printf("this(ref T9)\n"); }
+ inout this(inout T9 t) { this.i = t.i + 1; printf("this(T9)\n"); }
+}
+
+struct S9
+{
+ T9 t;
+ //inout this(return ref scope inout S9 t);// { this.i = t.i - 1; printf("this(ref T9)\n"); }
+ //@system inout this(return scope inout S9 t);// { this.i = t.i + 1; printf("this(T9)\n"); }
+}
+
+void test9()
+{
+ S9 s;
+ s.t.i = 3;
+ S9 u = s;
+ printf("u.t.i = %d\n", u.t.i);
+ assert(u.t.i == 2);
+
+ S9 v = __rvalue(u);
+ printf("v.t.i = %d\n", v.t.i);
+ assert(v.t.i == 3);
+}
+
+/********************************/
+// https://github.com/s-ludwig/taggedalgebraic/issues/75
+
+struct T10
+{
+ string s;
+ this(T10) {}
+ this(string v) { s = v; }
+}
+
+struct S10
+{
+ T10 p;
+}
+
+void test10()
+{
+ S10 s = S10(T10("hello"));
+ assert(s.p.s == "hello");
+}
+
+/********************************/
+
int main()
{
test1();
test6();
test7();
test8();
+ test9();
return 0;
}
-c7902293d7df9d02546562cb09fc8439004a70d1
+d6f693b46a1565172cac7a1438905141783a164f
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
/// Provide static branch and value hints for the LDC/GDC compilers.
/// DMD ignores these hints.
-pragma(inline, true) bool likely(bool b) { return !!expect(b, true); }
+pragma(inline, true) bool likely()(bool b) { return !!expect(b, true); }
/// ditto
-pragma(inline, true) bool unlikely(bool b) { return !!expect(b, false); }
+pragma(inline, true) bool unlikely()(bool b) { return !!expect(b, false); }
+
+///
+@nogc nothrow pure @safe unittest
+{
+ int x = 12;
+
+ expect(x, 12);
+
+ if (likely(x > 0))
+ {
+ // ...
+ }
+ else if (unlikely(x == int.min))
+ {
+ // ...
+ }
+}
if (parseMangledNameArg())
continue;
- else
- {
- dst.len = l;
- pos = p;
- brp = b;
- debug(trace) printf( "not a mangled name arg\n" );
- }
+ dst.len = l;
+ pos = p;
+ brp = b;
+ debug(trace) printf( "not a mangled name arg\n" );
}
if ( isDigit( front ) && isDigit( peek( 1 ) ) )
{
while (waited_pid == -1 && errno == EINTR);
if (waited_pid == 0)
return ChildStatus.running;
- else if (errno == ECHILD)
+ if (errno == ECHILD)
return ChildStatus.done; // someone called posix.syswait
- else if (waited_pid != pid || status != 0)
+ if (waited_pid != pid || status != 0)
onForkError();
return ChildStatus.done;
}
version (ARM) version = ARM_Any;
version (AArch64) version = ARM_Any;
version (HPPA) version = HPPA_Any;
+version (HPPA64) version = HPPA_Any;
version (MIPS32) version = MIPS_Any;
version (MIPS64) version = MIPS_Any;
version (PPC) version = PPC_Any;
SO_RCVLOWAT = 0x1004,
SO_RCVTIMEO = 0x1006,
SO_REUSEADDR = 0x0004,
+ SO_REUSEPORT = 0x0200,
SO_SNDBUF = 0x1001,
SO_SNDLOWAT = 0x1003,
SO_SNDTIMEO = 0x1005,
SO_RCVLOWAT = 0x1004,
SO_RCVTIMEO = 0x1006,
SO_REUSEADDR = 0x0004,
+ SO_REUSEPORT = 0x0200,
SO_SNDBUF = 0x1001,
SO_SNDLOWAT = 0x1003,
SO_SNDTIMEO = 0x1005,
SO_RCVLOWAT = 16,
SO_RCVTIMEO = 18,
SO_REUSEADDR = 2,
+ SO_REUSEPORT = 15,
SO_SNDBUF = 7,
SO_SNDLOWAT = 17,
SO_SNDTIMEO = 19,
SO_RCVLOWAT = 18,
SO_RCVTIMEO = 20,
SO_REUSEADDR = 2,
+ SO_REUSEPORT = 15,
SO_SNDBUF = 7,
SO_SNDLOWAT = 19,
SO_SNDTIMEO = 21,
SO_RCVLOWAT = 18,
SO_RCVTIMEO = 20,
SO_REUSEADDR = 2,
+ SO_REUSEPORT = 0x0200, //FIXME: the rest appear to be wrong
SO_SNDBUF = 7,
SO_SNDLOWAT = 19,
SO_SNDTIMEO = 21,
SO_RCVLOWAT = 18,
SO_RCVTIMEO = 20,
SO_REUSEADDR = 2,
+ SO_REUSEPORT = 15,
SO_SNDBUF = 7,
SO_SNDLOWAT = 19,
SO_SNDTIMEO = 21,
SO_RCVLOWAT = 18,
SO_RCVTIMEO = 20,
SO_REUSEADDR = 2,
+ SO_REUSEPORT = 15,
SO_SNDBUF = 7,
SO_SNDLOWAT = 19,
SO_SNDTIMEO = 21,
SO_RCVLOWAT = 0x1004,
SO_RCVTIMEO = 0x1006,
SO_REUSEADDR = 0x0004,
+ SO_REUSEPORT = 0x100e,
SO_SNDBUF = 0x1001,
SO_SNDLOWAT = 0x1003,
SO_SNDTIMEO = 0x1005,
-03aeafd2095b563bb66b75342652d2dcea66c9e8
+336bed6d8ffec74d117b755866c5bd22e3d610a1
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.
alias memoize = impl;
}
- auto impl(Args...)(Args args) if (is(typeof(fun(args))))
+ auto impl(Args...)(Args args)
+ if (is(typeof(fun(args))))
{
import std.typecons : Tuple, tuple;
import std.traits : Unqual;
alias memoize = impl;
}
- auto impl(Args...)(Args args) if (is(typeof(fun(args))))
+ auto impl(Args...)(Args args)
+ if (is(typeof(fun(args))))
{
static if (args.length > 0)
{
/**
* Socket primitives.
- * Example: See $(SAMPLESRC listener.d) and $(SAMPLESRC htmlget.d)
+ * Example: See [listener.d](https://github.com/dlang/undeaD/blob/master/dmdsamples/listener.d) and [htmlget.d](https://github.com/dlang/undeaD/blob/master/dmdsamples/htmlget.d)
* License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
* Authors: Christopher E. Miller, $(HTTP klickverbot.at, David Nadlinger),
* $(HTTP thecybershadow.net, Vladimir Panteleev)
this(ref inout S rhs) @safe inout
{
- this.i = i;
+ this.i = rhs.i;
copied = true;
}
}
class MallocGC : GC
{
nothrow @nogc:
+ // To make sure all allocations are multiples of 8 bytes for alignment
+ private size_t alignUp(size_t size)
+ {
+ return (size + 7) & ~7LU;
+ }
+
static GC initialize()
{
import core.stdc.string : memcpy;
void* malloc(size_t size, uint bits, const TypeInfo ti) nothrow
{
+ size = alignUp(size);
return sentinelAdd(.malloc(size + sentinelSize), size);
}
BlkInfo qalloc(size_t size, uint bits, const scope TypeInfo ti) nothrow
{
+ size = alignUp(size);
return BlkInfo(malloc(size, bits, ti), size);
}
void* calloc(size_t size, uint bits, const TypeInfo ti) nothrow
{
+ size = alignUp(size);
return sentinelAdd(.calloc(1, size + sentinelSize), size);
}
void* realloc(void* p, size_t size, uint bits, const TypeInfo ti) nothrow
{
+ size = alignUp(size);
return sentinelAdd(.realloc(p - sentinelSize, size + sentinelSize), size);
}