d: Merge upstream dmd, druntime d6f693b46a, phobos 336bed6d8.

D front-end changes:

	- Import latest fixes from dmd v2.110.0-rc.1.

D runtime changes:

	- Import latest fixes from druntime v2.110.0-rc.1.

Phobos changes:

	- Import latest fixes from phobos v2.110.0-rc.1.

Included in the merge are fixes for the following PRs:

	PR d/118438
	PR d/118448
	PR d/118449

gcc/d/ChangeLog:

	* dmd/MERGE: Merge upstream dmd d6f693b46a.
	* d-incpath.cc (add_import_paths): Update for new front-end interface.

libphobos/ChangeLog:

	* libdruntime/MERGE: Merge upstream druntime d6f693b46a.
	* src/MERGE: Merge upstream phobos 336bed6d8.
	* testsuite/libphobos.init_fini/custom_gc.d: Adjust test.
This commit is contained in:
Iain Buclaw 2025-01-14 20:51:45 +01:00
parent 5006b9d810
commit c8894b6811
50 changed files with 474 additions and 270 deletions

View file

@ -133,7 +133,7 @@ add_import_paths (const char *iprefix, const char *imultilib, bool stdinc)
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;
@ -160,7 +160,7 @@ add_import_paths (const char *iprefix, const char *imultilib, bool stdinc)
/* 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;

View file

@ -1,4 +1,4 @@
c7902293d7df9d02546562cb09fc8439004a70d1
d6f693b46a1565172cac7a1438905141783a164f
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.

View file

@ -269,7 +269,7 @@ FuncDeclaration buildOpAssign(StructDeclaration sd, Scope* sc)
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
@ -1278,7 +1278,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
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
@ -1380,6 +1380,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
// 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);
@ -1445,6 +1446,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
*/
if (sdv.dtor)
{
sdv.dtor.isGenerated = true;
functionSemantic(sdv.dtor);
// keep a list of fields that need to be destroyed in case
@ -1545,25 +1547,27 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
}
/**
* 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;
@ -1571,28 +1575,37 @@ private CtorDeclaration generateCopyCtorDeclaration(StructDeclaration sd, const
}
/**
* 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());
}
@ -1600,6 +1613,57 @@ private Statement generateCopyCtorBody(StructDeclaration sd)
return new CompoundStatement(loc, s1);
}
/******************************************
* Find root `this` constructor for struct sd.
* (root is starting position for overloaded constructors)
* Params:
* sd = the `struct` to be searched
* ctor = `this` if found, otherwise null
* Result:
* false means `this` found in overload set
*/
private bool findStructConstructorRoot(StructDeclaration sd, out Dsymbol ctor)
{
ctor = sd.search(sd.loc, Id.ctor); // Aggregate.searchCtor() ?
if (ctor)
{
if (ctor.isOverloadSet())
return false;
if (auto td = ctor.isTemplateDeclaration())
ctor = td.funcroot;
}
return true;
}
/***********************************************
* 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())
return 0;
auto ctorDecl = s.isCtorDeclaration();
assert(ctorDecl);
if (ctorDecl.isCpCtor)
{
if (!copyCtor)
copyCtor = ctorDecl;
}
else if (ctorDecl.isMoveCtor)
{
if (!moveCtor)
moveCtor = ctorDecl;
}
return 0;
});
}
/**
* Determine if a copy constructor is needed for struct sd,
* if the following conditions are met:
@ -1609,69 +1673,42 @@ private Statement generateCopyCtorBody(StructDeclaration sd)
*
* Params:
* sd = the `struct` for which the copy constructor is generated
* hasCpCtor = set to true if a copy constructor is already present
* 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
*/
bool needCopyCtor(StructDeclaration sd, out bool hasCpCtor, out bool hasMoveCtor)
void needCopyOrMoveCtor(StructDeclaration sd, out bool hasCopyCtor, out bool hasMoveCtor, out bool needCopyCtor, out bool needMoveCtor)
{
//printf("needCopyCtor() %s\n", sd.toChars());
//printf("needCopyOrMoveCtor() %s\n", sd.toChars());
if (global.errors)
return false;
return;
Dsymbol ctor;
if (!findStructConstructorRoot(sd, ctor))
return;
CtorDeclaration copyCtor;
CtorDeclaration moveCtor;
auto ctor = sd.search(sd.loc, Id.ctor);
if (ctor)
{
if (ctor.isOverloadSet())
return false;
if (auto td = ctor.isTemplateDeclaration())
ctor = td.funcroot;
}
findMoveAndCopyConstructors(ctor, copyCtor, moveCtor);
CtorDeclaration cpCtor;
CtorDeclaration rvalueCtor;
if (!ctor)
goto LcheckFields;
overloadApply(ctor, (Dsymbol s)
{
if (s.isTemplateDeclaration())
return 0;
auto ctorDecl = s.isCtorDeclaration();
assert(ctorDecl);
if (ctorDecl.isCpCtor)
{
if (!cpCtor)
cpCtor = ctorDecl;
return 0;
}
if (ctorDecl.isMoveCtor)
rvalueCtor = ctorDecl;
return 0;
});
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)
{
@ -1686,20 +1723,25 @@ LcheckFields:
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;
}
/**
@ -1713,28 +1755,20 @@ LcheckFields:
* }
*
* 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();
@ -1751,5 +1785,4 @@ bool buildCopyCtor(StructDeclaration sd, Scope* sc, out bool hasMoveCtor)
ccd.storage_class |= STC.disable;
ccd.fbody = null;
}
return true;
}

View file

@ -1226,10 +1226,7 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
{
return 1; // they are not equal
}
else
{
return (r1 != r2);
}
return (r1 != r2);
}
else if (e1.type.isComplex())
{
@ -1242,33 +1239,30 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
// 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)
{
@ -1361,11 +1355,11 @@ bool ctfeCmp(const ref Loc loc, EXP op, Expression e1, Expression e2)
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());

View file

@ -474,7 +474,7 @@ MATCH implicitConvTo(Expression e, Type t)
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;
@ -1499,12 +1499,11 @@ MATCH implicitConvTo(Type from, Type to)
{
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)
@ -4150,9 +4149,9 @@ Expression typeCombine(BinExp be, Scope* sc)
// 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();
}
@ -4399,10 +4398,9 @@ IntRange getIntRange(Expression e)
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)

View file

@ -50,16 +50,13 @@ extern (C++) final class Import : Dsymbol
// 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());

View file

@ -310,8 +310,9 @@ extern (C++) class Package : ScopeDsymbol
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_;
}
@ -499,12 +500,18 @@ extern (C++) final class Module : 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)
@ -512,7 +519,7 @@ extern (C++) final class Module : Package
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:
@ -521,11 +528,17 @@ extern (C++) final class Module : Package
// 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)
@ -662,7 +675,7 @@ extern (C++) final class Module : Package
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
{

View file

@ -477,7 +477,7 @@ void gendocfile(Module m, const char[] ddoctext, const char* datetime, ErrorSink
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++;
@ -510,7 +510,7 @@ void escapeDdocString(ref OutBuffer buf, size_t start)
{
for (size_t u = start; u < buf.length; u++)
{
char c = buf[u];
const c = buf[u];
switch (c)
{
case '$':
@ -637,7 +637,7 @@ private void escapeStrayParenthesis(Loc loc, ref OutBuffer buf, size_t start, bo
for (size_t u = buf.length; u > start;)
{
u--;
char c = buf[u];
const c = buf[u];
switch (c)
{
case ')':

View file

@ -323,7 +323,9 @@ extern (C++) class StructDeclaration : AggregateDeclaration
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

View file

@ -2513,10 +2513,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
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));
}
}
}
@ -3007,8 +3009,34 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
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);
@ -6601,7 +6629,7 @@ private extern(C++) class SearchVisitor : Visitor
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;
@ -7265,7 +7293,7 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor
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)

View file

@ -910,7 +910,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
*/
extern (D) TemplateTupleParameter isVariadic()
{
size_t dim = parameters.length;
const dim = parameters.length;
if (dim == 0)
return null;
return (*parameters)[dim - 1].isTemplateTupleParameter();
@ -6129,14 +6129,13 @@ MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, Templ
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);
}

