@@ -197,8 +197,8 @@ build_frontend_type (tree type)
length = size_binop (PLUS_EXPR, size_one_node,
convert (sizetype, length));
- dtype =
- dmd::addMod (dtype->sarrayOf (TREE_INT_CST_LOW (length)), mod);
+ dtype = dmd::sarrayOf (dtype, TREE_INT_CST_LOW (length));
+ dtype = dmd::addMod (dtype, mod);
builtin_converted_decls.safe_push (builtin_data (dtype, type));
return dtype;
}
@@ -214,7 +214,7 @@ build_frontend_type (tree type)
if (!dtype)
break;
- dtype = dmd::addMod (dtype->sarrayOf (nunits), mod);
+ dtype = dmd::addMod (dmd::sarrayOf (dtype, nunits), mod);
if (target.isVectorTypeSupported (dtype->size (), dtype->nextOf ()))
break;
@@ -1906,7 +1906,7 @@ build_assert_call (const Loc &loc, libcall_fn libcall, tree msg)
tree str = build_string (len, filename);
TREE_TYPE (str) = make_array_type (Type::tchar, len);
- file = d_array_value (build_ctype (Type::tchar->arrayOf ()),
+ file = d_array_value (build_ctype (dmd::arrayOf (Type::tchar)),
size_int (len), build_address (str));
}
else
@@ -957,7 +957,7 @@ d_array_convert (Expression *exp)
if (tb->ty == TY::Tsarray)
{
- Type *totype = tb->nextOf ()->arrayOf ();
+ Type *totype = dmd::arrayOf (tb->nextOf ());
return convert_expr (build_expr (exp), exp->type, totype);
}
@@ -986,7 +986,7 @@ d_array_convert (Type *etype, Expression *exp)
expr = compound_expr (modify_expr (var, expr), var);
}
- return d_array_value (build_ctype (exp->type->arrayOf ()),
+ return d_array_value (build_ctype (dmd::arrayOf (exp->type)),
size_int (1), build_address (expr));
}
else
@@ -2211,7 +2211,7 @@ get_vtable_decl (ClassDeclaration *decl)
tree ident = mangle_internal_decl (decl, "__vtbl", "Z");
/* Note: Using a static array type for the VAR_DECL, the DECL_INITIAL value
will have a different type. However the back-end seems to accept this. */
- tree type = build_ctype (Type::tvoidptr->sarrayOf (decl->vtbl.length));
+ tree type = build_ctype (dmd::sarrayOf (Type::tvoidptr, decl->vtbl.length));
Dsymbol *vtblsym = decl->vtblSymbol ();
vtblsym->csym = declare_extern_var (ident, type);
@@ -1,4 +1,4 @@
-ceff48bf7db05503117f54fdc0cefcb89b711136
+f8bae0455851a1dfc8113d69323415f6de549e39
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
@@ -1 +1 @@
-v2.107.1-rc.1
+v2.108.0-beta.1
@@ -36,7 +36,7 @@ import dmd.root.utf;
import dmd.sideeffect;
import dmd.target;
import dmd.tokens;
-import dmd.typesem : toDsymbol, equivalent;
+import dmd.typesem : toDsymbol, equivalent, sarrayOf;
private enum LOG = false;
@@ -2155,7 +2155,7 @@ final class CParser(AST) : Parser!AST
error("function identifier-list cannot end with `...`");
ft.parameterList.varargs = AST.VarArg.KRvariadic; // but C11 allows extra arguments
auto plLength = pl.length;
- if (symbols.length != plLength)
+ if (symbols && symbols.length != plLength)
error(token.loc, "%d identifiers does not match %d declarations", cast(int)plLength, cast(int)symbols.length);
/* Transfer the types and storage classes from symbols[] to pl[]
@@ -2176,6 +2176,12 @@ final class CParser(AST) : Parser!AST
if (p.type || !(p.storageClass & STC.parameter))
error("storage class and type are not allowed in identifier-list");
+ if (!symbols)
+ {
+ // Error already given in cparseDeclaration
+ p.type = AST.Type.terror;
+ continue;
+ }
foreach (s; (*symbols)[]) // yes, quadratic
{
auto ad = s.isAttribDeclaration();
@@ -475,6 +475,18 @@ bool equivalent(Type src, Type t)
return dmd.typesem.equivalent(src, t);
}
+Type sarrayOf(Type type, dinteger_t dim)
+{
+ import dmd.typesem;
+ return dmd.typesem.sarrayOf(type, dim);
+}
+
+Type arrayOf(Type type)
+{
+ import dmd.typesem;
+ return dmd.typesem.arrayOf(type);
+}
+
Type constOf(Type type)
{
import dmd.typesem;
@@ -535,6 +547,30 @@ Type sharedWildConstOf(Type type)
return dmd.typesem.sharedWildConstOf(type);
}
+Type substWildTo(Type type, uint mod)
+{
+ import dmd.typesem;
+ return dmd.typesem.substWildTo(type, mod);
+}
+
+Type unqualify(Type type, uint m)
+{
+ import dmd.typesem;
+ return dmd.typesem.unqualify(type, m);
+}
+
+Type toHeadMutable(const(Type) type)
+{
+ import dmd.typesem;
+ return dmd.typesem.toHeadMutable(type);
+}
+
+Type aliasthisOf(Type type)
+{
+ import dmd.typesem;
+ return dmd.typesem.aliasthisOf(type);
+}
+
Type castMod(Type type, MOD mod)
{
import dmd.typesem;
@@ -20,7 +20,6 @@ import dmd.astenums;
import dmd.attrib;
import dmd.gluelayer;
import dmd.declaration;
-import dmd.dscope;
import dmd.dsymbol;
import dmd.expression;
import dmd.id;
@@ -50,7 +50,7 @@ import dmd.rootobject;
import dmd.root.utf;
import dmd.statement;
import dmd.tokens;
-import dmd.typesem : mutableOf, equivalent, pointerTo;
+import dmd.typesem : mutableOf, equivalent, pointerTo, sarrayOf, arrayOf;
import dmd.utils : arrayCastBigEndian;
import dmd.visitor;
@@ -3787,7 +3787,7 @@ public:
if (v is v2 || !v.isOverlappedWith(v2))
continue;
auto e = (*sle.elements)[i];
- if (e.op != EXP.void_)
+ if (e !is null && e.op != EXP.void_)
(*sle.elements)[i] = voidInitLiteral(e.type, v).copy();
}
}
@@ -1394,6 +1394,7 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod)
{
enum SourceEncoding { utf16, utf32}
enum Endian { little, big}
+ immutable loc = mod.getLoc();
/*
* Convert a buffer from UTF32 to UTF8
@@ -1413,7 +1414,7 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod)
if (buf.length & 3)
{
- .error(mod.loc, "%s `%s` odd length of UTF-32 char source %llu",
+ .error(loc, "%s `%s` odd length of UTF-32 char source %llu",
mod.kind, mod.toPrettyChars, cast(ulong) buf.length);
return null;
}
@@ -1430,7 +1431,7 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod)
{
if (u > 0x10FFFF)
{
- .error(mod.loc, "%s `%s` UTF-32 value %08x greater than 0x10FFFF", mod.kind, mod.toPrettyChars, u);
+ .error(loc, "%s `%s` UTF-32 value %08x greater than 0x10FFFF", mod.kind, mod.toPrettyChars, u);
return null;
}
dbuf.writeUTF8(u);
@@ -1460,7 +1461,7 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod)
if (buf.length & 1)
{
- .error(mod.loc, "%s `%s` odd length of UTF-16 char source %llu", mod.kind, mod.toPrettyChars, cast(ulong) buf.length);
+ .error(loc, "%s `%s` odd length of UTF-16 char source %llu", mod.kind, mod.toPrettyChars, cast(ulong) buf.length);
return null;
}
@@ -1480,13 +1481,13 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod)
i++;
if (i >= eBuf.length)
{
- .error(mod.loc, "%s `%s` surrogate UTF-16 high value %04x at end of file", mod.kind, mod.toPrettyChars, u);
+ .error(loc, "%s `%s` surrogate UTF-16 high value %04x at end of file", mod.kind, mod.toPrettyChars, u);
return null;
}
const u2 = readNext(&eBuf[i]);
if (u2 < 0xDC00 || 0xE000 <= u2)
{
- .error(mod.loc, "%s `%s` surrogate UTF-16 low value %04x out of range", mod.kind, mod.toPrettyChars, u2);
+ .error(loc, "%s `%s` surrogate UTF-16 low value %04x out of range", mod.kind, mod.toPrettyChars, u2);
return null;
}
u = (u - 0xD7C0) << 10;
@@ -1494,12 +1495,12 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod)
}
else if (u >= 0xDC00 && u <= 0xDFFF)
{
- .error(mod.loc, "%s `%s` unpaired surrogate UTF-16 value %04x", mod.kind, mod.toPrettyChars, u);
+ .error(loc, "%s `%s` unpaired surrogate UTF-16 value %04x", mod.kind, mod.toPrettyChars, u);
return null;
}
else if (u == 0xFFFE || u == 0xFFFF)
{
- .error(mod.loc, "%s `%s` illegal UTF-16 value %04x", mod.kind, mod.toPrettyChars, u);
+ .error(loc, "%s `%s` illegal UTF-16 value %04x", mod.kind, mod.toPrettyChars, u);
return null;
}
dbuf.writeUTF8(u);
@@ -1558,7 +1559,6 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod)
// It's UTF-8
if (buf[0] >= 0x80)
{
- auto loc = mod.getLoc();
.error(loc, "%s `%s` source file must start with BOM or ASCII character, not \\x%02X", mod.kind, mod.toPrettyChars, buf[0]);
return null;
}
@@ -12357,8 +12357,16 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return result;
}
- void handleCatArgument(Expressions *arguments, Expression e)
+ void handleCatArgument(Expressions *arguments, Expression e, Type catType, bool isRightArg)
{
+ auto tb = e.type.toBasetype();
+
+ if ((isRightArg && e.parens) || (!isRightArg && !tb.equals(catType)))
+ {
+ arguments.push(e);
+ return;
+ }
+
if (auto ce = e.isCatExp())
{
Expression lowering = ce.lowering;
@@ -12388,8 +12396,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
arguments.push(new StringExp(exp.loc, funcname.toDString()));
}
- handleCatArgument(arguments, exp.e1);
- handleCatArgument(arguments, exp.e2);
+ handleCatArgument(arguments, exp.e1, exp.type.toBasetype(), false);
+ handleCatArgument(arguments, exp.e2, exp.type.toBasetype(), true);
Expression id = new IdentifierExp(exp.loc, Id.empty);
id = new DotIdExp(exp.loc, id, Id.object);
@@ -34,12 +34,10 @@ import dmd.dmodule;
import dmd.dscope;
import dmd.dstruct;
import dmd.dsymbol;
-import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.errors;
import dmd.escape;
import dmd.expression;
-import dmd.funcsem;
import dmd.globals;
import dmd.hdrgen;
import dmd.id;
@@ -57,7 +55,6 @@ import dmd.semantic2;
import dmd.semantic3;
import dmd.statement_rewrite_walker;
import dmd.statement;
-import dmd.statementsem;
import dmd.tokens;
import dmd.typesem;
import dmd.visitor;
@@ -115,90 +112,6 @@ enum BUILTIN : ubyte
toPrecReal
}
-/* Tweak all return statements and dtor call for nrvo_var, for correct NRVO.
- */
-extern (C++) final class NrvoWalker : StatementRewriteWalker
-{
- alias visit = typeof(super).visit;
-public:
- FuncDeclaration fd;
- Scope* sc;
-
- override void visit(ReturnStatement s)
- {
- // See if all returns are instead to be replaced with a goto returnLabel;
- if (fd.returnLabel)
- {
- /* Rewrite:
- * return exp;
- * as:
- * vresult = exp; goto Lresult;
- */
- auto gs = new GotoStatement(s.loc, Id.returnLabel);
- gs.label = fd.returnLabel;
-
- Statement s1 = gs;
- if (s.exp)
- s1 = new CompoundStatement(s.loc, new ExpStatement(s.loc, s.exp), gs);
-
- replaceCurrent(s1);
- }
- }
-
- override void visit(TryFinallyStatement s)
- {
- DtorExpStatement des;
- if (fd.isNRVO() && s.finalbody && (des = s.finalbody.isDtorExpStatement()) !is null &&
- fd.nrvo_var == des.var)
- {
- if (!(global.params.useExceptions && ClassDeclaration.throwable))
- {
- /* Don't need to call destructor at all, since it is nrvo
- */
- replaceCurrent(s._body);
- s._body.accept(this);
- return;
- }
-
- /* Normally local variable dtors are called regardless exceptions.
- * But for nrvo_var, its dtor should be called only when exception is thrown.
- *
- * Rewrite:
- * try { s.body; } finally { nrvo_var.edtor; }
- * // equivalent with:
- * // s.body; scope(exit) nrvo_var.edtor;
- * as:
- * try { s.body; } catch(Throwable __o) { nrvo_var.edtor; throw __o; }
- * // equivalent with:
- * // s.body; scope(failure) nrvo_var.edtor;
- */
- Statement sexception = new DtorExpStatement(Loc.initial, fd.nrvo_var.edtor, fd.nrvo_var);
- Identifier id = Identifier.generateId("__o");
-
- Statement handler = new PeelStatement(sexception);
- if (sexception.blockExit(fd, null) & BE.fallthru)
- {
- auto ts = new ThrowStatement(Loc.initial, new IdentifierExp(Loc.initial, id));
- ts.internalThrow = true;
- handler = new CompoundStatement(Loc.initial, handler, ts);
- }
-
- auto catches = new Catches();
- auto ctch = new Catch(Loc.initial, getThrowable(), id, handler);
- ctch.internalCatch = true;
- ctch.catchSemantic(sc); // Run semantic to resolve identifier '__o'
- catches.push(ctch);
-
- Statement s2 = new TryCatchStatement(Loc.initial, s._body, catches);
- fd.hasNoEH = false;
- replaceCurrent(s2);
- s2.accept(this);
- }
- else
- StatementRewriteWalker.visit(s);
- }
-}
-
private struct FUNCFLAG
{
bool purityInprocess; /// working on determining purity
@@ -2021,44 +1934,6 @@ extern (C++) class FuncDeclaration : Declaration
return f && f.nextOf() && f.nextOf().toBasetype().ty != Tvoid;
}
- /****************************************************
- * Declare result variable lazily.
- */
- extern (D) final void buildResultVar(Scope* sc, Type tret)
- {
- if (!vresult)
- {
- Loc loc = fensure ? fensure.loc : this.loc;
-
- /* If inferRetType is true, tret may not be a correct return type yet.
- * So, in here it may be a temporary type for vresult, and after
- * fbody.dsymbolSemantic() running, vresult.type might be modified.
- */
- vresult = new VarDeclaration(loc, tret, Id.result, null);
- vresult.storage_class |= STC.nodtor | STC.temp;
- if (!isVirtual())
- vresult.storage_class |= STC.const_;
- vresult.storage_class |= STC.result;
-
- // set before the semantic() for checkNestedReference()
- vresult.parent = this;
- }
-
- if (sc && vresult.semanticRun == PASS.initial)
- {
- TypeFunction tf = type.toTypeFunction();
- if (tf.isref)
- vresult.storage_class |= STC.ref_;
- vresult.type = tret;
-
- vresult.dsymbolSemantic(sc);
-
- if (!sc.insert(vresult))
- .error(loc, "%s `%s` out result %s is already defined", kind, toPrettyChars, vresult.toChars());
- assert(vresult.parent == this);
- }
- }
-
/****************************************************
* Merge into this function the 'in' contracts of all it overrides.
* 'in's are OR'd together, i.e. only one of them needs to pass.
@@ -2680,57 +2555,6 @@ extern (C++) class FuncDeclaration : Declaration
}
}
-/********************************************************
- * Generate Expression to call the invariant.
- * Input:
- * ad aggregate with the invariant
- * vthis variable with 'this'
- * Returns:
- * void expression that calls the invariant
- */
-Expression addInvariant(AggregateDeclaration ad, VarDeclaration vthis)
-{
- Expression e = null;
- // Call invariant directly only if it exists
- FuncDeclaration inv = ad.inv;
- ClassDeclaration cd = ad.isClassDeclaration();
-
- while (!inv && cd)
- {
- cd = cd.baseClass;
- if (!cd)
- break;
- inv = cd.inv;
- }
- if (inv)
- {
- version (all)
- {
- // Workaround for https://issues.dlang.org/show_bug.cgi?id=13394
- // For the correct mangling,
- // run attribute inference on inv if needed.
- functionSemantic(inv);
- }
-
- //e = new DsymbolExp(Loc.initial, inv);
- //e = new CallExp(Loc.initial, e);
- //e = e.semantic(sc2);
-
- /* https://issues.dlang.org/show_bug.cgi?id=13113
- * Currently virtual invariant calls completely
- * bypass attribute enforcement.
- * Change the behavior of pre-invariant call by following it.
- */
- e = new ThisExp(Loc.initial);
- e.type = ad.type.addMod(vthis.type.mod);
- e = new DotVarExp(Loc.initial, e, inv, false);
- e.type = inv.type;
- e = new CallExp(Loc.initial, e);
- e.type = Type.tvoid;
- }
- return e;
-}
-
/***************************************************
* Visit each overloaded function/template in turn, and call dg(s) on it.
* Exit when no more, or dg(s) returns nonzero.
@@ -65,6 +65,90 @@ import dmd.tokens;
import dmd.typesem;
import dmd.visitor;
+/* Tweak all return statements and dtor call for nrvo_var, for correct NRVO.
+ */
+extern (C++) final class NrvoWalker : StatementRewriteWalker
+{
+ alias visit = typeof(super).visit;
+public:
+ FuncDeclaration fd;
+ Scope* sc;
+
+ override void visit(ReturnStatement s)
+ {
+ // See if all returns are instead to be replaced with a goto returnLabel;
+ if (fd.returnLabel)
+ {
+ /* Rewrite:
+ * return exp;
+ * as:
+ * vresult = exp; goto Lresult;
+ */
+ auto gs = new GotoStatement(s.loc, Id.returnLabel);
+ gs.label = fd.returnLabel;
+
+ Statement s1 = gs;
+ if (s.exp)
+ s1 = new CompoundStatement(s.loc, new ExpStatement(s.loc, s.exp), gs);
+
+ replaceCurrent(s1);
+ }
+ }
+
+ override void visit(TryFinallyStatement s)
+ {
+ DtorExpStatement des;
+ if (fd.isNRVO() && s.finalbody && (des = s.finalbody.isDtorExpStatement()) !is null &&
+ fd.nrvo_var == des.var)
+ {
+ if (!(global.params.useExceptions && ClassDeclaration.throwable))
+ {
+ /* Don't need to call destructor at all, since it is nrvo
+ */
+ replaceCurrent(s._body);
+ s._body.accept(this);
+ return;
+ }
+
+ /* Normally local variable dtors are called regardless exceptions.
+ * But for nrvo_var, its dtor should be called only when exception is thrown.
+ *
+ * Rewrite:
+ * try { s.body; } finally { nrvo_var.edtor; }
+ * // equivalent with:
+ * // s.body; scope(exit) nrvo_var.edtor;
+ * as:
+ * try { s.body; } catch(Throwable __o) { nrvo_var.edtor; throw __o; }
+ * // equivalent with:
+ * // s.body; scope(failure) nrvo_var.edtor;
+ */
+ Statement sexception = new DtorExpStatement(Loc.initial, fd.nrvo_var.edtor, fd.nrvo_var);
+ Identifier id = Identifier.generateId("__o");
+
+ Statement handler = new PeelStatement(sexception);
+ if (sexception.blockExit(fd, null) & BE.fallthru)
+ {
+ auto ts = new ThrowStatement(Loc.initial, new IdentifierExp(Loc.initial, id));
+ ts.internalThrow = true;
+ handler = new CompoundStatement(Loc.initial, handler, ts);
+ }
+
+ auto catches = new Catches();
+ auto ctch = new Catch(Loc.initial, getThrowable(), id, handler);
+ ctch.internalCatch = true;
+ ctch.catchSemantic(sc); // Run semantic to resolve identifier '__o'
+ catches.push(ctch);
+
+ Statement s2 = new TryCatchStatement(Loc.initial, s._body, catches);
+ fd.hasNoEH = false;
+ replaceCurrent(s2);
+ s2.accept(this);
+ }
+ else
+ StatementRewriteWalker.visit(s);
+ }
+}
+
/**********************************
* Main semantic routine for functions.
*/
@@ -1755,3 +1839,87 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration))
if (constraintsTip)
.tip(constraintsTip);
}
+
+/********************************************************
+ * Generate Expression to call the invariant.
+ * Input:
+ * ad aggregate with the invariant
+ * vthis variable with 'this'
+ * Returns:
+ * void expression that calls the invariant
+ */
+Expression addInvariant(AggregateDeclaration ad, VarDeclaration vthis)
+{
+ Expression e = null;
+ // Call invariant directly only if it exists
+ FuncDeclaration inv = ad.inv;
+ ClassDeclaration cd = ad.isClassDeclaration();
+
+ while (!inv && cd)
+ {
+ cd = cd.baseClass;
+ if (!cd)
+ break;
+ inv = cd.inv;
+ }
+ if (inv)
+ {
+ version (all)
+ {
+ // Workaround for https://issues.dlang.org/show_bug.cgi?id=13394
+ // For the correct mangling,
+ // run attribute inference on inv if needed.
+ functionSemantic(inv);
+ }
+
+ //e = new DsymbolExp(Loc.initial, inv);
+ //e = new CallExp(Loc.initial, e);
+ //e = e.semantic(sc2);
+
+ /* https://issues.dlang.org/show_bug.cgi?id=13113
+ * Currently virtual invariant calls completely
+ * bypass attribute enforcement.
+ * Change the behavior of pre-invariant call by following it.
+ */
+ e = new ThisExp(Loc.initial);
+ e.type = ad.type.addMod(vthis.type.mod);
+ e = new DotVarExp(Loc.initial, e, inv, false);
+ e.type = inv.type;
+ e = new CallExp(Loc.initial, e);
+ e.type = Type.tvoid;
+ }
+ return e;
+}
+
+/****************************************************
+ * Declare result variable lazily.
+ */
+void buildResultVar(FuncDeclaration fd, Scope* sc, Type tret)
+{
+ if (!fd.vresult)
+ {
+ Loc loc = fd.fensure ? fd.fensure.loc : fd.loc;
+ /* If inferRetType is true, tret may not be a correct return type yet.
+ * So, in here it may be a temporary type for vresult, and after
+ * fbody.dsymbolSemantic() running, vresult.type might be modified.
+ */
+ fd.vresult = new VarDeclaration(loc, tret, Id.result, null);
+ fd.vresult.storage_class |= STC.nodtor | STC.temp;
+ if (!fd.isVirtual())
+ fd.vresult.storage_class |= STC.const_;
+ fd.vresult.storage_class |= STC.result;
+ // set before the semantic() for checkNestedReference()
+ fd.vresult.parent = fd;
+ }
+ if (sc && fd.vresult.semanticRun == PASS.initial)
+ {
+ TypeFunction tf = fd.type.toTypeFunction();
+ if (tf.isref)
+ fd.vresult.storage_class |= STC.ref_;
+ fd.vresult.type = tret;
+ fd.vresult.dsymbolSemantic(sc);
+ if (!sc.insert(fd.vresult))
+ .error(fd.loc, "%s `%s` out result %s is already defined", fd.kind, fd.toPrettyChars, fd.vresult.toChars());
+ assert(fd.vresult.parent == fd);
+ }
+}
@@ -115,15 +115,7 @@ nothrow:
//printf("setting %s\n", name);
filenames.push(name);
fileIndex = cast(uint)filenames.length;
- if (!fileIndex)
- {
- import dmd.globals : global;
- import dmd.errors : error, fatal;
-
- global.gag = 0; // ensure error message gets printed
- error(Loc.initial, "internal compiler error: file name index overflow!");
- fatal();
- }
+ assert(fileIndex, "internal compiler error: file name index overflow");
}
else
fileIndex = 0;
@@ -1185,110 +1185,12 @@ extern (C++) abstract class Type : ASTNode
return t;
}
- final Type arrayOf()
- {
- if (ty == Terror)
- return this;
- if (!arrayof)
- {
- Type t = new TypeDArray(this);
- arrayof = t.merge();
- }
- return arrayof;
- }
-
- // Make corresponding static array type without semantic
- final Type sarrayOf(dinteger_t dim)
- {
- assert(deco);
- Type t = new TypeSArray(this, new IntegerExp(Loc.initial, dim, Type.tsize_t));
- // according to TypeSArray::semantic()
- t = t.addMod(mod);
- t = t.merge();
- return t;
- }
-
final bool hasDeprecatedAliasThis()
{
auto ad = isAggregate(this);
return ad && ad.aliasthis && (ad.aliasthis.isDeprecated || ad.aliasthis.sym.isDeprecated);
}
- final Type aliasthisOf()
- {
- auto ad = isAggregate(this);
- if (!ad || !ad.aliasthis)
- return null;
-
- auto s = ad.aliasthis.sym;
- if (s.isAliasDeclaration())
- s = s.toAlias();
-
- if (s.isTupleDeclaration())
- return null;
-
- if (auto vd = s.isVarDeclaration())
- {
- auto t = vd.type;
- if (vd.needThis())
- t = t.addMod(this.mod);
- return t;
- }
- Dsymbol callable = s.isFuncDeclaration();
- callable = callable ? callable : s.isTemplateDeclaration();
- if (callable)
- {
- auto fd = resolveFuncCall(Loc.initial, null, callable, null, this, ArgumentList(), FuncResolveFlag.quiet);
- if (!fd || fd.errors || !functionSemantic(fd))
- return Type.terror;
-
- auto t = fd.type.nextOf();
- if (!t) // https://issues.dlang.org/show_bug.cgi?id=14185
- return Type.terror;
- t = t.substWildTo(mod == 0 ? MODFlags.mutable : mod);
- return t;
- }
- if (auto d = s.isDeclaration())
- {
- assert(d.type);
- return d.type;
- }
- if (auto ed = s.isEnumDeclaration())
- {
- return ed.type;
- }
-
- //printf("%s\n", s.kind());
- return null;
- }
-
- /**
- * Check whether this type has endless `alias this` recursion.
- * Returns:
- * `true` if this type has an `alias this` that can be implicitly
- * converted back to this type itself.
- */
- extern (D) final bool checkAliasThisRec()
- {
- Type tb = toBasetype();
- AliasThisRec* pflag;
- if (tb.ty == Tstruct)
- pflag = &(cast(TypeStruct)tb).att;
- else if (tb.ty == Tclass)
- pflag = &(cast(TypeClass)tb).att;
- else
- return false;
-
- AliasThisRec flag = cast(AliasThisRec)(*pflag & AliasThisRec.typeMask);
- if (flag == AliasThisRec.fwdref)
- {
- Type att = aliasthisOf();
- flag = att && att.implicitConvTo(this) ? AliasThisRec.yes : AliasThisRec.no;
- }
- *pflag = cast(AliasThisRec)(flag | (*pflag & ~AliasThisRec.typeMask));
- return flag == AliasThisRec.yes;
- }
-
Type makeConst()
{
//printf("Type::makeConst() %p, %s\n", this, toChars());
@@ -1451,129 +1353,6 @@ extern (C++) abstract class Type : ASTNode
return 0;
}
- Type substWildTo(uint mod)
- {
- //printf("+Type::substWildTo this = %s, mod = x%x\n", toChars(), mod);
- Type t;
-
- if (Type tn = nextOf())
- {
- // substitution has no effect on function pointer type.
- if (ty == Tpointer && tn.ty == Tfunction)
- {
- t = this;
- goto L1;
- }
-
- t = tn.substWildTo(mod);
- if (t == tn)
- t = this;
- else
- {
- if (ty == Tpointer)
- t = t.pointerTo();
- else if (ty == Tarray)
- t = t.arrayOf();
- else if (ty == Tsarray)
- t = new TypeSArray(t, (cast(TypeSArray)this).dim.syntaxCopy());
- else if (ty == Taarray)
- {
- t = new TypeAArray(t, (cast(TypeAArray)this).index.syntaxCopy());
- }
- else if (ty == Tdelegate)
- {
- t = new TypeDelegate(t.isTypeFunction());
- }
- else
- assert(0);
-
- t = t.merge();
- }
- }
- else
- t = this;
-
- L1:
- if (isWild())
- {
- if (mod == MODFlags.immutable_)
- {
- t = t.immutableOf();
- }
- else if (mod == MODFlags.wildconst)
- {
- t = t.wildConstOf();
- }
- else if (mod == MODFlags.wild)
- {
- if (isWildConst())
- t = t.wildConstOf();
- else
- t = t.wildOf();
- }
- else if (mod == MODFlags.const_)
- {
- t = t.constOf();
- }
- else
- {
- if (isWildConst())
- t = t.constOf();
- else
- t = t.mutableOf();
- }
- }
- if (isConst())
- t = t.addMod(MODFlags.const_);
- if (isShared())
- t = t.addMod(MODFlags.shared_);
-
- //printf("-Type::substWildTo t = %s\n", t.toChars());
- return t;
- }
-
- final Type unqualify(uint m)
- {
- Type t = this.mutableOf().unSharedOf();
-
- Type tn = ty == Tenum ? null : nextOf();
- if (tn && tn.ty != Tfunction)
- {
- Type utn = tn.unqualify(m);
- if (utn != tn)
- {
- if (ty == Tpointer)
- t = utn.pointerTo();
- else if (ty == Tarray)
- t = utn.arrayOf();
- else if (ty == Tsarray)
- t = new TypeSArray(utn, (cast(TypeSArray)this).dim);
- else if (ty == Taarray)
- {
- t = new TypeAArray(utn, (cast(TypeAArray)this).index);
- }
- else
- assert(0);
-
- t = t.merge();
- }
- }
- t = t.addMod(mod & ~m);
- return t;
- }
-
- /**************************
- * Return type with the top level of it being mutable.
- */
- inout(Type) toHeadMutable() inout
- {
- if (!mod)
- return this;
- Type unqualThis = cast(Type) this;
- // `mutableOf` needs a mutable `this` only for caching
- return cast(inout(Type)) unqualThis.mutableOf();
- }
-
inout(ClassDeclaration) isClassHandle() inout
{
return null;
@@ -3396,55 +3175,6 @@ extern (C++) final class TypeFunction : TypeNext
return linkage == LINK.d && parameterList.varargs == VarArg.variadic;
}
- override Type substWildTo(uint)
- {
- if (!iswild && !(mod & MODFlags.wild))
- return this;
-
- // Substitude inout qualifier of function type to mutable or immutable
- // would break type system. Instead substitude inout to the most weak
- // qualifer - const.
- uint m = MODFlags.const_;
-
- assert(next);
- Type tret = next.substWildTo(m);
- Parameters* params = parameterList.parameters;
- if (mod & MODFlags.wild)
- params = parameterList.parameters.copy();
- for (size_t i = 0; i < params.length; i++)
- {
- Parameter p = (*params)[i];
- Type t = p.type.substWildTo(m);
- if (t == p.type)
- continue;
- if (params == parameterList.parameters)
- params = parameterList.parameters.copy();
- (*params)[i] = new Parameter(p.loc, p.storageClass, t, null, null, null);
- }
- if (next == tret && params == parameterList.parameters)
- return this;
-
- // Similar to TypeFunction::syntaxCopy;
- auto t = new TypeFunction(ParameterList(params, parameterList.varargs), tret, linkage);
- t.mod = ((mod & MODFlags.wild) ? (mod & ~MODFlags.wild) | MODFlags.const_ : mod);
- t.isnothrow = isnothrow;
- t.isnogc = isnogc;
- t.purity = purity;
- t.isproperty = isproperty;
- t.isref = isref;
- t.isreturn = isreturn;
- t.isreturnscope = isreturnscope;
- t.isScopeQual = isScopeQual;
- t.isreturninferred = isreturninferred;
- t.isscopeinferred = isscopeinferred;
- t.isInOutParam = false;
- t.isInOutQual = false;
- t.trust = trust;
- t.fargs = fargs;
- t.isctor = isctor;
- return t.merge();
- }
-
extern(D) static const(char)* getMatchError(A...)(const(char)* format, A args)
{
if (global.gag && !global.params.v.showGaggedErrors)
@@ -4316,7 +4046,7 @@ extern (C++) final class TypeStruct : Type
MATCH m;
if (!(ty == to.ty && sym == (cast(TypeStruct)to).sym) && sym.aliasthis && !(att & AliasThisRec.tracing))
{
- if (auto ato = aliasthisOf())
+ if (auto ato = aliasthisOf(this))
{
att = cast(AliasThisRec)(att | AliasThisRec.tracing);
m = ato.implicitConvTo(to);
@@ -4353,7 +4083,7 @@ extern (C++) final class TypeStruct : Type
if (t.hasWild() && sym.aliasthis && !(att & AliasThisRec.tracing))
{
- if (auto ato = aliasthisOf())
+ if (auto ato = aliasthisOf(this))
{
att = cast(AliasThisRec)(att | AliasThisRec.tracing);
wm = ato.deduceWild(t, isRef);
@@ -4364,11 +4094,6 @@ extern (C++) final class TypeStruct : Type
return wm;
}
- override inout(Type) toHeadMutable() inout
- {
- return this;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -4595,7 +4320,7 @@ extern (C++) final class TypeClass : Type
MATCH m;
if (sym.aliasthis && !(att & AliasThisRec.tracing))
{
- if (auto ato = aliasthisOf())
+ if (auto ato = aliasthisOf(this))
{
att = cast(AliasThisRec)(att | AliasThisRec.tracing);
m = ato.implicitConvTo(to);
@@ -4644,7 +4369,7 @@ extern (C++) final class TypeClass : Type
if (t.hasWild() && sym.aliasthis && !(att & AliasThisRec.tracing))
{
- if (auto ato = aliasthisOf())
+ if (auto ato = aliasthisOf(this))
{
att = cast(AliasThisRec)(att | AliasThisRec.tracing);
wm = ato.deduceWild(t, isRef);
@@ -4655,11 +4380,6 @@ extern (C++) final class TypeClass : Type
return wm;
}
- override inout(Type) toHeadMutable() inout
- {
- return this;
- }
-
override bool isZeroInit(const ref Loc loc)
{
return true;
@@ -5852,36 +5572,3 @@ TypeIdentifier getException()
tid.addIdent(Id.Exception);
return tid;
}
-
-/**************************************
- * Check and set 'att' if 't' is a recursive 'alias this' type
- *
- * The goal is to prevent endless loops when there is a cycle in the alias this chain.
- * Since there is no multiple `alias this`, the chain either ends in a leaf,
- * or it loops back on itself as some point.
- *
- * Example: S0 -> (S1 -> S2 -> S3 -> S1)
- *
- * `S0` is not a recursive alias this, so this returns `false`, and a rewrite to `S1` can be tried.
- * `S1` is a recursive alias this type, but since `att` is initialized to `null`,
- * this still returns `false`, but `att1` is set to `S1`.
- * A rewrite to `S2` and `S3` can be tried, but when we want to try a rewrite to `S1` again,
- * we notice `att == t`, so we're back at the start of the loop, and this returns `true`.
- *
- * Params:
- * att = type reference used to detect recursion. Should be initialized to `null`.
- * t = type of 'alias this' rewrite to attempt
- *
- * Returns:
- * `false` if the rewrite is safe, `true` if it would loop back around
- */
-bool isRecursiveAliasThis(ref Type att, Type t)
-{
- //printf("+isRecursiveAliasThis(att = %s, t = %s)\n", att ? att.toChars() : "null", t.toChars());
- auto tb = t.toBasetype();
- if (att && tb.equivalent(att))
- return true;
- else if (!att && tb.checkAliasThisRec())
- att = tb;
- return false;
-}
@@ -257,7 +257,6 @@ public:
Type *arrayOf();
Type *sarrayOf(dinteger_t dim);
bool hasDeprecatedAliasThis();
- Type *aliasthisOf();
virtual Type *makeConst();
virtual Type *makeImmutable();
virtual Type *makeShared();
@@ -271,11 +270,7 @@ public:
virtual MATCH implicitConvTo(Type *to);
virtual MATCH constConv(Type *to);
virtual unsigned char deduceWild(Type *t, bool isRef);
- virtual Type *substWildTo(unsigned mod);
- Type *unqualify(unsigned m);
-
- virtual Type *toHeadMutable();
virtual ClassDeclaration *isClassHandle();
virtual structalign_t alignment();
virtual Expression *defaultInitLiteral(const Loc &loc);
@@ -580,7 +575,6 @@ public:
bool hasLazyParameters();
bool isDstyleVariadic() const;
- Type *substWildTo(unsigned mod) override;
MATCH constConv(Type *to) override;
bool isnothrow() const;
@@ -751,7 +745,6 @@ public:
MATCH implicitConvTo(Type *to) override;
MATCH constConv(Type *to) override;
unsigned char deduceWild(Type *t, bool isRef) override;
- Type *toHeadMutable() override;
void accept(Visitor *v) override { v->visit(this); }
};
@@ -804,7 +797,6 @@ public:
MATCH implicitConvTo(Type *to) override;
MATCH constConv(Type *to) override;
unsigned char deduceWild(Type *t, bool isRef) override;
- Type *toHeadMutable() override;
bool isZeroInit(const Loc &loc) override;
bool isscope() override;
bool isBoolean() override;
@@ -892,6 +884,8 @@ namespace dmd
Type *pointerTo(Type *type);
Type *referenceTo(Type *type);
Type *merge2(Type *type);
+ Type *sarrayOf(Type *type, dinteger_t dim);
+ Type *arrayOf(Type *type);
Type *constOf(Type *type);
Type *immutableOf(Type *type);
Type *mutableOf(Type *type);
@@ -902,7 +896,11 @@ namespace dmd
Type *wildConstOf(Type *type);
Type *sharedWildOf(Type *type);
Type *sharedWildConstOf(Type *type);
+ Type *unqualify(Type *type, unsigned m);
+ Type *toHeadMutable(Type *type);
+ Type *aliasthisOf(Type *type);
Type *castMod(Type *type, MOD mod);
Type *addMod(Type *type, MOD mod);
Type *addStorageClass(Type *type, StorageClass stc);
+ Type *substWildTo(Type *type, unsigned mod);
}
@@ -1349,7 +1349,7 @@ Expression optimize(Expression e, int result, bool keepLvalue = false)
if (b++ == global.recursionLimit)
{
error(e.loc, "infinite loop while optimizing expression");
- fatal();
+ return ErrorExp.get();
}
auto ex = ret;
@@ -26,7 +26,7 @@ import dmd.identifier;
import dmd.mtype;
import dmd.target;
import dmd.tokens;
-import dmd.typesem : hasPointers;
+import dmd.typesem : hasPointers, arrayOf;
import dmd.func : setUnsafe, setUnsafePreview;
/*************************************************************
@@ -1687,7 +1687,7 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
if (!ClassDeclaration.object)
{
.error(Loc.initial, "missing or corrupt object.d");
- fatal();
+ return error();
}
__gshared FuncDeclaration feq = null;
@@ -6229,6 +6229,29 @@ Type referenceTo(Type type)
return type.rto;
}
+// Make corresponding static array type without semantic
+Type sarrayOf(Type type, dinteger_t dim)
+{
+ assert(type.deco);
+ Type t = new TypeSArray(type, new IntegerExp(Loc.initial, dim, Type.tsize_t));
+ // according to TypeSArray.semantic()
+ t = t.addMod(type.mod);
+ t = t.merge();
+ return t;
+}
+
+Type arrayOf(Type type)
+{
+ if (type.ty == Terror)
+ return type;
+ if (!type.arrayof)
+ {
+ Type t = new TypeDArray(type);
+ type.arrayof = t.merge();
+ }
+ return type.arrayof;
+}
+
/********************************
* Convert to 'const'.
*/
@@ -6478,6 +6501,104 @@ Type sharedWildConstOf(Type type)
return t;
}
+Type unqualify(Type type, uint m)
+{
+ Type t = type.mutableOf().unSharedOf();
+
+ Type tn = type.ty == Tenum ? null : type.nextOf();
+ if (tn && tn.ty != Tfunction)
+ {
+ Type utn = tn.unqualify(m);
+ if (utn != tn)
+ {
+ if (type.ty == Tpointer)
+ t = utn.pointerTo();
+ else if (type.ty == Tarray)
+ t = utn.arrayOf();
+ else if (type.ty == Tsarray)
+ t = new TypeSArray(utn, (cast(TypeSArray)type).dim);
+ else if (type.ty == Taarray)
+ {
+ t = new TypeAArray(utn, (cast(TypeAArray)type).index);
+ }
+ else
+ assert(0);
+
+ t = t.merge();
+ }
+ }
+ t = t.addMod(type.mod & ~m);
+ return t;
+}
+
+/**************************
+ * Return type with the top level of it being mutable.
+ *
+ * Params:
+ * t = type for which the top level mutable version is being returned
+ *
+ * Returns:
+ * type version with mutable top level
+ */
+Type toHeadMutable(const Type t)
+{
+ Type unqualType = cast(Type) t;
+ if (t.isTypeStruct() || t.isTypeClass())
+ return unqualType;
+
+ if (!t.mod)
+ return unqualType;
+ return unqualType.mutableOf();
+}
+
+Type aliasthisOf(Type type)
+{
+ auto ad = isAggregate(type);
+ if (!ad || !ad.aliasthis)
+ return null;
+
+ auto s = ad.aliasthis.sym;
+ if (s.isAliasDeclaration())
+ s = s.toAlias();
+
+ if (s.isTupleDeclaration())
+ return null;
+
+ if (auto vd = s.isVarDeclaration())
+ {
+ auto t = vd.type;
+ if (vd.needThis())
+ t = t.addMod(type.mod);
+ return t;
+ }
+ Dsymbol callable = s.isFuncDeclaration();
+ callable = callable ? callable : s.isTemplateDeclaration();
+ if (callable)
+ {
+ auto fd = resolveFuncCall(Loc.initial, null, callable, null, type, ArgumentList(), FuncResolveFlag.quiet);
+ if (!fd || fd.errors || !functionSemantic(fd))
+ return Type.terror;
+
+ auto t = fd.type.nextOf();
+ if (!t) // https://issues.dlang.org/show_bug.cgi?id=14185
+ return Type.terror;
+ t = t.substWildTo(type.mod == 0 ? MODFlags.mutable : type.mod);
+ return t;
+ }
+ if (auto d = s.isDeclaration())
+ {
+ assert(d.type);
+ return d.type;
+ }
+ if (auto ed = s.isEnumDeclaration())
+ {
+ return ed.type;
+ }
+
+ //printf("%s\n", s.kind());
+ return null;
+}
+
/************************************
* Apply MODxxxx bits to existing type.
*/
@@ -6528,6 +6649,137 @@ Type castMod(Type type, MOD mod)
return t;
}
+Type substWildTo(Type type, uint mod)
+{
+ auto tf = type.isTypeFunction();
+ if (!tf)
+ {
+ //printf("+Type.substWildTo this = %s, mod = x%x\n", toChars(), mod);
+ Type t;
+
+ if (Type tn = type.nextOf())
+ {
+ // substitution has no effect on function pointer type.
+ if (type.ty == Tpointer && tn.ty == Tfunction)
+ {
+ t = type;
+ goto L1;
+ }
+
+ t = tn.substWildTo(mod);
+ if (t == tn)
+ t = type;
+ else
+ {
+ if (type.ty == Tpointer)
+ t = t.pointerTo();
+ else if (type.ty == Tarray)
+ t = t.arrayOf();
+ else if (type.ty == Tsarray)
+ t = new TypeSArray(t, (cast(TypeSArray)type).dim.syntaxCopy());
+ else if (type.ty == Taarray)
+ {
+ t = new TypeAArray(t, (cast(TypeAArray)type).index.syntaxCopy());
+ }
+ else if (type.ty == Tdelegate)
+ {
+ t = new TypeDelegate(t.isTypeFunction());
+ }
+ else
+ assert(0);
+
+ t = t.merge();
+ }
+ }
+ else
+ t = type;
+
+ L1:
+ if (type.isWild())
+ {
+ if (mod == MODFlags.immutable_)
+ {
+ t = t.immutableOf();
+ }
+ else if (mod == MODFlags.wildconst)
+ {
+ t = t.wildConstOf();
+ }
+ else if (mod == MODFlags.wild)
+ {
+ if (type.isWildConst())
+ t = t.wildConstOf();
+ else
+ t = t.wildOf();
+ }
+ else if (mod == MODFlags.const_)
+ {
+ t = t.constOf();
+ }
+ else
+ {
+ if (type.isWildConst())
+ t = t.constOf();
+ else
+ t = t.mutableOf();
+ }
+ }
+ if (type.isConst())
+ t = t.addMod(MODFlags.const_);
+ if (type.isShared())
+ t = t.addMod(MODFlags.shared_);
+
+ //printf("-Type.substWildTo t = %s\n", t.toChars());
+ return t;
+ }
+
+ if (!tf.iswild && !(tf.mod & MODFlags.wild))
+ return tf;
+
+ // Substitude inout qualifier of function type to mutable or immutable
+ // would break type system. Instead substitude inout to the most weak
+ // qualifer - const.
+ uint m = MODFlags.const_;
+
+ assert(tf.next);
+ Type tret = tf.next.substWildTo(m);
+ Parameters* params = tf.parameterList.parameters;
+ if (tf.mod & MODFlags.wild)
+ params = tf.parameterList.parameters.copy();
+ for (size_t i = 0; i < params.length; i++)
+ {
+ Parameter p = (*params)[i];
+ Type t = p.type.substWildTo(m);
+ if (t == p.type)
+ continue;
+ if (params == tf.parameterList.parameters)
+ params = tf.parameterList.parameters.copy();
+ (*params)[i] = new Parameter(p.loc, p.storageClass, t, null, null, null);
+ }
+ if (tf.next == tret && params == tf.parameterList.parameters)
+ return tf;
+
+ // Similar to TypeFunction.syntaxCopy;
+ auto t = new TypeFunction(ParameterList(params, tf.parameterList.varargs), tret, tf.linkage);
+ t.mod = ((tf.mod & MODFlags.wild) ? (tf.mod & ~MODFlags.wild) | MODFlags.const_ : tf.mod);
+ t.isnothrow = tf.isnothrow;
+ t.isnogc = tf.isnogc;
+ t.purity = tf.purity;
+ t.isproperty = tf.isproperty;
+ t.isref = tf.isref;
+ t.isreturn = tf.isreturn;
+ t.isreturnscope = tf.isreturnscope;
+ t.isScopeQual = tf.isScopeQual;
+ t.isreturninferred = tf.isreturninferred;
+ t.isscopeinferred = tf.isscopeinferred;
+ t.isInOutParam = false;
+ t.isInOutQual = false;
+ t.trust = tf.trust;
+ t.fargs = tf.fargs;
+ t.isctor = tf.isctor;
+ return t.merge();
+}
+
/************************************
* Add MODxxxx bits to existing type.
* We're adding, not replacing, so adding const to
@@ -6633,6 +6885,69 @@ Type addMod(Type type, MOD mod)
return t;
}
+/**
+ * Check whether this type has endless `alias this` recursion.
+ *
+ * Params:
+ * t = type to check whether it has a recursive alias this
+ * Returns:
+ * `true` if `t` has an `alias this` that can be implicitly
+ * converted back to `t` itself.
+ */
+private bool checkAliasThisRec(Type t)
+{
+ Type tb = t.toBasetype();
+ AliasThisRec* pflag;
+ if (tb.ty == Tstruct)
+ pflag = &(cast(TypeStruct)tb).att;
+ else if (tb.ty == Tclass)
+ pflag = &(cast(TypeClass)tb).att;
+ else
+ return false;
+
+ AliasThisRec flag = cast(AliasThisRec)(*pflag & AliasThisRec.typeMask);
+ if (flag == AliasThisRec.fwdref)
+ {
+ Type att = aliasthisOf(t);
+ flag = att && att.implicitConvTo(t) ? AliasThisRec.yes : AliasThisRec.no;
+ }
+ *pflag = cast(AliasThisRec)(flag | (*pflag & ~AliasThisRec.typeMask));
+ return flag == AliasThisRec.yes;
+}
+
+/**************************************
+ * Check and set 'att' if 't' is a recursive 'alias this' type
+ *
+ * The goal is to prevent endless loops when there is a cycle in the alias this chain.
+ * Since there is no multiple `alias this`, the chain either ends in a leaf,
+ * or it loops back on itself as some point.
+ *
+ * Example: S0 -> (S1 -> S2 -> S3 -> S1)
+ *
+ * `S0` is not a recursive alias this, so this returns `false`, and a rewrite to `S1` can be tried.
+ * `S1` is a recursive alias this type, but since `att` is initialized to `null`,
+ * this still returns `false`, but `att1` is set to `S1`.
+ * A rewrite to `S2` and `S3` can be tried, but when we want to try a rewrite to `S1` again,
+ * we notice `att == t`, so we're back at the start of the loop, and this returns `true`.
+ *
+ * Params:
+ * att = type reference used to detect recursion. Should be initialized to `null`.
+ * t = type of 'alias this' rewrite to attempt
+ *
+ * Returns:
+ * `false` if the rewrite is safe, `true` if it would loop back around
+ */
+bool isRecursiveAliasThis(ref Type att, Type t)
+{
+ //printf("+isRecursiveAliasThis(att = %s, t = %s)\n", att ? att.toChars() : "null", t.toChars());
+ auto tb = t.toBasetype();
+ if (att && tb.equivalent(att))
+ return true;
+ else if (!att && tb.checkAliasThisRec())
+ att = tb;
+ return false;
+}
+
/******************************* Private *****************************************/
private:
@@ -464,7 +464,7 @@ public:
else
{
/* Use _adEq2() to compare each element. */
- Type *t1array = t1elem->arrayOf ();
+ Type *t1array = dmd::arrayOf (t1elem);
tree result = build_libcall (LIBCALL_ADEQ2, e->type, 3,
d_array_convert (e->e1),
d_array_convert (e->e2),
@@ -2172,7 +2172,8 @@ public:
{
/* Generate a slice for non-zero initialized aggregates,
otherwise create an empty array. */
- gcc_assert (e->type == dmd::constOf (Type::tvoid->arrayOf ()));
+ gcc_assert (e->type->isConst ()
+ && e->type->nextOf ()->ty == TY::Tvoid);
tree type = build_ctype (e->type);
tree length = size_int (sd->dsym->structsize);
@@ -2571,7 +2572,7 @@ public:
/* Implicitly convert void[n] to ubyte[n]. */
if (tb->ty == TY::Tsarray && tb->nextOf ()->toBasetype ()->ty == TY::Tvoid)
- tb = Type::tuns8->sarrayOf (tb->isTypeSArray ()->dim->toUInteger ());
+ tb = dmd::sarrayOf (Type::tuns8, tb->isTypeSArray ()->dim->toUInteger ());
gcc_assert (tb->ty == TY::Tarray || tb->ty == TY::Tsarray
|| tb->ty == TY::Tpointer);
@@ -2685,7 +2686,7 @@ public:
/* Allocate space on the memory managed heap. */
tree mem = build_libcall (LIBCALL_ARRAYLITERALTX,
dmd::pointerTo (etype), 2,
- build_typeinfo (e, etype->arrayOf ()),
+ build_typeinfo (e, dmd::arrayOf (etype)),
size_int (e->elements->length));
mem = d_save_expr (mem);
@@ -2732,20 +2733,20 @@ public:
/* Build an expression that assigns all expressions in KEYS
to a constructor. */
- tree akeys = build_array_from_exprs (ta->index->sarrayOf (e->keys->length),
- e->keys, this->constp_);
+ Type *tkarray = dmd::sarrayOf (ta->index, e->keys->length);
+ tree akeys = build_array_from_exprs (tkarray, e->keys, this->constp_);
tree init = stabilize_expr (&akeys);
/* Do the same with all expressions in VALUES. */
- tree avals = build_array_from_exprs (ta->next->sarrayOf (e->values->length),
- e->values, this->constp_);
+ Type *tvarray = dmd::sarrayOf (ta->next, e->values->length);
+ tree avals = build_array_from_exprs (tvarray, e->values, this->constp_);
init = compound_expr (init, stabilize_expr (&avals));
/* Generate: _d_assocarrayliteralTX (ti, keys, vals); */
- tree keys = d_array_value (build_ctype (ta->index->arrayOf ()),
+ tree keys = d_array_value (build_ctype (dmd::arrayOf (ta->index)),
size_int (e->keys->length),
build_address (akeys));
- tree vals = d_array_value (build_ctype (ta->next->arrayOf ()),
+ tree vals = d_array_value (build_ctype (dmd::arrayOf (ta->next)),
size_int (e->values->length),
build_address (avals));
@@ -274,7 +274,7 @@ build_shuffle_mask_type (tree type)
gcc_assert (t != NULL);
unsigned HOST_WIDE_INT nunits = TYPE_VECTOR_SUBPARTS (type).to_constant ();
- return build_ctype (TypeVector::create (t->sarrayOf (nunits)));
+ return build_ctype (TypeVector::create (dmd::sarrayOf (t, nunits)));
}
/* Checks if call to intrinsic FUNCTION in CALLEXP matches the internal
@@ -414,7 +414,7 @@ maybe_warn_intrinsic_mismatch (tree function, tree callexp)
break;
Type *inner = build_frontend_type (TREE_TYPE (vec0));
- Type *vector = TypeVector::create (inner->sarrayOf (nunits));
+ Type *vector = TypeVector::create (dmd::sarrayOf (inner, nunits));
return warn_mismatched_argument (callexp, 1,
build_ctype (vector), true);
}
@@ -479,7 +479,7 @@ maybe_warn_intrinsic_mismatch (tree function, tree callexp)
break;
Type *inner = build_frontend_type (TREE_TYPE (arg));
- Type *vector = TypeVector::create (inner->sarrayOf (nunits));
+ Type *vector = TypeVector::create (dmd::sarrayOf (inner, nunits));
return warn_mismatched_argument (callexp, 0,
build_ctype (vector), true);
}
@@ -158,31 +158,31 @@ get_libcall_type (d_libcall_type type)
break;
case LCT_ARRAY_VOID:
- libcall_types[type] = Type::tvoid->arrayOf ();
+ libcall_types[type] = dmd::arrayOf (Type::tvoid);
break;
case LCT_ARRAY_SIZE_T:
- libcall_types[type] = Type::tsize_t->arrayOf ();
+ libcall_types[type] = dmd::arrayOf (Type::tsize_t);
break;
case LCT_ARRAY_BYTE:
- libcall_types[type] = Type::tint8->arrayOf ();
+ libcall_types[type] = dmd::arrayOf (Type::tint8);
break;
case LCT_ARRAY_STRING:
- libcall_types[type] = Type::tstring->arrayOf ();
+ libcall_types[type] = dmd::arrayOf (Type::tstring);
break;
case LCT_ARRAY_WSTRING:
- libcall_types[type] = Type::twstring->arrayOf ();
+ libcall_types[type] = dmd::arrayOf (Type::twstring);
break;
case LCT_ARRAY_DSTRING:
- libcall_types[type] = Type::tdstring->arrayOf ();
+ libcall_types[type] = dmd::arrayOf (Type::tdstring);
break;
case LCT_ARRAYARRAY_BYTE:
- libcall_types[type] = Type::tint8->arrayOf ()->arrayOf ();
+ libcall_types[type] = dmd::arrayOf (Type::tint8);
break;
case LCT_POINTER_ASSOCARRAY:
@@ -190,15 +190,15 @@ get_libcall_type (d_libcall_type type)
break;
case LCT_POINTER_VOIDPTR:
- libcall_types[type] = Type::tvoidptr->arrayOf ();
+ libcall_types[type] = dmd::arrayOf (Type::tvoidptr);
break;
case LCT_ARRAYPTR_VOID:
- libcall_types[type] = dmd::pointerTo (Type::tvoid->arrayOf ());
+ libcall_types[type] = dmd::pointerTo (dmd::arrayOf (Type::tvoid));
break;
case LCT_ARRAYPTR_BYTE:
- libcall_types[type] = dmd::pointerTo (Type::tint8->arrayOf ());
+ libcall_types[type] = dmd::pointerTo (dmd::arrayOf (Type::tint8));
break;
case LCT_IMMUTABLE_CHARPTR:
@@ -415,7 +415,7 @@ class TypeInfoVisitor : public Visitor
tree decl = this->internal_reference (value);
TREE_READONLY (decl) = 1;
- value = d_array_value (build_ctype (Type::tchar->arrayOf ()),
+ value = d_array_value (build_ctype (dmd::arrayOf (Type::tchar)),
size_int (len), build_address (decl));
this->layout_field (value);
}
@@ -1137,7 +1137,7 @@ public:
this->layout_base (Type::typeinfotypelist);
/* TypeInfo[] elements; */
- Type *satype = Type::tvoidptr->sarrayOf (ti->arguments->length);
+ Type *satype = dmd::sarrayOf (Type::tvoidptr, ti->arguments->length);
vec<constructor_elt, va_gc> *elms = NULL;
for (size_t i = 0; i < ti->arguments->length; i++)
{
new file mode 100644
@@ -0,0 +1,9 @@
+// REQUIRED_ARGS: -main
+// LINK:
+template rt_options()
+{
+ __gshared string[] rt_options = [];
+ string[] rt_options_tls = [];
+}
+
+alias _ = rt_options!();
new file mode 100644
@@ -0,0 +1,17 @@
+static struct S
+{
+ union
+ {
+ int i;
+ long l;
+ }
+}
+
+int f()
+{
+ S* r = new S();
+ r.i = 5;
+ return r.i;
+}
+
+enum X = f();
new file mode 100644
@@ -0,0 +1,6 @@
+// PERMUTE_ARGS:
+// https://issues.dlang.org/show_bug.cgi?id=24401
+int main()
+{
+ return (() @trusted => 0)();
+}
new file mode 100644
@@ -0,0 +1,15 @@
+// https://issues.dlang.org/show_bug.cgi?id=24371
+
+void main()
+{
+ assert("b" ~ "c" == "bc");
+ assert(["a"] ~ "b" == ["a", "b"]);
+ assert(["a"] ~ ("b" ~ "c") == ["a", "bc"]);
+
+ auto strArr = ["a"];
+ assert(strArr ~ ("b" ~ "c") == ["a", "bc"]);
+ auto str = "c";
+ assert(["a"] ~ ("b" ~ str) == ["a", "bc"]);
+
+ assert(strArr ~ ("b" ~ str) == ["a", "bc"]);
+}
@@ -1,12 +1,5 @@
// EXTRA_CPP_SOURCES: cpp7925.cpp
-/*
-Exclude -O/-inline due to a codegen bug on OSX:
-https://issues.dlang.org/show_bug.cgi?id=22556
-
-PERMUTE_ARGS(osx): -release -g
-*/
-
import core.vararg;
extern(C++) class C1
@@ -1,4 +1,4 @@
-ceff48bf7db05503117f54fdc0cefcb89b711136
+f8bae0455851a1dfc8113d69323415f6de549e39
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
@@ -19,6 +19,19 @@ void __switch_errorT()(string file = __FILE__, size_t line = __LINE__) @trusted
assert(0, "No appropriate switch clause found");
}
+/*
+ * Make sure template __switch_errorT is always instantiated when building
+ * druntime. This works around https://issues.dlang.org/show_bug.cgi?id=20802.
+ * When druntime and phobos are compiled with -release, the instance for
+ * __switch_errorT is not needed. An application compiled with -release
+ * could need the instance for __switch_errorT, but the compiler would
+ * not generate code for it, because it assumes, that it was already
+ * generated for druntime. Always including the instance in a compiled
+ * druntime allows to use an application without -release with druntime
+ * with -release.
+ */
+private alias dummy__switch_errorT = __switch_errorT!();
+
/**
* Thrown on a range error.
*/
@@ -39,11 +39,18 @@ struct ifaddrs
union
{
/// Broadcast address of the interface
- sockaddr* ifu_broadaddr;
+ sockaddr* ifa_broadaddr;
+
/// Point-to-point destination addresss
- sockaddr* if_dstaddr;
+ sockaddr* ifa_dstaddr;
}
+ deprecated("druntime declared this incorrectly before. The correct name is ifa_broadaddr.")
+ alias ifu_broadaddr = ifa_broadaddr;
+
+ deprecated("druntime declared this incorrectly before. The correct name is ifa_dstaddr.")
+ alias if_dstaddr = ifa_dstaddr;
+
/// Address specific data
void* ifa_data;
}
@@ -183,7 +183,8 @@ else version (FreeBSD)
struct fd_set
{
- __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] __fds_bits;
+ __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] fds_bits;
+ deprecated("druntime incorrectly named fds_bits __fds_bits") alias __fds_bits = fds_bits;
}
extern (D) __fd_mask __fdset_mask(uint n) pure
@@ -193,17 +194,17 @@ else version (FreeBSD)
extern (D) void FD_CLR( int n, fd_set* p ) pure
{
- p.__fds_bits[n / _NFDBITS] &= ~__fdset_mask(n);
+ p.fds_bits[n / _NFDBITS] &= ~__fdset_mask(n);
}
extern (D) bool FD_ISSET( int n, const(fd_set)* p ) pure
{
- return (p.__fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0;
+ return (p.fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0;
}
extern (D) void FD_SET( int n, fd_set* p ) pure
{
- p.__fds_bits[n / _NFDBITS] |= __fdset_mask(n);
+ p.fds_bits[n / _NFDBITS] |= __fdset_mask(n);
}
extern (D) void FD_ZERO( fd_set* p ) pure
@@ -214,7 +215,7 @@ else version (FreeBSD)
_p = p;
_n = (FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS;
while (_n > 0)
- _p.__fds_bits[--_n] = 0;
+ _p.fds_bits[--_n] = 0;
}
int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
@@ -232,7 +233,8 @@ else version (NetBSD)
struct fd_set
{
- __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] __fds_bits;
+ __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] fds_bits;
+ deprecated("druntime incorrectly named fds_bits __fds_bits") alias __fds_bits = fds_bits;
}
extern (D) __fd_mask __fdset_mask(uint n) pure
@@ -242,17 +244,17 @@ else version (NetBSD)
extern (D) void FD_CLR( int n, fd_set* p ) pure
{
- p.__fds_bits[n / _NFDBITS] &= ~__fdset_mask(n);
+ p.fds_bits[n / _NFDBITS] &= ~__fdset_mask(n);
}
extern (D) bool FD_ISSET( int n, const(fd_set)* p ) pure
{
- return (p.__fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0;
+ return (p.fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0;
}
extern (D) void FD_SET( int n, fd_set* p ) pure
{
- p.__fds_bits[n / _NFDBITS] |= __fdset_mask(n);
+ p.fds_bits[n / _NFDBITS] |= __fdset_mask(n);
}
extern (D) void FD_ZERO( fd_set* p ) pure
@@ -263,7 +265,7 @@ else version (NetBSD)
_p = p;
_n = (FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS;
while (_n > 0)
- _p.__fds_bits[--_n] = 0;
+ _p.fds_bits[--_n] = 0;
}
int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
@@ -281,7 +283,8 @@ else version (OpenBSD)
struct fd_set
{
- __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] __fds_bits;
+ __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] fds_bits;
+ deprecated("druntime incorrectly named fds_bits __fds_bits") alias __fds_bits = fds_bits;
}
extern (D) __fd_mask __fdset_mask(uint n) pure
@@ -291,17 +294,17 @@ else version (OpenBSD)
extern (D) void FD_CLR(int n, fd_set* p) pure
{
- p.__fds_bits[n / _NFDBITS] &= ~__fdset_mask(n);
+ p.fds_bits[n / _NFDBITS] &= ~__fdset_mask(n);
}
extern (D) bool FD_ISSET(int n, const(fd_set)* p) pure
{
- return (p.__fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0;
+ return (p.fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0;
}
extern (D) void FD_SET(int n, fd_set* p) pure
{
- p.__fds_bits[n / _NFDBITS] |= __fdset_mask(n);
+ p.fds_bits[n / _NFDBITS] |= __fdset_mask(n);
}
extern (D) void FD_ZERO(fd_set* p) pure
@@ -310,7 +313,7 @@ else version (OpenBSD)
size_t _n = (FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS;
while (_n > 0)
- _p.__fds_bits[--_n] = 0;
+ _p.fds_bits[--_n] = 0;
}
int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
@@ -328,7 +331,8 @@ else version (DragonFlyBSD)
struct fd_set
{
- __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] __fds_bits;
+ __fd_mask[(FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS] fds_bits;
+ deprecated("druntime incorrectly named fds_bits __fds_bits") alias __fds_bits = fds_bits;
}
extern (D) __fd_mask __fdset_mask(uint n) pure
@@ -338,17 +342,17 @@ else version (DragonFlyBSD)
extern (D) void FD_CLR( int n, fd_set* p ) pure
{
- p.__fds_bits[n / _NFDBITS] &= ~__fdset_mask(n);
+ p.fds_bits[n / _NFDBITS] &= ~__fdset_mask(n);
}
extern (D) bool FD_ISSET( int n, const(fd_set)* p ) pure
{
- return (p.__fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0;
+ return (p.fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0;
}
extern (D) void FD_SET( int n, fd_set* p ) pure
{
- p.__fds_bits[n / _NFDBITS] |= __fdset_mask(n);
+ p.fds_bits[n / _NFDBITS] |= __fdset_mask(n);
}
extern (D) void FD_ZERO( fd_set* p ) pure
@@ -359,7 +363,7 @@ else version (DragonFlyBSD)
_p = p;
_n = (FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS;
while (_n > 0)
- _p.__fds_bits[--_n] = 0;
+ _p.fds_bits[--_n] = 0;
}
int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
@@ -1,4 +1,4 @@
-dcbfbd43ac321e81af60afd795bd0f3c3f47cfa0
+a2ade9dec49e70c6acd447df52321988a4c2fb9f
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.
@@ -9,9 +9,9 @@ module etc.c.zlib;
import core.stdc.config;
/* zlib.h -- interface of the 'zlib' general purpose compression library
- version 1.2.12, March 11th, 2022
+ version 1.3.1, January 22nd, 2024
- Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
+ Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -43,8 +43,8 @@ nothrow:
extern (C):
// Those are extern(D) as they should be mangled
-extern(D) immutable string ZLIB_VERSION = "1.2.12";
-extern(D) immutable ZLIB_VERNUM = 0x12c0;
+extern(D) immutable string ZLIB_VERSION = "1.3.1";
+extern(D) immutable ZLIB_VERNUM = 0x1310;
/*
The 'zlib' compression library provides in-memory compression and
@@ -250,7 +250,7 @@ int deflateInit(z_streamp strm, int level)
Initializes the internal stream state for compression. The fields
zalloc, zfree and opaque must be initialized before by the caller. If
zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
- allocation functions.
+ allocation functions. total_in, total_out, adler, and msg are initialized.
The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
1 gives best speed, 9 gives best compression, 0 gives no compression at all
@@ -296,7 +296,7 @@ int deflate(z_streamp strm, int flush);
== 0), or after each call of deflate(). If deflate returns Z_OK and with
zero avail_out, it must be called again after making room in the output
buffer because there might be more output pending. See deflatePending(),
- which can be used if desired to determine whether or not there is more ouput
+ which can be used if desired to determine whether or not there is more output
in that case.
Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
@@ -340,8 +340,8 @@ int deflate(z_streamp strm, int flush);
with the same value of the flush parameter and more output space (updated
avail_out), until the flush is complete (deflate returns with non-zero
avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
- avail_out is greater than six to avoid repeated flush markers due to
- avail_out == 0 on return.
+ avail_out is greater than six when the flush marker begins, in order to avoid
+ repeated flush markers upon calling deflate() again when avail_out == 0.
If the parameter flush is set to Z_FINISH, pending input is processed,
pending output is flushed and deflate returns with Z_STREAM_END if there was
@@ -405,7 +405,8 @@ int inflateInit(z_streamp strm)
read or consumed. The allocation of a sliding window will be deferred to
the first call of inflate (if the decompression does not complete on the
first call). If zalloc and zfree are set to Z_NULL, inflateInit updates
- them to use default allocation functions.
+ them to use default allocation functions. total_in, total_out, adler, and
+ msg are initialized.
inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
@@ -680,7 +681,7 @@ int deflateGetDictionary(z_streamp strm, ubyte *dictionary, uint dictLength);
to dictionary. dictionary must have enough space, where 32768 bytes is
always enough. If deflateGetDictionary() is called with dictionary equal to
Z_NULL, then only the dictionary length is returned, and nothing is copied.
- Similary, if dictLength is Z_NULL, then it is not set.
+ Similarly, if dictLength is Z_NULL, then it is not set.
deflateGetDictionary() may return a length less than the window size, even
when more than the window size in input has been provided. It may return up
@@ -715,7 +716,7 @@ int deflateReset(z_streamp strm);
This function is equivalent to deflateEnd followed by deflateInit, but
does not free and reallocate the internal compression state. The stream
will leave the compression level and any other attributes that may have been
- set unchanged.
+ set unchanged. total_in, total_out, adler, and msg are initialized.
deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent (such as zalloc or state being Z_NULL).
@@ -746,7 +747,7 @@ int deflateParams(z_streamp strm, int level, int strategy);
Then no more input data should be provided before the deflateParams() call.
If this is done, the old level and strategy will be applied to the data
compressed before deflateParams(), and the new level and strategy will be
- applied to the the data compressed after deflateParams().
+ applied to the data compressed after deflateParams().
deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream
state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if
@@ -829,8 +830,9 @@ int deflateSetHeader(z_streamp strm, gz_headerp head);
gzip file" and give up.
If deflateSetHeader is not used, the default gzip header has text false,
- the time set to zero, and os set to 255, with no extra, name, or comment
- fields. The gzip header is returned to the default state by deflateReset().
+ the time set to zero, and os set to the current operating system, with no
+ extra, name, or comment fields. The gzip header is returned to the default
+ state by deflateReset().
deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent.
@@ -920,7 +922,7 @@ int inflateGetDictionary(z_streamp strm, ubyte* dictionary, uint* dictLength);
to dictionary. dictionary must have enough space, where 32768 bytes is
always enough. If inflateGetDictionary() is called with dictionary equal to
Z_NULL, then only the dictionary length is returned, and nothing is copied.
- Similary, if dictLength is Z_NULL, then it is not set.
+ Similarly, if dictLength is Z_NULL, then it is not set.
inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
stream state is inconsistent.
@@ -939,10 +941,10 @@ int inflateSync(z_streamp strm);
inflateSync returns Z_OK if a possible full flush point has been found,
Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
- In the success case, the application may save the current current value of
- total_in which indicates where valid compressed data was found. In the
- error case, the application may repeatedly call inflateSync, providing more
- input each time, until success or end of the input data.
+ In the success case, the application may save the current value of total_in
+ which indicates where valid compressed data was found. In the error case,
+ the application may repeatedly call inflateSync, providing more input each
+ time, until success or end of the input data.
*/
int inflateCopy(z_streamp dest, z_streamp source);
@@ -1446,12 +1448,12 @@ z_size_t gzfread(void* buf, z_size_t size, z_size_t nitems, gzFile file);
In the event that the end of file is reached and only a partial item is
available at the end, i.e. the remaining uncompressed data length is not a
- multiple of size, then the final partial item is nevetheless read into buf
+ multiple of size, then the final partial item is nevertheless read into buf
and the end-of-file flag is set. The length of the partial item read is not
provided, but could be inferred from the result of gztell(). This behavior
is the same as the behavior of fread() implementations in common libraries,
but it prevents the direct use of gzfread() to read a concurrently written
- file, reseting and retrying on end-of-file, when size is not 1.
+ file, resetting and retrying on end-of-file, when size is not 1.
*/
int gzwrite(gzFile file, void* buf, uint len);
@@ -1747,19 +1749,18 @@ uint crc32_z(uint crc, const(ubyte)* buf, z_size_t len);
*/
uint crc32_combine(uint crc1, uint crc2, z_off_t len2);
-
/*
Combine two CRC-32 check values into one. For two sequences of bytes,
seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
- len2.
+ len2. len2 must be non-negative.
*/
uint crc32_combine_gen(z_off_t len2);
/*
Return the operator corresponding to length len2, to be used with
- crc32_combine_op().
+ crc32_combine_op(). len2 must be non-negative.
*/
uint crc32_combine_op(uint crc1, uint crc2, uint op);