From patchwork Mon Jul 10 22:09:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 1806002 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=UxnXBsZh; dkim-atps=neutral Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4R0J9f71BQz20ZZ for ; Tue, 11 Jul 2023 08:11:02 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A48DB3858CDA for ; Mon, 10 Jul 2023 22:11:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A48DB3858CDA DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1689027060; bh=UQQODb47rY99xhsZbVjmU0c2LhtxuTXrZYw3r/ugBHg=; h=To:Cc:Subject:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=UxnXBsZhBrmab1ZP/q77foPK8a1iqE4NAuBVk0j1MEo2cBPNQGay4aXokNgAIodz5 oHi8xH6MV/kMNN6JS8/Kh+GLxLUhk9fJ7xoe0DbGim2D7Vvc9YjQSuqyACE848B4Sl 77luBcaqwrn/KDyxop/CzmoR+f5NFcIUgSjGfdkY= 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 [IPv6:2001:67c:2050:0:465::101]) by sourceware.org (Postfix) with ESMTPS id B4ED63858284 for ; Mon, 10 Jul 2023 22:10:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B4ED63858284 Received: from smtp202.mailbox.org (smtp202.mailbox.org [10.196.197.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 4R0J8R3VVKz9sc0; Tue, 11 Jul 2023 00:09:59 +0200 (CEST) To: gcc-patches@gcc.gnu.org Cc: Iain Buclaw Subject: [committed] d: Merge upstream dmd, druntime a88e1335f7, phobos 1921d29df. Date: Tue, 11 Jul 2023 00:09:57 +0200 Message-Id: <20230710220957.1579524-1-ibuclaw@gdcproject.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Hi, This patch merges the D front-end and run-time library with upstream dmd a88e1335f7, and standard library with phobos 1921d29df. Synchronizing with the latest bug fixes in the v2.104.1 release. D front-end changes: - Import dmd v2.104.1. - Deprecation phase ended for access to private method when overloaded with public method. D runtime changes: - Import druntime v2.104.1. - Linux input header translations were added to druntime. - Integration with the Valgrind `memcheck' tool has been added to the garbage collector. Phobos changes: - Import phobos v2.104.1. Bootstrapped and regression tested on x86_64-linux-gnu/-m32, committed to mainline. Regards, Iain. --- gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd a88e1335f7. * dmd/VERSION: Bump version to v2.104.1. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime a88e1335f7. * src/MERGE: Merge upstream phobos 1921d29df. * config.h.in: Regenerate. * configure: Regenerate. * configure.ac (libphobos-checking): Add valgrind flag. (DRUNTIME_LIBRARIES_VALGRIND): Call. * libdruntime/Makefile.am (DRUNTIME_CSOURCES): Add etc/valgrind/valgrind_.c. (DRUNTIME_DSOURCES): Add etc/valgrind/valgrind.d. (DRUNTIME_DSOURCES_LINUX): Add core/sys/linux/input.d, core/sys/linux/input_event_codes.d, core/sys/linux/uinput.d. * libdruntime/Makefile.in: Regenerate. * m4/druntime/libraries.m4 (DRUNTIME_LIBRARIES_VALGRIND): Define. --- gcc/d/dmd/MERGE | 2 +- gcc/d/dmd/README.md | 1 - gcc/d/dmd/VERSION | 2 +- gcc/d/dmd/access.d | 4 - gcc/d/dmd/attrib.d | 3 +- gcc/d/dmd/canthrow.d | 4 +- gcc/d/dmd/cparse.d | 2 +- gcc/d/dmd/dcast.d | 1 + gcc/d/dmd/declaration.d | 2 +- gcc/d/dmd/dinterpret.d | 28 +- gcc/d/dmd/dmangle.d | 2 +- gcc/d/dmd/dmodule.d | 19 +- gcc/d/dmd/dsymbolsem.d | 51 +- gcc/d/dmd/dtemplate.d | 64 +- gcc/d/dmd/dtoh.d | 2 +- gcc/d/dmd/escape.d | 36 +- gcc/d/dmd/expression.d | 25 +- gcc/d/dmd/expressionsem.d | 103 ++- gcc/d/dmd/hdrgen.d | 8 +- gcc/d/dmd/initsem.d | 14 +- gcc/d/dmd/inline.d | 4 +- gcc/d/dmd/lexer.d | 2 +- gcc/d/dmd/mtype.d | 19 +- gcc/d/dmd/opover.d | 8 +- gcc/d/dmd/optimize.d | 2 +- gcc/d/dmd/parse.d | 21 +- gcc/d/dmd/root/array.d | 18 + gcc/d/dmd/semantic2.d | 7 + gcc/d/dmd/semantic3.d | 4 +- gcc/d/dmd/statementsem.d | 30 +- gcc/d/dmd/traits.d | 6 +- gcc/d/dmd/transitivevisitor.d | 8 +- gcc/d/dmd/typesem.d | 12 +- gcc/testsuite/gdc.test/compilable/b20938.d | 3 +- .../gdc.test/compilable/commontype.d | 12 +- .../compilable/imports/pkg20008/package.d | 9 + .../compilable/imports/pkg20008/submod.d | 2 + .../imports/pkg20008/subpkg/package.d | 7 + .../imports/pkg20008/subpkg/subsubmod.d | 9 + .../gdc.test/compilable/imports/test9692b.d | 2 +- .../gdc.test/compilable/issue24018.d | 10 + .../gdc.test/compilable/stc_traits.d | 106 +-- gcc/testsuite/gdc.test/compilable/test13668.d | 2 +- gcc/testsuite/gdc.test/compilable/test16635.d | 2 +- gcc/testsuite/gdc.test/compilable/test17143.d | 2 +- gcc/testsuite/gdc.test/compilable/test17373.d | 4 +- gcc/testsuite/gdc.test/compilable/test17545.d | 2 +- gcc/testsuite/gdc.test/compilable/test19728.d | 14 +- gcc/testsuite/gdc.test/compilable/test20008.d | 6 + gcc/testsuite/gdc.test/compilable/test21282.d | 2 +- gcc/testsuite/gdc.test/compilable/test21330.d | 4 +- gcc/testsuite/gdc.test/compilable/test23965.d | 11 + gcc/testsuite/gdc.test/compilable/test23978.d | 30 + gcc/testsuite/gdc.test/compilable/test23979.d | 17 + gcc/testsuite/gdc.test/compilable/test23986.d | 11 + gcc/testsuite/gdc.test/compilable/test24013.d | 43 + gcc/testsuite/gdc.test/compilable/test24017.d | 11 + gcc/testsuite/gdc.test/compilable/test9692.d | 4 +- .../gdc.test/compilable/testInference.d | 6 +- .../gdc.test/fail_compilation/callconst.d | 16 + .../gdc.test/fail_compilation/casttuple.d | 6 +- .../gdc.test/fail_compilation/cppmangle.d | 2 +- .../gdc.test/fail_compilation/dassert.d | 2 +- .../gdc.test/fail_compilation/diag13884.d | 2 +- .../gdc.test/fail_compilation/diag14876.d | 2 +- .../fail_compilation/dtor_attributes.d | 2 +- .../gdc.test/fail_compilation/e15876_1.d | 13 +- .../gdc.test/fail_compilation/e15876_2.d | 9 +- .../gdc.test/fail_compilation/e15876_3.d | 27 +- .../gdc.test/fail_compilation/e15876_4.d | 23 +- .../gdc.test/fail_compilation/e15876_5.d | 11 +- .../gdc.test/fail_compilation/enum_init.d | 2 + .../gdc.test/fail_compilation/fail12436.d | 2 +- .../gdc.test/fail_compilation/fail15755.d | 2 +- .../gdc.test/fail_compilation/fail16772.d | 3 +- .../gdc.test/fail_compilation/fail19209.d | 2 +- .../gdc.test/fail_compilation/fail196.d | 38 +- .../gdc.test/fail_compilation/fail21206.d | 3 +- .../gdc.test/fail_compilation/fail21275.d | 5 +- .../gdc.test/fail_compilation/fail222.d | 4 +- .../gdc.test/fail_compilation/fail22729.d | 39 + .../gdc.test/fail_compilation/fail23745.d | 2 +- .../gdc.test/fail_compilation/fail315.d | 15 +- .../gdc.test/fail_compilation/funcpostattr.d | 21 + .../gdc.test/fail_compilation/ice11965.d | 9 +- .../gdc.test/fail_compilation/ice11982.d | 17 +- .../gdc.test/fail_compilation/ice12574.d | 2 +- .../gdc.test/fail_compilation/ice14424.d | 2 +- .../gdc.test/fail_compilation/ice15855.d | 21 +- .../fail_compilation/imports/issue23947a.d | 8 + .../gdc.test/fail_compilation/issue20422.d | 9 +- .../gdc.test/fail_compilation/issue23947.d | 10 + .../gdc.test/fail_compilation/lexer4.d | 2 +- .../fail_compilation/misc_parser_err_cov1.d | 3 +- .../gdc.test/fail_compilation/missingbrace.d | 10 + .../gdc.test/fail_compilation/retscope.d | 2 +- .../gdc.test/fail_compilation/test20245.d | 2 +- .../gdc.test/fail_compilation/test21025.d | 25 + .../gdc.test/fail_compilation/test23968.d | 23 + .../gdc.test/fail_compilation/test23982.d | 36 + .../gdc.test/fail_compilation/typeerrors.d | 2 +- .../fail_compilation/unmatchedbrace.d | 10 + gcc/testsuite/gdc.test/runnable/functype.d | 2 +- gcc/testsuite/gdc.test/runnable/interface2.d | 4 +- gcc/testsuite/gdc.test/runnable/link10425.d | 2 +- gcc/testsuite/gdc.test/runnable/sdtor.d | 36 + gcc/testsuite/gdc.test/runnable/template9.d | 3 +- gcc/testsuite/gdc.test/runnable/test23959.d | 30 + .../gdc.test/runnable/testcontracts.d | 2 +- gcc/testsuite/gdc.test/runnable/uda.d | 42 +- gcc/testsuite/gdc.test/runnable/xtest46.d | 10 +- gcc/testsuite/gdc.test/runnable/xtest46_gc.d | 10 +- libphobos/config.h.in | 12 + libphobos/configure | 101 ++- libphobos/configure.ac | 16 +- libphobos/libdruntime/MERGE | 2 +- libphobos/libdruntime/Makefile.am | 16 +- libphobos/libdruntime/Makefile.in | 58 +- libphobos/libdruntime/core/atomic.d | 10 +- .../core/internal/array/concatenation.d | 17 +- .../core/internal/gc/impl/conservative/gc.d | 131 ++- .../libdruntime/core/internal/gc/proxy.d | 7 +- .../libdruntime/core/internal/parseoptions.d | 12 +- libphobos/libdruntime/core/lifetime.d | 10 +- libphobos/libdruntime/core/stdc/assert_.d | 13 +- libphobos/libdruntime/core/stdc/wchar_.d | 5 +- libphobos/libdruntime/core/sys/linux/input.d | 236 ++++++ .../core/sys/linux/input_event_codes.d | 758 ++++++++++++++++++ libphobos/libdruntime/core/sys/linux/uinput.d | 85 ++ .../libdruntime/core/sys/openbsd/unistd.d | 4 + libphobos/libdruntime/core/sys/windows/dll.d | 49 +- libphobos/libdruntime/etc/valgrind/valgrind.d | 85 ++ .../libdruntime/etc/valgrind/valgrind_.c | 102 +++ libphobos/libdruntime/object.d | 40 +- libphobos/libdruntime/rt/lifetime.d | 12 +- libphobos/libdruntime/rt/minfo.d | 4 +- libphobos/libdruntime/rt/util/typeinfo.d | 2 +- libphobos/m4/druntime/libraries.m4 | 53 ++ libphobos/src/MERGE | 2 +- libphobos/src/std/algorithm/iteration.d | 4 +- libphobos/src/std/algorithm/mutation.d | 2 +- libphobos/src/std/algorithm/searching.d | 48 +- libphobos/src/std/complex.d | 4 +- libphobos/src/std/container/array.d | 2 +- libphobos/src/std/conv.d | 22 +- libphobos/src/std/exception.d | 2 +- .../building_blocks/kernighan_ritchie.d | 2 +- libphobos/src/std/format/internal/floats.d | 12 +- libphobos/src/std/format/internal/write.d | 8 +- libphobos/src/std/math/operations.d | 15 +- libphobos/src/std/path.d | 22 +- libphobos/src/std/random.d | 4 +- libphobos/src/std/range/package.d | 41 +- libphobos/src/std/regex/internal/ir.d | 25 +- libphobos/src/std/signals.d | 4 +- libphobos/src/std/stdio.d | 90 ++- libphobos/src/std/traits.d | 6 +- libphobos/src/std/typecons.d | 134 ++++ libphobos/src/std/uni/package.d | 39 +- 159 files changed, 3079 insertions(+), 681 deletions(-) create mode 100644 gcc/testsuite/gdc.test/compilable/imports/pkg20008/package.d create mode 100644 gcc/testsuite/gdc.test/compilable/imports/pkg20008/submod.d create mode 100644 gcc/testsuite/gdc.test/compilable/imports/pkg20008/subpkg/package.d create mode 100644 gcc/testsuite/gdc.test/compilable/imports/pkg20008/subpkg/subsubmod.d create mode 100644 gcc/testsuite/gdc.test/compilable/issue24018.d create mode 100644 gcc/testsuite/gdc.test/compilable/test20008.d create mode 100644 gcc/testsuite/gdc.test/compilable/test23965.d create mode 100644 gcc/testsuite/gdc.test/compilable/test23978.d create mode 100644 gcc/testsuite/gdc.test/compilable/test23979.d create mode 100644 gcc/testsuite/gdc.test/compilable/test23986.d create mode 100644 gcc/testsuite/gdc.test/compilable/test24013.d create mode 100644 gcc/testsuite/gdc.test/compilable/test24017.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/callconst.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/fail22729.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/funcpostattr.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/imports/issue23947a.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/issue23947.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/missingbrace.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test21025.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test23968.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test23982.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/unmatchedbrace.d create mode 100644 gcc/testsuite/gdc.test/runnable/test23959.d create mode 100644 libphobos/libdruntime/core/sys/linux/input.d create mode 100644 libphobos/libdruntime/core/sys/linux/input_event_codes.d create mode 100644 libphobos/libdruntime/core/sys/linux/uinput.d create mode 100644 libphobos/libdruntime/etc/valgrind/valgrind.d create mode 100644 libphobos/libdruntime/etc/valgrind/valgrind_.c diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index 1cff48a7b2a..308d51b55d0 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -17ccd12af386543c0b9935bf7e0a8e701b903105 +a88e1335f7ea767ef438c34998f5d1f26008c586 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/README.md b/gcc/d/dmd/README.md index 79215b7a0ea..4fd7831866a 100644 --- a/gcc/d/dmd/README.md +++ b/gcc/d/dmd/README.md @@ -174,7 +174,6 @@ | [cond.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cond.d) | Evaluate `static if`, `version` `debug ` | | [staticcond.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/staticcond.d) | Lazily evaluate static conditions for `static if`, `static assert` and template constraints | | [delegatize.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/delegatize.d) | Converts expression to delegates for `lazy` parameters | -| [eh.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/eh.d) | Generate tables for exception handling | | [nspace.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/nspace.d) | Namespace for `extern (C++, Module)` | | [intrange.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/intrange.d) | [Value range propagation](https://digitalmars.com/articles/b62.html) | | [dimport.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dimport.d) | Renamed imports (`import aliasSymbol = pkg1.pkg2.symbol`) | diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION index d5aee89f2cb..9c46eea2d8c 100644 --- a/gcc/d/dmd/VERSION +++ b/gcc/d/dmd/VERSION @@ -1 +1 @@ -v2.104.0 +v2.104.1 diff --git a/gcc/d/dmd/access.d b/gcc/d/dmd/access.d index f2d68d53d75..668129a5385 100644 --- a/gcc/d/dmd/access.d +++ b/gcc/d/dmd/access.d @@ -16,17 +16,13 @@ module dmd.access; import dmd.aggregate; import dmd.astenums; import dmd.dclass; -import dmd.declaration; import dmd.dmodule; import dmd.dscope; import dmd.dstruct; import dmd.dsymbol; -import dmd.errors; import dmd.expression; -import dmd.func; import dmd.globals; import dmd.location; -import dmd.mtype; import dmd.tokens; private enum LOG = false; diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d index c08382cbd04..ff4ebe8eaf9 100644 --- a/gcc/d/dmd/attrib.d +++ b/gcc/d/dmd/attrib.d @@ -653,7 +653,8 @@ extern (C++) final class VisibilityDeclaration : AttribDeclaration { Module m = sc._module; - // While isAncestorPackageOf does an equality check, the fix for issue 17441 adds a check to see if + // https://issues.dlang.org/show_bug.cgi?id=17441 + // While isAncestorPackageOf does an equality check, the fix for the issue adds a check to see if // each package's .isModule() properites are equal. // // Properties generated from `package(foo)` i.e. visibility.pkg have .isModule() == null. diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d index 09d39ca6f1c..89d5519b5d8 100644 --- a/gcc/d/dmd/canthrow.d +++ b/gcc/d/dmd/canthrow.d @@ -80,7 +80,7 @@ extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN if (!f.isDtorDeclaration()) errorSupplementalInferredAttr(f, 10, false, STC.nothrow_); - e.checkOverridenDtor(null, f, dd => dd.type.toTypeFunction().isnothrow, "not nothrow"); + e.checkOverriddenDtor(null, f, dd => dd.type.toTypeFunction().isnothrow, "not nothrow"); } else if (func) { @@ -118,7 +118,7 @@ extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN { auto sd = ts.sym; const id = ce.f.ident; - if (sd.postblit && isArrayConstructionOrAssign(id)) + if (sd.postblit && isArrayConstruction(id)) { checkFuncThrows(ce, sd.postblit); return; diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d index 33669e38c41..1b6b2bb4b1b 100644 --- a/gcc/d/dmd/cparse.d +++ b/gcc/d/dmd/cparse.d @@ -4235,7 +4235,7 @@ final class CParser(AST) : Parser!AST return false; /* https://issues.dlang.org/show_bug.cgi?id=22267 - Fix issue 22267: If the parser encounters the following + If the parser encounters the following `identifier variableName = (expression);` the initializer is not identified as such since the parentheses cause the parser to keep walking indefinitely diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index 6fcc2806585..b2aa6433baf 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.d @@ -2922,6 +2922,7 @@ Type typeMerge(Scope* sc, EXP op, ref Expression pe1, ref Expression pe2) ubyte mod = MODmerge(t1.mod, t2.mod); t1 = t1.castMod(mod); t2 = t2.castMod(mod); + return Lret(t1); } Lagain: diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d index cfa6988a861..5559b93eb20 100644 --- a/gcc/d/dmd/declaration.d +++ b/gcc/d/dmd/declaration.d @@ -599,7 +599,7 @@ extern (C++) final class TupleDeclaration : Declaration override const(char)* kind() const { - return "tuple"; + return "sequence"; } override Type getType() diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d index 5b27a07339a..cb74a079cd4 100644 --- a/gcc/d/dmd/dinterpret.d +++ b/gcc/d/dmd/dinterpret.d @@ -2412,7 +2412,7 @@ public: continue; if (ex.op == EXP.voidExpression) { - e.error("CTFE internal error: void element `%s` in tuple", exp.toChars()); + e.error("CTFE internal error: void element `%s` in sequence", exp.toChars()); assert(0); } @@ -3890,7 +3890,7 @@ public: newval = copyLiteral(newval).copy(); assignInPlace(oldval, newval); } - else if (wantCopy && e.op == EXP.assign) + else if (wantCopy && (e.op == EXP.assign || e.op == EXP.loweredAssignExp)) { // Currently postblit/destructor calls on static array are done // in the druntime internal functions so they don't appear in AST. @@ -4299,7 +4299,7 @@ public: rb.newval = newval; rb.refCopy = wantRef || cow; rb.needsPostblit = sd && sd.postblit && e.op != EXP.blit && e.e2.isLvalue(); - rb.needsDtor = sd && sd.dtor && e.op == EXP.assign; + rb.needsDtor = sd && sd.dtor && (e.op == EXP.assign || e.op == EXP.loweredAssignExp); if (Expression ex = rb.assignTo(existingAE, cast(size_t)lowerbound, cast(size_t)upperbound)) return ex; @@ -4773,12 +4773,11 @@ public: result = CTFEExp.voidexp; return; } - else if (isArrayConstructionOrAssign(fd.ident)) + else if (isArrayConstruction(fd.ident)) { - // In expressionsem.d, the following lowerings were performed: - // * `T[x] ea = eb;` to `_d_array{,set}ctor(ea[], eb[]);`. - // * `ea = eb` to `_d_array{,setassign,assign_l,assign_r}(ea[], eb)`. - // The following code will rewrite them back to `ea = eb` and + // In expressionsem.d, `T[x] ea = eb;` was lowered to: + // `_d_array{,set}ctor(ea[], eb[]);`. + // The following code will rewrite it back to `ea = eb` and // then interpret that expression. if (fd.ident == Id._d_arrayctor) @@ -4791,17 +4790,14 @@ public: ea = ea.isCastExp.e1; Expression eb = (*e.arguments)[1]; - if (eb.isCastExp() && fd.ident != Id._d_arraysetctor) + if (eb.isCastExp() && fd.ident == Id._d_arrayctor) eb = eb.isCastExp.e1; - Expression rewrittenExp; - if (fd.ident == Id._d_arrayctor || fd.ident == Id._d_arraysetctor) - rewrittenExp = new ConstructExp(e.loc, ea, eb); - else - rewrittenExp = new AssignExp(e.loc, ea, eb); + ConstructExp ce = new ConstructExp(e.loc, ea, eb); + ce.type = ea.type; - rewrittenExp.type = ea.type; - result = interpret(rewrittenExp, istate); + ce.type = ea.type; + result = interpret(ce, istate); return; } diff --git a/gcc/d/dmd/dmangle.d b/gcc/d/dmd/dmangle.d index 72a44765787..ad1e8165668 100644 --- a/gcc/d/dmd/dmangle.d +++ b/gcc/d/dmd/dmangle.d @@ -888,7 +888,7 @@ public: buf.writeByte('V'); if (ea.op == EXP.tuple) { - ea.error("tuple is not a valid template value argument"); + ea.error("sequence is not a valid template value argument"); continue; } // Now that we know it is not an alias, we MUST obtain a value diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d index 149a5b1aeb5..f00dec7a4e3 100644 --- a/gcc/d/dmd/dmodule.d +++ b/gcc/d/dmd/dmodule.d @@ -53,6 +53,10 @@ import dmd.target; import dmd.utils; import dmd.visitor; +version (IN_GCC) {} +else version (IN_LLVM) {} +else version = MARS; + // function used to call semantic3 on a module's dependencies void semantic3OnDependencies(Module m) { @@ -615,9 +619,18 @@ extern (C++) final class Module : Package if (FileName.equals(srcfile.toString(), "object.d")) { .error(loc, "cannot find source code for runtime library file 'object.d'"); - errorSupplemental(loc, "dmd might not be correctly installed. Run 'dmd -man' for installation instructions."); - const dmdConfFile = global.inifilename.length ? FileName.canonicalName(global.inifilename) : "not found"; - errorSupplemental(loc, "config file: %.*s", cast(int)dmdConfFile.length, dmdConfFile.ptr); + version (IN_LLVM) + { + errorSupplemental(loc, "ldc2 might not be correctly installed."); + errorSupplemental(loc, "Please check your ldc2.conf configuration file."); + errorSupplemental(loc, "Installation instructions can be found at http://wiki.dlang.org/LDC."); + } + version (MARS) + { + errorSupplemental(loc, "dmd might not be correctly installed. Run 'dmd -man' for installation instructions."); + const dmdConfFile = global.inifilename.length ? FileName.canonicalName(global.inifilename) : "not found"; + errorSupplemental(loc, "config file: %.*s", cast(int)dmdConfFile.length, dmdConfFile.ptr); + } } else if (FileName.ext(this.arg) || !loc.isValid()) { diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index a5cd63b1d4f..622e28691a6 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -587,6 +587,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor const loc = (s ? s : dsym).loc; loc.errorSupplemental("required by type `%s`", dsym.type.toChars()); } + errorSupplemental(dsym.loc, "see https://dlang.org/spec/struct.html#opaque_struct_unions"); + errorSupplemental(dsym.loc, "perhaps declare a variable with pointer type `%s*` instead", dsym.type.toChars()); // Flag variable as error to avoid invalid error messages due to unknown size dsym.type = Type.terror; @@ -693,7 +695,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor size_t tedim = te.exps.length; if (tedim != nelems) { - error(dsym.loc, "tuple of %d elements cannot be assigned to tuple of %d elements", cast(int)tedim, cast(int)nelems); + error(dsym.loc, "sequence of %d elements cannot be assigned to sequence of %d elements", cast(int)tedim, cast(int)nelems); for (size_t u = tedim; u < nelems; u++) // fill dummy expression te.exps.push(ErrorExp.get()); } @@ -2042,7 +2044,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor { } else - ns.exp.error("compile time string constant (or tuple) expected, not `%s`", + ns.exp.error("compile time string constant (or sequence) expected, not `%s`", ns.exp.toChars()); attribSemantic(ns); } @@ -2712,7 +2714,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } if (i + 1 != tempdecl.parameters.length && tp.isTemplateTupleParameter()) { - tempdecl.error("template tuple parameter must be last one"); + tempdecl.error("template sequence parameter must be the last one"); tempdecl.errors = true; } } @@ -3963,13 +3965,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor hgs.fullQual = true; // https://issues.dlang.org/show_bug.cgi?id=23745 - // If the potentially overriden function contains errors, + // If the potentially overridden function contains errors, // inform the user to fix that one first if (fd.errors) { error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?", funcdecl.toChars(), fd.toPrettyChars()); - errorSupplemental(fd.loc, "Function `%s` contains errors in its declaration, therefore it cannot be correctly overriden", + errorSupplemental(fd.loc, "Function `%s` contains errors in its declaration, therefore it cannot be correctly overridden", fd.toPrettyChars()); } else @@ -3985,7 +3987,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor { error(funcdecl.loc, "function `%s` does not override any function, did you mean to override %s `%s`?", funcdeclToChars, s.kind, s.toPrettyChars()); - errorSupplemental(funcdecl.loc, "Functions are the only declarations that may be overriden"); + errorSupplemental(funcdecl.loc, "Functions are the only declarations that may be overridden"); } } else @@ -5897,6 +5899,31 @@ void addEnumMembers(EnumDeclaration ed, Scope* sc, ScopeDsymbol sds) }); } +/****************************************************** + * Verifies if the given Identifier is a DRuntime hook. It uses the hooks + * defined in `id.d`. + * + * Params: + * id = Identifier to verify + * Returns: + * true if `id` is a DRuntime hook + * false otherwise + */ +private bool isDRuntimeHook(Identifier id) +{ + return id == Id._d_HookTraceImpl || + id == Id._d_newclassT || id == Id._d_newclassTTrace || + id == Id._d_arraycatnTX || id == Id._d_arraycatnTXTrace || + id == Id._d_newThrowable || id == Id._d_delThrowable || + id == Id._d_arrayassign_l || id == Id._d_arrayassign_r || + id == Id._d_arraysetassign || id == Id._d_arraysetctor || + id == Id._d_arrayctor || + id == Id._d_arraysetlengthTImpl || id == Id._d_arraysetlengthT || + id == Id._d_arraysetlengthTTrace || + id == Id._d_arrayappendT || id == Id._d_arrayappendTTrace || + id == Id._d_arrayappendcTXImpl; +} + void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList argumentList) { //printf("[%s] TemplateInstance.dsymbolSemantic('%s', this=%p, gag = %d, sc = %p)\n", tempinst.loc.toChars(), tempinst.toChars(), tempinst, global.gag, sc); @@ -6376,8 +6403,20 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList tempinst.deferred = &deferred; //printf("Run semantic3 on %s\n", toChars()); + + /* https://issues.dlang.org/show_bug.cgi?id=23965 + * DRuntime hooks are not deprecated, but may be used for deprecated + * types. Deprecations are disabled while analysing hooks to avoid + * spurious error messages. + */ + auto saveUseDeprecated = global.params.useDeprecated; + if (sc.isDeprecated() && isDRuntimeHook(tempinst.name)) + global.params.useDeprecated = DiagnosticReporting.off; + tempinst.trySemantic3(sc2); + global.params.useDeprecated = saveUseDeprecated; + for (size_t i = 0; i < deferred.length; i++) { //printf("+ run deferred semantic3 on %s\n", deferred[i].toChars()); diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d index 5b98d2f4877..f2ab69444bc 100644 --- a/gcc/d/dmd/dtemplate.d +++ b/gcc/d/dmd/dtemplate.d @@ -1302,36 +1302,19 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol /************************************************* * Match function arguments against a specific template function. - * Input: - * ti - * sc instantiation scope - * fd - * tthis 'this' argument if !NULL - * argumentList arguments to function - * Output: - * fd Partially instantiated function declaration - * ti.tdtypes Expression/Type deduced template arguments + * + * Params: + * ti = template instance. `ti.tdtypes` will be set to Expression/Type deduced template arguments + * sc = instantiation scope + * fd = Partially instantiated function declaration, which is set to an instantiated function declaration + * tthis = 'this' argument if !NULL + * argumentList = arguments to function + * * Returns: * match pair of initial and inferred template arguments */ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateInstance ti, Scope* sc, ref FuncDeclaration fd, Type tthis, ArgumentList argumentList) { - size_t nfparams; - size_t nfargs; - size_t ntargs; // array size of tiargs - size_t fptupindex = IDX_NOTFOUND; - MATCH match = MATCH.exact; - MATCH matchTiargs = MATCH.exact; - ParameterList fparameters; // function parameter list - VarArg fvarargs; // function varargs - uint wildmatch = 0; - size_t inferStart = 0; - - Loc instLoc = ti.loc; - Objects* tiargs = ti.tiargs; - auto dedargs = new Objects(parameters.length); - Objects* dedtypes = &ti.tdtypes; // for T:T*, the dedargs is the T*, dedtypes is the T - version (none) { printf("\nTemplateDeclaration.deduceFunctionTemplateMatch() %s\n", toChars()); @@ -1348,8 +1331,10 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol assert(_scope); + auto dedargs = new Objects(parameters.length); dedargs.zero(); + Objects* dedtypes = &ti.tdtypes; // for T:T*, the dedargs is the T*, dedtypes is the T dedtypes.setDim(parameters.length); dedtypes.zero(); @@ -1393,8 +1378,12 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol } } - ntargs = 0; - if (tiargs) + size_t ntargs = 0; // array size of tiargs + size_t inferStart = 0; // index of first parameter to infer + const Loc instLoc = ti.loc; + MATCH matchTiargs = MATCH.exact; + + if (auto tiargs = ti.tiargs) { // Set initial template arguments ntargs = tiargs.length; @@ -1460,9 +1449,9 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol } } - fparameters = fd.getParameterList(); - nfparams = fparameters.length; // number of function parameters - nfargs = argumentList.length; // number of function arguments + ParameterList fparameters = fd.getParameterList(); // function parameter list + const nfparams = fparameters.length; // number of function parameters + const nfargs = argumentList.length; // number of function arguments if (argumentList.hasNames) return matcherror(); // TODO: resolve named args Expressions* fargs = argumentList.arguments; // TODO: resolve named args @@ -1473,6 +1462,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol * void foo(T, A...)(T t, A a); * void main() { foo(1,2,3); } */ + size_t fptupindex = IDX_NOTFOUND; if (tp) // if variadic { // TemplateTupleParameter always makes most lesser matching. @@ -1515,6 +1505,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol } } + MATCH match = MATCH.exact; if (toParent().isModule()) tthis = null; if (tthis) @@ -1579,6 +1570,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol //printf("\ttp = %p, fptupindex = %d, found = %d, declaredTuple = %s\n", tp, fptupindex, fptupindex != IDX_NOTFOUND, declaredTuple ? declaredTuple.toChars() : NULL); size_t argi = 0; size_t nfargs2 = nfargs; // nfargs + supplied defaultArgs + uint inoutMatch = 0; // for debugging only for (size_t parami = 0; parami < nfparams; parami++) { Parameter fparam = fparameters[parami]; @@ -1643,7 +1635,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol MATCH m; if (ubyte wm = deduceWildHelper(farg.type, &tt, tid)) { - wildmatch |= wm; + inoutMatch |= wm; m = MATCH.constant; } else @@ -1896,10 +1888,10 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol if (fparameters.varargs == VarArg.typesafe && parami + 1 == nfparams && argi + 1 < nfargs) goto Lvarargs; - uint wm = 0; - MATCH m = deduceType(oarg, paramscope, prmtype, parameters, dedtypes, &wm, inferStart); - //printf("\tL%d deduceType m = %d, wm = x%x, wildmatch = x%x\n", __LINE__, m, wm, wildmatch); - wildmatch |= wm; + uint im = 0; + MATCH m = deduceType(oarg, paramscope, prmtype, parameters, dedtypes, &im, inferStart); + //printf("\tL%d deduceType m = %d, im = x%x, inoutMatch = x%x\n", __LINE__, m, im, inoutMatch); + inoutMatch |= im; /* If no match, see if the argument can be matched by using * implicit conversions. @@ -2087,7 +2079,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol { uint wm = 0; m = deduceType(arg, paramscope, ta.next, parameters, dedtypes, &wm, inferStart); - wildmatch |= wm; + inoutMatch |= wm; } if (m == MATCH.nomatch) return nomatch(); diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d index f00b8dba86c..b9bbad0a7a4 100644 --- a/gcc/d/dmd/dtoh.d +++ b/gcc/d/dmd/dtoh.d @@ -2450,7 +2450,7 @@ public: { debug (Debug_DtoH) mixin(traceVisit!e); - // Valid in most cases, others should be overriden below + // Valid in most cases, others should be overridden below // to use the appropriate operators (:: and ->) buf.writestring(e.toString()); } diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d index c0dd17f2ea6..efd6bea6821 100644 --- a/gcc/d/dmd/escape.d +++ b/gcc/d/dmd/escape.d @@ -93,22 +93,7 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf, bool isMutable; // true if reference to mutable } - /* Store escapeBy as static data escapeByStorage so we can keep reusing the same - * arrays rather than reallocating them. - */ - __gshared EscapeBy[] escapeByStorage; - auto escapeBy = escapeByStorage; - if (escapeBy.length < len) - { - auto newPtr = cast(EscapeBy*)mem.xrealloc(escapeBy.ptr, len * EscapeBy.sizeof); - // Clear the new section - memset(newPtr + escapeBy.length, 0, (len - escapeBy.length) * EscapeBy.sizeof); - escapeBy = newPtr[0 .. len]; - escapeByStorage = escapeBy; - } - else - escapeBy = escapeBy[0 .. len]; - + auto escapeBy = new EscapeBy[len]; const paramLength = tf.parameterList.length; // Fill in escapeBy[] with arguments[], ethis, and outerVars[] @@ -181,7 +166,7 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf, if (!(eb.isMutable || eb2.isMutable)) return; - if (!tf.islive && !(global.params.useDIP1000 == FeatureState.enabled && sc.func.setUnsafe())) + if (!tf.islive && !(global.params.useDIP1000 == FeatureState.enabled && sc.func && sc.func.setUnsafe())) return; if (!gag) @@ -228,13 +213,6 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf, escape(i, eb, false); } - /* Reset the arrays in escapeBy[] so we can reuse them next time through - */ - foreach (ref eb; escapeBy) - { - eb.er.reset(); - } - return errors; } @@ -387,8 +365,9 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId, (!fdc && parId) ? (desc ~ " `%s` assigned to non-scope parameter `%s`") : (desc ~ " `%s` assigned to non-scope anonymous parameter"); - auto param = isThis ? v : (parId ? parId : fdc); - if (sc.setUnsafeDIP1000(gag, arg.loc, msg, v, param, fdc)) + if (isThis ? + sc.setUnsafeDIP1000(gag, arg.loc, msg, arg, fdc.toParent2(), fdc) : + sc.setUnsafeDIP1000(gag, arg.loc, msg, v, parId ? parId : fdc, fdc)) { result = true; printScopeFailure(previewSupplementalFunc(sc.isDeprecated(), global.params.useDIP1000), vPar, 10); @@ -508,7 +487,7 @@ bool checkParamArgumentReturn(Scope* sc, Expression firstArg, Expression arg, Pa const byRef = param.isReference() && !(param.storageClass & STC.scope_) && !(param.storageClass & STC.returnScope); // fixme: it's possible to infer returnScope without scope with vaIsFirstRef - scope e = new AssignExp(arg.loc, firstArg, arg); + auto e = new AssignExp(arg.loc, firstArg, arg); return checkAssignEscape(sc, e, gag, byRef); } @@ -2487,6 +2466,9 @@ bool isReferenceToMutable(Type t) } break; + case Tnull: + return false; + default: assert(0); } diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d index 473efb8c99a..35f11afdc93 100644 --- a/gcc/d/dmd/expression.d +++ b/gcc/d/dmd/expression.d @@ -1242,7 +1242,7 @@ extern (C++) abstract class Expression : ASTNode if (!f.isDtorDeclaration()) errorSupplementalInferredAttr(f, /*max depth*/ 10, /*deprecation*/ false, STC.pure_); - checkOverridenDtor(sc, f, dd => dd.type.toTypeFunction().purity != PURE.impure, "impure"); + checkOverriddenDtor(sc, f, dd => dd.type.toTypeFunction().purity != PURE.impure, "impure"); return true; } return false; @@ -1261,7 +1261,7 @@ extern (C++) abstract class Expression : ASTNode * check = current check (e.g. whether it's pure) * checkName = the kind of check (e.g. `"pure"`) */ - extern (D) final void checkOverridenDtor(Scope* sc, FuncDeclaration f, + extern (D) final void checkOverriddenDtor(Scope* sc, FuncDeclaration f, scope bool function(DtorDeclaration) check, const string checkName ) { auto dd = f.isDtorDeclaration(); @@ -1314,7 +1314,7 @@ extern (C++) abstract class Expression : ASTNode field.loc.errorSupplemental(" - %s %s", field.type.toChars(), field.toChars()); if (fieldSd.dtor.isGenerated()) - checkOverridenDtor(sc, fieldSd.dtor, check, checkName); + checkOverriddenDtor(sc, fieldSd.dtor, check, checkName); else fieldSd.dtor.loc.errorSupplemental(" %.*s `%s.~this` is declared here", cast(int) checkName.length, checkName.ptr, fieldSd.toChars()); @@ -1505,7 +1505,7 @@ extern (C++) abstract class Expression : ASTNode errorSupplementalInferredAttr(f, /*max depth*/ 10, /*deprecation*/ false, STC.safe); .errorSupplemental(f.loc, "`%s` is declared here", prettyChars); - checkOverridenDtor(sc, f, dd => dd.type.toTypeFunction().trust > TRUST.system, "@system"); + checkOverriddenDtor(sc, f, dd => dd.type.toTypeFunction().trust > TRUST.system, "@system"); return true; } @@ -1569,7 +1569,7 @@ extern (C++) abstract class Expression : ASTNode f.errorSupplementalInferredAttr(/*max depth*/ 10, /*deprecation*/ false, STC.nogc); } - checkOverridenDtor(sc, f, dd => dd.type.toTypeFunction().isnogc, "non-@nogc"); + checkOverriddenDtor(sc, f, dd => dd.type.toTypeFunction().isnogc, "non-@nogc"); return true; } @@ -4512,7 +4512,7 @@ extern (C++) abstract class BinExp : Expression Type t2 = e2.type; // T opAssign floating yields a floating. Prevent truncating conversions (float to int). - // See issue 3841. + // See https://issues.dlang.org/show_bug.cgi?id=3841. // Should we also prevent double to float (type.isfloating() && type.size() < t2.size()) ? if (op == EXP.addAssign || op == EXP.minAssign || op == EXP.mulAssign || op == EXP.divAssign || op == EXP.modAssign || @@ -7425,23 +7425,20 @@ extern(D) Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag } /** - * Verify if the given identifier is any of - * _d_array{ctor,setctor,setassign,assign_l, assign_r}. + * Verify if the given identifier is _d_array{,set}ctor. * * Params: * id = the identifier to verify * * Returns: - * `true` if the identifier corresponds to a construction of assignement - * runtime hook, `false` otherwise. + * `true` if the identifier corresponds to a construction runtime hook, + * `false` otherwise. */ -bool isArrayConstructionOrAssign(const Identifier id) +bool isArrayConstruction(const Identifier id) { import dmd.id : Id; - return id == Id._d_arrayctor || id == Id._d_arraysetctor || - id == Id._d_arrayassign_l || id == Id._d_arrayassign_r || - id == Id._d_arraysetassign; + return id == Id._d_arrayctor || id == Id._d_arraysetctor; } /****************************** diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index 8ac8866a85b..be597dfa90f 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -386,34 +386,6 @@ Expression checkNoreturnVarAccess(Expression exp) return result; } -/****************************** - * Check the tail CallExp is really property function call. - * Bugs: - * This doesn't appear to do anything. - */ -private bool checkPropertyCall(Expression e) -{ - e = lastComma(e); - - if (auto ce = e.isCallExp()) - { - if (ce.f) - { - auto tf = ce.f.type.isTypeFunction(); - /* If a forward reference to ce.f, try to resolve it - */ - if (!tf.deco && ce.f.semanticRun < PASS.semanticdone) - { - ce.f.dsymbolSemantic(null); - tf = ce.f.type.isTypeFunction(); - } - } - else if (!ce.e1.type.isFunction_Delegate_PtrToFunction()) - assert(0); - } - return false; -} - /****************************** * Find symbol in accordance with the UFCS name look up rule */ @@ -489,6 +461,15 @@ private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident) if (auto dti = ue.isDotTemplateInstanceExp()) { + // https://issues.dlang.org/show_bug.cgi?id=23968 + // Typically, deprecated alias declarations are caught + // when `TemplateInstance.findTempDecl` is called, + // however, in this case the tempdecl field is updated + // therefore `findTempDecl` will return immediately + // and not get the chance to issue the deprecation. + if (s.isAliasDeclaration()) + s.checkDeprecated(ue.loc, sc); + auto ti = new TemplateInstance(loc, s.ident, dti.ti.tiargs); if (!ti.updateTempDecl(sc, s)) return ErrorExp.get(); @@ -717,7 +698,6 @@ private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2 } else if (ex && !e) { - checkPropertyCall(ex); ex = new AssignExp(loc, ex, e2); return ex.expressionSemantic(sc); } @@ -726,7 +706,6 @@ private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2 // strict setter prints errors if fails e = e.expressionSemantic(sc); } - checkPropertyCall(e); return e; } else @@ -736,9 +715,13 @@ private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2 auto arguments = new Expressions(1); (*arguments)[0] = eleft; e = new CallExp(loc, e, arguments); + + // https://issues.dlang.org/show_bug.cgi?id=24017 + if (sc.flags & SCOPE.debug_) + e.isCallExp().inDebugStatement = true; + e = e.expressionSemantic(sc); - checkPropertyCall(e); - return e.expressionSemantic(sc); + return e; } } @@ -1189,6 +1172,13 @@ L1: */ private bool haveSameThis(FuncDeclaration outerFunc, FuncDeclaration calledFunc) { + // https://issues.dlang.org/show_bug.cgi?id=24013 + // traits(getOverloads) inserts an alias to select the overload. + // When searching for the right this we need to use the aliased + // overload/function, not the alias. + outerFunc = outerFunc.toAliasFunc(); + calledFunc = calledFunc.toAliasFunc(); + auto thisAd = outerFunc.isMemberLocal(); if (!thisAd) return false; @@ -1386,15 +1376,6 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = { if (fd.errors) return ErrorExp.get(); - if (!checkSymbolAccess(sc, fd)) - { - // @@@DEPRECATED_2.105@@@ - // When turning into error, uncomment the return statement - TypeFunction tf = fd.type.isTypeFunction(); - deprecation(loc, "function `%s` of type `%s` is not accessible from module `%s`", - fd.toPrettyChars(), tf.toChars, sc._module.toChars); - //return ErrorExp.get(); - } assert(fd.type.ty == Tfunction); Expression e = new CallExp(loc, e1, e2); return e.expressionSemantic(sc); @@ -1409,14 +1390,6 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = TypeFunction tf = fd.type.isTypeFunction(); if (!e2 || tf.isref) { - if (!checkSymbolAccess(sc, fd)) - { - // @@@DEPRECATED_2.105@@@ - // When turning into error, uncomment the return statement - deprecation(loc, "function `%s` of type `%s` is not accessible from module `%s`", - fd.toPrettyChars(), tf.toChars, sc._module.toChars); - //return ErrorExp.get(); - } Expression e = new CallExp(loc, e1); if (e2) { @@ -3404,7 +3377,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (ve && ve.var && exp.parens && !ve.var.isStatic() && !(sc.stc & STC.static_) && sc.func && sc.func.needThis && ve.var.isMember2()) { - // printf("apply fix for issue 9490: add `this.` to `%s`...\n", e.toChars()); + // printf("apply fix for bugzilla issue 9490: add `this.` to `%s`...\n", e.toChars()); e = new DotVarExp(exp.loc, new ThisExp(exp.loc), ve.var, false); } //printf("e = %s %s\n", Token.toChars(e.op), e.toChars()); @@ -4092,9 +4065,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (arg.op == EXP.error) return setError(); arg = arg.optimize(WANTvalue); - if (arg.op == EXP.int64 && cast(sinteger_t)arg.toInteger() < 0) + if (arg.op == EXP.int64 && (target.isLP64 ? + cast(sinteger_t)arg.toInteger() : cast(int)arg.toInteger()) < 0) { - exp.error("negative array index `%s`", arg.toChars()); + exp.error("negative array dimension `%s`", (*exp.arguments)[i].toChars()); return setError(); } (*exp.arguments)[i] = arg; @@ -5024,7 +4998,21 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (!exp.ignoreAttributes) checkFunctionAttributes(exp, sc, exp.f); - checkAccess(exp.loc, sc, ue.e1, exp.f); + + // Cut-down version of checkAccess() that doesn't use the "most visible" version of exp.f. + // We've already selected an overload here. + const parent = exp.f.toParent(); + if (parent && parent.isTemplateInstance()) + { + // already a deprecation + } + else if (!checkSymbolAccess(sc, exp.f)) + { + exp.error("%s `%s` of type `%s` is not accessible from module `%s`", + exp.f.kind(), exp.f.toPrettyChars(), exp.f.type.toChars(), sc._module.toChars); + return setError(); + } + if (!exp.f.needThis()) { exp.e1 = Expression.combine(ue.e1, new VarExp(exp.loc, exp.f, false)); @@ -7828,7 +7816,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (exp.to.ty == Ttuple) { - exp.error("cannot cast `%s` of type `%s` to tuple type `%s`", exp.e1.toChars(), exp.e1.type.toChars(), exp.to.toChars()); + exp.error("cannot cast `%s` of type `%s` to type sequence `%s`", exp.e1.toChars(), exp.e1.type.toChars(), exp.to.toChars()); return setError(); } @@ -8174,7 +8162,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } if (!exp.lwr || !exp.upr) { - exp.error("need upper and lower bound to slice tuple"); + exp.error("need upper and lower bound to slice a sequence"); return setError(); } } @@ -9219,7 +9207,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor Expression e = null; if (dim != tup2.exps.length) { - exp.error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.length); + exp.error("mismatched sequence lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.length); return setError(); } if (dim == 0) @@ -10363,6 +10351,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (global.params.verbose) message("lowered %s =>\n %s", ae.toChars(), res.toChars()); + res = new LoweredAssignExp(ae, res); + res.type = ae.type; + return res; } diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d index a159c2f1561..62e0d49fdd5 100644 --- a/gcc/d/dmd/hdrgen.d +++ b/gcc/d/dmd/hdrgen.d @@ -927,7 +927,7 @@ public: } if (d.decl.length == 0 || (hgs.hdrgen && d.decl.length == 1 && (*d.decl)[0].isUnitTestDeclaration())) { - // hack for bugzilla 8081 + // hack for https://issues.dlang.org/show_bug.cgi?id=8081 if (hasSTC) buf.writeByte(' '); buf.writestring("{}"); } @@ -2217,13 +2217,13 @@ private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg { buf.writeByte('('); e.e0.expressionPrettyPrint(buf, hgs); - buf.writestring(", tuple("); + buf.writestring(", AliasSeq!("); argsToBuffer(e.exps, buf, hgs); buf.writestring("))"); } else { - buf.writestring("tuple("); + buf.writestring("AliasSeq!("); argsToBuffer(e.exps, buf, hgs); buf.writeByte(')'); } @@ -4141,7 +4141,7 @@ string EXPtoString(EXP op) EXP.delegatePointer : "delegateptr", EXP.delegateFunctionPointer : "delegatefuncptr", EXP.remove : "remove", - EXP.tuple : "tuple", + EXP.tuple : "sequence", EXP.traits : "__traits", EXP.overloadSet : "__overloadset", EXP.void_ : "void", diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d index ca770bd77b6..ee288d1e474 100644 --- a/gcc/d/dmd/initsem.d +++ b/gcc/d/dmd/initsem.d @@ -582,7 +582,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ Initializer visitC(CInitializer ci) { - //printf("CInitializer::semantic() (%s) %s\n", t.toChars(), ci.toChars()); + //printf("CInitializer::semantic() tx: %s t: %s ci: %s\n", (tx ? tx.toChars() : "".ptr), t.toChars(), ci.toChars()); /* Rewrite CInitializer into ExpInitializer, ArrayInitializer, or StructInitializer */ t = t.toBasetype(); @@ -770,7 +770,6 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ return err(); } const nfields = sd.fields.length; - size_t fieldi = 0; for (size_t index = 0; index < ci.initializerList.length; ) @@ -807,6 +806,12 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ { if (fieldi == nfields) break; + if (index == 0 && ci.initializerList.length == 1 && di.initializer.isCInitializer()) + { + ci = di.initializer.isCInitializer(); + continue; + } + VarDeclaration field; while (1) // skip field if it overlaps with previously seen fields { @@ -954,10 +959,13 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ return initializerSemantic(ai, sc, tx, needInterpret); } else if (ExpInitializer ei = isBraceExpression()) + { return visitExp(ei); + } else { - assert(0); + error(ci.loc, "unrecognized C initializer `%s`", ci.toChars()); + return err(); } } diff --git a/gcc/d/dmd/inline.d b/gcc/d/dmd/inline.d index 8e63122f4cb..afab8315f92 100644 --- a/gcc/d/dmd/inline.d +++ b/gcc/d/dmd/inline.d @@ -21,8 +21,8 @@ import dmd.expression; * Perform the "inline copying" of a default argument for a function parameter. * * Todo: - * The hack for bugzilla 4820 case is still questionable. Perhaps would have to - * handle a delegate expression with 'null' context properly in front-end. + * The hack for https://issues.dlang.org/show_bug.cgi?id=4820 case is still questionable. + * Perhaps would have to handle a delegate expression with 'null' context properly in front-end. */ public Expression inlineCopy(Expression e, Scope* sc) { diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d index a878cc9523d..add1ce68468 100644 --- a/gcc/d/dmd/lexer.d +++ b/gcc/d/dmd/lexer.d @@ -2205,7 +2205,7 @@ class Lexer p++; if ((flags & f) && !err) { - error("unrecognized token"); + error("repeated integer suffix `%c`", p[-1]); err = true; } flags = cast(FLAGS)(flags | f); diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d index cb3e6cddd20..7ecd4023ee1 100644 --- a/gcc/d/dmd/mtype.d +++ b/gcc/d/dmd/mtype.d @@ -2054,7 +2054,7 @@ extern (C++) abstract class Type : ASTNode return Type.terror; auto t = fd.type.nextOf(); - if (!t) // issue 14185 + if (!t) // https://issues.dlang.org/show_bug.cgi?id=14185 return Type.terror; t = t.substWildTo(mod == 0 ? MODFlags.mutable : mod); return t; @@ -4597,10 +4597,9 @@ extern (C++) final class TypeFunction : TypeNext // show qualification when toChars() is the same but types are different // https://issues.dlang.org/show_bug.cgi?id=19948 // when comparing the type with strcmp, we need to drop the qualifier - auto at = arg.type.mutableOf().toChars(); - bool qual = !arg.type.equals(par.type) && strcmp(at, par.type.mutableOf().toChars()) == 0; - if (qual) - at = arg.type.toPrettyChars(true); + bool qual = !arg.type.mutableOf().equals(par.type.mutableOf()) && + strcmp(arg.type.mutableOf().toChars(), par.type.mutableOf().toChars()) == 0; + auto at = qual ? arg.type.toPrettyChars(true) : arg.type.toChars(); OutBuffer buf; // only mention rvalue if it's relevant const rv = !arg.isLvalue() && par.isReference(); @@ -4940,7 +4939,7 @@ extern (C++) final class TypeFunction : TypeNext } if (tb.ty == Ttuple) { - error(loc, "functions cannot return a tuple"); + error(loc, "functions cannot return a sequence (use `std.typecons.Tuple`)"); next = Type.terror; } if (!isref && (tb.ty == Tstruct || tb.ty == Tsarray)) @@ -5105,7 +5104,7 @@ extern (C++) final class TypeDelegate : TypeNext * This is a shell containing a TraitsExp that can be * either resolved to a type or to a symbol. * - * The point is to allow AliasDeclarationY to use `__traits()`, see issue 7804. + * The point is to allow AliasDeclarationY to use `__traits()`, see https://issues.dlang.org/show_bug.cgi?id=7804. */ extern (C++) final class TypeTraits : Type { @@ -6218,7 +6217,7 @@ extern (C++) final class TypeTuple : Type { Expression e = (*exps)[i]; if (e.type.ty == Ttuple) - e.error("cannot form tuple of tuples"); + e.error("cannot form sequence of sequences"); auto arg = new Parameter(STC.undefined_, e.type, null, null, null); (*arguments)[i] = arg; } @@ -6273,7 +6272,7 @@ extern (C++) final class TypeTuple : Type override const(char)* kind() const { - return "tuple"; + return "sequence"; } override TypeTuple syntaxCopy() @@ -7271,7 +7270,7 @@ private extern(D) bool isCopyConstructorCallable (StructDeclaration argStruct, { /* Although a copy constructor may exist, no suitable match was found. * i.e: `inout` constructor creates `const` object, not mutable. - * Fallback to using the original generic error before bugzilla 22202. + * Fallback to using the original generic error before https://issues.dlang.org/show_bug.cgi?id=22202. */ goto Lnocpctor; } diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d index 0e64d9c7c8d..8b42a91f0af 100644 --- a/gcc/d/dmd/opover.d +++ b/gcc/d/dmd/opover.d @@ -416,9 +416,11 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) * op(e1.aliasthis) */ //printf("att una %s e1 = %s\n", EXPtoString(op).ptr, this.e1.type.toChars()); - e.e1 = resolveAliasThis(sc, e.e1, true); - if (e.e1) + if (auto e1 = resolveAliasThis(sc, e.e1, true)) + { + e.e1 = e1; continue; + } break; } break; @@ -1043,7 +1045,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) size_t dim = tup1.exps.length; if (dim != tup2.exps.length) { - e.error("mismatched tuple lengths, `%d` and `%d`", + e.error("mismatched sequence lengths, `%d` and `%d`", cast(int)dim, cast(int)tup2.exps.length); return ErrorExp.get(); } diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d index 335310de65d..f98e7c76bcc 100644 --- a/gcc/d/dmd/optimize.d +++ b/gcc/d/dmd/optimize.d @@ -189,7 +189,7 @@ private Expression fromConstInitializer(int result, Expression e1) { // If it is a comma expression involving a declaration, we mustn't // perform a copy -- we'd get two declarations of the same variable. - // See bugzilla 4465. + // See https://issues.dlang.org/show_bug.cgi?id=4465. if (e.op == EXP.comma && e.isCommaExp().e1.isDeclarationExp()) e = e1; else if (e.type != e1.type && e1.type && e1.type.ty != Tident) diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index b7e07911cb9..eeaef8d7d8b 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -1155,6 +1155,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer case TOK.leftCurly: { + const lcLoc = token.loc; const lookingForElseSave = lookingForElse; lookingForElse = Loc(); @@ -1164,6 +1165,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer { /* { */ error("matching `}` expected, not `%s`", token.toChars()); + eSink.errorSupplemental(lcLoc, "unmatched `{`"); } else nextToken(); @@ -1405,6 +1407,15 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer break; } default: + Token* tk; + if (skipAttributes(&token, &tk) && tk.ptr != token.ptr || + token.value == TOK.static_ || token.value == TOK.extern_) + { + error("`%s` token is not allowed in postfix position", + Token.toChars(token.value)); + nextToken(); + continue; + } return storageClass; } storageClass = appendStorageClass(storageClass, stc); @@ -6006,6 +6017,7 @@ LagainStc: } case TOK.leftCurly: { + const lcLoc = token.loc; const lookingForElseSave = lookingForElse; lookingForElse = Loc.initial; @@ -6028,7 +6040,14 @@ LagainStc: s = new AST.CompoundStatement(loc, statements); if (flags & (ParseStatementFlags.scope_ | ParseStatementFlags.curlyScope)) s = new AST.ScopeStatement(loc, s, token.loc); - check(TOK.rightCurly, "compound statement"); + if (token.value != TOK.rightCurly) + { + error(token.loc, "matching `}` expected following compound statement, not `%s`", + token.toChars()); + eSink.errorSupplemental(lcLoc, "unmatched `{`"); + } + else + nextToken(); lookingForElse = lookingForElseSave; break; } diff --git a/gcc/d/dmd/root/array.d b/gcc/d/dmd/root/array.d index d1c61be7344..f36ddb4f29e 100644 --- a/gcc/d/dmd/root/array.d +++ b/gcc/d/dmd/root/array.d @@ -251,6 +251,18 @@ public: length++; } + /// Insert 'count' copies of 'value' at 'index' position + void insert(size_t index, size_t count, T value) pure nothrow + { + if (count == 0) + return; + reserve(count); + if (length != index) + memmove(data.ptr + index + count, data.ptr + index, (length - index) * T.sizeof); + data[index .. index + count] = value; + length += count; + } + void setDim(size_t newdim) pure nothrow { if (length < newdim) @@ -458,6 +470,12 @@ unittest arrayA.insert(0, [7, 8]); arrayA.insert(arrayA.length, [0, 9]); assert(arrayA[] == [7, 8, 5, 1, 2, 6, 0, 9]); + arrayA.insert(4, 3, 8); + assert(arrayA[] == [7, 8, 5, 1, 8, 8, 8, 2, 6, 0, 9]); + arrayA.insert(0, 3, 8); + assert(arrayA[] == [8, 8, 8, 7, 8, 5, 1, 8, 8, 8, 2, 6, 0, 9]); + arrayA.insert(arrayA.length, 3, 8); + assert(arrayA[] == [8, 8, 8, 7, 8, 5, 1, 8, 8, 8, 2, 6, 0, 9, 8, 8, 8]); } /** diff --git a/gcc/d/dmd/semantic2.d b/gcc/d/dmd/semantic2.d index c40e72c0862..3cbf14f2b8f 100644 --- a/gcc/d/dmd/semantic2.d +++ b/gcc/d/dmd/semantic2.d @@ -657,6 +657,13 @@ private extern(C++) final class Semantic2Visitor : Visitor { foreach (base; cd.interfaces) { + // https://issues.dlang.org/show_bug.cgi?id=22729 + // interfaces that have errors or that + // inherit from interfaces that have errors + // might have an uninitialized vtable + if (!base.sym.vtbl.length) + continue; + // first entry is ClassInfo reference auto methods = base.sym.vtbl[base.sym.vtblOffset .. $]; diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d index 33c2f02249e..e4ca22a98b5 100644 --- a/gcc/d/dmd/semantic3.d +++ b/gcc/d/dmd/semantic3.d @@ -1367,6 +1367,8 @@ private extern(C++) final class Semantic3Visitor : Visitor if (isCppNonMappableType(f.next.toBasetype())) { funcdecl.error("cannot return type `%s` because its linkage is `extern(C++)`", f.next.toChars()); + if (f.next.isTypeDArray()) + errorSupplemental(funcdecl.loc, "slices are specific to D and do not have a counterpart representation in C++", f.next.toChars()); funcdecl.errors = true; } foreach (i, param; f.parameterList) @@ -1605,7 +1607,7 @@ private struct FuncDeclSem3 sc = s; } - /* Checks that the overriden functions (if any) have in contracts if + /* Checks that the overridden functions (if any) have in contracts if * funcdecl has an in contract. */ void checkInContractOverrides() diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d index f0454163224..2def2539597 100644 --- a/gcc/d/dmd/statementsem.d +++ b/gcc/d/dmd/statementsem.d @@ -257,8 +257,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) continue; } - Statements* flt = s.flatten(sc); - if (flt) + if (auto flt = s.flatten(sc)) { cs.statements.remove(i); cs.statements.insert(i, flt); @@ -279,6 +278,24 @@ Statement statementSemanticVisit(Statement s, Scope* sc) ++i; continue; // look for errors in rest of statements } + + // expand tuple variables in order to attach destruction/exception logic + if (auto es = s.isExpStatement()) + { + if (es.exp && es.exp.isDeclarationExp()) + { + auto de = es.exp.isDeclarationExp(); + auto vd = de.declaration.isVarDeclaration(); + if (vd && vd.aliasTuple && vd.aliasTuple.objects.length) + { + auto j = i; + cs.statements.insert(i, vd.aliasTuple.objects.length - 1, null); + vd.aliasTuple.foreachVar((v) { (*cs.statements)[j++] = toStatement(v); }); + s = (*cs.statements)[i]; + } + } + } + Statement sentry; Statement sexception; Statement sfinally; @@ -384,12 +401,11 @@ Statement statementSemanticVisit(Statement s, Scope* sc) /* Flatten them in place */ - void flatten(Statements* statements) + void flattenStatements(ref Statements statements) { for (size_t i = 0; i < statements.length;) { - Statement s = (*statements)[i]; - if (s) + if (auto s = statements[i]) { if (auto flt = s.flatten(sc)) { @@ -406,7 +422,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) * 'semantic' may return another CompoundStatement * (eg. CaseRangeStatement), so flatten it here. */ - flatten(cs.statements); + flattenStatements(*cs.statements); foreach (s; *cs.statements) { @@ -4298,7 +4314,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState const bool skipCheck = isStatic && needExpansion; if (!skipCheck && (dim < 1 || dim > 2)) { - fs.error("only one (value) or two (key,value) arguments for tuple `foreach`"); + fs.error("only one (value) or two (key,value) arguments allowed for sequence `foreach`"); return returnEarly(); } diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d index 53c8fb08b50..caebf1cee25 100644 --- a/gcc/d/dmd/traits.d +++ b/gcc/d/dmd/traits.d @@ -1556,7 +1556,9 @@ Expression semanticTraits(TraitsExp e, Scope* sc) if (auto imp = s.isImport()) { // https://issues.dlang.org/show_bug.cgi?id=9692 - s = imp.mod; + // https://issues.dlang.org/show_bug.cgi?id=20008 + if (imp.pkg) + s = imp.pkg; } // https://issues.dlang.org/show_bug.cgi?id=16044 @@ -2116,7 +2118,7 @@ private bool isSame(RootObject o1, RootObject o2, Scope* sc) return true; } - // issue 12001, allow isSame, , + // https://issues.dlang.org/show_bug.cgi?id=12001, allow isSame, , Type t1 = isType(o1); Type t2 = isType(o2); if (t1 && t2 && t1.equals(t2)) diff --git a/gcc/d/dmd/transitivevisitor.d b/gcc/d/dmd/transitivevisitor.d index a82a268eb66..376c12fa808 100644 --- a/gcc/d/dmd/transitivevisitor.d +++ b/gcc/d/dmd/transitivevisitor.d @@ -162,14 +162,14 @@ package mixin template ParseVisitMethods(AST) } override void visit(AST.StaticForeachStatement s) - { + { // printf("Visiting StaticForeachStatement\n"); - if (s.sfe.aggrfe) + if (s.sfe.aggrfe) s.sfe.aggrfe.accept(this); - if (s.sfe.rangefe) + if (s.sfe.rangefe) s.sfe.rangefe.accept(this); - } + } override void visit(AST.IfStatement s) { diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index 09eef83ba08..d0923953663 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -121,7 +121,7 @@ private void resolveTupleIndex(const ref Loc loc, Scope* sc, Dsymbol s, out Expr const(uinteger_t) d = eindex.toUInteger(); if (d >= tup.objects.length) { - .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong)tup.objects.length); + .error(loc, "sequence index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong)tup.objects.length); pt = Type.terror; return; } @@ -525,7 +525,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) uinteger_t d = mtype.dim.toUInteger(); if (d >= tup.objects.length) { - .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tup.objects.length); + .error(loc, "sequence index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tup.objects.length); return error(); } @@ -621,7 +621,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) uinteger_t d = mtype.dim.toUInteger(); if (d >= tt.arguments.length) { - .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tt.arguments.length); + .error(loc, "sequence index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tt.arguments.length); return error(); } Type telem = (*tt.arguments)[cast(size_t)d].type; @@ -1684,7 +1684,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) Type tbn = tn.toBasetype(); if (tbn.ty != Ttuple) { - .error(loc, "can only slice tuple types, not `%s`", tbn.toChars()); + .error(loc, "can only slice type sequences, not `%s`", tbn.toChars()); return error(); } TypeTuple tt = cast(TypeTuple)tbn; @@ -2436,7 +2436,7 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden } else { - error(loc, "no property `%s` for tuple `%s`", ident.toChars(), mt.toChars()); + error(loc, "no property `%s` for sequence `%s`", ident.toChars(), mt.toChars()); e = ErrorExp.get(); } return e; @@ -2563,7 +2563,7 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type const d = mt.dim.toUInteger(); if (d >= tup.objects.length) { - error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong) tup.objects.length); + error(loc, "sequence index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong) tup.objects.length); return returnError(); } diff --git a/gcc/testsuite/gdc.test/compilable/b20938.d b/gcc/testsuite/gdc.test/compilable/b20938.d index ba3565ae8f9..b3aa46c2435 100644 --- a/gcc/testsuite/gdc.test/compilable/b20938.d +++ b/gcc/testsuite/gdc.test/compilable/b20938.d @@ -1,4 +1,5 @@ -// issue 20938 - Cannot create const arrays mixing immutable and mutable structs with indirections +// https://issues.dlang.org/show_bug.cgi?id=20938 +// Cannot create const arrays mixing immutable and mutable structs with indirections struct S { int[] a; } enum A { a } enum B { b } diff --git a/gcc/testsuite/gdc.test/compilable/commontype.d b/gcc/testsuite/gdc.test/compilable/commontype.d index abe956c8094..a980ace2177 100644 --- a/gcc/testsuite/gdc.test/compilable/commontype.d +++ b/gcc/testsuite/gdc.test/compilable/commontype.d @@ -117,18 +117,18 @@ static assert(is( X!( Ei, Ei ) == Ei )); static assert(is( X!( Ei, const(Ei) ) == const(Ei) )); static assert(is( X!( Ei, immutable(Ei) ) == const(Ei) )); static assert(is( X!( Eb, Eb ) == Eb )); -static assert(is( X!( Eb, const(Eb) ) == int )); -static assert(is( X!( Eb, immutable(Eb) ) == int )); +static assert(is( X!( Eb, const(Eb) ) == const(Eb) )); +static assert(is( X!( Eb, immutable(Eb) ) == const(Eb) )); static assert(is( X!( Ei, Eb ) == int )); static assert(is( X!( Ei, const(Eb) ) == int )); static assert(is( X!( Ei, immutable(Eb) ) == int )); static assert(is( X!( Ec, Ec ) == Ec )); -static assert(is( X!( Ec, const(Ec) ) == const(char) )); -static assert(is( X!( Ec, immutable(Ec) ) == const(char) )); +static assert(is( X!( Ec, const(Ec) ) == const(Ec) )); +static assert(is( X!( Ec, immutable(Ec) ) == const(Ec) )); static assert(is( X!( Ew, Ew ) == Ew )); -static assert(is( X!( Ew, const(Ew) ) == const(wchar) )); -static assert(is( X!( Ew, immutable(Ew) ) == const(wchar) )); +static assert(is( X!( Ew, const(Ew) ) == const(Ew) )); +static assert(is( X!( Ew, immutable(Ew) ) == const(Ew) )); static assert(is( X!( Ew, Ec ) == dchar )); static assert(is( X!( Ew, const(Ec) ) == dchar )); static assert(is( X!( Ew, immutable(Ec) ) == dchar )); diff --git a/gcc/testsuite/gdc.test/compilable/imports/pkg20008/package.d b/gcc/testsuite/gdc.test/compilable/imports/pkg20008/package.d new file mode 100644 index 00000000000..ecd1568ad34 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/pkg20008/package.d @@ -0,0 +1,9 @@ +module pkg20008; + +import pkg20008.submod; + +enum T2 { y } +enum T3 { z } + +static assert([__traits(allMembers, pkg20008)] == ["object", "pkg20008", "T2", "T3"]); +static assert([__traits(allMembers, pkg20008.submod)] == ["object", "T1"]); diff --git a/gcc/testsuite/gdc.test/compilable/imports/pkg20008/submod.d b/gcc/testsuite/gdc.test/compilable/imports/pkg20008/submod.d new file mode 100644 index 00000000000..a38a5e88cfb --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/pkg20008/submod.d @@ -0,0 +1,2 @@ +module pkg20008.submod; +enum T1 { x } diff --git a/gcc/testsuite/gdc.test/compilable/imports/pkg20008/subpkg/package.d b/gcc/testsuite/gdc.test/compilable/imports/pkg20008/subpkg/package.d new file mode 100644 index 00000000000..cf3e4dfb422 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/pkg20008/subpkg/package.d @@ -0,0 +1,7 @@ +module pkg20008.subpkg; + +import pkg20008.subpkg.subsubmod; + +enum T9 { x } + +static assert([__traits(allMembers, pkg20008.subpkg)] == ["object", "pkg20008", "T9"]); diff --git a/gcc/testsuite/gdc.test/compilable/imports/pkg20008/subpkg/subsubmod.d b/gcc/testsuite/gdc.test/compilable/imports/pkg20008/subpkg/subsubmod.d new file mode 100644 index 00000000000..69a416a021d --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/pkg20008/subpkg/subsubmod.d @@ -0,0 +1,9 @@ +module pkg20008.subpkg.subsubmod; + +import pkg20008.subpkg; +import pkg20008.subpkg.subsubmod; + +enum T8 { x } + +static assert([__traits(allMembers, pkg20008.subpkg)] == ["object", "pkg20008", "T9"]); +static assert([__traits(allMembers, pkg20008.subpkg.subsubmod)] == ["object", "pkg20008", "T8"]); diff --git a/gcc/testsuite/gdc.test/compilable/imports/test9692b.d b/gcc/testsuite/gdc.test/compilable/imports/test9692b.d index 25be84b3413..dab7a986aaf 100644 --- a/gcc/testsuite/gdc.test/compilable/imports/test9692b.d +++ b/gcc/testsuite/gdc.test/compilable/imports/test9692b.d @@ -1,2 +1,2 @@ module imports.test9692b; -int j; +int k; diff --git a/gcc/testsuite/gdc.test/compilable/issue24018.d b/gcc/testsuite/gdc.test/compilable/issue24018.d new file mode 100644 index 00000000000..559710c27df --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/issue24018.d @@ -0,0 +1,10 @@ +struct S +{ + @disable this(); +} + +void main() +{ + S[] s; + s = s ~ s; +} diff --git a/gcc/testsuite/gdc.test/compilable/stc_traits.d b/gcc/testsuite/gdc.test/compilable/stc_traits.d index c5c4e5f0ac0..71d17315510 100644 --- a/gcc/testsuite/gdc.test/compilable/stc_traits.d +++ b/gcc/testsuite/gdc.test/compilable/stc_traits.d @@ -2,59 +2,59 @@ /* TEST_OUTPUT: --- -100 tuple() -101 tuple("return", "ref") -102 tuple("ref") -103 tuple() -104 tuple("ref") -105 tuple() -106 tuple() -107 tuple("ref") -108 tuple("ref") -109 tuple("ref") -110 tuple("ref") -111 tuple() -112 tuple("ref") -113 tuple("ref") -114 tuple("ref") -115 tuple("ref") -116 tuple() -117 tuple("ref") -118 tuple("ref") -119 tuple() -120 tuple("ref") -121 tuple() -122 tuple("ref") -123 tuple("in") -124 tuple("in") -m tuple("ref") -m-mixin tuple("ref") -m tuple("ref") -m-mixin tuple("ref") -m tuple("ref") -m-mixin tuple("ref") -m tuple("return", "ref") -m-mixin tuple("return", "ref") -m tuple("ref") -m-mixin tuple("ref") -m tuple("ref") -m-mixin tuple("ref") -m tuple() -m-mixin tuple() -m tuple("ref") -m-mixin tuple("ref") -m tuple("ref") -m-mixin tuple("ref") -m tuple("ref") -m-mixin tuple("ref") -m tuple("ref") -m-mixin tuple("ref") -m tuple("ref") -m-mixin tuple("ref") -m tuple("ref") -m-mixin tuple("ref") -m tuple("in") -m-mixin tuple("in") +100 AliasSeq!() +101 AliasSeq!("return", "ref") +102 AliasSeq!("ref") +103 AliasSeq!() +104 AliasSeq!("ref") +105 AliasSeq!() +106 AliasSeq!() +107 AliasSeq!("ref") +108 AliasSeq!("ref") +109 AliasSeq!("ref") +110 AliasSeq!("ref") +111 AliasSeq!() +112 AliasSeq!("ref") +113 AliasSeq!("ref") +114 AliasSeq!("ref") +115 AliasSeq!("ref") +116 AliasSeq!() +117 AliasSeq!("ref") +118 AliasSeq!("ref") +119 AliasSeq!() +120 AliasSeq!("ref") +121 AliasSeq!() +122 AliasSeq!("ref") +123 AliasSeq!("in") +124 AliasSeq!("in") +m AliasSeq!("ref") +m-mixin AliasSeq!("ref") +m AliasSeq!("ref") +m-mixin AliasSeq!("ref") +m AliasSeq!("ref") +m-mixin AliasSeq!("ref") +m AliasSeq!("return", "ref") +m-mixin AliasSeq!("return", "ref") +m AliasSeq!("ref") +m-mixin AliasSeq!("ref") +m AliasSeq!("ref") +m-mixin AliasSeq!("ref") +m AliasSeq!() +m-mixin AliasSeq!() +m AliasSeq!("ref") +m-mixin AliasSeq!("ref") +m AliasSeq!("ref") +m-mixin AliasSeq!("ref") +m AliasSeq!("ref") +m-mixin AliasSeq!("ref") +m AliasSeq!("ref") +m-mixin AliasSeq!("ref") +m AliasSeq!("ref") +m-mixin AliasSeq!("ref") +m AliasSeq!("ref") +m-mixin AliasSeq!("ref") +m AliasSeq!("in") +m-mixin AliasSeq!("in") --- */ diff --git a/gcc/testsuite/gdc.test/compilable/test13668.d b/gcc/testsuite/gdc.test/compilable/test13668.d index d69c764b91c..2cf758cc98b 100644 --- a/gcc/testsuite/gdc.test/compilable/test13668.d +++ b/gcc/testsuite/gdc.test/compilable/test13668.d @@ -3,7 +3,7 @@ /* TEST_OUTPUT: --- -tuple("id", "toString", "toHash", "opCmp", "opEquals", "Monitor", "factory") +AliasSeq!("id", "toString", "toHash", "opCmp", "opEquals", "Monitor", "factory") genProps --- */ diff --git a/gcc/testsuite/gdc.test/compilable/test16635.d b/gcc/testsuite/gdc.test/compilable/test16635.d index 5f3d0ba9b6c..dcdd35b3bb0 100644 --- a/gcc/testsuite/gdc.test/compilable/test16635.d +++ b/gcc/testsuite/gdc.test/compilable/test16635.d @@ -39,7 +39,7 @@ void test16635_1() Vector2 b = Vector2(3, 4); // this line causes application to run infinitely - // Already fixed. It was issue 16621 + // Already fixed. It was https://issues.dlang.org/show_bug.cgi?id=16621 Vector2 c = a + b; // OK <- this line seg faults without the above line diff --git a/gcc/testsuite/gdc.test/compilable/test17143.d b/gcc/testsuite/gdc.test/compilable/test17143.d index 4ec029572f4..272d65934b8 100644 --- a/gcc/testsuite/gdc.test/compilable/test17143.d +++ b/gcc/testsuite/gdc.test/compilable/test17143.d @@ -13,4 +13,4 @@ Tuple!T tuple(T...)(T args) enum foo = tuple(1, 2).expand; static assert(typeof(foo).stringof == "(int, int)"); -static assert(foo.stringof == "tuple(1, 2)"); +static assert(foo.stringof == "AliasSeq!(1, 2)"); diff --git a/gcc/testsuite/gdc.test/compilable/test17373.d b/gcc/testsuite/gdc.test/compilable/test17373.d index 9a5ee6431a2..1f83f51685d 100644 --- a/gcc/testsuite/gdc.test/compilable/test17373.d +++ b/gcc/testsuite/gdc.test/compilable/test17373.d @@ -28,5 +28,5 @@ interface ConnectionStream : Stream void close(); } -static assert(__traits(getOverloads, ConnectionStream, "connected").stringof == "tuple(connected)"); -static assert(__traits(getOverloads, ConnectionStream, "close").stringof == "tuple(close)"); +static assert(__traits(getOverloads, ConnectionStream, "connected").stringof == "AliasSeq!(connected)"); +static assert(__traits(getOverloads, ConnectionStream, "close").stringof == "AliasSeq!(close)"); diff --git a/gcc/testsuite/gdc.test/compilable/test17545.d b/gcc/testsuite/gdc.test/compilable/test17545.d index 6285418b806..d1ba7cddea1 100644 --- a/gcc/testsuite/gdc.test/compilable/test17545.d +++ b/gcc/testsuite/gdc.test/compilable/test17545.d @@ -1,6 +1,6 @@ /* TEST_OUTPUT: --- -tuple((Attrib)) +AliasSeq!((Attrib)) --- */ diff --git a/gcc/testsuite/gdc.test/compilable/test19728.d b/gcc/testsuite/gdc.test/compilable/test19728.d index 551ac0f6a89..73ed9c4a3d8 100644 --- a/gcc/testsuite/gdc.test/compilable/test19728.d +++ b/gcc/testsuite/gdc.test/compilable/test19728.d @@ -1,13 +1,13 @@ /* TEST_OUTPUT: --- -tuple((A), (B)) -tuple((A), (B), 0) -tuple((A), (B), (A)) -tuple((A), (B), (A), (B)) -tuple((A), (B), (A), (B)) -tuple((A), (B), (A), (B), (A), (B), (A), (B)) -tuple((Attr)) +AliasSeq!((A), (B)) +AliasSeq!((A), (B), 0) +AliasSeq!((A), (B), (A)) +AliasSeq!((A), (B), (A), (B)) +AliasSeq!((A), (B), (A), (B)) +AliasSeq!((A), (B), (A), (B), (A), (B), (A), (B)) +AliasSeq!((Attr)) --- */ diff --git a/gcc/testsuite/gdc.test/compilable/test20008.d b/gcc/testsuite/gdc.test/compilable/test20008.d new file mode 100644 index 00000000000..5a37248c15e --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test20008.d @@ -0,0 +1,6 @@ +/* +REQUIRED_ARGS: -Icompilable/imports -c -o- +EXTRA_FILES: imports/pkg20008/package.d imports/pkg20008/submod.d imports/pkg20008/subpkg/package.d imports/pkg20008/subpkg/subsubmod.d +*/ +import pkg20008; +import pkg20008.subpkg; diff --git a/gcc/testsuite/gdc.test/compilable/test21282.d b/gcc/testsuite/gdc.test/compilable/test21282.d index 761a6a60dd7..276591f6b07 100644 --- a/gcc/testsuite/gdc.test/compilable/test21282.d +++ b/gcc/testsuite/gdc.test/compilable/test21282.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -tuple(func) +AliasSeq!(func) --- */ // https://issues.dlang.org/show_bug.cgi?id=21282 diff --git a/gcc/testsuite/gdc.test/compilable/test21330.d b/gcc/testsuite/gdc.test/compilable/test21330.d index 4abf36717b5..66f9e29a63a 100644 --- a/gcc/testsuite/gdc.test/compilable/test21330.d +++ b/gcc/testsuite/gdc.test/compilable/test21330.d @@ -2,8 +2,8 @@ REQUIRED_ARGS: -unittest TEST_OUTPUT: --- -tuple(__unittest_L14_C5_1, __unittest_L14_C5_2) -tuple(__unittest_L14_C5_2) +AliasSeq!(__unittest_L14_C5_1, __unittest_L14_C5_2) +AliasSeq!(__unittest_L14_C5_2) --- */ // https://issues.dlang.org/show_bug.cgi?id=21330 diff --git a/gcc/testsuite/gdc.test/compilable/test23965.d b/gcc/testsuite/gdc.test/compilable/test23965.d new file mode 100644 index 00000000000..36e4e428a85 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test23965.d @@ -0,0 +1,11 @@ +// https://issues.dlang.org/show_bug.cgi?id=23965 +// REQUIRED_ARGS: -de +deprecated: + +struct S {} + +void fun() +{ + S[] arr; + arr ~= S(); +} diff --git a/gcc/testsuite/gdc.test/compilable/test23978.d b/gcc/testsuite/gdc.test/compilable/test23978.d new file mode 100644 index 00000000000..cc30f728dee --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test23978.d @@ -0,0 +1,30 @@ +// REQUIRED_ARGS: -preview=dip1021 -lowmem +// https://issues.dlang.org/show_bug.cgi?id=23978 + +// Note: this is a memory corruption bug. +// Memory returned by `GC.realloc` retains references to old memory in it, +// mostly because of the smallarray optimization for `Array(T)`. +// If this fails again, it might not be consistent, so try running it multiple times. + +class LUBench { } +void lup(ulong , ulong , int , int = 1) +{ + new LUBench; +} +void lup_3200(ulong iters, ulong flops) +{ + lup(iters, flops, 3200); +} +void raytrace() +{ + struct V + { + float x, y, z; + auto normalize() { } + struct Tid { } + auto spawnLinked() { } + string[] namesByTid; + class MessageBox { } + auto cross() { } + } +} diff --git a/gcc/testsuite/gdc.test/compilable/test23979.d b/gcc/testsuite/gdc.test/compilable/test23979.d new file mode 100644 index 00000000000..f7eb2c554ee --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test23979.d @@ -0,0 +1,17 @@ +// REQUIRED_ARGS: -o- +// https://issues.dlang.org/show_bug.cgi?id=23979 +// Issue 23979 - ICE on failed alias this attempt on pointer expression + +class A {} + +void h() +{ + const auto classPtr = SPtr.init; + assert(!__traits(compiles, *classPtr)); +} + +struct SPtr +{ + A ptr() { return A.init; } + alias ptr this; +} diff --git a/gcc/testsuite/gdc.test/compilable/test23986.d b/gcc/testsuite/gdc.test/compilable/test23986.d new file mode 100644 index 00000000000..6bbf1c2aeaa --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test23986.d @@ -0,0 +1,11 @@ +// REQUIRED_ARGS: -preview=dip1021 -o- +// https://issues.dlang.org/show_bug.cgi?id=23986 +// dip1021 asserts on `typeof(null)` parameter +@safe: + +void f(typeof(null) obj, int* x) {} + +void g() +{ + f(null, null); +} diff --git a/gcc/testsuite/gdc.test/compilable/test24013.d b/gcc/testsuite/gdc.test/compilable/test24013.d new file mode 100644 index 00000000000..132ada61c8e --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test24013.d @@ -0,0 +1,43 @@ +// https://issues.dlang.org/show_bug.cgi?id=24013 + +struct PropDescriptor(T) +{ + void define(T delegate() aGetter, string aName) {} +} + +enum Get; + +mixin template PropertyPublisherImpl() +{ + void collectPublicationsFromPairs(T)() + { + foreach (member; __traits(derivedMembers, T)) + foreach (overload; __traits(getOverloads, T, member)) + { + alias Attributes = __traits(getAttributes, overload); + static if (Attributes.length != 0) + { + auto descriptor = new PropDescriptor!size_t; + auto dg = &overload; + descriptor.define(dg, member); + } + } + } +} + +void main() +{ + class Bar + { + size_t _field; + mixin PropertyPublisherImpl; + this() + { + collectPublicationsFromPairs!Bar; + } + @Get size_t field() + { + return _field; + } + } +} diff --git a/gcc/testsuite/gdc.test/compilable/test24017.d b/gcc/testsuite/gdc.test/compilable/test24017.d new file mode 100644 index 00000000000..0d039781201 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test24017.d @@ -0,0 +1,11 @@ +// https://issues.dlang.org/show_bug.cgi?id=24017 + +// REQUIRED_ARGS: -debug + +void writeln(string) {} + +void main() nothrow +{ + debug writeln("Hello"); + debug "Hello".writeln; +} diff --git a/gcc/testsuite/gdc.test/compilable/test9692.d b/gcc/testsuite/gdc.test/compilable/test9692.d index 57131b8080c..cb5da6a3422 100644 --- a/gcc/testsuite/gdc.test/compilable/test9692.d +++ b/gcc/testsuite/gdc.test/compilable/test9692.d @@ -4,5 +4,5 @@ module test9692; import test9692a; import imports.test9692b; -enum x = [__traits(allMembers, imports.test9692b)]; // ok -enum y = [__traits(allMembers, test9692a)]; // ng: should work +static assert([__traits(allMembers, imports.test9692b)] == ["object", "k"]); // ok +static assert([__traits(allMembers, test9692a)] == ["object", "j"]); // ng: should work diff --git a/gcc/testsuite/gdc.test/compilable/testInference.d b/gcc/testsuite/gdc.test/compilable/testInference.d index 31b10494148..bddbaf42946 100644 --- a/gcc/testsuite/gdc.test/compilable/testInference.d +++ b/gcc/testsuite/gdc.test/compilable/testInference.d @@ -171,9 +171,9 @@ template map7017(fun...) if (fun.length >= 1) auto map7017() { struct Result { - this(int dummy){} // impure member function -> inferred to pure by fixing issue 10329 + this(int dummy){} // impure member function -> inferred to pure by fixing https://issues.dlang.org/show_bug.cgi?id=10329 } - return Result(0); // impure call -> inferred to pure by fixing issue 10329 + return Result(0); // impure call -> inferred to pure by fixing https://issues.dlang.org/show_bug.cgi?id=10329 } } @@ -588,7 +588,7 @@ auto fb10148(T)() static assert(is(typeof(&fc) == void delegate())); fa10148(); } - // [1] this is now inferred to @safe by implementing issue 7511 + // [1] this is now inferred to @safe by implementing https://issues.dlang.org/show_bug.cgi?id=7511 this(S a) {} } diff --git a/gcc/testsuite/gdc.test/fail_compilation/callconst.d b/gcc/testsuite/gdc.test/fail_compilation/callconst.d new file mode 100644 index 00000000000..74c1902b2d4 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/callconst.d @@ -0,0 +1,16 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/callconst.d(13): Error: function `callconst.func(ref X)` is not callable using argument types `(const(X))` +fail_compilation/callconst.d(13): cannot pass argument `x` of type `const(X)` to parameter `ref X` +--- +*/ +struct X {} + +void main() +{ + auto x = const X(); + func(x); +} + +void func(ref X); diff --git a/gcc/testsuite/gdc.test/fail_compilation/casttuple.d b/gcc/testsuite/gdc.test/fail_compilation/casttuple.d index d08de08b553..89e5f3de7ee 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/casttuple.d +++ b/gcc/testsuite/gdc.test/fail_compilation/casttuple.d @@ -1,9 +1,9 @@ /* TEST_OUTPUT: --- -fail_compilation/casttuple.d(104): Error: cannot cast `__tup1_field_0` of type `int` to tuple type `(string)` -fail_compilation/casttuple.d(107): Error: cannot cast `tuple(__tup2_field_0, __tup2_field_1)` of type `(int, int)` to tuple type `(string, string)` -fail_compilation/casttuple.d(111): Error: cannot cast `tuple(foo, 123)` of type `(int, int)` to tuple type `(string, string)` +fail_compilation/casttuple.d(104): Error: cannot cast `__tup1_field_0` of type `int` to type sequence `(string)` +fail_compilation/casttuple.d(107): Error: cannot cast `AliasSeq!(__tup2_field_0, __tup2_field_1)` of type `(int, int)` to type sequence `(string, string)` +fail_compilation/casttuple.d(111): Error: cannot cast `AliasSeq!(foo, 123)` of type `(int, int)` to type sequence `(string, string)` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d b/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d index 8134afb18d2..b3c89b46d2a 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d +++ b/gcc/testsuite/gdc.test/fail_compilation/cppmangle.d @@ -3,7 +3,7 @@ TEST_OUTPUT: --- fail_compilation/cppmangle.d(11): Error: expected valid identifier for C++ namespace but got `` fail_compilation/cppmangle.d(15): Error: expected valid identifier for C++ namespace but got `0num` -fail_compilation/cppmangle.d(19): Error: compile time string constant (or tuple) expected, not `2` +fail_compilation/cppmangle.d(19): Error: compile time string constant (or sequence) expected, not `2` fail_compilation/cppmangle.d(23): Error: expected valid identifier for C++ namespace but got `invalid@namespace` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/dassert.d b/gcc/testsuite/gdc.test/fail_compilation/dassert.d index 8a813177c35..c18a28d2ffb 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/dassert.d +++ b/gcc/testsuite/gdc.test/fail_compilation/dassert.d @@ -2,7 +2,7 @@ REQUIRED_ARGS: -checkaction=context TEST_OUTPUT: --- -fail_compilation/dassert.d(14): Error: expression `tuple(0, 0)` of type `(int, int)` does not have a boolean value +fail_compilation/dassert.d(14): Error: expression `AliasSeq!(0, 0)` of type `(int, int)` does not have a boolean value fail_compilation/dassert.d(21): Error: assignment cannot be used as a condition, perhaps `==` was meant? fail_compilation/dassert.d(29): Error: assignment cannot be used as a condition, perhaps `==` was meant? fail_compilation/dassert.d(40): Error: expression `issue()` of type `void` does not have a boolean value diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag13884.d b/gcc/testsuite/gdc.test/fail_compilation/diag13884.d index fe47c838dd9..14af2c884a9 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag13884.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag13884.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/diag13884.d(14): Error: functions cannot return a tuple +fail_compilation/diag13884.d(14): Error: functions cannot return a sequence (use `std.typecons.Tuple`) fail_compilation/diag13884.d(21): instantiated from here: `MapResult!((t) => t.tupleof, Foo[])` fail_compilation/diag13884.d(14): instantiated from here: `map!(Foo[])` --- diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag14876.d b/gcc/testsuite/gdc.test/fail_compilation/diag14876.d index 0ca03602f97..4beea959001 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag14876.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag14876.d @@ -8,7 +8,7 @@ fail_compilation/diag14876.d(20): Deprecation: class `diag14876.Dep` is deprecat fail_compilation/diag14876.d(21): Deprecation: class `diag14876.Dep` is deprecated fail_compilation/diag14876.d(22): Deprecation: class `diag14876.Dep` is deprecated fail_compilation/diag14876.d(23): Deprecation: class `diag14876.Dep` is deprecated -fail_compilation/diag14876.d(23): Error: can only slice tuple types, not `diag14876.Dep` +fail_compilation/diag14876.d(23): Error: can only slice type sequences, not `diag14876.Dep` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d b/gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d index 21a12ed0253..02d95586eae 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d +++ b/gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d @@ -30,7 +30,7 @@ struct HasDtor ~this() {} } -// The user-defined dtor is overriden by a generated dtor calling both +// The user-defined dtor is overridden by a generated dtor calling both // - HasDtor.~this // - Strict.~this struct Strict diff --git a/gcc/testsuite/gdc.test/fail_compilation/e15876_1.d b/gcc/testsuite/gdc.test/fail_compilation/e15876_1.d index 92e07342d49..0152cdee276 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/e15876_1.d +++ b/gcc/testsuite/gdc.test/fail_compilation/e15876_1.d @@ -1,12 +1,13 @@ /* TEST_OUTPUT: --- -fail_compilation/e15876_1.d(16): Error: valid scope identifiers are `exit`, `failure`, or `success`, not `x` -fail_compilation/e15876_1.d(17): Error: found `End of File` when expecting `)` -fail_compilation/e15876_1.d(17): Error: found `End of File` instead of statement -fail_compilation/e15876_1.d(17): Error: found `End of File` when expecting `}` following compound statement -fail_compilation/e15876_1.d(17): Error: found `End of File` when expecting `]` -fail_compilation/e15876_1.d(17): Error: no identifier for declarator `o[() +fail_compilation/e15876_1.d(17): Error: valid scope identifiers are `exit`, `failure`, or `success`, not `x` +fail_compilation/e15876_1.d(18): Error: found `End of File` when expecting `)` +fail_compilation/e15876_1.d(18): Error: found `End of File` instead of statement +fail_compilation/e15876_1.d(18): Error: matching `}` expected following compound statement, not `End of File` +fail_compilation/e15876_1.d(17): unmatched `{` +fail_compilation/e15876_1.d(18): Error: found `End of File` when expecting `]` +fail_compilation/e15876_1.d(18): Error: no identifier for declarator `o[() { scope(exit) __error__ } diff --git a/gcc/testsuite/gdc.test/fail_compilation/e15876_2.d b/gcc/testsuite/gdc.test/fail_compilation/e15876_2.d index 10ff7d53a98..92164a4fd8b 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/e15876_2.d +++ b/gcc/testsuite/gdc.test/fail_compilation/e15876_2.d @@ -1,10 +1,11 @@ /* TEST_OUTPUT: --- -fail_compilation/e15876_2.d(15): Error: identifier expected following `template` -fail_compilation/e15876_2.d(15): Error: found `End of File` when expecting `}` following compound statement -fail_compilation/e15876_2.d(15): Error: found `End of File` when expecting `]` -fail_compilation/e15876_2.d(15): Error: no identifier for declarator `o[() +fail_compilation/e15876_2.d(16): Error: identifier expected following `template` +fail_compilation/e15876_2.d(16): Error: matching `}` expected following compound statement, not `End of File` +fail_compilation/e15876_2.d(15): unmatched `{` +fail_compilation/e15876_2.d(16): Error: found `End of File` when expecting `]` +fail_compilation/e15876_2.d(16): Error: no identifier for declarator `o[() { ; } diff --git a/gcc/testsuite/gdc.test/fail_compilation/e15876_3.d b/gcc/testsuite/gdc.test/fail_compilation/e15876_3.d index 0ac72296639..0482e87a549 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/e15876_3.d +++ b/gcc/testsuite/gdc.test/fail_compilation/e15876_3.d @@ -1,18 +1,19 @@ /* TEST_OUTPUT: --- -fail_compilation/e15876_3.d(27): Error: unexpected `(` in declarator -fail_compilation/e15876_3.d(27): Error: basic type expected, not `=` -fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `(` -fail_compilation/e15876_3.d(28): Error: found `End of File` instead of statement -fail_compilation/e15876_3.d(28): Error: expression expected, not `End of File` -fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `;` following `for` condition -fail_compilation/e15876_3.d(28): Error: expression expected, not `End of File` -fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `)` -fail_compilation/e15876_3.d(28): Error: found `End of File` instead of statement -fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `}` following compound statement -fail_compilation/e15876_3.d(28): Error: found `End of File` when expecting `)` -fail_compilation/e15876_3.d(28): Error: no identifier for declarator `d(_error_ = () +fail_compilation/e15876_3.d(28): Error: unexpected `(` in declarator +fail_compilation/e15876_3.d(28): Error: basic type expected, not `=` +fail_compilation/e15876_3.d(29): Error: found `End of File` when expecting `(` +fail_compilation/e15876_3.d(29): Error: found `End of File` instead of statement +fail_compilation/e15876_3.d(29): Error: expression expected, not `End of File` +fail_compilation/e15876_3.d(29): Error: found `End of File` when expecting `;` following `for` condition +fail_compilation/e15876_3.d(29): Error: expression expected, not `End of File` +fail_compilation/e15876_3.d(29): Error: found `End of File` when expecting `)` +fail_compilation/e15876_3.d(29): Error: found `End of File` instead of statement +fail_compilation/e15876_3.d(29): Error: matching `}` expected following compound statement, not `End of File` +fail_compilation/e15876_3.d(28): unmatched `{` +fail_compilation/e15876_3.d(29): Error: found `End of File` when expecting `)` +fail_compilation/e15876_3.d(29): Error: no identifier for declarator `d(_error_ = () { for (__error__ 0; 0) @@ -21,7 +22,7 @@ __error__ } } )` -fail_compilation/e15876_3.d(28): Error: semicolon expected following function declaration, not `End of File` +fail_compilation/e15876_3.d(29): Error: semicolon expected following function declaration, not `End of File` --- */ d(={for diff --git a/gcc/testsuite/gdc.test/fail_compilation/e15876_4.d b/gcc/testsuite/gdc.test/fail_compilation/e15876_4.d index f4bd407b9c0..e5c3bbf5673 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/e15876_4.d +++ b/gcc/testsuite/gdc.test/fail_compilation/e15876_4.d @@ -1,17 +1,18 @@ /* TEST_OUTPUT: --- -fail_compilation/e15876_4.d(25): Error: found `)` when expecting `(` -fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `(` -fail_compilation/e15876_4.d(26): Error: found `End of File` instead of statement -fail_compilation/e15876_4.d(26): Error: expression expected, not `End of File` -fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `;` following `for` condition -fail_compilation/e15876_4.d(26): Error: expression expected, not `End of File` -fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `)` -fail_compilation/e15876_4.d(26): Error: found `End of File` instead of statement -fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `}` following compound statement -fail_compilation/e15876_4.d(26): Error: found `End of File` when expecting `)` -fail_compilation/e15876_4.d(26): Error: no identifier for declarator `typeof(() +fail_compilation/e15876_4.d(26): Error: found `)` when expecting `(` +fail_compilation/e15876_4.d(27): Error: found `End of File` when expecting `(` +fail_compilation/e15876_4.d(27): Error: found `End of File` instead of statement +fail_compilation/e15876_4.d(27): Error: expression expected, not `End of File` +fail_compilation/e15876_4.d(27): Error: found `End of File` when expecting `;` following `for` condition +fail_compilation/e15876_4.d(27): Error: expression expected, not `End of File` +fail_compilation/e15876_4.d(27): Error: found `End of File` when expecting `)` +fail_compilation/e15876_4.d(27): Error: found `End of File` instead of statement +fail_compilation/e15876_4.d(27): Error: matching `}` expected following compound statement, not `End of File` +fail_compilation/e15876_4.d(26): unmatched `{` +fail_compilation/e15876_4.d(27): Error: found `End of File` when expecting `)` +fail_compilation/e15876_4.d(27): Error: no identifier for declarator `typeof(() { for (__error__ 0; 0) diff --git a/gcc/testsuite/gdc.test/fail_compilation/e15876_5.d b/gcc/testsuite/gdc.test/fail_compilation/e15876_5.d index 96b23e278cd..6bebc29fcb6 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/e15876_5.d +++ b/gcc/testsuite/gdc.test/fail_compilation/e15876_5.d @@ -1,11 +1,12 @@ /* TEST_OUTPUT: --- -fail_compilation/e15876_5.d(16): Error: basic type expected, not `End of File` -fail_compilation/e15876_5.d(16): Error: semicolon expected to close `alias` declaration, not `End of File` -fail_compilation/e15876_5.d(16): Error: found `End of File` when expecting `}` following compound statement -fail_compilation/e15876_5.d(16): Error: found `End of File` when expecting `]` -fail_compilation/e15876_5.d(16): Error: no identifier for declarator `p[() +fail_compilation/e15876_5.d(17): Error: basic type expected, not `End of File` +fail_compilation/e15876_5.d(17): Error: semicolon expected to close `alias` declaration, not `End of File` +fail_compilation/e15876_5.d(17): Error: matching `}` expected following compound statement, not `End of File` +fail_compilation/e15876_5.d(16): unmatched `{` +fail_compilation/e15876_5.d(17): Error: found `End of File` when expecting `]` +fail_compilation/e15876_5.d(17): Error: no identifier for declarator `p[() { alias ; } diff --git a/gcc/testsuite/gdc.test/fail_compilation/enum_init.d b/gcc/testsuite/gdc.test/fail_compilation/enum_init.d index 8344a4701c7..c968f5ee184 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/enum_init.d +++ b/gcc/testsuite/gdc.test/fail_compilation/enum_init.d @@ -58,6 +58,8 @@ TEST_OUTPUT: --- fail_compilation/enum_init.d(306): Error: variable `enum_init.fooOB.ob` - no definition of struct `S` fail_compilation/enum_init.d(302): required by type `OpaqueBase` +fail_compilation/enum_init.d(306): see https://dlang.org/spec/struct.html#opaque_struct_unions +fail_compilation/enum_init.d(306): perhaps declare a variable with pointer type `OpaqueBase*` instead --- */ #line 300 diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail12436.d b/gcc/testsuite/gdc.test/fail_compilation/fail12436.d index 5bdf0d5a891..415e362bf29 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail12436.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail12436.d @@ -12,7 +12,7 @@ alias Tuple!(int, int) TupleType; TEST_OUTPUT: --- fail_compilation/fail12436.d(18): Error: functions cannot return a function -fail_compilation/fail12436.d(19): Error: functions cannot return a tuple +fail_compilation/fail12436.d(19): Error: functions cannot return a sequence (use `std.typecons.Tuple`) --- */ FuncType test1(); diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail15755.d b/gcc/testsuite/gdc.test/fail_compilation/fail15755.d index 8fd2b51b60a..502eedcd6e3 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail15755.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail15755.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail15755.d(28): Error: `tuple(123)` has no effect +fail_compilation/fail15755.d(28): Error: `AliasSeq!(123)` has no effect --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail16772.d b/gcc/testsuite/gdc.test/fail_compilation/fail16772.d index e77951d3302..0bc97512c9a 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail16772.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail16772.d @@ -1,7 +1,8 @@ // https://issues.dlang.org/show_bug.cgi?id=16772 /* TEST_OUTPUT: --- -fail_compilation/fail16772.d(7): Error: function `fail16772.ice16772` cannot return type `ubyte[]` because its linkage is `extern(C++)` +fail_compilation/fail16772.d(8): Error: function `fail16772.ice16772` cannot return type `ubyte[]` because its linkage is `extern(C++)` +fail_compilation/fail16772.d(8): slices are specific to D and do not have a counterpart representation in C++ --- */ extern(C++) ubyte[] ice16772() { return []; } diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19209.d b/gcc/testsuite/gdc.test/fail_compilation/fail19209.d index ceede5e0eed..56b85815150 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail19209.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail19209.d @@ -2,7 +2,7 @@ TEST_OUTPUT: --- fail_compilation/fail19209.d(16): Error: function `fail19209.Spammer.method()` does not override any function, did you mean to override variable `fail19209.Spam.method`? -fail_compilation/fail19209.d(16): Functions are the only declarations that may be overriden +fail_compilation/fail19209.d(16): Functions are the only declarations that may be overridden --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail196.d b/gcc/testsuite/gdc.test/fail_compilation/fail196.d index 53505f496c2..cdad5c491db 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail196.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail196.d @@ -1,24 +1,26 @@ /* TEST_OUTPUT: --- -fail_compilation/fail196.d(27): Error: delimited string must end in `)"` -fail_compilation/fail196.d(27): Error: implicit string concatenation is error-prone and disallowed in D -fail_compilation/fail196.d(27): Use the explicit syntax instead (concatenating literals is `@nogc`): "foo(xxx)" ~ ";\n assert(s == " -fail_compilation/fail196.d(28): Error: semicolon needed to end declaration of `s`, instead of `foo` -fail_compilation/fail196.d(27): `s` declared here -fail_compilation/fail196.d(28): Error: found `");\n\n s = q"` when expecting `;` following statement `foo(xxx)` on line fail_compilation/fail196.d(28) -fail_compilation/fail196.d(30): Error: found `";\n assert(s == "` when expecting `;` following statement `[foo[xxx]]` on line fail_compilation/fail196.d(30) -fail_compilation/fail196.d(31): Error: found `");\n\n s = q"` when expecting `;` following statement `foo[xxx]` on line fail_compilation/fail196.d(31) -fail_compilation/fail196.d(33): Error: found `{` when expecting `;` following statement `foo` on line fail_compilation/fail196.d(33) -fail_compilation/fail196.d(33): Error: found `}` when expecting `;` following statement `xxx` on line fail_compilation/fail196.d(33) -fail_compilation/fail196.d(34): Error: found `foo` when expecting `;` following statement `";\n assert(s == "` on line fail_compilation/fail196.d(33) -fail_compilation/fail196.d(34): Error: found `}` when expecting `;` following statement `xxx` on line fail_compilation/fail196.d(34) -fail_compilation/fail196.d(36): Error: found `<` when expecting `;` following statement `");\n\n s = q" < foo` on line fail_compilation/fail196.d(34) -fail_compilation/fail196.d(37): Error: found `foo` when expecting `;` following statement `xxx >> ";\n assert(s == "` on line fail_compilation/fail196.d(36) -fail_compilation/fail196.d(37): Error: found `<` instead of statement -fail_compilation/fail196.d(43): Error: unterminated string constant starting at fail_compilation/fail196.d(43) -fail_compilation/fail196.d(45): Error: found `End of File` when expecting `}` following compound statement -fail_compilation/fail196.d(45): Error: found `End of File` when expecting `}` following compound statement +fail_compilation/fail196.d(29): Error: delimited string must end in `)"` +fail_compilation/fail196.d(29): Error: implicit string concatenation is error-prone and disallowed in D +fail_compilation/fail196.d(29): Use the explicit syntax instead (concatenating literals is `@nogc`): "foo(xxx)" ~ ";\n assert(s == " +fail_compilation/fail196.d(30): Error: semicolon needed to end declaration of `s`, instead of `foo` +fail_compilation/fail196.d(29): `s` declared here +fail_compilation/fail196.d(30): Error: found `");\n\n s = q"` when expecting `;` following statement `foo(xxx)` on line fail_compilation/fail196.d(30) +fail_compilation/fail196.d(32): Error: found `";\n assert(s == "` when expecting `;` following statement `[foo[xxx]]` on line fail_compilation/fail196.d(32) +fail_compilation/fail196.d(33): Error: found `");\n\n s = q"` when expecting `;` following statement `foo[xxx]` on line fail_compilation/fail196.d(33) +fail_compilation/fail196.d(35): Error: found `{` when expecting `;` following statement `foo` on line fail_compilation/fail196.d(35) +fail_compilation/fail196.d(35): Error: found `}` when expecting `;` following statement `xxx` on line fail_compilation/fail196.d(35) +fail_compilation/fail196.d(36): Error: found `foo` when expecting `;` following statement `";\n assert(s == "` on line fail_compilation/fail196.d(35) +fail_compilation/fail196.d(36): Error: found `}` when expecting `;` following statement `xxx` on line fail_compilation/fail196.d(36) +fail_compilation/fail196.d(38): Error: found `<` when expecting `;` following statement `");\n\n s = q" < foo` on line fail_compilation/fail196.d(36) +fail_compilation/fail196.d(39): Error: found `foo` when expecting `;` following statement `xxx >> ";\n assert(s == "` on line fail_compilation/fail196.d(38) +fail_compilation/fail196.d(39): Error: found `<` instead of statement +fail_compilation/fail196.d(45): Error: unterminated string constant starting at fail_compilation/fail196.d(45) +fail_compilation/fail196.d(47): Error: matching `}` expected following compound statement, not `End of File` +fail_compilation/fail196.d(36): unmatched `{` +fail_compilation/fail196.d(47): Error: matching `}` expected following compound statement, not `End of File` +fail_compilation/fail196.d(28): unmatched `{` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21206.d b/gcc/testsuite/gdc.test/fail_compilation/fail21206.d index c3d648e5d75..b3b42f34296 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail21206.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail21206.d @@ -1,7 +1,8 @@ // https://issues.dlang.org/show_bug.cgi?id=21206 /* TEST_OUTPUT: --- -fail_compilation/fail21206.d(9): Error: function `fail21206.Obj.toString` cannot return type `string` because its linkage is `extern(C++)` +fail_compilation/fail21206.d(10): Error: function `fail21206.Obj.toString` cannot return type `string` because its linkage is `extern(C++)` +fail_compilation/fail21206.d(10): slices are specific to D and do not have a counterpart representation in C++ --- */ extern(C++) struct Obj diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21275.d b/gcc/testsuite/gdc.test/fail_compilation/fail21275.d index 69cdf1ada9a..b7bbcfa6250 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail21275.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail21275.d @@ -1,12 +1,11 @@ // https://issues.dlang.org/show_bug.cgi?id=21275 -// REQUIRED_ARGS: -de // EXTRA_FILES: imports/fail21275a.d /* TEST_OUTPUT: --- -fail_compilation/fail21275.d(18): Deprecation: function `imports.fail21275a.Foo.x` of type `ref int() return` is not accessible from module `fail21275` -fail_compilation/fail21275.d(21): Deprecation: function `imports.fail21275a.Bar.x` of type `int(int)` is not accessible from module `fail21275` +fail_compilation/fail21275.d(17): Error: function `imports.fail21275a.Foo.x` of type `ref int() return` is not accessible from module `fail21275` +fail_compilation/fail21275.d(20): Error: function `imports.fail21275a.Bar.x` of type `int(int)` is not accessible from module `fail21275` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail222.d b/gcc/testsuite/gdc.test/fail_compilation/fail222.d index 30eb0144d99..e196b253065 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail222.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail222.d @@ -1,10 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/fail222.d(11): Error: template `fail222.getMixin(TArg..., int i = 0)()` template tuple parameter must be last one +fail_compilation/fail222.d(11): Error: template `fail222.getMixin(TArg..., int i = 0)()` template sequence parameter must be the last one fail_compilation/fail222.d(18): Error: template instance `getMixin!()` does not match template declaration `getMixin(TArg..., int i = 0)()` fail_compilation/fail222.d(21): Error: template instance `fail222.Thing!()` error instantiating -fail_compilation/fail222.d(23): Error: template `fail222.fooBar(A..., B...)()` template tuple parameter must be last one +fail_compilation/fail222.d(23): Error: template `fail222.fooBar(A..., B...)()` template sequence parameter must be the last one --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22729.d b/gcc/testsuite/gdc.test/fail_compilation/fail22729.d new file mode 100644 index 00000000000..38bbfeeed2b --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fail22729.d @@ -0,0 +1,39 @@ +// https://issues.dlang.org/show_bug.cgi?id=22729 + +/* +TEST_OUTPUT: +--- +fail_compilation/fail22729.d(12): Error: field `getChildAtPosition` not allowed in interface +--- +*/ + +interface ContainerFunctionSetI +{ + Tuple!(WidgetI) getChildAtPosition; +} + +interface WidgetI : ContainerFunctionSetI +{ +} + +class Form : WidgetI +{ +} + +template Tuple(Specs) +{ + enum areCompatibleTuples(Tup2)(Tuple tup1, Tup2 tup2) + { + tup1.field == tup2; + } + + struct Tuple + { + Specs field; + + bool opEquals(R)(R) if (areCompatibleTuples!R) + { + } + + } +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23745.d b/gcc/testsuite/gdc.test/fail_compilation/fail23745.d index eda9e1e63fa..46d92f0fa10 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail23745.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail23745.d @@ -5,7 +5,7 @@ TEST_OUTPUT: --- fail_compilation/fail23745.d(21): Error: undefined identifier `UndefinedType` fail_compilation/fail23745.d(14): Error: function `fun` does not override any function, did you mean to override `fail23745.A.fun`? -fail_compilation/fail23745.d(21): Function `fail23745.A.fun` contains errors in its declaration, therefore it cannot be correctly overriden +fail_compilation/fail23745.d(21): Function `fail23745.A.fun` contains errors in its declaration, therefore it cannot be correctly overridden --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail315.d b/gcc/testsuite/gdc.test/fail_compilation/fail315.d index c7fd78f8fc1..1a7e0f35f91 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail315.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail315.d @@ -1,13 +1,14 @@ /* TEST_OUTPUT: --- -fail_compilation/fail315.d-mixin-16(16): Error: found `;` when expecting `,` -fail_compilation/fail315.d-mixin-16(16): Error: expression expected, not `}` -fail_compilation/fail315.d-mixin-16(16): Error: found `End of File` when expecting `,` -fail_compilation/fail315.d-mixin-16(16): Error: found `End of File` when expecting `]` -fail_compilation/fail315.d-mixin-16(16): Error: found `End of File` when expecting `;` following `return` statement -fail_compilation/fail315.d-mixin-16(16): Error: found `End of File` when expecting `}` following compound statement -fail_compilation/fail315.d(21): Error: template instance `fail315.foo!()` error instantiating +fail_compilation/fail315.d-mixin-17(17): Error: found `;` when expecting `,` +fail_compilation/fail315.d-mixin-17(17): Error: expression expected, not `}` +fail_compilation/fail315.d-mixin-17(17): Error: found `End of File` when expecting `,` +fail_compilation/fail315.d-mixin-17(17): Error: found `End of File` when expecting `]` +fail_compilation/fail315.d-mixin-17(17): Error: found `End of File` when expecting `;` following `return` statement +fail_compilation/fail315.d-mixin-17(17): Error: matching `}` expected following compound statement, not `End of File` +fail_compilation/fail315.d-mixin-17(17): unmatched `{` +fail_compilation/fail315.d(22): Error: template instance `fail315.foo!()` error instantiating --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/funcpostattr.d b/gcc/testsuite/gdc.test/fail_compilation/funcpostattr.d new file mode 100644 index 00000000000..b50db058e32 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/funcpostattr.d @@ -0,0 +1,21 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/funcpostattr.d(11): Error: `deprecated` token is not allowed in postfix position +fail_compilation/funcpostattr.d(11): Error: `extern` token is not allowed in postfix position +fail_compilation/funcpostattr.d(15): Error: `static` token is not allowed in postfix position +fail_compilation/funcpostattr.d(15): Error: `ref` token is not allowed in postfix position +fail_compilation/funcpostattr.d(20): Error: `override` token is not allowed in postfix position +--- +*/ +void foo() deprecated extern; + +void main() { + int i; + int foo() static ref => i; +} + +class C +{ + void foo() override {} +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11965.d b/gcc/testsuite/gdc.test/fail_compilation/ice11965.d index c8db60fe9c9..9e6da3bbf84 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice11965.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice11965.d @@ -1,10 +1,11 @@ /* TEST_OUTPUT: --- -fail_compilation/ice11965.d(15): Error: no identifier for declarator `b*` -fail_compilation/ice11965.d(15): Error: found `End of File` when expecting `}` following compound statement -fail_compilation/ice11965.d(15): Error: found `End of File` when expecting `]` -fail_compilation/ice11965.d(15): Error: no identifier for declarator `u[() +fail_compilation/ice11965.d(16): Error: no identifier for declarator `b*` +fail_compilation/ice11965.d(16): Error: matching `}` expected following compound statement, not `End of File` +fail_compilation/ice11965.d(15): unmatched `{` +fail_compilation/ice11965.d(16): Error: found `End of File` when expecting `]` +fail_compilation/ice11965.d(16): Error: no identifier for declarator `u[() { b* A; } diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11982.d b/gcc/testsuite/gdc.test/fail_compilation/ice11982.d index 0f2ce413c40..0886df61678 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice11982.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice11982.d @@ -1,19 +1,20 @@ /* TEST_OUTPUT: --- -fail_compilation/ice11982.d(19): Error: basic type expected, not `scope` -fail_compilation/ice11982.d(19): Error: found `scope` when expecting `;` following statement `new _error_` on line fail_compilation/ice11982.d(19) -fail_compilation/ice11982.d(19): Error: basic type expected, not `}` -fail_compilation/ice11982.d(19): Error: missing `{ ... }` for function literal -fail_compilation/ice11982.d(19): Error: C style cast illegal, use `cast(funk)function _error_() +fail_compilation/ice11982.d(20): Error: basic type expected, not `scope` +fail_compilation/ice11982.d(20): Error: found `scope` when expecting `;` following statement `new _error_` on line fail_compilation/ice11982.d(20) +fail_compilation/ice11982.d(20): Error: basic type expected, not `}` +fail_compilation/ice11982.d(20): Error: missing `{ ... }` for function literal +fail_compilation/ice11982.d(20): Error: C style cast illegal, use `cast(funk)function _error_() { } ` -fail_compilation/ice11982.d(19): Error: found `}` when expecting `;` following statement `cast(funk)function _error_() +fail_compilation/ice11982.d(20): Error: found `}` when expecting `;` following statement `cast(funk)function _error_() { } -` on line fail_compilation/ice11982.d(19) -fail_compilation/ice11982.d(20): Error: found `End of File` when expecting `}` following compound statement +` on line fail_compilation/ice11982.d(20) +fail_compilation/ice11982.d(21): Error: matching `}` expected following compound statement, not `End of File` +fail_compilation/ice11982.d(20): unmatched `{` --- */ void main() { new scope ( funk ) function } diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice12574.d b/gcc/testsuite/gdc.test/fail_compilation/ice12574.d index 93e5f1d8cc0..ecb0fd69a05 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice12574.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice12574.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/ice12574.d(40): Error: tuple index `2` out of bounds `[0 .. 2]` +fail_compilation/ice12574.d(40): Error: sequence index `2` out of bounds `[0 .. 2]` fail_compilation/ice12574.d(53): Error: template instance `ice12574.reduce!("a", "a").reduce!(Tuple!(int, int, int))` error instantiating --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice14424.d b/gcc/testsuite/gdc.test/fail_compilation/ice14424.d index c99522dceb6..b0e0cd6407f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice14424.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice14424.d @@ -3,7 +3,7 @@ /* TEST_OUTPUT: --- -fail_compilation/ice14424.d(13): Error: `tuple(__unittest_L3_C1)` has no effect +fail_compilation/ice14424.d(13): Error: `AliasSeq!(__unittest_L3_C1)` has no effect --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice15855.d b/gcc/testsuite/gdc.test/fail_compilation/ice15855.d index b26fe4cda04..f7ad3900683 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice15855.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice15855.d @@ -2,16 +2,17 @@ /* TEST_OUTPUT: --- -fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `(` -fail_compilation/ice15855.d(27): Error: found `End of File` instead of statement -fail_compilation/ice15855.d(27): Error: expression expected, not `End of File` -fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `;` following `for` condition -fail_compilation/ice15855.d(27): Error: expression expected, not `End of File` -fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `)` -fail_compilation/ice15855.d(27): Error: found `End of File` instead of statement -fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `}` following compound statement -fail_compilation/ice15855.d(27): Error: found `End of File` when expecting `]` -fail_compilation/ice15855.d(27): Error: no identifier for declarator `a[() +fail_compilation/ice15855.d(28): Error: found `End of File` when expecting `(` +fail_compilation/ice15855.d(28): Error: found `End of File` instead of statement +fail_compilation/ice15855.d(28): Error: expression expected, not `End of File` +fail_compilation/ice15855.d(28): Error: found `End of File` when expecting `;` following `for` condition +fail_compilation/ice15855.d(28): Error: expression expected, not `End of File` +fail_compilation/ice15855.d(28): Error: found `End of File` when expecting `)` +fail_compilation/ice15855.d(28): Error: found `End of File` instead of statement +fail_compilation/ice15855.d(28): Error: matching `}` expected following compound statement, not `End of File` +fail_compilation/ice15855.d(27): unmatched `{` +fail_compilation/ice15855.d(28): Error: found `End of File` when expecting `]` +fail_compilation/ice15855.d(28): Error: no identifier for declarator `a[() { for (__error__ 0; 0) diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/issue23947a.d b/gcc/testsuite/gdc.test/fail_compilation/imports/issue23947a.d new file mode 100644 index 00000000000..270bf5fd538 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/imports/issue23947a.d @@ -0,0 +1,8 @@ +module imports.issue23947a; + +struct X { } +struct Y { } +class Class { + private void handle(X x) { } + public void handle(Y y) { } +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue20422.d b/gcc/testsuite/gdc.test/fail_compilation/issue20422.d index 1964f8ac888..9dcab004d2c 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/issue20422.d +++ b/gcc/testsuite/gdc.test/fail_compilation/issue20422.d @@ -1,12 +1,19 @@ // https://issues.dlang.org/show_bug.cgi?id=20422 /* +REQUIRED_ARGS: -m32 TEST_OUTPUT: --- -fail_compilation/issue20422.d(11): Error: missing length argument for array +fail_compilation/issue20422.d(15): Error: missing length argument for array +fail_compilation/issue20422.d(16): Error: negative array dimension `-1` +fail_compilation/issue20422.d(17): Error: negative array dimension `-2147483648` +fail_compilation/issue20422.d(18): Error: too many arguments for array --- */ void main() { new int[]; + new int[-1]; + new int[](int.min); + new int[](1, 2); } diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue23947.d b/gcc/testsuite/gdc.test/fail_compilation/issue23947.d new file mode 100644 index 00000000000..d73cd8572fa --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/issue23947.d @@ -0,0 +1,10 @@ +// https://issues.dlang.org/show_bug.cgi?id=23947 +/* +TEST_OUTPUT: +--- +fail_compilation/issue23947.d(10): Error: function `imports.issue23947a.Class.handle` of type `void(X x)` is not accessible from module `issue23947` +--- +*/ +import imports.issue23947a; + +void main() { Class.init.handle(X.init); } diff --git a/gcc/testsuite/gdc.test/fail_compilation/lexer4.d b/gcc/testsuite/gdc.test/fail_compilation/lexer4.d index c9db26434df..c4bdb4fd64c 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/lexer4.d +++ b/gcc/testsuite/gdc.test/fail_compilation/lexer4.d @@ -8,7 +8,7 @@ fail_compilation/lexer4.d(26): Error: binary digit expected, not `2` fail_compilation/lexer4.d(27): Error: octal digit expected, not `8` fail_compilation/lexer4.d(27): Error: octal literals larger than 7 are no longer supported fail_compilation/lexer4.d(28): Error: decimal digit expected, not `a` -fail_compilation/lexer4.d(29): Error: unrecognized token +fail_compilation/lexer4.d(29): Error: repeated integer suffix `U` fail_compilation/lexer4.d(30): Error: exponent required for hex float fail_compilation/lexer4.d(31): Error: lower case integer suffix 'l' is not allowed. Please use 'L' instead fail_compilation/lexer4.d(32): Error: use 'i' suffix instead of 'I' diff --git a/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d b/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d index d1361440920..a719b123a6a 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d +++ b/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d @@ -24,7 +24,8 @@ fail_compilation/misc_parser_err_cov1.d(40): Error: identifier or `new` expected fail_compilation/misc_parser_err_cov1.d(41): Error: identifier or new keyword expected following `(...)`. fail_compilation/misc_parser_err_cov1.d(41): Error: expression expected, not `;` fail_compilation/misc_parser_err_cov1.d(42): Error: found `}` when expecting `;` following statement `(__error) + 0` on line fail_compilation/misc_parser_err_cov1.d(41) -fail_compilation/misc_parser_err_cov1.d(43): Error: found `End of File` when expecting `}` following compound statement +fail_compilation/misc_parser_err_cov1.d(43): Error: matching `}` expected following compound statement, not `End of File` +fail_compilation/misc_parser_err_cov1.d(33): unmatched `{` --- */ module misc_parser_err_cov1; diff --git a/gcc/testsuite/gdc.test/fail_compilation/missingbrace.d b/gcc/testsuite/gdc.test/fail_compilation/missingbrace.d new file mode 100644 index 00000000000..5c8166eaa6e --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/missingbrace.d @@ -0,0 +1,10 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/missingbrace.d(11): Error: matching `}` expected following compound statement, not `End of File` +fail_compilation/missingbrace.d(9): unmatched `{` +--- +*/ +void main() +{ + int a; diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope.d b/gcc/testsuite/gdc.test/fail_compilation/retscope.d index 50cfdd3ef9c..c08747fa7e3 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/retscope.d +++ b/gcc/testsuite/gdc.test/fail_compilation/retscope.d @@ -403,7 +403,7 @@ class Foo13 /* TEST_OUTPUT: --- -fail_compilation/retscope.d(1205): Error: scope variable `f14` calling non-scope member function `f14.foo()` +fail_compilation/retscope.d(1205): Error: scope variable `f14` calling non-scope member function `Foo14.foo()` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20245.d b/gcc/testsuite/gdc.test/fail_compilation/test20245.d index 3c43c5cfe4b..a6bbba29128 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test20245.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test20245.d @@ -9,7 +9,7 @@ fail_compilation/test20245.d(27): Error: cannot take address of `scope` variable fail_compilation/test20245.d(33): Error: reference to local variable `x` assigned to non-scope parameter `ptr` calling `escape` fail_compilation/test20245.d(34): Error: copying `&x` into allocated memory escapes a reference to parameter `x` fail_compilation/test20245.d(50): Error: reference to local variable `price` assigned to non-scope `this.minPrice` -fail_compilation/test20245.d(69): Error: reference to local variable `this` calling non-scope member function `this.this()` +fail_compilation/test20245.d(69): Error: reference to local variable `this.content[]` calling non-scope member function `Exception.this()` fail_compilation/test20245.d(89): Error: reference to local variable `this` assigned to non-scope parameter `content` calling `listUp` fail_compilation/test20245.d(82): which is not `scope` because of `charPtr = content` --- diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21025.d b/gcc/testsuite/gdc.test/fail_compilation/test21025.d new file mode 100644 index 00000000000..85641998751 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test21025.d @@ -0,0 +1,25 @@ +// https://issues.dlang.org/show_bug.cgi?id=21025 +// REQUIRED_ARGS: -preview=dip1021 + +/* +TEST_OUTPUT: +--- +fail_compilation/test21025.d(15): Error: variable `r` cannot be read at compile time +fail_compilation/test21025.d(15): called from here: `binaryFun(r, r)` +fail_compilation/test21025.d(24): Error: template `test21025.uniq` is not callable using argument types `!()(void[])` +fail_compilation/test21025.d(14): Candidate is: `uniq()(int[] r)` +--- +*/ + +void uniq()(int[] r) +if (binaryFun(r, r)) {} + +bool binaryFun(T, U)(T, U) +{ + return true; +} + +void generateStatements() +{ + uniq([]); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23968.d b/gcc/testsuite/gdc.test/fail_compilation/test23968.d new file mode 100644 index 00000000000..4456e75c707 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test23968.d @@ -0,0 +1,23 @@ +// https://issues.dlang.org/show_bug.cgi?id=23968 + +// REQUIRED_ARGS: -de + +/* +TEST_OUTPUT: +--- +fail_compilation/test23968.d(22): Deprecation: alias `test23968.a` is deprecated +--- +*/ + +int fun()(int) +{ + return 0; +} + +deprecated alias a = fun; + +void main() +{ + int v; + int y = v.a!(); // No deprecation? +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23982.d b/gcc/testsuite/gdc.test/fail_compilation/test23982.d new file mode 100644 index 00000000000..f8eee238ed8 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test23982.d @@ -0,0 +1,36 @@ +/* +REQUIRED_ARGS: -preview=dip1000 +TEST_OUTPUT: +--- +fail_compilation/test23982.d(35): Error: scope variable `a` assigned to non-scope parameter `a` calling `foo2` +fail_compilation/test23982.d(26): which is not `scope` because of `b = a` +--- +*/ +// https://issues.dlang.org/show_bug.cgi?id=23982 +// Issue 23982 - segfault when printing scope inference failure +@safe: + +struct B() +{ + this(int* a) + { + this.a = a; + } + int* a; +} + +class C() +{ + int* foo2(int* a) + { + auto b = B!()(a); + return b.a; + } +} + +void main() +{ + scope int* a; + C!() c; + c.foo2(a); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/typeerrors.d b/gcc/testsuite/gdc.test/fail_compilation/typeerrors.d index 9d527b75d71..404a4c0e3fe 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/typeerrors.d +++ b/gcc/testsuite/gdc.test/fail_compilation/typeerrors.d @@ -2,7 +2,7 @@ TEST_OUTPUT: --- fail_compilation/typeerrors.d(32): Deprecation: `scope` as a type constraint is deprecated. Use `scope` at the usage site. -fail_compilation/typeerrors.d(37): Error: tuple index `4` out of bounds `[0 .. 4]` +fail_compilation/typeerrors.d(37): Error: sequence index `4` out of bounds `[0 .. 4]` fail_compilation/typeerrors.d(39): Error: variable `x` cannot be read at compile time fail_compilation/typeerrors.d(40): Error: cannot have array of `void()` fail_compilation/typeerrors.d(41): Error: cannot have array of scope `typeerrors.C` diff --git a/gcc/testsuite/gdc.test/fail_compilation/unmatchedbrace.d b/gcc/testsuite/gdc.test/fail_compilation/unmatchedbrace.d new file mode 100644 index 00000000000..30dc3b5d90e --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/unmatchedbrace.d @@ -0,0 +1,10 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/unmatchedbrace.d(11): Error: matching `}` expected, not `End of File` +fail_compilation/unmatchedbrace.d(8): unmatched `{` +--- +*/ +@safe { + // + struct S {} diff --git a/gcc/testsuite/gdc.test/runnable/functype.d b/gcc/testsuite/gdc.test/runnable/functype.d index 5dad6186fba..cdeb4182a1f 100644 --- a/gcc/testsuite/gdc.test/runnable/functype.d +++ b/gcc/testsuite/gdc.test/runnable/functype.d @@ -301,7 +301,7 @@ void test10734() void test14656() { - //void unaryFun()(auto int a) pure nothrow @safe @nogc {} // changed to invalid by fixing issue 14669 + //void unaryFun()(auto int a) pure nothrow @safe @nogc {} // changed to invalid by fixing https://issues.dlang.org/show_bug.cgi?id=14669 alias Identity(F) = F; //unaryFun!()(41); static void fun(int n) pure nothrow @safe @nogc {} diff --git a/gcc/testsuite/gdc.test/runnable/interface2.d b/gcc/testsuite/gdc.test/runnable/interface2.d index fabbbfd4bfc..603e4b25108 100644 --- a/gcc/testsuite/gdc.test/runnable/interface2.d +++ b/gcc/testsuite/gdc.test/runnable/interface2.d @@ -962,11 +962,11 @@ void test1747() assert(pia == pc + n); assert(id.mA() == 1); - assert(id.mB() == 2); // OK <- NG (bugzilla 2013 case) + assert(id.mB() == 2); // OK <- NG (https://issues.dlang.org/show_bug.cgi?id=2013 case) assert(id.mD() == 3); assert(ic.mA() == 1); - assert(ic.mB() == 2); // OK <- NG (bugzilla 2013 case) + assert(ic.mB() == 2); // OK <- NG (https://issues.dlang.org/show_bug.cgi?id=2013 case) assert(ib.mA() == 1); assert(ib.mB() == 2); // OK <- NG diff --git a/gcc/testsuite/gdc.test/runnable/link10425.d b/gcc/testsuite/gdc.test/runnable/link10425.d index d0825165765..ae135ea703a 100644 --- a/gcc/testsuite/gdc.test/runnable/link10425.d +++ b/gcc/testsuite/gdc.test/runnable/link10425.d @@ -10,7 +10,7 @@ void main() * the TypeInfo object on comdat section (done by TypeInfoDeclaration::toObjFile), * even if the associated struct belongs *non-root modules*. * - * And, from 2.062, issue 7511 is implemented. + * And, from 2.062, https://issues.dlang.org/show_bug.cgi?id=7511 is implemented. * The attribute inference for member functions in instantiated struct may modify * their actual mangled names. Then TypeInfo object compiled in this module would * use wrong symbol names, to link non-template opEquals/opCmp/toHash/toString diff --git a/gcc/testsuite/gdc.test/runnable/sdtor.d b/gcc/testsuite/gdc.test/runnable/sdtor.d index e6b3238149e..be15cb244a1 100644 --- a/gcc/testsuite/gdc.test/runnable/sdtor.d +++ b/gcc/testsuite/gdc.test/runnable/sdtor.d @@ -4813,6 +4813,41 @@ void testPR12012() } } +/**********************************/ +// https://issues.dlang.org/show_bug.cgi?id=24010 + +alias AliasSeq(TList...) = TList; + +__gshared int x24010 = 7; + +struct A24010 { + int x; + ~this() { + printf("A.~this\n"); + x24010 += 1; + } +} + +struct B24010 { + ~this() { + printf("B.~this\n"); + x24010 *= 10; + } +} + +void test24010() +{ + { + AliasSeq!(A24010, B24010) params; + printf("statement\n"); + params[0].x = 3; + printf(".x = %d\n", params[0].x); + assert(params[0].x == 3); + assert(x24010 == 7); + } + assert(x24010 == 71); +} + /**********************************/ int main() @@ -4954,6 +4989,7 @@ int main() test67(); test68(); testPR12012(); + test24010(); printf("Success\n"); return 0; diff --git a/gcc/testsuite/gdc.test/runnable/template9.d b/gcc/testsuite/gdc.test/runnable/template9.d index cb3de5bc6f0..dbad3f1daec 100644 --- a/gcc/testsuite/gdc.test/runnable/template9.d +++ b/gcc/testsuite/gdc.test/runnable/template9.d @@ -4689,7 +4689,8 @@ struct S14604 } alias Id14604(alias thing) = thing; alias c14604 = Id14604!(S14604.opDispatch!"go"); // ok -alias d14604 = Id14604!(S14604.go); // issue 14604, 'Error: template instance opDispatch!"go" cannot resolve forward reference' +// https://issues.dlang.org/show_bug.cgi?id=14604 +alias d14604 = Id14604!(S14604.go); // 'Error: template instance opDispatch!"go" cannot resolve forward reference' /******************************************/ // https://issues.dlang.org/show_bug.cgi?id=14735 diff --git a/gcc/testsuite/gdc.test/runnable/test23959.d b/gcc/testsuite/gdc.test/runnable/test23959.d new file mode 100644 index 00000000000..32883736d44 --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable/test23959.d @@ -0,0 +1,30 @@ +// https://issues.dlang.org/show_bug.cgi?id=23959; + +struct ST() +{ + int i; + this(this) {} +} + +alias S = ST!(); + +void poison() +{ + static S g; + auto s = g; +} + +S[1] sa; + +void fun(S[] values...) +{ + sa[] = values; +} + +int main() +{ + fun(S(1)); + assert(sa[0].i); + + return 0; +} diff --git a/gcc/testsuite/gdc.test/runnable/testcontracts.d b/gcc/testsuite/gdc.test/runnable/testcontracts.d index e79c6a05716..439040b7b38 100644 --- a/gcc/testsuite/gdc.test/runnable/testcontracts.d +++ b/gcc/testsuite/gdc.test/runnable/testcontracts.d @@ -936,7 +936,7 @@ void test9383() /*******************************************/ // https://issues.dlang.org/show_bug.cgi?id=15524 -// Different from issue 9383 cases, closed variable size is bigger than REGSIZE. +// Different from https://issues.dlang.org/show_bug.cgi?id=9383 cases, closed variable size is bigger than REGSIZE. class A15524 { diff --git a/gcc/testsuite/gdc.test/runnable/uda.d b/gcc/testsuite/gdc.test/runnable/uda.d index 1d010989646..d4e4c2ae95e 100644 --- a/gcc/testsuite/gdc.test/runnable/uda.d +++ b/gcc/testsuite/gdc.test/runnable/uda.d @@ -2,30 +2,30 @@ EXTRA_FILES: imports/a9741.d TEST_OUTPUT: --- -tuple(3, 4, 7, (SSS)) -tuple(3, 4, 7, (SSS)) +AliasSeq!(3, 4, 7, (SSS)) +AliasSeq!(3, 4, 7, (SSS)) 7 SSS -tuple("hello") -tuple('c') -tuple((FFF)) -tuple(10) -tuple(20) -tuple(30) -tuple((Test6)) -tuple(Test7(3, "foo")) -tuple((Test8!"foo")) -tuple((Test9!"foo")) -tuple(Test10(3)) -tuple(Test11(3)) -tuple(10) -tuple(20) -tuple() -tuple(40) +AliasSeq!("hello") +AliasSeq!('c') +AliasSeq!((FFF)) +AliasSeq!(10) +AliasSeq!(20) +AliasSeq!(30) +AliasSeq!((Test6)) +AliasSeq!(Test7(3, "foo")) +AliasSeq!((Test8!"foo")) +AliasSeq!((Test9!"foo")) +AliasSeq!(Test10(3)) +AliasSeq!(Test11(3)) +AliasSeq!(10) +AliasSeq!(20) +AliasSeq!() +AliasSeq!(40) B9741 -tuple((A9741)) -tuple(1) -tuple(2) +AliasSeq!((A9741)) +AliasSeq!(1) +AliasSeq!(2) --- RUN_OUTPUT: diff --git a/gcc/testsuite/gdc.test/runnable/xtest46.d b/gcc/testsuite/gdc.test/runnable/xtest46.d index 5017a767693..972de900203 100644 --- a/gcc/testsuite/gdc.test/runnable/xtest46.d +++ b/gcc/testsuite/gdc.test/runnable/xtest46.d @@ -13,17 +13,17 @@ runnable/xtest46.d(2964): Deprecation: alias this for classes/interfaces is depr int(int i, long j = 7L) long C10390(C10390(C10390())) -tuple(height) -tuple(get, get) -tuple(clear) -tuple(draw, draw) +AliasSeq!(height) +AliasSeq!(get, get) +AliasSeq!(clear) +AliasSeq!(draw, draw) const(int) string[] double[] double[] {} runnable/xtest46.d(4670): Deprecation: alias this for classes/interfaces is deprecated -tuple("m") +AliasSeq!("m") true TFunction1: extern (C) void function() --- diff --git a/gcc/testsuite/gdc.test/runnable/xtest46_gc.d b/gcc/testsuite/gdc.test/runnable/xtest46_gc.d index 224625c65ec..aab6227230a 100644 --- a/gcc/testsuite/gdc.test/runnable/xtest46_gc.d +++ b/gcc/testsuite/gdc.test/runnable/xtest46_gc.d @@ -14,17 +14,17 @@ runnable/xtest46_gc.d-mixin-33(2996): Deprecation: alias this for classes/interf int(int i, long j = 7L) long C10390(C10390()) -tuple(height) -tuple(get, get) -tuple(clear) -tuple(draw, draw) +AliasSeq!(height) +AliasSeq!(get, get) +AliasSeq!(clear) +AliasSeq!(draw, draw) const(int) string[] double[] double[] {} runnable/xtest46_gc.d-mixin-33(4702): Deprecation: alias this for classes/interfaces is deprecated -tuple("m") +AliasSeq!("m") true TFunction1: extern (C) void function() --- diff --git a/libphobos/config.h.in b/libphobos/config.h.in index 0249849c890..6ecb3f2b1ba 100644 --- a/libphobos/config.h.in +++ b/libphobos/config.h.in @@ -1,14 +1,23 @@ /* config.h.in. Generated from configure.ac by autoheader. */ +/* Define to enable to integrate valgrind (a memory checker) in the GC. */ +#undef ENABLE_VALGRIND_CHECKING + /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H +/* Define if valgrind's memcheck.h header is installed. */ +#undef HAVE_MEMCHECK_H + /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H +/* Define to 1 if you have the header file. */ +#undef HAVE_STDDEF_H + /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H @@ -30,6 +39,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H +/* Define if valgrind's valgrind/memcheck.h header is installed. */ +#undef HAVE_VALGRIND_MEMCHECK_H + /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR diff --git a/libphobos/configure b/libphobos/configure index 925c53c5f5e..d702c8f494c 100755 --- a/libphobos/configure +++ b/libphobos/configure @@ -1498,8 +1498,8 @@ Optional Features: --enable-libphobos-checking[=LIST] enable expensive run-time checks. With LIST, enable only specific categories of checks. Categories are: - yes,no,all,none,release. Flags are: assert or other - strings + yes,no,all,none,release. Flags are: assert,valgrind + or other strings Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -15553,16 +15553,20 @@ for check in release $ac_checking_flags do case $check in # These set all the flags to specific states - yes|all) RELEASE_FLAG="-fno-release" ; ASSERT_FLAG= ;; - no|none|release) RELEASE_FLAG="-frelease" ; ASSERT_FLAG= ;; + yes|all) RELEASE_FLAG="-fno-release" ; ASSERT_FLAG= ; + VALGRIND_FLAG= ;; + no|none|release) RELEASE_FLAG="-frelease" ; ASSERT_FLAG= ; + VALGRIND_FLAG= ;; # These enable particular checks - assert) ASSERT_FLAG="-fassert" ;; + assert) ASSERT_FLAG="-fassert" ;; + valgrind) VALGRIND_FLAG="-fdebug=VALGRIND" ;; # Accept *) ;; esac done IFS="$ac_save_IFS" -CHECKING_DFLAGS="$RELEASE_FLAG $ASSERT_FLAG" +CHECKING_DFLAGS="$RELEASE_FLAG $ASSERT_FLAG $VALGRIND_FLAG" + # Add drtbegin.o/drtend.o to startfile/endfile specs in libgphobos.spec @@ -15600,6 +15604,91 @@ fi + + for ac_header in stddef.h stdlib.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + ac_fn_c_check_header_mongrel "$LINENO" "valgrind.h" "ac_cv_header_valgrind_h" "$ac_includes_default" +if test "x$ac_cv_header_valgrind_h" = xyes; then : + have_valgrind_h=yes +else + have_valgrind_h=no +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in " >&5 +$as_echo_n "checking for VALGRIND_DISCARD in ... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #ifndef VALGRIND_DISCARD + #error VALGRIND_DISCARD not defined + #endif +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + have_valgrind_memcheck_h=yes +else + have_valgrind_memcheck_h=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_valgrind_memcheck_h" >&5 +$as_echo "$have_valgrind_memcheck_h" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in " >&5 +$as_echo_n "checking for VALGRIND_DISCARD in ... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #ifndef VALGRIND_DISCARD + #error VALGRIND_DISCARD not defined + #endif +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + have_memcheck_h=yes +else + have_memcheck_h=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_memcheck_h" >&5 +$as_echo "$have_memcheck_h" >&6; } + + if test x$VALGRIND_FLAG != x ; then + +$as_echo "#define ENABLE_VALGRIND_CHECKING 1" >>confdefs.h + + fi + if test $have_valgrind_memcheck_h = yes; then + +$as_echo "#define HAVE_VALGRIND_MEMCHECK_H 1" >>confdefs.h + + fi + if test $have_memcheck_h = yes; then + +$as_echo "#define HAVE_MEMCHECK_H 1" >>confdefs.h + + fi + + if test x$VALGRIND_FLAG != x; then + if (test $have_valgrind_h = no \ + && test $have_memcheck_h = no \ + && test $have_valgrind_memcheck_h = no); then + as_fn_error $? "*** valgrind checking requested, but +*** Can't find valgrind/memcheck.h, memcheck.h or valgrind.h" "$LINENO" 5 + fi + fi + + ac_config_files="$ac_config_files Makefile" diff --git a/libphobos/configure.ac b/libphobos/configure.ac index 464f4105430..3b2e6df5d5c 100644 --- a/libphobos/configure.ac +++ b/libphobos/configure.ac @@ -221,25 +221,29 @@ AC_ARG_ENABLE(libphobos-checking, [enable expensive run-time checks. With LIST, enable only specific categories of checks. Categories are: yes,no,all,none,release. - Flags are: assert or other strings])], + Flags are: assert,valgrind or other strings])], [ac_checking_flags="${enableval}"],[ac_checking_flags=release]) IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="$IFS," for check in release $ac_checking_flags do case $check in # These set all the flags to specific states - yes|all) RELEASE_FLAG="-fno-release" ; ASSERT_FLAG= ;; - no|none|release) RELEASE_FLAG="-frelease" ; ASSERT_FLAG= ;; + yes|all) RELEASE_FLAG="-fno-release" ; ASSERT_FLAG= ; + VALGRIND_FLAG= ;; + no|none|release) RELEASE_FLAG="-frelease" ; ASSERT_FLAG= ; + VALGRIND_FLAG= ;; # These enable particular checks - assert) ASSERT_FLAG="-fassert" ;; + assert) ASSERT_FLAG="-fassert" ;; + valgrind) VALGRIND_FLAG="-fdebug=VALGRIND" ;; # Accept *) ;; esac done IFS="$ac_save_IFS" -CHECKING_DFLAGS="$RELEASE_FLAG $ASSERT_FLAG" +CHECKING_DFLAGS="$RELEASE_FLAG $ASSERT_FLAG $VALGRIND_FLAG" AC_SUBST(CHECKING_DFLAGS) + # Add drtbegin.o/drtend.o to startfile/endfile specs in libgphobos.spec if test "$DCFG_MINFO_BRACKETING" = "false"; then DRTSTUFF_SPEC=$srcdir/src/drtstuff.spec @@ -269,6 +273,8 @@ AC_SUBST(WARN_DFLAGS) AC_CHECK_HEADER(stdio.h,:, [AC_MSG_ERROR([cannot find stdio.h.])]) +DRUNTIME_LIBRARIES_VALGRIND + AC_CONFIG_FILES(Makefile) AC_CONFIG_FILES(libdruntime/gcc/config.d libdruntime/gcc/libbacktrace.d) diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index 1cff48a7b2a..308d51b55d0 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -1,4 +1,4 @@ -17ccd12af386543c0b9935bf7e0a8e701b903105 +a88e1335f7ea767ef438c34998f5d1f26008c586 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 8225ba4a028..832a0524ab3 100644 --- a/libphobos/libdruntime/Makefile.am +++ b/libphobos/libdruntime/Makefile.am @@ -165,7 +165,7 @@ install-data-local: # Can't use wildcards here: # https://www.gnu.org/software/automake/manual/html_node/Wildcards.html -DRUNTIME_CSOURCES = core/stdc/errno_.c +DRUNTIME_CSOURCES = core/stdc/errno_.c etc/valgrind/valgrind_.c DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \ core/builtins.d core/checkedint.d core/cpuid.d core/demangle.d \ @@ -205,11 +205,11 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \ core/sync/semaphore.d core/thread/context.d core/thread/fiber.d \ core/thread/osthread.d core/thread/package.d core/thread/threadbase.d \ core/thread/threadgroup.d core/thread/types.d core/time.d \ - core/vararg.d core/volatile.d gcc/attribute.d gcc/attributes.d \ - gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \ - gcc/sections/common.d gcc/sections/elf.d gcc/sections/macho.d \ - gcc/sections/package.d gcc/sections/pecoff.d gcc/simd.d \ - gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \ + core/vararg.d core/volatile.d etc/valgrind/valgrind.d gcc/attribute.d \ + gcc/attributes.d gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d \ + gcc/gthread.d gcc/sections/common.d gcc/sections/elf.d \ + gcc/sections/macho.d gcc/sections/package.d gcc/sections/pecoff.d \ + gcc/simd.d gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \ gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \ rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arraycat.d rt/cast_.d \ rt/config.d rt/critical_.d rt/deh.d rt/dmain2.d rt/ehalloc.d \ @@ -273,6 +273,7 @@ DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \ core/sys/linux/dlfcn.d core/sys/linux/elf.d core/sys/linux/epoll.d \ core/sys/linux/err.d core/sys/linux/errno.d core/sys/linux/execinfo.d \ core/sys/linux/fcntl.d core/sys/linux/fs.d core/sys/linux/ifaddrs.d \ + core/sys/linux/input.d core/sys/linux/input_event_codes.d \ core/sys/linux/io_uring.d core/sys/linux/link.d \ core/sys/linux/netinet/in_.d core/sys/linux/netinet/tcp.d \ core/sys/linux/perf_event.d core/sys/linux/sched.d \ @@ -284,7 +285,8 @@ DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \ core/sys/linux/sys/socket.d core/sys/linux/sys/sysinfo.d \ core/sys/linux/sys/time.d core/sys/linux/sys/xattr.d \ core/sys/linux/termios.d core/sys/linux/time.d \ - core/sys/linux/timerfd.d core/sys/linux/tipc.d core/sys/linux/unistd.d + core/sys/linux/timerfd.d core/sys/linux/tipc.d core/sys/linux/uinput.d \ + core/sys/linux/unistd.d DRUNTIME_DSOURCES_NETBSD = core/sys/netbsd/dlfcn.d \ core/sys/netbsd/err.d core/sys/netbsd/execinfo.d \ diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in index 797d6435a7c..61a2a770888 100644 --- a/libphobos/libdruntime/Makefile.in +++ b/libphobos/libdruntime/Makefile.in @@ -235,12 +235,12 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \ core/thread/osthread.lo core/thread/package.lo \ core/thread/threadbase.lo core/thread/threadgroup.lo \ core/thread/types.lo core/time.lo core/vararg.lo \ - core/volatile.lo gcc/attribute.lo gcc/attributes.lo \ - gcc/backtrace.lo gcc/builtins.lo gcc/deh.lo gcc/emutls.lo \ - gcc/gthread.lo gcc/sections/common.lo gcc/sections/elf.lo \ - gcc/sections/macho.lo gcc/sections/package.lo \ - gcc/sections/pecoff.lo gcc/simd.lo gcc/unwind/arm.lo \ - gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \ + core/volatile.lo etc/valgrind/valgrind.lo gcc/attribute.lo \ + gcc/attributes.lo gcc/backtrace.lo gcc/builtins.lo gcc/deh.lo \ + gcc/emutls.lo gcc/gthread.lo gcc/sections/common.lo \ + gcc/sections/elf.lo gcc/sections/macho.lo \ + gcc/sections/package.lo gcc/sections/pecoff.lo gcc/simd.lo \ + gcc/unwind/arm.lo gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \ gcc/unwind/generic.lo gcc/unwind/package.lo gcc/unwind/pe.lo \ object.lo rt/aApply.lo rt/aApplyR.lo rt/aaA.lo rt/adi.lo \ rt/arraycat.lo rt/cast_.lo rt/config.lo rt/critical_.lo \ @@ -248,7 +248,8 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \ rt/lifetime.lo rt/memory.lo rt/minfo.lo rt/monitor_.lo \ rt/profilegc.lo rt/sections.lo rt/tlsgc.lo rt/util/typeinfo.lo \ rt/util/utility.lo -am__objects_2 = core/stdc/libgdruntime_la-errno_.lo +am__objects_2 = core/stdc/libgdruntime_la-errno_.lo \ + etc/valgrind/libgdruntime_la-valgrind_.lo am__objects_3 = core/sys/elf/package.lo am__objects_4 = core/stdcpp/allocator.lo core/stdcpp/array.lo \ core/stdcpp/exception.lo core/stdcpp/memory.lo \ @@ -363,6 +364,7 @@ am__objects_19 = core/sys/linux/config.lo core/sys/linux/dlfcn.lo \ core/sys/linux/err.lo core/sys/linux/errno.lo \ core/sys/linux/execinfo.lo core/sys/linux/fcntl.lo \ core/sys/linux/fs.lo core/sys/linux/ifaddrs.lo \ + core/sys/linux/input.lo core/sys/linux/input_event_codes.lo \ core/sys/linux/io_uring.lo core/sys/linux/link.lo \ core/sys/linux/netinet/in_.lo core/sys/linux/netinet/tcp.lo \ core/sys/linux/perf_event.lo core/sys/linux/sched.lo \ @@ -375,7 +377,7 @@ am__objects_19 = core/sys/linux/config.lo core/sys/linux/dlfcn.lo \ core/sys/linux/sys/time.lo core/sys/linux/sys/xattr.lo \ core/sys/linux/termios.lo core/sys/linux/time.lo \ core/sys/linux/timerfd.lo core/sys/linux/tipc.lo \ - core/sys/linux/unistd.lo + core/sys/linux/uinput.lo core/sys/linux/unistd.lo @DRUNTIME_OS_LINUX_TRUE@am__objects_20 = $(am__objects_19) am__objects_21 = core/sys/windows/accctrl.lo \ core/sys/windows/aclapi.lo core/sys/windows/aclui.lo \ @@ -497,7 +499,8 @@ am__objects_35 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \ am_libgdruntime_la_OBJECTS = $(am__objects_35) libgdruntime_la_OBJECTS = $(am_libgdruntime_la_OBJECTS) am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -am__objects_36 = core/stdc/libgdruntime_convenience_la-errno_.lo +am__objects_36 = core/stdc/libgdruntime_convenience_la-errno_.lo \ + etc/valgrind/libgdruntime_convenience_la-valgrind_.lo @DRUNTIME_OS_MINGW_TRUE@am__objects_37 = $(am__objects_21) \ @DRUNTIME_OS_MINGW_TRUE@ config/mingw/libgdruntime_convenience_la-msvc.lo @DRUNTIME_CPU_AARCH64_TRUE@am__objects_38 = config/aarch64/libgdruntime_convenience_la-switchcontext.lo @@ -836,7 +839,7 @@ libgdruntime_convenience_la_LINK = $(libgdruntime_la_LINK) # https://gist.github.com/jpf91/8ad1dbc9902d6ad876313f134c6527d1 # Can't use wildcards here: # https://www.gnu.org/software/automake/manual/html_node/Wildcards.html -DRUNTIME_CSOURCES = core/stdc/errno_.c +DRUNTIME_CSOURCES = core/stdc/errno_.c etc/valgrind/valgrind_.c DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \ core/builtins.d core/checkedint.d core/cpuid.d core/demangle.d \ core/exception.d core/factory.d core/gc/config.d core/gc/gcinterface.d \ @@ -875,11 +878,11 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \ core/sync/semaphore.d core/thread/context.d core/thread/fiber.d \ core/thread/osthread.d core/thread/package.d core/thread/threadbase.d \ core/thread/threadgroup.d core/thread/types.d core/time.d \ - core/vararg.d core/volatile.d gcc/attribute.d gcc/attributes.d \ - gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d gcc/gthread.d \ - gcc/sections/common.d gcc/sections/elf.d gcc/sections/macho.d \ - gcc/sections/package.d gcc/sections/pecoff.d gcc/simd.d \ - gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \ + core/vararg.d core/volatile.d etc/valgrind/valgrind.d gcc/attribute.d \ + gcc/attributes.d gcc/backtrace.d gcc/builtins.d gcc/deh.d gcc/emutls.d \ + gcc/gthread.d gcc/sections/common.d gcc/sections/elf.d \ + gcc/sections/macho.d gcc/sections/package.d gcc/sections/pecoff.d \ + gcc/simd.d gcc/unwind/arm.d gcc/unwind/arm_common.d gcc/unwind/c6x.d \ gcc/unwind/generic.d gcc/unwind/package.d gcc/unwind/pe.d object.d \ rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arraycat.d rt/cast_.d \ rt/config.d rt/critical_.d rt/deh.d rt/dmain2.d rt/ehalloc.d \ @@ -942,6 +945,7 @@ DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \ core/sys/linux/dlfcn.d core/sys/linux/elf.d core/sys/linux/epoll.d \ core/sys/linux/err.d core/sys/linux/errno.d core/sys/linux/execinfo.d \ core/sys/linux/fcntl.d core/sys/linux/fs.d core/sys/linux/ifaddrs.d \ + core/sys/linux/input.d core/sys/linux/input_event_codes.d \ core/sys/linux/io_uring.d core/sys/linux/link.d \ core/sys/linux/netinet/in_.d core/sys/linux/netinet/tcp.d \ core/sys/linux/perf_event.d core/sys/linux/sched.d \ @@ -953,7 +957,8 @@ DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \ core/sys/linux/sys/socket.d core/sys/linux/sys/sysinfo.d \ core/sys/linux/sys/time.d core/sys/linux/sys/xattr.d \ core/sys/linux/termios.d core/sys/linux/time.d \ - core/sys/linux/timerfd.d core/sys/linux/tipc.d core/sys/linux/unistd.d + core/sys/linux/timerfd.d core/sys/linux/tipc.d core/sys/linux/uinput.d \ + core/sys/linux/unistd.d DRUNTIME_DSOURCES_NETBSD = core/sys/netbsd/dlfcn.d \ core/sys/netbsd/err.d core/sys/netbsd/execinfo.d \ @@ -1331,6 +1336,10 @@ core/thread/types.lo: core/thread/$(am__dirstamp) core/time.lo: core/$(am__dirstamp) core/vararg.lo: core/$(am__dirstamp) core/volatile.lo: core/$(am__dirstamp) +etc/valgrind/$(am__dirstamp): + @$(MKDIR_P) etc/valgrind + @: > etc/valgrind/$(am__dirstamp) +etc/valgrind/valgrind.lo: etc/valgrind/$(am__dirstamp) gcc/$(am__dirstamp): @$(MKDIR_P) gcc @: > gcc/$(am__dirstamp) @@ -1387,6 +1396,8 @@ rt/util/$(am__dirstamp): rt/util/typeinfo.lo: rt/util/$(am__dirstamp) rt/util/utility.lo: rt/util/$(am__dirstamp) core/stdc/libgdruntime_la-errno_.lo: core/stdc/$(am__dirstamp) +etc/valgrind/libgdruntime_la-valgrind_.lo: \ + etc/valgrind/$(am__dirstamp) core/sys/elf/$(am__dirstamp): @$(MKDIR_P) core/sys/elf @: > core/sys/elf/$(am__dirstamp) @@ -1668,6 +1679,8 @@ core/sys/linux/execinfo.lo: core/sys/linux/$(am__dirstamp) core/sys/linux/fcntl.lo: core/sys/linux/$(am__dirstamp) core/sys/linux/fs.lo: core/sys/linux/$(am__dirstamp) core/sys/linux/ifaddrs.lo: core/sys/linux/$(am__dirstamp) +core/sys/linux/input.lo: core/sys/linux/$(am__dirstamp) +core/sys/linux/input_event_codes.lo: core/sys/linux/$(am__dirstamp) core/sys/linux/io_uring.lo: core/sys/linux/$(am__dirstamp) core/sys/linux/link.lo: core/sys/linux/$(am__dirstamp) core/sys/linux/netinet/$(am__dirstamp): @@ -1698,6 +1711,7 @@ core/sys/linux/termios.lo: core/sys/linux/$(am__dirstamp) core/sys/linux/time.lo: core/sys/linux/$(am__dirstamp) core/sys/linux/timerfd.lo: core/sys/linux/$(am__dirstamp) core/sys/linux/tipc.lo: core/sys/linux/$(am__dirstamp) +core/sys/linux/uinput.lo: core/sys/linux/$(am__dirstamp) core/sys/linux/unistd.lo: core/sys/linux/$(am__dirstamp) core/sys/windows/$(am__dirstamp): @$(MKDIR_P) core/sys/windows @@ -1951,6 +1965,8 @@ libgdruntime.la: $(libgdruntime_la_OBJECTS) $(libgdruntime_la_DEPENDENCIES) $(EX $(AM_V_GEN)$(libgdruntime_la_LINK) -rpath $(toolexeclibdir) $(libgdruntime_la_OBJECTS) $(libgdruntime_la_LIBADD) $(LIBS) core/stdc/libgdruntime_convenience_la-errno_.lo: \ core/stdc/$(am__dirstamp) +etc/valgrind/libgdruntime_convenience_la-valgrind_.lo: \ + etc/valgrind/$(am__dirstamp) config/mingw/libgdruntime_convenience_la-msvc.lo: \ config/mingw/$(am__dirstamp) config/aarch64/libgdruntime_convenience_la-switchcontext.lo: \ @@ -2077,6 +2093,8 @@ mostlyclean-compile: -rm -f core/sys/windows/stdc/*.lo -rm -f core/thread/*.$(OBJEXT) -rm -f core/thread/*.lo + -rm -f etc/valgrind/*.$(OBJEXT) + -rm -f etc/valgrind/*.lo -rm -f gcc/*.$(OBJEXT) -rm -f gcc/*.lo -rm -f gcc/sections/*.$(OBJEXT) @@ -2160,12 +2178,18 @@ config/s390/libgdruntime_convenience_la-get_tls_offset.lo: config/s390/get_tls_o core/stdc/libgdruntime_la-errno_.lo: core/stdc/errno_.c $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c +etc/valgrind/libgdruntime_la-valgrind_.lo: etc/valgrind/valgrind_.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o etc/valgrind/libgdruntime_la-valgrind_.lo `test -f 'etc/valgrind/valgrind_.c' || echo '$(srcdir)/'`etc/valgrind/valgrind_.c + config/mingw/libgdruntime_la-msvc.lo: config/mingw/msvc.c $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/mingw/libgdruntime_la-msvc.lo `test -f 'config/mingw/msvc.c' || echo '$(srcdir)/'`config/mingw/msvc.c core/stdc/libgdruntime_convenience_la-errno_.lo: core/stdc/errno_.c $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o core/stdc/libgdruntime_convenience_la-errno_.lo `test -f 'core/stdc/errno_.c' || echo '$(srcdir)/'`core/stdc/errno_.c +etc/valgrind/libgdruntime_convenience_la-valgrind_.lo: etc/valgrind/valgrind_.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o etc/valgrind/libgdruntime_convenience_la-valgrind_.lo `test -f 'etc/valgrind/valgrind_.c' || echo '$(srcdir)/'`etc/valgrind/valgrind_.c + config/mingw/libgdruntime_convenience_la-msvc.lo: config/mingw/msvc.c $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgdruntime_convenience_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/mingw/libgdruntime_convenience_la-msvc.lo `test -f 'config/mingw/msvc.c' || echo '$(srcdir)/'`config/mingw/msvc.c @@ -2225,6 +2249,7 @@ clean-libtool: -rm -rf core/sys/windows/.libs core/sys/windows/_libs -rm -rf core/sys/windows/stdc/.libs core/sys/windows/stdc/_libs -rm -rf core/thread/.libs core/thread/_libs + -rm -rf etc/valgrind/.libs etc/valgrind/_libs -rm -rf gcc/.libs gcc/_libs -rm -rf gcc/sections/.libs gcc/sections/_libs -rm -rf gcc/unwind/.libs gcc/unwind/_libs @@ -2387,6 +2412,7 @@ distclean-generic: -rm -f core/sys/windows/$(am__dirstamp) -rm -f core/sys/windows/stdc/$(am__dirstamp) -rm -f core/thread/$(am__dirstamp) + -rm -f etc/valgrind/$(am__dirstamp) -rm -f gcc/$(am__dirstamp) -rm -f gcc/sections/$(am__dirstamp) -rm -f gcc/unwind/$(am__dirstamp) diff --git a/libphobos/libdruntime/core/atomic.d b/libphobos/libdruntime/core/atomic.d index 5a7d00c38db..ff7f7abf0c2 100644 --- a/libphobos/libdruntime/core/atomic.d +++ b/libphobos/libdruntime/core/atomic.d @@ -85,7 +85,7 @@ enum MemoryOrder * Returns: * The value of 'val'. */ -T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(ref return scope const T val) pure nothrow @nogc @trusted +T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(auto ref return scope const T val) pure nothrow @nogc @trusted if (!is(T == shared U, U) && !is(T == shared inout U, U) && !is(T == shared const U, U)) { static if (__traits(isFloating, T)) @@ -99,7 +99,7 @@ T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(ref return scope const T val) } /// Ditto -T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(ref return scope shared const T val) pure nothrow @nogc @trusted +T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(auto ref return scope shared const T val) pure nothrow @nogc @trusted if (!hasUnsharedIndirections!T) { import core.internal.traits : hasUnsharedIndirections; @@ -109,7 +109,7 @@ T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(ref return scope shared const } /// Ditto -TailShared!T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(ref shared const T val) pure nothrow @nogc @trusted +TailShared!T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(auto ref shared const T val) pure nothrow @nogc @trusted if (hasUnsharedIndirections!T) { // HACK: DEPRECATE THIS FUNCTION, IT IS INVALID TO DO ATOMIC LOAD OF SHARED CLASS @@ -1203,7 +1203,7 @@ version (CoreUnittest) } } - @betterC pure nothrow @nogc @safe unittest // issue 16651 + @betterC pure nothrow @nogc @safe unittest // https://issues.dlang.org/show_bug.cgi?id=16651 { shared ulong a = 2; uint b = 1; @@ -1216,7 +1216,7 @@ version (CoreUnittest) assert(c == 1); } - pure nothrow @safe unittest // issue 16230 + pure nothrow @safe unittest // https://issues.dlang.org/show_bug.cgi?id=16230 { shared int i; static assert(is(typeof(atomicLoad(i)) == int)); diff --git a/libphobos/libdruntime/core/internal/array/concatenation.d b/libphobos/libdruntime/core/internal/array/concatenation.d index ff777a6b3ab..4a05b50fcff 100644 --- a/libphobos/libdruntime/core/internal/array/concatenation.d +++ b/libphobos/libdruntime/core/internal/array/concatenation.d @@ -19,6 +19,7 @@ module core.internal.array.concatenation; */ Tret _d_arraycatnTX(Tret, Tarr...)(auto ref Tarr froms) @trusted { + import core.internal.array.capacity : _d_arraysetlengthTImpl; import core.internal.traits : hasElaborateCopyConstructor, Unqual; import core.lifetime : copyEmplace; import core.stdc.string : memcpy; @@ -38,7 +39,21 @@ Tret _d_arraycatnTX(Tret, Tarr...)(auto ref Tarr froms) @trusted if (totalLen == 0) return res; - res.length = totalLen; + + // We cannot use this, because it refuses to work if the array type has disabled default construction. + // res.length = totalLen; + // Call the runtime function directly instead. + // TODO: once `__arrayAlloc` is templated, call that instead. + version (D_ProfileGC) + { + // TODO: forward file, line, name from _d_arraycatnTXTrace + _d_arraysetlengthTImpl!(typeof(res))._d_arraysetlengthTTrace( + __FILE__, __LINE__, "_d_arraycatnTX", res, totalLen); + } + else + { + _d_arraysetlengthTImpl!(typeof(res))._d_arraysetlengthT(res, totalLen); + } /* Currently, if both a postblit and a cpctor are defined, the postblit is * used. If this changes, the condition below will have to be adapted. diff --git a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d index 62ce941e393..39cd30aee16 100644 --- a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d +++ b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d @@ -26,6 +26,7 @@ module core.internal.gc.impl.conservative.gc; //debug = INVARIANT; // enable invariants //debug = PROFILE_API; // profile API calls for config.profile > 1 //debug = GC_RECURSIVE_LOCK; // check for recursive locking on the same thread +//debug = VALGRIND; // Valgrind memcheck integration /***************************************************/ version = COLLECT_PARALLEL; // parallel scanning @@ -52,6 +53,8 @@ version (GNU) import gcc.builtins; debug (PRINTF_TO_FILE) import core.stdc.stdio : sprintf, fprintf, fopen, fflush, FILE; else import core.stdc.stdio : sprintf, printf; // needed to output profiling results +debug (VALGRIND) import etc.valgrind.valgrind; + import core.time; alias currTime = MonoTime.currTime; @@ -90,7 +93,7 @@ private int rt_hasFinalizerInSegment(void* p, size_t size, uint attr, const scope void[] segment) nothrow; // Declared as an extern instead of importing core.exception - // to avoid inlining - see issue 13725. + // to avoid inlining - see https://issues.dlang.org/show_bug.cgi?id=13725. void onInvalidMemoryOperationError(void* pretend_sideffect = null) @trusted pure nothrow @nogc; void onOutOfMemoryErrorNoGC() @trusted nothrow @nogc; @@ -480,6 +483,8 @@ class ConservativeGC : GC auto p = runLocked!(mallocNoSync, mallocTime, numMallocs)(size, bits, localAllocSize, ti); + invalidate(p[0 .. localAllocSize], 0xF0, true); + if (!(bits & BlkAttr.NO_SCAN)) { memset(p + size, 0, localAllocSize - size); @@ -567,6 +572,9 @@ class ConservativeGC : GC auto p = runLocked!(mallocNoSync, mallocTime, numMallocs)(size, bits, localAllocSize, ti); + debug (VALGRIND) makeMemUndefined(p[0..size]); + invalidate((p + size)[0 .. localAllocSize - size], 0xF0, true); + memset(p, 0, size); if (!(bits & BlkAttr.NO_SCAN)) { @@ -688,7 +696,7 @@ class ConservativeGC : GC else if (newsz < psz) { // Shrink in place - debug (MEMSTOMP) memset(p + size, 0xF2, psize - size); + invalidate((p + size)[0 .. psize - size], 0xF2, false); lpool.freePages(pagenum + newsz, psz - newsz); lpool.mergeFreePageOffsets!(false, true)(pagenum + newsz, psz - newsz); lpool.bPageOffsets[pagenum] = cast(uint) newsz; @@ -704,7 +712,7 @@ class ConservativeGC : GC if (freesz < newPages) return doMalloc(); // free range too small - debug (MEMSTOMP) memset(p + psize, 0xF0, size - psize); + invalidate((p + psize)[0 .. size - psize], 0xF0, true); debug (PRINTF) printFreeInfo(pool); memset(&lpool.pagetable[pagenum + psz], Bins.B_PAGEPLUS, newPages); lpool.bPageOffsets[pagenum] = cast(uint) newsz; @@ -795,7 +803,7 @@ class ConservativeGC : GC if (freesz < minsz) return 0; size_t sz = freesz > maxsz ? maxsz : freesz; - debug (MEMSTOMP) memset(pool.baseAddr + (pagenum + psz) * PAGESIZE, 0xF0, sz * PAGESIZE); + invalidate((pool.baseAddr + (pagenum + psz) * PAGESIZE)[0 .. sz * PAGESIZE], 0xF0, true); memset(lpool.pagetable + pagenum + psz, Bins.B_PAGEPLUS, sz); lpool.bPageOffsets[pagenum] = cast(uint) (psz + sz); for (auto offset = psz; offset < psz + sz; offset++) @@ -911,7 +919,7 @@ class ConservativeGC : GC size_t npages = lpool.bPageOffsets[pagenum]; auto size = npages * PAGESIZE; ssize = sentinel_size(q, size); - debug (MEMSTOMP) memset(p, 0xF2, size); + invalidate(p[0 .. size], 0xF2, false); lpool.freePages(pagenum, npages); lpool.mergeFreePageOffsets!(true, true)(pagenum, npages); } @@ -925,13 +933,13 @@ class ConservativeGC : GC auto size = binsize[bin]; ssize = sentinel_size(q, size); - debug (MEMSTOMP) memset(p, 0xF2, size); + invalidate(p[0 .. size], 0xF2, false); // in case the page hasn't been recovered yet, don't add the object to the free list if (!gcx.recoverPool[bin] || pool.binPageChain[pagenum] == Pool.PageRecovered) { - list.next = gcx.bucket[bin]; - list.pool = pool; + undefinedWrite(list.next, gcx.bucket[bin]); + undefinedWrite(list.pool, pool); gcx.bucket[bin] = list; } pool.freebits.set(biti); @@ -1965,8 +1973,8 @@ struct Gcx assert(p !is null); L_hasBin: // Return next item from free list - bucket[bin] = (cast(List*)p).next; - auto pool = (cast(List*)p).pool; + bucket[bin] = undefinedRead((cast(List*)p).next); + auto pool = undefinedRead((cast(List*)p).pool); auto biti = (p - pool.baseAddr) >> pool.shiftBy; assert(pool.freebits.test(biti)); @@ -1976,7 +1984,7 @@ struct Gcx if (bits) pool.setBits(biti, bits); //debug(PRINTF) printf("\tmalloc => %p\n", p); - debug (MEMSTOMP) memset(p, 0xF0, alloc_size); + invalidate(p[0 .. alloc_size], 0xF0, true); if (ConservativeGC.isPrecise) { @@ -2059,7 +2067,7 @@ struct Gcx auto p = pool.baseAddr + pn * PAGESIZE; debug(PRINTF) printf("Got large alloc: %p, pt = %d, np = %d\n", p, pool.pagetable[pn], npages); - debug (MEMSTOMP) memset(p, 0xF1, size); + invalidate(p[0 .. size], 0xF1, true); alloc_size = npages * PAGESIZE; //debug(PRINTF) printf("\tp = %p\n", p); @@ -2241,6 +2249,7 @@ struct Gcx immutable ncap = _cap ? 2 * _cap : initSize / RANGE.sizeof; auto p = cast(RANGE*)os_mem_map(ncap * RANGE.sizeof); if (p is null) onOutOfMemoryErrorNoGC(); + debug (VALGRIND) makeMemUndefined(p[0..ncap]); if (_p !is null) { p[0 .. _length] = _p[0 .. _length]; @@ -2295,7 +2304,8 @@ struct Gcx for (;;) { - auto p = *cast(void**)(rng.pbot); + auto p = undefinedRead(*cast(void**)(rng.pbot)); + debug (VALGRIND) makeMemDefined((&p)[0 .. 1]); debug(MARK_PRINTF) printf("\tmark %p: %p\n", rng.pbot, p); @@ -2525,6 +2535,7 @@ struct Gcx for (auto p = cast(void**)pbot; cast(void*)p < ptop; p++) { auto ptr = *p; + debug (VALGRIND) makeMemDefined((&ptr)[0 .. 1]); if (cast(size_t)(ptr - minAddr) < memSize) toscanRoots.push(ptr); } @@ -2650,7 +2661,7 @@ struct Gcx pool.freepages += npages; numFree += npages; - debug (MEMSTOMP) memset(p, 0xF3, npages * PAGESIZE); + invalidate(p[0 .. npages * PAGESIZE], 0xF3, false); // Don't need to update searchStart here because // pn is guaranteed to be greater than last time // we updated it. @@ -2765,7 +2776,7 @@ struct Gcx debug(COLLECT_PRINTF) printf("\tcollecting %p\n", p); leakDetector.log_free(q, sentinel_size(q, size)); - debug (MEMSTOMP) memset(p, 0xF3, size); + invalidate(p[0 .. size], 0xF3, false); } } } @@ -2830,11 +2841,11 @@ struct Gcx if (!core.bitop.bt(freebitsdata, u / 16)) continue; auto elem = cast(List *)(p + u); - elem.pool = &pool.base; - *bucketTail = elem; + undefinedWrite(elem.pool, &pool.base); + undefinedWrite(*bucketTail, elem); bucketTail = &elem.next; } - *bucketTail = null; + undefinedWrite(*bucketTail, null); assert(bucket[bin] !is null); return true; } @@ -3572,6 +3583,7 @@ struct Pool //debug(PRINTF) printf("Pool::Pool(%u)\n", npages); poolsize = npages * PAGESIZE; baseAddr = cast(byte *)os_mem_map(poolsize); + version (VALGRIND) makeMemNoAccess(baseAddr[0..poolsize]); // Some of the code depends on page alignment of memory pools assert((cast(size_t)baseAddr & (PAGESIZE - 1)) == 0); @@ -4275,7 +4287,7 @@ struct LargeObjectPool for (; pn + n < npages; ++n) if (pagetable[pn + n] != Bins.B_PAGEPLUS) break; - debug (MEMSTOMP) memset(baseAddr + pn * PAGESIZE, 0xF3, n * PAGESIZE); + invalidate((baseAddr + pn * PAGESIZE)[0 .. n * PAGESIZE], 0xF3, false); freePages(pn, n); mergeFreePageOffsets!(true, true)(pn, n); } @@ -4394,7 +4406,7 @@ struct SmallObjectPool debug(COLLECT_PRINTF) printf("\tcollecting %p\n", p); //log_free(sentinel_add(p)); - debug (MEMSTOMP) memset(p, 0xF3, size); + invalidate(p[0 .. size], 0xF3, false); } if (freeBits) @@ -4431,17 +4443,17 @@ struct SmallObjectPool void* ptop = p + PAGESIZE - 2 * size + 1; for (; p < ptop; p += size) { - (cast(List *)p).next = cast(List *)(p + size); - (cast(List *)p).pool = &base; + undefinedWrite((cast(List *)p).next, cast(List *)(p + size)); + undefinedWrite((cast(List *)p).pool, &base); } - (cast(List *)p).next = null; - (cast(List *)p).pool = &base; + undefinedWrite((cast(List *)p).next, null); + undefinedWrite((cast(List *)p).pool, &base); return first; } } debug(SENTINEL) {} else // no additional capacity with SENTINEL -unittest // bugzilla 14467 +unittest // https://issues.dlang.org/show_bug.cgi?id=14467 { int[] arr = new int[10]; assert(arr.capacity); @@ -4449,7 +4461,7 @@ unittest // bugzilla 14467 assert(arr.capacity); } -unittest // bugzilla 15353 +unittest // https://issues.dlang.org/show_bug.cgi?id=15353 { import core.memory : GC; @@ -4466,7 +4478,7 @@ unittest // bugzilla 15353 GC.collect(); } -unittest // bugzilla 15822 +unittest // https://issues.dlang.org/show_bug.cgi?id=15822 { import core.memory : GC; @@ -4487,7 +4499,7 @@ unittest // bugzilla 15822 GC.collect(); } -unittest // bugzilla 1180 +unittest // https://issues.dlang.org/show_bug.cgi?id=1180 { import core.exception; try @@ -4823,13 +4835,22 @@ debug (SENTINEL) { assert(size <= uint.max); *sentinel_psize(p) = cast(uint)size; - *sentinel_pre(p) = SENTINEL_PRE; - *sentinel_post(p) = SENTINEL_POST; + debug (VALGRIND) + { + makeMemNoAccess(sentinel_pre(p)[0..1]); + makeMemNoAccess(sentinel_post(p)[0..1]); + } + else + { + *sentinel_pre(p) = SENTINEL_PRE; + *sentinel_post(p) = SENTINEL_POST; + } } void sentinel_Invariant(const void *p) nothrow @nogc { + debug (VALGRIND) {} else debug { assert(*sentinel_pre(p) == SENTINEL_PRE); @@ -5063,3 +5084,53 @@ unittest printf("unexpected pointers %p and %p\n", p.ptr, q.ptr); } } + +/* ============================ MEMSTOMP =============================== */ + +/// Mark the specified memory region as uninitialized - +/// reading from this region is an error. +/// If writable is false, writing to it is also an error. +pragma(inline, true) +void invalidate(void[] mem, ubyte pattern, bool writable) nothrow @nogc +{ + debug (MEMSTOMP) memset(mem.ptr, pattern, mem.length); + debug (VALGRIND) + { + if (writable) + makeMemUndefined(mem); + else + makeMemNoAccess(mem); + } +} + +/// Read memory that should otherwise be marked as unreadable +/// (e.g. free lists overlapped with unallocated heap objects). +pragma(inline, true) +T undefinedRead(T)(ref T var) nothrow +{ + debug (VALGRIND) + { + auto varArr = (&var)[0..1]; + disableAddrReportingInRange(varArr); + T result = var; + enableAddrReportingInRange(varArr); + return result; + } + else + return var; +} + +/// Write memory that should otherwise be marked as unwritable. +pragma(inline, true) +void undefinedWrite(T)(ref T var, T value) nothrow +{ + debug (VALGRIND) + { + auto varArr = (&var)[0..1]; + disableAddrReportingInRange(varArr); + var = value; + enableAddrReportingInRange(varArr); + } + else + var = value; +} diff --git a/libphobos/libdruntime/core/internal/gc/proxy.d b/libphobos/libdruntime/core/internal/gc/proxy.d index 695ef061a81..abc8c6ac2ea 100644 --- a/libphobos/libdruntime/core/internal/gc/proxy.d +++ b/libphobos/libdruntime/core/internal/gc/proxy.d @@ -62,8 +62,9 @@ extern (C) { import core.stdc.stdio : fprintf, stderr; import core.stdc.stdlib : exit; + import core.atomic : atomicLoad; - fprintf(stderr, "No GC was initialized, please recheck the name of the selected GC ('%.*s').\n", cast(int)config.gc.length, config.gc.ptr); + fprintf(atomicLoad(stderr), "No GC was initialized, please recheck the name of the selected GC ('%.*s').\n", cast(int)config.gc.length, config.gc.ptr); instanceLock.unlock(); exit(1); @@ -97,7 +98,9 @@ extern (C) { default: import core.stdc.stdio : fprintf, stderr; - fprintf(stderr, "Unknown GC cleanup method, please recheck ('%.*s').\n", + import core.atomic : atomicLoad; + + fprintf(atomicLoad(stderr), "Unknown GC cleanup method, please recheck ('%.*s').\n", cast(int)config.cleanup.length, config.cleanup.ptr); break; case "none": diff --git a/libphobos/libdruntime/core/internal/parseoptions.d b/libphobos/libdruntime/core/internal/parseoptions.d index ed6251f758b..ac0eb826b35 100644 --- a/libphobos/libdruntime/core/internal/parseoptions.d +++ b/libphobos/libdruntime/core/internal/parseoptions.d @@ -146,9 +146,11 @@ private: bool optError(const scope char[] msg, const scope char[] name, const(char)[] errName) { + import core.atomic : atomicLoad; + version (CoreUnittest) if (inUnittest) return false; - fprintf(stderr, "%.*s %.*s option '%.*s'.\n", + fprintf(atomicLoad(stderr), "%.*s %.*s option '%.*s'.\n", cast(int)msg.length, msg.ptr, cast(int)errName.length, errName.ptr, cast(int)name.length, name.ptr); @@ -332,9 +334,11 @@ do bool parseError(const scope char[] exp, const scope char[] opt, const scope char[] got, const(char)[] errName) { + import core.atomic : atomicLoad; + version (CoreUnittest) if (inUnittest) return false; - fprintf(stderr, "Expecting %.*s as argument for %.*s option '%.*s', got '%.*s' instead.\n", + fprintf(atomicLoad(stderr), "Expecting %.*s as argument for %.*s option '%.*s', got '%.*s' instead.\n", cast(int)exp.length, exp.ptr, cast(int)errName.length, errName.ptr, cast(int)opt.length, opt.ptr, @@ -344,9 +348,11 @@ bool parseError(const scope char[] exp, const scope char[] opt, const scope char bool overflowedError(const scope char[] opt, const scope char[] got) { + import core.atomic : atomicLoad; + version (CoreUnittest) if (inUnittest) return false; - fprintf(stderr, "Argument for %.*s option '%.*s' is too big.\n", + fprintf(atomicLoad(stderr), "Argument for %.*s option '%.*s' is too big.\n", cast(int)opt.length, opt.ptr, cast(int)got.length, got.ptr); return false; diff --git a/libphobos/libdruntime/core/lifetime.d b/libphobos/libdruntime/core/lifetime.d index ae047cb730e..89236dbf4c1 100644 --- a/libphobos/libdruntime/core/lifetime.d +++ b/libphobos/libdruntime/core/lifetime.d @@ -364,7 +364,7 @@ T* emplace(T, Args...)(void[] chunk, auto ref Args args) assert(u1.a == "hello"); } -@system unittest // bugzilla 15772 +@system unittest // https://issues.dlang.org/show_bug.cgi?id=15772 { abstract class Foo {} class Bar: Foo {} @@ -2322,7 +2322,7 @@ pure nothrow @nogc @system unittest assert(val == 1); } -// issue 18913 +// https://issues.dlang.org/show_bug.cgi?id=18913 @safe unittest { static struct NoCopy @@ -2454,7 +2454,7 @@ template _d_delstructImpl(T) assert(outerDtors == 1); } -// issue 25552 +// https://issues.dlang.org/show_bug.cgi?id=25552 pure nothrow @system unittest { int i; @@ -2478,7 +2478,7 @@ pure nothrow @system unittest assert(i == 2); } -// issue 25552 +// https://issues.dlang.org/show_bug.cgi?id=25552 @safe unittest { int i; @@ -2527,7 +2527,7 @@ pure nothrow @system unittest assert(i == 6); } -// issue 25552 +// https://issues.dlang.org/show_bug.cgi?id=25552 @safe unittest { int i; diff --git a/libphobos/libdruntime/core/stdc/assert_.d b/libphobos/libdruntime/core/stdc/assert_.d index a8909e26126..d6cb8a608a0 100644 --- a/libphobos/libdruntime/core/stdc/assert_.d +++ b/libphobos/libdruntime/core/stdc/assert_.d @@ -59,7 +59,7 @@ else version (FreeBSD) /*** * Assert failure function in the FreeBSD C library. */ - noreturn __assert(const(char)* exp, const(char)* file, uint line, const(char)* exp); + noreturn __assert(const(char)* func, const(char)* file, uint line, const(char)* exp); } else version (NetBSD) { @@ -67,6 +67,8 @@ else version (NetBSD) * Assert failure function in the NetBSD C library. */ noreturn __assert(const(char)* file, int line, const(char)* exp); + /// + noreturn __assert13(const(char)* file, int line, const(char)* func, const(char)* exp); } else version (OpenBSD) { @@ -75,14 +77,14 @@ else version (OpenBSD) */ noreturn __assert(const(char)* file, int line, const(char)* exp); /// - void __assert2(const(char)* file, int line, const(char)* func, const(char)* exp); + noreturn __assert2(const(char)* file, int line, const(char)* func, const(char)* exp); } else version (DragonFlyBSD) { /*** * Assert failure function in the DragonFlyBSD C library. */ - noreturn __assert(const(char)* exp, const(char)* file, uint line, const(char)* exp); + noreturn __assert(const(char)* func, const(char)* file, uint line, const(char)* exp); } else version (CRuntime_Glibc) { @@ -97,7 +99,12 @@ else version (CRuntime_Glibc) } else version (CRuntime_Bionic) { + /*** + * Assert failure functions in the Bionic library. + */ noreturn __assert(const(char)* __file, int __line, const(char)* __msg); + /// + noreturn __assert2(const(char)* __file, int __line, const(char)* __function, const(char)* __msg); } else version (CRuntime_Musl) { diff --git a/libphobos/libdruntime/core/stdc/wchar_.d b/libphobos/libdruntime/core/stdc/wchar_.d index fe5fce481cd..2d01e2634dc 100644 --- a/libphobos/libdruntime/core/stdc/wchar_.d +++ b/libphobos/libdruntime/core/stdc/wchar_.d @@ -17,6 +17,7 @@ module core.stdc.wchar_; import core.stdc.config; import core.stdc.stdarg; // for va_list import core.stdc.stdio; // for FILE, not exposed per spec +import core.atomic : atomicLoad; public import core.stdc.stddef; // for wchar_t public import core.stdc.time; // for tm public import core.stdc.stdint; // for WCHAR_MIN, WCHAR_MAX @@ -211,9 +212,9 @@ int fputws(const scope wchar_t* s, FILE* stream); extern (D) @trusted { /// - wint_t getwchar() { return fgetwc(stdin); } + wint_t getwchar() { return fgetwc(atomicLoad(stdin)); } /// - wint_t putwchar(wchar_t c) { return fputwc(c,stdout); } + wint_t putwchar(wchar_t c) { return fputwc(c,atomicLoad(stdout)); } } /// diff --git a/libphobos/libdruntime/core/sys/linux/input.d b/libphobos/libdruntime/core/sys/linux/input.d new file mode 100644 index 00000000000..1bf356dca98 --- /dev/null +++ b/libphobos/libdruntime/core/sys/linux/input.d @@ -0,0 +1,236 @@ +module core.sys.linux.input; + +version (linux): +extern(C): +nothrow: + +import core.sys.linux.sys.time; +import core.sys.posix.sys.ioctl; + +public import core.sys.linux.input_event_codes; + +struct input_event +{ + timeval time; + ushort type; + ushort code; + int value; +} + +enum EV_VERSION = 0x010001; + +struct input_id +{ + ushort bustype; + ushort vendor; + ushort product; + ushort version_; +} + +struct input_absinfo +{ + int value; + int minimum; + int maximum; + int fuzz; + int flat; + int resolution; +} + +enum INPUT_KEYMAP_BY_INDEX = (1 << 0); +struct input_keymap_entry +{ + ubyte flags; + ubyte len; + ushort index; + uint keycode; + ubyte[32] scancode; +} + +struct input_mask +{ + uint type; + uint codes_size; + ulong codes_ptr; +} + +enum EVIOCGVERSION = _IOR!int('E', 0x01); +enum EVIOCGID = _IOR!input_id('E', 0x02); +enum EVIOCGREP = _IOR!(uint[2])('E', 0x03); +enum EVIOCSREP = _IOW!(uint[2])('E', 0x03); + +enum EVIOCGKEYCODE = _IOR!(uint[2])('E', 0x04); +enum EVIOCGKEYCODE_V2 = _IOR!input_keymap_entry('E', 0x04); +enum EVIOCSKEYCODE = _IOW!(uint[2])('E', 0x04); +enum EVIOCSKEYCODE_V2 = _IOW!input_keymap_entry('E', 0x04); + +enum EVIOCGNAME(len) = _IOC(_IOC_READ, 'E', 0x06, len); +enum EVIOCGPHYS(len) = _IOC(_IOC_READ, 'E', 0x07, len); +enum EVIOCGUNIQ(len) = _IOC(_IOC_READ, 'E', 0x08, len); +enum EVIOCGPROP(len) = _IOC(_IOC_READ, 'E', 0x09, len); + +enum EVIOCGMTSLOTS(len) = _IOC(_IOC_READ, 'E', 0x0a, len); + +enum EVIOCGKEY(len) = _IOC(_IOC_READ, 'E', 0x18, len); +enum EVIOCGLED(len) = _IOC(_IOC_READ, 'E', 0x19, len); +enum EVIOCGSND(len) = _IOC(_IOC_READ, 'E', 0x1a, len); +enum EVIOCGSW(len) = _IOC(_IOC_READ, 'E', 0x1b, len); + +enum EVIOCGBIT(ev,len) = _IOC(_IOC_READ, 'E', 0x20 + (ev), len); +enum EVIOCGABS(abs) = _IOR!input_absinfo('E', 0x40 + (abs)); +enum EVIOCSABS(abs) = _IOW!input_absinfo('E', 0xc0 + (abs)); + +enum EVIOCSFF = _IOW!ff_effect('E', 0x80); +enum EVIOCRMFF = _IOW!int('E', 0x81); +enum EVIOCGEFFECTS = _IOR!int('E', 0x84); + +enum EVIOCGRAB = _IOW!int('E', 0x90); +enum EVIOCREVOKE = _IOW!int('E', 0x91); + +enum EVIOCGMASK = _IOR!input_mask('E', 0x92); + +enum EVIOCSMASK = _IOW!input_mask('E', 0x93); + +enum EVIOCSCLOCKID = _IOW!int('E', 0xa0); + +enum ID_BUS = 0; +enum ID_VENDOR = 1; +enum ID_PRODUCT = 2; +enum ID_VERSION = 3; + +enum BUS_PCI = 0x01; +enum BUS_ISAPNP = 0x02; +enum BUS_USB = 0x03; +enum BUS_HIL = 0x04; +enum BUS_BLUETOOTH = 0x05; +enum BUS_VIRTUAL = 0x06; + +enum BUS_ISA = 0x10; +enum BUS_I8042 = 0x11; +enum BUS_XTKBD = 0x12; +enum BUS_RS232 = 0x13; +enum BUS_GAMEPORT = 0x14; +enum BUS_PARPORT = 0x15; +enum BUS_AMIGA = 0x16; +enum BUS_ADB = 0x17; +enum BUS_I2C = 0x18; +enum BUS_HOST = 0x19; +enum BUS_GSC = 0x1A; +enum BUS_ATARI = 0x1B; +enum BUS_SPI = 0x1C; +enum BUS_RMI = 0x1D; +enum BUS_CEC = 0x1E; +enum BUS_INTEL_ISHTP = 0x1F; + +enum MT_TOOL_FINGER = 0; +enum MT_TOOL_PEN = 1; +enum MT_TOOL_PALM = 2; +enum MT_TOOL_MAX = 2; + +enum FF_STATUS_STOPPED = 0x00; +enum FF_STATUS_PLAYING = 0x01; +enum FF_STATUS_MAX = 0x01; + +struct ff_replay { + ushort length; + ushort delay; +}; + +struct ff_trigger { + ushort button; + ushort interval; +}; + +struct ff_envelope { + ushort attack_length; + ushort attack_level; + ushort fade_length; + ushort fade_level; +}; + +struct ff_constant_effect { + short level; + ff_envelope envelope; +}; + +struct ff_ramp_effect { + short start_level; + short end_level; + ff_envelope envelope; +}; + +struct ff_condition_effect { + ushort right_saturation; + ushort left_saturation; + + short right_coeff; + short left_coeff; + + ushort deadband; + short center; +}; + +struct ff_periodic_effect { + ushort waveform; + ushort period; + short magnitude; + short offset; + ushort phase; + + ff_envelope envelope; + + uint custom_len; + short *custom_data; +}; + +struct ff_rumble_effect { + ushort strong_magnitude; + ushort weak_magnitude; +}; + +struct ff_effect { + ushort type; + short id; + ushort direction; + ff_trigger trigger; + ff_replay replay; + + union U { + ff_constant_effect constant; + ff_ramp_effect ramp; + ff_periodic_effect periodic; + ff_condition_effect[2] condition; + ff_rumble_effect rumble; + } + U u; +}; + +enum FF_RUMBLE = 0x50; +enum FF_PERIODIC = 0x51; +enum FF_CONSTANT = 0x52; +enum FF_SPRING = 0x53; +enum FF_FRICTION = 0x54; +enum FF_DAMPER = 0x55; +enum FF_INERTIA = 0x56; +enum FF_RAMP = 0x57; + +enum FF_EFFECT_MIN = FF_RUMBLE; +enum FF_EFFECT_MAX = FF_RAMP; + +enum FF_SQUARE = 0x58; +enum FF_TRIANGLE = 0x59; +enum FF_SINE = 0x5a; +enum FF_SAW_UP = 0x5b; +enum FF_SAW_DOWN = 0x5c; +enum FF_CUSTOM = 0x5d; + +enum FF_WAVEFORM_MIN = FF_SQUARE; +enum FF_WAVEFORM_MAX = FF_CUSTOM; + +enum FF_GAIN = 0x60; +enum FF_AUTOCENTER = 0x61; + +enum FF_MAX_EFFECTS = FF_GAIN; + +enum FF_MAX = 0x7f; +enum FF_CNT = (FF_MAX+1); diff --git a/libphobos/libdruntime/core/sys/linux/input_event_codes.d b/libphobos/libdruntime/core/sys/linux/input_event_codes.d new file mode 100644 index 00000000000..3ebda69fd07 --- /dev/null +++ b/libphobos/libdruntime/core/sys/linux/input_event_codes.d @@ -0,0 +1,758 @@ +module core.sys.linux.input_event_codes; + +version (linux): +extern(C): +nothrow: + +enum INPUT_PROP_POINTER = 0x00; +enum INPUT_PROP_DIRECT = 0x01; +enum INPUT_PROP_BUTTONPAD = 0x02; +enum INPUT_PROP_SEMI_MT = 0x03; +enum INPUT_PROP_TOPBUTTONPAD = 0x04; +enum INPUT_PROP_POINTING_STICK = 0x05; +enum INPUT_PROP_ACCELEROMETER = 0x06; + +enum INPUT_PROP_MAX = 0x1f; +enum INPUT_PROP_CNT = (INPUT_PROP_MAX + 1); + +enum EV_SYN = 0x00; +enum EV_KEY = 0x01; +enum EV_REL = 0x02; +enum EV_ABS = 0x03; +enum EV_MSC = 0x04; +enum EV_SW = 0x05; +enum EV_LED = 0x11; +enum EV_SND = 0x12; +enum EV_REP = 0x14; +enum EV_FF = 0x15; +enum EV_PWR = 0x16; +enum EV_FF_STATUS = 0x17; +enum EV_MAX = 0x1f; +enum EV_CNT = (EV_MAX+1); + +enum SYN_REPORT = 0; +enum SYN_CONFIG = 1; +enum SYN_MT_REPORT = 2; +enum SYN_DROPPED = 3; +enum SYN_MAX = 0xf; +enum SYN_CNT = (SYN_MAX+1); + +enum KEY_RESERVED = 0; +enum KEY_ESC = 1; +enum KEY_1 = 2; +enum KEY_2 = 3; +enum KEY_3 = 4; +enum KEY_4 = 5; +enum KEY_5 = 6; +enum KEY_6 = 7; +enum KEY_7 = 8; +enum KEY_8 = 9; +enum KEY_9 = 10; +enum KEY_0 = 11; +enum KEY_MINUS = 12; +enum KEY_EQUAL = 13; +enum KEY_BACKSPACE = 14; +enum KEY_TAB = 15; +enum KEY_Q = 16; +enum KEY_W = 17; +enum KEY_E = 18; +enum KEY_R = 19; +enum KEY_T = 20; +enum KEY_Y = 21; +enum KEY_U = 22; +enum KEY_I = 23; +enum KEY_O = 24; +enum KEY_P = 25; +enum KEY_LEFTBRACE = 26; +enum KEY_RIGHTBRACE = 27; +enum KEY_ENTER = 28; +enum KEY_LEFTCTRL = 29; +enum KEY_A = 30; +enum KEY_S = 31; +enum KEY_D = 32; +enum KEY_F = 33; +enum KEY_G = 34; +enum KEY_H = 35; +enum KEY_J = 36; +enum KEY_K = 37; +enum KEY_L = 38; +enum KEY_SEMICOLON = 39; +enum KEY_APOSTROPHE = 40; +enum KEY_GRAVE = 41; +enum KEY_LEFTSHIFT = 42; +enum KEY_BACKSLASH = 43; +enum KEY_Z = 44; +enum KEY_X = 45; +enum KEY_C = 46; +enum KEY_V = 47; +enum KEY_B = 48; +enum KEY_N = 49; +enum KEY_M = 50; +enum KEY_COMMA = 51; +enum KEY_DOT = 52; +enum KEY_SLASH = 53; +enum KEY_RIGHTSHIFT = 54; +enum KEY_KPASTERISK = 55; +enum KEY_LEFTALT = 56; +enum KEY_SPACE = 57; +enum KEY_CAPSLOCK = 58; +enum KEY_F1 = 59; +enum KEY_F2 = 60; +enum KEY_F3 = 61; +enum KEY_F4 = 62; +enum KEY_F5 = 63; +enum KEY_F6 = 64; +enum KEY_F7 = 65; +enum KEY_F8 = 66; +enum KEY_F9 = 67; +enum KEY_F10 = 68; +enum KEY_NUMLOCK = 69; +enum KEY_SCROLLLOCK = 70; +enum KEY_KP7 = 71; +enum KEY_KP8 = 72; +enum KEY_KP9 = 73; +enum KEY_KPMINUS = 74; +enum KEY_KP4 = 75; +enum KEY_KP5 = 76; +enum KEY_KP6 = 77; +enum KEY_KPPLUS = 78; +enum KEY_KP1 = 79; +enum KEY_KP2 = 80; +enum KEY_KP3 = 81; +enum KEY_KP0 = 82; +enum KEY_KPDOT = 83; + +enum KEY_ZENKAKUHANKAKU = 85; +enum KEY_102ND = 86; +enum KEY_F11 = 87; +enum KEY_F12 = 88; +enum KEY_RO = 89; +enum KEY_KATAKANA = 90; +enum KEY_HIRAGANA = 91; +enum KEY_HENKAN = 92; +enum KEY_KATAKANAHIRAGANA = 93; +enum KEY_MUHENKAN = 94; +enum KEY_KPJPCOMMA = 95; +enum KEY_KPENTER = 96; +enum KEY_RIGHTCTRL = 97; +enum KEY_KPSLASH = 98; +enum KEY_SYSRQ = 99; +enum KEY_RIGHTALT = 100; +enum KEY_LINEFEED = 101; +enum KEY_HOME = 102; +enum KEY_UP = 103; +enum KEY_PAGEUP = 104; +enum KEY_LEFT = 105; +enum KEY_RIGHT = 106; +enum KEY_END = 107; +enum KEY_DOWN = 108; +enum KEY_PAGEDOWN = 109; +enum KEY_INSERT = 110; +enum KEY_DELETE = 111; +enum KEY_MACRO = 112; +enum KEY_MUTE = 113; +enum KEY_VOLUMEDOWN = 114; +enum KEY_VOLUMEUP = 115; +enum KEY_POWER = 116; +enum KEY_KPEQUAL = 117; +enum KEY_KPPLUSMINUS = 118; +enum KEY_PAUSE = 119; +enum KEY_SCALE = 120; + +enum KEY_KPCOMMA = 121; +enum KEY_HANGEUL = 122; +enum KEY_HANGUEL = KEY_HANGEUL; +enum KEY_HANJA = 123; +enum KEY_YEN = 124; +enum KEY_LEFTMETA = 125; +enum KEY_RIGHTMETA = 126; +enum KEY_COMPOSE = 127; + +enum KEY_STOP = 128; +enum KEY_AGAIN = 129; +enum KEY_PROPS = 130; +enum KEY_UNDO = 131; +enum KEY_FRONT = 132; +enum KEY_COPY = 133; +enum KEY_OPEN = 134; +enum KEY_PASTE = 135; +enum KEY_FIND = 136; +enum KEY_CUT = 137; +enum KEY_HELP = 138; +enum KEY_MENU = 139; +enum KEY_CALC = 140; +enum KEY_SETUP = 141; +enum KEY_SLEEP = 142; +enum KEY_WAKEUP = 143; +enum KEY_FILE = 144; +enum KEY_SENDFILE = 145; +enum KEY_DELETEFILE = 146; +enum KEY_XFER = 147; +enum KEY_PROG1 = 148; +enum KEY_PROG2 = 149; +enum KEY_WWW = 150; +enum KEY_MSDOS = 151; +enum KEY_COFFEE = 152; +enum KEY_SCREENLOCK = KEY_COFFEE; +enum KEY_ROTATE_DISPLAY = 153; +enum KEY_DIRECTION = KEY_ROTATE_DISPLAY; +enum KEY_CYCLEWINDOWS = 154; +enum KEY_MAIL = 155; +enum KEY_BOOKMARKS = 156; +enum KEY_COMPUTER = 157; +enum KEY_BACK = 158; +enum KEY_FORWARD = 159; +enum KEY_CLOSECD = 160; +enum KEY_EJECTCD = 161; +enum KEY_EJECTCLOSECD = 162; +enum KEY_NEXTSONG = 163; +enum KEY_PLAYPAUSE = 164; +enum KEY_PREVIOUSSONG = 165; +enum KEY_STOPCD = 166; +enum KEY_RECORD = 167; +enum KEY_REWIND = 168; +enum KEY_PHONE = 169; +enum KEY_ISO = 170; +enum KEY_CONFIG = 171; +enum KEY_HOMEPAGE = 172; +enum KEY_REFRESH = 173; +enum KEY_EXIT = 174; +enum KEY_MOVE = 175; +enum KEY_EDIT = 176; +enum KEY_SCROLLUP = 177; +enum KEY_SCROLLDOWN = 178; +enum KEY_KPLEFTPAREN = 179; +enum KEY_KPRIGHTPAREN = 180; +enum KEY_NEW = 181; +enum KEY_REDO = 182; + +enum KEY_F13 = 183; +enum KEY_F14 = 184; +enum KEY_F15 = 185; +enum KEY_F16 = 186; +enum KEY_F17 = 187; +enum KEY_F18 = 188; +enum KEY_F19 = 189; +enum KEY_F20 = 190; +enum KEY_F21 = 191; +enum KEY_F22 = 192; +enum KEY_F23 = 193; +enum KEY_F24 = 194; + +enum KEY_PLAYCD = 200; +enum KEY_PAUSECD = 201; +enum KEY_PROG3 = 202; +enum KEY_PROG4 = 203; +enum KEY_DASHBOARD = 204; +enum KEY_SUSPEND = 205; +enum KEY_CLOSE = 206; +enum KEY_PLAY = 207; +enum KEY_FASTFORWARD = 208; +enum KEY_BASSBOOST = 209; +enum KEY_PRINT = 210; +enum KEY_HP = 211; +enum KEY_CAMERA = 212; +enum KEY_SOUND = 213; +enum KEY_QUESTION = 214; +enum KEY_EMAIL = 215; +enum KEY_CHAT = 216; +enum KEY_SEARCH = 217; +enum KEY_CONNECT = 218; +enum KEY_FINANCE = 219; +enum KEY_SPORT = 220; +enum KEY_SHOP = 221; +enum KEY_ALTERASE = 222; +enum KEY_CANCEL = 223; +enum KEY_BRIGHTNESSDOWN = 224; +enum KEY_BRIGHTNESSUP = 225; +enum KEY_MEDIA = 226; + +enum KEY_SWITCHVIDEOMODE = 227; +enum KEY_KBDILLUMTOGGLE = 228; +enum KEY_KBDILLUMDOWN = 229; +enum KEY_KBDILLUMUP = 230; + +enum KEY_SEND = 231; +enum KEY_REPLY = 232; +enum KEY_FORWARDMAIL = 233; +enum KEY_SAVE = 234; +enum KEY_DOCUMENTS = 235; + +enum KEY_BATTERY = 236; + +enum KEY_BLUETOOTH = 237; +enum KEY_WLAN = 238; +enum KEY_UWB = 239; + +enum KEY_UNKNOWN = 240; + +enum KEY_VIDEO_NEXT = 241; +enum KEY_VIDEO_PREV = 242; +enum KEY_BRIGHTNESS_CYCLE = 243; +enum KEY_BRIGHTNESS_AUTO = 244; +enum KEY_BRIGHTNESS_ZERO = KEY_BRIGHTNESS_AUTO; +enum KEY_DISPLAY_OFF = 245; + +enum KEY_WWAN = 246; +enum KEY_WIMAX = KEY_WWAN; +enum KEY_RFKILL = 247; + +enum KEY_MICMUTE = 248; + +enum BTN_MISC = 0x100; +enum BTN_0 = 0x100; +enum BTN_1 = 0x101; +enum BTN_2 = 0x102; +enum BTN_3 = 0x103; +enum BTN_4 = 0x104; +enum BTN_5 = 0x105; +enum BTN_6 = 0x106; +enum BTN_7 = 0x107; +enum BTN_8 = 0x108; +enum BTN_9 = 0x109; + +enum BTN_MOUSE = 0x110; +enum BTN_LEFT = 0x110; +enum BTN_RIGHT = 0x111; +enum BTN_MIDDLE = 0x112; +enum BTN_SIDE = 0x113; +enum BTN_EXTRA = 0x114; +enum BTN_FORWARD = 0x115; +enum BTN_BACK = 0x116; +enum BTN_TASK = 0x117; + +enum BTN_JOYSTICK = 0x120; +enum BTN_TRIGGER = 0x120; +enum BTN_THUMB = 0x121; +enum BTN_THUMB2 = 0x122; +enum BTN_TOP = 0x123; +enum BTN_TOP2 = 0x124; +enum BTN_PINKIE = 0x125; +enum BTN_BASE = 0x126; +enum BTN_BASE2 = 0x127; +enum BTN_BASE3 = 0x128; +enum BTN_BASE4 = 0x129; +enum BTN_BASE5 = 0x12a; +enum BTN_BASE6 = 0x12b; +enum BTN_DEAD = 0x12f; + +enum BTN_GAMEPAD = 0x130; +enum BTN_SOUTH = 0x130; +enum BTN_A = BTN_SOUTH; +enum BTN_EAST = 0x131; +enum BTN_B = BTN_EAST; +enum BTN_C = 0x132; +enum BTN_NORTH = 0x133; +enum BTN_X = BTN_NORTH; +enum BTN_WEST = 0x134; +enum BTN_Y = BTN_WEST; +enum BTN_Z = 0x135; +enum BTN_TL = 0x136; +enum BTN_TR = 0x137; +enum BTN_TL2 = 0x138; +enum BTN_TR2 = 0x139; +enum BTN_SELECT = 0x13a; +enum BTN_START = 0x13b; +enum BTN_MODE = 0x13c; +enum BTN_THUMBL = 0x13d; +enum BTN_THUMBR = 0x13e; + +enum BTN_DIGI = 0x140; +enum BTN_TOOL_PEN = 0x140; +enum BTN_TOOL_RUBBER = 0x141; +enum BTN_TOOL_BRUSH = 0x142; +enum BTN_TOOL_PENCIL = 0x143; +enum BTN_TOOL_AIRBRUSH = 0x144; +enum BTN_TOOL_FINGER = 0x145; +enum BTN_TOOL_MOUSE = 0x146; +enum BTN_TOOL_LENS = 0x147; +enum BTN_TOOL_QUINTTAP = 0x148; +enum BTN_STYLUS3 = 0x149; +enum BTN_TOUCH = 0x14a; +enum BTN_STYLUS = 0x14b; +enum BTN_STYLUS2 = 0x14c; +enum BTN_TOOL_DOUBLETAP = 0x14d; +enum BTN_TOOL_TRIPLETAP = 0x14e; +enum BTN_TOOL_QUADTAP = 0x14f; + +enum BTN_WHEEL = 0x150; +enum BTN_GEAR_DOWN = 0x150; +enum BTN_GEAR_UP = 0x151; + +enum KEY_OK = 0x160; +enum KEY_SELECT = 0x161; +enum KEY_GOTO = 0x162; +enum KEY_CLEAR = 0x163; +enum KEY_POWER2 = 0x164; +enum KEY_OPTION = 0x165; +enum KEY_INFO = 0x166; +enum KEY_TIME = 0x167; +enum KEY_VENDOR = 0x168; +enum KEY_ARCHIVE = 0x169; +enum KEY_PROGRAM = 0x16a; +enum KEY_CHANNEL = 0x16b; +enum KEY_FAVORITES = 0x16c; +enum KEY_EPG = 0x16d; +enum KEY_PVR = 0x16e; +enum KEY_MHP = 0x16f; +enum KEY_LANGUAGE = 0x170; +enum KEY_TITLE = 0x171; +enum KEY_SUBTITLE = 0x172; +enum KEY_ANGLE = 0x173; +enum KEY_ZOOM = 0x174; +enum KEY_MODE = 0x175; +enum KEY_KEYBOARD = 0x176; +enum KEY_SCREEN = 0x177; +enum KEY_PC = 0x178; +enum KEY_TV = 0x179; +enum KEY_TV2 = 0x17a; +enum KEY_VCR = 0x17b; +enum KEY_VCR2 = 0x17c; +enum KEY_SAT = 0x17d; +enum KEY_SAT2 = 0x17e; +enum KEY_CD = 0x17f; +enum KEY_TAPE = 0x180; +enum KEY_RADIO = 0x181; +enum KEY_TUNER = 0x182; +enum KEY_PLAYER = 0x183; +enum KEY_TEXT = 0x184; +enum KEY_DVD = 0x185; +enum KEY_AUX = 0x186; +enum KEY_MP3 = 0x187; +enum KEY_AUDIO = 0x188; +enum KEY_VIDEO = 0x189; +enum KEY_DIRECTORY = 0x18a; +enum KEY_LIST = 0x18b; +enum KEY_MEMO = 0x18c; +enum KEY_CALENDAR = 0x18d; +enum KEY_RED = 0x18e; +enum KEY_GREEN = 0x18f; +enum KEY_YELLOW = 0x190; +enum KEY_BLUE = 0x191; +enum KEY_CHANNELUP = 0x192; +enum KEY_CHANNELDOWN = 0x193; +enum KEY_FIRST = 0x194; +enum KEY_LAST = 0x195; +enum KEY_AB = 0x196; +enum KEY_NEXT = 0x197; +enum KEY_RESTART = 0x198; +enum KEY_SLOW = 0x199; +enum KEY_SHUFFLE = 0x19a; +enum KEY_BREAK = 0x19b; +enum KEY_PREVIOUS = 0x19c; +enum KEY_DIGITS = 0x19d; +enum KEY_TEEN = 0x19e; +enum KEY_TWEN = 0x19f; +enum KEY_VIDEOPHONE = 0x1a0; +enum KEY_GAMES = 0x1a1; +enum KEY_ZOOMIN = 0x1a2; +enum KEY_ZOOMOUT = 0x1a3; +enum KEY_ZOOMRESET = 0x1a4; +enum KEY_WORDPROCESSOR = 0x1a5; +enum KEY_EDITOR = 0x1a6; +enum KEY_SPREADSHEET = 0x1a7; +enum KEY_GRAPHICSEDITOR = 0x1a8; +enum KEY_PRESENTATION = 0x1a9; +enum KEY_DATABASE = 0x1aa; +enum KEY_NEWS = 0x1ab; +enum KEY_VOICEMAIL = 0x1ac; +enum KEY_ADDRESSBOOK = 0x1ad; +enum KEY_MESSENGER = 0x1ae; +enum KEY_DISPLAYTOGGLE = 0x1af; +enum KEY_BRIGHTNESS_TOGGLE = KEY_DISPLAYTOGGLE; +enum KEY_SPELLCHECK = 0x1b0; +enum KEY_LOGOFF = 0x1b1; + +enum KEY_DOLLAR = 0x1b2; +enum KEY_EURO = 0x1b3; + +enum KEY_FRAMEBACK = 0x1b4; +enum KEY_FRAMEFORWARD = 0x1b5; +enum KEY_CONTEXT_MENU = 0x1b6; +enum KEY_MEDIA_REPEAT = 0x1b7; +enum KEY_10CHANNELSUP = 0x1b8; +enum KEY_10CHANNELSDOWN = 0x1b9; +enum KEY_IMAGES = 0x1ba; + +enum KEY_DEL_EOL = 0x1c0; +enum KEY_DEL_EOS = 0x1c1; +enum KEY_INS_LINE = 0x1c2; +enum KEY_DEL_LINE = 0x1c3; + +enum KEY_FN = 0x1d0; +enum KEY_FN_ESC = 0x1d1; +enum KEY_FN_F1 = 0x1d2; +enum KEY_FN_F2 = 0x1d3; +enum KEY_FN_F3 = 0x1d4; +enum KEY_FN_F4 = 0x1d5; +enum KEY_FN_F5 = 0x1d6; +enum KEY_FN_F6 = 0x1d7; +enum KEY_FN_F7 = 0x1d8; +enum KEY_FN_F8 = 0x1d9; +enum KEY_FN_F9 = 0x1da; +enum KEY_FN_F10 = 0x1db; +enum KEY_FN_F11 = 0x1dc; +enum KEY_FN_F12 = 0x1dd; +enum KEY_FN_1 = 0x1de; +enum KEY_FN_2 = 0x1df; +enum KEY_FN_D = 0x1e0; +enum KEY_FN_E = 0x1e1; +enum KEY_FN_F = 0x1e2; +enum KEY_FN_S = 0x1e3; +enum KEY_FN_B = 0x1e4; + +enum KEY_BRL_DOT1 = 0x1f1; +enum KEY_BRL_DOT2 = 0x1f2; +enum KEY_BRL_DOT3 = 0x1f3; +enum KEY_BRL_DOT4 = 0x1f4; +enum KEY_BRL_DOT5 = 0x1f5; +enum KEY_BRL_DOT6 = 0x1f6; +enum KEY_BRL_DOT7 = 0x1f7; +enum KEY_BRL_DOT8 = 0x1f8; +enum KEY_BRL_DOT9 = 0x1f9; +enum KEY_BRL_DOT10 = 0x1fa; + +enum KEY_NUMERIC_0 = 0x200; +enum KEY_NUMERIC_1 = 0x201; +enum KEY_NUMERIC_2 = 0x202; +enum KEY_NUMERIC_3 = 0x203; +enum KEY_NUMERIC_4 = 0x204; +enum KEY_NUMERIC_5 = 0x205; +enum KEY_NUMERIC_6 = 0x206; +enum KEY_NUMERIC_7 = 0x207; +enum KEY_NUMERIC_8 = 0x208; +enum KEY_NUMERIC_9 = 0x209; +enum KEY_NUMERIC_STAR = 0x20a; +enum KEY_NUMERIC_POUND = 0x20b; +enum KEY_NUMERIC_A = 0x20c; +enum KEY_NUMERIC_B = 0x20d; +enum KEY_NUMERIC_C = 0x20e; +enum KEY_NUMERIC_D = 0x20f; + +enum KEY_CAMERA_FOCUS = 0x210; +enum KEY_WPS_BUTTON = 0x211; + +enum KEY_TOUCHPAD_TOGGLE = 0x212; +enum KEY_TOUCHPAD_ON = 0x213; +enum KEY_TOUCHPAD_OFF = 0x214; + +enum KEY_CAMERA_ZOOMIN = 0x215; +enum KEY_CAMERA_ZOOMOUT = 0x216; +enum KEY_CAMERA_UP = 0x217; +enum KEY_CAMERA_DOWN = 0x218; +enum KEY_CAMERA_LEFT = 0x219; +enum KEY_CAMERA_RIGHT = 0x21a; + +enum KEY_ATTENDANT_ON = 0x21b; +enum KEY_ATTENDANT_OFF = 0x21c; +enum KEY_ATTENDANT_TOGGLE = 0x21d; +enum KEY_LIGHTS_TOGGLE = 0x21e; + +enum BTN_DPAD_UP = 0x220; +enum BTN_DPAD_DOWN = 0x221; +enum BTN_DPAD_LEFT = 0x222; +enum BTN_DPAD_RIGHT = 0x223; + +enum KEY_ALS_TOGGLE = 0x230; +enum KEY_ROTATE_LOCK_TOGGLE = 0x231; + +enum KEY_BUTTONCONFIG = 0x240; +enum KEY_TASKMANAGER = 0x241; +enum KEY_JOURNAL = 0x242; +enum KEY_CONTROLPANEL = 0x243; +enum KEY_APPSELECT = 0x244; +enum KEY_SCREENSAVER = 0x245; +enum KEY_VOICECOMMAND = 0x246; +enum KEY_ASSISTANT = 0x247; + +enum KEY_BRIGHTNESS_MIN = 0x250; +enum KEY_BRIGHTNESS_MAX = 0x251; + +enum KEY_KBDINPUTASSIST_PREV = 0x260; +enum KEY_KBDINPUTASSIST_NEXT = 0x261; +enum KEY_KBDINPUTASSIST_PREVGROUP = 0x262; +enum KEY_KBDINPUTASSIST_NEXTGROUP = 0x263; +enum KEY_KBDINPUTASSIST_ACCEPT = 0x264; +enum KEY_KBDINPUTASSIST_CANCEL = 0x265; + +enum KEY_RIGHT_UP = 0x266; +enum KEY_RIGHT_DOWN = 0x267; +enum KEY_LEFT_UP = 0x268; +enum KEY_LEFT_DOWN = 0x269; + +enum KEY_ROOT_MENU = 0x26a; +enum KEY_MEDIA_TOP_MENU = 0x26b; +enum KEY_NUMERIC_11 = 0x26c; +enum KEY_NUMERIC_12 = 0x26d; +enum KEY_AUDIO_DESC = 0x26e; +enum KEY_3D_MODE = 0x26f; +enum KEY_NEXT_FAVORITE = 0x270; +enum KEY_STOP_RECORD = 0x271; +enum KEY_PAUSE_RECORD = 0x272; +enum KEY_VOD = 0x273; +enum KEY_UNMUTE = 0x274; +enum KEY_FASTREVERSE = 0x275; +enum KEY_SLOWREVERSE = 0x276; +enum KEY_DATA = 0x277; +enum KEY_ONSCREEN_KEYBOARD = 0x278; + +enum BTN_TRIGGER_HAPPY = 0x2c0; +enum BTN_TRIGGER_HAPPY1 = 0x2c0; +enum BTN_TRIGGER_HAPPY2 = 0x2c1; +enum BTN_TRIGGER_HAPPY3 = 0x2c2; +enum BTN_TRIGGER_HAPPY4 = 0x2c3; +enum BTN_TRIGGER_HAPPY5 = 0x2c4; +enum BTN_TRIGGER_HAPPY6 = 0x2c5; +enum BTN_TRIGGER_HAPPY7 = 0x2c6; +enum BTN_TRIGGER_HAPPY8 = 0x2c7; +enum BTN_TRIGGER_HAPPY9 = 0x2c8; +enum BTN_TRIGGER_HAPPY10 = 0x2c9; +enum BTN_TRIGGER_HAPPY11 = 0x2ca; +enum BTN_TRIGGER_HAPPY12 = 0x2cb; +enum BTN_TRIGGER_HAPPY13 = 0x2cc; +enum BTN_TRIGGER_HAPPY14 = 0x2cd; +enum BTN_TRIGGER_HAPPY15 = 0x2ce; +enum BTN_TRIGGER_HAPPY16 = 0x2cf; +enum BTN_TRIGGER_HAPPY17 = 0x2d0; +enum BTN_TRIGGER_HAPPY18 = 0x2d1; +enum BTN_TRIGGER_HAPPY19 = 0x2d2; +enum BTN_TRIGGER_HAPPY20 = 0x2d3; +enum BTN_TRIGGER_HAPPY21 = 0x2d4; +enum BTN_TRIGGER_HAPPY22 = 0x2d5; +enum BTN_TRIGGER_HAPPY23 = 0x2d6; +enum BTN_TRIGGER_HAPPY24 = 0x2d7; +enum BTN_TRIGGER_HAPPY25 = 0x2d8; +enum BTN_TRIGGER_HAPPY26 = 0x2d9; +enum BTN_TRIGGER_HAPPY27 = 0x2da; +enum BTN_TRIGGER_HAPPY28 = 0x2db; +enum BTN_TRIGGER_HAPPY29 = 0x2dc; +enum BTN_TRIGGER_HAPPY30 = 0x2dd; +enum BTN_TRIGGER_HAPPY31 = 0x2de; +enum BTN_TRIGGER_HAPPY32 = 0x2df; +enum BTN_TRIGGER_HAPPY33 = 0x2e0; +enum BTN_TRIGGER_HAPPY34 = 0x2e1; +enum BTN_TRIGGER_HAPPY35 = 0x2e2; +enum BTN_TRIGGER_HAPPY36 = 0x2e3; +enum BTN_TRIGGER_HAPPY37 = 0x2e4; +enum BTN_TRIGGER_HAPPY38 = 0x2e5; +enum BTN_TRIGGER_HAPPY39 = 0x2e6; +enum BTN_TRIGGER_HAPPY40 = 0x2e7; + +enum KEY_MIN_INTERESTING = KEY_MUTE; +enum KEY_MAX = 0x2ff; +enum KEY_CNT = (KEY_MAX+1); + +enum REL_X = 0x00; +enum REL_Y = 0x01; +enum REL_Z = 0x02; +enum REL_RX = 0x03; +enum REL_RY = 0x04; +enum REL_RZ = 0x05; +enum REL_HWHEEL = 0x06; +enum REL_DIAL = 0x07; +enum REL_WHEEL = 0x08; +enum REL_MISC = 0x09; +enum REL_MAX = 0x0f; +enum REL_CNT = (REL_MAX+1); + +enum ABS_X = 0x00; +enum ABS_Y = 0x01; +enum ABS_Z = 0x02; +enum ABS_RX = 0x03; +enum ABS_RY = 0x04; +enum ABS_RZ = 0x05; +enum ABS_THROTTLE = 0x06; +enum ABS_RUDDER = 0x07; +enum ABS_WHEEL = 0x08; +enum ABS_GAS = 0x09; +enum ABS_BRAKE = 0x0a; +enum ABS_HAT0X = 0x10; +enum ABS_HAT0Y = 0x11; +enum ABS_HAT1X = 0x12; +enum ABS_HAT1Y = 0x13; +enum ABS_HAT2X = 0x14; +enum ABS_HAT2Y = 0x15; +enum ABS_HAT3X = 0x16; +enum ABS_HAT3Y = 0x17; +enum ABS_PRESSURE = 0x18; +enum ABS_DISTANCE = 0x19; +enum ABS_TILT_X = 0x1a; +enum ABS_TILT_Y = 0x1b; +enum ABS_TOOL_WIDTH = 0x1c; + +enum ABS_VOLUME = 0x20; + +enum ABS_MISC = 0x28; + +enum ABS_MT_SLOT = 0x2f; +enum ABS_MT_TOUCH_MAJOR = 0x30; +enum ABS_MT_TOUCH_MINOR = 0x31; +enum ABS_MT_WIDTH_MAJOR = 0x32; +enum ABS_MT_WIDTH_MINOR = 0x33; +enum ABS_MT_ORIENTATION = 0x34; +enum ABS_MT_POSITION_X = 0x35; +enum ABS_MT_POSITION_Y = 0x36; +enum ABS_MT_TOOL_TYPE = 0x37; +enum ABS_MT_BLOB_ID = 0x38; +enum ABS_MT_TRACKING_ID = 0x39; +enum ABS_MT_PRESSURE = 0x3a; +enum ABS_MT_DISTANCE = 0x3b; +enum ABS_MT_TOOL_X = 0x3c; +enum ABS_MT_TOOL_Y = 0x3d; + +enum ABS_MAX = 0x3f; +enum ABS_CNT = (ABS_MAX+1); + +enum SW_LID = 0x00; +enum SW_TABLET_MODE = 0x01; +enum SW_HEADPHONE_INSERT = 0x02; +enum SW_RFKILL_ALL = 0x03; +enum SW_RADIO = SW_RFKILL_ALL; +enum SW_MICROPHONE_INSERT = 0x04; +enum SW_DOCK = 0x05; +enum SW_LINEOUT_INSERT = 0x06; +enum SW_JACK_PHYSICAL_INSERT = 0x07; +enum SW_VIDEOOUT_INSERT = 0x08; +enum SW_CAMERA_LENS_COVER = 0x09; +enum SW_KEYPAD_SLIDE = 0x0a; +enum SW_FRONT_PROXIMITY = 0x0b; +enum SW_ROTATE_LOCK = 0x0c; +enum SW_LINEIN_INSERT = 0x0d; +enum SW_MUTE_DEVICE = 0x0e; +enum SW_PEN_INSERTED = 0x0f; +enum SW_MAX = 0x0f; +enum SW_CNT = (SW_MAX+1); + +enum MSC_SERIAL = 0x00; +enum MSC_PULSELED = 0x01; +enum MSC_GESTURE = 0x02; +enum MSC_RAW = 0x03; +enum MSC_SCAN = 0x04; +enum MSC_TIMESTAMP = 0x05; +enum MSC_MAX = 0x07; +enum MSC_CNT = (MSC_MAX+1); + +enum LED_NUML = 0x00; +enum LED_CAPSL = 0x01; +enum LED_SCROLLL = 0x02; +enum LED_COMPOSE = 0x03; +enum LED_KANA = 0x04; +enum LED_SLEEP = 0x05; +enum LED_SUSPEND = 0x06; +enum LED_MUTE = 0x07; +enum LED_MISC = 0x08; +enum LED_MAIL = 0x09; +enum LED_CHARGING = 0x0a; +enum LED_MAX = 0x0f; +enum LED_CNT = (LED_MAX+1); + +enum REP_DELAY = 0x00; +enum REP_PERIOD = 0x01; +enum REP_MAX = 0x01; +enum REP_CNT = (REP_MAX+1); + +enum SND_CLICK = 0x00; +enum SND_BELL = 0x01; +enum SND_TONE = 0x02; +enum SND_MAX = 0x07; +enum SND_CNT = (SND_MAX+1); diff --git a/libphobos/libdruntime/core/sys/linux/uinput.d b/libphobos/libdruntime/core/sys/linux/uinput.d new file mode 100644 index 00000000000..abb61f919c2 --- /dev/null +++ b/libphobos/libdruntime/core/sys/linux/uinput.d @@ -0,0 +1,85 @@ +module core.sys.linux.uinput; + +version (linux): +extern(C): +nothrow: + +import core.sys.posix.sys.ioctl; + +public import core.sys.linux.input; +public import core.sys.linux.input_event_codes; + +enum UINPUT_VERSION = 5; +enum UINPUT_MAX_NAME_SIZE = 80; + +struct uinput_ff_upload +{ + uint request_id; + int retval; + ff_effect effect; + ff_effect old; +} + +struct uinput_ff_erase +{ + uint request_id; + int retval; + uint effect_id; +} + +enum UINPUT_IOCTL_BASE = 'U'; +enum UI_DEV_CREATE = _IO(UINPUT_IOCTL_BASE, 1); +enum UI_DEV_DESTROY = _IO(UINPUT_IOCTL_BASE, 2); + +struct uinput_setup +{ + input_id id; + char[UINPUT_MAX_NAME_SIZE] name; + uint ff_effects_max; +} + +enum UI_DEV_SETUP = _IOW!uinput_setup(UINPUT_IOCTL_BASE, 3); + +struct uinput_abs_setup +{ + ushort code; + + input_absinfo absinfo; +} + +enum UI_ABS_SETUP = _IOW!uinput_abs_setup(UINPUT_IOCTL_BASE, 4); + +enum UI_SET_EVBIT = _IOW!int(UINPUT_IOCTL_BASE, 100); +enum UI_SET_KEYBIT = _IOW!int(UINPUT_IOCTL_BASE, 101); +enum UI_SET_RELBIT = _IOW!int(UINPUT_IOCTL_BASE, 102); +enum UI_SET_ABSBIT = _IOW!int(UINPUT_IOCTL_BASE, 103); +enum UI_SET_MSCBIT = _IOW!int(UINPUT_IOCTL_BASE, 104); +enum UI_SET_LEDBIT = _IOW!int(UINPUT_IOCTL_BASE, 105); +enum UI_SET_SNDBIT = _IOW!int(UINPUT_IOCTL_BASE, 106); +enum UI_SET_FFBIT = _IOW!int(UINPUT_IOCTL_BASE, 107); +enum UI_SET_PHYS = _IOW!(char*)(UINPUT_IOCTL_BASE, 108); +enum UI_SET_SWBIT = _IOW!int(UINPUT_IOCTL_BASE, 109); +enum UI_SET_PROPBIT = _IOW!int(UINPUT_IOCTL_BASE, 110); + +enum UI_BEGIN_FF_UPLOAD = _IOWR!uinput_ff_upload(UINPUT_IOCTL_BASE, 200); +enum UI_END_FF_UPLOAD = _IOW!uinput_ff_upload(UINPUT_IOCTL_BASE, 201); +enum UI_BEGIN_FF_ERASE = _IOWR!uinput_ff_erase(UINPUT_IOCTL_BASE, 202); +enum UI_END_FF_ERASE = _IOW!uinput_ff_erase(UINPUT_IOCTL_BASE, 203); + +enum UI_GET_SYSNAME(len) = _IOC(_IOC_READ, UINPUT_IOCTL_BASE, 44, len); + +enum UI_GET_VERSION = _IOR!uint(UINPUT_IOCTL_BASE, 45); + +enum EV_UINPUT = 0x0101; +enum UI_FF_UPLOAD = 1; +enum UI_FF_ERASE = 2; + +struct uinput_user_dev { + char[UINPUT_MAX_NAME_SIZE] name; + input_id id; + uint ff_effects_max; + int[ABS_CNT] absmax; + int[ABS_CNT] absmin; + int[ABS_CNT] absfuzz; + int[ABS_CNT] absflat; +} diff --git a/libphobos/libdruntime/core/sys/openbsd/unistd.d b/libphobos/libdruntime/core/sys/openbsd/unistd.d index 0b8580fb860..4232c036049 100644 --- a/libphobos/libdruntime/core/sys/openbsd/unistd.d +++ b/libphobos/libdruntime/core/sys/openbsd/unistd.d @@ -12,6 +12,10 @@ extern (C): nothrow: @nogc: +public import core.sys.posix.sys.types; + int getentropy(void*, size_t); +int getthrname(pid_t, char*, size_t); int pledge(const scope char*, const scope char*); +int setthrname(pid_t, const scope char*); int unveil(const scope char*, const scope char*); diff --git a/libphobos/libdruntime/core/sys/windows/dll.d b/libphobos/libdruntime/core/sys/windows/dll.d index 367c1d90d93..5b02fb55801 100644 --- a/libphobos/libdruntime/core/sys/windows/dll.d +++ b/libphobos/libdruntime/core/sys/windows/dll.d @@ -328,6 +328,8 @@ public: * first access to a __declspec(thread) variable occurs, that is." * * _tls_index is initialized by the compiler to 0, so we can use this as a test. + * Returns: + * true for success, false for failure */ bool dll_fixTLS( HINSTANCE hInstance, void* tlsstart, void* tlsend, void* tls_callbacks_a, int* tlsindex ) nothrow { @@ -448,8 +450,13 @@ int dll_getRefCount( HINSTANCE hInstance ) nothrow @nogc return ldrMod.LoadCount; } -// fixup TLS storage, initialize runtime and attach to threads -// to be called from DllMain with reason DLL_PROCESS_ATTACH +/***************************** + * To be called from DllMain with reason DLL_PROCESS_ATTACH + * + * fixup TLS storage, initialize runtime and attach to threads + * Returns: + * true = success, false = failure + */ bool dll_process_attach( HINSTANCE hInstance, bool attach_threads, void* tlsstart, void* tlsend, void* tls_callbacks_a, int* tlsindex ) { @@ -480,7 +487,8 @@ bool dll_process_attach( HINSTANCE hInstance, bool attach_threads, }, null ); } -// same as above, but only usable if druntime is linked statically +/** same as above, but only usable if druntime is linked statically + */ bool dll_process_attach( HINSTANCE hInstance, bool attach_threads = true ) { version (Win64) @@ -495,7 +503,9 @@ bool dll_process_attach( HINSTANCE hInstance, bool attach_threads = true ) } } -// to be called from DllMain with reason DLL_PROCESS_DETACH +/** + * to be called from DllMain with reason DLL_PROCESS_DETACH + */ void dll_process_detach( HINSTANCE hInstance, bool detach_threads = true ) { // notify core.thread.joinLowLevelThread that the DLL is about to be unloaded @@ -527,7 +537,11 @@ static bool tlsCtorRun; static this() { tlsCtorRun = true; } static ~this() { tlsCtorRun = false; } -// to be called from DllMain with reason DLL_THREAD_ATTACH +/** + * To be called from DllMain with reason DLL_THREAD_ATTACH + * Returns: + * true for success, false for failure + */ bool dll_thread_attach( bool attach_thread = true, bool initTls = true ) { // if the OS has not prepared TLS for us, don't attach to the thread @@ -546,7 +560,11 @@ bool dll_thread_attach( bool attach_thread = true, bool initTls = true ) return true; } -// to be called from DllMain with reason DLL_THREAD_DETACH +/** + * To be called from DllMain with reason DLL_THREAD_DETACH + * Returns: + * true for success, false for failure + */ bool dll_thread_detach( bool detach_thread = true, bool exitTls = true ) { // if the OS has not prepared TLS for us, we did not attach to the thread @@ -562,14 +580,17 @@ bool dll_thread_detach( bool detach_thread = true, bool exitTls = true ) return true; } -/// A simple mixin to provide a $(D DllMain) which calls the necessary -/// runtime initialization and termination functions automatically. -/// -/// Instead of writing a custom $(D DllMain), simply write: -/// -/// --- -/// mixin SimpleDllMain; -/// --- +/********************************** + * A mixin to provide a $(D DllMain) which calls the necessary + * D runtime initialization and termination functions automatically. + * + * Example: + * --- + * module dllmain; + * import core.sys.windows.dll; + * mixin SimpleDllMain; + * --- + */ mixin template SimpleDllMain() { import core.sys.windows.windef : HINSTANCE, BOOL, DWORD, LPVOID; diff --git a/libphobos/libdruntime/etc/valgrind/valgrind.d b/libphobos/libdruntime/etc/valgrind/valgrind.d new file mode 100644 index 00000000000..21829fc23bf --- /dev/null +++ b/libphobos/libdruntime/etc/valgrind/valgrind.d @@ -0,0 +1,85 @@ +/// D wrapper for the Valgrind client API. +/// Note that you must include this file into your program's compilation +/// and compile with `-debug=VALGRIND` to access the declarations below. +module etc.valgrind.valgrind; + +version (StdDdoc) +{ + /// Mark the memory covered by `mem` as unaddressable. + void makeMemNoAccess (const(void)[] mem) nothrow @nogc; + + /// Similarly, mark memory covered by `mem` as addressable but undefined. + void makeMemUndefined(const(void)[] mem) nothrow @nogc; + + /// Similarly, mark memory covered by `mem` as addressable and defined. + void makeMemDefined (const(void)[] mem) nothrow @nogc; + + /// Get the validity data for the address range covered by `mem` and copy it + /// into the provided `bits` array. + /// Returns: + /// - 0 if not running on valgrind + /// - 1 success + /// - 2 [previously indicated unaligned arrays; these are now allowed] + /// - 3 if any parts of `mem`/`bits` are not addressable. + /// The metadata is not copied in cases 0, 2 or 3 so it should be + /// impossible to segfault your system by using this call. + uint getVBits(const(void)[] mem, ubyte[] bits) nothrow @nogc; + + /// Set the validity data for the address range covered by `mem`, copying it + /// from the provided `bits` array. + /// Returns: + /// - 0 if not running on valgrind + /// - 1 success + /// - 2 [previously indicated unaligned arrays; these are now allowed] + /// - 3 if any parts of `mem`/`bits` are not addressable. + /// The metadata is not copied in cases 0, 2 or 3 so it should be + /// impossible to segfault your system by using this call. + uint setVBits(const(void)[] mem, ubyte[] bits) nothrow @nogc; + + /// Disable and re-enable reporting of addressing errors in the + /// address range covered by `mem`. + void disableAddrReportingInRange(const(void)[] mem) nothrow @nogc; + + /// ditto + void enableAddrReportingInRange(const(void)[] mem) nothrow @nogc; +} +else: + +debug(VALGRIND): + +private extern(C) nothrow @nogc +{ + void _d_valgrind_make_mem_noaccess (const(void)* addr, size_t len); + void _d_valgrind_make_mem_undefined(const(void)* addr, size_t len); + void _d_valgrind_make_mem_defined (const(void)* addr, size_t len); + uint _d_valgrind_get_vbits(const(void)* addr, ubyte* bits, size_t len); + uint _d_valgrind_set_vbits(const(void)* addr, ubyte* bits, size_t len); + void _d_valgrind_disable_addr_reporting_in_range(const(void)* addr, size_t len); + void _d_valgrind_enable_addr_reporting_in_range (const(void)* addr, size_t len); +} + +void makeMemNoAccess (const(void)[] mem) nothrow @nogc { _d_valgrind_make_mem_noaccess (mem.ptr, mem.length); } +void makeMemUndefined(const(void)[] mem) nothrow @nogc { _d_valgrind_make_mem_undefined(mem.ptr, mem.length); } +void makeMemDefined (const(void)[] mem) nothrow @nogc { _d_valgrind_make_mem_defined (mem.ptr, mem.length); } + +uint getVBits(const(void)[] mem, ubyte[] bits) nothrow @nogc +{ + assert(mem.length == bits.length); + return _d_valgrind_get_vbits(mem.ptr, bits.ptr, mem.length); +} + +uint setVBits(const(void)[] mem, ubyte[] bits) nothrow @nogc +{ + assert(mem.length == bits.length); + return _d_valgrind_set_vbits(mem.ptr, bits.ptr, mem.length); +} + +void disableAddrReportingInRange(const(void)[] mem) nothrow @nogc +{ + _d_valgrind_disable_addr_reporting_in_range(mem.ptr, mem.length); +} + +void enableAddrReportingInRange(const(void)[] mem) nothrow @nogc +{ + _d_valgrind_enable_addr_reporting_in_range(mem.ptr, mem.length); +} diff --git a/libphobos/libdruntime/etc/valgrind/valgrind_.c b/libphobos/libdruntime/etc/valgrind/valgrind_.c new file mode 100644 index 00000000000..4dc4a171f8b --- /dev/null +++ b/libphobos/libdruntime/etc/valgrind/valgrind_.c @@ -0,0 +1,102 @@ +/** + * This file contains wrapper functions for macro-defined valgrind routines. + * + * Copyright: Copyright: Copyright (C) D Language Foundation 2023 + * License: Distributed under the + * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). + * (See accompanying file LICENSE) + * Source: $(DRUNTIMESRC etc/valgrind/valgrind.c) + */ + +/* NOTE: This file has been patched from the original DMD distribution to + * work with the GDC compiler. + */ +#include "config.h" + +#ifdef ENABLE_VALGRIND_CHECKING + +#ifdef HAVE_STDDEF_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif + +#ifdef HAVE_VALGRIND_MEMCHECK_H +# include +#elif defined HAVE_MEMCHECK_H +# include +#else +# include +#endif + +#ifndef VALGRIND_MAKE_MEM_NOACCESS +# define VALGRIND_MAKE_MEM_NOACCESS VALGRIND_MAKE_NOACCESS +#endif +#ifndef VALGRIND_MAKE_MEM_UNDEFINED +# define VALGRIND_MAKE_MEM_UNDEFINED VALGRIND_MAKE_WRITABLE +#endif +#ifndef VALGRIND_MAKE_MEM_DEFINED +# define VALGRIND_MAKE_MEM_DEFINED VALGRIND_MAKE_READABLE +#endif + +#ifndef VALGRIND_GET_VBITS +# define VALGRIND_GET_VBITS(a,b,l) 0 +#endif +#ifndef VALGRIND_SET_VBITS +# define VALGRIND_SET_VBITS(a,b,l) 0 +#endif +#ifndef VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE +# define VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,l) +#endif +#ifndef VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE +# define VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(a,l) +#endif + +#define MAYBE_UNUSED __attribute__((unused)) + +void _d_valgrind_make_mem_noaccess(const void* addr, size_t len) +{ + VALGRIND_DISCARD(VALGRIND_MAKE_MEM_NOACCESS(addr, len)); +} + +void _d_valgrind_make_mem_undefined(const void* addr, size_t len) +{ + VALGRIND_DISCARD(VALGRIND_MAKE_MEM_UNDEFINED(addr, len)); +} + +void _d_valgrind_make_mem_defined(const void* addr, size_t len) +{ + VALGRIND_DISCARD(VALGRIND_MAKE_MEM_DEFINED(addr, len)); +} + +unsigned _d_valgrind_get_vbits(const void* addr MAYBE_UNUSED, + char* bits MAYBE_UNUSED, + size_t len MAYBE_UNUSED) +{ + return VALGRIND_GET_VBITS(addr, bits, len); +} + +unsigned _d_valgrind_set_vbits(const void* addr MAYBE_UNUSED, + char* bits MAYBE_UNUSED, + size_t len MAYBE_UNUSED) +{ + return VALGRIND_SET_VBITS(addr, bits, len); +} + +void _d_valgrind_disable_addr_reporting_in_range(const void* addr MAYBE_UNUSED, + size_t len MAYBE_UNUSED) +{ + VALGRIND_DISCARD(VALGRIND_DISABLE_ADDR_ERROR_REPORTING_IN_RANGE(addr, len)); +} + +void _d_valgrind_enable_addr_reporting_in_range(const void* addr MAYBE_UNUSED, + size_t len MAYBE_UNUSED) +{ + VALGRIND_DISCARD(VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(addr, len)); +} + +#endif /* ENABLE_VALGRIND_CHECKING */ diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d index 337eabf64db..b0889b66386 100644 --- a/libphobos/libdruntime/object.d +++ b/libphobos/libdruntime/object.d @@ -289,8 +289,9 @@ if ((is(LHS : const Object) || is(LHS : const shared Object)) && // If same exact type => one call to method opEquals if (typeid(lhs) is typeid(rhs) || !__ctfe && typeid(lhs).opEquals(typeid(rhs))) - /* CTFE doesn't like typeid much. 'is' works, but opEquals doesn't - (issue 7147). But CTFE also guarantees that equal TypeInfos are + /* CTFE doesn't like typeid much. 'is' works, but opEquals doesn't: + https://issues.dlang.org/show_bug.cgi?id=7147 + But CTFE also guarantees that equal TypeInfos are always identical. So, no opEquals needed during CTFE. */ { return true; @@ -983,7 +984,7 @@ class TypeInfo_Enum : TypeInfo } -@safe unittest // issue 12233 +@safe unittest // https://issues.dlang.org/show_bug.cgi?id=12233 { static assert(is(typeof(TypeInfo.init) == TypeInfo)); assert(TypeInfo.init is null); @@ -4195,8 +4196,11 @@ void destroy(bool initialize = true, T)(T obj) if (is(T == interface)) assert(c.s == "S"); // `c.s` is back to its inital state, `"S"` assert(c.a.dtorCount == 1); // `c.a`'s destructor was called assert(c.a.x == 10); // `c.a.x` is back to its inital state, `10` +} - // check C++ classes work too! +/// C++ classes work too +@system unittest +{ extern (C++) class CPP { struct Agg @@ -4247,6 +4251,34 @@ void destroy(bool initialize = true, T)(T obj) if (is(T == interface)) assert(i == 0); // `i` is back to its initial state `0` } +/// Nested struct type +@system unittest +{ + int dtorCount; + struct A + { + int i; + ~this() + { + dtorCount++; // capture local variable + } + } + A a = A(5); + destroy!false(a); + assert(dtorCount == 1); + assert(a.i == 5); + + destroy(a); + assert(dtorCount == 2); + assert(a.i == 0); + + // the context pointer is now null + // restore it so the dtor can run + import core.lifetime : emplace; + emplace(&a, A(0)); + // dtor also called here +} + @system unittest { extern(C++) diff --git a/libphobos/libdruntime/rt/lifetime.d b/libphobos/libdruntime/rt/lifetime.d index 40fa3e00b45..1245374ec5f 100644 --- a/libphobos/libdruntime/rt/lifetime.d +++ b/libphobos/libdruntime/rt/lifetime.d @@ -1307,12 +1307,19 @@ int hasArrayFinalizerInSegment(void* p, size_t size, in void[] segment) nothrow return cast(size_t)(cast(void*)si.xdtor - segment.ptr) < segment.length; } +debug (VALGRIND) import etc.valgrind.valgrind; + // called by the GC void finalize_array2(void* p, size_t size) nothrow { debug(PRINTF) printf("rt_finalize_array2(p = %p)\n", p); TypeInfo_Struct si = void; + debug (VALGRIND) + { + auto block = p[0..size]; + disableAddrReportingInRange(block); + } if (size <= 256) { si = *cast(TypeInfo_Struct*)(p + size - size_t.sizeof); @@ -1329,6 +1336,7 @@ void finalize_array2(void* p, size_t size) nothrow size = *cast(size_t*)p; p += LARGEPREFIX; } + debug (VALGRIND) enableAddrReportingInRange(block); try { @@ -2373,7 +2381,7 @@ unittest unittest { - // bugzilla 13854 + // https://issues.dlang.org/show_bug.cgi?id=13854 auto arr = new ubyte[PAGESIZE]; // ensure page size auto info1 = GC.query(arr.ptr); assert(info1.base !is arr.ptr); // offset is required for page size or larger @@ -2416,7 +2424,7 @@ unittest unittest { - // bugzilla 13878 + // https://issues.dlang.org/show_bug.cgi?id=13878 auto arr = new ubyte[1]; auto info = GC.query(arr.ptr); assert(info.attr & BlkAttr.NO_SCAN); // should be NO_SCAN diff --git a/libphobos/libdruntime/rt/minfo.d b/libphobos/libdruntime/rt/minfo.d index 74891506364..b5c868f70bc 100644 --- a/libphobos/libdruntime/rt/minfo.d +++ b/libphobos/libdruntime/rt/minfo.d @@ -268,7 +268,9 @@ struct ModuleGroup } } // trim space to what is needed. - edges[i] = (cast(int*)realloc(edge, int.sizeof * nEdges))[0 .. nEdges]; + edges[i] = nEdges > 0 + ? (cast(int*)realloc(edge, int.sizeof * nEdges))[0 .. nEdges] + : null; } } diff --git a/libphobos/libdruntime/rt/util/typeinfo.d b/libphobos/libdruntime/rt/util/typeinfo.d index 7b55693a720..730649ef481 100644 --- a/libphobos/libdruntime/rt/util/typeinfo.d +++ b/libphobos/libdruntime/rt/util/typeinfo.d @@ -545,7 +545,7 @@ unittest unittest { - // Original test case from issue 13073 + // Original test case from https://issues.dlang.org/show_bug.cgi?id=13073 uint x = 0x22_DF_FF_FF; uint y = 0xA2_DF_FF_FF; assert(!(x < y && y < x)); diff --git a/libphobos/m4/druntime/libraries.m4 b/libphobos/m4/druntime/libraries.m4 index 45a56f6f76a..8dd9c7da107 100644 --- a/libphobos/m4/druntime/libraries.m4 +++ b/libphobos/m4/druntime/libraries.m4 @@ -233,3 +233,56 @@ AC_DEFUN([DRUNTIME_LIBRARIES_UCONTEXT], AC_MSG_ERROR([swapcontext required but not found])) fi ]) + +# DRUNTIME_LIBRARIES_VALGRIND +# ------------------------------ +# Allow specifying whether to use valgrind integration in the GC, which enables +# the D run-time to communicate which memory access operations are valid. +# This is only required if `--enable-libphobos-checking=valgrind' was seen. +AC_DEFUN([DRUNTIME_LIBRARIES_VALGRIND], +[ + AC_CHECK_HEADERS(stddef.h stdlib.h) + + AC_CHECK_HEADER(valgrind.h, have_valgrind_h=yes, have_valgrind_h=no) + + AC_MSG_CHECKING(for VALGRIND_DISCARD in ) + AC_PREPROC_IFELSE([AC_LANG_SOURCE( + [[#include + #ifndef VALGRIND_DISCARD + #error VALGRIND_DISCARD not defined + #endif]])], + [have_valgrind_memcheck_h=yes], + [have_valgrind_memcheck_h=no]) + AC_MSG_RESULT($have_valgrind_memcheck_h) + AC_MSG_CHECKING(for VALGRIND_DISCARD in ) + AC_PREPROC_IFELSE([AC_LANG_SOURCE( + [[#include + #ifndef VALGRIND_DISCARD + #error VALGRIND_DISCARD not defined + #endif]])], + [have_memcheck_h=yes], + [have_memcheck_h=no]) + AC_MSG_RESULT($have_memcheck_h) + + if test x$VALGRIND_FLAG != x ; then + AC_DEFINE(ENABLE_VALGRIND_CHECKING, 1, + [Define to enable to integrate valgrind (a memory checker) in the GC.]) + fi + if test $have_valgrind_memcheck_h = yes; then + AC_DEFINE(HAVE_VALGRIND_MEMCHECK_H, 1, + [Define if valgrind's valgrind/memcheck.h header is installed.]) + fi + if test $have_memcheck_h = yes; then + AC_DEFINE(HAVE_MEMCHECK_H, 1, + [Define if valgrind's memcheck.h header is installed.]) + fi + + if test x$VALGRIND_FLAG != x; then + if (test $have_valgrind_h = no \ + && test $have_memcheck_h = no \ + && test $have_valgrind_memcheck_h = no); then + AC_MSG_ERROR([*** valgrind checking requested, but +*** Can't find valgrind/memcheck.h, memcheck.h or valgrind.h]) + fi + fi +]) diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE index d3ebf74468c..e0011d7e7f7 100644 --- a/libphobos/src/MERGE +++ b/libphobos/src/MERGE @@ -1,4 +1,4 @@ -8d3800bee23db56f71ef4066f74bce057fcce256 +1921d29df25f2b44d6014c224e2018ce63ac2b71 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/iteration.d b/libphobos/src/std/algorithm/iteration.d index 55ccb512b73..39927be9bbb 100644 --- a/libphobos/src/std/algorithm/iteration.d +++ b/libphobos/src/std/algorithm/iteration.d @@ -2026,7 +2026,7 @@ private struct ChunkByGroup(alias eq, Range, bool eqEquivalenceAssured) } } - // Cannot be a copy constructor due to issue 22239 + // Cannot be a copy constructor due to https://issues.dlang.org/show_bug.cgi?id=22239 this(this) @trusted { import core.lifetime : emplace; @@ -2128,7 +2128,7 @@ if (isForwardRange!Range) }(); } - // Cannot be a copy constructor due to issue 22239 + // Cannot be a copy constructor due to https://issues.dlang.org/show_bug.cgi?id=22239 this(this) @trusted { import core.lifetime : emplace; diff --git a/libphobos/src/std/algorithm/mutation.d b/libphobos/src/std/algorithm/mutation.d index 9b1d9207b9a..61b6a5e4eff 100644 --- a/libphobos/src/std/algorithm/mutation.d +++ b/libphobos/src/std/algorithm/mutation.d @@ -3049,7 +3049,7 @@ if (isBlitAssignable!T && !is(typeof(lhs.proxySwap(rhs)))) swap(b1, b2); } -// issue 20732 +// https://issues.dlang.org/show_bug.cgi?id=20732 @safe unittest { static struct A diff --git a/libphobos/src/std/algorithm/searching.d b/libphobos/src/std/algorithm/searching.d index ee318c88a0f..f061915d582 100644 --- a/libphobos/src/std/algorithm/searching.d +++ b/libphobos/src/std/algorithm/searching.d @@ -1282,7 +1282,7 @@ if (isInputRange!R && @safe pure unittest { - //example from issue 19727 + //example from https://issues.dlang.org/show_bug.cgi?id=19727 import std.path : asRelativePath; string[] ext = ["abc", "def", "ghi"]; string path = "/foo/file.def"; @@ -1315,19 +1315,12 @@ in } do { - import std.typecons : Rebindable; + import std.typecons : Rebindable2; alias Element = ElementType!Range; - Rebindable!Element seed = r.front; + auto seed = Rebindable2!Element(r.front); r.popFront(); - static if (is(Rebindable!Element == T[], T)) - { - return extremum!(map, selector)(r, seed); - } - else - { - return extremum!(map, selector)(r, seed.get); - } + return extremum!(map, selector)(r, seed.get); } private auto extremum(alias map, alias selector = "a < b", Range, @@ -1337,25 +1330,24 @@ if (isInputRange!Range && !isInfinite!Range && !is(CommonType!(ElementType!Range, RangeElementType) == void) && is(typeof(unaryFun!map(ElementType!(Range).init)))) { - import std.typecons : Rebindable; + import std.typecons : Rebindable2; alias mapFun = unaryFun!map; alias selectorFun = binaryFun!selector; alias Element = ElementType!Range; alias CommonElement = CommonType!(Element, RangeElementType); - Rebindable!CommonElement extremeElement = seedElement; + auto extremeElement = Rebindable2!CommonElement(seedElement); // if we only have one statement in the loop, it can be optimized a lot better static if (__traits(isSame, map, a => a)) { - // direct access via a random access range is faster static if (isRandomAccessRange!Range) { foreach (const i; 0 .. r.length) { - if (selectorFun(r[i], extremeElement)) + if (selectorFun(r[i], extremeElement.get)) { extremeElement = r[i]; } @@ -1365,7 +1357,7 @@ if (isInputRange!Range && !isInfinite!Range && { while (!r.empty) { - if (selectorFun(r.front, extremeElement)) + if (selectorFun(r.front, extremeElement.get)) { extremeElement = r.front; } @@ -1376,7 +1368,7 @@ if (isInputRange!Range && !isInfinite!Range && else { alias MapType = Unqual!(typeof(mapFun(CommonElement.init))); - MapType extremeElementMapped = mapFun(extremeElement); + MapType extremeElementMapped = mapFun(extremeElement.get); // direct access via a random access range is faster static if (isRandomAccessRange!Range) @@ -1405,15 +1397,7 @@ if (isInputRange!Range && !isInfinite!Range && } } } - // Rebindable is an alias to T for arrays - static if (is(typeof(extremeElement) == T[], T)) - { - return extremeElement; - } - else - { - return extremeElement.get; - } + return extremeElement.get; } private auto extremum(alias selector = "a < b", Range)(Range r) @@ -2309,7 +2293,7 @@ private R1 simpleMindedFind(alias pred, R1, R2)(R1 haystack, scope R2 needle) @safe: string _impl; - // This is what triggers issue 7992. + // This is what triggers https://issues.dlang.org/show_bug.cgi?id=7992. @property size_t length() const { return _impl.length; } @property void length(size_t len) { _impl.length = len; } @@ -2322,7 +2306,7 @@ private R1 simpleMindedFind(alias pred, R1, R2)(R1 haystack, scope R2 needle) @property CustomString save() { return this; } } - // If issue 7992 occurs, this will throw an exception from calling + // If https://issues.dlang.org/show_bug.cgi?id=7992 occurs, this will throw an exception from calling // popFront() on an empty range. auto r = find(CustomString("a"), CustomString("b")); assert(r.empty); @@ -3880,6 +3864,14 @@ if (isInputRange!Range && !isInfinite!Range && assert(arr.maxElement!"a.val".val == 1); } +// https://issues.dlang.org/show_bug.cgi?id=23993 +@safe unittest +{ + import std.bigint : BigInt; + + assert([BigInt(2), BigInt(3)].maxElement == BigInt(3)); +} + // minPos /** Computes a subrange of `range` starting at the first occurrence of `range`'s diff --git a/libphobos/src/std/complex.d b/libphobos/src/std/complex.d index 3b860fe476b..347e351c26a 100644 --- a/libphobos/src/std/complex.d +++ b/libphobos/src/std/complex.d @@ -1066,7 +1066,7 @@ Complex!T asin(T)(Complex!T z) @safe pure nothrow @nogc { import std.math.operations : isClose; import std.math.constants : PI; - version (DigitalMars) {} else // Disabled because of issue 21376 + version (DigitalMars) {} else // Disabled because of https://issues.dlang.org/show_bug.cgi?id=21376 assert(isClose(asin(complex(0.5f)), float(PI) / 6)); } @@ -1092,7 +1092,7 @@ Complex!T acos(T)(Complex!T z) @safe pure nothrow @nogc { import std.math.operations : isClose; import std.math.constants : PI; - version (DigitalMars) {} else // Disabled because of issue 21376 + version (DigitalMars) {} else // Disabled because of https://issues.dlang.org/show_bug.cgi?id=21376 assert(isClose(acos(complex(0.5f)), float(PI) / 3)); } diff --git a/libphobos/src/std/container/array.d b/libphobos/src/std/container/array.d index f5efe6d1f2a..0d6be93a1c1 100644 --- a/libphobos/src/std/container/array.d +++ b/libphobos/src/std/container/array.d @@ -1566,7 +1566,7 @@ if (!is(immutable T == immutable bool)) r2[0 .. 0] += 0; } -// Test issue 11194 +// Test https://issues.dlang.org/show_bug.cgi?id=11194 @system unittest { static struct S { diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d index 89d4e5eafa2..aabcd784229 100644 --- a/libphobos/src/std/conv.d +++ b/libphobos/src/std/conv.d @@ -209,14 +209,14 @@ template to(T) return toImpl!T(args); } - // Fix issue 6175 + // Fix https://issues.dlang.org/show_bug.cgi?id=6175 T to(S)(ref S arg) if (isStaticArray!S) { return toImpl!T(arg); } - // Fix issue 16108 + // Fix https://issues.dlang.org/show_bug.cgi?id=16108 T to(S)(ref S arg) if (isAggregateType!S && !isCopyable!S) { @@ -423,7 +423,7 @@ template to(T) assert(c == "abcx"); } -// Tests for issue 6175 +// Tests for https://issues.dlang.org/show_bug.cgi?id=6175 @safe pure nothrow unittest { char[9] sarr = "blablabla"; @@ -432,7 +432,7 @@ template to(T) assert(sarr.length == darr.length); } -// Tests for issue 7348 +// Tests for https://issues.dlang.org/show_bug.cgi?id=7348 @safe pure /+nothrow+/ unittest { assert(to!string(null) == "null"); @@ -454,7 +454,7 @@ template to(T) assert(text("a", s) == "aS"); } -// Tests for issue 11390 +// Tests for https://issues.dlang.org/show_bug.cgi?id=11390 @safe pure /+nothrow+/ unittest { const(typeof(null)) ctn; @@ -463,7 +463,7 @@ template to(T) assert(to!string(itn) == "null"); } -// Tests for issue 8729: do NOT skip leading WS +// Tests for https://issues.dlang.org/show_bug.cgi?id=8729: do NOT skip leading WS @safe pure unittest { import std.exception; @@ -1370,7 +1370,7 @@ if (is (T == immutable) && isExactSomeString!T && is(S == enum)) S2 s2; assert(to!string(s2) == "S2(42, 43.5)"); - // Test for issue 8080 + // Test for https://issues.dlang.org/show_bug.cgi?id=8080 struct S8080 { short[4] data; @@ -1972,7 +1972,7 @@ $(UL private T toImpl(T, S)(S value) if (isInputRange!S && isSomeChar!(ElementEncodingType!S) && !isExactSomeString!T && is(typeof(parse!T(value))) && - // issue 20539 + // https://issues.dlang.org/show_bug.cgi?id=20539 !(is(T == enum) && is(typeof(value == OriginalType!T.init)) && !isSomeString!(OriginalType!T))) { scope(success) @@ -5560,7 +5560,7 @@ private bool isHexLiteral(String)(scope const String hexData) static assert( ("5A 01A C FF de 1b"d).isHexLiteral); static assert( ("0123456789abcdefABCDEF"d).isHexLiteral); static assert( (" 012 34 5 6789 abcd ef\rAB\nCDEF"d).isHexLiteral); - // library version allows what's pointed by issue 10454 + // library version allows what's pointed by https://issues.dlang.org/show_bug.cgi?id=10454 static assert( ("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF").isHexLiteral); } @@ -5931,7 +5931,7 @@ if ((radix == 2 || radix == 8 || radix == 10 || radix == 16) && } } -@safe unittest // opSlice (issue 16192) +@safe unittest // opSlice (https://issues.dlang.org/show_bug.cgi?id=16192) { import std.meta : AliasSeq; @@ -5959,7 +5959,7 @@ if ((radix == 2 || radix == 8 || radix == 10 || radix == 16) && for (; !r.empty; r.popFront(), ++i) { assert(original[i .. original.length].tupleof == r.tupleof); - // tupleof is used to work around issue 16216. + // tupleof is used to work around https://issues.dlang.org/show_bug.cgi?id=16216. } // opSlice vs popBack diff --git a/libphobos/src/std/exception.d b/libphobos/src/std/exception.d index 6ffc0f7750a..1d93d351d99 100644 --- a/libphobos/src/std/exception.d +++ b/libphobos/src/std/exception.d @@ -1035,7 +1035,7 @@ Params: Bugs: The function is explicitly annotated `@nogc` because inference could fail, - see $(LINK2 https://issues.dlang.org/show_bug.cgi?id=17084, issue 17084). + see $(LINK2 https://issues.dlang.org/show_bug.cgi?id=17084, Bugzilla issue 17084). Returns: `true` if `source`'s representation embeds a pointer that points to `target`'s representation or somewhere inside diff --git a/libphobos/src/std/experimental/allocator/building_blocks/kernighan_ritchie.d b/libphobos/src/std/experimental/allocator/building_blocks/kernighan_ritchie.d index 65226e7f4cb..6883d33adae 100644 --- a/libphobos/src/std/experimental/allocator/building_blocks/kernighan_ritchie.d +++ b/libphobos/src/std/experimental/allocator/building_blocks/kernighan_ritchie.d @@ -827,7 +827,7 @@ version (StdUnittest) // Both sequences must work on either system - // A sequence of allocs which generates the error described in issue 16564 + // A sequence of allocs which generates the error described in https://issues.dlang.org/show_bug.cgi?id=16564 // that is a gap at the end of buf from the perspective of the allocator // for 64 bit systems (leftover balance = 8 bytes < 16) diff --git a/libphobos/src/std/format/internal/floats.d b/libphobos/src/std/format/internal/floats.d index 632bf7674a6..afe0bfa3cb5 100644 --- a/libphobos/src/std/format/internal/floats.d +++ b/libphobos/src/std/format/internal/floats.d @@ -1449,7 +1449,7 @@ if (is(T == float) || is(T == double) assert(printFloat(-0.1L, f) == "-1.000000e-01"); assert(printFloat(10.0L, f) == "1.000000e+01"); assert(printFloat(-10.0L, f) == "-1.000000e+01"); - version (Windows) {} // issue 20972 + version (Windows) {} // https://issues.dlang.org/show_bug.cgi?id=20972 else { assert(printFloat(1e4000L, f) == "1.000000e+4000"); @@ -1472,7 +1472,7 @@ if (is(T == float) || is(T == double) { // log2 is broken for x87-reals on some computers in CTFE // the following tests excludes these computers from the tests - // (issue 21757) + // (https://issues.dlang.org/show_bug.cgi?id=21757) enum test = cast(int) log2(3.05e2312L); static if (real.mant_dig == 64 && test == 7681) { @@ -2120,7 +2120,7 @@ if (is(T == float) || is(T == double) assert(printFloat(-0.1L, f) == "-0.100000"); assert(printFloat(10.0L, f) == "10.000000"); assert(printFloat(-10.0L, f) == "-10.000000"); - version (Windows) {} // issue 20972 + version (Windows) {} // https://issues.dlang.org/show_bug.cgi?id=20972 else { auto result1 = printFloat(1e4000L, f); @@ -2145,7 +2145,7 @@ if (is(T == float) || is(T == double) { // log2 is broken for x87-reals on some computers in CTFE // the following tests excludes these computers from the tests - // (issue 21757) + // (https://issues.dlang.org/show_bug.cgi?id=21757) enum test = cast(int) log2(3.05e2312L); static if (real.mant_dig == 64 && test == 7681) { @@ -2803,7 +2803,7 @@ if (is(T == float) || is(T == double) assert(printFloat(-0.1L, f) == "-0.1"); assert(printFloat(10.0L, f) == "10"); assert(printFloat(-10.0L, f) == "-10"); - version (Windows) {} // issue 20972 + version (Windows) {} // https://issues.dlang.org/show_bug.cgi?id=20972 else { assert(printFloat(1e4000L, f) == "1e+4000"); @@ -2826,7 +2826,7 @@ if (is(T == float) || is(T == double) { // log2 is broken for x87-reals on some computers in CTFE // the following tests excludes these computers from the tests - // (issue 21757) + // (https://issues.dlang.org/show_bug.cgi?id=21757) enum test = cast(int) log2(3.05e2312L); static if (real.mant_dig == 64 && test == 7681) { diff --git a/libphobos/src/std/format/internal/write.d b/libphobos/src/std/format/internal/write.d index 7f127c09847..8eb70eaa268 100644 --- a/libphobos/src/std/format/internal/write.d +++ b/libphobos/src/std/format/internal/write.d @@ -738,7 +738,7 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char)) assert(FloatingPointControl.rounding == FloatingPointControl.roundToNearest); } - // issue 20320 + // https://issues.dlang.org/show_bug.cgi?id=20320 real a = 0.16; real b = 0.016; assert(format("%.1f", a) == "0.2"); @@ -749,7 +749,7 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char)) assert(format("%.1f", a1) == "0.2"); assert(format("%.2f", b1) == "0.02"); - // issue 9889 + // https://issues.dlang.org/show_bug.cgi?id=9889 assert(format("%.1f", 0.09) == "0.1"); assert(format("%.1f", -0.09) == "-0.1"); assert(format("%.1f", 0.095) == "0.1"); @@ -907,7 +907,7 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char)) // log2 is broken for x87-reals on some computers in CTFE // the following test excludes these computers from the test - // (issue 21757) + // (https://issues.dlang.org/show_bug.cgi?id=21757) enum test = cast(int) log2(3.05e2312L); static if (real.mant_dig == 64 && test == 7681) // 80 bit reals { @@ -3334,7 +3334,7 @@ if (isSomeString!T1 && isSomeString!T2 && isSomeString!T3 && isSomeString!T4) long fractsWidth = fracts.length; // TODO: does not take graphemes into account long suffixWidth; - // TODO: remove this workaround which hides issue 21815 + // TODO: remove this workaround which hides https://issues.dlang.org/show_bug.cgi?id=21815 if (f.width > 0) { prefixWidth = getWidth(prefix); diff --git a/libphobos/src/std/math/operations.d b/libphobos/src/std/math/operations.d index f2e18005e25..4bf19ee3da9 100644 --- a/libphobos/src/std/math/operations.d +++ b/libphobos/src/std/math/operations.d @@ -1287,11 +1287,12 @@ bool isClose(T, U, V = CommonType!(FloatingPointBaseType!T,FloatingPointBaseType // two numbers if (lhs == rhs) return true; - static if (is(typeof(lhs.infinity)) && is(typeof(rhs.infinity))) - { - if (lhs == lhs.infinity || rhs == rhs.infinity || - lhs == -lhs.infinity || rhs == -rhs.infinity) return false; - } + static if (is(typeof(lhs.infinity))) + if (lhs == lhs.infinity || lhs == -lhs.infinity) + return false; + static if (is(typeof(rhs.infinity))) + if (rhs == rhs.infinity || rhs == -rhs.infinity) + return false; import std.math.algebraic : abs; @@ -1406,6 +1407,8 @@ bool isClose(T, U, V = CommonType!(FloatingPointBaseType!T,FloatingPointBaseType assert(!isClose(1,real.nan)); assert(!isClose(real.nan,real.max)); assert(!isClose(real.nan,real.nan)); + + assert(!isClose(-double.infinity, 1)); } @safe pure nothrow @nogc unittest @@ -1950,7 +1953,7 @@ if (isFloatingPoint!T) // log2 is broken for x87-reals on some computers in CTFE // the following test excludes these computers from the test - // (issue 21757) + // (https://issues.dlang.org/show_bug.cgi?id=21757) enum test = cast(int) log2(3.05e2312L); static if (F.realFormat == RealFormat.ieeeExtended && test == 7681) { diff --git a/libphobos/src/std/path.d b/libphobos/src/std/path.d index e81f2b6b855..449235a6820 100644 --- a/libphobos/src/std/path.d +++ b/libphobos/src/std/path.d @@ -1595,7 +1595,7 @@ if (isSomeChar!C) @safe unittest { - // Test for issue 7397 + // Test for https://issues.dlang.org/show_bug.cgi?id=7397 string[] ary = ["a", "b"]; version (Posix) { @@ -1875,7 +1875,7 @@ if (isSomeChar!C) @safe unittest { - // Test for issue 7397 + // Test for https://issues.dlang.org/show_bug.cgi?id=7397 string[] ary = ["a", "b"]; version (Posix) { @@ -2745,7 +2745,7 @@ else version (Posix) See_Also: $(LREF asAbsolutePath) which does not allocate */ -string absolutePath(string path, lazy string base = getcwd()) +string absolutePath(return scope const string path, lazy string base = getcwd()) @safe pure { import std.array : array; @@ -2792,6 +2792,19 @@ string absolutePath(string path, lazy string base = getcwd()) assertThrown(absolutePath("bar", "foo")); } +// Ensure that we can call absolute path with scope paramaters +@safe unittest +{ + string testAbsPath(scope const string path, scope const string base) { + return absolutePath(path, base); + } + + version (Posix) + assert(testAbsPath("some/file", "/foo/bar") == "/foo/bar/some/file"); + version (Windows) + assert(testAbsPath(`some\file`, `c:\foo\bar`) == `c:\foo\bar\some\file`); +} + /** Transforms `path` into an absolute path. The following algorithm is used: @@ -3559,7 +3572,8 @@ if (isConvertibleToString!Range) assert(!globMatch("foo.bar", "[gh]???bar")); assert(!globMatch("foo.bar"w, "[!fg]*bar"w)); assert(!globMatch("foo.bar"d, "[fg]???baz"d)); - assert(!globMatch("foo.di", "*.d")); // test issue 6634: triggered bad assertion + // https://issues.dlang.org/show_bug.cgi?id=6634 + assert(!globMatch("foo.di", "*.d")); // triggered bad assertion assert(globMatch("foo.bar", "{foo,bif}.bar")); assert(globMatch("bif.bar"w, "{foo,bif}.bar"w)); diff --git a/libphobos/src/std/random.d b/libphobos/src/std/random.d index 066ed1713e2..87e63f3f6ee 100644 --- a/libphobos/src/std/random.d +++ b/libphobos/src/std/random.d @@ -2842,7 +2842,7 @@ auto ref choice(Range)(ref Range range) "Choice did not return a valid element from the given Range"); } -@safe unittest // issue 18631 +@safe unittest // https://issues.dlang.org/show_bug.cgi?id=18631 { auto rng = MinstdRand0(42); const a = [0,1,2]; @@ -2855,7 +2855,7 @@ auto ref choice(Range)(ref Range range) auto z1 = choice(cast(const)[1, 2, 3], rng); } -@safe unittest // Ref range (issue 18631 PR) +@safe unittest // Ref range (https://issues.dlang.org/show_bug.cgi?id=18631 PR) { struct TestRange { diff --git a/libphobos/src/std/range/package.d b/libphobos/src/std/range/package.d index d37c6416434..191ec32cf4b 100644 --- a/libphobos/src/std/range/package.d +++ b/libphobos/src/std/range/package.d @@ -3902,24 +3902,17 @@ Returns: struct Repeat(T) { private: - //Store a non-qualified T when possible: This is to make Repeat assignable - static if ((is(T == class) || is(T == interface)) && (is(T == const) || is(T == immutable))) - { - import std.typecons : Rebindable; - alias UT = Rebindable!T; - } - else static if (is(T : Unqual!T) && is(Unqual!T : T)) - alias UT = Unqual!T; - else - alias UT = T; - UT _value; + import std.typecons : Rebindable2; + + // Store a rebindable T to make Repeat assignable. + Rebindable2!T _value; public: /// Range primitives - @property inout(T) front() inout { return _value; } + @property inout(T) front() inout { return _value.get; } /// ditto - @property inout(T) back() inout { return _value; } + @property inout(T) back() inout { return _value.get; } /// ditto enum bool empty = false; @@ -3934,7 +3927,7 @@ public: @property auto save() inout { return this; } /// ditto - inout(T) opIndex(size_t) inout { return _value; } + inout(T) opIndex(size_t) inout { return _value.get; } /// ditto auto opSlice(size_t i, size_t j) @@ -3959,7 +3952,12 @@ public: } /// Ditto -Repeat!T repeat(T)(T value) { return Repeat!T(value); } +Repeat!T repeat(T)(T value) +{ + import std.typecons : Rebindable2; + + return Repeat!T(Rebindable2!T(value)); +} /// pure @safe nothrow unittest @@ -9144,7 +9142,7 @@ public: { static if (needsEndTracker) { - if (poppedElems < windowSize) + if (nextSource.empty) hasShownPartialBefore = true; } else @@ -10124,6 +10122,15 @@ public: assert("ab cd".splitter(' ').slide!(No.withPartial)(2).equal!equal([["ab", "cd"]])); } +// https://issues.dlang.org/show_bug.cgi?id=23976 +@safe unittest +{ + import std.algorithm.comparison : equal; + import std.algorithm.iteration : splitter; + + assert("1<2".splitter('<').slide(2).equal!equal([["1", "2"]])); +} + private struct OnlyResult(Values...) if (Values.length > 1) { @@ -10339,7 +10346,7 @@ if (!is(CommonType!Values == void)) /// ditto auto only()() { - // cannot use noreturn due to issue 22383 + // cannot use noreturn due to https://issues.dlang.org/show_bug.cgi?id=22383 struct EmptyElementType {} EmptyElementType[] result; return result; diff --git a/libphobos/src/std/regex/internal/ir.d b/libphobos/src/std/regex/internal/ir.d index ec0cb66631e..3b38f9c9fbc 100644 --- a/libphobos/src/std/regex/internal/ir.d +++ b/libphobos/src/std/regex/internal/ir.d @@ -49,10 +49,29 @@ CharMatcher[CodepointSet] matcherCache; } } -@property ref wordMatcher()() +// Force pure because that is needed +// Templated so that we don't pull in std.uni wordCharacter unnecessarily. +@property ref wordMatcher()() pure { - static immutable CharMatcher matcher = CharMatcher(wordCharacter); - return matcher; + static auto actual() + { + static CharMatcher matcher; + static bool haveMatcher; + + if (!haveMatcher) + { + matcher = CharMatcher(wordCharacter); + haveMatcher = true; + } + + return &matcher; + } + + // WORKAROUND: if the compiler won't memoize the output of the function for us, + // we'll do it with pure and there will be casts and it'll be happy about it. + // This is unfortunately needed to make std.regex as a whole faster to import & use + // in build times ~500ms. + return *(cast(immutable(CharMatcher)* function() @safe nothrow @nogc pure)&actual)(); } // some special Unicode white space characters diff --git a/libphobos/src/std/signals.d b/libphobos/src/std/signals.d index e5dc67eb83d..97004d52ddd 100644 --- a/libphobos/src/std/signals.d +++ b/libphobos/src/std/signals.d @@ -624,7 +624,7 @@ void linkin() { } a.value6 = 46; } -// Triggers bug from issue 15341 +// Triggers bug from https://issues.dlang.org/show_bug.cgi?id=15341 @system unittest { class Observer @@ -666,7 +666,7 @@ version (none) // Disabled because of https://issues.dlang.org/show_bug.cgi?id=5 } } -// Triggers bug from issue 16249 +// Triggers bug from https://issues.dlang.org/show_bug.cgi?id=16249 @system unittest { class myLINE diff --git a/libphobos/src/std/stdio.d b/libphobos/src/std/stdio.d index 5ed685fe7fc..19ce9880b89 100644 --- a/libphobos/src/std/stdio.d +++ b/libphobos/src/std/stdio.d @@ -34,9 +34,17 @@ $(TR $(TD Misc) $(TD )) )) -Standard I/O functions that extend $(B core.stdc.stdio). $(B core.stdc.stdio) +Standard I/O functions that extend $(LINK2 https://dlang.org/phobos/core_stdc_stdio.html, core.stdc.stdio). $(B core.stdc.stdio) is $(D_PARAM public)ally imported when importing $(B std.stdio). +There are three layers of I/O: +$(OL +$(LI The lowest layer is the operating system layer. The two main schemes are Windows and Posix.) +$(LI C's $(TT stdio.h) which unifies the two operating system schemes.) +$(LI $(TT std.stdio), this module, unifies the various $(TT stdio.h) implementations into +a high level package for D programs.) +) + Source: $(PHOBOSSRC std/stdio.d) Copyright: Copyright The D Language Foundation 2007-. License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0). @@ -48,6 +56,55 @@ CSTDIO=$(HTTP cplusplus.com/reference/cstdio/$1/, $1) */ module std.stdio; +/* +# Glossary + +The three layers have many terms for their data structures and types. +Here we try to bring some sanity to them for the intrepid code spelunker. + +## Windows + +Handle + + A Windows handle is an opaque object of type HANDLE. + The `HANDLE` for standard devices can be retrieved with + Windows `GetStdHandle()`. + +## Posix + +file descriptor, aka fileno, aka fildes + + An int from 0..`FOPEN_MAX`, which is an index into some internal data + structure. + 0 is for `stdin`, 1 for `stdout`, 2 for `stderr`. + Negative values usually indicate an error. + +## stdio.h + +`FILE` + + A struct that encapsulates the C library's view of the operating system + files. A `FILE` should only be referred to via a pointer. + +`fileno` + + A field of `FILE` which is the Posix file descriptor for Posix systems, and + and an index into an array of file `HANDLE`s for Windows. + This array is how Posix behavior is emulated on Windows. + For Digital Mars C, that array is `__osfhnd[]`, and is initialized + at program start by the C runtime library. + In this module, they are typed as `fileno_t`. + +`stdin`, `stdout`, `stderr` + + Global pointers to `FILE` representing standard input, output, and error streams. + Being global means there are synchronization issues when multiple threads + are doing I/O on the same streams. + +## std.stdio + +*/ + import core.stdc.stddef : wchar_t; public import core.stdc.stdio; import std.algorithm.mutation : copy; @@ -129,6 +186,10 @@ else version (Solaris) { version = GENERIC_IO; } +else +{ + static assert(0, "unsupported operating system"); +} // Character type used for operating system filesystem APIs version (Windows) @@ -140,6 +201,7 @@ else private alias FSChar = char; } +private alias fileno_t = int; // file descriptor, fildes, fileno version (Windows) { @@ -203,7 +265,7 @@ version (DIGITAL_MARS_STDIO) // @@@DEPRECATED_2.107@@@ deprecated("internal function _fileno was unintentionally available from " ~ "std.stdio and will be removed afer 2.107") - int _fileno(FILE* f) { return f._file; } + fileno_t _fileno(FILE* f) { return f._file; } } else version (MICROSOFT_STDIO) { @@ -550,7 +612,7 @@ Throws: `ErrnoException` if the file could not be opened. stdioOpenmode, "'")), name); - // MSVCRT workaround (issue 14422) + // MSVCRT workaround (https://issues.dlang.org/show_bug.cgi?id=14422) version (MICROSOFT_STDIO) { setAppendWin(stdioOpenmode); @@ -708,7 +770,7 @@ Throws: `ErrnoException` in case of error. { auto handle = _p.handle; _p.handle = null; - // fclose disassociates the FILE* even in case of error (issue 19751) + // fclose disassociates the FILE* even in case of error (https://issues.dlang.org/show_bug.cgi?id=19751) errnoEnforce(.fclose(handle) == 0, "Could not close file `"~_name~"'"); } @@ -1140,7 +1202,7 @@ Throws: `ErrnoException` if the file is not opened or the call to `fread` fails. enforce(isOpen, "Attempting to read from an unopened file"); version (Windows) { - immutable fd = .fileno(_p.handle); + immutable fileno_t fd = .fileno(_p.handle); immutable mode = .__setmode(fd, _O_BINARY); scope(exit) .__setmode(fd, mode); version (DIGITAL_MARS_STDIO) @@ -1230,7 +1292,7 @@ Throws: `ErrnoException` if the file is not opened or if the call to `fwrite` fa version (Windows) { - immutable fd = .fileno(_p.handle); + immutable fileno_t fd = .fileno(_p.handle); immutable oldMode = .__setmode(fd, _O_BINARY); if (oldMode != _O_BINARY) @@ -2287,7 +2349,7 @@ Returns the `FILE*` corresponding to this object. /** Returns the file number corresponding to this object. */ - @property int fileno() const @trusted + @property fileno_t fileno() const @trusted { import std.exception : enforce; @@ -3108,10 +3170,13 @@ is empty, throws an `Exception`. In case of an I/O error throws // "wide-oriented" for us. immutable int mode = __setmode(f.fileno, _O_TEXT); // Set some arbitrary mode to obtain the previous one. - __setmode(f.fileno, mode); // Restore previous mode. - if (mode & (_O_WTEXT | _O_U16TEXT | _O_U8TEXT)) + if (mode != -1) // __setmode() succeeded { - orientation_ = 1; // wide + __setmode(f.fileno, mode); // Restore previous mode. + if (mode & (_O_WTEXT | _O_U16TEXT | _O_U8TEXT)) + { + orientation_ = 1; // wide + } } } else @@ -3336,7 +3401,8 @@ is empty, throws an `Exception`. In case of an I/O error throws version (Windows) { - int fd, oldMode; + fileno_t fd; + int oldMode; version (DIGITAL_MARS_STDIO) ubyte oldInfo; } @@ -3795,7 +3861,7 @@ void main() assert(std.file.readText!string(deleteme) == "y"); } -@safe unittest // issue 18801 +@safe unittest // https://issues.dlang.org/show_bug.cgi?id=18801 { static import std.file; import std.string : stripLeft; diff --git a/libphobos/src/std/traits.d b/libphobos/src/std/traits.d index 689f0aef809..4dc569df297 100644 --- a/libphobos/src/std/traits.d +++ b/libphobos/src/std/traits.d @@ -5337,7 +5337,7 @@ package template isBlitAssignable(T) enum isBlitAssignable = isBlitAssignable!(OriginalType!T); } else static if (isStaticArray!T && is(T == E[n], E, size_t n)) - // Workaround for issue 11499 : isStaticArray!T should not be necessary. + // Workaround for https://issues.dlang.org/show_bug.cgi?id=11499 : isStaticArray!T should not be necessary. { enum isBlitAssignable = isBlitAssignable!E; } @@ -8877,7 +8877,9 @@ template getSymbolsByUDA(alias symbol, alias attribute) @Attr void c(); } - static assert(getSymbolsByUDA!(A, Attr).stringof == "tuple(a, a, c)"); + alias ola = __traits(getOverloads, A, "a"); + static assert(__traits(isSame, getSymbolsByUDA!(A, Attr), + AliasSeq!(ola[0], ola[1], A.c))); } // getSymbolsByUDA no longer works on modules diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d index 0748d5251e0..67a1ede8148 100644 --- a/libphobos/src/std/typecons.d +++ b/libphobos/src/std/typecons.d @@ -2955,6 +2955,140 @@ Rebindable!T rebindable(T)(Rebindable!T obj) assert(rebindable(pr3341_aa)[321] == 543); } +package(std) struct Rebindable2(T) +{ +private: + static if (isAssignable!(typeof(cast() T.init))) + { + enum useQualifierCast = true; + + typeof(cast() T.init) data; + } + else + { + enum useQualifierCast = false; + + align(T.alignof) + static struct Payload + { + static if (hasIndirections!T) + { + void[T.sizeof] data; + } + else + { + ubyte[T.sizeof] data; + } + } + + Payload data; + } + +public: + + static if (!__traits(compiles, { T value; })) + { + @disable this(); + } + + /** + * Constructs a `Rebindable2` from a given value. + */ + this(T value) @trusted + { + static if (useQualifierCast) + { + this.data = cast() value; + } + else + { + set(value); + } + } + + /** + * Overwrites the currently stored value with `value`. + */ + void opAssign(this This)(T value) @trusted + { + clear; + set(value); + } + + /** + * Returns the value currently stored in the `Rebindable2`. + */ + T get(this This)() @property @trusted + { + static if (useQualifierCast) + { + return cast(T) this.data; + } + else + { + return *cast(T*) &this.data; + } + } + + /// Ditto + inout(T) get() inout @property @trusted + { + static if (useQualifierCast) + { + return cast(inout(T)) this.data; + } + else + { + return *cast(inout(T)*) &this.data; + } + } + + static if (!useQualifierCast) + { + ~this() @trusted + { + clear; + } + } + +private: + + void set(this This)(T value) + { + static if (useQualifierCast) + { + this.data = cast() value; + } + else + { + // As we're escaping a copy of `value`, deliberately leak a copy: + static union DontCallDestructor + { + T value; + } + DontCallDestructor copy = DontCallDestructor(value); + this.data = *cast(Payload*) © + } + } + + void clear(this This)() + { + // work around reinterpreting cast being impossible in CTFE + if (__ctfe) + { + return; + } + + // call possible struct destructors + .destroy!(No.initialize)(*cast(T*) &this.data); + } +} + +package(std) Rebindable2!T rebindable2(T)(T value) +{ + return Rebindable2!T(value); +} + /** Similar to `Rebindable!(T)` but strips all qualifiers from the reference as opposed to just constness / immutability. Primary intended use case is with diff --git a/libphobos/src/std/uni/package.d b/libphobos/src/std/uni/package.d index e2a0de73535..6ab6ba0f631 100644 --- a/libphobos/src/std/uni/package.d +++ b/libphobos/src/std/uni/package.d @@ -8592,7 +8592,7 @@ public: Decomposes a Hangul syllable. If `ch` is not a composed syllable then this function returns $(LREF Grapheme) containing only `ch` as is. */ -Grapheme decomposeHangul(dchar ch) @safe +Grapheme decomposeHangul(dchar ch) nothrow pure @safe { immutable idxS = cast(int) ch - jamoSBase; if (idxS < 0 || idxS >= jamoSCount) return Grapheme(ch); @@ -8709,7 +8709,15 @@ enum { In cases where the string in question is already normalized, it is returned unmodified and no memory allocation happens. +/ -inout(C)[] normalize(NormalizationForm norm=NFC, C)(return scope inout(C)[] input) +/* + WARNING: @trusted lambda inside - handle with same care as @trusted + functions + + Despite being a template, the attributes do no harm since this doesn't work + with user-defined range or character types anyway. +*/ +pure @safe inout(C)[] normalize(NormalizationForm norm=NFC, C) + (return scope inout(C)[] input) { import std.algorithm.mutation : SwapStrategy; import std.algorithm.sorting : sort; @@ -8790,20 +8798,24 @@ inout(C)[] normalize(NormalizationForm norm=NFC, C)(return scope inout(C)[] inpu // reset variables decomposed.length = 0; () @trusted { - decomposed.assumeSafeAppend(); + // assumeSafeAppend isn't considered pure as of writing, hence the + // cast. It isn't pure in the sense that the elements after + // the array in question are affected, but we don't use those + // making the call pure for our purposes. + (cast(void delegate() pure nothrow) {decomposed.assumeSafeAppend();})(); ccc.length = 0; - ccc.assumeSafeAppend(); + (cast(void delegate() pure nothrow) {ccc.assumeSafeAppend();})(); } (); input = input[anchors[1]..$]; // and move on anchors = splitNormalized!norm(input); - }while (anchors[0] != input.length); + } while (anchors[0] != input.length); app.put(input[0 .. anchors[0]]); return () @trusted inout { return cast(inout(C)[]) app.data; } (); } /// -@safe unittest +@safe pure unittest { // any encoding works wstring greet = "Hello world"; @@ -8817,7 +8829,7 @@ inout(C)[] normalize(NormalizationForm norm=NFC, C)(return scope inout(C)[] inpu assert(normalize!NFKD("ϓ") == "\u03A5\u0301"); } -@safe unittest +@safe pure unittest { import std.conv : text; @@ -8825,18 +8837,9 @@ inout(C)[] normalize(NormalizationForm norm=NFC, C)(return scope inout(C)[] inpu assert(normalize!NFKD("2¹⁰") == "210", normalize!NFKD("2¹⁰")); assert(normalize!NFD("Äffin") == "A\u0308ffin"); - // check example - - // any encoding works - wstring greet = "Hello world"; + // test with dstring + dstring greet = "Hello world"; assert(normalize(greet) is greet); // the same exact slice - - // An example of a character with all 4 forms being different: - // Greek upsilon with acute and hook symbol (code point 0x03D3) - assert(normalize!NFC("ϓ") == "\u03D3"); - assert(normalize!NFD("ϓ") == "\u03D2\u0301"); - assert(normalize!NFKC("ϓ") == "\u038E"); - assert(normalize!NFKD("ϓ") == "\u03A5\u0301"); } // canonically recompose given slice of code points, works in-place and mutates data