View file

@ -2796,7 +2796,7 @@ public:
{
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())
{

View file

@ -197,6 +197,16 @@ else
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.
@ -420,7 +430,10 @@ else
* 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
@ -433,7 +446,10 @@ extern (C++) void verrorReport(const ref Loc loc, const(char)* format, va_list a
* 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

View file

@ -2805,11 +2805,11 @@ extern (C++) final class FuncExp : Expression
{
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
@ -3573,10 +3573,9 @@ TypeFunction calledFunctionType(CallExp ce)
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

View file

@ -118,10 +118,9 @@ private bool isNeedThisScope(Scope* sc, Declaration d)
{
if (ad2 == ad)
return false;
else if (ad2.isNested())
if (ad2.isNested())
continue;
else
return true;
return true;
}
if (FuncDeclaration f = s.isFuncDeclaration())
{
@ -1521,7 +1520,7 @@ Expression resolvePropertiesOnly(Scope* sc, Expression e1)
}
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())
@ -1529,7 +1528,7 @@ Expression resolvePropertiesOnly(Scope* sc, Expression e1)
}
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();
@ -1539,7 +1538,7 @@ Expression resolvePropertiesOnly(Scope* sc, Expression e1)
}
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());
@ -6163,7 +6162,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
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;
}
@ -7262,7 +7261,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
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();
@ -17036,6 +17035,7 @@ bool checkDisabled(Declaration d, Loc loc, Scope* sc, bool isAliasedDeclaration
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());

