diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2025-03-12 17:19:49 +0100 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2025-03-15 16:33:00 +0100 |
commit | e8c9f4ab8f0c8ad8da5f7fb0f1a4956507fe64f5 (patch) | |
tree | 46099e73f24300a919394d9f1972fdf5941f672d | |
parent | 254549d2bb9bb3c2719dec597427919c59514fc3 (diff) | |
download | gcc-e8c9f4ab8f0c8ad8da5f7fb0f1a4956507fe64f5.zip gcc-e8c9f4ab8f0c8ad8da5f7fb0f1a4956507fe64f5.tar.gz gcc-e8c9f4ab8f0c8ad8da5f7fb0f1a4956507fe64f5.tar.bz2 |
d: Merge upstream dmd, druntime b7e3b3b617
D front-end changes:
- `delete' is no longer a keyword.
- Initializing a field with itself has been deprecated.
D runtime changes:
- Add Windows BCrypt bindings under `core.sys.windows.bcrypt'.
gcc/d/ChangeLog:
* dmd/MERGE: Merge upstream b7e3b3b617.
libphobos/ChangeLog:
* libdruntime/MERGE: Merge upstream b7e3b3b617.
* libdruntime/Makefile.am (DRUNTIME_DSOURCES_WINDOWS): Add
core/sys/windows/bcrypt.d.
* libdruntime/Makefile.in: Regenerate.
* libdruntime/gcc/sections/elf.d (sizeofTLS): Give function the same
mangling as gcc.sections.sizeofTLS.
* libdruntime/gcc/sections/package.d: Import core.internal.traits.
(pinLoadedLibraries): Mangle as function from rt.sections_elf_shared.
(unpinLoadedLibraries): Likewise.
(inheritLoadedLibraries): Likewise.
(cleanupLoadedLibraries): Likewise.
(sizeOfTLS): Add forward declaration.
87 files changed, 2878 insertions, 2562 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index 4172630..a91f40b 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -d1157134103a209d36d6ee9c1df1d61d5929ec6d +b7e3b3b61711bf6c6cad27c7b5b73df0e570c215 The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d index d7658c6..93b6dc3 100644 --- a/gcc/d/dmd/clone.d +++ b/gcc/d/dmd/clone.d @@ -101,7 +101,7 @@ StorageClass mergeFuncAttrs(StorageClass s1, const FuncDeclaration f) pure @safe */ FuncDeclaration hasIdentityOpAssign(AggregateDeclaration ad, Scope* sc) { - Dsymbol assign = search_function(ad, Id.assign); + Dsymbol assign = search_function(ad, Id.opAssign); if (!assign) return null; @@ -303,7 +303,7 @@ FuncDeclaration buildOpAssign(StructDeclaration sd, Scope* sc) auto fparams = new Parameters(); fparams.push(new Parameter(loc, STC.nodtor, sd.type, Id.p, null, null)); auto tf = new TypeFunction(ParameterList(fparams), sd.handleType(), LINK.d, stc | STC.ref_); - auto fop = new FuncDeclaration(declLoc, Loc.initial, Id.assign, stc, tf); + auto fop = new FuncDeclaration(declLoc, Loc.initial, Id.opAssign, stc, tf); fop.storage_class |= STC.inference; fop.isGenerated = true; Expression e; @@ -482,7 +482,7 @@ bool needOpEquals(StructDeclaration sd) private FuncDeclaration hasIdentityOpEquals(AggregateDeclaration ad, Scope* sc) { FuncDeclaration f; - Dsymbol eq = search_function(ad, Id.eq); + Dsymbol eq = search_function(ad, Id.opEquals); if (!eq) return null; @@ -537,7 +537,7 @@ private FuncDeclaration hasIdentityOpEquals(AggregateDeclaration ad, Scope* sc) * opEquals is changed to be never implicitly generated. * Now, struct objects comparison s1 == s2 is translated to: * s1.tupleof == s2.tupleof - * to calculate structural equality. See EqualExp.op_overload. + * to calculate structural equality. See `opOverloadEquals`. */ FuncDeclaration buildOpEquals(StructDeclaration sd, Scope* sc) { @@ -564,7 +564,7 @@ FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc) return null; // bitwise comparison would work //printf("StructDeclaration::buildXopEquals() %s\n", sd.toChars()); - if (Dsymbol eq = search_function(sd, Id.eq)) + if (Dsymbol eq = search_function(sd, Id.opEquals)) { if (FuncDeclaration fd = eq.isFuncDeclaration()) { @@ -639,7 +639,7 @@ FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc) FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc) { //printf("StructDeclaration::buildXopCmp() %s\n", toChars()); - if (Dsymbol cmp = search_function(sd, Id.cmp)) + if (Dsymbol cmp = search_function(sd, Id.opCmp)) { if (FuncDeclaration fd = cmp.isFuncDeclaration()) { @@ -667,7 +667,7 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc) * Consider 'alias this', but except opDispatch. */ Expression e = new DsymbolExp(sd.loc, sd); - e = new DotIdExp(sd.loc, e, Id.cmp); + e = new DotIdExp(sd.loc, e, Id.opCmp); Scope* sc2 = sc.push(); e = e.trySemantic(sc2); sc2.pop(); @@ -688,7 +688,7 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc) default: break; } - if (!s || s.ident != Id.cmp) + if (!s || s.ident != Id.opCmp) e = null; // there's no valid member 'opCmp' } if (!e) @@ -736,7 +736,7 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc) fop.parent = sd; Expression e1 = new IdentifierExp(loc, Id.This); Expression e2 = new IdentifierExp(loc, Id.p); - Expression e = new CallExp(loc, new DotIdExp(loc, e1, Id.cmp), e2); + Expression e = new CallExp(loc, new DotIdExp(loc, e1, Id.opCmp), e2); fop.fbody = new ReturnStatement(loc, e); const errors = global.startGagging(); // Do not report errors Scope* sc2 = sc.push(); diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d index a6cfe6e..6d2a954 100644 --- a/gcc/d/dmd/ctfeexpr.d +++ b/gcc/d/dmd/ctfeexpr.d @@ -1529,11 +1529,9 @@ Expression ctfeCast(UnionExp* pue, const ref Loc loc, Type type, Type to, Expres : tclass.implicitConvTo(to.mutableOf()); if (match) return paint(); - else - { - emplaceExp!(NullExp)(pue, loc, to); - return pue.exp(); - } + + emplaceExp!(NullExp)(pue, loc, to); + return pue.exp(); } // Allow TypeInfo type painting diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index 2f33301..0d95ad4 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.d @@ -4144,20 +4144,6 @@ Expression typeCombine(BinExp be, Scope* sc) return ErrorExp.get(); } - Type t1 = be.e1.type.toBasetype(); - Type t2 = be.e2.type.toBasetype(); - - if (be.op == EXP.min || be.op == EXP.add) - { - // struct+struct, and class+class are errors - if (t1.ty == Tstruct && t2.ty == Tstruct) - return errorReturn(); - if (t1.ty == Tclass && t2.ty == Tclass) - return errorReturn(); - if (t1.ty == Taarray && t2.ty == Taarray) - return errorReturn(); - } - if (auto result = typeMerge(sc, be.op, be.e1, be.e2)) { if (be.type is null) diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index 0d87f6e..c7fb26a 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -3061,7 +3061,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (sd.ctor) { - Dsymbol scall = sd.search(Loc.initial, Id.call); + Dsymbol scall = sd.search(Loc.initial, Id.opCall); if (scall) { const xerrors = global.startGagging(); diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d index 7f7437c..dd9f3da 100644 --- a/gcc/d/dmd/dtemplate.d +++ b/gcc/d/dmd/dtemplate.d @@ -217,17 +217,12 @@ Dsymbol getDsymbol(RootObject oarg) return te.td; if (auto te = ea.isScopeExp()) return te.sds; - else - return null; - } - else - { - // Try to convert Type to symbol - if (auto ta = isType(oarg)) - return ta.toDsymbol(null); - else - return isDsymbol(oarg); // if already a symbol + return null; } + // Try to convert Type to symbol + if (auto ta = isType(oarg)) + return ta.toDsymbol(null); + return isDsymbol(oarg); // if already a symbol } @@ -5752,8 +5747,8 @@ MATCH matchArg(TemplateParameter tp, Loc instLoc, Scope* sc, Objects* tiargs, si if (auto ttp = tp.isTemplateTupleParameter()) return matchArgTuple(ttp); - else - return matchArgParameter(); + + return matchArgParameter(); } MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, TemplateParameters* parameters, ref Objects dedtypes, Declaration* psparam) @@ -6221,8 +6216,8 @@ void printTemplateStats(bool listInstances, ErrorSink eSink) auto diff = b.ts.uniqueInstantiations - a.ts.uniqueInstantiations; if (diff) return diff; - else - return b.ts.numInstantiations - a.ts.numInstantiations; + + return b.ts.numInstantiations - a.ts.numInstantiations; } } diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d index 75d6468..5b8e010 100644 --- a/gcc/d/dmd/expression.d +++ b/gcc/d/dmd/expression.d @@ -535,98 +535,6 @@ extern (C++) abstract class Expression : ASTNode return false; } - extern (D) final bool checkScalar() - { - if (op == EXP.error) - return true; - if (type.toBasetype().ty == Terror) - return true; - if (!type.isScalar()) - { - error(loc, "`%s` is not a scalar, it is a `%s`", toChars(), type.toChars()); - return true; - } - return checkValue(); - } - - extern (D) final bool checkNoBool() - { - if (op == EXP.error) - return true; - if (type.toBasetype().ty == Terror) - return true; - if (type.toBasetype().ty == Tbool) - { - error(loc, "operation not allowed on `bool` `%s`", toChars()); - return true; - } - return false; - } - - extern (D) final bool checkIntegral() - { - if (op == EXP.error) - return true; - if (type.toBasetype().ty == Terror) - return true; - if (!type.isIntegral()) - { - error(loc, "`%s` is not of integral type, it is a `%s`", toChars(), type.toChars()); - return true; - } - return checkValue(); - } - - extern (D) final bool checkArithmetic(EXP op) - { - if (op == EXP.error) - return true; - if (type.toBasetype().ty == Terror) - return true; - if (!type.isIntegral() && !type.isFloating()) - { - // unary aggregate ops error here - const char* msg = type.isAggregate() ? - "operator `%s` is not defined for `%s` of type `%s`" : - "illegal operator `%s` for `%s` of type `%s`"; - error(loc, msg, EXPtoString(op).ptr, toChars(), type.toChars()); - return true; - } - return checkValue(); - } - - /******************************* - * Check whether the expression allows RMW operations, error with rmw operator diagnostic if not. - * ex is the RHS expression, or NULL if ++/-- is used (for diagnostics) - * Returns true if error occurs. - */ - extern (D) final bool checkReadModifyWrite(EXP rmwOp, Expression ex = null) - { - //printf("Expression::checkReadModifyWrite() %s %s", toChars(), ex ? ex.toChars() : ""); - if (!type || !type.isShared() || type.isTypeStruct() || type.isTypeClass()) - return false; - - // atomicOp uses opAssign (+=/-=) rather than opOp (++/--) for the CT string literal. - switch (rmwOp) - { - case EXP.plusPlus: - case EXP.prePlusPlus: - rmwOp = EXP.addAssign; - break; - case EXP.minusMinus: - case EXP.preMinusMinus: - rmwOp = EXP.minAssign; - break; - default: - break; - } - - error(loc, "read-modify-write operations are not allowed for `shared` variables"); - errorSupplemental(loc, "Use `core.atomic.atomicOp!\"%s\"(%s, %s)` instead", - EXPtoString(rmwOp).ptr, toChars(), ex ? ex.toChars() : "1"); - return true; - } - /****************************** * Take address of expression. */ @@ -3039,8 +2947,6 @@ extern (C++) abstract class BinExp : Expression { Expression e1; Expression e2; - Type att1; // Save alias this type to detect recursion - Type att2; // Save alias this type to detect recursion extern (D) this(const ref Loc loc, EXP op, Expression e1, Expression e2) scope @safe { @@ -3058,20 +2964,6 @@ extern (C++) abstract class BinExp : Expression return e; } - extern (D) final bool checkIntegralBin() - { - bool r1 = e1.checkIntegral(); - bool r2 = e2.checkIntegral(); - return (r1 || r2); - } - - extern (D) final bool checkArithmeticBin() - { - bool r1 = e1.checkArithmetic(this.op); - bool r2 = e2.checkArithmetic(this.op); - return (r1 || r2); - } - /********************* * Mark the operands as will never be dereferenced, * which is useful info for @safe checks. diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h index d62aea8..07b163f1 100644 --- a/gcc/d/dmd/expression.h +++ b/gcc/d/dmd/expression.h @@ -679,9 +679,6 @@ public: Expression *e1; Expression *e2; - Type *att1; // Save alias this type to detect recursion - Type *att2; // Save alias this type to detect recursion - BinExp *syntaxCopy() override; void accept(Visitor *v) override { v->visit(this); } diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index eb4a5f8..fcb47a5 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -663,7 +663,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0) assert(!ae.lengthVar); *pe0 = null; AggregateDeclaration ad = isAggregate(ae.e1.type); - Dsymbol slice = search_function(ad, Id.slice); + Dsymbol slice = search_function(ad, Id.opSlice); //printf("slice = %s %s\n", slice.kind(), slice.toChars()); Expression fallback() { @@ -2403,7 +2403,7 @@ private bool checkPostblit(Type t, ref Loc loc, Scope* sc) /*************************************** * Pull out any properties. */ -private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = null, BinExp saveAtts = null) +private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = null, Type[2]* aliasThisStop = null) { //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", EXPtoString(e1.op).ptr, e1.toChars(), e2 ? e2.toChars() : null); Loc loc = e1.loc; @@ -2478,11 +2478,9 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = if (e2) { e = new AssignExp(loc, e, e2); - if (saveAtts) - { - (cast(BinExp)e).att1 = saveAtts.att1; - (cast(BinExp)e).att2 = saveAtts.att2; - } + if (aliasThisStop) + return e.expressionSemantic(sc, *aliasThisStop); + return e.expressionSemantic(sc); } return e.expressionSemantic(sc); } @@ -2584,11 +2582,8 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = if (e2) { e = new AssignExp(loc, e, e2); - if (saveAtts) - { - (cast(BinExp)e).att1 = saveAtts.att1; - (cast(BinExp)e).att2 = saveAtts.att2; - } + if (aliasThisStop) + return e.expressionSemantic(sc, *aliasThisStop); } return e.expressionSemantic(sc); } @@ -3816,6 +3811,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor Scope* sc; Expression result; + // For binary expressions, stores recursive 'alias this' types of lhs and rhs to prevent endless loops. + // See tryAliasThisSemantic + Type[2] aliasThisStop; + this(Scope* sc) scope @safe { this.sc = sc; @@ -6206,7 +6205,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } // No constructor, look for overload of opCall - if (search_function(sd, Id.call)) + if (search_function(sd, Id.opCall)) goto L1; // overload of opCall, therefore it's a call if (exp.e1.op != EXP.type) @@ -6247,7 +6246,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { L1: // Rewrite as e1.call(arguments) - Expression e = new DotIdExp(exp.loc, exp.e1, Id.call); + Expression e = new DotIdExp(exp.loc, exp.e1, Id.opCall); e = new CallExp(exp.loc, e, exp.arguments, exp.names); e = e.expressionSemantic(sc); result = e; @@ -7536,13 +7535,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor override void visit(BinAssignExp exp) { - Expression e = exp.op_overload(sc); - if (e) + if (Expression e = exp.opOverloadBinaryAssign(sc, aliasThisStop)) { result = e; return; } + Expression e; if (exp.e1.op == EXP.arrayLength) { // arr.length op= e2; @@ -7933,7 +7932,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { const callExpIdent = callExpFunc.ident; isEqualsCallExpression = callExpIdent == Id.__equals || - callExpIdent == Id.eq; + callExpIdent == Id.opEquals; } } if (op == EXP.equal || op == EXP.notEqual || @@ -8777,8 +8776,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor printf("PtrExp::semantic('%s')\n", exp.toChars()); } - Expression e = exp.op_overload(sc); - if (e) + if (Expression e = exp.opOverloadUnary(sc)) { result = e; return; @@ -8835,8 +8833,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor printf("NegExp::semantic('%s')\n", exp.toChars()); } - Expression e = exp.op_overload(sc); - if (e) + if (Expression e = exp.opOverloadUnary(sc)) { result = e; return; @@ -8876,8 +8873,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor printf("UAddExp::semantic('%s')\n", exp.toChars()); } - Expression e = exp.op_overload(sc); - if (e) + if (Expression e = exp.opOverloadUnary(sc)) { result = e; return; @@ -8902,8 +8898,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor override void visit(ComExp exp) { - Expression e = exp.op_overload(sc); - if (e) + if (Expression e = exp.opOverloadUnary(sc)) { result = e; return; @@ -8975,17 +8970,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor override void visit(DeleteExp exp) { - // @@@DEPRECATED_2.109@@@ - // 1. Deprecated since 2.079 - // 2. Error since 2.099 - // 3. Removal of keyword, "delete" can be used for other identities - if (!exp.isRAII) - { - error(exp.loc, "the `delete` keyword is obsolete"); - errorSupplemental(exp.loc, "use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead"); - return setError(); - } - Expression e = exp; if (Expression ex = unaSemantic(exp, sc)) @@ -9176,7 +9160,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (!exp.to.equals(exp.e1.type) && exp.mod == cast(ubyte)~0) { - if (Expression e = exp.op_overload(sc)) + if (Expression e = exp.opOverloadCast(sc)) { result = e.implicitCastTo(sc, exp.to); return; @@ -9466,8 +9450,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor error(exp.loc, "upper and lower bounds are needed to slice a pointer"); if (auto ad = isAggregate(tp.next.toBasetype())) { - auto s = search_function(ad, Id.index); - if (!s) s = search_function(ad, Id.slice); + auto s = search_function(ad, Id.opIndex); + if (!s) s = search_function(ad, Id.opSlice); if (s) { auto fd = s.isFuncDeclaration(); @@ -9710,8 +9694,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (result) return; - Expression e = exp.op_overload(sc); - if (e) + if (Expression e = exp.opOverloadArray(sc)) { result = e; return; @@ -10133,13 +10116,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } exp.e1 = e1x; - Expression e = exp.op_overload(sc); - if (e) - { - result = e; - return; - } - if (exp.e1.checkReadModifyWrite(exp.op)) return setError(); @@ -10182,7 +10158,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // Combine de,ea,eb,ec if (de) ea = new CommaExp(exp.loc, de, ea); - e = new CommaExp(exp.loc, ea, eb); + Expression e = new CommaExp(exp.loc, ea, eb); e = new CommaExp(exp.loc, e, ec); e = e.expressionSemantic(sc); result = e; @@ -10192,7 +10168,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor exp.e1 = exp.e1.modifiableLvalue(sc); exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true); - e = exp; + Expression e = exp; if (exp.e1.checkScalar() || exp.e1.checkSharedAccess(sc)) return setError(); @@ -10209,15 +10185,15 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor override void visit(PreExp exp) { - Expression e = exp.op_overload(sc); // printf("PreExp::semantic('%s')\n", toChars()); - if (e) + if (Expression e = exp.opOverloadUnary(sc)) { result = e; return; } // Rewrite as e1+=1 or e1-=1 + Expression e; if (exp.op == EXP.prePlusPlus) e = new AddAssignExp(exp.loc, exp.e1, IntegerExp.literal!1); else @@ -10328,7 +10304,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor AggregateDeclaration ad = isAggregate(t1b); if (!ad) break; - if (search_function(ad, Id.indexass)) + if (search_function(ad, Id.opIndexAssign)) { // Deal with $ res = resolveOpDollar(sc, ae, &e0); @@ -10347,7 +10323,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor */ Expressions* a = ae.arguments.copy(); a.insert(0, exp.e2); - res = new DotIdExp(exp.loc, ae.e1, Id.indexass); + res = new DotIdExp(exp.loc, ae.e1, Id.opIndexAssign); res = new CallExp(exp.loc, res, a); if (maybeSlice) // a[] = e2 might be: a.opSliceAssign(e2) res = res.trySemantic(sc); @@ -10358,7 +10334,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } Lfallback: - if (maybeSlice && search_function(ad, Id.sliceass)) + if (maybeSlice && search_function(ad, Id.opSliceAssign)) { // Deal with $ res = resolveOpDollar(sc, ae, ie, &e0); @@ -10381,7 +10357,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor a.push(ie.lwr); a.push(ie.upr); } - res = new DotIdExp(exp.loc, ae.e1, Id.sliceass); + res = new DotIdExp(exp.loc, ae.e1, Id.opSliceAssign); res = new CallExp(exp.loc, res, a); res = res.expressionSemantic(sc); return setResult(Expression.combine(e0, res)); @@ -10471,7 +10447,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor * or: * f() = value */ - if (Expression e = resolvePropertiesX(sc, e1x, exp.e2, exp)) + if (Expression e = resolvePropertiesX(sc, e1x, exp.e2, &aliasThisStop)) return setResult(e); if (e1x.checkRightThis(sc)) @@ -10604,6 +10580,35 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (exp.op == EXP.assign && exp.e1.checkModifiable(sc) == Modifiable.initialization) { + // Check common mistake of misspelled parameters in constructors, + // e.g. `this(int feild) { this.field = field; }` + if (auto dve1 = exp.e1.isDotVarExp) + if (auto dve2 = exp.e2.isDotVarExp) + if (sc.func && sc.func.parameters && dve1.e1.isThisExp && dve2.e1.isThisExp() + && dve1.var.ident.equals(dve2.var.ident)) + { + // @@@DEPRECATED_2.121@@@ + // Deprecated in 2.111, make it an error in 2.121 + deprecation(exp.e1.loc, "cannot initialize field `%s` with itself", dve1.var.toChars()); + auto findParameter(const(char)[] s, ref int cost) + { + foreach (p; *sc.func.parameters) + { + if (p.ident.toString == s) + { + cost = 1; + return p.ident.toString; + } + } + return null; + } + import dmd.root.speller : speller; + if (auto s = speller!findParameter(dve1.var.ident.toString)) + { + deprecationSupplemental(sc.func.loc, "did you mean to use parameter `%.*s`?\n", s.fTuple.expand); + } + } + //printf("[%s] change to init - %s\n", exp.loc.toChars(), exp.toChars()); auto t = exp.type; exp = new ConstructExp(exp.loc, exp.e1, exp.e2); @@ -10826,13 +10831,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (!e2x.implicitConvTo(t1)) { AggregateDeclaration ad2 = isAggregate(e2x.type); - if (ad2 && ad2.aliasthis && !isRecursiveAliasThis(exp.att2, exp.e2.type)) + if (ad2 && ad2.aliasthis && !isRecursiveAliasThis(aliasThisStop[1], exp.e2.type)) { /* Rewrite (e1 op e2) as: * (e1 op e2.aliasthis) */ exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident); - result = exp.expressionSemantic(sc); + result = exp.expressionSemantic(sc, aliasThisStop); return; } } @@ -10887,14 +10892,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor result = e; return; } - if (search_function(sd, Id.call)) + if (search_function(sd, Id.opCall)) { /* Look for static opCall * https://issues.dlang.org/show_bug.cgi?id=2702 * Rewrite as: * e1 = typeof(e1).opCall(arguments) */ - e2x = typeDotIdExp(e2x.loc, e1x.type, Id.call); + e2x = typeDotIdExp(e2x.loc, e1x.type, Id.opCall); e2x = new CallExp(exp.loc, e2x, exp.e2); e2x = e2x.expressionSemantic(sc); @@ -10911,13 +10916,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor else // https://issues.dlang.org/show_bug.cgi?id=11355 { AggregateDeclaration ad2 = isAggregate(e2x.type); - if (ad2 && ad2.aliasthis && !isRecursiveAliasThis(exp.att2, exp.e2.type)) + if (ad2 && ad2.aliasthis && !isRecursiveAliasThis(aliasThisStop[1], exp.e2.type)) { /* Rewrite (e1 op e2) as: * (e1 op e2.aliasthis) */ exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident); - result = exp.expressionSemantic(sc); + result = exp.expressionSemantic(sc, aliasThisStop); return; } } @@ -10958,8 +10963,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor ae.e1 = ae.e1.expressionSemantic(sc); ae.e1 = ae.e1.optimize(WANTvalue); ae.e2 = ev; - Expression e = ae.op_overload(sc); - if (e) + if (Expression e = ae.opOverloadAssign(sc, aliasThisStop)) { Expression ey = null; if (t2.ty == Tstruct && sd == t2.toDsymbol(sc)) @@ -11009,14 +11013,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } } - else + else if (Expression e = exp.isAssignExp().opOverloadAssign(sc, aliasThisStop)) { - Expression e = exp.op_overload(sc); - if (e) - { - result = e; - return; - } + result = e; + return; } } else @@ -11033,8 +11033,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // Disallow assignment operator overloads for same type if (exp.op == EXP.assign && !exp.e2.implicitConvTo(exp.e1.type)) { - Expression e = exp.op_overload(sc); - if (e) + if (Expression e = exp.isAssignExp().opOverloadAssign(sc, aliasThisStop)) { result = e; return; @@ -11410,7 +11409,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (e2x.op == EXP.error && exp.op == EXP.construct && t1.ty == Tstruct) { scope sd = (cast(TypeStruct)t1).sym; - Dsymbol opAssign = search_function(sd, Id.assign); + Dsymbol opAssign = search_function(sd, Id.opAssign); // and the struct defines an opAssign if (opAssign) @@ -11705,9 +11704,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor override void visit(PowAssignExp exp) { - - Expression e = exp.op_overload(sc); - if (e) + if (Expression e = exp.opOverloadBinaryAssign(sc, aliasThisStop)) { result = e; return; @@ -11754,7 +11751,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if ((exp.e1.type.isIntegral() || exp.e1.type.isFloating()) && (exp.e2.type.isIntegral() || exp.e2.type.isFloating())) { Expression e0 = null; - e = exp.reorderSettingAAElem(sc); + Expression e = exp.reorderSettingAAElem(sc); e = Expression.extractLast(e, e0); assert(e == exp); @@ -11786,8 +11783,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { //printf("CatAssignExp::semantic() %s\n", exp.toChars()); - Expression e = exp.op_overload(sc); - if (e) + if (Expression e = exp.opOverloadBinaryAssign(sc, aliasThisStop)) { result = e; return; @@ -11881,49 +11877,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else { - // Try alias this on first operand - static Expression tryAliasThisForLhs(BinAssignExp exp, Scope* sc) - { - AggregateDeclaration ad1 = isAggregate(exp.e1.type); - if (!ad1 || !ad1.aliasthis) - return null; - - /* Rewrite (e1 op e2) as: - * (e1.aliasthis op e2) - */ - if (isRecursiveAliasThis(exp.att1, exp.e1.type)) - return null; - //printf("att %s e1 = %s\n", Token.toChars(e.op), e.e1.type.toChars()); - Expression e1 = new DotIdExp(exp.loc, exp.e1, ad1.aliasthis.ident); - BinExp be = cast(BinExp)exp.copy(); - be.e1 = e1; - return be.trySemantic(sc); - } - - // Try alias this on second operand - static Expression tryAliasThisForRhs(BinAssignExp exp, Scope* sc) - { - AggregateDeclaration ad2 = isAggregate(exp.e2.type); - if (!ad2 || !ad2.aliasthis) - return null; - /* Rewrite (e1 op e2) as: - * (e1 op e2.aliasthis) - */ - if (isRecursiveAliasThis(exp.att2, exp.e2.type)) - return null; - //printf("att %s e2 = %s\n", Token.toChars(e.op), e.e2.type.toChars()); - Expression e2 = new DotIdExp(exp.loc, exp.e2, ad2.aliasthis.ident); - BinExp be = cast(BinExp)exp.copy(); - be.e2 = e2; - return be.trySemantic(sc); - } - Laliasthis: - result = tryAliasThisForLhs(exp, sc); + result = checkAliasThisForLhs(isAggregate(exp.e1.type), sc, exp, aliasThisStop); if (result) return; - result = tryAliasThisForRhs(exp, sc); + result = checkAliasThisForRhs(isAggregate(exp.e2.type), sc, exp, aliasThisStop); if (result) return; @@ -12076,13 +12035,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor printf("AddExp::semantic('%s')\n", exp.toChars()); } - if (Expression ex = binSemanticProp(exp, sc)) - { - result = ex; - return; - } - Expression e = exp.op_overload(sc); - if (e) + if (Expression e = exp.opOverloadBinary(sc, aliasThisStop)) { result = e; return; @@ -12139,6 +12092,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } + if (exp.checkArithmeticBin()) + return setError(); + tb1 = exp.e1.type.toBasetype(); if (!target.isVectorOpSupported(tb1, exp.op, tb2)) { @@ -12178,13 +12134,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor printf("MinExp::semantic('%s')\n", exp.toChars()); } - if (Expression ex = binSemanticProp(exp, sc)) - { - result = ex; - return; - } - Expression e = exp.op_overload(sc); - if (e) + if (Expression e = exp.opOverloadBinary(sc, aliasThisStop)) { result = e; return; @@ -12217,6 +12167,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (t1.ty == Tpointer) { + Expression e; if (t2.ty == Tpointer) { // https://dlang.org/spec/expression.html#add_expressions @@ -12294,6 +12245,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } + if (exp.checkArithmeticBin()) + return setError(); + t1 = exp.e1.type.toBasetype(); t2 = exp.e2.type.toBasetype(); if (!target.isVectorOpSupported(t1, exp.op, t2)) @@ -12422,14 +12376,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { // https://dlang.org/spec/expression.html#cat_expressions //printf("CatExp.semantic() %s\n", toChars()); - - if (Expression ex = binSemanticProp(exp, sc)) - { - result = ex; - return; - } - Expression e = exp.op_overload(sc); - if (e) + if (Expression e = exp.opOverloadBinary(sc, aliasThisStop)) { result = e; return; @@ -12581,6 +12528,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } Type t1 = exp.e1.type.toBasetype(); Type t2 = exp.e2.type.toBasetype(); + Expression e; if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray)) { @@ -12598,30 +12546,25 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor trySetCatExpLowering(result); } - override void visit(MulExp exp) + bool commonBinOpSemantic(BinExp exp) { - version (none) - { - printf("MulExp::semantic() %s\n", exp.toChars()); - } - - if (Expression ex = binSemanticProp(exp, sc)) - { - result = ex; - return; - } - Expression e = exp.op_overload(sc); - if (e) + if (Expression e = exp.opOverloadBinary(sc, aliasThisStop)) { result = e; - return; + return true; } if (Expression ex = typeCombine(exp, sc)) { result = ex; - return; + return true; } + return false; + } + bool commonArithBinOpSemantic(BinExp exp) + { + if (commonBinOpSemantic(exp)) + return true; Type tb = exp.type.toBasetype(); if (tb.ty == Tarray || tb.ty == Tsarray) @@ -12629,15 +12572,28 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (!isArrayOpValid(exp)) { result = arrayOpInvalidError(exp); - return; + return true; } result = exp; - return; + return true; } if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)) - return setError(); + { + setError(); + return true; + } + return false; + } + override void visit(MulExp exp) + { + version (none) + { + printf("MulExp::semantic() %s\n", exp.toChars()); + } + if (commonArithBinOpSemantic(exp)) + return; if (exp.type.isFloating()) { Type t1 = exp.e1.type; @@ -12676,7 +12632,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // iy * iv = -yv exp.e1.type = exp.type; exp.e2.type = exp.type; - e = new NegExp(exp.loc, exp); + Expression e = new NegExp(exp.loc, exp); e = e.expressionSemantic(sc); result = e; return; @@ -12689,7 +12645,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor exp.type = t1; // t1 is complex } } - else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) + else if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype())) { result = exp.incompatibleTypes(); return; @@ -12699,39 +12655,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor override void visit(DivExp exp) { - - if (Expression ex = binSemanticProp(exp, sc)) - { - result = ex; - return; - } - Expression e = exp.op_overload(sc); - if (e) - { - result = e; - return; - } - - if (Expression ex = typeCombine(exp, sc)) - { - result = ex; - return; - } - - Type tb = exp.type.toBasetype(); - if (tb.ty == Tarray || tb.ty == Tsarray) - { - if (!isArrayOpValid(exp)) - { - result = arrayOpInvalidError(exp); - return; - } - result = exp; + if (commonArithBinOpSemantic(exp)) return; - } - - if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)) - return setError(); if (exp.type.isFloating()) { @@ -12745,7 +12670,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { // x/iv = i(-x/v) exp.e2.type = t1; - e = new NegExp(exp.loc, exp); + Expression e = new NegExp(exp.loc, exp); e = e.expressionSemantic(sc); result = e; return; @@ -12785,7 +12710,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor exp.type = t1; // t1 is complex } } - else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) + else if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype())) { result = exp.incompatibleTypes(); return; @@ -12795,45 +12720,15 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor override void visit(ModExp exp) { - - if (Expression ex = binSemanticProp(exp, sc)) - { - result = ex; - return; - } - Expression e = exp.op_overload(sc); - if (e) - { - result = e; + if (commonArithBinOpSemantic(exp)) return; - } - if (Expression ex = typeCombine(exp, sc)) - { - result = ex; - return; - } - - Type tb = exp.type.toBasetype(); - if (tb.ty == Tarray || tb.ty == Tsarray) - { - if (!isArrayOpValid(exp)) - { - result = arrayOpInvalidError(exp); - return; - } - result = exp; - return; - } - if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) + if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype())) { result = exp.incompatibleTypes(); return; } - if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)) - return setError(); - if (exp.type.isFloating()) { exp.type = exp.e1.type; @@ -12848,49 +12743,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor override void visit(PowExp exp) { - - //printf("PowExp::semantic() %s\n", toChars()); - if (Expression ex = binSemanticProp(exp, sc)) - { - result = ex; - return; - } - Expression e = exp.op_overload(sc); - if (e) - { - result = e; + if (commonArithBinOpSemantic(exp)) return; - } - - if (Expression ex = typeCombine(exp, sc)) - { - result = ex; - return; - } - - Type tb = exp.type.toBasetype(); - if (tb.ty == Tarray || tb.ty == Tsarray) - { - if (!isArrayOpValid(exp)) - { - result = arrayOpInvalidError(exp); - return; - } - result = exp; - return; - } - - if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)) - return setError(); - if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype())) + if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype())) { result = exp.incompatibleTypes(); return; } // First, attempt to fold the expression. - e = exp.optimize(WANTvalue); + Expression e = exp.optimize(WANTvalue); if (e.op != EXP.pow) { e = e.expressionSemantic(sc); @@ -12923,14 +12786,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor private void visitShift(BinExp exp) { - - if (Expression ex = binSemanticProp(exp, sc)) - { - result = ex; - return; - } - Expression e = exp.op_overload(sc); - if (e) + if (Expression e = exp.opOverloadBinary(sc, aliasThisStop)) { result = e; return; @@ -12971,14 +12827,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor private void visitBinaryBitOp(BinExp exp) { - - if (Expression ex = binSemanticProp(exp, sc)) - { - result = ex; - return; - } - Expression e = exp.op_overload(sc); - if (e) + if (Expression e = exp.opOverloadBinary(sc, aliasThisStop)) { result = e; return; @@ -13136,57 +12985,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return setError(); } - - EXP cmpop = exp.op; - if (auto e = exp.op_overload(sc, &cmpop)) + if (auto e = exp.opOverloadCmp(sc, aliasThisStop)) { - if (!e.type.isScalar() && e.type.equals(exp.e1.type)) - { - error(exp.loc, "recursive `opCmp` expansion"); - return setError(); - } - if (e.op == EXP.call) - { - - if (t1.ty == Tclass && t2.ty == Tclass) - { - // Lower to object.__cmp(e1, e2) - Expression cl = new IdentifierExp(exp.loc, Id.empty); - cl = new DotIdExp(exp.loc, cl, Id.object); - cl = new DotIdExp(exp.loc, cl, Id.__cmp); - cl = cl.expressionSemantic(sc); - - auto arguments = new Expressions(); - // Check if op_overload found a better match by calling e2.opCmp(e1) - // If the operands were swapped, then the result must be reversed - // e1.opCmp(e2) == -e2.opCmp(e1) - // cmpop takes care of this - if (exp.op == cmpop) - { - arguments.push(exp.e1); - arguments.push(exp.e2); - } - else - { - // Use better match found by op_overload - arguments.push(exp.e2); - arguments.push(exp.e1); - } - - cl = new CallExp(exp.loc, cl, arguments); - cl = new CmpExp(cmpop, exp.loc, cl, new IntegerExp(0)); - result = cl.expressionSemantic(sc); - return; - } - - e = new CmpExp(cmpop, exp.loc, e, IntegerExp.literal!0); - e = e.expressionSemantic(sc); - } result = e; return; } - if (Expression ex = typeCombine(exp, sc)) { result = ex; @@ -13284,14 +13088,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor override void visit(InExp exp) { - - if (Expression ex = binSemanticProp(exp, sc)) - { - result = ex; - return; - } - Expression e = exp.op_overload(sc); - if (e) + if (Expression e = exp.opOverloadBinary(sc, aliasThisStop)) { result = e; return; @@ -13455,13 +13252,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return false; } - if (auto e = exp.op_overload(sc)) + if (auto e = exp.opOverloadEqual(sc, aliasThisStop)) { result = e; return; } - const isArrayComparison = (t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray); const needsArrayLowering = isArrayComparison && needsDirectEq(t1, t2, sc); @@ -13931,6 +13727,32 @@ Expression trySemantic(Expression exp, Scope* sc) return e; } +/********************************** + * Try expression semantic on `exp`, gagging semantic errors, + * but don't resolve alias this on a BinExp when the lhs or rhs + * has the corresponding type in `aliasThisStop` (See `isRecursiveAliasThis`). + * + * Params: + * exp = expression to try semantic on + * sc = scope + * aliasThisStop = pair of recursive alias this types to stop endless recursion + * Returns: + * exp after expression semantic, or `null` on error + */ +Expression trySemanticAliasThis(Expression exp, Scope* sc, Type[2] aliasThisStop) +{ + if (exp.expressionSemanticDone) + return exp; + + const errors = global.startGagging(); + Expression e = expressionSemantic(exp, sc, aliasThisStop); + + if (global.endGagging(errors)) + return null; + + return e; +} + /************************** * Helper function for easy error propagation. * If error occurs, returns ErrorExp. Otherwise returns NULL. @@ -14015,6 +13837,18 @@ Expression expressionSemantic(Expression e, Scope* sc) return v.result; } +// ditto, but passes alias this stop types, see trySemanticAliasThis +private Expression expressionSemantic(Expression e, Scope* sc, Type[2] aliasThisStop) +{ + if (e.expressionSemanticDone) + return e; + + scope v = new ExpressionSemanticVisitor(sc); + v.aliasThisStop = aliasThisStop; + e.accept(v); + return v.result; +} + private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc) { //printf("dotIdSemanticPropX() %s\n", toChars(exp)); @@ -14849,6 +14683,105 @@ MATCH matchType(FuncExp funcExp, Type to, Scope* sc, FuncExp* presult, ErrorSink return m; } +private bool checkScalar(Expression e) +{ + if (e.op == EXP.error) + return true; + if (e.type.toBasetype().ty == Terror) + return true; + if (!e.type.isScalar()) + { + error(e.loc, "`%s` is not a scalar, it is a `%s`", e.toChars(), e.type.toChars()); + return true; + } + return e.checkValue(); +} + +private bool checkNoBool(Expression e) +{ + if (e.op == EXP.error) + return true; + if (e.type.toBasetype().ty == Terror) + return true; + if (e.type.toBasetype().ty == Tbool) + { + error(e.loc, "operation not allowed on `bool` `%s`", e.toChars()); + return true; + } + return false; +} + +private bool checkIntegral(Expression e) +{ + if (e.op == EXP.error) + return true; + if (e.type.toBasetype().ty == Terror) + return true; + if (!e.type.isIntegral()) + { + error(e.loc, "`%s` is not of integral type, it is a `%s`", e.toChars(), e.type.toChars()); + return true; + } + return e.checkValue(); +} + +private bool checkArithmetic(Expression e, EXP op) +{ + if (op == EXP.error) + return true; + if (e.type.toBasetype().ty == Terror) + return true; + if (!e.type.isIntegral() && !e.type.isFloating()) + { + // unary aggregate ops error here + const char* msg = e.type.isAggregate() ? + "operator `%s` is not defined for `%s` of type `%s`" : + "illegal operator `%s` for `%s` of type `%s`"; + error(e.loc, msg, EXPtoString(op).ptr, e.toChars(), e.type.toChars()); + return true; + } + + // FIXME: Existing code relies on adding / subtracting types in typeof() expressions: + // alias I = ulong; alias U = typeof(I + 1u); + // https://github.com/dlang/dmd/issues/20763 + if (op == EXP.add || op == EXP.min) + return false; + + return e.checkValue(); +} + +/******************************* + * Check whether the expression allows RMW operations, error with rmw operator diagnostic if not. + * ex is the RHS expression, or NULL if ++/-- is used (for diagnostics) + * Returns true if error occurs. + */ +private bool checkReadModifyWrite(Expression e, EXP rmwOp, Expression ex = null) +{ + //printf("Expression::checkReadModifyWrite() %s %s", toChars(), ex ? ex.toChars() : ""); + if (!e.type || !e.type.isShared() || e.type.isTypeStruct() || e.type.isTypeClass()) + return false; + + // atomicOp uses opAssign (+=/-=) rather than opOp (++/--) for the CT string literal. + switch (rmwOp) + { + case EXP.plusPlus: + case EXP.prePlusPlus: + rmwOp = EXP.addAssign; + break; + case EXP.minusMinus: + case EXP.preMinusMinus: + rmwOp = EXP.minAssign; + break; + default: + break; + } + + error(e.loc, "read-modify-write operations are not allowed for `shared` variables"); + errorSupplemental(e.loc, "Use `core.atomic.atomicOp!\"%s\"(%s, %s)` instead", + EXPtoString(rmwOp).ptr, e.toChars(), ex ? ex.toChars() : "1"); + return true; +} + private bool checkSharedAccessBin(BinExp binExp, Scope* sc) { const r1 = binExp.e1.checkSharedAccess(sc); @@ -14856,6 +14789,18 @@ private bool checkSharedAccessBin(BinExp binExp, Scope* sc) return (r1 || r2); } +private bool checkIntegralBin(BinExp e) +{ + bool r1 = e.e1.checkIntegral(); + bool r2 = e.e2.checkIntegral(); + return (r1 || r2); +} + +private bool checkArithmeticBin(BinExp e) +{ + return (e.e1.checkArithmetic(e.op) || e.e2.checkArithmetic(e.op)); +} + /*************************************** * If expression is shared, check that we can access it. * Give error message if not. @@ -16451,7 +16396,7 @@ Expression toBoolean(Expression exp, Scope* sc) /* Don't really need to check for opCast first, but by doing so we * get better error messages if it isn't there. */ - if (Dsymbol fd = search_function(ad, Id._cast)) + if (Dsymbol fd = search_function(ad, Id.opCast)) { e = new CastExp(exp.loc, e, Type.tbool); e = e.expressionSemantic(sc); diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index 993bce8..70f4c83 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -581,8 +581,7 @@ extern (C++) class FuncDeclaration : Declaration { if (isMain()) return "D main"; - else - return Dsymbol.toPrettyChars(QualifyTypes); + return Dsymbol.toPrettyChars(QualifyTypes); } /** for diagnostics, e.g. 'int foo(int x, int y) pure' */ diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d index d391bdb..961a0d2 100644 --- a/gcc/d/dmd/hdrgen.d +++ b/gcc/d/dmd/hdrgen.d @@ -2435,7 +2435,7 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt void visitSymOff(SymOffExp e) { if (e.offset) - buf.printf("(& %s%+lld)", e.var.toChars(), e.offset); + buf.printf("(& %s + %llu)", e.var.toChars(), e.offset); else if (e.var.isTypeInfoDeclaration()) buf.writestring(e.var.toChars()); else diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d index ee4214a..9833e198 100644 --- a/gcc/d/dmd/id.d +++ b/gcc/d/dmd/id.d @@ -223,60 +223,15 @@ immutable Msgtable[] msgtable = { "__LOCAL_SIZE" }, // For operator overloads - { "uadd", "opPos" }, - { "neg", "opNeg" }, - { "com", "opCom" }, - { "add", "opAdd" }, - { "add_r", "opAdd_r" }, - { "sub", "opSub" }, - { "sub_r", "opSub_r" }, - { "mul", "opMul" }, - { "mul_r", "opMul_r" }, - { "div", "opDiv" }, - { "div_r", "opDiv_r" }, - { "mod", "opMod" }, - { "mod_r", "opMod_r" }, - { "eq", "opEquals" }, - { "cmp", "opCmp" }, - { "iand", "opAnd" }, - { "iand_r", "opAnd_r" }, - { "ior", "opOr" }, - { "ior_r", "opOr_r" }, - { "ixor", "opXor" }, - { "ixor_r", "opXor_r" }, - { "shl", "opShl" }, - { "shl_r", "opShl_r" }, - { "shr", "opShr" }, - { "shr_r", "opShr_r" }, - { "ushr", "opUShr" }, - { "ushr_r", "opUShr_r" }, - { "cat", "opCat" }, - { "cat_r", "opCat_r" }, - { "assign", "opAssign" }, - { "addass", "opAddAssign" }, - { "subass", "opSubAssign" }, - { "mulass", "opMulAssign" }, - { "divass", "opDivAssign" }, - { "modass", "opModAssign" }, - { "andass", "opAndAssign" }, - { "orass", "opOrAssign" }, - { "xorass", "opXorAssign" }, - { "shlass", "opShlAssign" }, - { "shrass", "opShrAssign" }, - { "ushrass", "opUShrAssign" }, - { "catass", "opCatAssign" }, - { "postinc", "opPostInc" }, - { "postdec", "opPostDec" }, - { "index", "opIndex" }, - { "indexass", "opIndexAssign" }, - { "slice", "opSlice" }, - { "sliceass", "opSliceAssign" }, - { "call", "opCall" }, - { "_cast", "opCast" }, - { "opIn" }, - { "opIn_r" }, - { "opStar" }, - { "opDot" }, + { "opEquals" }, + { "opCmp" }, + { "opAssign" }, + { "opIndex" }, + { "opIndexAssign" }, + { "opSlice" }, + { "opSliceAssign" }, + { "opCall" }, + { "opCast" }, { "opDispatch" }, { "opDollar" }, { "opUnary" }, @@ -287,9 +242,6 @@ immutable Msgtable[] msgtable = { "opOpAssign" }, { "opIndexOpAssign" }, { "opSliceOpAssign" }, - { "pow", "opPow" }, - { "pow_r", "opPow_r" }, - { "powass", "opPowAssign" }, { "classNew", "new" }, { "classDelete", "delete" }, diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d index aec6807..c181d53 100644 --- a/gcc/d/dmd/initsem.d +++ b/gcc/d/dmd/initsem.d @@ -489,7 +489,7 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn else i.exp = e.optimize(WANTvalue); } - else if (search_function(sd, Id.call)) + else if (search_function(sd, Id.opCall)) { /* https://issues.dlang.org/show_bug.cgi?id=1547 * @@ -499,7 +499,7 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn * i.exp = typeof(sd).opCall(arguments) */ - Expression e = typeDotIdExp(i.loc, sd.type, Id.call); + Expression e = typeDotIdExp(i.loc, sd.type, Id.opCall); e = new CallExp(i.loc, e, i.exp); e = e.expressionSemantic(sc); e = resolveProperties(sc, e); diff --git a/gcc/d/dmd/mangle/cpp.d b/gcc/d/dmd/mangle/cpp.d index 67c9b53..4932b01 100644 --- a/gcc/d/dmd/mangle/cpp.d +++ b/gcc/d/dmd/mangle/cpp.d @@ -60,11 +60,11 @@ package CppOperator isCppOperator(const scope Identifier id) { with (Id) with (CppOperator) { - return (id == _cast) ? Cast : - (id == assign) ? Assign : - (id == eq) ? Eq : - (id == index) ? Index : - (id == call) ? Call : + return (id == opCast) ? Cast : + (id == opAssign) ? Assign : + (id == opEquals) ? Eq : + (id == opIndex) ? Index : + (id == opCall) ? Call : (id == opUnary) ? Unary : (id == opBinary) ? Binary : (id == opOpAssign) ? OpAssign : @@ -435,10 +435,10 @@ private final class CppMangleVisitor : Visitor // 4. null pointer: std::nullptr_t (since C++11) if (t.ty == Tvoid || t.ty == Tbool) return true; - else if (t.ty == Tnull && global.params.cplusplus >= CppStdRevision.cpp11) + if (t.ty == Tnull && global.params.cplusplus >= CppStdRevision.cpp11) return true; - else - return t.isTypeBasic() && (t.isIntegral() || t.isReal()); + + return t.isTypeBasic() && (t.isIntegral() || t.isReal()); } /****************************** @@ -1102,13 +1102,13 @@ private final class CppMangleVisitor : Visitor buf.writestring(ctor.isCpCtor ? "C2" : "C1"); else if (d.isAggregateDtor()) buf.writestring("D1"); - else if (d.ident && d.ident == Id.assign) + else if (d.ident && d.ident == Id.opAssign) buf.writestring("aS"); - else if (d.ident && d.ident == Id.eq) + else if (d.ident && d.ident == Id.opEquals) buf.writestring("eq"); - else if (d.ident && d.ident == Id.index) + else if (d.ident && d.ident == Id.opIndex) buf.writestring("ix"); - else if (d.ident && d.ident == Id.call) + else if (d.ident && d.ident == Id.opCall) buf.writestring("cl"); else source_name(d, true); @@ -1939,21 +1939,21 @@ extern(C++): //printf("enum id = '%s'\n", id.toChars()); if (id == Id.__c_long) return writeBasicType(t, 0, 'l'); - else if (id == Id.__c_ulong) + if (id == Id.__c_ulong) return writeBasicType(t, 0, 'm'); - else if (id == Id.__c_char) + if (id == Id.__c_char) return writeBasicType(t, 0, 'c'); - else if (id == Id.__c_wchar_t) + if (id == Id.__c_wchar_t) return writeBasicType(t, 0, 'w'); - else if (id == Id.__c_longlong) + if (id == Id.__c_longlong) return writeBasicType(t, 0, 'x'); - else if (id == Id.__c_ulonglong) + if (id == Id.__c_ulonglong) return writeBasicType(t, 0, 'y'); - else if (id == Id.__c_complex_float) + if (id == Id.__c_complex_float) return Type.tcomplex32.accept(this); - else if (id == Id.__c_complex_double) + if (id == Id.__c_complex_double) return Type.tcomplex64.accept(this); - else if (id == Id.__c_complex_real) + if (id == Id.__c_complex_real) return Type.tcomplex80.accept(this); doSymbol(t); @@ -2362,8 +2362,7 @@ private bool isNamespaceEqual (CPPNamespaceDeclaration a, Nspace b, size_t idx = // We need to see if there's more ident enclosing if (auto pb = b.toParent().isNspace()) return isNamespaceEqual(a.cppnamespace, pb); - else - return a.cppnamespace is null; + return a.cppnamespace is null; } /// Returns: diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d index f91687b..b270943 100644 --- a/gcc/d/dmd/mtype.d +++ b/gcc/d/dmd/mtype.d @@ -1295,17 +1295,15 @@ extern (C++) abstract class Type : ASTNode { if (t.isWildConst()) return MODFlags.wild; - else - return MODFlags.wildconst; + return MODFlags.wildconst; } - else if (isWild()) + if (isWild()) return MODFlags.wild; - else if (isConst()) + if (isConst()) return MODFlags.const_; - else if (isMutable()) + if (isMutable()) return MODFlags.mutable; - else - assert(0); + assert(0); } return 0; } diff --git a/gcc/d/dmd/mustuse.d b/gcc/d/dmd/mustuse.d index fc7618b..4fc117e 100644 --- a/gcc/d/dmd/mustuse.d +++ b/gcc/d/dmd/mustuse.d @@ -111,26 +111,13 @@ private bool isAssignmentOpId(Identifier id) { import dmd.id : Id; - return id == Id.assign - || id == Id.addass - || id == Id.subass - || id == Id.mulass - || id == Id.divass - || id == Id.modass - || id == Id.andass - || id == Id.orass - || id == Id.xorass - || id == Id.shlass - || id == Id.shrass - || id == Id.ushrass - || id == Id.catass - || id == Id.indexass - || id == Id.slice - || id == Id.sliceass + return id == Id.opAssign + || id == Id.opIndexAssign + || id == Id.opSlice + || id == Id.opSliceAssign || id == Id.opOpAssign || id == Id.opIndexOpAssign - || id == Id.opSliceOpAssign - || id == Id.powass; + || id == Id.opSliceOpAssign; } /** diff --git a/gcc/d/dmd/objc.d b/gcc/d/dmd/objc.d index c5ee77a..b671986 100644 --- a/gcc/d/dmd/objc.d +++ b/gcc/d/dmd/objc.d @@ -714,8 +714,8 @@ extern(C++) private final class Supported : Objc { if (cd.classKind == ClassKind.objc && fd.isStatic && !cd.objc.isMeta) return cd.objc.metaclass; - else - return cd; + + return cd; } override void addToClassMethodList(FuncDeclaration fd, ClassDeclaration cd) const @@ -805,11 +805,10 @@ extern(C++) private final class Supported : Objc { if (classDeclaration.baseClass) return getRuntimeMetaclass(classDeclaration.baseClass); - else - return classDeclaration; + + return classDeclaration; } - else - return classDeclaration.objc.metaclass; + return classDeclaration.objc.metaclass; } override void addSymbols(AttribDeclaration attribDeclaration, diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d index 56b3601..92f3bb2 100644 --- a/gcc/d/dmd/opover.d +++ b/gcc/d/dmd/opover.d @@ -71,84 +71,6 @@ bool isCommutative(EXP op) @safe return false; } -/*********************************** - * Get Identifier for operator overload. - */ -private Identifier opId(Expression e) -{ - switch (e.op) - { - case EXP.uadd: return Id.uadd; - case EXP.negate: return Id.neg; - case EXP.tilde: return Id.com; - case EXP.cast_: return Id._cast; - case EXP.in_: return Id.opIn; - case EXP.plusPlus: return Id.postinc; - case EXP.minusMinus: return Id.postdec; - case EXP.add: return Id.add; - case EXP.min: return Id.sub; - case EXP.mul: return Id.mul; - case EXP.div: return Id.div; - case EXP.mod: return Id.mod; - case EXP.pow: return Id.pow; - case EXP.leftShift: return Id.shl; - case EXP.rightShift: return Id.shr; - case EXP.unsignedRightShift: return Id.ushr; - case EXP.and: return Id.iand; - case EXP.or: return Id.ior; - case EXP.xor: return Id.ixor; - case EXP.concatenate: return Id.cat; - case EXP.assign: return Id.assign; - case EXP.addAssign: return Id.addass; - case EXP.minAssign: return Id.subass; - case EXP.mulAssign: return Id.mulass; - case EXP.divAssign: return Id.divass; - case EXP.modAssign: return Id.modass; - case EXP.powAssign: return Id.powass; - case EXP.leftShiftAssign: return Id.shlass; - case EXP.rightShiftAssign: return Id.shrass; - case EXP.unsignedRightShiftAssign: return Id.ushrass; - case EXP.andAssign: return Id.andass; - case EXP.orAssign: return Id.orass; - case EXP.xorAssign: return Id.xorass; - case EXP.concatenateAssign: return Id.catass; - case EXP.equal: return Id.eq; - case EXP.lessThan: - case EXP.lessOrEqual: - case EXP.greaterThan: - case EXP.greaterOrEqual: return Id.cmp; - case EXP.array: return Id.index; - case EXP.star: return Id.opStar; - default: assert(0); - } -} - -/*********************************** - * Get Identifier for reverse operator overload, - * `null` if not supported for this operator. - */ -private Identifier opId_r(Expression e) -{ - switch (e.op) - { - case EXP.in_: return Id.opIn_r; - case EXP.add: return Id.add_r; - case EXP.min: return Id.sub_r; - case EXP.mul: return Id.mul_r; - case EXP.div: return Id.div_r; - case EXP.mod: return Id.mod_r; - case EXP.pow: return Id.pow_r; - case EXP.leftShift: return Id.shl_r; - case EXP.rightShift: return Id.shr_r; - case EXP.unsignedRightShift:return Id.ushr_r; - case EXP.and: return Id.iand_r; - case EXP.or: return Id.ior_r; - case EXP.xor: return Id.ixor_r; - case EXP.concatenate: return Id.cat_r; - default: return null; - } -} - /******************************************* * Helper function to turn operator into template argument list */ @@ -208,7 +130,7 @@ Objects* opToArg(Scope* sc, EXP op) } // Try alias this on first operand -private Expression checkAliasThisForLhs(AggregateDeclaration ad, Scope* sc, BinExp e) +Expression checkAliasThisForLhs(AggregateDeclaration ad, Scope* sc, BinExp e, Type[2] aliasThisStop) { if (!ad || !ad.aliasthis) return null; @@ -216,7 +138,7 @@ private Expression checkAliasThisForLhs(AggregateDeclaration ad, Scope* sc, BinE /* Rewrite (e1 op e2) as: * (e1.aliasthis op e2) */ - if (isRecursiveAliasThis(e.att1, e.e1.type)) + if (isRecursiveAliasThis(aliasThisStop[0], e.e1.type)) return null; //printf("att %s e1 = %s\n", Token.toChars(e.op), e.e1.type.toChars()); BinExp be = cast(BinExp)e.copy(); @@ -227,24 +149,18 @@ private Expression checkAliasThisForLhs(AggregateDeclaration ad, Scope* sc, BinE if (!be.e1) return null; - Expression result; - if (be.op == EXP.concatenateAssign) - result = be.op_overload(sc); - else - result = be.trySemantic(sc); - - return result; + return be.trySemanticAliasThis(sc, aliasThisStop); } // Try alias this on second operand -private Expression checkAliasThisForRhs(AggregateDeclaration ad, Scope* sc, BinExp e) +Expression checkAliasThisForRhs(AggregateDeclaration ad, Scope* sc, BinExp e, Type[2] aliasThisStop) { if (!ad || !ad.aliasthis) return null; /* Rewrite (e1 op e2) as: * (e1 op e2.aliasthis) */ - if (isRecursiveAliasThis(e.att2, e.e2.type)) + if (isRecursiveAliasThis(aliasThisStop[1], e.e2.type)) return null; //printf("att %s e2 = %s\n", Token.toChars(e.op), e.e2.type.toChars()); BinExp be = cast(BinExp)e.copy(); @@ -252,189 +168,14 @@ private Expression checkAliasThisForRhs(AggregateDeclaration ad, Scope* sc, BinE if (!be.e2) return null; - Expression result; - if (be.op == EXP.concatenateAssign) - result = be.op_overload(sc); - else - result = be.trySemantic(sc); - - return result; + return be.trySemanticAliasThis(sc, aliasThisStop); } -/************************************ - * Operator overload. - * Check for operator overload, if so, replace - * with function call. - * Params: - * e = expression with operator - * sc = context - * pop = if not null, is set to the operator that was actually overloaded, - * which may not be `e.op`. Happens when operands are reversed to - * match an overload - * Returns: - * `null` if not an operator overload, - * otherwise the lowered expression - */ -Expression op_overload(Expression e, Scope* sc, EXP* pop = null) +Expression opOverloadUnary(UnaExp e, Scope* sc) { - Expression visit(Expression e) - { - assert(0); - } - - Expression visitUna(UnaExp e) - { - //printf("UnaExp::op_overload() (%s)\n", e.toChars()); - Expression result; - if (auto ae = e.e1.isArrayExp()) - { - ae.e1 = ae.e1.expressionSemantic(sc); - ae.e1 = resolveProperties(sc, ae.e1); - Expression ae1old = ae.e1; - const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval); - IntervalExp ie = null; - if (maybeSlice && ae.arguments.length) - { - ie = (*ae.arguments)[0].isIntervalExp(); - } - Type att = null; // first cyclic `alias this` type - while (true) - { - if (ae.e1.op == EXP.error) - { - return ae.e1; - } - Expression e0 = null; - Expression ae1save = ae.e1; - ae.lengthVar = null; - Type t1b = ae.e1.type.toBasetype(); - AggregateDeclaration ad = isAggregate(t1b); - if (!ad) - break; - if (search_function(ad, Id.opIndexUnary)) - { - // Deal with $ - result = resolveOpDollar(sc, ae, &e0); - if (!result) // op(a[i..j]) might be: a.opSliceUnary!(op)(i, j) - goto Lfallback; - if (result.op == EXP.error) - return result; - /* Rewrite op(a[arguments]) as: - * a.opIndexUnary!(op)(arguments) - */ - Expressions* a = ae.arguments.copy(); - Objects* tiargs = opToArg(sc, e.op); - result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opIndexUnary, tiargs); - result = new CallExp(e.loc, result, a); - if (maybeSlice) // op(a[]) might be: a.opSliceUnary!(op)() - result = result.trySemantic(sc); - else - result = result.expressionSemantic(sc); - if (result) - { - return Expression.combine(e0, result); - } - } - Lfallback: - if (maybeSlice && search_function(ad, Id.opSliceUnary)) - { - // Deal with $ - result = resolveOpDollar(sc, ae, ie, &e0); - if (result.op == EXP.error) - return result; - /* Rewrite op(a[i..j]) as: - * a.opSliceUnary!(op)(i, j) - */ - auto a = new Expressions(); - if (ie) - { - a.push(ie.lwr); - a.push(ie.upr); - } - Objects* tiargs = opToArg(sc, e.op); - result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opSliceUnary, tiargs); - result = new CallExp(e.loc, result, a); - result = result.expressionSemantic(sc); - result = Expression.combine(e0, result); - return result; - } - // Didn't find it. Forward to aliasthis - if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type)) - { - /* Rewrite op(a[arguments]) as: - * op(a.aliasthis[arguments]) - */ - ae.e1 = resolveAliasThis(sc, ae1save, true); - if (ae.e1) - continue; - } - break; - } - ae.e1 = ae1old; // recovery - ae.lengthVar = null; - } - e.e1 = e.e1.expressionSemantic(sc); - e.e1 = resolveProperties(sc, e.e1); - Type att = null; // first cyclic `alias this` type - while (1) - { - if (e.e1.op == EXP.error) - { - return e.e1; - } - - AggregateDeclaration ad = isAggregate(e.e1.type); - if (!ad) - break; - - Dsymbol fd = null; - /* Rewrite as: - * e1.opUnary!(op)() - */ - fd = search_function(ad, Id.opUnary); - if (fd) - { - Objects* tiargs = opToArg(sc, e.op); - result = new DotTemplateInstanceExp(e.loc, e.e1, fd.ident, tiargs); - result = new CallExp(e.loc, result); - result = result.expressionSemantic(sc); - return result; - } - // D1-style operator overloads, deprecated - if (e.op != EXP.prePlusPlus && e.op != EXP.preMinusMinus) - { - auto id = opId(e); - fd = search_function(ad, id); - if (fd) - { - // @@@DEPRECATED_2.110@@@. - // Deprecated in 2.088, made an error in 2.100 - error(e.loc, "`%s` is obsolete. Use `opUnary(string op)() if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr); - return ErrorExp.get(); - } - } - // Didn't find it. Forward to aliasthis - if (ad.aliasthis && !isRecursiveAliasThis(att, e.e1.type)) - { - /* Rewrite op(e1) as: - * op(e1.aliasthis) - */ - //printf("att una %s e1 = %s\n", EXPtoString(op).ptr, this.e1.type.toChars()); - if (auto e1 = resolveAliasThis(sc, e.e1, true)) - { - e.e1 = e1; - continue; - } - break; - } - break; - } - return result; - } - - Expression visitArray(ArrayExp ae) + Expression result; + if (auto ae = e.e1.isArrayExp()) { - //printf("ArrayExp::op_overload() (%s)\n", ae.toChars()); ae.e1 = ae.e1.expressionSemantic(sc); ae.e1 = resolveProperties(sc, ae.e1); Expression ae1old = ae.e1; @@ -444,7 +185,6 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) { ie = (*ae.arguments)[0].isIntervalExp(); } - Expression result; Type att = null; // first cyclic `alias this` type while (true) { @@ -458,43 +198,23 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) Type t1b = ae.e1.type.toBasetype(); AggregateDeclaration ad = isAggregate(t1b); if (!ad) - { - // If the non-aggregate expression ae.e1 is indexable or sliceable, - // convert it to the corresponding concrete expression. - if (isIndexableNonAggregate(t1b) || ae.e1.op == EXP.type) - { - // Convert to SliceExp - if (maybeSlice) - { - result = new SliceExp(ae.loc, ae.e1, ie); - result = result.expressionSemantic(sc); - return result; - } - // Convert to IndexExp - if (ae.arguments.length == 1) - { - result = new IndexExp(ae.loc, ae.e1, (*ae.arguments)[0]); - result = result.expressionSemantic(sc); - return result; - } - } break; - } - if (search_function(ad, Id.index)) + if (search_function(ad, Id.opIndexUnary)) { // Deal with $ result = resolveOpDollar(sc, ae, &e0); - if (!result) // a[i..j] might be: a.opSlice(i, j) + if (!result) // op(a[i..j]) might be: a.opSliceUnary!(op)(i, j) goto Lfallback; if (result.op == EXP.error) return result; - /* Rewrite e1[arguments] as: - * e1.opIndex(arguments) - */ + /* Rewrite op(a[arguments]) as: + * a.opIndexUnary!(op)(arguments) + */ Expressions* a = ae.arguments.copy(); - result = new DotIdExp(ae.loc, ae.e1, Id.index); - result = new CallExp(ae.loc, result, a); - if (maybeSlice) // a[] might be: a.opSlice() + Objects* tiargs = opToArg(sc, e.op); + result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opIndexUnary, tiargs); + result = new CallExp(e.loc, result, a); + if (maybeSlice) // op(a[]) might be: a.opSliceUnary!(op)() result = result.trySemantic(sc); else result = result.expressionSemantic(sc); @@ -504,36 +224,24 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) } } Lfallback: - if (maybeSlice && ae.e1.op == EXP.type) - { - result = new SliceExp(ae.loc, ae.e1, ie); - result = result.expressionSemantic(sc); - result = Expression.combine(e0, result); - return result; - } - if (maybeSlice && search_function(ad, Id.slice)) + if (maybeSlice && search_function(ad, Id.opSliceUnary)) { // Deal with $ result = resolveOpDollar(sc, ae, ie, &e0); - if (result.op == EXP.error) - { - if (!e0 && !search_function(ad, Id.dollar)) { - ae.loc.errorSupplemental("Aggregate declaration '%s' does not define 'opDollar'", ae.e1.toChars()); - } return result; - } - /* Rewrite a[i..j] as: - * a.opSlice(i, j) - */ + /* Rewrite op(a[i..j]) as: + * a.opSliceUnary!(op)(i, j) + */ auto a = new Expressions(); if (ie) { a.push(ie.lwr); a.push(ie.upr); } - result = new DotIdExp(ae.loc, ae.e1, Id.slice); - result = new CallExp(ae.loc, result, a); + Objects* tiargs = opToArg(sc, e.op); + result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opSliceUnary, tiargs); + result = new CallExp(e.loc, result, a); result = result.expressionSemantic(sc); result = Expression.combine(e0, result); return result; @@ -541,10 +249,9 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) // Didn't find it. Forward to aliasthis if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type)) { - //printf("att arr e1 = %s\n", this.e1.type.toChars()); /* Rewrite op(a[arguments]) as: - * op(a.aliasthis[arguments]) - */ + * op(a.aliasthis[arguments]) + */ ae.e1 = resolveAliasThis(sc, ae1save, true); if (ae.e1) continue; @@ -553,846 +260,810 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) } ae.e1 = ae1old; // recovery ae.lengthVar = null; - return result; } - - /*********************************************** - * This is mostly the same as UnaryExp::op_overload(), but has - * a different rewrite. - */ - Expression visitCast(CastExp e, Type att = null) + e.e1 = e.e1.expressionSemantic(sc); + e.e1 = resolveProperties(sc, e.e1); + Type att = null; // first cyclic `alias this` type + while (1) { - //printf("CastExp::op_overload() (%s)\n", e.toChars()); - Expression result; - if (AggregateDeclaration ad = isAggregate(e.e1.type)) + if (e.e1.op == EXP.error) { - Dsymbol fd = null; - /* Rewrite as: - * e1.opCast!(T)() + return e.e1; + } + + AggregateDeclaration ad = isAggregate(e.e1.type); + if (!ad) + break; + + Dsymbol fd = null; + /* Rewrite as: + * e1.opUnary!(op)() + */ + fd = search_function(ad, Id.opUnary); + if (fd) + { + Objects* tiargs = opToArg(sc, e.op); + result = new DotTemplateInstanceExp(e.loc, e.e1, fd.ident, tiargs); + result = new CallExp(e.loc, result); + result = result.expressionSemantic(sc); + return result; + } + + // Didn't find it. Forward to aliasthis + if (ad.aliasthis && !isRecursiveAliasThis(att, e.e1.type)) + { + /* Rewrite op(e1) as: + * op(e1.aliasthis) */ - fd = search_function(ad, Id._cast); - if (fd) - { - version (all) - { - // Backwards compatibility with D1 if opCast is a function, not a template - if (fd.isFuncDeclaration()) - { - // Rewrite as: e1.opCast() - return build_overload(e.loc, sc, e.e1, null, fd); - } - } - auto tiargs = new Objects(); - tiargs.push(e.to); - result = new DotTemplateInstanceExp(e.loc, e.e1, fd.ident, tiargs); - result = new CallExp(e.loc, result); - result = result.expressionSemantic(sc); - return result; - } - // Didn't find it. Forward to aliasthis - if (ad.aliasthis && !isRecursiveAliasThis(att, e.e1.type)) + //printf("att una %s e1 = %s\n", EXPtoString(op).ptr, this.e1.type.toChars()); + if (auto e1 = resolveAliasThis(sc, e.e1, true)) { - /* Rewrite op(e1) as: - * op(e1.aliasthis) - */ - if (auto e1 = resolveAliasThis(sc, e.e1, true)) - { - result = e.copy(); - (cast(UnaExp)result).e1 = e1; - result = visitCast(result.isCastExp(), att); - return result; - } + e.e1 = e1; + continue; } + break; } - return result; + break; } + return result; +} - Expression visitBin(BinExp e) +Expression opOverloadArray(ArrayExp ae, Scope* sc) +{ + ae.e1 = ae.e1.expressionSemantic(sc); + ae.e1 = resolveProperties(sc, ae.e1); + Expression ae1old = ae.e1; + const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval); + IntervalExp ie = null; + if (maybeSlice && ae.arguments.length) { - //printf("BinExp::op_overload() (%s)\n", e.toChars()); - Identifier id = opId(e); - Identifier id_r = opId_r(e); - int argsset = 0; - AggregateDeclaration ad1 = isAggregate(e.e1.type); - AggregateDeclaration ad2 = isAggregate(e.e2.type); - if (e.op == EXP.assign && ad1 == ad2) - { - StructDeclaration sd = ad1.isStructDeclaration(); - if (sd && - (!sd.hasIdentityAssign || - /* Do a blit if we can and the rvalue is something like .init, - * where a postblit is not necessary. - */ - (sd.hasBlitAssign && !e.e2.isLvalue()))) - { - /* This is bitwise struct assignment. */ - return null; - } - } - Dsymbol s = null; - Dsymbol s_r = null; - Objects* tiargs = null; - if (e.op == EXP.plusPlus || e.op == EXP.minusMinus) + ie = (*ae.arguments)[0].isIntervalExp(); + } + Expression result; + Type att = null; // first cyclic `alias this` type + while (true) + { + if (ae.e1.op == EXP.error) { - // Bug4099 fix - if (ad1 && search_function(ad1, Id.opUnary)) - return null; + return ae.e1; } - if (e.op != EXP.equal && e.op != EXP.notEqual && e.op != EXP.assign && e.op != EXP.plusPlus && e.op != EXP.minusMinus) + Expression e0 = null; + Expression ae1save = ae.e1; + ae.lengthVar = null; + Type t1b = ae.e1.type.toBasetype(); + AggregateDeclaration ad = isAggregate(t1b); + if (!ad) { - /* Try opBinary and opBinaryRight - */ - if (ad1) + // If the non-aggregate expression ae.e1 is indexable or sliceable, + // convert it to the corresponding concrete expression. + if (isIndexableNonAggregate(t1b) || ae.e1.op == EXP.type) { - s = search_function(ad1, Id.opBinary); - if (s && !s.isTemplateDeclaration()) + // Convert to SliceExp + if (maybeSlice) { - error(e.e1.loc, "`%s.opBinary` isn't a template", e.e1.toChars()); - return ErrorExp.get(); + result = new SliceExp(ae.loc, ae.e1, ie); + result = result.expressionSemantic(sc); + return result; } - } - if (ad2) - { - s_r = search_function(ad2, Id.opBinaryRight); - if (s_r && !s_r.isTemplateDeclaration()) + // Convert to IndexExp + if (ae.arguments.length == 1) { - error(e.e2.loc, "`%s.opBinaryRight` isn't a template", e.e2.toChars()); - return ErrorExp.get(); + result = new IndexExp(ae.loc, ae.e1, (*ae.arguments)[0]); + result = result.expressionSemantic(sc); + return result; } - if (s_r && s_r == s) // https://issues.dlang.org/show_bug.cgi?id=12778 - s_r = null; } - // Set tiargs, the template argument list, which will be the operator string - if (s || s_r) + break; + } + if (search_function(ad, Id.opIndex)) + { + // Deal with $ + result = resolveOpDollar(sc, ae, &e0); + if (!result) // a[i..j] might be: a.opSlice(i, j) + goto Lfallback; + if (result.op == EXP.error) + return result; + /* Rewrite e1[arguments] as: + * e1.opIndex(arguments) + */ + Expressions* a = ae.arguments.copy(); + result = new DotIdExp(ae.loc, ae.e1, Id.opIndex); + result = new CallExp(ae.loc, result, a); + if (maybeSlice) // a[] might be: a.opSlice() + result = result.trySemantic(sc); + else + result = result.expressionSemantic(sc); + if (result) { - id = Id.opBinary; - id_r = Id.opBinaryRight; - tiargs = opToArg(sc, e.op); + return Expression.combine(e0, result); } } - if (!s && !s_r) + Lfallback: + if (maybeSlice && ae.e1.op == EXP.type) + { + result = new SliceExp(ae.loc, ae.e1, ie); + result = result.expressionSemantic(sc); + result = Expression.combine(e0, result); + return result; + } + if (maybeSlice && search_function(ad, Id.opSlice)) { - // Try the D1-style operators, deprecated - if (ad1 && id) + // Deal with $ + result = resolveOpDollar(sc, ae, ie, &e0); + + if (result.op == EXP.error) { - s = search_function(ad1, id); - if (s && id != Id.assign) - { - // @@@DEPRECATED_2.110@@@. - // Deprecated in 2.088, made an error in 2.100 - if (id == Id.postinc || id == Id.postdec) - error(e.loc, "`%s` is obsolete. Use `opUnary(string op)() if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr); - else - error(e.loc, "`%s` is obsolete. Use `opBinary(string op)(...) if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr); - return ErrorExp.get(); + if (!e0 && !search_function(ad, Id.dollar)) { + ae.loc.errorSupplemental("Aggregate declaration '%s' does not define 'opDollar'", ae.e1.toChars()); } + return result; } - if (ad2 && id_r) + /* Rewrite a[i..j] as: + * a.opSlice(i, j) + */ + auto a = new Expressions(); + if (ie) { - s_r = search_function(ad2, id_r); - // https://issues.dlang.org/show_bug.cgi?id=12778 - // If both x.opBinary(y) and y.opBinaryRight(x) found, - // and they are exactly same symbol, x.opBinary(y) should be preferred. - if (s_r && s_r == s) - s_r = null; - if (s_r) - { - // @@@DEPRECATED_2.110@@@. - // Deprecated in 2.088, made an error in 2.100 - error(e.loc, "`%s` is obsolete. Use `opBinaryRight(string op)(...) if (op == \"%s\")` instead.", id_r.toChars(), EXPtoString(e.op).ptr); - return ErrorExp.get(); - } + a.push(ie.lwr); + a.push(ie.upr); } + result = new DotIdExp(ae.loc, ae.e1, Id.opSlice); + result = new CallExp(ae.loc, result, a); + result = result.expressionSemantic(sc); + result = Expression.combine(e0, result); + return result; } - Expressions* args1 = new Expressions(); - Expressions* args2 = new Expressions(); - if (s || s_r) + // Didn't find it. Forward to aliasthis + if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type)) { - /* Try: - * a.opfunc(b) - * b.opfunc_r(a) - * and see which is better. + //printf("att arr e1 = %s\n", this.e1.type.toChars()); + /* Rewrite op(a[arguments]) as: + * op(a.aliasthis[arguments]) */ - args1.setDim(1); - (*args1)[0] = e.e1; - expandTuples(args1); - args2.setDim(1); - (*args2)[0] = e.e2; - expandTuples(args2); - argsset = 1; - MatchAccumulator m; - if (s) - { - functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2)); - if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) - { - return ErrorExp.get(); - } - } - FuncDeclaration lastf = m.lastf; - if (s_r) + ae.e1 = resolveAliasThis(sc, ae1save, true); + if (ae.e1) + continue; + } + break; + } + ae.e1 = ae1old; // recovery + ae.lengthVar = null; + return result; +} + +/*********************************************** + * This is mostly the same as opOverloadUnary but has + * a different rewrite. + */ +Expression opOverloadCast(CastExp e, Scope* sc, Type att = null) +{ + Expression result; + if (AggregateDeclaration ad = isAggregate(e.e1.type)) + { + Dsymbol fd = null; + /* Rewrite as: + * e1.opCast!(T)() + */ + fd = search_function(ad, Id.opCast); + if (fd) + { + version (all) { - functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, ArgumentList(args1)); - if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) + // Backwards compatibility with D1 if opCast is a function, not a template + if (fd.isFuncDeclaration()) { - return ErrorExp.get(); + // Rewrite as: e1.opCast() + return build_overload(e.loc, sc, e.e1, null, fd); } } - if (m.count > 1) - { - // Error, ambiguous - error(e.loc, "overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars()); - } - else if (m.last == MATCH.nomatch) - { - if (tiargs) - goto L1; - m.lastf = null; - } - if (e.op == EXP.plusPlus || e.op == EXP.minusMinus) - { - // Kludge because operator overloading regards e++ and e-- - // as unary, but it's implemented as a binary. - // Rewrite (e1 ++ e2) as e1.postinc() - // Rewrite (e1 -- e2) as e1.postdec() - return build_overload(e.loc, sc, e.e1, null, m.lastf ? m.lastf : s); - } - else if (lastf && m.lastf == lastf || !s_r && m.last == MATCH.nomatch) - { - // Rewrite (e1 op e2) as e1.opfunc(e2) - return build_overload(e.loc, sc, e.e1, e.e2, m.lastf ? m.lastf : s); - } - else - { - // Rewrite (e1 op e2) as e2.opfunc_r(e1) - return build_overload(e.loc, sc, e.e2, e.e1, m.lastf ? m.lastf : s_r); - } + auto tiargs = new Objects(); + tiargs.push(e.to); + result = new DotTemplateInstanceExp(e.loc, e.e1, fd.ident, tiargs); + result = new CallExp(e.loc, result); + result = result.expressionSemantic(sc); + return result; } - L1: - version (all) + // Didn't find it. Forward to aliasthis + if (ad.aliasthis && !isRecursiveAliasThis(att, e.e1.type)) { - // Retained for D1 compatibility - if (isCommutative(e.op) && !tiargs) + /* Rewrite op(e1) as: + * op(e1.aliasthis) + */ + if (auto e1 = resolveAliasThis(sc, e.e1, true)) { - s = null; - s_r = null; - if (ad1 && id_r) - { - s_r = search_function(ad1, id_r); - } - if (ad2 && id) - { - s = search_function(ad2, id); - if (s && s == s_r) // https://issues.dlang.org/show_bug.cgi?id=12778 - s = null; - } - if (s || s_r) - { - /* Try: - * a.opfunc_r(b) - * b.opfunc(a) - * and see which is better. - */ - if (!argsset) - { - args1.setDim(1); - (*args1)[0] = e.e1; - expandTuples(args1); - args2.setDim(1); - (*args2)[0] = e.e2; - expandTuples(args2); - } - MatchAccumulator m; - if (s_r) - { - functionResolve(m, s_r, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2)); - if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) - { - return ErrorExp.get(); - } - } - FuncDeclaration lastf = m.lastf; - if (s) - { - functionResolve(m, s, e.loc, sc, tiargs, e.e2.type, ArgumentList(args1)); - if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) - { - return ErrorExp.get(); - } - } - if (m.count > 1) - { - // Error, ambiguous - error(e.loc, "overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars()); - } - else if (m.last == MATCH.nomatch) - { - m.lastf = null; - } - - if (lastf && m.lastf == lastf || !s && m.last == MATCH.nomatch) - { - // Rewrite (e1 op e2) as e1.opfunc_r(e2) - return build_overload(e.loc, sc, e.e1, e.e2, m.lastf ? m.lastf : s_r); - } - else - { - // Rewrite (e1 op e2) as e2.opfunc(e1) - Expression result = build_overload(e.loc, sc, e.e2, e.e1, m.lastf ? m.lastf : s); - // When reversing operands of comparison operators, - // need to reverse the sense of the op - if (pop) - *pop = reverseRelation(e.op); - return result; - } - } + result = e.copy(); + (cast(UnaExp)result).e1 = e1; + result = opOverloadCast(result.isCastExp(), sc, att); + return result; } } + } + return result; +} - Expression rewrittenLhs; - if (!(e.op == EXP.assign && ad2 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943 +// When no operator overload functions are found for `e`, recursively try with `alias this` +// Returns: `null` when still no overload found, otherwise resolved lowering +Expression binAliasThis(BinExp e, Scope* sc, Type[2] aliasThisStop) +{ + AggregateDeclaration ad1 = isAggregate(e.e1.type); + AggregateDeclaration ad2 = isAggregate(e.e2.type); + Expression rewrittenLhs; + if (!(e.op == EXP.assign && ad2 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943 + { + if (Expression result = checkAliasThisForLhs(ad1, sc, e, aliasThisStop)) { - if (Expression result = checkAliasThisForLhs(ad1, sc, e)) - { - /* https://issues.dlang.org/show_bug.cgi?id=19441 - * - * alias this may not be used for partial assignment. - * If a struct has a single member which is aliased this - * directly or aliased to a ref getter function that returns - * the mentioned member, then alias this may be - * used since the object will be fully initialised. - * If the struct is nested, the context pointer is considered - * one of the members, hence the `ad1.fields.length == 2 && ad1.vthis` - * condition. - */ - if (result.op != EXP.assign) - return result; // i.e: Rewrote `e1 = e2` -> `e1(e2)` + /* https://issues.dlang.org/show_bug.cgi?id=19441 + * + * alias this may not be used for partial assignment. + * If a struct has a single member which is aliased this + * directly or aliased to a ref getter function that returns + * the mentioned member, then alias this may be + * used since the object will be fully initialised. + * If the struct is nested, the context pointer is considered + * one of the members, hence the `ad1.fields.length == 2 && ad1.vthis` + * condition. + */ + if (result.op != EXP.assign) + return result; // i.e: Rewrote `e1 = e2` -> `e1(e2)` - auto ae = result.isAssignExp(); - if (ae.e1.op != EXP.dotVariable) - return result; // i.e: Rewrote `e1 = e2` -> `e1() = e2` + auto ae = result.isAssignExp(); + if (ae.e1.op != EXP.dotVariable) + return result; // i.e: Rewrote `e1 = e2` -> `e1() = e2` - auto dve = ae.e1.isDotVarExp(); - if (auto ad = dve.var.isMember2()) + auto dve = ae.e1.isDotVarExp(); + if (auto ad = dve.var.isMember2()) + { + // i.e: Rewrote `e1 = e2` -> `e1.some.var = e2` + // Ensure that `var` is the only field member in `ad` + if (ad.fields.length == 1 || (ad.fields.length == 2 && ad.vthis)) { - // i.e: Rewrote `e1 = e2` -> `e1.some.var = e2` - // Ensure that `var` is the only field member in `ad` - if (ad.fields.length == 1 || (ad.fields.length == 2 && ad.vthis)) - { - if (dve.var == ad.aliasthis.sym) - return result; - } + if (dve.var == ad.aliasthis.sym) + return result; } - rewrittenLhs = ae.e1; } + rewrittenLhs = ae.e1; } - if (!(e.op == EXP.assign && ad1 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943 - { - if (Expression result = checkAliasThisForRhs(ad2, sc, e)) - return result; - } - if (rewrittenLhs) - { - error(e.loc, "cannot use `alias this` to partially initialize variable `%s` of type `%s`. Use `%s`", - e.e1.toChars(), ad1.toChars(), rewrittenLhs.toChars()); - return ErrorExp.get(); - } - return null; } - - Expression visitEqual(EqualExp e) + if (!(e.op == EXP.assign && ad1 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943 { - //printf("EqualExp::op_overload() (%s)\n", e.toChars()); - Type t1 = e.e1.type.toBasetype(); - Type t2 = e.e2.type.toBasetype(); + if (Expression result = checkAliasThisForRhs(ad2, sc, e, aliasThisStop)) + return result; + } + if (rewrittenLhs) + { + error(e.loc, "cannot use `alias this` to partially initialize variable `%s` of type `%s`. Use `%s`", + e.e1.toChars(), ad1.toChars(), rewrittenLhs.toChars()); + return ErrorExp.get(); + } + return null; +} - /* Array equality is handled by expressionSemantic() potentially - * lowering to object.__equals(), which takes care of overloaded - * operators for the element types. - */ - if ((t1.ty == Tarray || t1.ty == Tsarray) && - (t2.ty == Tarray || t2.ty == Tsarray)) +Expression opOverloadAssign(AssignExp e, Scope* sc, Type[2] aliasThisStop) +{ + AggregateDeclaration ad1 = isAggregate(e.e1.type); + AggregateDeclaration ad2 = isAggregate(e.e2.type); + if (ad1 == ad2) + { + StructDeclaration sd = ad1.isStructDeclaration(); + if (sd && + (!sd.hasIdentityAssign || + /* Do a blit if we can and the rvalue is something like .init, + * where a postblit is not necessary. + */ + (sd.hasBlitAssign && !e.e2.isLvalue()))) { + /* This is bitwise struct assignment. */ return null; } + } + Dsymbol s = search_function(ad1, Id.opAssign); - /* Check for class equality with null literal or typeof(null). - */ - if (t1.ty == Tclass && e.e2.op == EXP.null_ || - t2.ty == Tclass && e.e1.op == EXP.null_) - { - error(e.loc, "use `%s` instead of `%s` when comparing with `null`", - EXPtoString(e.op == EXP.equal ? EXP.identity : EXP.notIdentity).ptr, - EXPtoString(e.op).ptr); - return ErrorExp.get(); - } - if (t1.ty == Tclass && t2.ty == Tnull || - t1.ty == Tnull && t2.ty == Tclass) - { - // Comparing a class with typeof(null) should not call opEquals - return null; - } + bool choseReverse; + if (auto result = pickBestBinaryOverload(sc, null, s, null, e, choseReverse)) + return result; - /* Check for class equality. - */ - if (t1.ty == Tclass && t2.ty == Tclass) - { - ClassDeclaration cd1 = t1.isClassHandle(); - ClassDeclaration cd2 = t2.isClassHandle(); - if (!(cd1.classKind == ClassKind.cpp || cd2.classKind == ClassKind.cpp)) - { - /* Rewrite as: - * .object.opEquals(e1, e2) - */ - if (!ClassDeclaration.object) - { - error(e.loc, "cannot compare classes for equality because `object.Object` was not declared"); - return null; - } + return binAliasThis(e, sc, aliasThisStop); +} - Expression e1x = e.e1; - Expression e2x = e.e2; +Expression opOverloadBinary(BinExp e, Scope* sc, Type[2] aliasThisStop) +{ + if (Expression err = binSemanticProp(e, sc)) + return err; - /* The explicit cast is necessary for interfaces - * https://issues.dlang.org/show_bug.cgi?id=4088 - */ - Type to = ClassDeclaration.object.getType(); - if (cd1.isInterfaceDeclaration()) - e1x = new CastExp(e.loc, e.e1, t1.isMutable() ? to : to.constOf()); - if (cd2.isInterfaceDeclaration()) - e2x = new CastExp(e.loc, e.e2, t2.isMutable() ? to : to.constOf()); - - Expression result = new IdentifierExp(e.loc, Id.empty); - result = new DotIdExp(e.loc, result, Id.object); - result = new DotIdExp(e.loc, result, Id.eq); - result = new CallExp(e.loc, result, e1x, e2x); - if (e.op == EXP.notEqual) - result = new NotExp(e.loc, result); - result = result.expressionSemantic(sc); - return result; - } - } + AggregateDeclaration ad1 = isAggregate(e.e1.type); + AggregateDeclaration ad2 = isAggregate(e.e2.type); + + // Try opBinary and opBinaryRight + Dsymbol s = search_function(ad1, Id.opBinary); + if (s && !s.isTemplateDeclaration()) + { + error(e.e1.loc, "`%s.opBinary` isn't a template", e.e1.toChars()); + return ErrorExp.get(); + } + + Dsymbol s_r = search_function(ad2, Id.opBinaryRight); + if (s_r && !s_r.isTemplateDeclaration()) + { + error(e.e2.loc, "`%s.opBinaryRight` isn't a template", e.e2.toChars()); + return ErrorExp.get(); + } + if (s_r && s_r == s) // https://issues.dlang.org/show_bug.cgi?id=12778 + s_r = null; + + bool choseReverse; + if (auto res = pickBestBinaryOverload(sc, opToArg(sc, e.op), s, s_r, e, choseReverse)) + return res; + + return binAliasThis(e, sc, aliasThisStop); +} + +Expression opOverloadEqual(EqualExp e, Scope* sc, Type[2] aliasThisStop) +{ + Type t1 = e.e1.type.toBasetype(); + Type t2 = e.e2.type.toBasetype(); + + /* Array equality is handled by expressionSemantic() potentially + * lowering to object.__equals(), which takes care of overloaded + * operators for the element types. + */ + if ((t1.ty == Tarray || t1.ty == Tsarray) && + (t2.ty == Tarray || t2.ty == Tsarray)) + { + return null; + } + + /* Check for class equality with null literal or typeof(null). + */ + if (t1.ty == Tclass && e.e2.op == EXP.null_ || + t2.ty == Tclass && e.e1.op == EXP.null_) + { + error(e.loc, "use `%s` instead of `%s` when comparing with `null`", + EXPtoString(e.op == EXP.equal ? EXP.identity : EXP.notIdentity).ptr, + EXPtoString(e.op).ptr); + return ErrorExp.get(); + } + if (t1.ty == Tclass && t2.ty == Tnull || + t1.ty == Tnull && t2.ty == Tclass) + { + // Comparing a class with typeof(null) should not call opEquals + return null; + } - if (Expression result = compare_overload(e, sc, Id.eq, null)) + /* Check for class equality. + */ + if (t1.ty == Tclass && t2.ty == Tclass) + { + ClassDeclaration cd1 = t1.isClassHandle(); + ClassDeclaration cd2 = t2.isClassHandle(); + if (!(cd1.classKind == ClassKind.cpp || cd2.classKind == ClassKind.cpp)) { - if (lastComma(result).op == EXP.call && e.op == EXP.notEqual) + /* Rewrite as: + * .object.opEquals(e1, e2) + */ + if (!ClassDeclaration.object) { - result = new NotExp(result.loc, result); - result = result.expressionSemantic(sc); + error(e.loc, "cannot compare classes for equality because `object.Object` was not declared"); + return null; } + + Expression e1x = e.e1; + Expression e2x = e.e2; + + /* The explicit cast is necessary for interfaces + * https://issues.dlang.org/show_bug.cgi?id=4088 + */ + Type to = ClassDeclaration.object.getType(); + if (cd1.isInterfaceDeclaration()) + e1x = new CastExp(e.loc, e.e1, t1.isMutable() ? to : to.constOf()); + if (cd2.isInterfaceDeclaration()) + e2x = new CastExp(e.loc, e.e2, t2.isMutable() ? to : to.constOf()); + + Expression result = new IdentifierExp(e.loc, Id.empty); + result = new DotIdExp(e.loc, result, Id.object); + result = new DotIdExp(e.loc, result, Id.opEquals); + result = new CallExp(e.loc, result, e1x, e2x); + if (e.op == EXP.notEqual) + result = new NotExp(e.loc, result); + result = result.expressionSemantic(sc); return result; } + } + + EXP cmpOp; + if (Expression result = compare_overload(e, sc, Id.opEquals, cmpOp, aliasThisStop)) + { + if (lastComma(result).op == EXP.call && e.op == EXP.notEqual) + { + result = new NotExp(result.loc, result); + result = result.expressionSemantic(sc); + } + return result; + } - /* Check for pointer equality. + /* Check for pointer equality. + */ + if (t1.ty == Tpointer || t2.ty == Tpointer) + { + /* Rewrite: + * ptr1 == ptr2 + * as: + * ptr1 is ptr2 + * + * This is just a rewriting for deterministic AST representation + * as the backend input. */ - if (t1.ty == Tpointer || t2.ty == Tpointer) + auto op2 = e.op == EXP.equal ? EXP.identity : EXP.notIdentity; + Expression r = new IdentityExp(op2, e.loc, e.e1, e.e2); + return r.expressionSemantic(sc); + } + + /* Check for struct equality without opEquals. + */ + if (t1.ty == Tstruct && t2.ty == Tstruct) + { + auto sd = t1.isTypeStruct().sym; + if (sd != t2.isTypeStruct().sym) + return null; + + import dmd.clone : needOpEquals; + if (!sc.previews.fieldwise && !needOpEquals(sd)) { - /* Rewrite: - * ptr1 == ptr2 - * as: - * ptr1 is ptr2 - * - * This is just a rewriting for deterministic AST representation - * as the backend input. - */ + // Use bitwise equality. auto op2 = e.op == EXP.equal ? EXP.identity : EXP.notIdentity; Expression r = new IdentityExp(op2, e.loc, e.e1, e.e2); return r.expressionSemantic(sc); } - /* Check for struct equality without opEquals. + /* Do memberwise equality. + * https://dlang.org/spec/expression.html#equality_expressions + * Rewrite: + * e1 == e2 + * as: + * e1.tupleof == e2.tupleof + * + * If sd is a nested struct, and if it's nested in a class, it will + * also compare the parent class's equality. Otherwise, compares + * the identity of parent context through void*. */ - if (t1.ty == Tstruct && t2.ty == Tstruct) - { - auto sd = t1.isTypeStruct().sym; - if (sd != t2.isTypeStruct().sym) - return null; - - import dmd.clone : needOpEquals; - if (!sc.previews.fieldwise && !needOpEquals(sd)) - { - // Use bitwise equality. - auto op2 = e.op == EXP.equal ? EXP.identity : EXP.notIdentity; - Expression r = new IdentityExp(op2, e.loc, e.e1, e.e2); - return r.expressionSemantic(sc); - } + e = e.copy().isEqualExp(); + e.e1 = new DotIdExp(e.loc, e.e1, Id._tupleof); + e.e2 = new DotIdExp(e.loc, e.e2, Id._tupleof); + + auto sc2 = sc.push(); + sc2.noAccessCheck = true; + Expression r = e.expressionSemantic(sc2); + sc2.pop(); + return r; + } - /* Do memberwise equality. - * https://dlang.org/spec/expression.html#equality_expressions - * Rewrite: - * e1 == e2 - * as: - * e1.tupleof == e2.tupleof - * - * If sd is a nested struct, and if it's nested in a class, it will - * also compare the parent class's equality. Otherwise, compares - * the identity of parent context through void*. - */ - e = e.copy().isEqualExp(); - e.e1 = new DotIdExp(e.loc, e.e1, Id._tupleof); - e.e2 = new DotIdExp(e.loc, e.e2, Id._tupleof); - - auto sc2 = sc.push(); - sc2.noAccessCheck = true; - Expression r = e.expressionSemantic(sc2); - sc2.pop(); - return r; + /* Check for tuple equality. + */ + if (e.e1.op == EXP.tuple && e.e2.op == EXP.tuple) + { + auto tup1 = e.e1.isTupleExp(); + auto tup2 = e.e2.isTupleExp(); + size_t dim = tup1.exps.length; + if (dim != tup2.exps.length) + { + error(e.loc, "mismatched sequence lengths, `%d` and `%d`", + cast(int)dim, cast(int)tup2.exps.length); + return ErrorExp.get(); } - /* Check for tuple equality. - */ - if (e.e1.op == EXP.tuple && e.e2.op == EXP.tuple) + Expression result; + if (dim == 0) + { + // zero-length tuple comparison should always return true or false. + result = IntegerExp.createBool(e.op == EXP.equal); + } + else { - auto tup1 = e.e1.isTupleExp(); - auto tup2 = e.e2.isTupleExp(); - size_t dim = tup1.exps.length; - if (dim != tup2.exps.length) + for (size_t i = 0; i < dim; i++) { - error(e.loc, "mismatched sequence lengths, `%d` and `%d`", - cast(int)dim, cast(int)tup2.exps.length); - return ErrorExp.get(); + auto ex1 = (*tup1.exps)[i]; + auto ex2 = (*tup2.exps)[i]; + auto eeq = new EqualExp(e.op, e.loc, ex1, ex2); + + if (!result) + result = eeq; + else if (e.op == EXP.equal) + result = new LogicalExp(e.loc, EXP.andAnd, result, eeq); + else + result = new LogicalExp(e.loc, EXP.orOr, result, eeq); } + assert(result); + } + result = Expression.combine(tup1.e0, tup2.e0, result); + result = result.expressionSemantic(sc); - Expression result; - if (dim == 0) - { - // zero-length tuple comparison should always return true or false. - result = IntegerExp.createBool(e.op == EXP.equal); - } - else - { - for (size_t i = 0; i < dim; i++) - { - auto ex1 = (*tup1.exps)[i]; - auto ex2 = (*tup2.exps)[i]; - auto eeq = new EqualExp(e.op, e.loc, ex1, ex2); - - if (!result) - result = eeq; - else if (e.op == EXP.equal) - result = new LogicalExp(e.loc, EXP.andAnd, result, eeq); - else - result = new LogicalExp(e.loc, EXP.orOr, result, eeq); - } - assert(result); - } - result = Expression.combine(tup1.e0, tup2.e0, result); - result = result.expressionSemantic(sc); + return result; + } + return null; +} - return result; - } +Expression opOverloadCmp(CmpExp exp, Scope* sc, Type[2] aliasThisStop) +{ + //printf("CmpExp:: () (%s)\n", e.toChars()); + EXP cmpOp = exp.op; + auto e = compare_overload(exp, sc, Id.opCmp, cmpOp, aliasThisStop); + if (!e) return null; + + if (!e.type.isScalar() && e.type.equals(exp.e1.type)) + { + error(e.loc, "recursive `opCmp` expansion"); + return ErrorExp.get(); } + if (e.op != EXP.call) + return e; - Expression visitCmp(CmpExp e) + Type t1 = exp.e1.type.toBasetype(); + Type t2 = exp.e2.type.toBasetype(); + if (t1.ty != Tclass || t2.ty != Tclass) { - //printf("CmpExp:: () (%s)\n", e.toChars()); - return compare_overload(e, sc, Id.cmp, pop); + return new CmpExp(cmpOp, exp.loc, e, IntegerExp.literal!0).expressionSemantic(sc); } - /********************************* - * Operator overloading for op= - */ - Expression visitBinAssign(BinAssignExp e) + // Lower to object.__cmp(e1, e2) + Expression cl = new IdentifierExp(exp.loc, Id.empty); + cl = new DotIdExp(exp.loc, cl, Id.object); + cl = new DotIdExp(exp.loc, cl, Id.__cmp); + cl = cl.expressionSemantic(sc); + + auto arguments = new Expressions(); + // Check if op_overload found a better match by calling e2.opCmp(e1) + // If the operands were swapped, then the result must be reversed + // e1.opCmp(e2) == -e2.opCmp(e1) + // cmpop takes care of this + if (exp.op == cmpOp) + { + arguments.push(exp.e1); + arguments.push(exp.e2); + } + else + { + // Use better match found by op_overload + arguments.push(exp.e2); + arguments.push(exp.e1); + } + + cl = new CallExp(e.loc, cl, arguments); + cl = new CmpExp(cmpOp, exp.loc, cl, new IntegerExp(0)); + return cl.expressionSemantic(sc); +} + +/********************************* + * Operator overloading for op= + */ +Expression opOverloadBinaryAssign(BinAssignExp e, Scope* sc, Type[2] aliasThisStop) +{ + if (auto ae = e.e1.isArrayExp()) { - //printf("BinAssignExp::op_overload() (%s)\n", e.toChars()); - if (auto ae = e.e1.isArrayExp()) + ae.e1 = ae.e1.expressionSemantic(sc); + ae.e1 = resolveProperties(sc, ae.e1); + Expression ae1old = ae.e1; + const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval); + IntervalExp ie = null; + if (maybeSlice && ae.arguments.length) { - ae.e1 = ae.e1.expressionSemantic(sc); - ae.e1 = resolveProperties(sc, ae.e1); - Expression ae1old = ae.e1; - const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval); - IntervalExp ie = null; - if (maybeSlice && ae.arguments.length) + ie = (*ae.arguments)[0].isIntervalExp(); + } + Type att = null; // first cyclic `alias this` type + while (true) + { + if (ae.e1.op == EXP.error) { - ie = (*ae.arguments)[0].isIntervalExp(); + return ae.e1; } - Type att = null; // first cyclic `alias this` type - while (true) + Expression e0 = null; + Expression ae1save = ae.e1; + ae.lengthVar = null; + Type t1b = ae.e1.type.toBasetype(); + AggregateDeclaration ad = isAggregate(t1b); + if (!ad) + break; + if (search_function(ad, Id.opIndexOpAssign)) { - if (ae.e1.op == EXP.error) - { - return ae.e1; - } - Expression e0 = null; - Expression ae1save = ae.e1; - ae.lengthVar = null; - Type t1b = ae.e1.type.toBasetype(); - AggregateDeclaration ad = isAggregate(t1b); - if (!ad) - break; - if (search_function(ad, Id.opIndexOpAssign)) - { - // Deal with $ - Expression result = resolveOpDollar(sc, ae, &e0); - if (!result) // (a[i..j] op= e2) might be: a.opSliceOpAssign!(op)(e2, i, j) - goto Lfallback; - if (result.op == EXP.error) - return result; - result = e.e2.expressionSemantic(sc); - if (result.op == EXP.error) - return result; - e.e2 = result; - /* Rewrite a[arguments] op= e2 as: - * a.opIndexOpAssign!(op)(e2, arguments) - */ - Expressions* a = ae.arguments.copy(); - a.insert(0, e.e2); - Objects* tiargs = opToArg(sc, e.op); - result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opIndexOpAssign, tiargs); - result = new CallExp(e.loc, result, a); - if (maybeSlice) // (a[] op= e2) might be: a.opSliceOpAssign!(op)(e2) - result = result.trySemantic(sc); - else - result = result.expressionSemantic(sc); - if (result) - { - return Expression.combine(e0, result); - } - } - Lfallback: - if (maybeSlice && search_function(ad, Id.opSliceOpAssign)) - { - // Deal with $ - Expression result = resolveOpDollar(sc, ae, ie, &e0); - if (result.op == EXP.error) - return result; - result = e.e2.expressionSemantic(sc); - if (result.op == EXP.error) - return result; - e.e2 = result; - /* Rewrite (a[i..j] op= e2) as: - * a.opSliceOpAssign!(op)(e2, i, j) - */ - auto a = new Expressions(); - a.push(e.e2); - if (ie) - { - a.push(ie.lwr); - a.push(ie.upr); - } - Objects* tiargs = opToArg(sc, e.op); - result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opSliceOpAssign, tiargs); - result = new CallExp(e.loc, result, a); - result = result.expressionSemantic(sc); - result = Expression.combine(e0, result); + // Deal with $ + Expression result = resolveOpDollar(sc, ae, &e0); + if (!result) // (a[i..j] op= e2) might be: a.opSliceOpAssign!(op)(e2, i, j) + goto Lfallback; + if (result.op == EXP.error) return result; - } - // Didn't find it. Forward to aliasthis - if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type)) + result = e.e2.expressionSemantic(sc); + if (result.op == EXP.error) + return result; + e.e2 = result; + /* Rewrite a[arguments] op= e2 as: + * a.opIndexOpAssign!(op)(e2, arguments) + */ + Expressions* a = ae.arguments.copy(); + a.insert(0, e.e2); + Objects* tiargs = opToArg(sc, e.op); + result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opIndexOpAssign, tiargs); + result = new CallExp(e.loc, result, a); + if (maybeSlice) // (a[] op= e2) might be: a.opSliceOpAssign!(op)(e2) + result = result.trySemantic(sc); + else + result = result.expressionSemantic(sc); + if (result) { - /* Rewrite (a[arguments] op= e2) as: - * a.aliasthis[arguments] op= e2 - */ - ae.e1 = resolveAliasThis(sc, ae1save, true); - if (ae.e1) - continue; + return Expression.combine(e0, result); } - break; } - ae.e1 = ae1old; // recovery - ae.lengthVar = null; - } - Expression result = e.binSemanticProp(sc); - if (result) - return result; - // Don't attempt 'alias this' if an error occurred - if (e.e1.type.ty == Terror || e.e2.type.ty == Terror) - { - return ErrorExp.get(); - } - Identifier id = opId(e); - Expressions* args2 = new Expressions(); - AggregateDeclaration ad1 = isAggregate(e.e1.type); - Dsymbol s = null; - Objects* tiargs = null; - /* Try opOpAssign - */ - if (ad1) - { - s = search_function(ad1, Id.opOpAssign); - if (s && !s.isTemplateDeclaration()) + Lfallback: + if (maybeSlice && search_function(ad, Id.opSliceOpAssign)) { - error(e.loc, "`%s.opOpAssign` isn't a template", e.e1.toChars()); - return ErrorExp.get(); + // Deal with $ + Expression result = resolveOpDollar(sc, ae, ie, &e0); + if (result.op == EXP.error) + return result; + result = e.e2.expressionSemantic(sc); + if (result.op == EXP.error) + return result; + e.e2 = result; + /* Rewrite (a[i..j] op= e2) as: + * a.opSliceOpAssign!(op)(e2, i, j) + */ + auto a = new Expressions(); + a.push(e.e2); + if (ie) + { + a.push(ie.lwr); + a.push(ie.upr); + } + Objects* tiargs = opToArg(sc, e.op); + result = new DotTemplateInstanceExp(e.loc, ae.e1, Id.opSliceOpAssign, tiargs); + result = new CallExp(e.loc, result, a); + result = result.expressionSemantic(sc); + result = Expression.combine(e0, result); + return result; } - } - // Set tiargs, the template argument list, which will be the operator string - if (s) - { - id = Id.opOpAssign; - tiargs = opToArg(sc, e.op); - } - - // Try D1-style operator overload, deprecated - if (!s && ad1 && id) - { - s = search_function(ad1, id); - if (s) + // Didn't find it. Forward to aliasthis + if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type)) { - // @@@DEPRECATED_2.110@@@. - // Deprecated in 2.088, made an error in 2.100 - scope char[] op = EXPtoString(e.op).dup; - op[$-1] = '\0'; // remove trailing `=` - error(e.loc, "`%s` is obsolete. Use `opOpAssign(string op)(...) if (op == \"%s\")` instead.", id.toChars(), op.ptr); - return ErrorExp.get(); + /* Rewrite (a[arguments] op= e2) as: + * a.aliasthis[arguments] op= e2 + */ + ae.e1 = resolveAliasThis(sc, ae1save, true); + if (ae.e1) + continue; } + break; } + ae.e1 = ae1old; // recovery + ae.lengthVar = null; + } + Expression result = e.binSemanticProp(sc); + if (result) + return result; + // Don't attempt 'alias this' if an error occurred + if (e.e1.type.ty == Terror || e.e2.type.ty == Terror) + { + return ErrorExp.get(); + } + AggregateDeclaration ad1 = isAggregate(e.e1.type); + Dsymbol s = search_function(ad1, Id.opOpAssign); + if (s && !s.isTemplateDeclaration()) + { + error(e.loc, "`%s.opOpAssign` isn't a template", e.e1.toChars()); + return ErrorExp.get(); + } - if (s) - { - /* Try: - * a.opOpAssign(b) - */ - args2.setDim(1); - (*args2)[0] = e.e2; - expandTuples(args2); - MatchAccumulator m; - functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2)); - if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) - { - return ErrorExp.get(); - } - if (m.count > 1) - { - // Error, ambiguous - error(e.loc, "overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars()); - } - else if (m.last == MATCH.nomatch) - { - if (tiargs) - goto L1; - m.lastf = null; - } - // Rewrite (e1 op e2) as e1.opOpAssign(e2) - return build_overload(e.loc, sc, e.e1, e.e2, m.lastf ? m.lastf : s); - } - L1: - result = checkAliasThisForLhs(ad1, sc, e); - if (result || !s) // no point in trying Rhs alias-this if there's no overload of any kind in lhs - return result; + bool choseReverse; + if (auto res = pickBestBinaryOverload(sc, opToArg(sc, e.op), s, null, e, choseReverse)) + return res; - return checkAliasThisForRhs(isAggregate(e.e2.type), sc, e); - } + result = checkAliasThisForLhs(ad1, sc, e, aliasThisStop); + if (result || !s) // no point in trying Rhs alias-this if there's no overload of any kind in lhs + return result; - if (pop) - *pop = e.op; + return checkAliasThisForRhs(isAggregate(e.e2.type), sc, e, aliasThisStop); +} - switch (e.op) - { - case EXP.cast_ : return visitCast(e.isCastExp()); - case EXP.array : return visitArray(e.isArrayExp()); +/** +Given symbols `s` and `s_r`, try to instantiate `e.e1.s!tiargs(e.e2)` and `e.e2.s_r!tiargs(e.e1)`, +and return the one with the best match level. + +Params: + sc = scope + tiargs = (optional) template arguments to instantiate symbols with + s = (optional) symbol of straightforward template (e.g. opBinary) + s_r = (optional) symbol of reversed template (e.g. opBinaryRight) + e = binary expression being overloaded, supplying arguments to the function calls + choseReverse = set to true when `s_r` was chosen instead of `s` +Returns: + Resulting operator overload function call, or `null` if neither symbol worked +*/ +private Expression pickBestBinaryOverload(Scope* sc, Objects* tiargs, Dsymbol s, Dsymbol s_r, BinExp e, out bool choseReverse) +{ + if (!s && !s_r) + return null; - case EXP.notEqual : - case EXP.equal : return visitEqual(e.isEqualExp()); + Expressions* args1 = new Expressions(1); + (*args1)[0] = e.e1; + expandTuples(args1); + Expressions* args2 = new Expressions(1); + (*args2)[0] = e.e2; + expandTuples(args2); + MatchAccumulator m; - case EXP.lessOrEqual : - case EXP.greaterThan : - case EXP.greaterOrEqual: - case EXP.lessThan : return visitCmp(cast(CmpExp)e); + if (s) + { + functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2)); + if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) + return ErrorExp.get(); + } + FuncDeclaration lastf = m.lastf; + int count = m.count; + if (s_r) + { + functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, ArgumentList(args1)); + if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) + return ErrorExp.get(); + } + if (m.count > 1) + { + /* The following if says "not ambiguous" if there's one match + * from s and one from s_r, in which case we pick s. + * This doesn't follow the spec, but is a workaround for the case + * where opEquals was generated from templates and we cannot figure + * out if both s and s_r came from the same declaration or not. + * The test case is: + * import std.typecons; + * void main() { + * assert(tuple("has a", 2u) == tuple("has a", 1)); + * } + */ + if (!(m.lastf == lastf && m.count == 2 && count == 1)) + { + // Error, ambiguous + error(e.loc, "overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars()); + } + } + else if (m.last == MATCH.nomatch) + { + if (tiargs) + return null; + m.lastf = null; + } - default: - if (auto ex = e.isBinAssignExp()) return visitBinAssign(ex); - if (auto ex = e.isBinExp()) return visitBin(ex); - if (auto ex = e.isUnaExp()) return visitUna(ex); - return visit(e); + if (lastf && m.lastf == lastf || !s_r && m.last == MATCH.nomatch) + { + choseReverse = false; + // Rewrite (e1 op e2) as e1.opfunc(e2) + return build_overload(e.loc, sc, e.e1, e.e2, m.lastf ? m.lastf : s); + } + else + { + choseReverse = true; + // Rewrite (e1 op e2) as e2.opfunc_r(e1) + return build_overload(e.loc, sc, e.e2, e.e1, m.lastf ? m.lastf : s_r); } } /****************************************** * Common code for overloading of EqualExp and CmpExp */ -private Expression compare_overload(BinExp e, Scope* sc, Identifier id, EXP* pop) +private Expression compare_overload(BinExp e, Scope* sc, Identifier id, ref EXP cmpOp, Type[2] aliasThisStop) { //printf("BinExp::compare_overload(id = %s) %s\n", id.toChars(), e.toChars()); AggregateDeclaration ad1 = isAggregate(e.e1.type); AggregateDeclaration ad2 = isAggregate(e.e2.type); - Dsymbol s = null; - Dsymbol s_r = null; - if (ad1) - { - s = search_function(ad1, id); - } - if (ad2) + Dsymbol s = search_function(ad1, id); + Dsymbol s_r = search_function(ad2, id); + + if (s == s_r) + s_r = null; + + bool choseReverse; + if (auto res = pickBestBinaryOverload(sc, null, s, s_r, e, choseReverse)) { - s_r = search_function(ad2, id); - if (s == s_r) - s_r = null; - } - Objects* tiargs = null; - if (s || s_r) - { - /* Try: - * a.opEquals(b) - * b.opEquals(a) - * and see which is better. - */ - Expressions* args1 = new Expressions(1); - (*args1)[0] = e.e1; - expandTuples(args1); - Expressions* args2 = new Expressions(1); - (*args2)[0] = e.e2; - expandTuples(args2); - MatchAccumulator m; - if (0 && s && s_r) - { - printf("s : %s\n", s.toPrettyChars()); - printf("s_r: %s\n", s_r.toPrettyChars()); - } - if (s) - { - functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(args2)); - if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) - return ErrorExp.get(); - } - FuncDeclaration lastf = m.lastf; - int count = m.count; - if (s_r) - { - functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, ArgumentList(args1)); - if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) - return ErrorExp.get(); - } - if (m.count > 1) - { - /* The following if says "not ambiguous" if there's one match - * from s and one from s_r, in which case we pick s. - * This doesn't follow the spec, but is a workaround for the case - * where opEquals was generated from templates and we cannot figure - * out if both s and s_r came from the same declaration or not. - * The test case is: - * import std.typecons; - * void main() { - * assert(tuple("has a", 2u) == tuple("has a", 1)); - * } - */ - if (!(m.lastf == lastf && m.count == 2 && count == 1)) - { - // Error, ambiguous - error(e.loc, "overloads `%s` and `%s` both match argument list for `%s`", m.lastf.type.toChars(), m.nextf.type.toChars(), m.lastf.toChars()); - } - } - else if (m.last == MATCH.nomatch) - { - m.lastf = null; - } - Expression result; - if (lastf && m.lastf == lastf || !s_r && m.last == MATCH.nomatch) - { - // Rewrite (e1 op e2) as e1.opfunc(e2) - result = build_overload(e.loc, sc, e.e1, e.e2, m.lastf ? m.lastf : s); - } - else - { - // Rewrite (e1 op e2) as e2.opfunc_r(e1) - result = build_overload(e.loc, sc, e.e2, e.e1, m.lastf ? m.lastf : s_r); - // When reversing operands of comparison operators, - // need to reverse the sense of the op - if (pop) - *pop = reverseRelation(e.op); - } - return result; + if (choseReverse) + cmpOp = reverseRelation(e.op); + return res; } + /* * https://issues.dlang.org/show_bug.cgi?id=16657 * at this point, no matching opEquals was found for structs, @@ -1400,8 +1071,8 @@ private Expression compare_overload(BinExp e, Scope* sc, Identifier id, EXP* pop */ if ((e.op == EXP.equal || e.op == EXP.notEqual) && ad1 == ad2) return null; - Expression result = checkAliasThisForLhs(ad1, sc, e); - return result ? result : checkAliasThisForRhs(isAggregate(e.e2.type), sc, e); + Expression result = checkAliasThisForLhs(ad1, sc, e, aliasThisStop); + return result ? result : checkAliasThisForRhs(isAggregate(e.e2.type), sc, e, aliasThisStop); } /*********************************** @@ -1425,6 +1096,8 @@ Expression build_overload(const ref Loc loc, Scope* sc, Expression ethis, Expres */ Dsymbol search_function(ScopeDsymbol ad, Identifier funcid) { + if (!ad) + return null; if (Dsymbol s = ad.search(Loc.initial, funcid)) { //printf("search_function: s = '%s'\n", s.kind()); diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index b851b9a..2e29762 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -2759,35 +2759,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer error("`new` allocator must be annotated with `@disabled`"); } nextToken(); - - /* @@@DEPRECATED_2.108@@@ - * After deprecation period (2.108), remove all code in the version(all) block. - */ - version (all) - { - auto parameterList = parseParameterList(null); // parameterList ignored - if (parameterList.parameters.length > 0 || parameterList.varargs != VarArg.none) - deprecation("`new` allocator with non-empty parameter list is deprecated"); - auto f = new AST.NewDeclaration(loc, stc); - if (token.value != TOK.semicolon) - { - deprecation("`new` allocator with function definition is deprecated"); - parseContracts(f); // body ignored - f.fbody = null; - f.fensures = null; - f.frequires = null; - } - else - nextToken(); - return f; - } - else - { - check(TOK.leftParenthesis); - check(TOK.rightParenthesis); - check(TOK.semicolon); - return new AST.NewDeclaration(loc, stc); - } + check(TOK.leftParenthesis); + check(TOK.rightParenthesis); + check(TOK.semicolon); + return new AST.NewDeclaration(loc, stc); } /********************************************** @@ -5844,7 +5819,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer case TOK.plusPlus: case TOK.minusMinus: case TOK.new_: - case TOK.delete_: case TOK.delegate_: case TOK.function_: case TOK.typeid_: @@ -8713,15 +8687,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer e = new AST.ComExp(loc, e); break; - case TOK.delete_: - // @@@DEPRECATED_2.109@@@ - // Use of `delete` keyword has been an error since 2.099. - // Remove from the parser after 2.109. - nextToken(); - e = parseUnaryExp(); - e = new AST.DeleteExp(loc, e, false); - break; - case TOK.cast_: // cast(type) expression { nextToken(); @@ -8839,7 +8804,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer case TOK.dot: case TOK.plusPlus: case TOK.minusMinus: - case TOK.delete_: case TOK.new_: case TOK.leftParenthesis: case TOK.identifier: diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d index def7d46..89f612c 100644 --- a/gcc/d/dmd/semantic3.d +++ b/gcc/d/dmd/semantic3.d @@ -270,7 +270,7 @@ private extern(C++) final class Semantic3Visitor : Visitor //{ static int x; if (++x == 2) *(char*)0=0; } //printf("\tlinkage = %d\n", sc.linkage); - if (funcdecl.ident == Id.assign && !funcdecl.inuse) + if (funcdecl.ident == Id.opAssign && !funcdecl.inuse) { if (funcdecl.storage_class & STC.inference) { diff --git a/gcc/d/dmd/tokens.d b/gcc/d/dmd/tokens.d index b499c00..e82a582 100644 --- a/gcc/d/dmd/tokens.d +++ b/gcc/d/dmd/tokens.d @@ -48,7 +48,6 @@ enum TOK : ubyte false_, throw_, new_, - delete_, variable, slice, version_, @@ -459,7 +458,6 @@ private immutable TOK[] keywords = TOK.false_, TOK.cast_, TOK.new_, - TOK.delete_, TOK.throw_, TOK.module_, TOK.pragma_, @@ -680,7 +678,6 @@ extern (C++) struct Token TOK.false_: "false", TOK.cast_: "cast", TOK.new_: "new", - TOK.delete_: "delete", TOK.throw_: "throw", TOK.module_: "module", TOK.pragma_: "pragma", diff --git a/gcc/d/dmd/tokens.h b/gcc/d/dmd/tokens.h index 2a984b4..c12a00b 100644 --- a/gcc/d/dmd/tokens.h +++ b/gcc/d/dmd/tokens.h @@ -54,7 +54,6 @@ enum class TOK : unsigned char false_, throw_, new_, - delete_, variable, slice, version_, diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index ca10db1..65d267f 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -2025,7 +2025,7 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc) } else if (sd.xeq == sd.xerreq) { - if (search_function(sd, Id.eq)) + if (search_function(sd, Id.opEquals)) { .error(loc, "%sAA key type `%s` does not have `bool opEquals(ref const %s) const`", s, sd.toChars(), sd.toChars()); } @@ -2037,7 +2037,7 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc) } else if (!sd.xhash) { - if (search_function(sd, Id.eq)) + if (search_function(sd, Id.opEquals)) { .error(loc, "%sAA key type `%s` should have `extern (D) size_t toHash() const nothrow @safe` if `opEquals` defined", s, sd.toChars()); } @@ -2075,9 +2075,9 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc) __gshared FuncDeclaration fcmp = null; __gshared FuncDeclaration fhash = null; if (!feq) - feq = search_function(ClassDeclaration.object, Id.eq).isFuncDeclaration(); + feq = search_function(ClassDeclaration.object, Id.opEquals).isFuncDeclaration(); if (!fcmp) - fcmp = search_function(ClassDeclaration.object, Id.cmp).isFuncDeclaration(); + fcmp = search_function(ClassDeclaration.object, Id.opCmp).isFuncDeclaration(); if (!fhash) fhash = search_function(ClassDeclaration.object, Id.tohash).isFuncDeclaration(); assert(fcmp && feq && fhash); @@ -3417,7 +3417,7 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden if (s) error(loc, "no property `%s` for type `%s`, did you mean `%s`?", ident.toChars(), mt.toChars(), s.toPrettyChars()); - else if (ident == Id.call && mt.ty == Tclass) + else if (ident == Id.opCall && mt.ty == Tclass) error(loc, "no property `%s` for type `%s`, did you mean `new %s`?", ident.toChars(), mt.toChars(), mt.toPrettyChars()); else if (const n = importHint(ident.toString())) @@ -4883,7 +4883,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag /*************************************** * `ident` was not found as a member of `mt`. - * Attempt to use overloaded opDot(), overloaded opDispatch(), or `alias this`. + * Attempt to use overloaded opDispatch() or `alias this`. * If that fails, forward to visitType(). * Params: * mt = class or struct @@ -4939,21 +4939,6 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag ident != Id.postblit && ident != Id.__xpostblit) { - /* Look for overloaded opDot() to see if we should forward request - * to it. - */ - if (auto fd = search_function(sym, Id.opDot)) - { - /* Rewrite e.ident as: - * e.opDot().ident - */ - e = build_overload(e.loc, sc, e, null, fd); - // @@@DEPRECATED_2.110@@@. - // Deprecated in 2.082, made an error in 2.100. - error(e.loc, "`opDot` is obsolete. Use `alias this`"); - return ErrorExp.get(); - } - /* Look for overloaded opDispatch to see if we should forward request * to it. */ diff --git a/gcc/testsuite/gdc.test/compilable/interpret3.d b/gcc/testsuite/gdc.test/compilable/interpret3.d index aa88458..f62147a 100644 --- a/gcc/testsuite/gdc.test/compilable/interpret3.d +++ b/gcc/testsuite/gdc.test/compilable/interpret3.d @@ -6240,9 +6240,9 @@ struct Coord13831 struct Chunk13831 { - this(Coord13831) + this(Coord13831 coord) { - coord = coord; + this.coord = coord; } Coord13831 coord; diff --git a/gcc/testsuite/gdc.test/compilable/nogc.d b/gcc/testsuite/gdc.test/compilable/nogc.d index 959adc4..5f14339 100644 --- a/gcc/testsuite/gdc.test/compilable/nogc.d +++ b/gcc/testsuite/gdc.test/compilable/nogc.d @@ -36,9 +36,6 @@ void foo_compiles() {} static assert(!__traits(compiles, new Struct())); static assert(!__traits(compiles, new Object())); - int* p; - static assert(!__traits(compiles, delete p)); - int[int] aa; static assert( __traits(compiles, aa[0])); static assert(!__traits(compiles, (aa[0] = 10))); diff --git a/gcc/testsuite/gdc.test/compilable/test22510.d b/gcc/testsuite/gdc.test/compilable/test22510.d index af5d0a4..1207bf0 100644 --- a/gcc/testsuite/gdc.test/compilable/test22510.d +++ b/gcc/testsuite/gdc.test/compilable/test22510.d @@ -7,7 +7,7 @@ struct S @disable this(this); this (scope ref inout S) inout { - this.b = b; + this.b = 0; } } diff --git a/gcc/testsuite/gdc.test/fail_compilation/ctor_self_assignment.d b/gcc/testsuite/gdc.test/fail_compilation/ctor_self_assignment.d new file mode 100644 index 0000000..9d424b1 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/ctor_self_assignment.d @@ -0,0 +1,23 @@ +/** +REQUIRED_ARGS: -de +TEST_OUTPUT: +--- +fail_compilation/ctor_self_assignment.d(17): Deprecation: cannot initialize field `location` with itself +fail_compilation/ctor_self_assignment.d(15): did you mean to use parameter `locaction`? +--- +*/ +// https://forum.dlang.org/post/teghfhpmvkdcfwfeovua@forum.dlang.org + +alias Location = int; + +struct Node +{ + this(Location locaction, uint f) + { + this.location = location; + this.f = f; + } + + Location location; + uint f; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/dep_d1_ops.d b/gcc/testsuite/gdc.test/fail_compilation/dep_d1_ops.d index 19c6475..f8ebc37 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/dep_d1_ops.d +++ b/gcc/testsuite/gdc.test/fail_compilation/dep_d1_ops.d @@ -1,52 +1,93 @@ /* -REQUIRED_ARGS: -de +REQUIRED_ARGS: TEST_OUTPUT: --- -fail_compilation/dep_d1_ops.d(105): Error: `opAdd` is obsolete. Use `opBinary(string op)(...) if (op == "+")` instead. -fail_compilation/dep_d1_ops.d(106): Error: `opAdd_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == "+")` instead. -fail_compilation/dep_d1_ops.d(107): Error: `opSub` is obsolete. Use `opBinary(string op)(...) if (op == "-")` instead. -fail_compilation/dep_d1_ops.d(108): Error: `opSub_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == "-")` instead. -fail_compilation/dep_d1_ops.d(109): Error: `opMul` is obsolete. Use `opBinary(string op)(...) if (op == "*")` instead. -fail_compilation/dep_d1_ops.d(110): Error: `opMul_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == "*")` instead. -fail_compilation/dep_d1_ops.d(111): Error: `opDiv` is obsolete. Use `opBinary(string op)(...) if (op == "/")` instead. -fail_compilation/dep_d1_ops.d(112): Error: `opDiv_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == "/")` instead. -fail_compilation/dep_d1_ops.d(113): Error: `opMod` is obsolete. Use `opBinary(string op)(...) if (op == "%")` instead. -fail_compilation/dep_d1_ops.d(114): Error: `opMod_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == "%")` instead. -fail_compilation/dep_d1_ops.d(116): Error: `opAnd` is obsolete. Use `opBinary(string op)(...) if (op == "&")` instead. -fail_compilation/dep_d1_ops.d(117): Error: `opOr` is obsolete. Use `opBinary(string op)(...) if (op == "|")` instead. -fail_compilation/dep_d1_ops.d(118): Error: `opXor` is obsolete. Use `opBinary(string op)(...) if (op == "^")` instead. -fail_compilation/dep_d1_ops.d(120): Error: `opShl` is obsolete. Use `opBinary(string op)(...) if (op == "<<")` instead. -fail_compilation/dep_d1_ops.d(121): Error: `opShl_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == "<<")` instead. -fail_compilation/dep_d1_ops.d(122): Error: `opShr` is obsolete. Use `opBinary(string op)(...) if (op == ">>")` instead. -fail_compilation/dep_d1_ops.d(123): Error: `opShr_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == ">>")` instead. -fail_compilation/dep_d1_ops.d(124): Error: `opUShr` is obsolete. Use `opBinary(string op)(...) if (op == ">>>")` instead. -fail_compilation/dep_d1_ops.d(125): Error: `opUShr_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == ">>>")` instead. -fail_compilation/dep_d1_ops.d(127): Error: `opCat` is obsolete. Use `opBinary(string op)(...) if (op == "~")` instead. -fail_compilation/dep_d1_ops.d(128): Error: `opCat_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == "~")` instead. -fail_compilation/dep_d1_ops.d(130): Error: `opNeg` is obsolete. Use `opUnary(string op)() if (op == "-")` instead. -fail_compilation/dep_d1_ops.d(131): Error: `opCom` is obsolete. Use `opUnary(string op)() if (op == "~")` instead. -fail_compilation/dep_d1_ops.d(132): Error: `opPostInc` is obsolete. Use `opUnary(string op)() if (op == "++")` instead. -fail_compilation/dep_d1_ops.d(133): Error: `opPostDec` is obsolete. Use `opUnary(string op)() if (op == "--")` instead. -fail_compilation/dep_d1_ops.d(134): Error: `opStar` is obsolete. Use `opUnary(string op)() if (op == "*")` instead. -fail_compilation/dep_d1_ops.d(136): Error: `opIn` is obsolete. Use `opBinary(string op)(...) if (op == "in")` instead. -fail_compilation/dep_d1_ops.d(137): Error: `opIn_r` is obsolete. Use `opBinaryRight(string op)(...) if (op == "in")` instead. -fail_compilation/dep_d1_ops.d(139): Error: `opAddAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "+")` instead. -fail_compilation/dep_d1_ops.d(140): Error: `opSubAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "-")` instead. -fail_compilation/dep_d1_ops.d(141): Error: `opMulAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "*")` instead. -fail_compilation/dep_d1_ops.d(142): Error: `opDivAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "/")` instead. -fail_compilation/dep_d1_ops.d(143): Error: `opModAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "%")` instead. -fail_compilation/dep_d1_ops.d(144): Error: `opAndAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "&")` instead. -fail_compilation/dep_d1_ops.d(145): Error: `opOrAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "|")` instead. -fail_compilation/dep_d1_ops.d(146): Error: `opXorAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "^")` instead. -fail_compilation/dep_d1_ops.d(147): Error: `opShlAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "<<")` instead. -fail_compilation/dep_d1_ops.d(148): Error: `opShrAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == ">>")` instead. -fail_compilation/dep_d1_ops.d(149): Error: `opUShrAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == ">>>")` instead. -fail_compilation/dep_d1_ops.d(150): Error: `opCatAssign` is obsolete. Use `opOpAssign(string op)(...) if (op == "~")` instead. -fail_compilation/dep_d1_ops.d(158): Error: `opCom` is obsolete. Use `opUnary(string op)() if (op == "~")` instead. +fail_compilation/dep_d1_ops.d(198): Error: incompatible types for `(s) + (1)`: `S` and `int` +fail_compilation/dep_d1_ops.d(199): Error: incompatible types for `(1) + (s)`: `int` and `S` +fail_compilation/dep_d1_ops.d(200): Error: incompatible types for `(s) - (1)`: `S` and `int` +fail_compilation/dep_d1_ops.d(201): Error: incompatible types for `(1) - (s)`: `int` and `S` +fail_compilation/dep_d1_ops.d(202): Error: incompatible types for `(s) * (1)`: `S` and `int` +fail_compilation/dep_d1_ops.d(203): Error: incompatible types for `(1) * (s)`: `int` and `S` +fail_compilation/dep_d1_ops.d(204): Error: incompatible types for `(s) / (1)`: `S` and `int` +fail_compilation/dep_d1_ops.d(205): Error: incompatible types for `(1) / (s)`: `int` and `S` +fail_compilation/dep_d1_ops.d(206): Error: incompatible types for `(s) % (1)`: `S` and `int` +fail_compilation/dep_d1_ops.d(207): Error: incompatible types for `(1) % (s)`: `int` and `S` +fail_compilation/dep_d1_ops.d(209): Error: incompatible types for `(s) & (1)`: `S` and `int` +fail_compilation/dep_d1_ops.d(210): Error: incompatible types for `(s) | (1)`: `S` and `int` +fail_compilation/dep_d1_ops.d(211): Error: incompatible types for `(s) ^ (1)`: `S` and `int` +fail_compilation/dep_d1_ops.d(213): Error: `s` is not of integral type, it is a `S` +fail_compilation/dep_d1_ops.d(214): Error: `s` is not of integral type, it is a `S` +fail_compilation/dep_d1_ops.d(215): Error: `s` is not of integral type, it is a `S` +fail_compilation/dep_d1_ops.d(216): Error: `s` is not of integral type, it is a `S` +fail_compilation/dep_d1_ops.d(217): Error: `s` is not of integral type, it is a `S` +fail_compilation/dep_d1_ops.d(218): Error: `s` is not of integral type, it is a `S` +fail_compilation/dep_d1_ops.d(220): Error: incompatible types for `(s) ~ (1)`: `S` and `int` +fail_compilation/dep_d1_ops.d(221): Error: incompatible types for `(1) ~ (s)`: `int` and `S` +fail_compilation/dep_d1_ops.d(223): Error: operator `+` is not defined for `s` of type `S` +fail_compilation/dep_d1_ops.d(224): Error: operator `-` is not defined for `s` of type `S` +fail_compilation/dep_d1_ops.d(225): Error: `s` is not of integral type, it is a `S` +fail_compilation/dep_d1_ops.d(226): Error: `s` is not a scalar, it is a `S` +fail_compilation/dep_d1_ops.d(227): Error: `s` is not a scalar, it is a `S` +fail_compilation/dep_d1_ops.d(228): Error: can only `*` a pointer, not a `S` +fail_compilation/dep_d1_ops.d(230): Error: incompatible types for `(s) in (1)`: `S` and `int` +fail_compilation/dep_d1_ops.d(231): Error: incompatible types for `(1) in (s)`: `int` and `S` +fail_compilation/dep_d1_ops.d(233): Error: `s` is not a scalar, it is a `S` +fail_compilation/dep_d1_ops.d(234): Error: `s` is not a scalar, it is a `S` +fail_compilation/dep_d1_ops.d(235): Error: `s` is not a scalar, it is a `S` +fail_compilation/dep_d1_ops.d(236): Error: `s` is not a scalar, it is a `S` +fail_compilation/dep_d1_ops.d(237): Error: `s` is not a scalar, it is a `S` +fail_compilation/dep_d1_ops.d(238): Error: `s` is not a scalar, it is a `S` +fail_compilation/dep_d1_ops.d(239): Error: `s` is not a scalar, it is a `S` +fail_compilation/dep_d1_ops.d(240): Error: `s` is not a scalar, it is a `S` +fail_compilation/dep_d1_ops.d(241): Error: `s` is not a scalar, it is a `S` +fail_compilation/dep_d1_ops.d(242): Error: `s` is not a scalar, it is a `S` +fail_compilation/dep_d1_ops.d(243): Error: `s` is not a scalar, it is a `S` +fail_compilation/dep_d1_ops.d(244): Error: cannot append type `int` to type `S` +fail_compilation/dep_d1_ops.d(248): Error: incompatible types for `(c) + (1)`: `dep_d1_ops.C` and `int` +fail_compilation/dep_d1_ops.d(249): Error: incompatible types for `(1) + (c)`: `int` and `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(250): Error: incompatible types for `(c) - (1)`: `dep_d1_ops.C` and `int` +fail_compilation/dep_d1_ops.d(251): Error: incompatible types for `(1) - (c)`: `int` and `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(252): Error: incompatible types for `(c) * (1)`: `dep_d1_ops.C` and `int` +fail_compilation/dep_d1_ops.d(253): Error: incompatible types for `(1) * (c)`: `int` and `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(254): Error: incompatible types for `(c) / (1)`: `dep_d1_ops.C` and `int` +fail_compilation/dep_d1_ops.d(255): Error: incompatible types for `(1) / (c)`: `int` and `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(256): Error: incompatible types for `(c) % (1)`: `dep_d1_ops.C` and `int` +fail_compilation/dep_d1_ops.d(257): Error: incompatible types for `(1) % (c)`: `int` and `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(259): Error: incompatible types for `(c) & (1)`: `dep_d1_ops.C` and `int` +fail_compilation/dep_d1_ops.d(260): Error: incompatible types for `(c) | (1)`: `dep_d1_ops.C` and `int` +fail_compilation/dep_d1_ops.d(261): Error: incompatible types for `(c) ^ (1)`: `dep_d1_ops.C` and `int` +fail_compilation/dep_d1_ops.d(263): Error: `c` is not of integral type, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(264): Error: `c` is not of integral type, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(265): Error: `c` is not of integral type, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(266): Error: `c` is not of integral type, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(267): Error: `c` is not of integral type, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(268): Error: `c` is not of integral type, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(270): Error: incompatible types for `(c) ~ (1)`: `dep_d1_ops.C` and `int` +fail_compilation/dep_d1_ops.d(271): Error: incompatible types for `(1) ~ (c)`: `int` and `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(273): Error: operator `+` is not defined for `c` of type `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(274): Error: operator `-` is not defined for `c` of type `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(275): Error: `c` is not of integral type, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(276): Error: `c` is not a scalar, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(277): Error: `c` is not a scalar, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(278): Error: can only `*` a pointer, not a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(280): Error: incompatible types for `(c) in (1)`: `dep_d1_ops.C` and `int` +fail_compilation/dep_d1_ops.d(281): Error: incompatible types for `(1) in (c)`: `int` and `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(283): Error: `c` is not a scalar, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(284): Error: `c` is not a scalar, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(285): Error: `c` is not a scalar, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(286): Error: `c` is not a scalar, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(287): Error: `c` is not a scalar, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(288): Error: `c` is not a scalar, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(289): Error: `c` is not a scalar, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(290): Error: `c` is not a scalar, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(291): Error: `c` is not a scalar, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(292): Error: `c` is not a scalar, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(293): Error: `c` is not a scalar, it is a `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(294): Error: cannot append type `int` to type `dep_d1_ops.C` +fail_compilation/dep_d1_ops.d(303): Error: `nd` is not of integral type, it is a `dep_d1_ops.NoDeprecation` --- */ -#line 50 struct S { int opAdd(int i) { return 0; } @@ -74,6 +115,58 @@ struct S int opCat(int i) { return 0; } int opCat_r(int i) { return 0; } + int opPos() { return 0; } + int opNeg() { return 0; } + int opCom() { return 0; } + int opPostInc() { return 0; } + int opPostDec() { return 0; } + int opStar() { return 0; } + + int opIn(int i) { return 0; } + int opIn_r(int i) { return 0; } + + int opAddAssign(int i) { return 0; } + int opSubAssign(int i) { return 0; } + int opMulAssign(int i) { return 0; } + int opDivAssign(int i) { return 0; } + int opModAssign(int i) { return 0; } + int opAndAssign(int i) { return 0; } + int opOrAssign(int i) { return 0; } + int opXorAssign(int i) { return 0; } + int opShlAssign(int i) { return 0; } + int opShrAssign(int i) { return 0; } + int opUShrAssign(int i) { return 0; } + int opCatAssign(int i) { return 0; } +} + +class C +{ + int opAdd(int i) { return 0; } + int opAdd_r(int i) { return 0; } + int opSub(int i) { return 0; } + int opSub_r(int i) { return 0; } + int opMul(int i) { return 0; } + int opMul_r(int i) { return 0; } + int opDiv(int i) { return 0; } + int opDiv_r(int i) { return 0; } + int opMod(int i) { return 0; } + int opMod_r(int i) { return 0; } + + int opAnd(int i) { return 0; } + int opOr(int i) { return 0; } + int opXor(int i) { return 0; } + + int opShl(int i) { return 0; } + int opShl_r(int i) { return 0; } + int opShr(int i) { return 0; } + int opShr_r(int i) { return 0; } + int opUShr(int i) { return 0; } + int opUShr_r(int i) { return 0; } + + int opCat(int i) { return 0; } + int opCat_r(int i) { return 0; } + + int opPos() { return 0; } int opNeg() { return 0; } int opCom() { return 0; } int opPostInc() { return 0; } @@ -99,55 +192,107 @@ struct S void main() { - S s; int i; + { + S s; + i = s + 1; + i = 1 + s; + i = s - 1; + i = 1 - s; + i = s * 1; + i = 1 * s; + i = s / 1; + i = 1 / s; + i = s % 1; + i = 1 % s; + + i = s & 1; + i = s | 1; + i = s ^ 1; + + i = s << 1; + i = 1 << s; + i = s >> 1; + i = 1 >> s; + i = s >>> 1; + i = 1 >>> s; + + i = s ~ 1; + i = 1 ~ s; + + i = +s; + i = -s; + i = ~s; + s++; + s--; + i = *s; + + i = s in 1; + i = 1 in s; + + s += 1; + s -= 1; + s *= 1; + s /= 1; + s %= 1; + s &= 1; + s |= 1; + s ^= 1; + s <<= 1; + s >>= 1; + s >>>= 1; + s ~= 1; + } + { + C c; + i = c + 1; + i = 1 + c; + i = c - 1; + i = 1 - c; + i = c * 1; + i = 1 * c; + i = c / 1; + i = 1 / c; + i = c % 1; + i = 1 % c; + + i = c & 1; + i = c | 1; + i = c ^ 1; + + i = c << 1; + i = 1 << c; + i = c >> 1; + i = 1 >> c; + i = c >>> 1; + i = 1 >>> c; - i = s + 1; - i = 1 + s; - i = s - 1; - i = 1 - s; - i = s * 1; - i = 1 * s; - i = s / 1; - i = 1 / s; - i = s % 1; - i = 1 % s; - - i = s & 1; - i = s | 1; - i = s ^ 1; - - i = s << 1; - i = 1 << s; - i = s >> 1; - i = 1 >> s; - i = s >>> 1; - i = 1 >>> s; - - i = s ~ 1; - i = 1 ~ s; - - i = -s; - i = ~s; - s++; - s--; - i = *s; - - i = s in 1; - i = 1 in s; - - s += 1; - s -= 1; - s *= 1; - s /= 1; - s %= 1; - s &= 1; - s |= 1; - s ^= 1; - s <<= 1; - s >>= 1; - s >>>= 1; - s ~= 1; + i = c ~ 1; + i = 1 ~ c; + + i = +c; + i = -c; + i = ~c; + c++; + c--; + i = *c; + + i = c in 1; + i = 1 in c; + + c += 1; + c -= 1; + c *= 1; + c /= 1; + c %= 1; + c &= 1; + c |= 1; + c ^= 1; + c <<= 1; + c >>= 1; + c >>>= 1; + c ~= 1; + } scope nd = new NoDeprecation; assert((42 in nd) == 0); diff --git a/gcc/testsuite/gdc.test/fail_compilation/deprecateopdot.d b/gcc/testsuite/gdc.test/fail_compilation/deprecateopdot.d deleted file mode 100644 index 46c9493..0000000 --- a/gcc/testsuite/gdc.test/fail_compilation/deprecateopdot.d +++ /dev/null @@ -1,30 +0,0 @@ -/* -REQUIRED_ARGS: -de -TEST_OUTPUT: ---- -fail_compilation/deprecateopdot.d(27): Error: `opDot` is obsolete. Use `alias this` -fail_compilation/deprecateopdot.d(28): Error: `opDot` is obsolete. Use `alias this` -fail_compilation/deprecateopdot.d(29): Error: `opDot` is obsolete. Use `alias this` ---- -*/ -struct S6 -{ - int a, b; -} -struct T6 -{ - S6 s; - - S6* opDot() return - { - return &s; - } -} - -void test6() -{ - T6 t; - t.a = 4; - assert(t.a == 4); - t.b = 5; -} diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag_class_alloc.d b/gcc/testsuite/gdc.test/fail_compilation/diag_class_alloc.d deleted file mode 100644 index 326d82e..0000000 --- a/gcc/testsuite/gdc.test/fail_compilation/diag_class_alloc.d +++ /dev/null @@ -1,19 +0,0 @@ -/* -TEST_OUTPUT: ---- -fail_compilation/diag_class_alloc.d(15): Error: `new` allocator must be annotated with `@disabled` -fail_compilation/diag_class_alloc.d(16): Deprecation: `new` allocator with non-empty parameter list is deprecated -fail_compilation/diag_class_alloc.d(16): Deprecation: `new` allocator with function definition is deprecated ---- -*/ - -// This test exists to ensure class allocators and deallocators emit an appropriate error message. -// This test can be deleted when class allocators and deallocators are removed from the language. - -class C -{ - new(size_t size) // error message - { - return malloc(size); - } -} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail10534.d b/gcc/testsuite/gdc.test/fail_compilation/fail10534.d index b5bb67c..f0e0b85 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail10534.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail10534.d @@ -1,22 +1,18 @@ /* TEST_OUTPUT: --- -fail_compilation/fail10534.d(28): Error: illegal operator `+` for `a` of type `int delegate()` -fail_compilation/fail10534.d(28): Error: illegal operator `+` for `b` of type `int delegate()` -fail_compilation/fail10534.d(29): Error: illegal operator `-` for `a` of type `int delegate()` -fail_compilation/fail10534.d(29): Error: illegal operator `-` for `b` of type `int delegate()` -fail_compilation/fail10534.d(30): Error: illegal operator `/` for `a` of type `int delegate()` -fail_compilation/fail10534.d(30): Error: illegal operator `/` for `b` of type `int delegate()` -fail_compilation/fail10534.d(31): Error: illegal operator `*` for `a` of type `int delegate()` -fail_compilation/fail10534.d(31): Error: illegal operator `*` for `b` of type `int delegate()` -fail_compilation/fail10534.d(36): Error: illegal operator `+` for `a` of type `int function()` -fail_compilation/fail10534.d(36): Error: illegal operator `+` for `b` of type `int function()` -fail_compilation/fail10534.d(37): Error: illegal operator `-` for `a` of type `int function()` -fail_compilation/fail10534.d(37): Error: illegal operator `-` for `b` of type `int function()` -fail_compilation/fail10534.d(38): Error: illegal operator `/` for `a` of type `int function()` -fail_compilation/fail10534.d(38): Error: illegal operator `/` for `b` of type `int function()` -fail_compilation/fail10534.d(39): Error: illegal operator `*` for `a` of type `int function()` -fail_compilation/fail10534.d(39): Error: illegal operator `*` for `b` of type `int function()` +fail_compilation/fail10534.d(24): Error: illegal operator `+` for `a` of type `int delegate()` +fail_compilation/fail10534.d(24): Error: illegal operator `+` for `b` of type `int delegate()` +fail_compilation/fail10534.d(25): Error: illegal operator `-` for `a` of type `int delegate()` +fail_compilation/fail10534.d(25): Error: illegal operator `-` for `b` of type `int delegate()` +fail_compilation/fail10534.d(26): Error: illegal operator `/` for `a` of type `int delegate()` +fail_compilation/fail10534.d(27): Error: illegal operator `*` for `a` of type `int delegate()` +fail_compilation/fail10534.d(32): Error: illegal operator `+` for `a` of type `int function()` +fail_compilation/fail10534.d(32): Error: illegal operator `+` for `b` of type `int function()` +fail_compilation/fail10534.d(33): Error: illegal operator `-` for `a` of type `int function()` +fail_compilation/fail10534.d(33): Error: illegal operator `-` for `b` of type `int function()` +fail_compilation/fail10534.d(34): Error: illegal operator `/` for `a` of type `int function()` +fail_compilation/fail10534.d(35): Error: illegal operator `*` for `a` of type `int function()` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail11445.d b/gcc/testsuite/gdc.test/fail_compilation/fail11445.d index 3295b24..e4105b8 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail11445.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail11445.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail11445.d(11): Error: incompatible types for `(a) + (b)`: both operands are of type `double[string]` +fail_compilation/fail11445.d(11): Error: illegal operator `+` for `a` of type `double[string]` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail13902.d b/gcc/testsuite/gdc.test/fail_compilation/fail13902.d index 9c82b2c..a1c1bab 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail13902.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail13902.d @@ -14,7 +14,7 @@ fail_compilation/fail13902.d(33): Error: returning `&s1.v` escapes a reference t fail_compilation/fail13902.d(38): Error: returning `& sa1` escapes a reference to local variable `sa1` fail_compilation/fail13902.d(39): Error: returning `& sa2` escapes a reference to local variable `sa2` fail_compilation/fail13902.d(40): Error: returning `& x` escapes a reference to local variable `x` -fail_compilation/fail13902.d(41): Error: returning `(& x+4)` escapes a reference to local variable `x` +fail_compilation/fail13902.d(41): Error: returning `(& x + 4)` escapes a reference to local variable `x` fail_compilation/fail13902.d(42): Error: returning `& x + cast(long)x * 4L` escapes a reference to local variable `x` fail_compilation/fail13902.d(45): Error: returning `& y` escapes a reference to local variable `y` --- @@ -59,7 +59,7 @@ fail_compilation/fail13902.d(76): Error: returning `&s1.v` escapes a reference t fail_compilation/fail13902.d(81): Error: returning `& sa1` escapes a reference to parameter `sa1` fail_compilation/fail13902.d(82): Error: returning `& sa2` escapes a reference to parameter `sa2` fail_compilation/fail13902.d(83): Error: returning `& x` escapes a reference to parameter `x` -fail_compilation/fail13902.d(84): Error: returning `(& x+4)` escapes a reference to parameter `x` +fail_compilation/fail13902.d(84): Error: returning `(& x + 4)` escapes a reference to parameter `x` fail_compilation/fail13902.d(85): Error: returning `& x + cast(long)x * 4L` escapes a reference to parameter `x` fail_compilation/fail13902.d(88): Error: returning `& y` escapes a reference to parameter `y` --- diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail14343.d b/gcc/testsuite/gdc.test/fail_compilation/fail14343.d new file mode 100644 index 0000000..d644ec9 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fail14343.d @@ -0,0 +1,25 @@ +// https://issues.dlang.org/show_bug.cgi?id=14343 +/* TEST_OUTPUT: +--- +fail_compilation/fail14343.d(21): Error: cannot modify struct instance `s` of type `S14343b` because it contains `const` or `immutable` members +fail_compilation/fail14343.d(23): Error: cannot modify struct instance `s` of type `S14343b` because it contains `const` or `immutable` members +--- +*/ + +struct S14343b +{ + int i; + immutable(Object) o; + + void opAddAssign(int j) { i += j; } + void opAssign(S14343b other) {} +} + +void test14343() +{ + S14343b s; + ++s; + assert(s.i == 1); + s++; + assert(s.i == 2); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail14486.d b/gcc/testsuite/gdc.test/fail_compilation/fail14486.d deleted file mode 100644 index 35312454..0000000 --- a/gcc/testsuite/gdc.test/fail_compilation/fail14486.d +++ /dev/null @@ -1,79 +0,0 @@ -// REQUIRED_ARGS: -o- - -/* -TEST_OUTPUT: ---- -fail_compilation/fail14486.d(47): Error: the `delete` keyword is obsolete -fail_compilation/fail14486.d(47): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead -fail_compilation/fail14486.d(48): Error: the `delete` keyword is obsolete -fail_compilation/fail14486.d(48): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead -fail_compilation/fail14486.d(53): Error: the `delete` keyword is obsolete -fail_compilation/fail14486.d(53): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead -fail_compilation/fail14486.d(54): Error: the `delete` keyword is obsolete -fail_compilation/fail14486.d(54): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead -fail_compilation/fail14486.d(59): Error: the `delete` keyword is obsolete -fail_compilation/fail14486.d(59): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead -fail_compilation/fail14486.d(60): Error: the `delete` keyword is obsolete -fail_compilation/fail14486.d(60): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead -fail_compilation/fail14486.d(65): Error: the `delete` keyword is obsolete -fail_compilation/fail14486.d(65): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead -fail_compilation/fail14486.d(66): Error: the `delete` keyword is obsolete -fail_compilation/fail14486.d(66): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead -fail_compilation/fail14486.d(71): Error: the `delete` keyword is obsolete -fail_compilation/fail14486.d(71): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead -fail_compilation/fail14486.d(72): Error: the `delete` keyword is obsolete -fail_compilation/fail14486.d(72): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead -fail_compilation/fail14486.d(77): Error: the `delete` keyword is obsolete -fail_compilation/fail14486.d(77): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead -fail_compilation/fail14486.d(78): Error: the `delete` keyword is obsolete -fail_compilation/fail14486.d(78): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead ---- -*/ - -class C0a { } -class C1a { ~this() {} } - -class C0b { } -class C1b { ~this() {} } - -struct S0a { } -struct S1a { ~this() {} } - -struct S0b { } -struct S1b { ~this() {} } - -void test1a() @nogc pure @safe -{ - C0a c0; delete c0; // error - C1a c1; delete c1; // error -} - -void test1b() nothrow -{ - C0b c0; delete c0; // no error - C1b c1; delete c1; // error -} - -void test2a() @nogc pure @safe -{ - S0a* s0; delete s0; // error - S1a* s1; delete s1; // error -} - -void test2b() nothrow -{ - S0b* s0; delete s0; // no error - S1b* s1; delete s1; // error -} - -void test3a() @nogc pure @safe -{ - S0a[] a0; delete a0; // error - S1a[] a1; delete a1; // error -} - -void test3b() nothrow -{ - S0b[] a0; delete a0; // no error - S1b[] a1; delete a1; // error -} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail17906.d b/gcc/testsuite/gdc.test/fail_compilation/fail17906.d deleted file mode 100644 index 41f7465..0000000 --- a/gcc/testsuite/gdc.test/fail_compilation/fail17906.d +++ /dev/null @@ -1,13 +0,0 @@ -// REQUIRED_ARGS: -de -/* TEST_OUTPUT: ---- -fail_compilation/fail17906.d(12): Error: the `delete` keyword is obsolete -fail_compilation/fail17906.d(12): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead ---- -*/ -// https://issues.dlang.org/show_bug.cgi?id=18647 -deprecated void main () -{ - Object o = new Object; - delete o; -} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail2361.d b/gcc/testsuite/gdc.test/fail_compilation/fail2361.d deleted file mode 100644 index ffc12f1..0000000 --- a/gcc/testsuite/gdc.test/fail_compilation/fail2361.d +++ /dev/null @@ -1,15 +0,0 @@ -/* -TEST_OUTPUT: ---- -fail_compilation/fail2361.d(14): Error: the `delete` keyword is obsolete -fail_compilation/fail2361.d(14): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead ---- -*/ - -class C {} - -void main() -{ - immutable c = new immutable(C); - delete c; -} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail297.d b/gcc/testsuite/gdc.test/fail_compilation/fail297.d index 5fc3bbf..3bb25dd 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail297.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail297.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail297.d(30): Error: incompatible types for `(Bar()) + (baz())`: `Bar` and `const(Bar)` +fail_compilation/fail297.d(30): Error: operator `+` is not defined for `Bar()` of type `Bar` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail3.d b/gcc/testsuite/gdc.test/fail_compilation/fail3.d index 5c1ea91..1c40c4f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail3.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail3.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail3.d(41): Error: incompatible types for `(a) + (b)`: both operands are of type `vec2` +fail_compilation/fail3.d(41): Error: operator `+` is not defined for `a` of type `vec2` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d b/gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d index 0db6a45..a8b53f1 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d @@ -209,8 +209,6 @@ fail_compilation/fail_arrayop2.d(269): Error: array operation `"abc"[] + '\x01'` fail_compilation/fail_arrayop2.d(272): Error: array operation `[1] * 6` without destination memory not allowed fail_compilation/fail_arrayop2.d(275): Error: cannot take address of expression `([1] * 6)[0..2]` because it is not an lvalue fail_compilation/fail_arrayop2.d(278): Error: can only `*` a pointer, not a `int[]` -fail_compilation/fail_arrayop2.d(281): Error: the `delete` keyword is obsolete -fail_compilation/fail_arrayop2.d(281): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead fail_compilation/fail_arrayop2.d(284): Error: array operation `da[] * 6` without destination memory not allowed fail_compilation/fail_arrayop2.d(287): Error: array operation `da[] * 6` without destination memory not allowed fail_compilation/fail_arrayop2.d(290): Error: cannot modify expression `[1] * 6` because it is not an lvalue @@ -235,6 +233,8 @@ fail_compilation/fail_arrayop2.d(321): Error: array operation `[1] * 6` without fail_compilation/fail_arrayop2.d(321): Error: array operation `[1] * 6` without destination memory not allowed --- */ + + // Test all expressions, which can take arrays as their operands but cannot be a part of array operation. void test15407exp() { @@ -277,8 +277,8 @@ void test15407exp() // PtrExp, *([1] * 6).ptr is also invalid -> show better diagnostic { auto r = *([1] * 6); } - // DeleteExp - e1 - delete ([1] * 6); + + // TypeDArray.dotExp, cannot check in ArrayLengthExp.semantic() { auto r = (6 * da[]).length; } diff --git a/gcc/testsuite/gdc.test/fail_compilation/faildeleteaa.d b/gcc/testsuite/gdc.test/fail_compilation/faildeleteaa.d deleted file mode 100644 index ed640fb..0000000 --- a/gcc/testsuite/gdc.test/fail_compilation/faildeleteaa.d +++ /dev/null @@ -1,13 +0,0 @@ -/* -TEST_OUTPUT: ---- -fail_compilation/faildeleteaa.d(12): Error: the `delete` keyword is obsolete -fail_compilation/faildeleteaa.d(12): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead ---- -*/ - -void main() -{ - int[int] aa = [1 : 2]; - delete aa[1]; -} diff --git a/gcc/testsuite/gdc.test/fail_compilation/hexstring.d b/gcc/testsuite/gdc.test/fail_compilation/hexstring.d index edbb4e6..2c6191e 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/hexstring.d +++ b/gcc/testsuite/gdc.test/fail_compilation/hexstring.d @@ -1,21 +1,24 @@ /** TEST_OUTPUT: --- -fail_compilation/hexstring.d(29): Error: cannot implicitly convert expression `"123F"` of type `string` to `immutable(ubyte[])` -fail_compilation/hexstring.d(33): Error: hex string length 1 must be a multiple of 2 to cast to `immutable(ushort[])` -fail_compilation/hexstring.d(34): Error: hex string length 3 must be a multiple of 4 to cast to `immutable(uint[])` -fail_compilation/hexstring.d(35): Error: hex string length 5 must be a multiple of 8 to cast to `immutable(ulong[])` -fail_compilation/hexstring.d(36): Error: array cast from `wstring` to `immutable(ulong[])` is not supported at compile time -fail_compilation/hexstring.d(36): perhaps remove postfix `w` from hex string -fail_compilation/hexstring.d(37): Error: array cast from `string` to `immutable(uint[])` is not supported at compile time -fail_compilation/hexstring.d(38): Error: array cast from `string` to `immutable(ushort[])` is not supported at compile time -fail_compilation/hexstring.d(39): Error: array cast from `string` to `immutable(uint[])` is not supported at compile time -fail_compilation/hexstring.d(39): perhaps remove postfix `c` from hex string -fail_compilation/hexstring.d(40): Error: hex string with `dstring` type needs to be multiple of 4 bytes, not 5 -fail_compilation/hexstring.d(41): Error: cannot implicitly convert expression `x"11223344"d` of type `dstring` to `immutable(float[])` -fail_compilation/hexstring.d(42): Error: cannot implicitly convert expression `x"1122"w` of type `wstring` to `immutable(ubyte[])` -fail_compilation/hexstring.d(50): Error: array cast from `string` to `S[]` is not supported at compile time -fail_compilation/hexstring.d(28): Error: cannot implicitly convert expression `x"123F"` of type `string` to `ubyte[]` +fail_compilation/hexstring.d(30): Error: array cast from `string` to `ubyte[3][1]` is not supported at compile time +fail_compilation/hexstring.d(33): Error: cannot implicitly convert expression `"123F"` of type `string` to `immutable(ubyte[])` +fail_compilation/hexstring.d(37): Error: hex string length 1 must be a multiple of 2 to cast to `immutable(ushort[])` +fail_compilation/hexstring.d(38): Error: hex string length 3 must be a multiple of 4 to cast to `immutable(uint[])` +fail_compilation/hexstring.d(39): Error: hex string length 5 must be a multiple of 8 to cast to `immutable(ulong[])` +fail_compilation/hexstring.d(40): Error: array cast from `wstring` to `immutable(ulong[])` is not supported at compile time +fail_compilation/hexstring.d(40): perhaps remove postfix `w` from hex string +fail_compilation/hexstring.d(41): Error: array cast from `string` to `immutable(uint[])` is not supported at compile time +fail_compilation/hexstring.d(42): Error: array cast from `string` to `immutable(ushort[])` is not supported at compile time +fail_compilation/hexstring.d(43): Error: array cast from `string` to `immutable(uint[])` is not supported at compile time +fail_compilation/hexstring.d(43): perhaps remove postfix `c` from hex string +fail_compilation/hexstring.d(44): Error: hex string with `dstring` type needs to be multiple of 4 bytes, not 5 +fail_compilation/hexstring.d(45): Error: cannot implicitly convert expression `x"11223344"d` of type `dstring` to `immutable(float[])` +fail_compilation/hexstring.d(46): Error: cannot implicitly convert expression `x"1122"w` of type `wstring` to `immutable(ubyte[])` +fail_compilation/hexstring.d(47): Error: array cast from `string` to `ubyte[3][1]` is not supported at compile time +fail_compilation/hexstring.d(48): Error: array cast from `string` to `ubyte[3][1][1]` is not supported at compile time +fail_compilation/hexstring.d(56): Error: array cast from `string` to `S[]` is not supported at compile time +fail_compilation/hexstring.d(32): Error: cannot implicitly convert expression `x"123F"` of type `string` to `ubyte[]` --- */ immutable ubyte[] s0 = x"123F"; @@ -24,6 +27,7 @@ static assert(s0[1] == 0x3F); immutable byte[] s1 = x"123F"; enum E(X) = cast(X[]) x"AABBCCDD"; static assert(E!int[0] == 0xAABBCCDD); +immutable ubyte[3] s2 = cast(ubyte[3][1])x"FFAAFF"; ubyte[] f1 = x"123F"; immutable ubyte[] f2 = "123F"; @@ -40,6 +44,8 @@ immutable uint[] f11 = cast(immutable uint[]) x"AABBCCDD"c; immutable uint[] f12 = x"1122334455"d; immutable float[] f13 = x"11223344"d; immutable ubyte[] f14 = x"1122"w; +immutable ubyte[3][1] f16 = cast(ubyte[3][1])x"FFBBFF"; +immutable ubyte[3][1][1] f17 = cast(ubyte[3][1][1])x"FFCCFF"; // https://issues.dlang.org/show_bug.cgi?id=24832 struct S diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11968.d b/gcc/testsuite/gdc.test/fail_compilation/ice11968.d deleted file mode 100644 index 1d50b66..0000000 --- a/gcc/testsuite/gdc.test/fail_compilation/ice11968.d +++ /dev/null @@ -1,9 +0,0 @@ -/* -TEST_OUTPUT: ----- -fail_compilation/ice11968.d(9): Error: the `delete` keyword is obsolete -fail_compilation/ice11968.d(9): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead ----- -*/ - -void main() { delete __FILE__ ; } diff --git a/gcc/testsuite/gdc.test/fail_compilation/nogc1.d b/gcc/testsuite/gdc.test/fail_compilation/nogc1.d index b2bea5b..ba6956e 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/nogc1.d +++ b/gcc/testsuite/gdc.test/fail_compilation/nogc1.d @@ -57,23 +57,3 @@ fail_compilation/nogc1.d(55): Error: allocating with `new` causes a GC allocatio scope Object o1 = new Object(); // no error scope o2 = new Object(); // no error } - -/***************** DeleteExp *******************/ - -/* -TEST_OUTPUT: ---- -fail_compilation/nogc1.d(76): Error: the `delete` keyword is obsolete -fail_compilation/nogc1.d(76): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead -fail_compilation/nogc1.d(77): Error: the `delete` keyword is obsolete -fail_compilation/nogc1.d(77): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead -fail_compilation/nogc1.d(78): Error: the `delete` keyword is obsolete -fail_compilation/nogc1.d(78): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead ---- -*/ -@nogc void testDelete(int* p, Object o, S1* s) -{ - delete p; - delete o; - delete s; -} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16195.d b/gcc/testsuite/gdc.test/fail_compilation/test16195.d deleted file mode 100644 index 018ab0d..0000000 --- a/gcc/testsuite/gdc.test/fail_compilation/test16195.d +++ /dev/null @@ -1,15 +0,0 @@ -/* - * TEST_OUTPUT: ---- -fail_compilation/test16195.d(14): Error: the `delete` keyword is obsolete -fail_compilation/test16195.d(14): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead ---- - */ - - -// https://issues.dlang.org/show_bug.cgi?id=16195 - -@safe pure nothrow @nogc void test(int* p) -{ - delete p; -} diff --git a/gcc/testsuite/gdc.test/runnable/funclit.d b/gcc/testsuite/gdc.test/runnable/funclit.d index 253df8f..bce4e9a 100644 --- a/gcc/testsuite/gdc.test/runnable/funclit.d +++ b/gcc/testsuite/gdc.test/runnable/funclit.d @@ -384,16 +384,6 @@ void test6714() } /***************************************************/ -// https://issues.dlang.org/show_bug.cgi?id=7193 - -void test7193() -{ - static assert(!__traits(compiles, { - delete a => a; - })); -} - -/***************************************************/ // https://issues.dlang.org/show_bug.cgi?id=7207 // on CastExp @@ -1331,7 +1321,6 @@ int main() test11(); test3235(); test6714(); - test7193(); test7202(); test7288(); test7499(); diff --git a/gcc/testsuite/gdc.test/runnable/newdel.d b/gcc/testsuite/gdc.test/runnable/newdel.d index 8ba7a0c..8888c75 100644 --- a/gcc/testsuite/gdc.test/runnable/newdel.d +++ b/gcc/testsuite/gdc.test/runnable/newdel.d @@ -42,10 +42,29 @@ void test1() } /*********************************************/ +// delete is no longer a keyword and can be used as an identifier + +enum E +{ + add, delete +} + +E delete() +{ + return E.delete; +} + +void test2() +{ + assert(delete() == E.delete); +} + +/*********************************************/ int main() { test1(); + test2(); printf("Success\n"); return 0; diff --git a/gcc/testsuite/gdc.test/runnable/opover.d b/gcc/testsuite/gdc.test/runnable/opover.d index 253a7a5..4e34e52 100644 --- a/gcc/testsuite/gdc.test/runnable/opover.d +++ b/gcc/testsuite/gdc.test/runnable/opover.d @@ -2,29 +2,13 @@ RUN_OUTPUT: --- i = 1 -Writer.opShl(char[]) -BinaryWriter.opShl(int) -a + 1 = 2 -1 + a = 2 -a + b = 3 -b + a = 3 i = 64 12 534 -A::opShl(int 4) -4A::opShl(char[]) - A::opShl(int 12) -12A::opShl(char[]) - -B::opShl_r(A) Success --- */ -// Test operator overloading -// Ignore deprecation warnings for D1 style operator overloading -// TRANSFORM_OUTPUT: remove_lines("Deprecation: `op") - import core.stdc.stdio; /**************************************/ @@ -996,20 +980,11 @@ struct S14343b void test14343() { - { - S14343a s, t; + S14343a s, t; - t = s; // OK - ++s; // OK - s++; // OK <- Error: cannot modify struct s S with immutable members - } - { - S14343b s; - ++s; - assert(s.i == 1); - s++; - assert(s.i == 2); - } + t = s; // OK + ++s; // OK + s++; // OK <- Error: cannot modify struct s S with immutable members } /**************************************/ @@ -1081,20 +1056,13 @@ void test20475() /**************************************/ int main() { - test1(); - test2(); - test3(); test4(); test5(); test6(); test7(); - test8(); test9(); - test10(); test11(); test12(); - test13(); - test14(); test15(); test1547(); test4953a(); diff --git a/gcc/testsuite/gdc.test/runnable/xtest46.d b/gcc/testsuite/gdc.test/runnable/xtest46.d index cbcbd1a..5893560 100644 --- a/gcc/testsuite/gdc.test/runnable/xtest46.d +++ b/gcc/testsuite/gdc.test/runnable/xtest46.d @@ -4091,30 +4091,30 @@ void test4258() { struct Foo4258 { // binary ++/-- - int opPostInc()() if (false) { return 0; } + int opUnary(string op)() if (false) { return 0; } // binary 1st - int opAdd(R)(R rhs) if (false) { return 0; } - int opAdd_r(R)(R rhs) if (false) { return 0; } + int opBinary(string op, R)(R rhs) if (false) { return 0; } + int opBinaryRight(string op, R)(R rhs) if (false) { return 0; } // compare - int opCmp(R)(R rhs) if (false) { return 0; } + int opCmp(R)(const(R) rhs) const if (false) { return 0; } // binary-op assign - int opAddAssign(R)(R rhs) if (false) { return 0; } + int opOpAssign(string op, R)(R rhs) if (false) { return 0; } } struct Bar4258 { // binary commutive 1 - int opAdd_r(R)(R rhs) if (false) { return 0; } + int opBinary(string op, R)(R rhs) if (false) { return 0; } // binary-op assign int opOpAssign(string op, R)(R rhs) if (false) { return 0; } } struct Baz4258 { // binary commutive 2 - int opAdd(R)(R rhs) if (false) { return 0; } + int opBinaryRight(string op, R)(R rhs) if (false) { return 0; } } -static assert(!is(typeof(Foo4258.init++))); +static assert(!is(typeof(++Foo4258.init))); static assert(!is(typeof(Foo4258.init + 1))); static assert(!is(typeof(1 + Foo4258.init))); static assert(!is(typeof(Foo4258.init < Foo4258.init))); diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index 4172630..a91f40b 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -1,4 +1,4 @@ -d1157134103a209d36d6ee9c1df1d61d5929ec6d +b7e3b3b61711bf6c6cad27c7b5b73df0e570c215 The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am index efdae4c..595e3f9 100644 --- a/libphobos/libdruntime/Makefile.am +++ b/libphobos/libdruntime/Makefile.am @@ -361,13 +361,14 @@ DRUNTIME_DSOURCES_SOLARIS = core/sys/solaris/dlfcn.d \ DRUNTIME_DSOURCES_WINDOWS = core/sys/windows/accctrl.d \ core/sys/windows/aclapi.d core/sys/windows/aclui.d \ core/sys/windows/basetsd.d core/sys/windows/basetyps.d \ - core/sys/windows/cderr.d core/sys/windows/cguid.d \ - core/sys/windows/com.d core/sys/windows/comcat.d \ - core/sys/windows/commctrl.d core/sys/windows/commdlg.d \ - core/sys/windows/core.d core/sys/windows/cpl.d \ - core/sys/windows/cplext.d core/sys/windows/custcntl.d \ - core/sys/windows/dbghelp.d core/sys/windows/dbghelp_types.d \ - core/sys/windows/dbt.d core/sys/windows/dde.d core/sys/windows/ddeml.d \ + core/sys/windows/bcrypt.d core/sys/windows/cderr.d \ + core/sys/windows/cguid.d core/sys/windows/com.d \ + core/sys/windows/comcat.d core/sys/windows/commctrl.d \ + core/sys/windows/commdlg.d core/sys/windows/core.d \ + core/sys/windows/cpl.d core/sys/windows/cplext.d \ + core/sys/windows/custcntl.d core/sys/windows/dbghelp.d \ + core/sys/windows/dbghelp_types.d core/sys/windows/dbt.d \ + core/sys/windows/dde.d core/sys/windows/ddeml.d \ core/sys/windows/dhcpcsdk.d core/sys/windows/dlgs.d \ core/sys/windows/dll.d core/sys/windows/docobj.d \ core/sys/windows/errorrep.d core/sys/windows/exdisp.d \ diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in index 1227c59..4832fd1 100644 --- a/libphobos/libdruntime/Makefile.in +++ b/libphobos/libdruntime/Makefile.in @@ -392,88 +392,88 @@ am__objects_19 = core/sys/linux/config.lo core/sys/linux/dlfcn.lo \ am__objects_21 = core/sys/windows/accctrl.lo \ core/sys/windows/aclapi.lo core/sys/windows/aclui.lo \ core/sys/windows/basetsd.lo core/sys/windows/basetyps.lo \ - core/sys/windows/cderr.lo core/sys/windows/cguid.lo \ - core/sys/windows/com.lo core/sys/windows/comcat.lo \ - core/sys/windows/commctrl.lo core/sys/windows/commdlg.lo \ - core/sys/windows/core.lo core/sys/windows/cpl.lo \ - core/sys/windows/cplext.lo core/sys/windows/custcntl.lo \ - core/sys/windows/dbghelp.lo core/sys/windows/dbghelp_types.lo \ - core/sys/windows/dbt.lo core/sys/windows/dde.lo \ - core/sys/windows/ddeml.lo core/sys/windows/dhcpcsdk.lo \ - core/sys/windows/dlgs.lo core/sys/windows/dll.lo \ - core/sys/windows/docobj.lo core/sys/windows/errorrep.lo \ - core/sys/windows/exdisp.lo core/sys/windows/exdispid.lo \ - core/sys/windows/httpext.lo core/sys/windows/idispids.lo \ - core/sys/windows/imagehlp.lo core/sys/windows/imm.lo \ - core/sys/windows/intshcut.lo core/sys/windows/ipexport.lo \ - core/sys/windows/iphlpapi.lo core/sys/windows/ipifcons.lo \ - core/sys/windows/iprtrmib.lo core/sys/windows/iptypes.lo \ - core/sys/windows/isguids.lo core/sys/windows/lm.lo \ - core/sys/windows/lmaccess.lo core/sys/windows/lmalert.lo \ - core/sys/windows/lmapibuf.lo core/sys/windows/lmat.lo \ - core/sys/windows/lmaudit.lo core/sys/windows/lmbrowsr.lo \ - core/sys/windows/lmchdev.lo core/sys/windows/lmconfig.lo \ - core/sys/windows/lmcons.lo core/sys/windows/lmerr.lo \ - core/sys/windows/lmerrlog.lo core/sys/windows/lmmsg.lo \ - core/sys/windows/lmremutl.lo core/sys/windows/lmrepl.lo \ - core/sys/windows/lmserver.lo core/sys/windows/lmshare.lo \ - core/sys/windows/lmsname.lo core/sys/windows/lmstats.lo \ - core/sys/windows/lmsvc.lo core/sys/windows/lmuse.lo \ - core/sys/windows/lmuseflg.lo core/sys/windows/lmwksta.lo \ - core/sys/windows/lzexpand.lo core/sys/windows/mapi.lo \ - core/sys/windows/mciavi.lo core/sys/windows/mcx.lo \ - core/sys/windows/mgmtapi.lo core/sys/windows/mmsystem.lo \ - core/sys/windows/msacm.lo core/sys/windows/mshtml.lo \ - core/sys/windows/mswsock.lo core/sys/windows/nb30.lo \ - core/sys/windows/nddeapi.lo core/sys/windows/nspapi.lo \ - core/sys/windows/ntdef.lo core/sys/windows/ntdll.lo \ - core/sys/windows/ntldap.lo core/sys/windows/ntsecapi.lo \ - core/sys/windows/ntsecpkg.lo core/sys/windows/oaidl.lo \ - core/sys/windows/objbase.lo core/sys/windows/objfwd.lo \ - core/sys/windows/objidl.lo core/sys/windows/objsafe.lo \ - core/sys/windows/ocidl.lo core/sys/windows/odbcinst.lo \ - core/sys/windows/ole.lo core/sys/windows/ole2.lo \ - core/sys/windows/ole2ver.lo core/sys/windows/oleacc.lo \ - core/sys/windows/oleauto.lo core/sys/windows/olectl.lo \ - core/sys/windows/olectlid.lo core/sys/windows/oledlg.lo \ - core/sys/windows/oleidl.lo core/sys/windows/pbt.lo \ - core/sys/windows/powrprof.lo core/sys/windows/prsht.lo \ - core/sys/windows/psapi.lo core/sys/windows/rapi.lo \ - core/sys/windows/ras.lo core/sys/windows/rasdlg.lo \ - core/sys/windows/raserror.lo core/sys/windows/rassapi.lo \ - core/sys/windows/reason.lo core/sys/windows/regstr.lo \ - core/sys/windows/richedit.lo core/sys/windows/richole.lo \ - core/sys/windows/rpc.lo core/sys/windows/rpcdce.lo \ - core/sys/windows/rpcdce2.lo core/sys/windows/rpcdcep.lo \ - core/sys/windows/rpcndr.lo core/sys/windows/rpcnsi.lo \ - core/sys/windows/rpcnsip.lo core/sys/windows/rpcnterr.lo \ - core/sys/windows/schannel.lo core/sys/windows/sdkddkver.lo \ - core/sys/windows/secext.lo core/sys/windows/security.lo \ - core/sys/windows/servprov.lo core/sys/windows/setupapi.lo \ - core/sys/windows/shellapi.lo core/sys/windows/shldisp.lo \ - core/sys/windows/shlguid.lo core/sys/windows/shlobj.lo \ - core/sys/windows/shlwapi.lo core/sys/windows/snmp.lo \ - core/sys/windows/sql.lo core/sys/windows/sqlext.lo \ - core/sys/windows/sqltypes.lo core/sys/windows/sqlucode.lo \ - core/sys/windows/sspi.lo core/sys/windows/stacktrace.lo \ - core/sys/windows/stat.lo core/sys/windows/stdc/malloc.lo \ - core/sys/windows/stdc/time.lo core/sys/windows/subauth.lo \ - core/sys/windows/threadaux.lo core/sys/windows/tlhelp32.lo \ - core/sys/windows/tmschema.lo core/sys/windows/unknwn.lo \ - core/sys/windows/uuid.lo core/sys/windows/vfw.lo \ - core/sys/windows/w32api.lo core/sys/windows/winbase.lo \ - core/sys/windows/winber.lo core/sys/windows/wincon.lo \ - core/sys/windows/wincrypt.lo core/sys/windows/windef.lo \ - core/sys/windows/windows.lo core/sys/windows/winerror.lo \ - core/sys/windows/wingdi.lo core/sys/windows/winhttp.lo \ - core/sys/windows/wininet.lo core/sys/windows/winioctl.lo \ - core/sys/windows/winldap.lo core/sys/windows/winnetwk.lo \ - core/sys/windows/winnls.lo core/sys/windows/winnt.lo \ - core/sys/windows/winperf.lo core/sys/windows/winreg.lo \ - core/sys/windows/winsock2.lo core/sys/windows/winspool.lo \ - core/sys/windows/winsvc.lo core/sys/windows/winuser.lo \ - core/sys/windows/winver.lo core/sys/windows/wtsapi32.lo \ - core/sys/windows/wtypes.lo + core/sys/windows/bcrypt.lo core/sys/windows/cderr.lo \ + core/sys/windows/cguid.lo core/sys/windows/com.lo \ + core/sys/windows/comcat.lo core/sys/windows/commctrl.lo \ + core/sys/windows/commdlg.lo core/sys/windows/core.lo \ + core/sys/windows/cpl.lo core/sys/windows/cplext.lo \ + core/sys/windows/custcntl.lo core/sys/windows/dbghelp.lo \ + core/sys/windows/dbghelp_types.lo core/sys/windows/dbt.lo \ + core/sys/windows/dde.lo core/sys/windows/ddeml.lo \ + core/sys/windows/dhcpcsdk.lo core/sys/windows/dlgs.lo \ + core/sys/windows/dll.lo core/sys/windows/docobj.lo \ + core/sys/windows/errorrep.lo core/sys/windows/exdisp.lo \ + core/sys/windows/exdispid.lo core/sys/windows/httpext.lo \ + core/sys/windows/idispids.lo core/sys/windows/imagehlp.lo \ + core/sys/windows/imm.lo core/sys/windows/intshcut.lo \ + core/sys/windows/ipexport.lo core/sys/windows/iphlpapi.lo \ + core/sys/windows/ipifcons.lo core/sys/windows/iprtrmib.lo \ + core/sys/windows/iptypes.lo core/sys/windows/isguids.lo \ + core/sys/windows/lm.lo core/sys/windows/lmaccess.lo \ + core/sys/windows/lmalert.lo core/sys/windows/lmapibuf.lo \ + core/sys/windows/lmat.lo core/sys/windows/lmaudit.lo \ + core/sys/windows/lmbrowsr.lo core/sys/windows/lmchdev.lo \ + core/sys/windows/lmconfig.lo core/sys/windows/lmcons.lo \ + core/sys/windows/lmerr.lo core/sys/windows/lmerrlog.lo \ + core/sys/windows/lmmsg.lo core/sys/windows/lmremutl.lo \ + core/sys/windows/lmrepl.lo core/sys/windows/lmserver.lo \ + core/sys/windows/lmshare.lo core/sys/windows/lmsname.lo \ + core/sys/windows/lmstats.lo core/sys/windows/lmsvc.lo \ + core/sys/windows/lmuse.lo core/sys/windows/lmuseflg.lo \ + core/sys/windows/lmwksta.lo core/sys/windows/lzexpand.lo \ + core/sys/windows/mapi.lo core/sys/windows/mciavi.lo \ + core/sys/windows/mcx.lo core/sys/windows/mgmtapi.lo \ + core/sys/windows/mmsystem.lo core/sys/windows/msacm.lo \ + core/sys/windows/mshtml.lo core/sys/windows/mswsock.lo \ + core/sys/windows/nb30.lo core/sys/windows/nddeapi.lo \ + core/sys/windows/nspapi.lo core/sys/windows/ntdef.lo \ + core/sys/windows/ntdll.lo core/sys/windows/ntldap.lo \ + core/sys/windows/ntsecapi.lo core/sys/windows/ntsecpkg.lo \ + core/sys/windows/oaidl.lo core/sys/windows/objbase.lo \ + core/sys/windows/objfwd.lo core/sys/windows/objidl.lo \ + core/sys/windows/objsafe.lo core/sys/windows/ocidl.lo \ + core/sys/windows/odbcinst.lo core/sys/windows/ole.lo \ + core/sys/windows/ole2.lo core/sys/windows/ole2ver.lo \ + core/sys/windows/oleacc.lo core/sys/windows/oleauto.lo \ + core/sys/windows/olectl.lo core/sys/windows/olectlid.lo \ + core/sys/windows/oledlg.lo core/sys/windows/oleidl.lo \ + core/sys/windows/pbt.lo core/sys/windows/powrprof.lo \ + core/sys/windows/prsht.lo core/sys/windows/psapi.lo \ + core/sys/windows/rapi.lo core/sys/windows/ras.lo \ + core/sys/windows/rasdlg.lo core/sys/windows/raserror.lo \ + core/sys/windows/rassapi.lo core/sys/windows/reason.lo \ + core/sys/windows/regstr.lo core/sys/windows/richedit.lo \ + core/sys/windows/richole.lo core/sys/windows/rpc.lo \ + core/sys/windows/rpcdce.lo core/sys/windows/rpcdce2.lo \ + core/sys/windows/rpcdcep.lo core/sys/windows/rpcndr.lo \ + core/sys/windows/rpcnsi.lo core/sys/windows/rpcnsip.lo \ + core/sys/windows/rpcnterr.lo core/sys/windows/schannel.lo \ + core/sys/windows/sdkddkver.lo core/sys/windows/secext.lo \ + core/sys/windows/security.lo core/sys/windows/servprov.lo \ + core/sys/windows/setupapi.lo core/sys/windows/shellapi.lo \ + core/sys/windows/shldisp.lo core/sys/windows/shlguid.lo \ + core/sys/windows/shlobj.lo core/sys/windows/shlwapi.lo \ + core/sys/windows/snmp.lo core/sys/windows/sql.lo \ + core/sys/windows/sqlext.lo core/sys/windows/sqltypes.lo \ + core/sys/windows/sqlucode.lo core/sys/windows/sspi.lo \ + core/sys/windows/stacktrace.lo core/sys/windows/stat.lo \ + core/sys/windows/stdc/malloc.lo core/sys/windows/stdc/time.lo \ + core/sys/windows/subauth.lo core/sys/windows/threadaux.lo \ + core/sys/windows/tlhelp32.lo core/sys/windows/tmschema.lo \ + core/sys/windows/unknwn.lo core/sys/windows/uuid.lo \ + core/sys/windows/vfw.lo core/sys/windows/w32api.lo \ + core/sys/windows/winbase.lo core/sys/windows/winber.lo \ + core/sys/windows/wincon.lo core/sys/windows/wincrypt.lo \ + core/sys/windows/windef.lo core/sys/windows/windows.lo \ + core/sys/windows/winerror.lo core/sys/windows/wingdi.lo \ + core/sys/windows/winhttp.lo core/sys/windows/wininet.lo \ + core/sys/windows/winioctl.lo core/sys/windows/winldap.lo \ + core/sys/windows/winnetwk.lo core/sys/windows/winnls.lo \ + core/sys/windows/winnt.lo core/sys/windows/winperf.lo \ + core/sys/windows/winreg.lo core/sys/windows/winsock2.lo \ + core/sys/windows/winspool.lo core/sys/windows/winsvc.lo \ + core/sys/windows/winuser.lo core/sys/windows/winver.lo \ + core/sys/windows/wtsapi32.lo core/sys/windows/wtypes.lo @DRUNTIME_OS_MINGW_TRUE@am__objects_22 = $(am__objects_21) \ @DRUNTIME_OS_MINGW_TRUE@ config/mingw/libgdruntime_la-msvc.lo am__objects_23 = core/sys/solaris/dlfcn.lo core/sys/solaris/elf.lo \ @@ -1041,13 +1041,14 @@ DRUNTIME_DSOURCES_SOLARIS = core/sys/solaris/dlfcn.d \ DRUNTIME_DSOURCES_WINDOWS = core/sys/windows/accctrl.d \ core/sys/windows/aclapi.d core/sys/windows/aclui.d \ core/sys/windows/basetsd.d core/sys/windows/basetyps.d \ - core/sys/windows/cderr.d core/sys/windows/cguid.d \ - core/sys/windows/com.d core/sys/windows/comcat.d \ - core/sys/windows/commctrl.d core/sys/windows/commdlg.d \ - core/sys/windows/core.d core/sys/windows/cpl.d \ - core/sys/windows/cplext.d core/sys/windows/custcntl.d \ - core/sys/windows/dbghelp.d core/sys/windows/dbghelp_types.d \ - core/sys/windows/dbt.d core/sys/windows/dde.d core/sys/windows/ddeml.d \ + core/sys/windows/bcrypt.d core/sys/windows/cderr.d \ + core/sys/windows/cguid.d core/sys/windows/com.d \ + core/sys/windows/comcat.d core/sys/windows/commctrl.d \ + core/sys/windows/commdlg.d core/sys/windows/core.d \ + core/sys/windows/cpl.d core/sys/windows/cplext.d \ + core/sys/windows/custcntl.d core/sys/windows/dbghelp.d \ + core/sys/windows/dbghelp_types.d core/sys/windows/dbt.d \ + core/sys/windows/dde.d core/sys/windows/ddeml.d \ core/sys/windows/dhcpcsdk.d core/sys/windows/dlgs.d \ core/sys/windows/dll.d core/sys/windows/docobj.d \ core/sys/windows/errorrep.d core/sys/windows/exdisp.d \ @@ -1767,6 +1768,7 @@ core/sys/windows/aclapi.lo: core/sys/windows/$(am__dirstamp) core/sys/windows/aclui.lo: core/sys/windows/$(am__dirstamp) core/sys/windows/basetsd.lo: core/sys/windows/$(am__dirstamp) core/sys/windows/basetyps.lo: core/sys/windows/$(am__dirstamp) +core/sys/windows/bcrypt.lo: core/sys/windows/$(am__dirstamp) core/sys/windows/cderr.lo: core/sys/windows/$(am__dirstamp) core/sys/windows/cguid.lo: core/sys/windows/$(am__dirstamp) core/sys/windows/com.lo: core/sys/windows/$(am__dirstamp) diff --git a/libphobos/libdruntime/core/internal/abort.d b/libphobos/libdruntime/core/internal/abort.d index 6942f7e..c0adde9 100644 --- a/libphobos/libdruntime/core/internal/abort.d +++ b/libphobos/libdruntime/core/internal/abort.d @@ -6,7 +6,7 @@ module core.internal.abort; */ void abort(scope string msg, scope string filename = __FILE__, size_t line = __LINE__) @nogc nothrow @safe { - import core.stdc.stdlib: c_abort = abort; + import core.stdc.stdlib : c_abort = abort; // use available OS system calls to print the message to stderr version (Posix) { diff --git a/libphobos/libdruntime/core/internal/array/casting.d b/libphobos/libdruntime/core/internal/array/casting.d index 4366da8..54e7463 100644 --- a/libphobos/libdruntime/core/internal/array/casting.d +++ b/libphobos/libdruntime/core/internal/array/casting.d @@ -136,7 +136,7 @@ TTo[] __ArrayCast(TFrom, TTo)(return scope TFrom[] from) @nogc pure @trusted if (msg != expected) { - import core.stdc.stdio; + import core.stdc.stdio : printf; printf("Expected: |%.*s|\n", cast(int) expected.length, expected.ptr); printf("Actual : |%.*s|\n", cast(int) msg.length, msg.ptr); assert(false); diff --git a/libphobos/libdruntime/core/internal/array/construction.d b/libphobos/libdruntime/core/internal/array/construction.d index c5d8c79..45a1ce5 100644 --- a/libphobos/libdruntime/core/internal/array/construction.d +++ b/libphobos/libdruntime/core/internal/array/construction.d @@ -13,7 +13,7 @@ import core.internal.traits : Unqual; debug(PRINTF) { - import core.stdc.stdio; + import core.stdc.stdio : printf; } /** @@ -46,7 +46,6 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from, char* ma import core.lifetime : copyEmplace; import core.stdc.string : memcpy; import core.stdc.stdint : uintptr_t; - debug(PRINTF) import core.stdc.stdio : printf; debug(PRINTF) printf("_d_arrayctor(from = %p,%zd) size = %zd\n", from.ptr, from.length, T.sizeof); diff --git a/libphobos/libdruntime/core/internal/array/duplication.d b/libphobos/libdruntime/core/internal/array/duplication.d index 9df8489..b5222b3 100644 --- a/libphobos/libdruntime/core/internal/array/duplication.d +++ b/libphobos/libdruntime/core/internal/array/duplication.d @@ -327,7 +327,7 @@ U[] _dup(T, U)(T[] a) if (!__traits(isPOD, T)) { if (l != 0xDEADBEEF) { - import core.stdc.stdio; + import core.stdc.stdio : fflush, printf, stdout; printf("Unexpected value: %lld\n", l); fflush(stdout); assert(false); diff --git a/libphobos/libdruntime/core/internal/array/utils.d b/libphobos/libdruntime/core/internal/array/utils.d index 03d4144..e7a661a 100644 --- a/libphobos/libdruntime/core/internal/array/utils.d +++ b/libphobos/libdruntime/core/internal/array/utils.d @@ -55,7 +55,7 @@ version (D_ProfileGC) // FIXME: use rt.tracegc.accumulator when it is accessable in the future. version (tracegc) } ~ "{\n" ~ q{ - import core.stdc.stdio; + import core.stdc.stdio : printf; printf("%sTrace file = '%.*s' line = %d function = '%.*s' type = %.*s\n", } ~ "\"" ~ Hook ~ "\".ptr," ~ q{ diff --git a/libphobos/libdruntime/core/internal/gc/bits.d b/libphobos/libdruntime/core/internal/gc/bits.d index a060e65..7aeb2e2 100644 --- a/libphobos/libdruntime/core/internal/gc/bits.d +++ b/libphobos/libdruntime/core/internal/gc/bits.d @@ -10,9 +10,9 @@ module core.internal.gc.bits; import core.internal.gc.os : os_mem_map, os_mem_unmap, HaveFork; import core.bitop; -import core.stdc.string; -import core.stdc.stdlib; import core.exception : onOutOfMemoryError; +import core.stdc.stdlib : calloc, free; +import core.stdc.string : memcpy, memset; // use version gcbitsSingleBitOperation to disable optimizations that use // word operands on bulk operation copyRange, setRange, clrRange, etc. diff --git a/libphobos/libdruntime/core/internal/gc/blkcache.d b/libphobos/libdruntime/core/internal/gc/blkcache.d index b141a69..07027f5 100644 --- a/libphobos/libdruntime/core/internal/gc/blkcache.d +++ b/libphobos/libdruntime/core/internal/gc/blkcache.d @@ -44,8 +44,7 @@ else { if (!__blkcache_storage) { - import core.stdc.stdlib; - import core.stdc.string; + import core.stdc.stdlib : calloc; import core.thread.threadbase; auto tBase = ThreadBase.getThis(); if (tBase is null) @@ -68,7 +67,7 @@ else { if (__blkcache_storage) { - import core.stdc.stdlib; + import core.stdc.stdlib : free; import core.thread.threadbase; auto tBase = ThreadBase.getThis(); if (tBase !is null) diff --git a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d index b5d9802..4cb7b57 100644 --- a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d +++ b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d @@ -15,7 +15,7 @@ module core.internal.gc.impl.conservative.gc; //debug = PARALLEL_PRINTF; // turn on printf's //debug = COLLECT_PRINTF; // turn on printf's //debug = MARK_PRINTF; // turn on printf's -//debug = PRINTF_TO_FILE; // redirect printf's ouptut to file "gcx.log" +//debug = PRINTF_TO_FILE; // redirect printf's output to file "gcx.log" //debug = LOGGING; // log allocations / frees //debug = MEMSTOMP; // stomp on memory //debug = SENTINEL; // add underrun/overrrun protection @@ -43,7 +43,7 @@ import core.internal.spinlock; import core.internal.gc.pooltable; import core.internal.gc.blkcache; -import cstdlib = core.stdc.stdlib : calloc, free, malloc, realloc; +import cstdlib = core.stdc.stdlib; import core.stdc.string : memcpy, memset, memmove; import core.bitop; import core.thread; @@ -4800,7 +4800,7 @@ debug(PRINTF_TO_FILE) } len += fprintf(gcx_fh, fmt, args); fflush(gcx_fh); - import core.stdc.string; + import core.stdc.string : strlen; hadNewline = fmt && fmt[0] && fmt[strlen(fmt) - 1] == '\n'; return len; } @@ -5266,8 +5266,8 @@ version (D_LP64) unittest catch (OutOfMemoryError) { // ignore if the system still doesn't have enough virtual memory - import core.stdc.stdio; - printf("%s(%d): out-of-memory execption ignored, phys_mem = %zd", + import core.stdc.stdio : printf; + printf("%s(%d): out-of-memory exception ignored, phys_mem = %zd", __FILE__.ptr, __LINE__, phys_mem); } } @@ -5321,7 +5321,7 @@ unittest unittest { import core.memory; - import core.stdc.stdio; + import core.stdc.stdio : printf; // allocate from large pool auto o = GC.malloc(10); diff --git a/libphobos/libdruntime/core/internal/gc/os.d b/libphobos/libdruntime/core/internal/gc/os.d index 9142708..d5431d4 100644 --- a/libphobos/libdruntime/core/internal/gc/os.d +++ b/libphobos/libdruntime/core/internal/gc/os.d @@ -33,8 +33,10 @@ else version (Posix) else version (WatchOS) version = Darwin; - import core.stdc.stdlib; + public import core.sys.posix.unistd : fork, pid_t; + import core.stdc.errno : ECHILD, EINTR, errno; import core.sys.posix.sys.mman : MAP_ANON, MAP_FAILED, MAP_PRIVATE, MAP_SHARED, mmap, munmap, PROT_READ, PROT_WRITE; + import core.sys.posix.sys.wait : waitpid, WNOHANG; /// Possible results for the wait_pid() function. @@ -74,15 +76,11 @@ else version (Posix) return ChildStatus.done; } - public import core.sys.posix.unistd : fork, pid_t; - import core.stdc.errno : ECHILD, EINTR, errno; - import core.sys.posix.sys.wait : waitpid, WNOHANG; - //version = GC_Use_Alloc_MMap; } else { - import core.stdc.stdlib; + import core.stdc.stdlib : free, malloc; //version = GC_Use_Alloc_Malloc; } diff --git a/libphobos/libdruntime/core/internal/gc/pooltable.d b/libphobos/libdruntime/core/internal/gc/pooltable.d index f9ec3d2..412ade4 100644 --- a/libphobos/libdruntime/core/internal/gc/pooltable.d +++ b/libphobos/libdruntime/core/internal/gc/pooltable.d @@ -7,7 +7,7 @@ */ module core.internal.gc.pooltable; -static import cstdlib=core.stdc.stdlib; +static import cstdlib = core.stdc.stdlib; struct PoolTable(Pool) { diff --git a/libphobos/libdruntime/core/internal/parseoptions.d b/libphobos/libdruntime/core/internal/parseoptions.d index 2dd3ec8..bc47555 100644 --- a/libphobos/libdruntime/core/internal/parseoptions.d +++ b/libphobos/libdruntime/core/internal/parseoptions.d @@ -9,12 +9,10 @@ module core.internal.parseoptions; -import core.stdc.stdlib; -import core.stdc.stdio; -import core.stdc.ctype; -import core.stdc.string; -import core.vararg; import core.internal.traits : externDFunc, hasUDA; +import core.stdc.ctype : isdigit, isspace; +import core.stdc.stdio : fprintf, snprintf, sscanf, stderr; +import core.vararg; @nogc nothrow: diff --git a/libphobos/libdruntime/core/internal/qsort.d b/libphobos/libdruntime/core/internal/qsort.d index fce1067..8938a44 100644 --- a/libphobos/libdruntime/core/internal/qsort.d +++ b/libphobos/libdruntime/core/internal/qsort.d @@ -10,8 +10,6 @@ module core.internal.qsort; //debug=qsort; -import core.stdc.stdlib; - debug (qsort) import core.stdc.stdio : printf; version (OSX) @@ -150,6 +148,8 @@ else version (CRuntime_UClibc) } else { + import core.stdc.stdlib : qsort; + private TypeInfo tiglobal; extern (C) void[] _adSort(return scope void[] a, TypeInfo ti) @@ -166,7 +166,6 @@ else unittest { - debug(qsort) import core.stdc.stdio; debug(qsort) printf("array.sort.unittest()\n"); int[] a = new int[10]; diff --git a/libphobos/libdruntime/core/internal/util/array.d b/libphobos/libdruntime/core/internal/util/array.d index 066ee7e..1a5c41b 100644 --- a/libphobos/libdruntime/core/internal/util/array.d +++ b/libphobos/libdruntime/core/internal/util/array.d @@ -10,7 +10,7 @@ module core.internal.util.array; import core.internal.string; -import core.stdc.stdint; +import core.stdc.stdint : uintptr_t; // TLS storage shared for all error messages. diff --git a/libphobos/libdruntime/core/runtime.d b/libphobos/libdruntime/core/runtime.d index ff1df7f..d76e14a 100644 --- a/libphobos/libdruntime/core/runtime.d +++ b/libphobos/libdruntime/core/runtime.d @@ -29,10 +29,12 @@ version (GNU) // It does however prevent the unittest SEGV handler to be installed, // which is desireable as it uses backtrace directly. private enum hasExecinfo = false; + version = LibBacktrace_TraceHandler; } else version (DRuntime_Use_Libunwind) { - import core.internal.backtrace.libunwind; + version = DefineBacktrace_using_UnwindBacktrace; + // This shouldn't be necessary but ensure that code doesn't get mixed // It does however prevent the unittest SEGV handler to be installed, // which is desireable as it uses backtrace directly. @@ -611,7 +613,9 @@ extern (C) UnitTestResult runModuleUnitTests() } else static if (hasExecinfo) { - import core.sys.posix.signal; // segv handler + // segv handler + import core.sys.posix.signal : SA_RESETHAND, SA_SIGINFO, sigaction, sigaction_t, SIGBUS, sigfillset, siginfo_t, + SIGSEGV; static extern (C) void unittestSegvHandler( int signum, siginfo_t* info, void* ptr ) nothrow { @@ -717,6 +721,44 @@ extern (C) UnitTestResult runModuleUnitTests() return results; } +version (DefineBacktrace_using_UnwindBacktrace) +{ + import core.internal.backtrace.unwind; + + private int backtrace(void** buffer, int maxSize) nothrow + { + if (maxSize < 0) return 0; + + struct State + { + void** buffer; + int maxSize; + int entriesWritten = 0; + } + + static extern(C) int handler(_Unwind_Context* context, void* statePtr) + { + auto state = cast(State*)statePtr; + if (state.entriesWritten >= state.maxSize) return _URC_END_OF_STACK; + + auto instructionPtr = _Unwind_GetIP(context); + if (!instructionPtr) return _URC_END_OF_STACK; + + state.buffer[state.entriesWritten] = cast(void*)instructionPtr; + ++state.entriesWritten; + + return _URC_NO_REASON; + } + + State state; + state.buffer = buffer; + state.maxSize = maxSize; + _Unwind_Backtrace(&handler, &state); + + return state.entriesWritten; + } +} + /** * Get the default `Throwable.TraceInfo` implementation for the platform * @@ -833,14 +875,11 @@ void defaultTraceDeallocator(Throwable.TraceInfo info) nothrow free(cast(void *)obj); } -version (DRuntime_Use_Libunwind) +version (LibBacktrace_TraceHandler) { - import core.internal.backtrace.handler; - - alias DefaultTraceInfo = LibunwindHandler; } /// Default implementation for most POSIX systems -else static if (hasExecinfo) private class DefaultTraceInfo : Throwable.TraceInfo +else version (Posix) private class DefaultTraceInfo : Throwable.TraceInfo { import core.demangle; import core.stdc.stdlib : free; @@ -907,30 +946,100 @@ else static if (hasExecinfo) private class DefaultTraceInfo : Throwable.TraceInf else version (Darwin) enum enableDwarf = true; else enum enableDwarf = false; - const framelist = backtrace_symbols( callstack.ptr, numframes ); - scope(exit) free(cast(void*) framelist); - - static if (enableDwarf) + static if (hasExecinfo) { - import core.internal.backtrace.dwarf; - return traceHandlerOpApplyImpl(numframes, - i => callstack[i], - (i) { auto str = framelist[i][0 .. strlen(framelist[i])]; return getMangledSymbolName(str); }, - dg); + const framelist = backtrace_symbols( callstack.ptr, numframes ); + scope(exit) free(cast(void*) framelist); + + static if (enableDwarf) + { + import core.internal.backtrace.dwarf; + return traceHandlerOpApplyImpl(numframes, + i => callstack[i], + (i) { auto str = framelist[i][0 .. strlen(framelist[i])]; return getMangledSymbolName(str); }, + dg); + } + else + { + int ret = 0; + for (size_t pos = 0; pos < numframes; ++pos) + { + char[4096] fixbuf = void; + auto buf = framelist[pos][0 .. strlen(framelist[pos])]; + buf = fixline( buf, fixbuf ); + ret = dg( pos, buf ); + if ( ret ) + break; + } + return ret; + } } else { - int ret = 0; - for (size_t pos = 0; pos < numframes; ++pos) + // https://code.woboq.org/userspace/glibc/debug/backtracesyms.c.html + // The logic that glibc's backtrace use is to check for for `dli_fname`, + // the file name, and error if not present, then check for `dli_sname`. + // In case `dli_fname` is present but not `dli_sname`, the address is + // printed related to the file. We just print the file. + static const(char)[] getFrameName (const(void)* ptr) + { + import core.sys.posix.dlfcn; + Dl_info info = void; + // Note: See the module documentation about `-L--export-dynamic` + if (dladdr(ptr, &info)) + { + // Return symbol name if possible + if (info.dli_sname !is null && info.dli_sname[0] != '\0') + return info.dli_sname[0 .. strlen(info.dli_sname)]; + + // Fall back to file name + if (info.dli_fname !is null && info.dli_fname[0] != '\0') + return info.dli_fname[0 .. strlen(info.dli_fname)]; + } + + // `dladdr` failed + return "<ERROR: Unable to retrieve function name>"; + } + + static if (enableDwarf) { - char[4096] fixbuf = void; - auto buf = framelist[pos][0 .. strlen(framelist[pos])]; - buf = fixline( buf, fixbuf ); - ret = dg( pos, buf ); - if ( ret ) - break; + import core.internal.backtrace.dwarf; + return traceHandlerOpApplyImpl(numframes, + i => callstack[i], + i => getFrameName(callstack[i]), + dg); + } + else + { + // Poor man solution. Does not show line numbers, but does (potentially) show a backtrace of function names. + import core.internal.container.array; + Array!(const(char)[]) frameNames; + frameNames.length = numframes; + size_t startIdx; + foreach (idx; 0 .. numframes) + { + frameNames[idx] = getFrameName(callstack[idx]); + + // NOTE: The first few frames with the current implementation are + // inside core.runtime and the object code, so eliminate + // these for readability. + // They also might depend on build parameters, which would make + // using a fixed number of frames otherwise brittle. + version (LDC) enum BaseExceptionFunctionName = "_d_throw_exception"; + else enum BaseExceptionFunctionName = "_d_throwdwarf"; + if (!startIdx && frameNames[idx] == BaseExceptionFunctionName) + startIdx = idx + 1; + } + + int ret = 0; + foreach (idx; startIdx .. numframes) + { + ret = dg( idx, frameNames[idx] ); + if ( ret ) + break; + } + return ret; } - return ret; } } @@ -948,40 +1057,43 @@ private: void*[MAXFRAMES] callstack = void; private: - const(char)[] fixline( const(char)[] buf, return ref char[4096] fixbuf ) const + static if (hasExecinfo) { - size_t symBeg, symEnd; - - getMangledSymbolName(buf, symBeg, symEnd); - - enum min = (size_t a, size_t b) => a <= b ? a : b; - if (symBeg == symEnd || symBeg >= fixbuf.length) - { - immutable len = min(buf.length, fixbuf.length); - fixbuf[0 .. len] = buf[0 .. len]; - return fixbuf[0 .. len]; - } - else + const(char)[] fixline( const(char)[] buf, return ref char[4096] fixbuf ) const { - fixbuf[0 .. symBeg] = buf[0 .. symBeg]; + size_t symBeg, symEnd; - auto sym = demangle(buf[symBeg .. symEnd], fixbuf[symBeg .. $], getCXXDemangler()); + getMangledSymbolName(buf, symBeg, symEnd); - if (sym.ptr !is fixbuf.ptr + symBeg) + enum min = (size_t a, size_t b) => a <= b ? a : b; + if (symBeg == symEnd || symBeg >= fixbuf.length) { - // demangle reallocated the buffer, copy the symbol to fixbuf - immutable len = min(fixbuf.length - symBeg, sym.length); - memmove(fixbuf.ptr + symBeg, sym.ptr, len); - if (symBeg + len == fixbuf.length) - return fixbuf[]; + immutable len = min(buf.length, fixbuf.length); + fixbuf[0 .. len] = buf[0 .. len]; + return fixbuf[0 .. len]; } + else + { + fixbuf[0 .. symBeg] = buf[0 .. symBeg]; + + auto sym = demangle(buf[symBeg .. symEnd], fixbuf[symBeg .. $], getCXXDemangler()); + + if (sym.ptr !is fixbuf.ptr + symBeg) + { + // demangle reallocated the buffer, copy the symbol to fixbuf + immutable len = min(fixbuf.length - symBeg, sym.length); + memmove(fixbuf.ptr + symBeg, sym.ptr, len); + if (symBeg + len == fixbuf.length) + return fixbuf[]; + } - immutable pos = symBeg + sym.length; - assert(pos < fixbuf.length); - immutable tail = buf.length - symEnd; - immutable len = min(fixbuf.length - pos, tail); - fixbuf[pos .. pos + len] = buf[symEnd .. symEnd + len]; - return fixbuf[0 .. pos + len]; + immutable pos = symBeg + sym.length; + assert(pos < fixbuf.length); + immutable tail = buf.length - symEnd; + immutable len = min(fixbuf.length - pos, tail); + fixbuf[pos .. pos + len] = buf[symEnd .. symEnd + len]; + return fixbuf[0 .. pos + len]; + } } } } diff --git a/libphobos/libdruntime/core/stdc/config.d b/libphobos/libdruntime/core/stdc/config.d index ca833ea..c95fe65 100644 --- a/libphobos/libdruntime/core/stdc/config.d +++ b/libphobos/libdruntime/core/stdc/config.d @@ -11,9 +11,6 @@ * Standards: ISO/IEC 9899:1999 (E) */ -/* NOTE: This file has been patched from the original DMD distribution to - * work with the GDC compiler. - */ module core.stdc.config; version (StdDdoc) diff --git a/libphobos/libdruntime/core/sys/windows/bcrypt.d b/libphobos/libdruntime/core/sys/windows/bcrypt.d new file mode 100644 index 0000000..6edf0df --- /dev/null +++ b/libphobos/libdruntime/core/sys/windows/bcrypt.d @@ -0,0 +1,900 @@ +/** + * Cryptographic primitives + * + * Translated from MinGW-w64 Windows headers + * + * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) + * Authors: Aya Partridge + * Source: $(DRUNTIMESRC core/sys/windows/_bcrypt.d) + */ +module core.sys.windows.bcrypt; +version (Windows): + +pragma(lib, "bcrypt"); + +import core.sys.windows.ntdef, core.sys.windows.sdkddkver, core.sys.windows.winbase, core.sys.windows.windef, core.sys.windows.winnt; + +pragma(inline, true) +bool BCRYPT_SUCCESS(NTSTATUS Status) @nogc nothrow pure @safe => Status >= 0; + +enum BCRYPT_OBJECT_ALIGNMENT = 16; + +enum { + BCRYPT_KDF_HASH = "HASH"w, + BCRYPT_KDF_HMAC = "HMAC"w, + BCRYPT_KDF_TLS_PRF = "TLS_PRF"w, + BCRYPT_KDF_SP80056A_CONCAT = "SP800_56A_CONCAT"w, +} +static if (NTDDI_VERSION >= NTDDI_WINBLUE) +enum { + BCRYPT_KDF_RAW_SECRET = "TRUNCATE"w, +} +static if (NTDDI_VERSION >= NTDDI_WIN10_RS4) +enum { + BCRYPT_KDF_HKDF = "HKDF"w, +} + +enum { + KDF_HASH_ALGORITHM = 0x0, + KDF_SECRET_PREPEND = 0x1, + KDF_SECRET_APPEND = 0x2, + KDF_HMAC_KEY = 0x3, + KDF_TLS_PRF_LABEL = 0x4, + KDF_TLS_PRF_SEED = 0x5, + KDF_SECRET_HANDLE = 0x6, +} +static if (NTDDI_VERSION >= NTDDI_WIN7) +enum { + KDF_TLS_PRF_PROTOCOL = 0x7, + KDF_ALGORITHMID = 0x8, + KDF_PARTYUINFO = 0x9, + KDF_PARTYVINFO = 0xA, + KDF_SUPPPUBINFO = 0xB, + KDF_SUPPPRIVINFO = 0xC, +} +static if (NTDDI_VERSION >= NTDDI_WIN8) +enum { + KDF_LABEL = 0xD, + KDF_CONTEXT = 0xE, + KDF_SALT = 0xF, + KDF_ITERATION_COUNT = 0x10, + KDF_GENERIC_PARAMETER = 0x11, + KDF_KEYBITLENGTH = 0x12, +} +static if (NTDDI_VERSION >= NTDDI_WIN10_RS4) +enum { + KDF_HKDF_SALT = 0x13, + KDF_HKDF_INFO = 0x14, +} + +enum KDF_USE_SECRET_AS_HMAC_KEY_FLAG = 1; + +enum BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_VERSION = 1; + +enum { + BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG = 0x00000001, + BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG = 0x00000002, +} + +pragma(inline, true) +void BCRYPT_INIT_AUTH_MODE_INFO(ref BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO _AUTH_INFO_STRUCT_) @nogc nothrow pure @safe { + (() @trusted => RtlZeroMemory(&_AUTH_INFO_STRUCT_, _AUTH_INFO_STRUCT_.sizeof))(); + _AUTH_INFO_STRUCT_.cbSize = _AUTH_INFO_STRUCT_.sizeof; + _AUTH_INFO_STRUCT_.dwInfoVersion = BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_VERSION; +} + +enum { + BCRYPT_OPAQUE_KEY_BLOB = "OpaqueKeyBlob"w, + BCRYPT_KEY_DATA_BLOB = "KeyDataBlob"w, +} +static if (NTDDI_VERSION >= NTDDI_WIN7) +enum { + BCRYPT_AES_WRAP_KEY_BLOB = "Rfc3565KeyWrapBlob"w, +} + +enum { + BCRYPT_ALGORITHM_NAME = "AlgorithmName"w, + BCRYPT_AUTH_TAG_LENGTH = "AuthTagLength"w, + BCRYPT_BLOCK_LENGTH = "BlockLength"w, + BCRYPT_BLOCK_SIZE_LIST = "BlockSizeList"w, + BCRYPT_CHAINING_MODE = "ChainingMode"w, + BCRYPT_CHAIN_MODE_CBC = "ChainingModeCBC"w, + BCRYPT_CHAIN_MODE_CCM = "ChainingModeCCM"w, + BCRYPT_CHAIN_MODE_CFB = "ChainingModeCFB"w, + BCRYPT_CHAIN_MODE_ECB = "ChainingModeECB"w, + BCRYPT_CHAIN_MODE_GCM = "ChainingModeGCM"w, + BCRYPT_CHAIN_MODE_NA = "ChainingModeN/A"w, + BCRYPT_EFFECTIVE_KEY_LENGTH = "EffectiveKeyLength"w, + BCRYPT_HASH_BLOCK_LENGTH = "HashBlockLength"w, + BCRYPT_HASH_LENGTH = "HashDigestLength"w, + BCRYPT_HASH_OID_LIST = "HashOIDList"w, + BCRYPT_INITIALIZATION_VECTOR = "IV"w, + BCRYPT_IS_KEYED_HASH = "IsKeyedHash"w, + BCRYPT_IS_REUSABLE_HASH = "IsReusableHash"w, + BCRYPT_KEY_LENGTH = "KeyLength"w, + BCRYPT_KEY_LENGTHS = "KeyLengths"w, + BCRYPT_KEY_OBJECT_LENGTH = "KeyObjectLength"w, + BCRYPT_KEY_STRENGTH = "KeyStrength"w, + BCRYPT_MESSAGE_BLOCK_LENGTH = "MessageBlockLength"w, + BCRYPT_OBJECT_LENGTH = "ObjectLength"w, + BCRYPT_PADDING_SCHEMES = "PaddingSchemes"w, + BCRYPT_PCP_PLATFORM_TYPE_PROPERTY = "PCP_PLATFORM_TYPE"w, + BCRYPT_PCP_PROVIDER_VERSION_PROPERTY = "PCP_PROVIDER_VERSION"w, + BCRYPT_PRIMITIVE_TYPE = "PrimitiveType"w, + BCRYPT_PROVIDER_HANDLE = "ProviderHandle"w, + BCRYPT_PUBLIC_KEY_LENGTH = "PublicKeyLength"w, + BCRYPT_SIGNATURE_LENGTH = "SignatureLength"w, +} +static if (NTDDI_VERSION >= NTDDI_WINBLUE) +enum { + BCRYPT_MULTI_OBJECT_LENGTH = "MultiObjectLength"w, +} +static if (NTDDI_VERSION >= NTDDI_WIN10_RS4) +enum { + BCRYPT_IS_IFX_TPM_WEAK_KEY = "IsIfxTpmWeakKey"w, + BCRYPT_HKDF_HASH_ALGORITHM = "HkdfHashAlgorithm"w, + BCRYPT_HKDF_SALT_AND_FINALIZE = "HkdfSaltAndFinalize"w, + BCRYPT_HKDF_PRK_AND_FINALIZE = "HkdfPrkAndFinalize"w, +} +static if (NTDDI_VERSION >= NTDDI_WIN11_ZN) +enum { + BCRYPT_FUNCTION_NAME_STRING = "FunctionNameString"w, + BCRYPT_CUSTOMIZATION_STRING = "CustomizationString"w, +} +static if (NTDDI_VERSION >= NTDDI_WIN11_GA) +enum { + BCRYPT_CHAIN_MODE_KWP = "ChainingModeKWP"w, +} + +enum { + BCRYPT_SUPPORTED_PAD_ROUTER = 0x00000001, + BCRYPT_SUPPORTED_PAD_PKCS1_ENC = 0x00000002, + BCRYPT_SUPPORTED_PAD_PKCS1_SIG = 0x00000004, + BCRYPT_SUPPORTED_PAD_OAEP = 0x00000008, + BCRYPT_SUPPORTED_PAD_PSS = 0x00000010, +} + +enum BCRYPT_PROV_DISPATCH = 0x00000001; + +enum BCRYPT_BLOCK_PADDING = 0x00000001; + +static if (NTDDI_VERSION >= NTDDI_WIN10_CO) +enum BCRYPT_GENERATE_IV = 0x00000020; + +enum { + BCRYPT_PAD_NONE = 0x00000001, + BCRYPT_PAD_PKCS1 = 0x00000002, + BCRYPT_PAD_OAEP = 0x00000004, + BCRYPT_PAD_PSS = 0x00000008, +} +static if (NTDDI_VERSION >= NTDDI_WINBLUE) +enum { + BCRYPT_PAD_PKCS1_OPTIONAL_HASH_OID = 0x00000010, +} + +enum BCRYPTBUFFER_VERSION = 0; + +struct BCRYPT_KEY_LENGTHS_STRUCT { + ULONG dwMinLength; + ULONG dwMaxLength; + ULONG dwIncrement; +} + +alias BCRYPT_AUTH_TAG_LENGTHS_STRUCT = BCRYPT_KEY_LENGTHS_STRUCT; + +struct BCRYPT_OID { + ULONG cbOID; + PUCHAR pbOID; +} + +struct BCRYPT_OID_LIST { + ULONG dwOIDCount; + BCRYPT_OID* pOIDs; +} + +struct BCRYPT_PKCS1_PADDING_INFO { + LPCWSTR pszAlgId; +} + +struct BCRYPT_PSS_PADDING_INFO { + LPCWSTR pszAlgId; + ULONG cbSalt; +} + +struct BCRYPT_OAEP_PADDING_INFO { + LPCWSTR pszAlgId; + PUCHAR pbLabel; + ULONG cbLabel; +} + +struct BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO { + ULONG cbSize; + ULONG dwInfoVersion; + PUCHAR pbNonce; + ULONG cbNonce; + PUCHAR pbAuthData; + ULONG cbAuthData; + PUCHAR pbTag; + ULONG cbTag; + PUCHAR pbMacContext; + ULONG cbMacContext; + ULONG cbAAD; + ULONGLONG cbData; + ULONG dwFlags; +} +alias PBCRYPT_AUTHENTICATED_CIPHER_MODE_INFO = BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO*; + +struct BCryptBuffer { + ULONG cbBuffer; + ULONG BufferType; + PVOID pvBuffer; +} +alias PBCryptBuffer = BCryptBuffer*; + +struct BCryptBufferDesc { + ULONG ulVersion; + ULONG cBuffers; + PBCryptBuffer pBuffers; +} +alias PBCryptBufferDesc = BCryptBufferDesc*; + +enum { + BCRYPT_PUBLIC_KEY_BLOB = "PUBLICBLOB"w, + BCRYPT_PRIVATE_KEY_BLOB = "PRIVATEBLOB"w, +} + +enum { + BCRYPT_RSAPUBLIC_BLOB = "RSAPUBLICBLOB"w, + BCRYPT_RSAPRIVATE_BLOB = "RSAPRIVATEBLOB"w, + LEGACY_RSAPUBLIC_BLOB = "CAPIPUBLICBLOB"w, + LEGACY_RSAPRIVATE_BLOB = "CAPIPRIVATEBLOB"w, +} + +enum { + BCRYPT_RSAPUBLIC_MAGIC = 0x31415352, + BCRYPT_RSAPRIVATE_MAGIC = 0x32415352, +} + +enum BCRYPT_RSAFULLPRIVATE_BLOB = "RSAFULLPRIVATEBLOB"w; + +enum BCRYPT_RSAFULLPRIVATE_MAGIC = 0x33415352; + +static if (NTDDI_VERSION >= NTDDI_WIN8) { + enum BCRYPT_GLOBAL_PARAMETERS = "SecretAgreementParam"w; + enum BCRYPT_PRIVATE_KEY = "PrivKeyVal"w; +} + +enum { + BCRYPT_ECCPUBLIC_BLOB = "ECCPUBLICBLOB"w, + BCRYPT_ECCPRIVATE_BLOB = "ECCPRIVATEBLOB"w, +} +static if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) +enum { + BCRYPT_ECCFULLPUBLIC_BLOB = "ECCFULLPUBLICBLOB"w, + BCRYPT_ECCFULLPRIVATE_BLOB = "ECCFULLPRIVATEBLOB"w, +} + +static if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) +enum SSL_ECCPUBLIC_BLOB = "SSLECCPUBLICBLOB"w; + +enum TLS_13_PRE_SHARED_KEY = "TLS13PRESHAREDKEY"w; + +enum { + BCRYPT_ECDH_PUBLIC_P256_MAGIC = 0x314B4345, + BCRYPT_ECDH_PRIVATE_P256_MAGIC = 0x324B4345, + BCRYPT_ECDH_PUBLIC_P384_MAGIC = 0x334B4345, + BCRYPT_ECDH_PRIVATE_P384_MAGIC = 0x344B4345, + BCRYPT_ECDH_PUBLIC_P521_MAGIC = 0x354B4345, + BCRYPT_ECDH_PRIVATE_P521_MAGIC = 0x364B4345, +} +static if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) +enum { + BCRYPT_ECDH_PUBLIC_GENERIC_MAGIC = 0x504B4345, + BCRYPT_ECDH_PRIVATE_GENERIC_MAGIC = 0x564B4345, +} + +enum { + BCRYPT_ECDSA_PUBLIC_P256_MAGIC = 0x31534345, + BCRYPT_ECDSA_PRIVATE_P256_MAGIC = 0x32534345, + BCRYPT_ECDSA_PUBLIC_P384_MAGIC = 0x33534345, + BCRYPT_ECDSA_PRIVATE_P384_MAGIC = 0x34534345, + BCRYPT_ECDSA_PUBLIC_P521_MAGIC = 0x35534345, + BCRYPT_ECDSA_PRIVATE_P521_MAGIC = 0x36534345, +} +static if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) +enum { + BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC = 0x50444345, + BCRYPT_ECDSA_PRIVATE_GENERIC_MAGIC = 0x56444345, +} + +enum { + BCRYPT_DH_PUBLIC_BLOB = "DHPUBLICBLOB"w, + BCRYPT_DH_PRIVATE_BLOB = "DHPRIVATEBLOB"w, + LEGACY_DH_PUBLIC_BLOB = "CAPIDHPUBLICBLOB"w, + LEGACY_DH_PRIVATE_BLOB = "CAPIDHPRIVATEBLOB"w, +} + +enum { + BCRYPT_DH_PUBLIC_MAGIC = 0x42504844, + BCRYPT_DH_PRIVATE_MAGIC = 0x56504844, +} + +enum { + BCRYPT_DH_PARAMETERS = "DHParameters"w, + BCRYPT_DH_PARAMETERS_MAGIC = 0x4D504844, +} + +enum { + BCRYPT_DSA_PUBLIC_BLOB = "DSAPUBLICBLOB"w, + BCRYPT_DSA_PRIVATE_BLOB = "DSAPRIVATEBLOB"w, + LEGACY_DSA_PUBLIC_BLOB = "CAPIDSAPUBLICBLOB"w, + LEGACY_DSA_PRIVATE_BLOB = "CAPIDSAPRIVATEBLOB"w, + LEGACY_DSA_V2_PUBLIC_BLOB = "V2CAPIDSAPUBLICBLOB"w, + LEGACY_DSA_V2_PRIVATE_BLOB = "V2CAPIDSAPRIVATEBLOB"w, +} + +enum { + BCRYPT_DSA_PUBLIC_MAGIC = 0x42505344, + BCRYPT_DSA_PRIVATE_MAGIC = 0x56505344, + BCRYPT_DSA_PUBLIC_MAGIC_V2 = 0x32425044, + BCRYPT_DSA_PRIVATE_MAGIC_V2 = 0x32565044, +} + +enum { + BCRYPT_KEY_DATA_BLOB_MAGIC = 0x4D42444B, + BCRYPT_KEY_DATA_BLOB_VERSION1 = 0x1, +} + +enum { + BCRYPT_DSA_PARAMETERS = "DSAParameters"w, + BCRYPT_DSA_PARAMETERS_MAGIC = 0x4D505344, + BCRYPT_DSA_PARAMETERS_MAGIC_V2 = 0x324D5044, +} + +enum { + MS_PRIMITIVE_PROVIDER = "Microsoft Primitive Provider"w, + MS_PLATFORM_CRYPTO_PROVIDER = "Microsoft Platform Crypto Provider"w, +} + +enum { + BCRYPT_RSA_ALGORITHM = "RSA"w, + BCRYPT_RSA_SIGN_ALGORITHM = "RSA_SIGN"w, + BCRYPT_DH_ALGORITHM = "DH"w, + BCRYPT_DSA_ALGORITHM = "DSA"w, + BCRYPT_RC2_ALGORITHM = "RC2"w, + BCRYPT_RC4_ALGORITHM = "RC4"w, + BCRYPT_AES_ALGORITHM = "AES"w, + BCRYPT_DES_ALGORITHM = "DES"w, + BCRYPT_DESX_ALGORITHM = "DESX"w, + BCRYPT_3DES_ALGORITHM = "3DES"w, + BCRYPT_3DES_112_ALGORITHM = "3DES_112"w, + BCRYPT_MD2_ALGORITHM = "MD2"w, + BCRYPT_MD4_ALGORITHM = "MD4"w, + BCRYPT_MD5_ALGORITHM = "MD5"w, + BCRYPT_SHA1_ALGORITHM = "SHA1"w, + BCRYPT_SHA256_ALGORITHM = "SHA256"w, + BCRYPT_SHA384_ALGORITHM = "SHA384"w, + BCRYPT_SHA512_ALGORITHM = "SHA512"w, + BCRYPT_AES_GMAC_ALGORITHM = "AES-GMAC"w, + BCRYPT_AES_CMAC_ALGORITHM = "AES-CMAC"w, + BCRYPT_ECDSA_P256_ALGORITHM = "ECDSA_P256"w, + BCRYPT_ECDSA_P384_ALGORITHM = "ECDSA_P384"w, + BCRYPT_ECDSA_P521_ALGORITHM = "ECDSA_P521"w, + BCRYPT_ECDH_P256_ALGORITHM = "ECDH_P256"w, + BCRYPT_ECDH_P384_ALGORITHM = "ECDH_P384"w, + BCRYPT_ECDH_P521_ALGORITHM = "ECDH_P521"w, + BCRYPT_RNG_ALGORITHM = "RNG"w, + BCRYPT_RNG_FIPS186_DSA_ALGORITHM = "FIPS186DSARNG"w, + BCRYPT_RNG_DUAL_EC_ALGORITHM = "DUALECRNG"w, + BCRYPT_SP800108_CTR_HMAC_ALGORITHM = "SP800_108_CTR_HMAC"w, + BCRYPT_SP80056A_CONCAT_ALGORITHM = "SP800_56A_CONCAT"w, + BCRYPT_PBKDF2_ALGORITHM = "PBKDF2"w, + BCRYPT_CAPI_KDF_ALGORITHM = "CAPI_KDF"w, +} + +enum { + BCRYPT_CIPHER_INTERFACE = 0x00000001, + BCRYPT_HASH_INTERFACE = 0x00000002, + BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE = 0x00000003, + BCRYPT_SECRET_AGREEMENT_INTERFACE = 0x00000004, + BCRYPT_SIGNATURE_INTERFACE = 0x00000005, + BCRYPT_RNG_INTERFACE = 0x00000006, + BCRYPT_KEY_DERIVATION_INTERFACE = 0x00000007, +} + +static if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) +enum : BCRYPT_ALG_HANDLE { + BCRYPT_MD2_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000001, + BCRYPT_MD4_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000011, + BCRYPT_MD5_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000021, + BCRYPT_SHA1_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000031, + BCRYPT_SHA256_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000041, + BCRYPT_SHA384_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000051, + BCRYPT_SHA512_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000061, + BCRYPT_RC4_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000071, + BCRYPT_RNG_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000081, + BCRYPT_HMAC_MD5_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000091, + BCRYPT_HMAC_SHA1_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000000A1, + BCRYPT_HMAC_SHA256_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000000B1, + BCRYPT_HMAC_SHA384_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000000C1, + BCRYPT_HMAC_SHA512_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000000D1, + BCRYPT_RSA_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000000E1, + BCRYPT_ECDSA_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000000F1, + + BCRYPT_AES_CMAC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000101, + BCRYPT_AES_GMAC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000111, + BCRYPT_HMAC_MD2_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000121, + BCRYPT_HMAC_MD4_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000131, + + BCRYPT_3DES_CBC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000141, + BCRYPT_3DES_ECB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000151, + BCRYPT_3DES_CFB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000161, + BCRYPT_3DES_112_CBC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000171, + BCRYPT_3DES_112_ECB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000181, + BCRYPT_3DES_112_CFB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000191, + BCRYPT_AES_CBC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000001A1, + BCRYPT_AES_ECB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000001B1, + BCRYPT_AES_CFB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000001C1, + BCRYPT_AES_CCM_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000001D1, + BCRYPT_AES_GCM_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000001E1, + BCRYPT_DES_CBC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000001F1, + BCRYPT_DES_ECB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000201, + BCRYPT_DES_CFB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000211, + BCRYPT_DESX_CBC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000221, + BCRYPT_DESX_ECB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000231, + BCRYPT_DESX_CFB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000241, + BCRYPT_RC2_CBC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000251, + BCRYPT_RC2_ECB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000261, + BCRYPT_RC2_CFB_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000271, + + BCRYPT_DH_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000281, + BCRYPT_ECDH_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000291, + BCRYPT_ECDH_P256_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000002A1, + BCRYPT_ECDH_P384_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000002B1, + BCRYPT_ECDH_P521_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000002C1, + BCRYPT_DSA_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000002D1, + BCRYPT_ECDSA_P256_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000002E1, + BCRYPT_ECDSA_P384_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000002F1, + BCRYPT_ECDSA_P521_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000301, + BCRYPT_RSA_SIGN_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000311, + + BCRYPT_CAPI_KDF_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000321, + BCRYPT_PBKDF2_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000331, + + BCRYPT_SP800108_CTR_HMAC_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000341, + BCRYPT_SP80056A_CONCAT_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000351, + + BCRYPT_TLS1_1_KDF_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000361, + BCRYPT_TLS1_2_KDF_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000371, + + BCRYPT_XTS_AES_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000381, + + BCRYPT_HKDF_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000391, +} +static if (NTDDI_VERSION >= NTDDI_WIN10_FE) +enum { + BCRYPT_CHACHA20_POLY1305_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000003A1, +} +static if (NTDDI_VERSION >= NTDDI_WIN11_ZN) +enum { + BCRYPT_SHA3_256_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000003B1, + BCRYPT_SHA3_384_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000003C1, + BCRYPT_SHA3_512_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000003D1, + BCRYPT_HMAC_SHA3_256_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000003E1, + BCRYPT_HMAC_SHA3_384_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x000003F1, + BCRYPT_HMAC_SHA3_512_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000401, + BCRYPT_CSHAKE128_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000411, + BCRYPT_CSHAKE256_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000421, + BCRYPT_KMAC128_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000431, + BCRYPT_KMAC256_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000441, +} +static if (NTDDI_VERSION >= NTDDI_WIN11_GA) +enum { + BCRYPT_AES_KWP_ALG_HANDLE = cast(BCRYPT_ALG_HANDLE) 0x00000451, +} + +enum { + BCRYPT_ALG_HANDLE_HMAC_FLAG = 0x00000008, + BCRYPT_CAPI_AES_FLAG = 0x00000010, + BCRYPT_HASH_REUSABLE_FLAG = 0x00000020, + + BCRYPT_BUFFERS_LOCKED_FLAG = 0x00000040, +} + +enum { + BCRYPT_CIPHER_OPERATION = 0x00000001, + BCRYPT_HASH_OPERATION = 0x00000002, + BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION = 0x00000004, + BCRYPT_SECRET_AGREEMENT_OPERATION = 0x00000008, + BCRYPT_SIGNATURE_OPERATION = 0x00000010, + BCRYPT_RNG_OPERATION = 0x00000020, + BCRYPT_KEY_DERIVATION_OPERATION = 0x00000040, +} + +enum { + BCRYPT_PUBLIC_KEY_FLAG = 0x00000001, + BCRYPT_PRIVATE_KEY_FLAG = 0x00000002, +} + +enum BCRYPT_NO_KEY_VALIDATION = 0x00000008; + +enum { + BCRYPT_RNG_USE_ENTROPY_IN_BUFFER = 0x00000001, + BCRYPT_USE_SYSTEM_PREFERRED_RNG = 0x00000002, +} + +pragma(inline, true) @nogc nothrow pure @safe { + BCRYPT_INTERFACE_VERSION BCRYPT_MAKE_INTERFACE_VERSION(int major, int minor) => + BCRYPT_INTERFACE_VERSION(MajorVersion: cast(USHORT)major, MinorVersion: cast(USHORT)minor); + bool BCRYPT_IS_INTERFACE_VERSION_COMPATIBLE(BCRYPT_INTERFACE_VERSION loader, BCRYPT_INTERFACE_VERSION provider) => + loader.MajorVersion <= provider.MajorVersion; +} + +enum { + BCRYPT_CIPHER_INTERFACE_VERSION_1 = BCRYPT_MAKE_INTERFACE_VERSION(1, 0), + BCRYPT_HASH_INTERFACE_VERSION_1 = BCRYPT_MAKE_INTERFACE_VERSION(1, 0), + BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE_VERSION_1 = BCRYPT_MAKE_INTERFACE_VERSION(1, 0), + BCRYPT_SECRET_AGREEMENT_INTERFACE_VERSION_1 = BCRYPT_MAKE_INTERFACE_VERSION(1, 0), + BCRYPT_SIGNATURE_INTERFACE_VERSION_1 = BCRYPT_MAKE_INTERFACE_VERSION(1, 0), + BCRYPT_RNG_INTERFACE_VERSION_1 = BCRYPT_MAKE_INTERFACE_VERSION(1, 0), +} + +enum { + CRYPT_MIN_DEPENDENCIES = 0x00000001, + CRYPT_PROCESS_ISOLATE = 0x00010000, +} + +enum { + CRYPT_UM = 0x00000001, + CRYPT_KM = 0x00000002, + CRYPT_MM = 0x00000003, + CRYPT_ANY = 0x00000004, +} + +enum CRYPT_OVERWRITE = 0x00000001; + +enum { + CRYPT_LOCAL = 0x00000001, + CRYPT_DOMAIN = 0x00000002, +} + +enum { + CRYPT_EXCLUSIVE = 0x00000001, + CRYPT_OVERRIDE = 0x00010000, +} + +enum { + CRYPT_ALL_FUNCTIONS = 0x00000001, + CRYPT_ALL_PROVIDERS = 0x00000002, +} + +enum { + CRYPT_PRIORITY_TOP = 0x00000000, + CRYPT_PRIORITY_BOTTOM = 0xFFFFFFFF, +} + +enum CRYPT_DEFAULT_CONTEXT = "Default"w; + +alias BCRYPT_HANDLE = PVOID; +alias BCRYPT_ALG_HANDLE = PVOID; +alias BCRYPT_KEY_HANDLE = PVOID; +alias BCRYPT_HASH_HANDLE = PVOID; +alias BCRYPT_SECRET_HANDLE = PVOID; + +struct BCRYPT_KEY_BLOB { + ULONG Magic; +} + +struct BCRYPT_RSAKEY_BLOB { + ULONG Magic; + ULONG BitLength; + ULONG cbPublicExp; + ULONG cbModulus; + ULONG cbPrime1; + ULONG cbPrime2; +} + +struct BCRYPT_ECCKEY_BLOB { + ULONG dwMagic; + ULONG cbKey; +} +alias PBCRYPT_ECCKEY_BLOB = BCRYPT_ECCKEY_BLOB*; + +static if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) { + struct SSL_ECCKEY_BLOB { + ULONG dwCurveType; + ULONG cbKey; + } + alias PSSL_ECCKEY_BLOB = SSL_ECCKEY_BLOB*; + + enum BCRYPT_ECC_FULLKEY_BLOB_V1 = 0x1; + + alias ECC_CURVE_TYPE_ENUM = int; + enum : ECC_CURVE_TYPE_ENUM { + BCRYPT_ECC_PRIME_SHORT_WEIERSTRASS_CURVE = 0x1, + BCRYPT_ECC_PRIME_TWISTED_EDWARDS_CURVE = 0x2, + BCRYPT_ECC_PRIME_MONTGOMERY_CURVE = 0x3 + } + + alias ECC_CURVE_ALG_ID_ENUM = int; + enum : ECC_CURVE_ALG_ID_ENUM { + BCRYPT_NO_CURVE_GENERATION_ALG_ID = 0x0, + } + + struct BCRYPT_ECCFULLKEY_BLOB { + ULONG dwMagic; + ULONG dwVersion; + ECC_CURVE_TYPE_ENUM dwCurveType; + ECC_CURVE_ALG_ID_ENUM dwCurveGenerationAlgId; + ULONG cbFieldLength; + ULONG cbSubgroupOrder; + ULONG cbCofactor; + ULONG cbSeed; + } + alias PBCRYPT_ECCFULLKEY_BLOB = BCRYPT_ECCFULLKEY_BLOB*; +} + +struct BCRYPT_DH_KEY_BLOB { + ULONG dwMagic; + ULONG cbKey; +} +alias PBCRYPT_DH_KEY_BLOB = BCRYPT_DH_KEY_BLOB*; + +struct BCRYPT_DH_PARAMETER_HEADER { + ULONG cbLength; + ULONG dwMagic; + ULONG cbKeyLength; +} + +struct BCRYPT_DSA_KEY_BLOB { + ULONG dwMagic; + ULONG cbKey; + UCHAR[4] Count; + UCHAR[20] Seed; + UCHAR[20] q; +} +alias PBCRYPT_DSA_KEY_BLOB = BCRYPT_DSA_KEY_BLOB*; + +alias HASHALGORITHM_ENUM = int; +enum : HASHALGORITHM_ENUM { + DSA_HASH_ALGORITHM_SHA1, + DSA_HASH_ALGORITHM_SHA256, + DSA_HASH_ALGORITHM_SHA512, +} + +alias DSAFIPSVERSION_ENUM = int; +enum : DSAFIPSVERSION_ENUM { + DSA_FIPS186_2, + DSA_FIPS186_3, +} + +struct BCRYPT_DSA_KEY_BLOB_V2 { + ULONG dwMagic; + ULONG cbKey; + HASHALGORITHM_ENUM hashAlgorithm; + DSAFIPSVERSION_ENUM standardVersion; + ULONG cbSeedLength; + ULONG cbGroupSize; + UCHAR[4] Count; +} +alias PBCRYPT_DSA_KEY_BLOB_V2 = BCRYPT_DSA_KEY_BLOB_V2*; + +struct BCRYPT_KEY_DATA_BLOB_HEADER { + ULONG dwMagic; + ULONG dwVersion; + ULONG cbKeyData; +} +alias PBCRYPT_KEY_DATA_BLOB_HEADER = BCRYPT_KEY_DATA_BLOB_HEADER*; + +struct BCRYPT_DSA_PARAMETER_HEADER { + ULONG cbLength; + ULONG dwMagic; + ULONG cbKeyLength; + UCHAR[4] Count; + UCHAR[20] Seed; + UCHAR[20] q; +} + +struct BCRYPT_DSA_PARAMETER_HEADER_V2 { + ULONG cbLength; + ULONG dwMagic; + ULONG cbKeyLength; + HASHALGORITHM_ENUM hashAlgorithm; + DSAFIPSVERSION_ENUM standardVersion; + ULONG cbSeedLength; + ULONG cbGroupSize; + UCHAR[4] Count; +} + +struct BCRYPT_ECC_CURVE_NAMES { + ULONG dwEccCurveNames; + LPWSTR* pEccCurveNames; +} + +alias BCRYPT_HASH_OPERATION_TYPE = int; +enum : BCRYPT_HASH_OPERATION_TYPE { + BCRYPT_HASH_OPERATION_HASH_DATA = 1, + BCRYPT_HASH_OPERATION_FINISH_HASH = 2, +} + +struct BCRYPT_MULTI_HASH_OPERATION { + ULONG iHash; + BCRYPT_HASH_OPERATION_TYPE hashOperation; + PUCHAR pbBuffer; + ULONG cbBuffer; +} + +alias BCRYPT_MULTI_OPERATION_TYPE = int; +enum : BCRYPT_MULTI_OPERATION_TYPE { + BCRYPT_OPERATION_TYPE_HASH = 1, +} + +struct BCRYPT_MULTI_OBJECT_LENGTH_STRUCT { + ULONG cbPerObject; + ULONG cbPerElement; +} + +struct BCRYPT_ALGORITHM_IDENTIFIER { + LPWSTR pszName; + ULONG dwClass; + ULONG dwFlags; +} + +struct BCRYPT_PROVIDER_NAME { + LPWSTR pszProviderName; +} + +struct BCRYPT_INTERFACE_VERSION { + USHORT MajorVersion; + USHORT MinorVersion; +} +alias PBCRYPT_INTERFACE_VERSION = BCRYPT_INTERFACE_VERSION*; + +struct CRYPT_INTERFACE_REG { + ULONG dwInterface; + ULONG dwFlags; + ULONG cFunctions; + PWSTR* rgpszFunctions; +} +alias PCRYPT_INTERFACE_REG = CRYPT_INTERFACE_REG*; + +struct CRYPT_IMAGE_REG { + PWSTR pszImage; + ULONG cInterfaces; + PCRYPT_INTERFACE_REG* rgpInterfaces; +} +alias PCRYPT_IMAGE_REG = CRYPT_IMAGE_REG*; + +struct CRYPT_PROVIDER_REG { + ULONG cAliases; + PWSTR* rgpszAliases; + PCRYPT_IMAGE_REG pUM; + PCRYPT_IMAGE_REG pKM; +} +alias PCRYPT_PROVIDER_REG = CRYPT_PROVIDER_REG*; + +struct CRYPT_PROVIDERS { + ULONG cProviders; + PWSTR* rgpszProviders; +} +alias PCRYPT_PROVIDERS = CRYPT_PROVIDERS*; + +struct CRYPT_CONTEXT_CONFIG { + ULONG dwFlags; + ULONG dwReserved; +} +alias PCRYPT_CONTEXT_CONFIG = CRYPT_CONTEXT_CONFIG*; + +struct CRYPT_CONTEXT_FUNCTION_CONFIG { + ULONG dwFlags; + ULONG dwReserved; +} +alias PCRYPT_CONTEXT_FUNCTION_CONFIG = CRYPT_CONTEXT_FUNCTION_CONFIG*; + +struct CRYPT_CONTEXTS { + ULONG cContexts; + PWSTR* rgpszContexts; +} +alias PCRYPT_CONTEXTS = CRYPT_CONTEXTS*; + +struct CRYPT_CONTEXT_FUNCTIONS { + ULONG cFunctions; + PWSTR* rgpszFunctions; +} +alias PCRYPT_CONTEXT_FUNCTIONS = CRYPT_CONTEXT_FUNCTIONS*; + +struct CRYPT_CONTEXT_FUNCTION_PROVIDERS { + ULONG cProviders; + PWSTR* rgpszProviders; +} +alias PCRYPT_CONTEXT_FUNCTION_PROVIDERS = CRYPT_CONTEXT_FUNCTION_PROVIDERS*; + +struct CRYPT_PROPERTY_REF { + PWSTR pszProperty; + ULONG cbValue; + PUCHAR pbValue; +} +alias PCRYPT_PROPERTY_REF = CRYPT_PROPERTY_REF*; + +struct CRYPT_IMAGE_REF { + PWSTR pszImage; + ULONG dwFlags; +} +alias PCRYPT_IMAGE_REF = CRYPT_IMAGE_REF*; + +struct CRYPT_PROVIDER_REF { + ULONG dwInterface; + PWSTR pszFunction; + PWSTR pszProvider; + ULONG cProperties; + PCRYPT_PROPERTY_REF* rgpProperties; + PCRYPT_IMAGE_REF pUM; + PCRYPT_IMAGE_REF pKM; +} +alias PCRYPT_PROVIDER_REF = CRYPT_PROVIDER_REF*; + +struct CRYPT_PROVIDER_REFS { + ULONG cProviders; + PCRYPT_PROVIDER_REF* rgpProviders; +} +alias PCRYPT_PROVIDER_REFS = CRYPT_PROVIDER_REFS*; + +extern(Windows) @nogc nothrow { + NTSTATUS BCryptOpenAlgorithmProvider(scope BCRYPT_ALG_HANDLE* phAlgorithm, scope LPCWSTR pszAlgId, scope LPCWSTR pszImplementation, ULONG dwFlags); + NTSTATUS BCryptEnumAlgorithms(ULONG dwAlgOperations, scope ULONG* pAlgCount, scope BCRYPT_ALGORITHM_IDENTIFIER** ppAlgList, ULONG dwFlags); + NTSTATUS BCryptEnumProviders(scope LPCWSTR pszAlgId, scope ULONG* pImplCount, scope BCRYPT_PROVIDER_NAME** ppImplList, ULONG dwFlags); + NTSTATUS BCryptGetProperty(BCRYPT_HANDLE hObject, scope LPCWSTR pszProperty, scope PUCHAR pbOutput, ULONG cbOutput, scope ULONG* pcbResult, ULONG dwFlags); + NTSTATUS BCryptSetProperty(BCRYPT_HANDLE hObject, scope LPCWSTR pszProperty, scope PUCHAR pbInput, ULONG cbInput, ULONG dwFlags); + NTSTATUS BCryptCloseAlgorithmProvider(BCRYPT_ALG_HANDLE hAlgorithm, ULONG dwFlags); + VOID BCryptFreeBuffer(PVOID pvBuffer); + NTSTATUS BCryptGenerateSymmetricKey(BCRYPT_ALG_HANDLE hAlgorithm, scope BCRYPT_KEY_HANDLE* phKey, scope PUCHAR pbKeyObject, ULONG cbKeyObject, scope PUCHAR pbSecret, ULONG cbSecret, ULONG dwFlags); + NTSTATUS BCryptGenerateKeyPair(BCRYPT_ALG_HANDLE hAlgorithm, scope BCRYPT_KEY_HANDLE* phKey, ULONG dwLength, ULONG dwFlags); + NTSTATUS BCryptEncrypt(BCRYPT_KEY_HANDLE hKey, scope PUCHAR pbInput, ULONG cbInput, scope VOID* pPaddingInfo, scope PUCHAR pbIV, ULONG cbIV, scope PUCHAR pbOutput, ULONG cbOutput, scope ULONG* pcbResult, ULONG dwFlags); + NTSTATUS BCryptDecrypt(BCRYPT_KEY_HANDLE hKey, scope PUCHAR pbInput, ULONG cbInput, scope VOID* pPaddingInfo, scope PUCHAR pbIV, ULONG cbIV, scope PUCHAR pbOutput, ULONG cbOutput, scope ULONG* pcbResult, ULONG dwFlags); + NTSTATUS BCryptExportKey(BCRYPT_KEY_HANDLE hKey, BCRYPT_KEY_HANDLE hExportKey, scope LPCWSTR pszBlobType, scope PUCHAR pbOutput, ULONG cbOutput, scope ULONG* pcbResult, ULONG dwFlags); + NTSTATUS BCryptImportKey(BCRYPT_ALG_HANDLE hAlgorithm, BCRYPT_KEY_HANDLE hImportKey, scope LPCWSTR pszBlobType, scope BCRYPT_KEY_HANDLE* phKey, scope PUCHAR pbKeyObject, ULONG cbKeyObject, scope PUCHAR pbInput, ULONG cbInput, ULONG dwFlags); + NTSTATUS BCryptImportKeyPair(BCRYPT_ALG_HANDLE hAlgorithm, BCRYPT_KEY_HANDLE hImportKey, scope LPCWSTR pszBlobType, scope BCRYPT_KEY_HANDLE* phKey, scope PUCHAR pbInput, ULONG cbInput, ULONG dwFlags); + NTSTATUS BCryptDuplicateKey(BCRYPT_KEY_HANDLE hKey, scope BCRYPT_KEY_HANDLE* phNewKey, scope PUCHAR pbKeyObject, ULONG cbKeyObject, ULONG dwFlags); + NTSTATUS BCryptFinalizeKeyPair(BCRYPT_KEY_HANDLE hKey, ULONG dwFlags); + NTSTATUS BCryptDestroyKey(BCRYPT_KEY_HANDLE hKey); + NTSTATUS BCryptDestroySecret(BCRYPT_SECRET_HANDLE hSecret); + NTSTATUS BCryptSignHash(BCRYPT_KEY_HANDLE hKey, scope VOID* pPaddingInfo, scope PUCHAR pbInput, ULONG cbInput, scope PUCHAR pbOutput, ULONG cbOutput, scope ULONG* pcbResult, ULONG dwFlags); + NTSTATUS BCryptVerifySignature(BCRYPT_KEY_HANDLE hKey, scope VOID* pPaddingInfo, scope PUCHAR pbHash, ULONG cbHash, scope PUCHAR pbSignature, ULONG cbSignature, ULONG dwFlags); + NTSTATUS BCryptSecretAgreement(BCRYPT_KEY_HANDLE hPrivKey, BCRYPT_KEY_HANDLE hPubKey, scope BCRYPT_SECRET_HANDLE* phAgreedSecret, ULONG dwFlags); + NTSTATUS BCryptDeriveKey(BCRYPT_SECRET_HANDLE hSharedSecret, LPCWSTR pwszKDF, scope BCryptBufferDesc* pParameterList, scope PUCHAR pbDerivedKey, ULONG cbDerivedKey, scope ULONG* pcbResult, ULONG dwFlags); + NTSTATUS BCryptKeyDerivation(BCRYPT_KEY_HANDLE hKey, scope BCryptBufferDesc* pParameterList, scope PUCHAR pbDerivedKey, ULONG cbDerivedKey, scope ULONG* pcbResult, ULONG dwFlags); + NTSTATUS BCryptCreateHash(BCRYPT_ALG_HANDLE hAlgorithm, scope BCRYPT_HASH_HANDLE* phHash, scope PUCHAR pbHashObject, ULONG cbHashObject, scope PUCHAR pbSecret, ULONG cbSecret, ULONG dwFlags); + NTSTATUS BCryptHashData(BCRYPT_HASH_HANDLE hHash, scope PUCHAR pbInput, ULONG cbInput, ULONG dwFlags); + NTSTATUS BCryptFinishHash(BCRYPT_HASH_HANDLE hHash, scope PUCHAR pbOutput, ULONG cbOutput, ULONG dwFlags); + static if (NTDDI_VERSION >= NTDDI_WINBLUE) { + NTSTATUS BCryptCreateMultiHash(BCRYPT_ALG_HANDLE hAlgorithm, scope BCRYPT_HASH_HANDLE* phHash, ULONG nHashes, scope PUCHAR pbHashObject, ULONG cbHashObject, scope PUCHAR pbSecret, ULONG cbSecret, ULONG dwFlags); + NTSTATUS BCryptProcessMultiOperations(BCRYPT_HANDLE hObject, BCRYPT_MULTI_OPERATION_TYPE operationType, scope PVOID pOperations, ULONG cbOperations, ULONG dwFlags); + } + NTSTATUS BCryptDuplicateHash(BCRYPT_HASH_HANDLE hHash, scope BCRYPT_HASH_HANDLE* phNewHash, scope PUCHAR pbHashObject, ULONG cbHashObject, ULONG dwFlags); + NTSTATUS BCryptDestroyHash(BCRYPT_HASH_HANDLE hHash); + static if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) { + NTSTATUS BCryptHash(BCRYPT_ALG_HANDLE hAlgorithm, scope PUCHAR pbSecret, ULONG cbSecret, scope PUCHAR pbInput, ULONG cbInput, scope PUCHAR pbOutput, ULONG cbOutput); + } + NTSTATUS BCryptGenRandom(BCRYPT_ALG_HANDLE hAlgorithm, scope PUCHAR pbBuffer, ULONG cbBuffer, ULONG dwFlags); + NTSTATUS BCryptDeriveKeyCapi(BCRYPT_HASH_HANDLE hHash, BCRYPT_ALG_HANDLE hTargetAlg, scope PUCHAR pbDerivedKey, ULONG cbDerivedKey, ULONG dwFlags); + NTSTATUS BCryptDeriveKeyPBKDF2(BCRYPT_ALG_HANDLE hPrf, scope PUCHAR pbPassword, ULONG cbPassword, scope PUCHAR pbSalt, ULONG cbSalt, ULONGLONG cIterations, scope PUCHAR pbDerivedKey, ULONG cbDerivedKey, ULONG dwFlags); + NTSTATUS BCryptResolveProviders(scope LPCWSTR pszContext, ULONG dwInterface, scope LPCWSTR pszFunction, scope LPCWSTR pszProvider, ULONG dwMode, ULONG dwFlags, scope ULONG* pcbBuffer, scope PCRYPT_PROVIDER_REFS* ppBuffer); + NTSTATUS BCryptGetFipsAlgorithmMode(scope BOOLEAN* pfEnabled); + NTSTATUS BCryptQueryProviderRegistration(scope LPCWSTR pszProvider, ULONG dwMode, ULONG dwInterface, scope ULONG* pcbBuffer, scope PCRYPT_PROVIDER_REG* ppBuffer); + NTSTATUS BCryptEnumRegisteredProviders(scope ULONG* pcbBuffer, scope PCRYPT_PROVIDERS* ppBuffer); + NTSTATUS BCryptCreateContext(ULONG dwTable, scope LPCWSTR pszContext, PCRYPT_CONTEXT_CONFIG pConfig); + NTSTATUS BCryptDeleteContext(ULONG dwTable, scope LPCWSTR pszContext); + NTSTATUS BCryptEnumContexts(ULONG dwTable, scope ULONG* pcbBuffer, scope PCRYPT_CONTEXTS* ppBuffer); + NTSTATUS BCryptConfigureContext(ULONG dwTable, scope LPCWSTR pszContext, PCRYPT_CONTEXT_CONFIG pConfig); + NTSTATUS BCryptQueryContextConfiguration(ULONG dwTable, scope LPCWSTR pszContext, scope ULONG* pcbBuffer, scope PCRYPT_CONTEXT_CONFIG* ppBuffer); + NTSTATUS BCryptAddContextFunction(ULONG dwTable, scope LPCWSTR pszContext, ULONG dwInterface, scope LPCWSTR pszFunction, ULONG dwPosition); + NTSTATUS BCryptRemoveContextFunction(ULONG dwTable, scope LPCWSTR pszContext, ULONG dwInterface, scope LPCWSTR pszFunction); + NTSTATUS BCryptEnumContextFunctions(ULONG dwTable, scope LPCWSTR pszContext, ULONG dwInterface, scope ULONG* pcbBuffer, scope PCRYPT_CONTEXT_FUNCTIONS* ppBuffer); + NTSTATUS BCryptConfigureContextFunction(ULONG dwTable, scope LPCWSTR pszContext, ULONG dwInterface, scope LPCWSTR pszFunction, PCRYPT_CONTEXT_FUNCTION_CONFIG pConfig); + NTSTATUS BCryptQueryContextFunctionConfiguration(ULONG dwTable, scope LPCWSTR pszContext, ULONG dwInterface, scope LPCWSTR pszFunction, scope ULONG* pcbBuffer, scope PCRYPT_CONTEXT_FUNCTION_CONFIG* ppBuffer); + NTSTATUS BCryptEnumContextFunctionProviders(ULONG dwTable, scope LPCWSTR pszContext, ULONG dwInterface, scope LPCWSTR pszFunction, scope ULONG* pcbBuffer, scope PCRYPT_CONTEXT_FUNCTION_PROVIDERS* ppBuffer); + NTSTATUS BCryptSetContextFunctionProperty(ULONG dwTable, scope LPCWSTR pszContext, ULONG dwInterface, scope LPCWSTR pszFunction, LPCWSTR pszProperty, ULONG cbValue, scope PUCHAR pbValue); + NTSTATUS BCryptQueryContextFunctionProperty(ULONG dwTable, scope LPCWSTR pszContext, ULONG dwInterface, scope LPCWSTR pszFunction, LPCWSTR pszProperty, ULONG* pcbValue, scope PUCHAR* ppbValue); + deprecated NTSTATUS BCryptRegisterConfigChangeNotify(scope HANDLE* phEvent); + NTSTATUS BCryptUnregisterConfigChangeNotify(HANDLE hEvent); +} diff --git a/libphobos/libdruntime/core/sys/windows/dll.d b/libphobos/libdruntime/core/sys/windows/dll.d index 7c601bb..06f01f3 100644 --- a/libphobos/libdruntime/core/sys/windows/dll.d +++ b/libphobos/libdruntime/core/sys/windows/dll.d @@ -9,9 +9,6 @@ * Source: $(DRUNTIMESRC core/sys/windows/_dll.d) */ -/* NOTE: This file has been patched from the original DMD distribution to - * work with the GDC compiler. - */ module core.sys.windows.dll; version (Windows): @@ -405,36 +402,29 @@ private bool isWindows8OrLater() nothrow @nogc int dll_getRefCount( HINSTANCE hInstance ) nothrow @nogc { void** peb; - version (Win64) + version (D_InlineAsm_X86_64) { - version (GNU_InlineAsm) + asm pure nothrow @nogc { - asm pure nothrow @nogc { "movq %%gs:0x60, %0;" : "=r" (peb); } + mov RAX, 0x60; + mov RAX,GS:[RAX]; + mov peb, RAX; } - else + } + else version (D_InlineAsm_X86) + { + asm pure nothrow @nogc { - asm pure nothrow @nogc - { - mov RAX, 0x60; - mov RAX,GS:[RAX]; - mov peb, RAX; - } + mov EAX,FS:[0x30]; + mov peb, EAX; } } - else version (Win32) + else version (GNU_InlineAsm) { - version (GNU_InlineAsm) - { + version (X86_64) + asm pure nothrow @nogc { "movq %%gs:0x60, %0;" : "=r" (peb); } + else version (X86) asm pure nothrow @nogc { "movl %%fs:0x30, %0;" : "=r" (peb); } - } - else - { - asm pure nothrow @nogc - { - mov EAX,FS:[0x30]; - mov peb, EAX; - } - } } dll_aux.LDR_MODULE *ldrMod = dll_aux.findLdrModule( hInstance, peb ); if ( !ldrMod ) diff --git a/libphobos/libdruntime/core/sys/windows/sdkddkver.d b/libphobos/libdruntime/core/sys/windows/sdkddkver.d index 3f5c01b..bdaaa81 100644 --- a/libphobos/libdruntime/core/sys/windows/sdkddkver.d +++ b/libphobos/libdruntime/core/sys/windows/sdkddkver.d @@ -7,9 +7,10 @@ * Source: $(DRUNTIMESRC core/sys/windows/sdkddkver.d) */ module core.sys.windows.sdkddkver; - version (Windows): +import core.sys.windows.w32api; + enum _WIN32_WINNT_NT4 = 0x0400; enum _WIN32_WINNT_WIN2K = 0x0500; enum _WIN32_WINNT_WINXP = 0x0501; @@ -21,6 +22,7 @@ enum _WIN32_WINNT_LONGHORN = 0x0600; enum _WIN32_WINNT_WIN7 = 0x0601; enum _WIN32_WINNT_WIN8 = 0x0602; enum _WIN32_WINNT_WINBLUE = 0x0603; +enum _WIN32_WINNT_WINTHRESHOLD = 0x0A00; enum _WIN32_WINNT_WIN10 = 0x0A00; enum _WIN32_IE_IE20 = 0x0200; @@ -38,6 +40,7 @@ enum _WIN32_IE_IE70 = 0x0700; enum _WIN32_IE_IE80 = 0x0800; enum _WIN32_IE_IE90 = 0x0900; enum _WIN32_IE_IE100 = 0x0A00; +enum _WIN32_IE_IE110 = 0x0A00; enum _WIN32_IE_NT4 = _WIN32_IE_IE20; enum _WIN32_IE_NT4SP1 = _WIN32_IE_IE20; @@ -64,6 +67,8 @@ enum _WIN32_IE_LONGHORN = _WIN32_IE_IE70; enum _WIN32_IE_WIN7 = _WIN32_IE_IE80; enum _WIN32_IE_WIN8 = _WIN32_IE_IE100; enum _WIN32_IE_WINBLUE = _WIN32_IE_IE100; +enum _WIN32_IE_WINTHRESHOLD = _WIN32_IE_IE110; +enum _WIN32_IE_WIN10 = _WIN32_IE_IE110; enum NTDDI_WIN2K = 0x05000000; @@ -106,12 +111,45 @@ enum NTDDI_WS08SP4 = NTDDI_WIN6SP4; enum NTDDI_WIN7 = 0x06010000; enum NTDDI_WIN8 = 0x06020000; enum NTDDI_WINBLUE = 0x06030000; - -enum OSVERSION_MASK = 0xFFFF0000; +enum NTDDI_WINTHRESHOLD = 0x0A000000; +enum NTDDI_WIN10 = 0x0A000000; +enum NTDDI_WIN10_TH2 = 0x0A000001; +enum NTDDI_WIN10_RS1 = 0x0A000002; +enum NTDDI_WIN10_RS2 = 0x0A000003; +enum NTDDI_WIN10_RS3 = 0x0A000004; +enum NTDDI_WIN10_RS4 = 0x0A000005; +enum NTDDI_WIN10_RS5 = 0x0A000006; +enum NTDDI_WIN10_19H1 = 0x0A000007; +enum NTDDI_WIN10_VB = 0x0A000008; +enum NTDDI_WIN10_MN = 0x0A000009; +enum NTDDI_WIN10_FE = 0x0A00000A; +enum NTDDI_WIN10_CO = 0x0A00000B; +enum NTDDI_WIN10_NI = 0x0A00000C; +enum NTDDI_WIN10_CU = 0x0A00000D; +enum NTDDI_WIN11_ZN = 0x0A00000E; +enum NTDDI_WIN11_GA = 0x0A00000F; +enum NTDDI_WIN11_GE = 0x0A000010; + +enum WDK_NTDDI_VERSION = NTDDI_WIN11_GE; + +enum OSVERSION_MASK = 0xFFFF0000U; enum SPVERSION_MASK = 0x0000FF00; enum SUBVERSION_MASK = 0x000000FF; -enum _WIN32_WINNT = 0x0603; +pragma(inline, true) @nogc nothrow pure @safe { + uint OSVER(uint Version) => Version & OSVERSION_MASK; + uint SPVER(uint Version) => (Version & SPVERSION_MASK) >> 8; + uint SUBVER(uint Version) => Version & SUBVERSION_MASK; + + uint NTDDI_VERSION_FROM_WIN32_WINNT2(uint Version) => Version * 0x10000; + alias NTDDI_VERSION_FROM_WIN32_WINNT = NTDDI_VERSION_FROM_WIN32_WINNT2; +} + + +static if (_WIN32_WINNT < _WIN32_WINNT_WIN10) { + enum NTDDI_VERSION = NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT); +} else { + enum NTDDI_VERSION = WDK_NTDDI_VERSION; +} -enum NTDDI_VERSION = 0x06030000; -enum WINVER = _WIN32_WINNT; +enum WINVER = _WIN32_WINNT; diff --git a/libphobos/libdruntime/core/sys/windows/threadaux.d b/libphobos/libdruntime/core/sys/windows/threadaux.d index 92bd1c6..dae8896 100644 --- a/libphobos/libdruntime/core/sys/windows/threadaux.d +++ b/libphobos/libdruntime/core/sys/windows/threadaux.d @@ -9,9 +9,6 @@ * Authors: Rainer Schuetze */ -/* NOTE: This file has been patched from the original DMD distribution to - * work with the GDC compiler. - */ module core.sys.windows.threadaux; version (Windows): @@ -166,42 +163,35 @@ struct thread_aux // get linear address of TEB of current thread static void** getTEB() nothrow @nogc { - version (Win32) + version (D_InlineAsm_X86) { - version (GNU_InlineAsm) + asm pure nothrow @nogc { - void** teb; - asm pure nothrow @nogc { "movl %%fs:0x18, %0;" : "=r" (teb); } - return teb; + naked; + mov EAX,FS:[0x18]; + ret; } - else + } + else version (D_InlineAsm_X86_64) + { + asm pure nothrow @nogc { - asm pure nothrow @nogc - { - naked; - mov EAX,FS:[0x18]; - ret; - } + naked; + mov RAX,0x30; + mov RAX,GS:[RAX]; // immediate value causes fixup + ret; } } - else version (Win64) + else version (GNU_InlineAsm) { - version (GNU_InlineAsm) - { - void** teb; + void** teb; + version (X86) + asm pure nothrow @nogc { "movl %%fs:0x18, %0;" : "=r" (teb); } + else version (X86_64) asm pure nothrow @nogc { "movq %%gs:0x30, %0;" : "=r" (teb); } - return teb; - } else - { - asm pure nothrow @nogc - { - naked; - mov RAX,0x30; - mov RAX,GS:[RAX]; // immediate value causes fixup - ret; - } - } + static assert(false); + return teb; } else { diff --git a/libphobos/libdruntime/core/sys/windows/w32api.d b/libphobos/libdruntime/core/sys/windows/w32api.d index a5aa975..bf84195 100644 --- a/libphobos/libdruntime/core/sys/windows/w32api.d +++ b/libphobos/libdruntime/core/sys/windows/w32api.d @@ -10,12 +10,45 @@ module core.sys.windows.w32api; version (Windows): +import core.sys.windows.sdkddkver; + version (ANSI) {} else version = Unicode; enum __W32API_VERSION = 3.17; enum __W32API_MAJOR_VERSION = 3; enum __W32API_MINOR_VERSION = 17; +enum Windows95 = 0x0400; +enum Windows98 = 0x0410; +enum WindowsME = 0x0500; + +enum WindowsNT4 = 0x0400; +enum Windows2000 = 0x0500; +enum WindowsXP = 0x0501; +enum Windows2003 = 0x0502; +enum WindowsVista = 0x0600; +enum Windows7 = 0x0601; +enum Windows8 = 0x0602; + +enum IE3 = 0x0300; +enum IE301 = 0x0300; +enum IE302 = 0x0300; +enum IE4 = 0x0400; +enum IE401 = 0x0401; +enum IE5 = 0x0500; +enum IE5a = 0x0500; +enum IE5b = 0x0500; +enum IE501 = 0x0501; +enum IE55 = 0x0501; +enum IE56 = 0x0560; +enum IE6 = 0x0600; +enum IE601 = 0x0601; +enum IE602 = 0x0603; +enum IE7 = 0x0700; +enum IE8 = 0x0800; +enum IE9 = 0x0900; +enum IE10 = 0x0A00; + /* These version identifiers are used to specify the minimum version of Windows that an * application will support. * @@ -23,62 +56,64 @@ enum __W32API_MINOR_VERSION = 17; * Windows 9x is no longer supported, either by Microsoft or by DMD, this distinction has been * removed in order to simplify the bindings. */ - version (Windows10) { - enum uint _WIN32_WINNT = 0xA00; +version (Windows11) { + enum uint _WIN32_WINNT = _WIN32_WINNT_WIN10; +} else version (Windows10) { + enum uint _WIN32_WINNT = _WIN32_WINNT_WIN10; } else version (Windows8_1) { // also Windows2012R2 - enum uint _WIN32_WINNT = 0x603; + enum uint _WIN32_WINNT = _WIN32_WINNT_WINBLUE; } else version (Windows8) { // also Windows2012 - enum uint _WIN32_WINNT = 0x602; + enum uint _WIN32_WINNT = _WIN32_WINNT_WIN8; } else version (Windows7) { // also Windows2008R2 - enum uint _WIN32_WINNT = 0x601; + enum uint _WIN32_WINNT = _WIN32_WINNT_WIN7; } else version (WindowsVista) { // also Windows2008 - enum uint _WIN32_WINNT = 0x600; + enum uint _WIN32_WINNT = _WIN32_WINNT_VISTA; } else version (Windows2003) { // also WindowsHomeServer, WindowsXP64 - enum uint _WIN32_WINNT = 0x502; + enum uint _WIN32_WINNT = _WIN32_WINNT_WS03; } else version (WindowsXP) { - enum uint _WIN32_WINNT = 0x501; + enum uint _WIN32_WINNT = _WIN32_WINNT_WINXP; } else version (Windows2000) { // Current DMD doesn't support any version of Windows older than XP, // but third-party compilers could use this - enum uint _WIN32_WINNT = 0x500; + enum uint _WIN32_WINNT = _WIN32_WINNT_WIN2K; } else { - enum uint _WIN32_WINNT = 0x601; + enum uint _WIN32_WINNT = _WIN32_WINNT_WIN7; } version (IE11) { - enum uint _WIN32_IE = 0xA00; + enum uint _WIN32_IE = _WIN32_IE_IE110; } else version (IE10) { - enum uint _WIN32_IE = 0xA00; + enum uint _WIN32_IE = _WIN32_IE_IE100; } else version (IE9) { - enum uint _WIN32_IE = 0x900; + enum uint _WIN32_IE = _WIN32_IE_IE90; } else version (IE8) { - enum uint _WIN32_IE = 0x800; + enum uint _WIN32_IE = _WIN32_IE_IE80; } else version (IE7) { - enum uint _WIN32_IE = 0x700; + enum uint _WIN32_IE = _WIN32_IE_IE70; } else version (IE602) { - enum uint _WIN32_IE = 0x603; + enum uint _WIN32_IE = _WIN32_IE_IE60SP2; } else version (IE601) { - enum uint _WIN32_IE = 0x601; + enum uint _WIN32_IE = _WIN32_IE_IE60SP1; } else version (IE6) { - enum uint _WIN32_IE = 0x600; + enum uint _WIN32_IE = _WIN32_IE_IE60; } else version (IE56) { - enum uint _WIN32_IE = 0x560; + enum uint _WIN32_IE = _WIN32_IE_IE60; } else version (IE55) { - enum uint _WIN32_IE = 0x550; + enum uint _WIN32_IE = _WIN32_IE_IE55; } else version (IE501) { - enum uint _WIN32_IE = 0x501; + enum uint _WIN32_IE = _WIN32_IE_IE501; } else version (IE5) { - enum uint _WIN32_IE = 0x500; + enum uint _WIN32_IE = _WIN32_IE_IE50; } else version (IE401) { - enum uint _WIN32_IE = 0x401; + enum uint _WIN32_IE = _WIN32_IE_IE401; } else version (IE4) { - enum uint _WIN32_IE = 0x400; + enum uint _WIN32_IE = _WIN32_IE_IE40; } else version (IE3) { - enum uint _WIN32_IE = 0x300; -} else static if (_WIN32_WINNT >= 0x500) { - enum uint _WIN32_IE = 0x600; -} else static if (_WIN32_WINNT >= 0x410) { - enum uint _WIN32_IE = 0x400; + enum uint _WIN32_IE = _WIN32_IE_IE30; +} else static if (_WIN32_WINNT >= _WIN32_WINNT_WIN2K) { + enum uint _WIN32_IE = _WIN32_IE_IE60; +} else static if (_WIN32_WINNT >= Windows98) { //NOTE: _WIN32_WINNT will never be set this low + enum uint _WIN32_IE = _WIN32_IE_IE40; } else { enum uint _WIN32_IE = 0; } diff --git a/libphobos/libdruntime/core/sys/windows/winbase.d b/libphobos/libdruntime/core/sys/windows/winbase.d index a30035c..935c7c4 100644 --- a/libphobos/libdruntime/core/sys/windows/winbase.d +++ b/libphobos/libdruntime/core/sys/windows/winbase.d @@ -1789,8 +1789,8 @@ extern (Windows) nothrow @nogc { alias RtlMoveMemory = memmove; alias RtlCopyMemory = memcpy; - pragma(inline, true) void RtlFillMemory(PVOID Destination, SIZE_T Length, BYTE Fill) { memset(Destination, Fill, Length); } - pragma(inline, true) void RtlZeroMemory(PVOID Destination, SIZE_T Length) { memset(Destination, 0, Length); } + pragma(inline, true) void RtlFillMemory(PVOID Destination, SIZE_T Length, BYTE Fill) pure { memset(Destination, Fill, Length); } + pragma(inline, true) void RtlZeroMemory(PVOID Destination, SIZE_T Length) pure { memset(Destination, 0, Length); } alias MoveMemory = RtlMoveMemory; alias CopyMemory = RtlCopyMemory; alias FillMemory = RtlFillMemory; diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d index e08e4a1..c1cd42b 100644 --- a/libphobos/libdruntime/core/thread/osthread.d +++ b/libphobos/libdruntime/core/thread/osthread.d @@ -10,9 +10,6 @@ * Source: $(DRUNTIMESRC core/thread/osthread.d) */ -/* NOTE: This file has been patched from the original DMD distribution to - * work with the GDC compiler. - */ module core.thread.osthread; import core.atomic; @@ -37,10 +34,6 @@ else version (TVOS) else version (WatchOS) version = Darwin; -version (Shared) - version (GNU) - version = GNUShared; - version (D_InlineAsm_X86) { version (Windows) @@ -482,16 +475,8 @@ class Thread : ThreadBase version (Shared) { - version (GNU) - { - auto libs = externDFunc!("gcc.sections.pinLoadedLibraries", - void* function() @nogc nothrow)(); - } - else - { - auto libs = externDFunc!("rt.sections_elf_shared.pinLoadedLibraries", - void* function() @nogc nothrow)(); - } + auto libs = externDFunc!("rt.sections_elf_shared.pinLoadedLibraries", + void* function() @nogc nothrow)(); auto ps = cast(void**).malloc(2 * size_t.sizeof); if (ps is null) onOutOfMemoryError(); @@ -499,16 +484,8 @@ class Thread : ThreadBase ps[1] = cast(void*)libs; if ( pthread_create( &m_addr, &attr, &thread_entryPoint, ps ) != 0 ) { - version (GNU) - { - externDFunc!("gcc.sections.unpinLoadedLibraries", - void function(void*) @nogc nothrow)(libs); - } - else - { - externDFunc!("rt.sections_elf_shared.unpinLoadedLibraries", - void function(void*) @nogc nothrow)(libs); - } + externDFunc!("rt.sections_elf_shared.unpinLoadedLibraries", + void function(void*) @nogc nothrow)(libs); .free(ps); onThreadError( "Error creating thread" ); } @@ -1562,7 +1539,7 @@ private extern(D) void* getStackBottom() nothrow @nogc else version (X86_64) asm pure nothrow @nogc { "movq %%gs:8, %0;" : "=r" (bottom); } else - static assert(false, "Platform not supported."); + static assert(false, "Architecture not supported."); return bottom; } @@ -2232,12 +2209,7 @@ else version (Posix) // loadedLibraries need to be inherited from parent thread // before initilizing GC for TLS (rt_tlsgc_init) - version (GNUShared) - { - externDFunc!("gcc.sections.inheritLoadedLibraries", - void function(void*) @nogc nothrow)(loadedLibraries); - } - else version (Shared) + version (Shared) { externDFunc!("rt.sections_elf_shared.inheritLoadedLibraries", void function(void*) @nogc nothrow)(loadedLibraries); @@ -2319,12 +2291,7 @@ else version (Posix) append( t ); } rt_moduleTlsDtor(); - version (GNUShared) - { - externDFunc!("gcc.sections.cleanupLoadedLibraries", - void function() @nogc nothrow)(); - } - else version (Shared) + version (Shared) { externDFunc!("rt.sections_elf_shared.cleanupLoadedLibraries", void function() @nogc nothrow)(); @@ -2801,16 +2768,8 @@ private size_t adjustStackSize(size_t sz) nothrow @nogc version (CRuntime_Glibc) { // On glibc, TLS uses the top of the stack, so add its size to the requested size - version (GNU) - { - sz += externDFunc!("gcc.sections.elf.sizeOfTLS", - size_t function() @nogc nothrow)(); - } - else - { - sz += externDFunc!("rt.sections_elf_shared.sizeOfTLS", - size_t function() @nogc nothrow)(); - } + sz += externDFunc!("rt.sections_elf_shared.sizeOfTLS", + size_t function() @nogc nothrow)(); } // stack size must be a multiple of pageSize diff --git a/libphobos/libdruntime/gcc/sections/elf.d b/libphobos/libdruntime/gcc/sections/elf.d index bbebedf..6d8b843 100644 --- a/libphobos/libdruntime/gcc/sections/elf.d +++ b/libphobos/libdruntime/gcc/sections/elf.d @@ -181,7 +181,7 @@ alias ScanDG = void delegate(void* pbeg, void* pend) nothrow; version (Shared) { import gcc.sections : pinLoadedLibraries, unpinLoadedLibraries, - inheritLoadedLibraries, cleanupLoadedLibraries; + inheritLoadedLibraries, cleanupLoadedLibraries, sizeOfTLS; /*** * Called once per thread; returns array of thread local storage ranges @@ -213,6 +213,7 @@ version (Shared) } } + pragma(mangle, gcc.sections.sizeOfTLS.mangleof) size_t sizeOfTLS() nothrow @nogc { auto tdsos = initTLSRanges(); @@ -295,6 +296,8 @@ version (Shared) } else { + import gcc.sections : sizeOfTLS; + /*** * Called once per thread; returns array of thread local storage ranges */ @@ -328,6 +331,7 @@ else } } + pragma(mangle, gcc.sections.sizeOfTLS.mangleof) size_t sizeOfTLS() nothrow @nogc { auto rngs = initTLSRanges(); diff --git a/libphobos/libdruntime/gcc/sections/package.d b/libphobos/libdruntime/gcc/sections/package.d index b003c31..b41cb28 100644 --- a/libphobos/libdruntime/gcc/sections/package.d +++ b/libphobos/libdruntime/gcc/sections/package.d @@ -42,11 +42,32 @@ else version (SectionsPeCoff) else static assert(0, "unimplemented"); +import core.internal.traits : externDFunc; + version (Shared) { - // interface for core.thread to inherit loaded libraries - void* pinLoadedLibraries() nothrow @nogc; - void unpinLoadedLibraries(void* p) nothrow @nogc; - void inheritLoadedLibraries(void* p) nothrow @nogc; - void cleanupLoadedLibraries() nothrow @nogc; + // interface for core.thread.osthread to inherit loaded libraries + pragma(mangle, externDFunc!("rt.sections_elf_shared.pinLoadedLibraries", + void* function() @nogc nothrow).mangleof) + void* pinLoadedLibraries() @nogc nothrow; + + pragma(mangle, externDFunc!("rt.sections_elf_shared.unpinLoadedLibraries", + void function(void*) @nogc nothrow).mangleof) + void unpinLoadedLibraries(void* p) @nogc nothrow; + + pragma(mangle, externDFunc!("rt.sections_elf_shared.inheritLoadedLibraries", + void function(void*) @nogc nothrow).mangleof) + void inheritLoadedLibraries(void* p) @nogc nothrow; + + pragma(mangle, externDFunc!("rt.sections_elf_shared.cleanupLoadedLibraries", + void function() @nogc nothrow).mangleof) + void cleanupLoadedLibraries() @nogc nothrow; +} + +version (SectionsElf) +{ + // interface for core.thread.osthread to adjust stack size + pragma(mangle, externDFunc!("rt.sections_elf_shared.sizeOfTLS", + size_t function() @nogc nothrow).mangleof) + size_t sizeOfTLS() @nogc nothrow; } diff --git a/libphobos/libdruntime/rt/adi.d b/libphobos/libdruntime/rt/adi.d index ece0f4b..02e4d77 100644 --- a/libphobos/libdruntime/rt/adi.d +++ b/libphobos/libdruntime/rt/adi.d @@ -11,12 +11,9 @@ module rt.adi; -//debug=adi; // uncomment to turn on debugging printf's +// debug = adi; // uncomment to turn on debugging printf's -private -{ - debug(adi) import core.stdc.stdio; -} +debug (adi) import core.stdc.stdio : printf; /*************************************** * Support for array equality test. diff --git a/libphobos/libdruntime/rt/arraycat.d b/libphobos/libdruntime/rt/arraycat.d index 0ab785b..a443c9b 100644 --- a/libphobos/libdruntime/rt/arraycat.d +++ b/libphobos/libdruntime/rt/arraycat.d @@ -10,12 +10,12 @@ module rt.arraycat; -private -{ - import core.stdc.string; - import core.internal.util.array; - debug(PRINTF) import core.stdc.stdio; -} +// debug = PRINTF; + +import core.internal.util.array; +import core.stdc.string : memcpy; + +debug(PRINTF) import core.stdc.stdio : printf; extern (C) @trusted nothrow: diff --git a/libphobos/libdruntime/rt/deh.d b/libphobos/libdruntime/rt/deh.d index 0a44be3..cb80c76 100644 --- a/libphobos/libdruntime/rt/deh.d +++ b/libphobos/libdruntime/rt/deh.d @@ -33,10 +33,6 @@ * Authors: Walter Bright * Source: $(DRUNTIMESRC rt/deh.d) */ - -/* NOTE: This file has been patched from the original DMD distribution to - * work with the GDC compiler. - */ module rt.deh; extern (C) diff --git a/libphobos/libdruntime/rt/dmain2.d b/libphobos/libdruntime/rt/dmain2.d index a1ddba5..f1e9491 100644 --- a/libphobos/libdruntime/rt/dmain2.d +++ b/libphobos/libdruntime/rt/dmain2.d @@ -9,27 +9,26 @@ * Source: $(DRUNTIMESRC rt/_dmain2.d) */ -/* NOTE: This file has been patched from the original DMD distribution to - * work with the GDC compiler. - */ module rt.dmain2; -import rt.memory; -import rt.sections; import core.atomic; -import core.stdc.stddef; -import core.stdc.stdlib; -import core.stdc.string; -import core.stdc.stdio; // for printf() +import core.internal.parseoptions : rt_parseOption; import core.stdc.errno : errno; +import core.stdc.stdio : fflush, fprintf, fwrite, stderr, stdout; +import core.stdc.stdlib : alloca, EXIT_FAILURE, EXIT_SUCCESS, free, malloc, realloc; +import core.stdc.string : strerror; +import rt.config : rt_cmdline_enabled, rt_configOption; +import rt.memory; +import rt.sections; version (Windows) { - import core.stdc.wchar_; + import core.stdc.stdio : fileno; + import core.stdc.wchar_ : wcslen; import core.sys.windows.basetsd : HANDLE; import core.sys.windows.shellapi : CommandLineToArgvW; - import core.sys.windows.winbase : FreeLibrary, GetCommandLineW, GetProcAddress, - IsDebuggerPresent, LoadLibraryW, LocalFree, WriteFile; + import core.sys.windows.winbase : FreeLibrary, GetCommandLineW, GetProcAddress, IsDebuggerPresent, LoadLibraryW, + LocalFree, WriteFile; import core.sys.windows.wincon : CONSOLE_SCREEN_BUFFER_INFO, GetConsoleOutputCP, GetConsoleScreenBufferInfo; import core.sys.windows.winnls : CP_UTF8, MultiByteToWideChar, WideCharToMultiByte; @@ -37,19 +36,12 @@ version (Windows) import core.sys.windows.winuser : MB_ICONERROR, MessageBoxW; pragma(lib, "shell32.lib"); // needed for CommandLineToArgvW -} -version (FreeBSD) -{ - import core.stdc.fenv; -} -version (NetBSD) -{ - import core.stdc.fenv; + import core.stdc.stdio : _get_osfhandle; } -version (DragonFlyBSD) +else version (Posix) { - import core.stdc.fenv; + import core.stdc.string : strlen; } // not sure why we can't define this in one place, but this is to keep this @@ -447,7 +439,6 @@ private extern (C) int _d_run_main2(char[][] args, size_t totalArgsLength, MainF char[][] argsCopy = buff[0 .. args.length]; auto argBuff = cast(char*) (buff + args.length); size_t j = 0; - import rt.config : rt_cmdline_enabled; bool parseOpts = rt_cmdline_enabled!(); foreach (arg; args) { @@ -590,8 +581,6 @@ private void formatThrowable(Throwable t, scope void delegate(in char[] s) nothr private auto parseExceptionOptions() { - import rt.config : rt_configOption; - import core.internal.parseoptions : rt_parseOption; const optName = "trapExceptions"; auto option = rt_configOption(optName); auto trap = rt_trapExceptions; diff --git a/libphobos/libdruntime/rt/ehalloc.d b/libphobos/libdruntime/rt/ehalloc.d index 65f92e3..7c3f06c 100644 --- a/libphobos/libdruntime/rt/ehalloc.d +++ b/libphobos/libdruntime/rt/ehalloc.d @@ -13,10 +13,7 @@ module rt.ehalloc; //debug = PRINTF; -debug(PRINTF) -{ - import core.stdc.stdio; -} +debug (PRINTF) import core.stdc.stdio : printf; /******************************************** diff --git a/libphobos/libdruntime/rt/lifetime.d b/libphobos/libdruntime/rt/lifetime.d index 71ed51b..3558674 100644 --- a/libphobos/libdruntime/rt/lifetime.d +++ b/libphobos/libdruntime/rt/lifetime.d @@ -13,11 +13,17 @@ module rt.lifetime; import core.attribute : weak; -import core.memory; +import core.checkedint : mulu; +import core.exception : onFinalizeError, onOutOfMemoryError, onUnicodeError; import core.internal.gc.blockmeta : PAGESIZE; -debug(PRINTF) import core.stdc.stdio; +import core.memory; +import core.stdc.stdlib : malloc; +import core.stdc.string : memcpy, memset; static import rt.tlsgc; +debug (PRINTF) import core.stdc.stdio : printf; +debug (VALGRIND) import etc.valgrind.valgrind; + alias BlkInfo = GC.BlkInfo; alias BlkAttr = GC.BlkAttr; @@ -81,8 +87,6 @@ Returns: newly created object */ extern (C) Object _d_newclass(const ClassInfo ci) @weak { - import core.stdc.stdlib; - import core.exception : onOutOfMemoryError; void* p; auto init = ci.initializer; @@ -268,7 +272,6 @@ extern(C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) nothrow } catch (Exception e) { - import core.exception : onFinalizeError; onFinalizeError(sti, e); } } @@ -336,9 +339,6 @@ in } do { - import core.stdc.string; - import core.exception : onOutOfMemoryError; - auto isshared = typeid(ti) is typeid(TypeInfo_Shared); auto tinext = unqualify(ti.next); auto size = tinext.tsize; @@ -368,8 +368,6 @@ do } else { - import core.checkedint : mulu; - bool overflow = false; size_t reqsize = mulu(size, newcapacity, overflow); if (!overflow) @@ -444,8 +442,6 @@ Returns: newly allocated array */ extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure nothrow @weak { - import core.exception : onOutOfMemoryError; - auto tinext = unqualify(ti.next); auto size = tinext.tsize; @@ -475,8 +471,6 @@ extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure noth } else { - import core.checkedint : mulu; - bool overflow = false; size = mulu(size, length, overflow); if (!overflow) @@ -497,8 +491,6 @@ Lcontinue: /// ditto extern (C) void[] _d_newarrayT(const TypeInfo ti, size_t length) pure nothrow @weak { - import core.stdc.string; - void[] result = _d_newarrayU(ti, length); auto tinext = unqualify(ti.next); auto size = tinext.tsize; @@ -533,7 +525,6 @@ extern (C) void[] _d_newarrayiT(const TypeInfo ti, size_t length) pure nothrow @ default: { - import core.stdc.string; immutable sz = init.length; for (size_t u = 0; u < size * length; u += sz) memcpy(result.ptr + u, init.ptr, sz); @@ -650,8 +641,6 @@ extern (C) int rt_hasFinalizerInSegment(void* p, size_t size, uint attr, scope c return false; } -debug (VALGRIND) import etc.valgrind.valgrind; - void finalize_array(void* p, size_t size, const TypeInfo_Struct si) { // Due to the fact that the delete operator calls destructors @@ -676,7 +665,6 @@ void finalize_struct(void* p, TypeInfo_Struct ti) nothrow } catch (Exception e) { - import core.exception : onFinalizeError; onFinalizeError(ti, e); } } @@ -717,7 +705,6 @@ extern (C) void rt_finalize2(void* p, bool det = true, bool resetMemory = true) } catch (Exception e) { - import core.exception : onFinalizeError; onFinalizeError(*pc, e); } finally @@ -760,7 +747,6 @@ extern (C) void rt_finalizeFromGC(void* p, size_t size, uint attr) nothrow } catch (Exception e) { - import core.exception : onFinalizeError; onFinalizeError(si, e); } } @@ -801,9 +787,6 @@ in } do { - import core.stdc.string; - import core.exception : onOutOfMemoryError; - debug(PRINTF) { //printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength); @@ -848,7 +831,6 @@ do } else { - import core.checkedint : mulu; const size_t newsize = mulu(sizeelem, newlength, overflow); } if (overflow) @@ -911,9 +893,6 @@ in } do { - import core.stdc.string; - import core.exception : onOutOfMemoryError; - debug(PRINTF) { //printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength); @@ -958,7 +937,6 @@ do } else { - import core.checkedint : mulu; const size_t newsize = mulu(sizeelem, newlength, overflow); } if (overflow) @@ -1111,8 +1089,6 @@ Returns: `px` after being appended to extern (C) byte[] _d_arrayappendcTX(const TypeInfo ti, return scope ref byte[] px, size_t n) @weak { - import core.stdc.string; - import core.exception : onOutOfMemoryError; // This is a cut&paste job from _d_arrayappendT(). Should be refactored. // Short circuit if no data is being appended. @@ -1218,7 +1194,6 @@ extern (C) void[] _d_arrayappendcd(ref byte[] x, dchar c) @weak } else { - import core.exception : onUnicodeError; onUnicodeError("Invalid UTF-8 sequence", 0); // invalid utf character } diff --git a/libphobos/libdruntime/rt/minfo.d b/libphobos/libdruntime/rt/minfo.d index 9bc1055..6e9cd1c8 100644 --- a/libphobos/libdruntime/rt/minfo.d +++ b/libphobos/libdruntime/rt/minfo.d @@ -12,10 +12,13 @@ module rt.minfo; -import core.stdc.stdlib; // alloca -import core.stdc.string; // memcpy +import core.stdc.stdio : fprintf, stderr; +import core.stdc.stdlib : free, malloc, realloc; +import core.stdc.string : memcpy, memset; import rt.sections; +debug (printModuleDependencies) import core.stdc.stdio : printf; + enum { MIctorstart = 0x1, // we've started constructing it @@ -179,7 +182,6 @@ struct ModuleGroup switch (cycleHandling) with(OnCycle) { case "deprecate": - import core.stdc.stdio : fprintf, stderr; // Option deprecated in 2.101, remove in 2.111 fprintf(stderr, "`--DRT-oncycle=deprecate` is no longer supported, using `abort` instead\n"); break; @@ -202,8 +204,6 @@ struct ModuleGroup debug (printModuleDependencies) { - import core.stdc.stdio : printf; - foreach (_m; _modules) { printf("%s%s%s:", _m.name.ptr, (_m.flags & MIstandalone) @@ -375,7 +375,6 @@ struct ModuleGroup case print: // print the message buildCycleMessage(idx, midx, (string x) { - import core.stdc.stdio : fprintf, stderr; fprintf(stderr, "%.*s", cast(int) x.length, x.ptr); }); // continue on as if this is correct. @@ -518,7 +517,6 @@ struct ModuleGroup !doSort(MItlsctor | MItlsdtor, _tlsctors)) { // print a warning - import core.stdc.stdio : fprintf, stderr; fprintf(stderr, "Deprecation 16211 warning:\n" ~ "A cycle has been detected in your program that was undetected prior to DMD\n" ~ "2.072. This program will continue, but will not operate when using DMD 2.074\n" diff --git a/libphobos/libdruntime/rt/monitor_.d b/libphobos/libdruntime/rt/monitor_.d index 5d6c2f8..1d4ed2e 100644 --- a/libphobos/libdruntime/rt/monitor_.d +++ b/libphobos/libdruntime/rt/monitor_.d @@ -8,7 +8,26 @@ */ module rt.monitor_; -import core.atomic, core.stdc.stdlib, core.stdc.string; +import core.atomic; +import core.stdc.stdlib : calloc, free, realloc; +import core.stdc.string : memmove; + +version (Windows) +{ + import core.sys.windows.winbase /+: CRITICAL_SECTION, DeleteCriticalSection, + EnterCriticalSection, InitializeCriticalSection, LeaveCriticalSection+/; +} +else version (Posix) +{ + import core.sys.posix.pthread : pthread_mutex_destroy, pthread_mutex_init, pthread_mutex_lock, + PTHREAD_MUTEX_RECURSIVE, pthread_mutex_unlock, pthread_mutexattr_destroy, pthread_mutexattr_init, + pthread_mutexattr_settype; + import core.sys.posix.sys.types : pthread_mutex_t, pthread_mutexattr_t; +} +else +{ + static assert(0, "Unsupported platform"); +} // NOTE: The dtor callback feature is only supported for monitors that are not // supplied by the user. The assumption is that any object with a user- @@ -173,9 +192,6 @@ alias DEvent = void delegate(Object); version (Windows) { - import core.sys.windows.winbase /+: CRITICAL_SECTION, DeleteCriticalSection, - EnterCriticalSection, InitializeCriticalSection, LeaveCriticalSection+/; - alias Mutex = CRITICAL_SECTION; alias initMutex = InitializeCriticalSection; @@ -185,11 +201,6 @@ version (Windows) } else version (Posix) { - import core.sys.posix.pthread : pthread_mutex_destroy, pthread_mutex_init, pthread_mutex_lock, - PTHREAD_MUTEX_RECURSIVE, pthread_mutex_unlock, pthread_mutexattr_destroy, pthread_mutexattr_init, - pthread_mutexattr_settype; - import core.sys.posix.sys.types : pthread_mutex_t, pthread_mutexattr_t; - @nogc: alias Mutex = pthread_mutex_t; __gshared pthread_mutexattr_t gattr; @@ -214,10 +225,6 @@ else version (Posix) pthread_mutex_unlock(mtx) && assert(0); } } -else -{ - static assert(0, "Unsupported platform"); -} struct Monitor { @@ -229,6 +236,8 @@ struct Monitor private: +__gshared Mutex gmtx; + @property ref shared(Monitor*) monitor(return scope Object h) pure nothrow @nogc { return *cast(shared Monitor**)&h.__monitor; @@ -244,8 +253,6 @@ void setMonitor(Object h, shared(Monitor)* m) pure @nogc atomicStore!(MemoryOrder.rel)(h.monitor, m); } -__gshared Mutex gmtx; - shared(Monitor)* ensureMonitor(Object h) { if (auto m = getMonitor(h)) diff --git a/libphobos/libdruntime/rt/profilegc.d b/libphobos/libdruntime/rt/profilegc.d index b97a5c5..e7d4f03 100644 --- a/libphobos/libdruntime/rt/profilegc.d +++ b/libphobos/libdruntime/rt/profilegc.d @@ -15,10 +15,9 @@ module rt.profilegc; private: -import core.stdc.errno; -import core.stdc.stdio; -import core.stdc.stdlib; -import core.stdc.string; +import core.stdc.errno : errno; +import core.stdc.stdio : fclose, FILE, fopen, fprintf, snprintf, stderr, stdout; +import core.stdc.stdlib : free, malloc, qsort, realloc; import core.exception : onOutOfMemoryError; import core.internal.container.hashtab; diff --git a/libphobos/libdruntime/rt/sections.d b/libphobos/libdruntime/rt/sections.d index a7b75d4ba..ce5a668 100644 --- a/libphobos/libdruntime/rt/sections.d +++ b/libphobos/libdruntime/rt/sections.d @@ -8,9 +8,6 @@ * Source: $(DRUNTIMESRC rt/_sections.d) */ -/* NOTE: This file has been patched from the original DMD distribution to - * work with the GDC compiler. - */ module rt.sections; version (OSX) diff --git a/libphobos/libdruntime/rt/tlsgc.d b/libphobos/libdruntime/rt/tlsgc.d index f1dcc59..2b21d1e 100644 --- a/libphobos/libdruntime/rt/tlsgc.d +++ b/libphobos/libdruntime/rt/tlsgc.d @@ -13,9 +13,9 @@ */ module rt.tlsgc; -import core.stdc.stdlib; - -static import rt.lifetime, rt.sections; +import core.exception : onOutOfMemoryError; +import core.stdc.stdlib : free, malloc; +static import rt.sections; /** * Per thread record to store thread associated data for garbage collection. @@ -32,8 +32,7 @@ struct Data void* init() nothrow @nogc { auto data = cast(Data*).malloc(Data.sizeof); - import core.exception; - if ( data is null ) core.exception.onOutOfMemoryError(); + if ( data is null ) onOutOfMemoryError(); *data = Data.init; // do module specific initialization |