diff --git a/VERSION b/VERSION index 5ea2ba0d8e..83a14f57e1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.100.0 +v2.100.1 diff --git a/changelog/deprecate_scope_failure_return.dd b/changelog/deprecate_scope_failure_return.dd new file mode 100644 index 0000000000..19b9add960 --- /dev/null +++ b/changelog/deprecate_scope_failure_return.dd @@ -0,0 +1,23 @@ +`scope(failure)` blocks that contain `return` statements are now deprecated + +Starting with this release, having a `return` statement in the body of a `scope(failure)` +statement is deprecated. Having the ability to `return` from such blocks is error prone since currently, Errors are also handled by `scope(failure)`. This leads to the following situation: + +--- +ulong get () @safe nothrow +{ + scope (failure) return 10; + throw new Error(""); +} + +void main () @safe +{ + assert(get() == 10); // passes +} +--- + +where an error is circumvented by a return. If a return is indeed desired +in such situations, then the solution is to simply use a try-catch block +for the function body. + +Note: `scope(exit)` and `scope(success)` already present this restriction. diff --git a/src/dmd/astbase.d b/src/dmd/astbase.d index 4630e2f4a2..d3048a82ed 100644 --- a/src/dmd/astbase.d +++ b/src/dmd/astbase.d @@ -716,7 +716,7 @@ struct ASTBase { extern (D) this(const ref Loc loc, Loc endloc, StorageClass stc, Identifier id, Statement fbody) { - super(loc, endloc, id ? id : Identifier.generateId("__invariant"), stc, null); + super(loc, endloc, id ? id : Identifier.generateIdWithLoc("__invariant", loc), stc, null); this.fbody = fbody; } diff --git a/src/dmd/backend/cod2.d b/src/dmd/backend/cod2.d index 4ca5ea6e15..a4abbd329a 100644 --- a/src/dmd/backend/cod2.d +++ b/src/dmd/backend/cod2.d @@ -1348,6 +1348,7 @@ void cddiv(ref CodeBuilder cdb,elem *e,regm_t *pretregs) code cs = void; cs.Iflags = 0; + cs.IFL2 = 0; cs.Irex = 0; switch (e2.Eoper) diff --git a/src/dmd/backend/evalu8.d b/src/dmd/backend/evalu8.d index 5cb7c0d53d..03f44b4582 100644 --- a/src/dmd/backend/evalu8.d +++ b/src/dmd/backend/evalu8.d @@ -984,6 +984,10 @@ static if (0) case TYdouble_alias: e.EV.Vdouble = e1.EV.Vdouble / e2.EV.Vdouble; break; + case TYldouble: + // cast is required because Vldouble is a soft type on windows + e.EV.Vdouble = cast(double)(e1.EV.Vdouble / e2.EV.Vldouble); + break; case TYidouble: e.EV.Vdouble = -e1.EV.Vdouble / e2.EV.Vdouble; break; diff --git a/src/dmd/dcast.d b/src/dmd/dcast.d index 12051d9221..afd19f3d0f 100644 --- a/src/dmd/dcast.d +++ b/src/dmd/dcast.d @@ -1106,9 +1106,14 @@ MATCH implicitConvTo(Expression e, Type t) MATCH visitCond(CondExp e) { - auto result = visit(e); - if (result != MATCH.nomatch) - return result; + e.econd = e.econd.optimize(WANTvalue); + const opt = e.econd.toBool(); + if (opt.isPresent()) + { + auto result = visit(e); + if (result != MATCH.nomatch) + return result; + } MATCH m1 = e.e1.implicitConvTo(t); MATCH m2 = e.e2.implicitConvTo(t); @@ -2942,6 +2947,9 @@ Lagain: t1 = Type.basic[ty1]; t2 = Type.basic[ty2]; + + if (!(t1 && t2)) + return null; e1 = e1.castTo(sc, t1); e2 = e2.castTo(sc, t2); return Lret(Type.basic[ty]); diff --git a/src/dmd/dsymbolsem.d b/src/dmd/dsymbolsem.d index 11a51f10e9..d1e87b7720 100644 --- a/src/dmd/dsymbolsem.d +++ b/src/dmd/dsymbolsem.d @@ -4442,7 +4442,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor invd.semanticRun < PASS.semantic && !ad.isUnionDeclaration() // users are on their own with union fields ) + { + invd.fixupInvariantIdent(ad.invs.length); ad.invs.push(invd); + } if (!invd.type) invd.type = new TypeFunction(ParameterList(), Type.tvoid, LINK.d, invd.storage_class); diff --git a/src/dmd/e2ir.d b/src/dmd/e2ir.d index 0523531000..c81f12411e 100644 --- a/src/dmd/e2ir.d +++ b/src/dmd/e2ir.d @@ -2077,6 +2077,15 @@ elem* toElem(Expression e, IRState *irs) return e; } + /* + https://issues.dlang.org/show_bug.cgi?id=23120 + + If rhs is a noreturn expression, then there is no point + to generate any code for the noreturen variable. + */ + if (ae.e2.type.isTypeNoreturn()) + return setResult(toElem(ae.e2, irs)); + Type t1b = ae.e1.type.toBasetype(); // Look for array.length = n @@ -6077,7 +6086,10 @@ Lagain: /* Need to do postblit/destructor. * void *_d_arraysetassign(void *p, void *value, int dim, TypeInfo ti); */ - assert(op != EXP.construct, "Trying reference _d_arraysetctor, this should not happen!"); + if (op == EXP.construct) + { + assert(0, "Trying reference _d_arraysetctor, this should not happen!"); + } r = RTLSYM.ARRAYSETASSIGN; evalue = el_una(OPaddr, TYnptr, evalue); // This is a hack so we can call postblits on const/immutable objects. diff --git a/src/dmd/expressionsem.d b/src/dmd/expressionsem.d index 35ba5fa83e..ebc4fee9b3 100644 --- a/src/dmd/expressionsem.d +++ b/src/dmd/expressionsem.d @@ -9896,9 +9896,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor ae.e2.type.nextOf && ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf); + /* Unlike isArrayCtor above, lower all Rvalues. If the RHS is a literal, + * then we do want to make a temporary for it and call its destructor. + */ const isArraySetCtor = (ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) && - ae.e2.isLvalue && (ae.e2.type.ty == Tstruct || ae.e2.type.ty == Tsarray) && ae.e1.type.nextOf && ae.e1.type.nextOf.equivalent(ae.e2.type); @@ -12638,7 +12640,7 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag) e = new CommaExp(exp.loc, eleft, e); e.type = Type.tvoid; // ambiguous type? } - return e; + return e.expressionSemantic(sc); } if (auto o = s.isOverloadSet()) { diff --git a/src/dmd/func.d b/src/dmd/func.d index 9bf5cb191f..dc94f6a80e 100644 --- a/src/dmd/func.d +++ b/src/dmd/func.d @@ -4222,6 +4222,7 @@ extern (C++) final class InvariantDeclaration : FuncDeclaration { extern (D) this(const ref Loc loc, const ref Loc endloc, StorageClass stc, Identifier id, Statement fbody) { + // Make a unique invariant for now; we'll fix it up as we add it to the aggregate invariant list. super(loc, endloc, id ? id : Identifier.generateId("__invariant"), stc, null); this.fbody = fbody; } @@ -4258,6 +4259,15 @@ extern (C++) final class InvariantDeclaration : FuncDeclaration { v.visit(this); } + + extern (D) void fixupInvariantIdent(size_t offset) + { + OutBuffer idBuf; + idBuf.writestring("__invariant"); + idBuf.print(offset); + + ident = Identifier.idPool(idBuf[]); + } } diff --git a/src/dmd/impcnvtab.d b/src/dmd/impcnvtab.d index ab46f5eebb..832c331c31 100644 --- a/src/dmd/impcnvtab.d +++ b/src/dmd/impcnvtab.d @@ -64,6 +64,57 @@ enum ImpCnvTab impCnvTab = generateImpCnvTab(); ImpCnvTab generateImpCnvTab() { + TY[TMAX] typeTYs = + [ + Tarray, + Tsarray, + Taarray, + Tpointer, + Treference, + Tfunction, + Tident, + Tclass, + Tstruct, + Tenum, + Tdelegate, + Tnone, + Tvoid, + Tint8, + Tuns8, + Tint16, + Tuns16, + Tint32, + Tuns32, + Tint64, + Tuns64, + Tfloat32, + Tfloat64, + Tfloat80, + Timaginary32, + Timaginary64, + Timaginary80, + Tcomplex32, + Tcomplex64, + Tcomplex80, + Tbool, + Tchar, + Twchar, + Tdchar, + Terror, + Tinstance, + Ttypeof, + Ttuple, + Tslice, + Treturn, + Tnull, + Tvector, + Tint128, + Tuns128, + Ttraits, + Tmixin, + Tnoreturn, + Ttag, + ]; ImpCnvTab impCnvTab; // Set conversion tables @@ -375,5 +426,9 @@ ImpCnvTab generateImpCnvTab() X(Tcomplex80,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80); + // "No type is implicitly convertible to noreturn, but noreturn is implicitly convertible to every other type" + foreach(convertToTy; typeTYs) + X(Tnoreturn, convertToTy, convertToTy, convertToTy, convertToTy); + return impCnvTab; } diff --git a/src/dmd/inline.d b/src/dmd/inline.d index 2d0d880143..6eed93ca81 100644 --- a/src/dmd/inline.d +++ b/src/dmd/inline.d @@ -237,7 +237,7 @@ public: auto e1 = doInlineAs!Expression(ifs.ifbody, ids); assert(ids.foundReturn); auto e2 = doInlineAs!Expression(s3, ids); - + assert(e2); Expression e = new CondExp(econd.loc, econd, e1, e2); e.type = e1.type; if (e.type.ty == Ttuple) @@ -250,6 +250,7 @@ public: } else { + ids.foundReturn = false; auto e = doInlineAs!Expression(sx, ids); result = Expression.combine(result, e); } @@ -375,6 +376,7 @@ public: override void visit(ImportStatement s) { + //printf("ImportStatement.doInlineAs!%s()\n", Result.stringof.ptr); } override void visit(ForStatement s) diff --git a/src/dmd/root/longdouble.d b/src/dmd/root/longdouble.d index b359a0d4e8..bbffc35a4b 100644 --- a/src/dmd/root/longdouble.d +++ b/src/dmd/root/longdouble.d @@ -156,6 +156,7 @@ nothrow @nogc pure: static if (op == "+") return longdouble_soft(rhs).ld_add(this); else static if (op == "-") return longdouble_soft(rhs).ld_sub(this); else static if (op == "*") return longdouble_soft(rhs).ld_mul(this); + else static if (op == "/") return longdouble_soft(rhs).ld_div(this); else static if (op == "%") return longdouble_soft(rhs).ld_mod(this); else static assert(false, "Operator `"~op~"` is not implemented"); } diff --git a/src/dmd/statementsem.d b/src/dmd/statementsem.d index e86064a62c..e5e57535b3 100644 --- a/src/dmd/statementsem.d +++ b/src/dmd/statementsem.d @@ -2845,10 +2845,20 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor rs.error("`return` statements cannot be in contracts"); errors = true; } - if (sc.os && sc.os.tok != TOK.onScopeFailure) + if (sc.os) { - rs.error("`return` statements cannot be in `%s` bodies", Token.toChars(sc.os.tok)); - errors = true; + // @@@DEPRECATED_2.112@@@ + // Deprecated in 2.100, transform into an error in 2.112 + if (sc.os.tok == TOK.onScopeFailure) + { + rs.deprecation("`return` statements cannot be in `scope(failure)` bodies."); + deprecationSupplemental(rs.loc, "Use try-catch blocks for this purpose"); + } + else + { + rs.error("`return` statements cannot be in `%s` bodies", Token.toChars(sc.os.tok)); + errors = true; + } } if (sc.tf) { diff --git a/test/compilable/backendfloatoptim.d b/test/compilable/backendfloatoptim.d new file mode 100644 index 0000000000..7ec9f614ef --- /dev/null +++ b/test/compilable/backendfloatoptim.d @@ -0,0 +1,10 @@ +// REQUIRED_ARGS: -O -inline + +//https://issues.dlang.org/show_bug.cgi?id=20143 +real fun(int x) { return 0.0; } + +double bug() +{ + // value passed to fun is irrelevant + return 0.0 / fun(420); +} diff --git a/test/compilable/extra-files/vcg-ast.d.cg b/test/compilable/extra-files/vcg-ast.d.cg index ac228df894..f33030aaff 100644 --- a/test/compilable/extra-files/vcg-ast.d.cg +++ b/test/compilable/extra-files/vcg-ast.d.cg @@ -85,7 +85,7 @@ class C : Object } invariant { - this.__invariant1() , this.__invariant2(); + this.__invariant0() , this.__invariant1(); } } enum __c_wchar_t : dchar; diff --git a/test/compilable/noreturn1.d b/test/compilable/noreturn1.d index 5bba9baa72..e648a56d89 100644 --- a/test/compilable/noreturn1.d +++ b/test/compilable/noreturn1.d @@ -122,3 +122,31 @@ noreturn testdg(noreturn delegate() dg) { dg(); } + +noreturn func() +{ + while(1) + { + } +} +alias AliasSeq(T...) = T; +alias Types = AliasSeq!(bool, byte, ubyte, short, ushort, int, uint, + long, ulong, char, wchar, dchar, float, double, + real); +void noreturnImplicit() +{ + /* + Testing both ways because, although the underlying table + is symmetrical the code that calls into it may be buggy. + */ + { + int x = 2 + func(); + int y = func() + 2; + } + foreach(T; Types) + { + T value; + auto x = value + throw new Exception("Hello"); + auto y = (throw new Exception("wow")) + value; + } +} diff --git a/test/compilable/test23082.d b/test/compilable/test23082.d new file mode 100644 index 0000000000..9df4e4e777 --- /dev/null +++ b/test/compilable/test23082.d @@ -0,0 +1,17 @@ +// https://issues.dlang.org/show_bug.cgi?id=23082 + +/* +TEST_OUTPUT: +--- +bar +--- +*/ + +void foo()() {} +alias bar = foo; +void bar() { } + +void main() +{ + pragma(msg, __traits(parent, main).bar.stringof); +} diff --git a/test/compilable/test23166.d b/test/compilable/test23166.d new file mode 100644 index 0000000000..66da4cd696 --- /dev/null +++ b/test/compilable/test23166.d @@ -0,0 +1,22 @@ +// REQUIRED_ARGS: -inline + +// https://issues.dlang.org/show_bug.cgi?id=23166 + +// seg fault with -inline + +bool __equals(scope const char[] lhs, scope const char[] rhs) +{ + if (lhs.length != rhs.length) + return false; + + { + import core.stdc.string : memcmp; + return lhs.length == 0; + } + return true; +} + +int test(string type) +{ + return __equals(type, "as-is"); +} diff --git a/test/compilable/test23172.d b/test/compilable/test23172.d new file mode 100644 index 0000000000..18b6d4ce8c --- /dev/null +++ b/test/compilable/test23172.d @@ -0,0 +1,33 @@ +// https://issues.dlang.org/show_bug.cgi?id=23172 + +enum E : ubyte { // `ubyte` is needed to trigger the bug + A, + B, +} + +struct S { + E e; +} + +void compiles(bool b, S s) { + E e = b ? E.A : s.e; +} + +void errors(bool b, const ref S s) { + E e = b ? E.A : s.e; +} + +// from https://issues.dlang.org/show_bug.cgi?id=23188 + +enum Status : byte +{ + A, B, C +} + +Status foo() +{ + Status t = Status.A; + const Status s = t; + + return (s == Status.A) ? Status.B : s; // <-- here +} diff --git a/test/fail_compilation/fail23181.d b/test/fail_compilation/fail23181.d new file mode 100644 index 0000000000..519244c1cd --- /dev/null +++ b/test/fail_compilation/fail23181.d @@ -0,0 +1,16 @@ +/* https://issues.dlang.org/show_bug.cgi?id=23181 +TEST_OUTPUT: +--- +$p:druntime/import/core/lifetime.d$($n$): Error: struct `fail23181.fail23181.NoPostblit` is not copyable because it has a disabled postblit +$p:druntime/import/core/internal/array/construction.d$($n$): Error: template instance `core.lifetime.copyEmplace!(NoPostblit, NoPostblit)` error instantiating +fail_compilation/fail23181.d(15): instantiated from here: `_d_arraysetctor!(NoPostblit[], NoPostblit)` +--- +*/ +void fail23181() +{ + struct NoPostblit + { + @disable this(this); + } + NoPostblit[4] noblit23181 = NoPostblit(); +} diff --git a/test/fail_compilation/fail6889.d b/test/fail_compilation/fail6889.d index aa18977090..ee84a84ce7 100644 --- a/test/fail_compilation/fail6889.d +++ b/test/fail_compilation/fail6889.d @@ -55,7 +55,7 @@ L1: scope(failure) { L2: goto L1; } // OK goto L2; // NG - scope(failure) { return; } // OK + foreach (i; 0..1) { diff --git a/test/fail_compilation/fail7848.d b/test/fail_compilation/fail7848.d index e8371c4f7f..001c7d7544 100644 --- a/test/fail_compilation/fail7848.d +++ b/test/fail_compilation/fail7848.d @@ -9,12 +9,12 @@ fail_compilation/fail7848.d(21): `fail7848.func` is declared here fail_compilation/fail7848.d(27): Error: `@nogc` function `fail7848.C.__unittest_L25_C30` cannot call non-@nogc function `fail7848.func` fail_compilation/fail7848.d(27): Error: function `fail7848.func` is not `nothrow` fail_compilation/fail7848.d(25): Error: function `fail7848.C.__unittest_L25_C30` may throw but is marked as `nothrow` -fail_compilation/fail7848.d(32): Error: `pure` function `fail7848.C.__invariant1` cannot call impure function `fail7848.func` -fail_compilation/fail7848.d(32): Error: `@safe` function `fail7848.C.__invariant1` cannot call `@system` function `fail7848.func` +fail_compilation/fail7848.d(32): Error: `pure` function `fail7848.C.__invariant0` cannot call impure function `fail7848.func` +fail_compilation/fail7848.d(32): Error: `@safe` function `fail7848.C.__invariant0` cannot call `@system` function `fail7848.func` fail_compilation/fail7848.d(21): `fail7848.func` is declared here -fail_compilation/fail7848.d(32): Error: `@nogc` function `fail7848.C.__invariant1` cannot call non-@nogc function `fail7848.func` +fail_compilation/fail7848.d(32): Error: `@nogc` function `fail7848.C.__invariant0` cannot call non-@nogc function `fail7848.func` fail_compilation/fail7848.d(32): Error: function `fail7848.func` is not `nothrow` -fail_compilation/fail7848.d(30): Error: function `fail7848.C.__invariant1` may throw but is marked as `nothrow` +fail_compilation/fail7848.d(30): Error: function `fail7848.C.__invariant0` may throw but is marked as `nothrow` --- */ diff --git a/test/fail_compilation/test21443.d b/test/fail_compilation/test21443.d new file mode 100644 index 0000000000..2d99524da3 --- /dev/null +++ b/test/fail_compilation/test21443.d @@ -0,0 +1,21 @@ +// https://issues.dlang.org/show_bug.cgi?id=21443 +// REQUIRED_ARGS: -de + +/* +TEST_OUTPUT: +--- +fail_compilation/test21443.d(14): Deprecation: `return` statements cannot be in `scope(failure)` bodies. +fail_compilation/test21443.d(14): Use try-catch blocks for this purpose +--- +*/ + +ulong get () @safe nothrow +{ + scope (failure) return 10; + throw new Error(""); +} + +void main () @safe +{ + assert(get() == 10); // passes +} diff --git a/test/fail_compilation/test23170.d b/test/fail_compilation/test23170.d new file mode 100644 index 0000000000..eb79cd8156 --- /dev/null +++ b/test/fail_compilation/test23170.d @@ -0,0 +1,12 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/test23170.d(10): Error: array literal in `@nogc` delegate `test23170.__lambda5` may cause a GC allocation +--- +*/ +// https://issues.dlang.org/show_bug.cgi?id=23170 + +@nogc: +enum lambda = () => badAlias([1, 2, 3]); +alias badAlias = (int[] array) => id(array); +int[] id(int[] array) { return array; } diff --git a/test/runnable/extra-files/lib21723a.d b/test/runnable/extra-files/lib21723a.d new file mode 100644 index 0000000000..9f3980debd --- /dev/null +++ b/test/runnable/extra-files/lib21723a.d @@ -0,0 +1,3 @@ +import lib21723b; + +alias Struct = lib21723b.Struct; diff --git a/test/runnable/extra-files/lib21723b.d b/test/runnable/extra-files/lib21723b.d new file mode 100644 index 0000000000..c6bd7868c8 --- /dev/null +++ b/test/runnable/extra-files/lib21723b.d @@ -0,0 +1,4 @@ +struct Struct { + invariant { void call() { } } + void templfun()() { } +} diff --git a/test/runnable/extra-files/lib23148.d b/test/runnable/extra-files/lib23148.d new file mode 100644 index 0000000000..c532d8a536 --- /dev/null +++ b/test/runnable/extra-files/lib23148.d @@ -0,0 +1,10 @@ +struct Struct { + SumType!() v1; +} +void foo()() { SumType!() v2; } +struct SumType() { + ~this() { } + invariant { alias a = {}; match!a(); } + +} +void match(alias handler)() { } diff --git a/test/runnable/extra-files/test21723.d b/test/runnable/extra-files/test21723.d new file mode 100644 index 0000000000..2cbf2b45cb --- /dev/null +++ b/test/runnable/extra-files/test21723.d @@ -0,0 +1,5 @@ +import lib21723a; + +void trigger(Struct val) { val.templfun; } + +void main() { alias lambda = a => a; } diff --git a/test/runnable/extra-files/test23148.d b/test/runnable/extra-files/test23148.d new file mode 100644 index 0000000000..e25bc0707a --- /dev/null +++ b/test/runnable/extra-files/test23148.d @@ -0,0 +1,6 @@ +import lib23148; + +alias l = _ => 0; +void main() { + foo!()(); +} diff --git a/test/runnable/noreturn1.d b/test/runnable/noreturn1.d index 7d15b54a21..5ed46c1625 100644 --- a/test/runnable/noreturn1.d +++ b/test/runnable/noreturn1.d @@ -261,6 +261,37 @@ void testThrowDtor() /*****************************************/ +noreturn func() +{ + throw new Exception("B"); +} + +// https://issues.dlang.org/show_bug.cgi?id=23120 +void test23120() +{ + string a; + try + { + noreturn q = throw new Exception ("A"); + } + catch(Exception e) + { + a ~= e.msg; + } + + try + { + noreturn z = func(); + } + catch(Exception e) + { + a ~= e.msg; + } + + assert(a == "AB"); +} + +/*****************************************/ int main() { test1(); @@ -269,5 +300,6 @@ int main() testThrowExpression(); testThrowSideEffect(); testThrowDtor(); + test23120(); return 0; } diff --git a/test/runnable/test20734.d b/test/runnable/test20734.d index 264602bccc..b3c5916ada 100644 --- a/test/runnable/test20734.d +++ b/test/runnable/test20734.d @@ -16,6 +16,7 @@ extern(C) int main() nothrow @nogc @safe { takeScopeSlice([ S(1), S(2) ]); // @nogc => no GC allocation (() @trusted { assert(numDtor == 2); })(); // stack-allocated array literal properly destructed + assert23100([]); return 0; } @@ -26,3 +27,9 @@ void test23098() @safe { f23098([10, 20]); } + +// https://issues.dlang.org/show_bug.cgi?id=23100 +void assert23100(scope int[] d) @safe nothrow @nogc +{ + assert(!d); +} diff --git a/test/runnable/test21723.sh b/test/runnable/test21723.sh new file mode 100644 index 0000000000..b8833b83b7 --- /dev/null +++ b/test/runnable/test21723.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +$DMD -m${MODEL} -I${EXTRA_FILES} -of${OUTPUT_BASE}${LIBEXT} -lib ${EXTRA_FILES}/lib21723a.d ${EXTRA_FILES}/lib21723b.d +$DMD -m${MODEL} -I${EXTRA_FILES} -of${OUTPUT_BASE}${EXE} -inline ${EXTRA_FILES}/test21723.d ${OUTPUT_BASE}${LIBEXT} + +rm_retry ${OUTPUT_BASE}{${LIBEXT},${EXE}} diff --git a/test/runnable/test23148.sh b/test/runnable/test23148.sh new file mode 100644 index 0000000000..5d3c5e44e6 --- /dev/null +++ b/test/runnable/test23148.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +$DMD -m${MODEL} -I${EXTRA_FILES} -of${OUTPUT_BASE}${LIBEXT} -lib ${EXTRA_FILES}/lib23148.d +$DMD -m${MODEL} -I${EXTRA_FILES} -of${OUTPUT_BASE}${EXE} ${EXTRA_FILES}/test23148.d ${OUTPUT_BASE}${LIBEXT} + +rm_retry ${OUTPUT_BASE}{${LIBEXT},${EXE}} diff --git a/test/runnable/test23181.d b/test/runnable/test23181.d new file mode 100644 index 0000000000..b961690a2b --- /dev/null +++ b/test/runnable/test23181.d @@ -0,0 +1,27 @@ +// https://issues.dlang.org/show_bug.cgi?id=23181 +void main() +{ + int count; + struct HasDtor + { + ~this() { ++count; } + } + + // array[] = elem() + // -> creates temporary to construct array and calls destructor. + { + count = 0; + HasDtor[4] dtor1 = HasDtor(); + assert(count == 1); + } + assert(count == 5); + + // array[] = array[elem()] + // -> constructs array using direct emplacement. + { + count = 0; + HasDtor[2] dtor2 = [HasDtor(), HasDtor()]; + assert(count == 0); + } + assert(count == 2); +} diff --git a/test/runnable/warning1.d b/test/runnable/warning1.d index 537088e97c..01ac20c0ba 100644 --- a/test/runnable/warning1.d +++ b/test/runnable/warning1.d @@ -133,15 +133,6 @@ void test6518() } } -/******************************************/ -// https://issues.dlang.org/show_bug.cgi?id=7232 - -bool test7232() -{ - scope(failure) return false; - return true; -} - /***************************************************/ struct S9332