View file

@ -159,16 +159,20 @@ nothrow:
* 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);
@ -206,11 +210,11 @@ nothrow:
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);
@ -225,6 +229,7 @@ nothrow:
n = FileName.combine(p, sd);
if (FileName.exists(n) == 1) {
whichPathFoundThis = pathIndex;
return n;
}
FileName.free(n.ptr);
@ -236,11 +241,15 @@ nothrow:
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);
@ -258,18 +267,20 @@ nothrow:
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);

View file

@ -1373,11 +1373,9 @@ extern (C++) final class CtorDeclaration : FuncDeclaration
{
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);
}

View file

@ -1103,7 +1103,7 @@ Ldone:
{
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);
}
}
@ -1536,7 +1536,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
version (none)
{
printf("resolveFuncCall('%s')\n", s.toChars());
printf("resolveFuncCall() %s)\n", s.toChars());
if (tthis)
printf("\tthis: %s\n", tthis.toChars());
if (fargs)
@ -1548,7 +1548,6 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
printf("\t%s: %s\n", arg.toChars(), arg.type.toChars());
}
}
printf("\tfnames: %s\n", fnames ? fnames.toChars() : "null");
}
if (tiargs && arrayObjectIsError(*tiargs))
@ -2270,6 +2269,9 @@ int getLevelAndCheck(FuncDeclaration fd, const ref Loc loc, Scope* sc, FuncDecla
/**********************************
* 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
*/
@ -2291,7 +2293,8 @@ bool canInferAttributes(FuncDeclaration fd, Scope* sc)
(!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())
@ -2994,7 +2997,7 @@ extern (D) bool checkNRVO(FuncDeclaration fd)
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.

View file

@ -151,6 +151,10 @@ extern(C++) struct Verbose
}
}
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
{
@ -223,7 +227,7 @@ 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
@ -291,7 +295,8 @@ extern (C++) struct Global
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");

View file

@ -155,6 +155,14 @@ struct Verbose
unsigned errorSupplementCount();
};
struct ImportPathInfo
{
const char* path;
ImportPathInfo() : path(NULL) { }
ImportPathInfo(const char* p) : path(p) { }
};
// Put command line switches in here
struct Param
{
@ -227,7 +235,7 @@ 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
@ -315,8 +323,9 @@ struct Global
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;

View file

@ -2881,9 +2881,9 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
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);

