From patchwork Tue Jul 26 21:46:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 56350 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EB9A438582A0 for ; Tue, 26 Jul 2022 21:47:01 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EB9A438582A0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1658872022; bh=EPx7sM+81FAZoQpfbGi3JM6FNQ11SY/1e8OSH5CbP7w=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=guvLpejgH5b8YyazH5Ypm4LPgXLNl8CvtxTaMiF558MuOnwIVRGcmmB9Cie+h0Iha tFB0TYqRaNM06BpGdJDCI2lnkxsTrHudI5QdFYGNxiOkoOkZ9N2ggwP615j4CNFdM6 N4L9iqwfr4FNJbkp9LLoKBqoO26nuZB+F9ajidZ0= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [80.241.56.151]) by sourceware.org (Postfix) with ESMTPS id 4A12B3858C56 for ; Tue, 26 Jul 2022 21:46:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 4A12B3858C56 Received: from smtp202.mailbox.org (smtp202.mailbox.org [IPv6:2001:67c:2050:b231:465::202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4Lsr8J64yXz9sSK; Tue, 26 Jul 2022 23:46:24 +0200 (CEST) To: gcc-patches@gcc.gnu.org Subject: [GCC 12, committed] d: Merge upstream dmd 76e3b41375, druntime 1462ebd1, phobos 5fef0d28f. Date: Tue, 26 Jul 2022 23:46:21 +0200 Message-Id: <20220726214621.1275981-1-ibuclaw@gdcproject.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 4Lsr8J64yXz9sSK X-Spam-Status: No, score=-13.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_LOTSOFHASH, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Iain Buclaw via Gcc-patches From: Iain Buclaw Reply-To: Iain Buclaw Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, This patch merges the D front-end with upstream dmd 76e3b41375, and standard run-time libraries with druntime 1462ebd1, and phobos 5fef0d28f, updating the D language version to v2.100.1. D front-end changes: - Fix delegate literal with inferred return value that requires following alias-this to not use class cast. - Fix internal error on variadic template type instantiated with two arrays of classes. - `scope(failure)' blocks that contain `return' statements are now deprecated. - Fix regression where wrong cast was inserted for ternary operator and non-int enums. - Fix internal error in code generation trying to reference _d_arraysetctor. - Fix memory corruption when array literal is passed to map in lambda, then returned from nested function. - Generate invariant id on the basis of location rather than a global counter. - Make `noreturn' conversions work. - Fix segfault when `.stringof' of template alias overloaded with function accessed by trait. - Empty array literal passed to scope param not 'falsey' anymore. Phobos changes: - Avoid copying ranges in std.algorithm.comparison.equal. Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, and committed to the releases/gcc-12 branch. Regards, Iain. --- gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 76e3b41375. * dmd/VERSION: Bump version to v2.100.1. * decl.cc (DeclVisitor::visit (VarDeclaration *)): Evaluate RHS of noreturn declaration expressions first. * expr.cc (ExprVisitor::visit (AssignExp *)): Don't generate assignment for noreturn types. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 1462ebd1. * src/MERGE: Merge upstream phobos 5fef0d28f. --- gcc/d/decl.cc | 7 ++- gcc/d/dmd/MERGE | 2 +- gcc/d/dmd/VERSION | 2 +- gcc/d/dmd/dcast.d | 14 ++++- gcc/d/dmd/dsymbolsem.d | 3 + gcc/d/dmd/expressionsem.d | 13 +++-- gcc/d/dmd/func.d | 14 ++++- gcc/d/dmd/impcnvtab.d | 55 +++++++++++++++++++ gcc/d/dmd/mtype.d | 5 ++ gcc/d/dmd/statementsem.d | 16 +++++- gcc/d/expr.cc | 11 ++++ .../gdc.test/compilable/backendfloatoptim.d | 10 ++++ gcc/testsuite/gdc.test/compilable/noreturn1.d | 28 ++++++++++ gcc/testsuite/gdc.test/compilable/test23082.d | 17 ++++++ gcc/testsuite/gdc.test/compilable/test23166.d | 22 ++++++++ gcc/testsuite/gdc.test/compilable/test23172.d | 33 +++++++++++ gcc/testsuite/gdc.test/compilable/test23258.d | 21 +++++++ .../gdc.test/fail_compilation/fail23181.d | 16 ++++++ .../gdc.test/fail_compilation/fail6889.d | 2 +- .../gdc.test/fail_compilation/fail7848.d | 8 +-- .../gdc.test/fail_compilation/test21443.d | 21 +++++++ .../gdc.test/fail_compilation/test23170.d | 12 ++++ gcc/testsuite/gdc.test/runnable/noreturn1.d | 32 +++++++++++ gcc/testsuite/gdc.test/runnable/test20734.d | 7 +++ gcc/testsuite/gdc.test/runnable/test23181.d | 27 +++++++++ gcc/testsuite/gdc.test/runnable/test23234.d | 22 ++++++++ gcc/testsuite/gdc.test/runnable/warning1.d | 9 --- libphobos/libdruntime/MERGE | 2 +- libphobos/src/MERGE | 2 +- libphobos/src/std/algorithm/comparison.d | 2 +- libphobos/src/std/typecons.d | 10 +++- 31 files changed, 408 insertions(+), 37 deletions(-) create mode 100644 gcc/testsuite/gdc.test/compilable/backendfloatoptim.d create mode 100644 gcc/testsuite/gdc.test/compilable/test23082.d create mode 100644 gcc/testsuite/gdc.test/compilable/test23166.d create mode 100644 gcc/testsuite/gdc.test/compilable/test23172.d create mode 100644 gcc/testsuite/gdc.test/compilable/test23258.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail23181.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test21443.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test23170.d create mode 100644 gcc/testsuite/gdc.test/runnable/test23181.d create mode 100644 gcc/testsuite/gdc.test/runnable/test23234.d diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc index f5c21078aad..43c3d87cdd1 100644 --- a/gcc/d/decl.cc +++ b/gcc/d/decl.cc @@ -645,9 +645,12 @@ public: if (!d->isDataseg () && !d->isMember () && d->_init && !d->_init->isVoidInitializer ()) { + /* Evaluate RHS for side effects first. */ + Expression *ie = initializerToExpression (d->_init); + add_stmt (build_expr (ie)); + Expression *e = d->type->defaultInitLiteral (d->loc); - tree exp = build_expr (e); - add_stmt (exp); + add_stmt (build_expr (e)); } return; diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index d538621ba83..d79ebfae806 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -a53934d18eecccbf677cd32a4febeff3bc0ee292 +76e3b41375e3e1cb4dbca692b587d8e916c0b49f 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/VERSION b/gcc/d/dmd/VERSION index 5ea2ba0d8ec..83a14f57e16 100644 --- a/gcc/d/dmd/VERSION +++ b/gcc/d/dmd/VERSION @@ -1 +1 @@ -v2.100.0 +v2.100.1 diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index 83978391e42..6afa1c966b0 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.d @@ -1107,9 +1107,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); @@ -2954,6 +2959,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/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index be8f9150903..c5766787bf0 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -4407,7 +4407,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/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index 717420910aa..0617b69ccc9 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -2048,7 +2048,8 @@ private bool functionParameters(const ref Loc loc, Scope* sc, if (global.params.useDIP1000 == FeatureState.enabled) err |= checkParamArgumentEscape(sc, fd, p, arg, false, false); } - else if (!(pStc & STC.return_)) + else if (!(pStc & STC.return_) && + ((global.params.useDIP1000 == FeatureState.enabled) || !(p.storageClass & STC.scopeinferred))) { /* Argument value cannot escape from the called function. */ @@ -2058,10 +2059,10 @@ private bool functionParameters(const ref Loc loc, Scope* sc, ArrayLiteralExp ale; if (p.type.toBasetype().ty == Tarray && - (ale = a.isArrayLiteralExp()) !is null) + (ale = a.isArrayLiteralExp()) !is null && ale.elements && ale.elements.length > 0) { // allocate the array literal as temporary static array on the stack - ale.type = ale.type.nextOf().sarrayOf(ale.elements ? ale.elements.length : 0); + ale.type = ale.type.nextOf().sarrayOf(ale.elements.length); auto tmp = copyToTemp(0, "__arrayliteral_on_stack", ale); auto declareTmp = new DeclarationExp(ale.loc, tmp); auto castToSlice = new CastExp(ale.loc, new VarExp(ale.loc, tmp), @@ -9926,9 +9927,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); @@ -12535,7 +12538,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/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index 55abe4d52e7..aba5d62827a 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -3748,9 +3748,7 @@ extern (C++) final class FuncLiteralDeclaration : FuncDeclaration { Expression exp = s.exp; if (exp && !exp.type.equals(tret)) - { - s.exp = exp.castTo(sc, tret); - } + s.exp = exp.implicitCastTo(sc, tret); } } @@ -4150,6 +4148,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; } @@ -4186,6 +4185,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/gcc/d/dmd/impcnvtab.d b/gcc/d/dmd/impcnvtab.d index ab46f5eebbd..832c331c314 100644 --- a/gcc/d/dmd/impcnvtab.d +++ b/gcc/d/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/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d index 32f57d46773..12608534879 100644 --- a/gcc/d/dmd/mtype.d +++ b/gcc/d/dmd/mtype.d @@ -6184,6 +6184,11 @@ extern (C++) final class TypeClass : Type if (t && t.ty == Tclass) { ClassDeclaration cd = (cast(TypeClass)t).sym; + if (cd.semanticRun < PASS.semanticdone && !cd.isBaseInfoComplete()) + cd.dsymbolSemantic(null); + if (sym.semanticRun < PASS.semanticdone && !sym.isBaseInfoComplete()) + sym.dsymbolSemantic(null); + if (sym.isBaseOf(cd, poffset)) return true; } diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d index 2916bbc38dd..c1c2dc92e12 100644 --- a/gcc/d/dmd/statementsem.d +++ b/gcc/d/dmd/statementsem.d @@ -2829,10 +2829,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/gcc/d/expr.cc b/gcc/d/expr.cc index 73dab463926..6fba382f0ed 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -916,6 +916,17 @@ public: gcc_unreachable (); } + /* Look for exp = noreturn; */ + if (e->e2->type->isTypeNoreturn ()) + { + /* If the RHS is a `noreturn' expression, there is no point generating + any code for the assignment, just evaluate side effects. */ + tree t1 = build_expr (e->e1); + tree t2 = build_expr (e->e2); + this->result_ = compound_expr (t1, t2); + return; + } + /* Look for array[] = n; */ if (e->e1->op == EXP::slice) { diff --git a/gcc/testsuite/gdc.test/compilable/backendfloatoptim.d b/gcc/testsuite/gdc.test/compilable/backendfloatoptim.d new file mode 100644 index 00000000000..7ec9f614ef8 --- /dev/null +++ b/gcc/testsuite/gdc.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/gcc/testsuite/gdc.test/compilable/noreturn1.d b/gcc/testsuite/gdc.test/compilable/noreturn1.d index 5bba9baa72a..e648a56d896 100644 --- a/gcc/testsuite/gdc.test/compilable/noreturn1.d +++ b/gcc/testsuite/gdc.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/gcc/testsuite/gdc.test/compilable/test23082.d b/gcc/testsuite/gdc.test/compilable/test23082.d new file mode 100644 index 00000000000..9df4e4e7774 --- /dev/null +++ b/gcc/testsuite/gdc.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/gcc/testsuite/gdc.test/compilable/test23166.d b/gcc/testsuite/gdc.test/compilable/test23166.d new file mode 100644 index 00000000000..66da4cd6963 --- /dev/null +++ b/gcc/testsuite/gdc.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/gcc/testsuite/gdc.test/compilable/test23172.d b/gcc/testsuite/gdc.test/compilable/test23172.d new file mode 100644 index 00000000000..18b6d4ce8c5 --- /dev/null +++ b/gcc/testsuite/gdc.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/gcc/testsuite/gdc.test/compilable/test23258.d b/gcc/testsuite/gdc.test/compilable/test23258.d new file mode 100644 index 00000000000..1e8e91b7795 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test23258.d @@ -0,0 +1,21 @@ +// https://issues.dlang.org/show_bug.cgi?id=23258 + +struct SumType(Types...) +{ + this(Types[0]) + { + } + this(Types[1]) + { + } +} + +alias A2 = SumType!(C1[], C2[]); + +class C1 +{ +} + +class C2 +{ +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23181.d b/gcc/testsuite/gdc.test/fail_compilation/fail23181.d new file mode 100644 index 00000000000..519244c1cdf --- /dev/null +++ b/gcc/testsuite/gdc.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/gcc/testsuite/gdc.test/fail_compilation/fail6889.d b/gcc/testsuite/gdc.test/fail_compilation/fail6889.d index aa189770903..ee84a84ce79 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail6889.d +++ b/gcc/testsuite/gdc.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/gcc/testsuite/gdc.test/fail_compilation/fail7848.d b/gcc/testsuite/gdc.test/fail_compilation/fail7848.d index e8371c4f7fe..001c7d75443 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail7848.d +++ b/gcc/testsuite/gdc.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/gcc/testsuite/gdc.test/fail_compilation/test21443.d b/gcc/testsuite/gdc.test/fail_compilation/test21443.d new file mode 100644 index 00000000000..2d99524da35 --- /dev/null +++ b/gcc/testsuite/gdc.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/gcc/testsuite/gdc.test/fail_compilation/test23170.d b/gcc/testsuite/gdc.test/fail_compilation/test23170.d new file mode 100644 index 00000000000..eb79cd81565 --- /dev/null +++ b/gcc/testsuite/gdc.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/gcc/testsuite/gdc.test/runnable/noreturn1.d b/gcc/testsuite/gdc.test/runnable/noreturn1.d index 7d15b54a213..5ed46c16250 100644 --- a/gcc/testsuite/gdc.test/runnable/noreturn1.d +++ b/gcc/testsuite/gdc.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/gcc/testsuite/gdc.test/runnable/test20734.d b/gcc/testsuite/gdc.test/runnable/test20734.d index 264602bccc5..b3c5916ada5 100644 --- a/gcc/testsuite/gdc.test/runnable/test20734.d +++ b/gcc/testsuite/gdc.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/gcc/testsuite/gdc.test/runnable/test23181.d b/gcc/testsuite/gdc.test/runnable/test23181.d new file mode 100644 index 00000000000..b961690a2bc --- /dev/null +++ b/gcc/testsuite/gdc.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/gcc/testsuite/gdc.test/runnable/test23234.d b/gcc/testsuite/gdc.test/runnable/test23234.d new file mode 100644 index 00000000000..7872aa76dfe --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable/test23234.d @@ -0,0 +1,22 @@ +// https://issues.dlang.org/show_bug.cgi?id=23234 + +class Bar +{ +} + +class Foo +{ + Bar get() { return new Bar; } + alias get this; +} + +void main() +{ + auto foo = new Foo; + void test(Bar delegate() dg) + { + assert(dg() !is null); + } + + test(() => foo); +} diff --git a/gcc/testsuite/gdc.test/runnable/warning1.d b/gcc/testsuite/gdc.test/runnable/warning1.d index 537088e97cc..01ac20c0baf 100644 --- a/gcc/testsuite/gdc.test/runnable/warning1.d +++ b/gcc/testsuite/gdc.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 diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index 9bab8ed6395..c96180a3751 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -1,4 +1,4 @@ -9c0d4f914e0817c9ee4eafc5a45c41130aa6b981 +1462ebd188c0ab5181a0a75e3576754bb0b81a16 The first line of this file holds the git revision number of the last merge done from the dlang/druntime repository. diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE index ed9a02e1a0c..f2678185f39 100644 --- a/libphobos/src/MERGE +++ b/libphobos/src/MERGE @@ -1,4 +1,4 @@ -604534d7cb29d49a6474f0aaaa5d166057a44f72 +5fef0d28fc873fb5a0dbfb9149759d76a7b9f1b7 The first line of this file holds the git revision number of the last merge done from the dlang/phobos repository. diff --git a/libphobos/src/std/algorithm/comparison.d b/libphobos/src/std/algorithm/comparison.d index 2fcc2bacd5c..b810fbb9258 100644 --- a/libphobos/src/std/algorithm/comparison.d +++ b/libphobos/src/std/algorithm/comparison.d @@ -1027,7 +1027,7 @@ template equal(alias pred = "a == b") } } - private bool equalLoop(Rs...)(Rs rs) + private bool equalLoop(Rs...)(ref Rs rs) { for (; !rs[0].empty; rs[0].popFront) static foreach (r; rs[1 .. $]) diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d index 1ee7faaee7b..fb15001233a 100644 --- a/libphobos/src/std/typecons.d +++ b/libphobos/src/std/typecons.d @@ -4905,8 +4905,14 @@ if (is(Interface == interface) && is(BaseClass == class)) // - try default first // - only on a failure run & return fallback enum fallback = q{ - scope (failure) return fallback.%1$s(args); - return default_.%1$s(args); + try + { + return default_.%1$s(args); + } + catch (Exception) + { + return fallback.%1$s(args); + } }.format(__traits(identifier, func)); }