View file

@ -906,7 +906,7 @@ public:
arrayStart();
foreach (importPath; global.params.imppath[])
{
item(importPath.toDString);
item(importPath.path.toDString);
}
arrayEnd();

View file

@ -643,7 +643,7 @@ class Lexer
if (isidchar(c))
continue;
else if (c & 0x80)
if (c & 0x80)
{
const s = p;
const u = decodeUTF();

View file

@ -1294,7 +1294,7 @@ extern (C++) abstract class Type : ASTNode
{
if (isImmutable())
return MODFlags.immutable_;
else if (isWildConst())
if (isWildConst())
{
if (t.isWildConst())
return MODFlags.wild;

View file

@ -2146,11 +2146,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
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();

View file

@ -511,10 +511,9 @@ package PINLINE evalPragmaInline(Loc loc, Scope* sc, Expressions* args)
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;
}
/**
@ -566,11 +565,9 @@ private bool pragmaMsgSemantic(Loc loc, Scope* sc, Expressions* args)
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;
}

View file

@ -1333,7 +1333,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
// 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)

View file

@ -170,7 +170,7 @@ RootObject aliasParameterSemantic(Loc loc, Scope* sc, RootObject o, TemplatePara
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;
@ -183,14 +183,13 @@ RootObject aliasParameterSemantic(Loc loc, Scope* sc, RootObject o, TemplatePara
// 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);

View file

@ -726,8 +726,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
if (ClassDeclaration cd = agg.isClassDeclaration())
return cd.com ? True() : False();
else
return False();
return False();
}
if (e.ident == Id.identifier)
{

View file

@ -1050,7 +1050,7 @@ private extern(D) MATCH argumentMatchParameter (FuncDeclaration fd, TypeFunction
{
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
}
}
@ -7470,7 +7470,7 @@ bool isRecursiveAliasThis(ref Type att, Type t)
auto tb = t.toBasetype();
if (att && tb.equivalent(att))
return true;
else if (!att && tb.checkAliasThisRec())
if (!att && tb.checkAliasThisRec())
att = tb;
return false;
}

View file

@ -100,7 +100,6 @@ bool genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope* sc)
* 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`
*/

View file

@ -0,0 +1,14 @@
/* 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 {}
}

View file

@ -666,6 +666,8 @@ extern (C++) class C18890_2
Agg s;
}
void test18890()
{
version (CppMangle_Itanium)
{
static assert(C18890.__dtor.mangleof == "_ZN6C18890D1Ev");
@ -690,6 +692,7 @@ version (CppMangle_MSVC)
static assert(C18890_2.__xdtor.mangleof == "??_GC18890_2@@UEAAPEAXI@Z");
}
}
}
/**************************************/
// https://issues.dlang.org/show_bug.cgi?id=18891
@ -704,6 +707,8 @@ extern (C++) class C18891
Agg s;
}
void test18891()
{
version (CppMangle_Itanium)
{
static assert(C18891.__dtor.mangleof == "_ZN6C18891D1Ev");
@ -722,6 +727,7 @@ version (CppMangle_MSVC)
static assert(C18891.__xdtor.mangleof == "??_GC18891@@UEAAPEAXI@Z");
}
}
}
/**************************************/
// Test C++ operator mangling

View file

@ -817,4 +817,22 @@ void test13840() nothrow
{}
}
// 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;
}

View file

@ -1,19 +0,0 @@
/*
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 {}
}

View file

@ -296,7 +296,7 @@ fail_compilation/retscope2.d(1024): Error: assigning scope variable `p` to non-s
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
---
*/

View file

@ -51,8 +51,8 @@ void bar4()
/*
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

View file

@ -5,7 +5,7 @@ REQUIRED_ARGS: -preview=dip1000
/*
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
---
*/

View file

@ -2,12 +2,12 @@
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
---
*/
@ -57,9 +57,9 @@ void bar3()
/******************************
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
---
*/

View file

@ -194,6 +194,56 @@ void test8()
/********************************/
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();
@ -204,6 +254,7 @@ int main()
test6();
test7();
test8();
test9();
return 0;
}

View file

@ -1,4 +1,4 @@
c7902293d7df9d02546562cb09fc8439004a70d1
d6f693b46a1565172cac7a1438905141783a164f
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.

View file

@ -94,6 +94,23 @@ else version (DigitalMars)
/// 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))
{
// ...
}
}

View file

@ -1758,13 +1758,10 @@ pure @safe:
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 ) ) )
{

View file

@ -67,9 +67,9 @@ else version (Posix)
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;
}

View file

@ -30,6 +30,7 @@ else version (WatchOS)
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;
@ -317,6 +318,7 @@ version (linux)
SO_RCVLOWAT = 0x1004,
SO_RCVTIMEO = 0x1006,
SO_REUSEADDR = 0x0004,
SO_REUSEPORT = 0x0200,
SO_SNDBUF = 0x1001,
SO_SNDLOWAT = 0x1003,
SO_SNDTIMEO = 0x1005,
@ -351,6 +353,7 @@ version (linux)
SO_RCVLOWAT = 0x1004,
SO_RCVTIMEO = 0x1006,
SO_REUSEADDR = 0x0004,
SO_REUSEPORT = 0x0200,
SO_SNDBUF = 0x1001,
SO_SNDLOWAT = 0x1003,
SO_SNDTIMEO = 0x1005,
@ -385,6 +388,7 @@ version (linux)
SO_RCVLOWAT = 16,
SO_RCVTIMEO = 18,
SO_REUSEADDR = 2,
SO_REUSEPORT = 15,
SO_SNDBUF = 7,
SO_SNDLOWAT = 17,
SO_SNDTIMEO = 19,
@ -454,6 +458,7 @@ version (linux)
SO_RCVLOWAT = 18,
SO_RCVTIMEO = 20,
SO_REUSEADDR = 2,
SO_REUSEPORT = 15,
SO_SNDBUF = 7,
SO_SNDLOWAT = 19,
SO_SNDTIMEO = 21,
@ -488,6 +493,7 @@ version (linux)
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,
@ -522,6 +528,7 @@ version (linux)
SO_RCVLOWAT = 18,
SO_RCVTIMEO = 20,
SO_REUSEADDR = 2,
SO_REUSEPORT = 15,
SO_SNDBUF = 7,
SO_SNDLOWAT = 19,
SO_SNDTIMEO = 21,
@ -556,6 +563,7 @@ version (linux)
SO_RCVLOWAT = 18,
SO_RCVTIMEO = 20,
SO_REUSEADDR = 2,
SO_REUSEPORT = 15,
SO_SNDBUF = 7,
SO_SNDLOWAT = 19,
SO_SNDTIMEO = 21,
@ -1547,6 +1555,7 @@ else version (Solaris)
SO_RCVLOWAT = 0x1004,
SO_RCVTIMEO = 0x1006,
SO_REUSEADDR = 0x0004,
SO_REUSEPORT = 0x100e,
SO_SNDBUF = 0x1001,
SO_SNDLOWAT = 0x1003,
SO_SNDTIMEO = 0x1005,

View file

@ -1,4 +1,4 @@
03aeafd2095b563bb66b75342652d2dcea66c9e8
336bed6d8ffec74d117b755866c5bd22e3d610a1
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.

View file

@ -1349,7 +1349,8 @@ template memoize(alias fun)
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;
@ -1393,7 +1394,8 @@ template memoize(alias fun, uint maxSize)
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)
{

View file

@ -15,7 +15,7 @@
/**
* 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)

View file

@ -3348,7 +3348,7 @@ package(std) Rebindable2!T rebindable2(T)(T value)
this(ref inout S rhs) @safe inout
{
this.i = i;
this.i = rhs.i;
copied = true;
}
}

View file

@ -22,6 +22,12 @@ extern (C) void register_default_gcs()
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;
@ -81,21 +87,25 @@ nothrow @nogc:
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);
}