Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2218714/?format=api
{ "id": 2218714, "url": "http://patchwork.ozlabs.org/api/patches/2218714/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/20260401183432.3740846-1-ibuclaw@gdcproject.org/", "project": { "id": 17, "url": "http://patchwork.ozlabs.org/api/projects/17/?format=api", "name": "GNU Compiler Collection", "link_name": "gcc", "list_id": "gcc-patches.gcc.gnu.org", "list_email": "gcc-patches@gcc.gnu.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260401183432.3740846-1-ibuclaw@gdcproject.org>", "list_archive_url": null, "date": "2026-04-01T18:34:31", "name": "[committed] d: Merge upstream dmd, druntime 55e64690bc, phobos 0c519ae39.", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "6b1a76cf1b8ae66efc9d7336b553ddcdf8f9d77c", "submitter": { "id": 46728, "url": "http://patchwork.ozlabs.org/api/people/46728/?format=api", "name": "Iain Buclaw", "email": "ibuclaw@gdcproject.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/20260401183432.3740846-1-ibuclaw@gdcproject.org/mbox/", "series": [ { "id": 498377, "url": "http://patchwork.ozlabs.org/api/series/498377/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=498377", "date": "2026-04-01T18:34:31", "name": "[committed] d: Merge upstream dmd, druntime 55e64690bc, phobos 0c519ae39.", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/498377/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2218714/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2218714/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gdcproject.org header.i=@gdcproject.org\n header.a=rsa-sha256 header.s=MBO0001 header.b=oaH4/+Q3;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)", "sourceware.org;\n\tdkim=pass (2048-bit key,\n unprotected) header.d=gdcproject.org header.i=@gdcproject.org\n header.a=rsa-sha256 header.s=MBO0001 header.b=oaH4/+Q3", "sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=gdcproject.org", "sourceware.org; spf=pass smtp.mailfrom=gdcproject.org", "server2.sourceware.org;\n arc=none smtp.remote-ip=80.241.56.172", "outgoing_mbo_mout; dkim=none;\n spf=pass (outgoing_mbo_mout: domain of ibuclaw@gdcproject.org designates\n 2001:67c:2050:b231:465::2 as permitted sender)\n smtp.mailfrom=ibuclaw@gdcproject.org" ], "Received": [ "from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fmDFn2cBYz1yFv\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 02 Apr 2026 05:35:57 +1100 (AEDT)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 0D1E24BA2E3C\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 1 Apr 2026 18:35:55 +0000 (GMT)", "from mout-p-202.mailbox.org (mout-p-202.mailbox.org [80.241.56.172])\n by sourceware.org (Postfix) with ESMTPS id 64F444BA2E3C\n for <gcc-patches@gcc.gnu.org>; Wed, 1 Apr 2026 18:34:48 +0000 (GMT)", "from smtp2.mailbox.org (smtp2.mailbox.org\n [IPv6:2001:67c:2050:b231:465::2])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mout-p-202.mailbox.org (Postfix) with ESMTPS id 4fmDDN6WnTz9v5t;\n Wed, 1 Apr 2026 20:34:44 +0200 (CEST)" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org 0D1E24BA2E3C", "OpenDKIM Filter v2.11.0 sourceware.org 64F444BA2E3C" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 64F444BA2E3C", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 64F444BA2E3C", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1775068489; cv=none;\n b=HVvW/3PjLWHvDojCVtoX0JRcYD+Pcdh9XaRnv2DJa3KtXgjaD+jcfK7tKhXYXcmVB5smDfmFlwMlX1Dzk0Wczm+cppaRxYGT1Mr26hqyoUkZLnSiH9OBVETObXhysfuAxoa8Hll6yYpheuOva/E9xSwMOVlPhG+v46AbtUV0kyk=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1775068489; c=relaxed/simple;\n bh=mhNHvxM/oD/n3nFJQZTH7Ktr+1bIKiwyXajmUB8hqTk=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=SUBh3AN6q6TUpZ/f6FO/bMycPSmBMLWtX4BUd6Zj2E2b9Q8EML8CNqUB3TIvJi34LWPrlZ0goKYT1MshsVE9bLbDoPiO2vBFHjrxrag4lsyKiKTW5supX2Zot5AtghOtp/X3k6BG5cdcQAua93vgXb5xei90BI9ukTGgE6F8+qY=", "ARC-Authentication-Results": "i=1; server2.sourceware.org", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=gdcproject.org;\n s=MBO0001; t=1775068485;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding;\n bh=YhK/udaHQakofYL+e6MseF/pg3i+fX02Qw30IhNbaMw=;\n b=oaH4/+Q3zsLBqL5Z8UZxaesYip/5KQf59596aE5Cuv4dqAgKmbBIFJ8u/Y4bFnJtvmOLz6\n EiqdrGoSujqVaK8R61LWAbupl/BQNqQaPZXZyNz7o9zV+BFBX9tyg9vw6HaLwoLke9CYMi\n VUsz4i3GWWJP6pYOteZUJ1jm4j3JkBgw7gHCcL/A6LfjRrdnvjPUc00S4UGZ23to596Q+0\n X7N7Tjk4bRaelRY472kWMYVwXj+Jnaahd01j0yFSpa1zGBBJA+d6ZjjdD6BUn/xoJoij6O\n QWGeo47bOh67bceZ83jZEvC3+9t5KtDNRSlfkO7q0g8SVRE5HI2pTRPiJJKnng==", "From": "Iain Buclaw <ibuclaw@gdcproject.org>", "To": "gcc-patches@gcc.gnu.org", "Cc": "Iain Buclaw <ibuclaw@gdcproject.org>", "Subject": "[committed][PATCH] d: Merge upstream dmd, druntime 55e64690bc,\n phobos 0c519ae39.", "Date": "Wed, 1 Apr 2026 20:34:31 +0200", "Message-ID": "<20260401183432.3740846-1-ibuclaw@gdcproject.org>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=UTF-8", "Content-Transfer-Encoding": "8bit", "X-Rspamd-Queue-Id": "4fmDDN6WnTz9v5t", "X-BeenThere": "gcc-patches@gcc.gnu.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "Gcc-patches mailing list <gcc-patches.gcc.gnu.org>", "List-Unsubscribe": "<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>", "List-Archive": "<https://gcc.gnu.org/pipermail/gcc-patches/>", "List-Post": "<mailto:gcc-patches@gcc.gnu.org>", "List-Help": "<mailto:gcc-patches-request@gcc.gnu.org?subject=help>", "List-Subscribe": "<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>", "Errors-To": "gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org" }, "content": "Hi,\n\nThis patch merges the D front-end and runtime library with upstream dmd\n55e64690bc, and the standard library with phobos 0c519ae39.\n\nThis, now in sync with v2.113 release branch.\n\nD front-end changes:\n\n\t- Import dmd v2.113.0-beta.1.\n\t- Add support for static array length inference.\n\t- Added trait `__traits(needsDestruction, T)'.\n\t- Added trait `__traits(isOverlapped, field)'.\n\nD runtime changes:\n\n\t- Import druntime v2.113.0-beta.1.\n\nPhobos changes:\n\n\t- Import phobos v2.113.0-beta.1.\n\nBootstrapped and regtested on x86_64-linux-gnu, committed to mainline.\n\nRegards,\nIain.\n\n---\ngcc/d/ChangeLog:\n\n\t* dmd/MERGE: Merge upstream dmd 55e64690bc.\n\t* dmd/VERSION: Bump version to v2.113.0-beta.1.\n\t* d-codegen.cc (d_build_call): Check if argument is already a\n\tTARGET_EXPR.\n\t* decl.cc (DeclVisitor::visit (FuncDeclaration *)): Don't use\n\t`__result' decl as named return value if it's a ref type.\n\t* expr.cc (ExprVisitor::visit (StructLiteralExp *)): Force TARGET_EXPR\n\tif init symbol needs to be mutable.\n\t* runtime.def (ARRAYSETLENGTHT): Remove.\n\t(ARRAYSETLENGTHIT): Remove.\n\t(ARRAYCOPY): Remove.\n\t(ARRAYAPPENDCTX): Remove.\n\t* typeinfo.cc (TypeInfoVisitor::visit (TypeInfoClassDeclaration *)):\n\tOnly scan class fields for pointer members.\n\nlibphobos/ChangeLog:\n\n\t* libdruntime/MERGE: Merge upstream druntime 55e64690bc.\n\t* src/MERGE: Merge upstream phobos 0c519ae39.\n\t* testsuite/libphobos.aa/test_aa.d: Update.\n\t* testsuite/libphobos.phobos/std_array.d: Regenerate.\n\t* testsuite/libphobos.phobos/std_mathspecial.d: Regenerate.\n\t* src/std/internal/windows/bcrypt.d: New file.\n---\n gcc/d/d-codegen.cc | 3 +-\n gcc/d/decl.cc | 2 +-\n gcc/d/dmd/MERGE | 2 +-\n gcc/d/dmd/VERSION | 2 +-\n gcc/d/dmd/aliasthis.d | 2 +-\n gcc/d/dmd/common/charactertables.d | 7 +\n gcc/d/dmd/common/file.d | 6 +-\n gcc/d/dmd/cparse.d | 177 ++++----\n gcc/d/dmd/cxxfrontend.d | 6 +\n gcc/d/dmd/dcast.d | 2 -\n gcc/d/dmd/dclass.d | 1 -\n gcc/d/dmd/declaration.d | 6 +-\n gcc/d/dmd/dimport.d | 2 +-\n gcc/d/dmd/dmodule.d | 4 +-\n gcc/d/dmd/dsymbol.d | 78 +++-\n gcc/d/dmd/dsymbol.h | 1 -\n gcc/d/dmd/dsymbolsem.d | 211 ++++++---\n gcc/d/dmd/dtemplate.d | 38 --\n gcc/d/dmd/dversion.d | 4 +-\n gcc/d/dmd/expression.h | 1 +\n gcc/d/dmd/expressionsem.d | 151 +++++--\n gcc/d/dmd/func.d | 9 -\n gcc/d/dmd/funcsem.d | 3 +-\n gcc/d/dmd/hdrgen.d | 7 +-\n gcc/d/dmd/id.d | 6 +\n gcc/d/dmd/initsem.d | 18 +-\n gcc/d/dmd/lexer.d | 24 +-\n gcc/d/dmd/mtype.d | 4 +\n gcc/d/dmd/nogc.d | 14 +-\n gcc/d/dmd/parse.d | 15 +\n gcc/d/dmd/root/ctfloat.d | 6 +-\n gcc/d/dmd/semantic3.d | 58 ++-\n gcc/d/dmd/statement.d | 1 +\n gcc/d/dmd/statement.h | 1 +\n gcc/d/dmd/statementsem.d | 7 +-\n gcc/d/dmd/templatesem.d | 44 +-\n gcc/d/dmd/traits.d | 78 +++-\n gcc/d/dmd/typesem.d | 52 ++-\n gcc/d/expr.cc | 2 +\n gcc/d/runtime.def | 16 -\n gcc/d/typeinfo.cc | 9 +-\n gcc/testsuite/gdc.test/compilable/diag20916.d | 64 +++\n .../gdc.test/compilable/imports/test22480b.d | 13 +\n .../gdc.test/compilable/issue22769.d | 19 +\n gcc/testsuite/gdc.test/compilable/new_xdtor.d | 10 +\n .../gdc.test/compilable/struct_allMembers.d | 14 +\n gcc/testsuite/gdc.test/compilable/test22480.d | 10 +\n gcc/testsuite/gdc.test/compilable/test22501.d | 12 +\n gcc/testsuite/gdc.test/compilable/test22543.d | 11 +\n gcc/testsuite/gdc.test/compilable/test22544.d | 11 +\n gcc/testsuite/gdc.test/compilable/test22752.d | 23 +\n gcc/testsuite/gdc.test/compilable/test24295.d | 11 +\n .../gdc.test/compilable/test_isOverlapped.d | 181 ++++++++\n .../test_nosharedaccess_ctor_nested_new.d | 13 +\n ...est_nosharedaccess_shared_struct_literal.d | 15 +\n gcc/testsuite/gdc.test/compilable/traits.d | 1 +\n gcc/testsuite/gdc.test/compilable/vgc3.d | 8 +-\n .../gdc.test/fail_compilation/fail19898a.d | 2 +-\n .../gdc.test/fail_compilation/fail19898b.d | 4 +-\n .../fail_compilation/getMember_private.d | 26 ++\n .../gdc.test/fail_compilation/issue22147.d | 16 +\n .../gdc.test/fail_compilation/safeprintf.d | 37 +-\n .../gdc.test/fail_compilation/staticarray.d | 12 +\n .../gdc.test/fail_compilation/test17977.d | 2 +-\n .../gdc.test/fail_compilation/test24295.d | 13 -\n .../gdc.test/fail_compilation/test9150.d | 2 +-\n .../test_isOverlapped_errors.d | 17 +\n gcc/testsuite/gdc.test/runnable/b10562.d | 8 +\n .../runnable/extra-files/sectiondefs.d | 13 +\n gcc/testsuite/gdc.test/runnable/foreach5.d | 31 ++\n gcc/testsuite/gdc.test/runnable/issue22621.d | 40 ++\n gcc/testsuite/gdc.test/runnable/issue22639.d | 35 ++\n gcc/testsuite/gdc.test/runnable/lexer.d | 12 +\n gcc/testsuite/gdc.test/runnable/rvalue1.d | 24 +\n gcc/testsuite/gdc.test/runnable/sctor.d | 37 ++\n gcc/testsuite/gdc.test/runnable/staticarray.d | 83 ++++\n .../gdc.test/runnable/structlit_rvalue.d | 64 ++-\n gcc/testsuite/gdc.test/runnable/test20275.d | 1 +\n gcc/testsuite/gdc.test/runnable/test22422.d | 21 +\n gcc/testsuite/gdc.test/runnable/test22594.d | 23 +\n gcc/testsuite/gdc.test/runnable/testaa2.d | 8 +\n gcc/testsuite/gdc.test/runnable/testaa3.d | 70 +++\n libphobos/libdruntime/MERGE | 2 +-\n libphobos/libdruntime/core/atomic.d | 130 +++---\n libphobos/libdruntime/core/attribute.d | 26 ++\n libphobos/libdruntime/core/gc/config.d | 6 +\n .../core/internal/array/capacity.d | 20 +-\n .../core/internal/array/construction.d | 5 +-\n .../core/internal/array/duplication.d | 27 +-\n .../core/internal/array/equality.d | 44 +-\n .../libdruntime/core/internal/array/utils.d | 12 +-\n libphobos/libdruntime/core/internal/atomic.d | 78 ++++\n .../core/internal/gc/impl/conservative/gc.d | 29 +-\n .../libdruntime/core/internal/lifetime.d | 13 +-\n libphobos/libdruntime/core/internal/newaa.d | 24 +\n libphobos/libdruntime/core/internal/traits.d | 69 ++-\n libphobos/libdruntime/core/lifetime.d | 35 +-\n libphobos/libdruntime/core/memory.d | 2 +-\n libphobos/libdruntime/core/stdc/stdatomic.d | 5 +-\n libphobos/libdruntime/core/stdc/stdint.d | 15 +-\n libphobos/libdruntime/core/stdc/stdio.d | 20 +-\n libphobos/libdruntime/core/stdc/time.d | 73 ++-\n libphobos/libdruntime/core/sync/condition.d | 4 +-\n libphobos/libdruntime/core/sync/mutex.d | 18 +-\n libphobos/libdruntime/core/sync/rwmutex.d | 122 +----\n .../libdruntime/core/sys/darwin/crt_externs.d | 2 +-\n .../libdruntime/core/sys/freebsd/config.d | 3 +-\n libphobos/libdruntime/core/sys/posix/aio.d | 12 +\n libphobos/libdruntime/core/sys/posix/dirent.d | 20 +\n libphobos/libdruntime/core/sys/posix/locale.d | 13 +-\n .../libdruntime/core/sys/posix/netinet/in_.d | 48 +-\n libphobos/libdruntime/core/sys/posix/pwd.d | 14 +-\n libphobos/libdruntime/core/sys/posix/sched.d | 1 +\n libphobos/libdruntime/core/sys/posix/setjmp.d | 8 +-\n libphobos/libdruntime/core/sys/posix/signal.d | 1 +\n .../libdruntime/core/sys/posix/stdc/time.d | 1 +\n libphobos/libdruntime/core/sys/posix/stdlib.d | 4 +-\n .../libdruntime/core/sys/posix/sys/msg.d | 5 +-\n .../libdruntime/core/sys/posix/sys/resource.d | 2 +-\n .../libdruntime/core/sys/posix/sys/select.d | 2 +\n .../libdruntime/core/sys/posix/sys/shm.d | 2 +-\n .../libdruntime/core/sys/posix/sys/socket.d | 2 +-\n .../libdruntime/core/sys/posix/sys/stat.d | 6 +-\n .../libdruntime/core/sys/posix/sys/statvfs.d | 2 +\n .../libdruntime/core/sys/posix/sys/time.d | 4 +\n .../libdruntime/core/sys/posix/sys/types.d | 6 +-\n libphobos/libdruntime/core/sys/posix/time.d | 10 +\n libphobos/libdruntime/core/sys/posix/unistd.d | 20 +-\n libphobos/libdruntime/core/sys/posix/utime.d | 2 +-\n .../libdruntime/core/sys/windows/winuser.d | 8 +-\n libphobos/libdruntime/core/thread/context.d | 1 +\n libphobos/libdruntime/core/thread/osthread.d | 30 +-\n libphobos/libdruntime/core/thread/package.d | 26 +-\n libphobos/libdruntime/core/thread/types.d | 17 +-\n libphobos/libdruntime/etc/valgrind/valgrind.d | 2 +-\n libphobos/libdruntime/object.d | 42 +-\n libphobos/libdruntime/rt/critical_.d | 8 +-\n libphobos/libdruntime/rt/dmain2.d | 61 ++-\n libphobos/libdruntime/rt/minfo.d | 6 +-\n libphobos/libdruntime/rt/monitor_.d | 12 +-\n libphobos/libdruntime/rt/profilegc.d | 4 +-\n libphobos/libdruntime/rt/sections.d | 4 +-\n libphobos/src/MERGE | 2 +-\n libphobos/src/Makefile.am | 17 +-\n libphobos/src/Makefile.in | 19 +-\n libphobos/src/index.dd | 48 +-\n libphobos/src/std/algorithm/setops.d | 26 ++\n libphobos/src/std/array.d | 425 +++++-------------\n libphobos/src/std/container/rbtree.d | 36 +-\n .../src/std/experimental/allocator/common.d | 3 +-\n libphobos/src/std/file.d | 17 +-\n libphobos/src/std/format/write.d | 11 +-\n .../src/std/internal/math/errorfunction.d | 5 +\n .../src/std/internal/math/gammafunction.d | 175 +++++---\n libphobos/src/std/internal/windows/bcrypt.d | 65 +++\n libphobos/src/std/logger/core.d | 11 +\n libphobos/src/std/logger/package.d | 86 +++-\n libphobos/src/std/math/hardware.d | 67 ++-\n libphobos/src/std/mathspecial.d | 61 ++-\n libphobos/src/std/signals.d | 5 -\n libphobos/src/std/socket.d | 2 +-\n libphobos/src/std/traits.d | 4 +-\n libphobos/src/std/typecons.d | 50 +--\n libphobos/src/std/uni/package.d | 19 +\n libphobos/src/std/variant.d | 17 +-\n libphobos/testsuite/libphobos.aa/test_aa.d | 35 ++\n .../testsuite/libphobos.phobos/std_array.d | 17 -\n .../libphobos.phobos/std_mathspecial.d | 29 +-\n 168 files changed, 3280 insertions(+), 1259 deletions(-)\n create mode 100644 gcc/testsuite/gdc.test/compilable/diag20916.d\n create mode 100644 gcc/testsuite/gdc.test/compilable/imports/test22480b.d\n create mode 100644 gcc/testsuite/gdc.test/compilable/issue22769.d\n create mode 100644 gcc/testsuite/gdc.test/compilable/new_xdtor.d\n create mode 100644 gcc/testsuite/gdc.test/compilable/struct_allMembers.d\n create mode 100644 gcc/testsuite/gdc.test/compilable/test22480.d\n create mode 100644 gcc/testsuite/gdc.test/compilable/test22501.d\n create mode 100644 gcc/testsuite/gdc.test/compilable/test22543.d\n create mode 100644 gcc/testsuite/gdc.test/compilable/test22544.d\n create mode 100644 gcc/testsuite/gdc.test/compilable/test22752.d\n create mode 100644 gcc/testsuite/gdc.test/compilable/test24295.d\n create mode 100644 gcc/testsuite/gdc.test/compilable/test_isOverlapped.d\n create mode 100644 gcc/testsuite/gdc.test/compilable/test_nosharedaccess_ctor_nested_new.d\n create mode 100644 gcc/testsuite/gdc.test/compilable/test_nosharedaccess_shared_struct_literal.d\n create mode 100644 gcc/testsuite/gdc.test/fail_compilation/getMember_private.d\n create mode 100644 gcc/testsuite/gdc.test/fail_compilation/issue22147.d\n create mode 100644 gcc/testsuite/gdc.test/fail_compilation/staticarray.d\n delete mode 100644 gcc/testsuite/gdc.test/fail_compilation/test24295.d\n create mode 100644 gcc/testsuite/gdc.test/fail_compilation/test_isOverlapped_errors.d\n create mode 100644 gcc/testsuite/gdc.test/runnable/extra-files/sectiondefs.d\n create mode 100644 gcc/testsuite/gdc.test/runnable/issue22621.d\n create mode 100644 gcc/testsuite/gdc.test/runnable/issue22639.d\n create mode 100644 gcc/testsuite/gdc.test/runnable/staticarray.d\n create mode 100644 gcc/testsuite/gdc.test/runnable/test22422.d\n create mode 100644 gcc/testsuite/gdc.test/runnable/test22594.d\n create mode 100644 libphobos/src/std/internal/windows/bcrypt.d", "diff": "diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc\nindex 562a8c7ae26..6e397decea0 100644\n--- a/gcc/d/d-codegen.cc\n+++ b/gcc/d/d-codegen.cc\n@@ -2349,7 +2349,8 @@ d_build_call (TypeFunction *tf, tree callable, tree object,\n \t\t - The ABI of the function expects the callee to destroy its\n \t\t arguments; when the caller is handles destruction, then `targ'\n \t\t has already been made into a temporary. */\n-\t if (!can_elide_copy_p (arg)\n+\t if (TREE_CODE (targ) != TARGET_EXPR\n+\t\t && !can_elide_copy_p (arg)\n \t\t && (arg->op == EXP::structLiteral\n \t\t || (!sd->postblit && !sd->dtor)\n \t\t || target.isCalleeDestroyingArgs (tf)))\ndiff --git a/gcc/d/decl.cc b/gcc/d/decl.cc\nindex fd2b1013a46..3b6f8544f2a 100644\n--- a/gcc/d/decl.cc\n+++ b/gcc/d/decl.cc\n@@ -1053,7 +1053,7 @@ public:\n \n \tif (d->isNRVO () && d->nrvo_var)\n \t var = get_symbol_decl (d->nrvo_var);\n-\telse if (d->vresult)\n+\telse if (d->vresult && !d->vresult->isRef ())\n \t var = get_symbol_decl (d->vresult);\n \n \tif (var != NULL_TREE)\ndiff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE\nindex 434ad554b84..a5b457e873c 100644\n--- a/gcc/d/dmd/MERGE\n+++ b/gcc/d/dmd/MERGE\n@@ -1,4 +1,4 @@\n-e7c34c13de2930f2becc484e12b2c2cf1a16f6e8\n+662104f52607c175ecb80633bd261932aa004561\n \n The first line of this file holds the git revision number of the last\n merge done from the dlang/dmd repository.\ndiff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION\nindex bb14ba5b599..7efbee7bbe6 100644\n--- a/gcc/d/dmd/VERSION\n+++ b/gcc/d/dmd/VERSION\n@@ -1 +1 @@\n-v2.112.0\n+v2.113.0-beta.1\ndiff --git a/gcc/d/dmd/aliasthis.d b/gcc/d/dmd/aliasthis.d\nindex bb1fcd02038..98380cb90f3 100644\n--- a/gcc/d/dmd/aliasthis.d\n+++ b/gcc/d/dmd/aliasthis.d\n@@ -41,7 +41,7 @@ extern (C++) final class AliasThis : Dsymbol\n {\n assert(!s);\n auto at = new AliasThis(loc, ident);\n- at.comment = comment;\n+ at.addComment(comment);\n return at;\n }\n \ndiff --git a/gcc/d/dmd/common/charactertables.d b/gcc/d/dmd/common/charactertables.d\nindex baa12620328..620c04cfffc 100644\n--- a/gcc/d/dmd/common/charactertables.d\n+++ b/gcc/d/dmd/common/charactertables.d\n@@ -185,6 +185,13 @@ bool c_isalnum(const int c)\n ( c >= 'A' && c <= 'Z'));\n }\n \n+///\n+bool isAlphaASCII(const dchar c)\n+{\n+ return (( c >= 'a' && c <= 'z') ||\n+ ( c >= 'A' && c <= 'Z'));\n+}\n+\n extern(D) private:\n \n // originally from dmd.root.utf\ndiff --git a/gcc/d/dmd/common/file.d b/gcc/d/dmd/common/file.d\nindex dad41de13ef..7b7c2bf6a7d 100644\n--- a/gcc/d/dmd/common/file.d\n+++ b/gcc/d/dmd/common/file.d\n@@ -121,7 +121,7 @@ struct FileMapping(Datum)\n \n if (size > 0 && size != ulong.max && size <= size_t.max)\n {\n- auto p = mmap(null, cast(size_t) size, is(Datum == const) ? PROT_READ : PROT_WRITE, MAP_SHARED, handle, 0);\n+ auto p = mmap(null, cast(size_t) size, is(Datum == const) ? PROT_READ : (PROT_READ | PROT_WRITE), MAP_SHARED, handle, 0);\n if (p == MAP_FAILED)\n {\n fprintf(stderr, \"mmap(null, %zu) for \\\"%s\\\" failed: %s\\n\", cast(size_t) size, filename, strerror(errno));\n@@ -382,8 +382,8 @@ struct FileMapping(Datum)\n }\n if (size > 0)\n {\n- auto p = mmap(null, size, PROT_WRITE, MAP_SHARED, handle, 0);\n- if (cast(ssize_t) p == -1)\n+ auto p = mmap(null, size, PROT_READ | PROT_WRITE, MAP_SHARED, handle, 0);\n+ if (p == MAP_FAILED)\n {\n fprintf(stderr, \"mmap() failed for \\\"%s\\\": %s\\n\", filename, strerror(errno));\n exit(1);\ndiff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d\nindex 32b4e0146a3..e1793ae5426 100644\n--- a/gcc/d/dmd/cparse.d\n+++ b/gcc/d/dmd/cparse.d\n@@ -2395,7 +2395,6 @@ final class CParser(AST) : Parser!AST\n xllong = 0x40,\n xfloat = 0x80,\n xdouble = 0x100,\n- xldouble = 0x200,\n xtag = 0x400,\n xident = 0x800,\n xvoid = 0x1000,\n@@ -3657,109 +3656,108 @@ final class CParser(AST) : Parser!AST\n if (!isGnuAttributeName())\n return;\n \n- if (token.value == TOK.identifier)\n+ if (token.value != TOK.identifier)\n {\n- if (token.ident == Id.aligned)\n- {\n- nextToken();\n- if (token.value == TOK.leftParenthesis)\n- {\n- nextToken();\n- AST.Expression exp = cparseConstantExp();\n- if (!specifier.alignAttrs)\n- specifier.alignAttrs = new AST.Expressions();\n- specifier.alignAttrs.push(exp);\n- check(TOK.rightParenthesis);\n- }\n- else\n- {\n- /* ignore __attribute__((aligned)), which sets the alignment to the largest value for any data\n- * type on the target machine. It's the opposite of __attribute__((packed))\n- */\n- }\n- }\n- else if (token.ident == Id.packed)\n- {\n- specifier.packalign.set(1);\n- specifier.packalign.setPack();\n- nextToken();\n- }\n- else if (token.ident == Id.always_inline) // https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html\n- {\n- specifier.scw |= SCW.xinline;\n- nextToken();\n- }\n- else if (token.ident == Id._deprecated)\n- {\n- specifier._deprecated = true;\n- nextToken();\n- if (token.value == TOK.leftParenthesis) // optional deprecation message\n- {\n- nextToken();\n- specifier.depMsg = cparseExpression();\n- check(TOK.rightParenthesis);\n- }\n- }\n- else if (token.ident == Id.dllimport)\n- {\n- specifier.dllimport = true;\n- nextToken();\n- }\n- else if (token.ident == Id.dllexport)\n- {\n- specifier.dllexport = true;\n- nextToken();\n- }\n- else if (token.ident == Id.naked)\n- {\n- specifier.naked = true;\n- nextToken();\n- }\n- else if (token.ident == Id.noinline)\n- {\n- specifier.scw |= SCW.xnoinline;\n- nextToken();\n- }\n- else if (token.ident == Id.noreturn)\n+ nextToken();\n+ if (token.value == TOK.leftParenthesis)\n+ cparseParens();\n+ return;\n+ }\n+\n+ if (token.ident == Id.aligned)\n+ {\n+ nextToken();\n+ if (token.value == TOK.leftParenthesis)\n {\n- specifier.noreturn = true;\n nextToken();\n+ AST.Expression exp = cparseConstantExp();\n+ if (!specifier.alignAttrs)\n+ specifier.alignAttrs = new AST.Expressions();\n+ specifier.alignAttrs.push(exp);\n+ check(TOK.rightParenthesis);\n }\n- else if (token.ident == Id._nothrow)\n+ else\n {\n- specifier._nothrow = true;\n- nextToken();\n+ /* ignore __attribute__((aligned)), which sets the alignment to the largest value for any data\n+ * type on the target machine. It's the opposite of __attribute__((packed))\n+ */\n }\n- else if (token.ident == Id._pure)\n+ }\n+ else if (token.ident == Id.packed)\n+ {\n+ specifier.packalign.set(1);\n+ specifier.packalign.setPack();\n+ nextToken();\n+ }\n+ else if (token.ident == Id.always_inline) // https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html\n+ {\n+ specifier.scw |= SCW.xinline;\n+ nextToken();\n+ }\n+ else if (token.ident == Id._deprecated)\n+ {\n+ specifier._deprecated = true;\n+ nextToken();\n+ if (token.value == TOK.leftParenthesis) // optional deprecation message\n {\n- specifier._pure = true;\n nextToken();\n+ specifier.depMsg = cparseExpression();\n+ check(TOK.rightParenthesis);\n }\n- else if (token.ident == Id.vector_size)\n+ }\n+ else if (token.ident == Id.dllimport)\n+ {\n+ specifier.dllimport = true;\n+ nextToken();\n+ }\n+ else if (token.ident == Id.dllexport)\n+ {\n+ specifier.dllexport = true;\n+ nextToken();\n+ }\n+ else if (token.ident == Id.naked)\n+ {\n+ specifier.naked = true;\n+ nextToken();\n+ }\n+ else if (token.ident == Id.noinline)\n+ {\n+ specifier.scw |= SCW.xnoinline;\n+ nextToken();\n+ }\n+ else if (token.ident == Id.noreturn)\n+ {\n+ specifier.noreturn = true;\n+ nextToken();\n+ }\n+ else if (token.ident == Id._nothrow)\n+ {\n+ specifier._nothrow = true;\n+ nextToken();\n+ }\n+ else if (token.ident == Id._pure)\n+ {\n+ specifier._pure = true;\n+ nextToken();\n+ }\n+ else if (token.ident == Id.vector_size)\n+ {\n+ nextToken();\n+ check(TOK.leftParenthesis);\n+ if (token.value == TOK.int32Literal)\n {\n+ const n = token.unsvalue;\n+ if (n < 1 || n & (n - 1) || ushort.max < n)\n+ error(\"__attribute__((vector_size(%lld))) must be an integer positive power of 2 and be <= 32,768\", cast(ulong)n);\n+ specifier.vector_size = cast(uint) n;\n nextToken();\n- check(TOK.leftParenthesis);\n- if (token.value == TOK.int32Literal)\n- {\n- const n = token.unsvalue;\n- if (n < 1 || n & (n - 1) || ushort.max < n)\n- error(\"__attribute__((vector_size(%lld))) must be an integer positive power of 2 and be <= 32,768\", cast(ulong)n);\n- specifier.vector_size = cast(uint) n;\n- nextToken();\n- }\n- else\n- {\n- error(\"value for vector_size expected, not `%s`\", token.toChars());\n- nextToken();\n- }\n- check(TOK.rightParenthesis);\n }\n else\n {\n+ error(\"value for vector_size expected, not `%s`\", token.toChars());\n nextToken();\n- if (token.value == TOK.leftParenthesis)\n- cparseParens();\n }\n+ check(TOK.rightParenthesis);\n }\n else\n {\n@@ -5076,8 +5074,7 @@ final class CParser(AST) : Parser!AST\n if (pt && *pt)\n t = *pt;\n }\n- if (t.mcache && t.mcache.typedefIdent)\n- {\n+ if ((t.mcache && t.mcache.typedefIdent) || t.isTypeBasic()) {\n t = t.copy();\n t.mcache = null;\n }\ndiff --git a/gcc/d/dmd/cxxfrontend.d b/gcc/d/dmd/cxxfrontend.d\nindex b4524a465bc..709aff03caa 100644\n--- a/gcc/d/dmd/cxxfrontend.d\n+++ b/gcc/d/dmd/cxxfrontend.d\n@@ -430,6 +430,12 @@ bool isLvalue(Expression exp)\n return dmd.expressionsem.isLvalue(exp);\n }\n \n+bool canElideCopy(Expression exp, Type to, bool checkMod)\n+{\n+ import dmd.expressionsem;\n+ return dmd.expressionsem.canElideCopy(exp, to, checkMod);\n+}\n+\n int getFieldIndex(ClassReferenceExp cre, Type fieldtype, uint fieldoffset)\n {\n import dmd.expressionsem;\ndiff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d\nindex 66c0b8a8c20..fdc29094aa0 100644\n--- a/gcc/d/dmd/dcast.d\n+++ b/gcc/d/dmd/dcast.d\n@@ -4374,8 +4374,6 @@ void fix16997(Scope* sc, UnaExp ue)\n extern (D) bool keyCompatibleWithoutCasting(Expression ekey, Type t2)\n {\n Type t1 = ekey.type;\n- t1 = t1.toBasetype();\n- t2 = t2.toBasetype();\n \n if ((t1.isStaticOrDynamicArray() || t1.ty == Tpointer) && t2.ty == t1.ty)\n {\ndiff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d\nindex 6385265f9f1..950f7db1137 100644\n--- a/gcc/d/dmd/dclass.d\n+++ b/gcc/d/dmd/dclass.d\n@@ -20,7 +20,6 @@ import dmd.aggregate;\n import dmd.arraytypes;\n import dmd.astenums;\n import dmd.declaration;\n-import dmd.dscope;\n import dmd.dsymbol;\n import dmd.errors;\n import dmd.func;\ndiff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d\nindex d9eab5b7642..e1a4f9bf656 100644\n--- a/gcc/d/dmd/declaration.d\n+++ b/gcc/d/dmd/declaration.d\n@@ -361,7 +361,7 @@ extern (C++) final class AliasDeclaration : Declaration\n //printf(\"AliasDeclaration::syntaxCopy()\\n\");\n assert(!s);\n AliasDeclaration sa = type ? new AliasDeclaration(loc, ident, type.syntaxCopy()) : new AliasDeclaration(loc, ident, aliassym.syntaxCopy(null));\n- sa.comment = comment;\n+ sa.addComment(comment);\n sa.storage_class = storage_class;\n return sa;\n }\n@@ -512,7 +512,7 @@ extern (C++) class VarDeclaration : Declaration\n //printf(\"VarDeclaration::syntaxCopy(%s)\\n\", toChars());\n assert(!s);\n auto v = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, _init ? _init.syntaxCopy() : null, storage_class);\n- v.comment = comment;\n+ v.addComment(comment);\n return v;\n }\n \n@@ -678,7 +678,7 @@ extern (C++) class BitFieldDeclaration : VarDeclaration\n //printf(\"BitFieldDeclaration::syntaxCopy(%s)\\n\", toChars());\n assert(!s);\n auto bf = new BitFieldDeclaration(loc, type ? type.syntaxCopy() : null, ident, width.syntaxCopy(), _init ? _init.syntaxCopy() : null);\n- bf.comment = comment;\n+ bf.addComment(comment);\n return bf;\n }\n \ndiff --git a/gcc/d/dmd/dimport.d b/gcc/d/dmd/dimport.d\nindex 201ab010ced..349f439ac2c 100644\n--- a/gcc/d/dmd/dimport.d\n+++ b/gcc/d/dmd/dimport.d\n@@ -95,7 +95,7 @@ extern (C++) final class Import : Dsymbol\n {\n assert(!s);\n auto si = new Import(loc, packages, id, aliasId, isstatic);\n- si.comment = comment;\n+ si.addComment(comment);\n assert(!(isstatic && names.length));\n if (names.length && !si.aliasId)\n si.ident = null;\ndiff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d\nindex 1baf39b0751..de1c8f0a575 100644\n--- a/gcc/d/dmd/dmodule.d\n+++ b/gcc/d/dmd/dmodule.d\n@@ -707,7 +707,7 @@ extern (C++) final class Module : Package\n */\n if (buf.length>= 4 && buf[0..4] == \"Ddoc\")\n {\n- comment = buf.ptr + 4;\n+ this.addComment(buf.ptr + 4);\n filetype = FileType.ddoc;\n if (!docfile)\n setDocfile();\n@@ -720,7 +720,7 @@ extern (C++) final class Module : Package\n */\n if (FileName.equalsExt(arg, dd_ext))\n {\n- comment = buf.ptr; // the optional Ddoc, if present, is handled above.\n+ this.addComment(buf.ptr); // the optional Ddoc, if present, is handled above.\n filetype = FileType.ddoc;\n if (!docfile)\n setDocfile();\ndiff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d\nindex ed02ead4cf8..f61c2998195 100644\n--- a/gcc/d/dmd/dsymbol.d\n+++ b/gcc/d/dmd/dsymbol.d\n@@ -45,9 +45,7 @@ import dmd.statement;\n import dmd.staticassert;\n import dmd.tokens;\n import dmd.visitor;\n-\n import dmd.common.outbuffer;\n-\n /***************************************\n * Calls dg(Dsymbol* sym) for each Dsymbol.\n * If dg returns !=0, stops and returns that value else returns 0.\n@@ -100,6 +98,62 @@ void foreachDsymbol(Dsymbols* symbols, scope void delegate(Dsymbol) dg)\n }\n }\n \n+private void addComment(Dsymbol d, const(char)* comment)\n+{\n+ scope v = new AddCommentVisitor(comment);\n+ d.accept(v);\n+}\n+\n+extern (C++) private class AddCommentVisitor: Visitor\n+{\n+ alias visit = Visitor.visit;\n+\n+ const(char)* comment;\n+\n+ this(const(char)* comment)\n+ {\n+ this.comment = comment;\n+ }\n+\n+ override void visit(Dsymbol d)\n+ {\n+ if (!comment || !*comment)\n+ return;\n+\n+ //printf(\"addComment '%s' to Dsymbol %p '%s'\\n\", comment, this, toChars());\n+ void* h = cast(void*)d; // just the pointer is the key\n+ auto p = h in d.commentHashTable;\n+ if (!p)\n+ {\n+ d.commentHashTable[h] = comment;\n+ return;\n+ }\n+ if (strcmp(*p, comment) != 0)\n+ {\n+ // Concatenate the two\n+ import dmd.lexer;\n+ *p = Lexer.combineComments((*p).toDString(), comment.toDString(), true);\n+ }\n+ }\n+ override void visit(AttribDeclaration atd)\n+ {\n+ if (comment && atd.decl)\n+ {\n+ atd.decl.foreachDsymbol( s => s.addComment(comment) );\n+ }\n+ }\n+ override void visit(ConditionalDeclaration cd)\n+ {\n+ if (comment)\n+ {\n+ cd.decl .foreachDsymbol( s => s.addComment(comment) );\n+ cd.elsedecl.foreachDsymbol( s => s.addComment(comment) );\n+ }\n+ }\n+ override void visit(StaticForeachDeclaration sfd) {}\n+}\n+\n+\n struct Visibility\n {\n ///\n@@ -765,16 +819,6 @@ extern (C++) class Dsymbol : ASTNode\n assert(0);\n }\n \n- /****************************************\n- * Add documentation comment to Dsymbol.\n- * Ignore NULL comments.\n- */\n- void addComment(const(char)* comment)\n- {\n- import dmd.dsymbolsem;\n- dmd.dsymbolsem.addComment(this, comment);\n- }\n-\n /// get documentation comment for this Dsymbol\n final const(char)* comment()\n {\n@@ -786,10 +830,10 @@ extern (C++) class Dsymbol : ASTNode\n }\n return null;\n }\n-\n- /* Shell around addComment() to avoid disruption for the moment */\n- final void comment(const(char)* comment) { addComment(comment); }\n-\n+ final void addComment(const(char)* c)\n+ {\n+ .addComment(this, c);\n+ }\n extern (D) __gshared const(char)*[void*] commentHashTable;\n \n \n@@ -1072,7 +1116,7 @@ public:\n {\n //printf(\"ScopeDsymbol::syntaxCopy('%s')\\n\", toChars());\n ScopeDsymbol sds = s ? cast(ScopeDsymbol)s : new ScopeDsymbol(ident);\n- sds.comment = comment;\n+ sds.addComment(comment);\n sds.members = arraySyntaxCopy(members);\n sds.endlinnum = endlinnum;\n return sds;\ndiff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h\nindex f6665c59223..44b88445fd4 100644\n--- a/gcc/d/dmd/dsymbol.h\n+++ b/gcc/d/dmd/dsymbol.h\n@@ -242,7 +242,6 @@ public:\n virtual Visibility visible();\n virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees\n \n- virtual void addComment(const utf8_t *comment);\n const utf8_t *comment(); // current value of comment\n \n UnitTestDeclaration *ddocUnittest();\ndiff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d\nindex 3e372b58e99..16709bc1136 100644\n--- a/gcc/d/dmd/dsymbolsem.d\n+++ b/gcc/d/dmd/dsymbolsem.d\n@@ -143,6 +143,15 @@ void addObjcSymbols(Dsymbol _this, ClassDeclarations* classes, ClassDeclarations\n objc.addSymbols(cd, classes, categories);\n }\n \n+private void fixupInvariantIdent(InvariantDeclaration invd, size_t offset)\n+{\n+ OutBuffer idBuf;\n+ idBuf.writestring(\"__invariant\");\n+ idBuf.print(offset);\n+\n+ invd.ident = Identifier.idPool(idBuf[]);\n+}\n+\n /************************************\n * Maybe `ident` was a C or C++ name. Check for that,\n * and suggest the D equivalent.\n@@ -2268,6 +2277,152 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor\n dsym.inuse--;\n sc2.pop();\n }\n+ static bool hasDollarDimension(TypeSArray tsa)\n+ {\n+ auto d = tsa.dim;\n+ if (!d)\n+ return false;\n+ auto ide = d.isIdentifierExp();\n+ if (!ide)\n+ return false;\n+ return ide.ident == Id.dollar;\n+ }\n+ static bool hasUnresolvedDollar(Type t)\n+ {\n+ auto tsa = t.isTypeSArray();\n+ if (!tsa)\n+ return false;\n+ if (hasDollarDimension(tsa))\n+ return true;\n+ return hasUnresolvedDollar(tsa.next);\n+ }\n+\n+ static void resolveDollarToZero(Type t, Loc loc)\n+ {\n+ auto tsa = t.isTypeSArray();\n+ if (!tsa)\n+ return;\n+ if (hasDollarDimension(tsa)) {\n+ tsa.dim = new IntegerExp(loc, 0, Type.tsize_t);\n+ }\n+ resolveDollarToZero(tsa.next, loc);\n+ }\n+\n+ static bool inferExprLength(Expression e, out dinteger_t len)\n+ {\n+ if (!e)\n+ return false;\n+\n+ if (auto ale = e.isArrayLiteralExp())\n+ {\n+ len = ale.elements.length;\n+ return true;\n+ }\n+\n+ if (auto ce = e.isCatExp())\n+ {\n+ dinteger_t l1;\n+ dinteger_t l2;\n+ if (inferExprLength(ce.e1, l1) && inferExprLength(ce.e2, l2))\n+ {\n+ len = l1 + l2;\n+ return true;\n+ }\n+ }\n+\n+ if (!e.type)\n+ return false;\n+\n+ auto tsan = e.type.toBasetype().isTypeSArray();\n+ if (!tsan)\n+ return false;\n+\n+ auto dim = tsan.dim.isIntegerExp();\n+ if (!dim)\n+ return false;\n+\n+ len = dim.value;\n+ return true;\n+ }\n+\n+ static bool inferSArrayDim(TypeSArray tsa, Expression ie, Loc loc, Scope* sc)\n+ {\n+ if (!tsa || !ie)\n+ return false;\n+\n+ if (!hasDollarDimension(tsa))\n+ return false;\n+\n+ if (auto ale = ie.isArrayLiteralExp())\n+ {\n+ dinteger_t len = ale.elements.length;\n+ tsa.dim = new IntegerExp(loc, len, Type.tsize_t);\n+ if (auto innerTsa = tsa.next.isTypeSArray())\n+ {\n+ if (ale.elements.length > 0)\n+ {\n+ auto firstElem = (*ale.elements)[0];\n+ inferSArrayDim(innerTsa, firstElem, loc, sc);\n+ }\n+ }\n+ return true;\n+ }\n+ else if (auto se = ie.isStringExp())\n+ {\n+ Type next = tsa.next.toBasetype();\n+ if (next.ty == TY.Tchar || next.ty == TY.Twchar || next.ty == TY.Tdchar)\n+ {\n+ tsa.dim = new IntegerExp(loc, se.len, Type.tsize_t);\n+ return true;\n+ }\n+ return false;\n+ }\n+\n+ // For other initializer forms, infer `$` only when the extent is\n+ // compile-time known: either a concatenation whose operands are\n+ // inferable, or any expression whose type is a static array.\n+ dinteger_t len;\n+ if (!inferExprLength(ie, len))\n+ return false;\n+\n+ tsa.dim = new IntegerExp(loc, len, Type.tsize_t);\n+ return true;\n+ }\n+\n+ auto tsa = dsym.type.isTypeSArray();\n+\n+ if (tsa && hasDollarDimension(tsa))\n+ {\n+ if (!dsym._init || dsym._init.isVoidInitializer())\n+ {\n+ .error(dsym.loc, \"cannot infer static array length from `$`, provide an initializer\");\n+ tsa.dim = new IntegerExp(dsym.loc, 0, Type.tsize_t);\n+ }\n+ else\n+ {\n+ Expression ie = dsym._init.initializerToExpression(null, sc.inCfile);\n+ if (ie && ie.op != EXP.error)\n+ {\n+ ie = ie.expressionSemantic(sc);\n+ ie = ie.optimize(WANTvalue);\n+ bool dimInferred = inferSArrayDim(tsa, ie, dsym.loc, sc);\n+ if (!dimInferred)\n+ {\n+ .error(dsym.loc, \"cannot infer static array length from `$`, provide an initializer\");\n+ tsa.dim = new IntegerExp(dsym.loc, 0, Type.tsize_t);\n+ }\n+ if (auto ale = ie.isArrayLiteralExp())\n+ dsym._init = new ExpInitializer(dsym.loc, ale);\n+ }\n+ }\n+ }\n+ if (tsa && hasUnresolvedDollar(tsa.next))\n+ {\n+ .error(dsym.loc, \"cannot infer static array length from `$`, provide an initializer\");\n+ resolveDollarToZero(tsa.next, dsym.loc);\n+ return;\n+ }\n+\n //printf(\" semantic type = %s\\n\", dsym.type ? dsym.type.toChars() : \"null\");\n if (dsym.type.ty == Terror)\n dsym.errors = true;\n@@ -3434,7 +3589,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor\n \n sc = sc.push();\n sc.stc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.gshared);\n- sc.inunion = scd.isunion ? scd : null;\n+ sc.inunion = scd.isunion ? scd : sc.inunion;\n sc.resetAllFlags();\n for (size_t i = 0; i < scd.decl.length; i++)\n {\n@@ -9244,60 +9399,6 @@ Lfail:\n return false;\n }\n \n-void addComment(Dsymbol d, const(char)* comment)\n-{\n- scope v = new AddCommentVisitor(comment);\n- d.accept(v);\n-}\n-\n-extern (C++) class AddCommentVisitor: Visitor\n-{\n- alias visit = Visitor.visit;\n-\n- const(char)* comment;\n-\n- this(const(char)* comment)\n- {\n- this.comment = comment;\n- }\n-\n- override void visit(Dsymbol d)\n- {\n- if (!comment || !*comment)\n- return;\n-\n- //printf(\"addComment '%s' to Dsymbol %p '%s'\\n\", comment, this, toChars());\n- void* h = cast(void*)d; // just the pointer is the key\n- auto p = h in d.commentHashTable;\n- if (!p)\n- {\n- d.commentHashTable[h] = comment;\n- return;\n- }\n- if (strcmp(*p, comment) != 0)\n- {\n- // Concatenate the two\n- *p = Lexer.combineComments((*p).toDString(), comment.toDString(), true);\n- }\n- }\n- override void visit(AttribDeclaration atd)\n- {\n- if (comment)\n- {\n- atd.include(null).foreachDsymbol( s => s.addComment(comment) );\n- }\n- }\n- override void visit(ConditionalDeclaration cd)\n- {\n- if (comment)\n- {\n- cd.decl .foreachDsymbol( s => s.addComment(comment) );\n- cd.elsedecl.foreachDsymbol( s => s.addComment(comment) );\n- }\n- }\n- override void visit(StaticForeachDeclaration sfd) {}\n-}\n-\n void checkCtorConstInit(Dsymbol d)\n {\n scope v = new CheckCtorConstInitVisitor();\ndiff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d\nindex 40f1f07cbbe..c2bcb0d491e 100644\n--- a/gcc/d/dmd/dtemplate.d\n+++ b/gcc/d/dmd/dtemplate.d\n@@ -299,44 +299,6 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol\n this.visibility = Visibility(Visibility.Kind.undefined);\n }\n \n- extern(D) void computeIsTrivialAlias(Dsymbol s)\n- {\n- /* Set isTrivialAliasSeq if this fits the pattern:\n- * template AliasSeq(T...) { alias AliasSeq = T; }\n- * or set isTrivialAlias if this fits the pattern:\n- * template Alias(T) { alias Alias = qualifiers(T); }\n- */\n- if (!(parameters && parameters.length == 1))\n- return;\n-\n- auto ad = s.isAliasDeclaration();\n- if (!ad || !ad.type)\n- return;\n-\n- auto ti = ad.type.isTypeIdentifier();\n-\n- if (!ti || ti.idents.length != 0)\n- return;\n-\n- if (auto ttp = (*parameters)[0].isTemplateTupleParameter())\n- {\n- if (ti.ident is ttp.ident &&\n- ti.mod == 0)\n- {\n- //printf(\"found isTrivialAliasSeq %s %s\\n\", s.toChars(), ad.type.toChars());\n- isTrivialAliasSeq = true;\n- }\n- }\n- else if (auto ttp = (*parameters)[0].isTemplateTypeParameter())\n- {\n- if (ti.ident is ttp.ident)\n- {\n- //printf(\"found isTrivialAlias %s %s\\n\", s.toChars(), ad.type.toChars());\n- isTrivialAlias = true;\n- }\n- }\n- }\n-\n override TemplateDeclaration syntaxCopy(Dsymbol)\n {\n //printf(\"TemplateDeclaration.syntaxCopy()\\n\");\ndiff --git a/gcc/d/dmd/dversion.d b/gcc/d/dmd/dversion.d\nindex 17d888b17ed..2036f783042 100644\n--- a/gcc/d/dmd/dversion.d\n+++ b/gcc/d/dmd/dversion.d\n@@ -39,7 +39,7 @@ extern (C++) final class DebugSymbol : Dsymbol\n {\n assert(!s);\n auto ds = new DebugSymbol(loc, ident);\n- ds.comment = comment;\n+ ds.addComment(comment);\n return ds;\n }\n \n@@ -75,7 +75,7 @@ extern (C++) final class VersionSymbol : Dsymbol\n {\n assert(!s);\n auto ds = new VersionSymbol(loc, ident);\n- ds.comment = comment;\n+ ds.addComment(comment);\n return ds;\n }\n \ndiff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h\nindex a8e1c9fb921..d3896125bd8 100644\n--- a/gcc/d/dmd/expression.h\n+++ b/gcc/d/dmd/expression.h\n@@ -62,6 +62,7 @@ namespace dmd\n bool isIdentical(const Expression *exp, const Expression *e);\n bool equals(const Expression *exp, const Expression *e);\n bool isLvalue(Expression *exp);\n+ bool canElideCopy(Expression *exp, Type *to, bool checkMod = false);\n int32_t getFieldIndex(ClassReferenceExp *cre, Type *fieldtype, uint32_t fieldoffset);\n void fillTupleExpExps(TupleExp *te, TupleDeclaration *tup);\n Optional<bool> toBool(Expression *exp);\ndiff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d\nindex 3dec8c5e749..840dc0fd957 100644\n--- a/gcc/d/dmd/expressionsem.d\n+++ b/gcc/d/dmd/expressionsem.d\n@@ -209,7 +209,14 @@ dinteger_t toInteger(Expression _this)\n // import dmd.hdrgen : EXPtoString;\n //printf(\"Expression %s\\n\", EXPtoString(op).ptr);\n if (!_this.type || !_this.type.isTypeError())\n+ {\n+ if (auto ide = _this.isIdentifierExp())\n+ {\n+ if (ide.ident == Id.dollar)\n+ return 0;\n+ }\n error(_this.loc, \"integer constant expression expected instead of `%s`\", _this.toChars());\n+ }\n return 0;\n }\n \n@@ -681,8 +688,19 @@ bool isLvalue(Expression _this)\n if (tf && tf.isRef)\n {\n if (auto dve = _this.e1.isDotVarExp())\n+ {\n if (dve.var.isCtorDeclaration())\n- return false;\n+ {\n+ // Allow taking the address of explicit constructor calls,\n+ // but not (__stmp = S(), __stmp).__ctor().\n+\n+ auto ve = lastComma(dve.e1).isVarExp();\n+ if (ve && (ve.var.storage_class & STC.temp) != 0)\n+ return false;\n+\n+ return isLvalue(dve.e1);\n+ }\n+ }\n return true; // function returns a reference\n }\n return false;\n@@ -761,8 +779,13 @@ bool isLvalue(Expression _this)\n * Determine if copy elision is allowed when copying an expression to\n * a typed storage. This basically elides a restricted subset of so-called\n * \"pure\" rvalues, i.e. expressions with no reference semantics.\n+ *\n+ * Note: Please avoid using `checkMod` parameter because `canElideCopy()`\n+ * essentially defines a value category and should eventually be merged with\n+ * `isLvalue()` to return [isLvalue, allowEmplacement].\n+ * Checking type compatibility here is only a stopgap measure.\n */\n-bool canElideCopy(Expression e, Type to, bool checkMod = true)\n+bool canElideCopy(Expression e, Type to, bool checkMod = false)\n {\n if (checkMod && !MODimplicitConv(e.type.mod, to.mod))\n return false;\n@@ -770,8 +793,19 @@ bool canElideCopy(Expression e, Type to, bool checkMod = true)\n static bool visitCallExp(CallExp e)\n {\n if (auto dve = e.e1.isDotVarExp())\n+ {\n if (dve.var.isCtorDeclaration())\n- return true;\n+ {\n+ // Allow (__stmp = S(), __stmp).__ctor() to be elided,\n+ // but force a copy for (s2 = s1.__ctor()).\n+\n+ auto ve = lastComma(dve.e1).isVarExp();\n+ if (ve && (ve.var.storage_class & STC.temp) != 0)\n+ return true;\n+\n+ return canElideCopy(dve.e1, e.type);\n+ }\n+ }\n \n auto tb = e.e1.type.toBasetype();\n if (tb.ty == Tdelegate || tb.ty == Tpointer)\n@@ -791,7 +825,7 @@ bool canElideCopy(Expression e, Type to, bool checkMod = true)\n return false;\n \n // If an aggregate can be elided, so are its fields\n- return canElideCopy(e.e1, e.e1.type, false);\n+ return canElideCopy(e.e1, e.e1.type);\n }\n \n switch (e.op)\n@@ -808,8 +842,7 @@ bool canElideCopy(Expression e, Type to, bool checkMod = true)\n case EXP.dotVariable:\n return visitDotVarExp(e.isDotVarExp());\n case EXP.structLiteral:\n- auto sle = e.isStructLiteralExp();\n- return !(checkMod && sle.useStaticInit && to.isMutable());\n+ return true;\n case EXP.variable:\n return (e.isVarExp().var.storage_class & STC.rvalue) != 0;\n default:\n@@ -1921,7 +1954,7 @@ extern (D) Expression doCopyOrMove(Scope* sc, Expression e, Type t, bool nrvo, b\n {\n e = callCpCtor(sc, e, t, nrvo);\n }\n- else if (move && sd && sd.hasMoveCtor && !canElideCopy(e, t ? t : e.type, false))\n+ else if (move && sd && sd.hasMoveCtor && !canElideCopy(e, t ? t : e.type))\n {\n // #move\n /* Rewrite as:\n@@ -3378,21 +3411,31 @@ private bool checkSafety(FuncDeclaration f, ref Loc loc, Scope* sc, Expressions*\n return false;\n }\n \n- if (f.printf)\n+ if (f.printf && (f.isSafe() || f.isTrusted()))\n {\n TypeFunction tf = f.type.isTypeFunction();\n assert(tf);\n const isVa_list = tf.parameterList.varargs == VarArg.none;\n const nparams = tf.parameterList.length;\n const nargs = arguments ? arguments.length : 0;\n- if (nparams == 1 && nargs)\n+ assert(nparams && nargs); // should have been verified already\n+ if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())\n {\n- if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())\n+ if (!isFormatSafe(se.peekString()))\n {\n- if (isFormatSafe(se.peekString()))\n- return false;\n+ if (sc.setUnsafe(false, loc,\n+ \"calling `pragma(printf)` function `%s` with format string `%s`\", f, se))\n+ .errorSupplemental(f.loc, \"`%s` is declared here\", f.toPrettyChars());\n+ return true;\n }\n }\n+ else\n+ {\n+ if (sc.setUnsafe(false, loc,\n+ \"calling `pragma(printf)` function `%s` with non-literal format string\", f))\n+ .errorSupplemental(f.loc, \"`%s` is declared here\", f.toPrettyChars());\n+ return true;\n+ }\n }\n \n if (!f.isSafe() && !f.isTrusted())\n@@ -5809,8 +5852,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor\n {\n arguments.push(makeTemplateItem(Id.InterpolatedExpression, str));\n Expressions* mix = new Expressions(new StringExp(e.loc, str));\n- // FIXME: i'd rather not use MixinExp but idk how to do it lol\n- arguments.push(new MixinExp(e.loc, mix));\n+ auto mixinExp = new MixinExp(e.loc, mix);\n+ auto res = mixinExp.expressionSemantic(sc);\n+ res = resolveProperties(sc, res);\n+ arguments.push(res);\n }\n }\n \n@@ -6959,8 +7004,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor\n \n if (!global.params.useGC && sc.needsCodegen())\n {\n- error(exp.loc, \"expression `%s` allocates with the GC and cannot be used with switch `-%s`\", exp.toErrMsg(), SwitchVariadic.ptr);\n- return setError();\n+ if (sc.func)\n+ {\n+ sc.func.skipCodegen = true; // same net result as calling checkGC\n+ goto LskipNewArrayLowering; // not checked in sc.needsCodegen() !?\n+ }\n }\n \n if (!sc.needsCodegen())\n@@ -8483,7 +8531,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor\n {\n exp.type = tf.next;\n auto casted_exp = exp.castTo(sc, t);\n- if (auto cex = casted_exp.isCastExp())\n+ if (auto cex = lastComma(casted_exp).isCastExp())\n {\n lowerCastExp(cex, sc);\n }\n@@ -10900,7 +10948,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor\n }\n }\n \n- if (auto cex = ex.isCastExp())\n+ if (auto cex = lastComma(ex).isCastExp())\n {\n lowerCastExp(cex, sc);\n }\n@@ -12398,7 +12446,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor\n }\n \n /* Rewrite as:\n- * (e1 = e2).postblit();\n+ * (e1 = e2).postblit(), e1;\n *\n * Blit assignment e1 = e2 returns a reference to the original e1,\n * then call the postblit on it.\n@@ -12410,6 +12458,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor\n e = new BlitExp(exp.loc, e, e2x);\n e = new DotVarExp(exp.loc, e, sd.postblit, false);\n e = new CallExp(exp.loc, e);\n+ e = new CommaExp(exp.loc, e, e1x);\n result = e.expressionSemantic(sc);\n return;\n }\n@@ -15045,12 +15094,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor\n return;\n }\n \n- // When array comparison is not lowered to `__equals`, `memcmp` is used, but\n- // GC checks occur before the expression is lowered to `memcmp` in e2ir.d.\n- // Thus, we will consider the literal arrays as on-stack arrays to avoid issues\n- // during GC checks.\n+ // Remaining array comparisons are trivially memcmp-able.\n+ // Allocate array-literal operands on the stack, since they don't\n+ // escape during the comparison; enabling @nogc for these.\n if (isArrayComparison)\n {\n+ exp.e1 = exp.e1.optimize(WANTvalue);\n+ exp.e2 = exp.e2.optimize(WANTvalue);\n+\n if (auto ale1 = exp.e1.isArrayLiteralExp())\n {\n ale1.onstack = true;\n@@ -16642,6 +16693,8 @@ bool checkValue(Expression e)\n */\n bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)\n {\n+ Expression root = e;\n+\n if (!sc ||\n !sc.previews.noSharedAccess ||\n sc.intypeof ||\n@@ -16697,7 +16750,14 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)\n if (e.placement)\n check(e.placement, false);\n if (e.thisexp)\n- check(e.thisexp, false);\n+ {\n+ // In a shared constructor, accessing the current\n+ // `this` is safe for nested allocation.\n+ // See test_nosharedaccess_ctor_nested_new.d\n+ if (!(sc.func && sc.func.isCtorDeclaration() && sc.func.type.isShared() &&\n+ e.thisexp.isThisExp()))\n+ check(e.thisexp, false);\n+ }\n return false;\n }\n \n@@ -16812,6 +16872,12 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)\n case EXP.star: return visitPtr(e.isPtrExp());\n case EXP.dotVariable: return visitDotVar(e.isDotVarExp());\n case EXP.index: return visitIndex(e.isIndexExp());\n+ case EXP.structLiteral:\n+ // Allow constructing a shared struct literal as a value,\n+ // but keep rejecting later accesses through that temporary.\n+ if (e is root && e.type && e.type.isShared())\n+ return false;\n+ return visit(e);\n }\n }\n \n@@ -19696,12 +19762,12 @@ private Expression buildAAIndexRValueX(Type t, Expression eaa, Expression ekey,\n auto call = new CallExp(loc, func, arguments);\n e0 = Expression.combine(e0, call);\n \n- if (arrayBoundsCheck(sc.func))\n+ if (sc.func && arrayBoundsCheck(sc.func))\n {\n // __aaget = _d_aaGetRvalueX(aa, key), __aaget ? __aaget : onRangeError(__FILE__, __LINE__)\n auto ei = new ExpInitializer(loc, e0);\n- auto vartmp = Identifier.generateId(\"__aaget\");\n- auto vardecl = new VarDeclaration(loc, null, vartmp, ei, STC.exptemp);\n+ auto id = Identifier.generateId(\"__aaget\");\n+ auto vardecl = new VarDeclaration(loc, null, id, ei, STC.exptemp);\n auto declexp = new DeclarationExp(loc, vardecl);\n \n //Expression idrange = new IdentifierExp(loc, Identifier.idPool(\"_d_arraybounds\"));\n@@ -19711,9 +19777,9 @@ private Expression buildAAIndexRValueX(Type t, Expression eaa, Expression ekey,\n auto locargs = new Expressions(new FileInitExp(loc, EXP.file), new LineInitExp(loc));\n auto ex = new CallExp(loc, idrange, locargs);\n \n- auto idvar1 = new IdentifierExp(loc, vartmp);\n- auto idvar2 = new IdentifierExp(loc, vartmp);\n- auto cond = new CondExp(loc, idvar1, idvar2, ex);\n+ auto ve1 = new VarExp(loc, vardecl);\n+ auto ve2 = new VarExp(loc, vardecl);\n+ auto cond = new CondExp(loc, ve1, ve2, ex);\n auto comma = new CommaExp(loc, declexp, cond);\n return comma;\n }\n@@ -19746,6 +19812,26 @@ Expression revertIndexAssignToRvalues(IndexExp ie, Scope* sc)\n return lowerAAIndexRead(ie, sc);\n }\n \n+// Ditto, but traverses DotVarExp from `alias this` rewrites.\n+private Expression revertModifiableAAIndexReads(Expression e, Scope* sc)\n+{\n+ // Recurse through dot-accesses (alias this produces DotVarExp on an inner IndexExp)\n+ if (auto dve = e.isDotVarExp())\n+ {\n+ dve.e1 = revertModifiableAAIndexReads(dve.e1, sc);\n+ return e;\n+ }\n+ if (auto ie = e.isIndexExp())\n+ {\n+ // Recurse first to handle deeper nesting\n+ ie.e1 = revertModifiableAAIndexReads(ie.e1, sc);\n+ // Lower a modifiable AA IndexExp to an rvalue read\n+ if (ie.modifiable && ie.e1.type.isTypeAArray())\n+ return lowerAAIndexRead(ie, sc);\n+ }\n+ return e;\n+}\n+\n // helper for rewriteAAIndexAssign\n private Expression implicitConvertToStruct(Expression ev, StructDeclaration sd, Scope* sc)\n {\n@@ -19796,6 +19882,7 @@ private Expression rewriteAAIndexAssign(BinExp exp, Scope* sc, ref Type[2] alias\n // find the AA of multi dimensional access\n for (auto ieaa = ie.e1.isIndexExp(); ieaa && ieaa.e1.type.isTypeAArray(); ieaa = ieaa.e1.isIndexExp())\n eaa = ieaa.e1;\n+ eaa = revertModifiableAAIndexReads(eaa, sc);\n eaa = extractSideEffect(sc, \"__aatmp\", e0, eaa);\n // collect all keys of multi dimensional access\n Expressions ekeys;\n@@ -19834,7 +19921,7 @@ private Expression rewriteAAIndexAssign(BinExp exp, Scope* sc, ref Type[2] alias\n auto tiargs = new Objects(taa.index, taa.next);\n func = new DotTemplateInstanceExp(loc, func, hook, tiargs);\n \n- auto arguments = new Expressions(eaa, ekeys[i-1], new IdentifierExp(loc, idfound));\n+ auto arguments = new Expressions(eaa, ekeys[i-1], new VarExp(loc, varfound));\n eaa = new CallExp(loc, func, arguments);\n if (i > 1)\n {\n@@ -19891,7 +19978,7 @@ private Expression rewriteAAIndexAssign(BinExp exp, Scope* sc, ref Type[2] alias\n ex = new CastExp(ex.loc, ex, Type.tvoid);\n ey = new CastExp(ey.loc, ey, Type.tvoid);\n }\n- Expression condfound = new IdentifierExp(loc, idfound);\n+ Expression condfound = new VarExp(loc, varfound);\n ex = new CondExp(loc, condfound, ex, ey);\n ex = Expression.combine(e0, ex);\n ex.isCommaExp().originalExp = exp;\ndiff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d\nindex 1f902e4f184..a2ccc4c2256 100644\n--- a/gcc/d/dmd/func.d\n+++ b/gcc/d/dmd/func.d\n@@ -1116,15 +1116,6 @@ extern (C++) final class InvariantDeclaration : FuncDeclaration\n {\n v.visit(this);\n }\n-\n- extern (D) void fixupInvariantIdent(size_t offset)\n- {\n- OutBuffer idBuf;\n- idBuf.writestring(\"__invariant\");\n- idBuf.print(offset);\n-\n- ident = Identifier.idPool(idBuf[]);\n- }\n }\n \n \ndiff --git a/gcc/d/dmd/funcsem.d b/gcc/d/dmd/funcsem.d\nindex e153e11067e..31b6397ecf5 100644\n--- a/gcc/d/dmd/funcsem.d\n+++ b/gcc/d/dmd/funcsem.d\n@@ -2769,6 +2769,7 @@ void buildResultVar(FuncDeclaration fd, Scope* sc, Type tret)\n * fbody.dsymbolSemantic() running, vresult.type might be modified.\n */\n fd.vresult = new VarDeclaration(loc, tret, Id.result, null);\n+ fd.vresult._init = new VoidInitializer(loc); // hdrgen requires _init\n fd.vresult.storage_class |= STC.nodtor | STC.temp;\n if (!fd.isVirtual())\n fd.vresult.storage_class |= STC.const_;\n@@ -2779,7 +2780,7 @@ void buildResultVar(FuncDeclaration fd, Scope* sc, Type tret)\n if (sc && fd.vresult.semanticRun == PASS.initial)\n {\n TypeFunction tf = fd.type.toTypeFunction();\n- if (tf.isRef)\n+ if (fd.isNRVO || tf.isRef)\n fd.vresult.storage_class |= STC.ref_;\n else if (target.isReturnOnStack(tf, fd.needThis()))\n fd.vresult.nrvo = true;\ndiff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d\nindex 7b50af1685f..71e94c2a90c 100644\n--- a/gcc/d/dmd/hdrgen.d\n+++ b/gcc/d/dmd/hdrgen.d\n@@ -58,6 +58,7 @@ struct HdrGenState\n bool fullDump; /// true if generating a full AST dump file\n bool importcHdr; /// true if generating a .di file from an ImportC file\n bool inCAlias; /// Set to prevent ImportC translating typedefs as `alias X = X`\n+ bool inFuncReturn; /// Set when printing function return type to avoid typedef name\n bool doFuncBodies; /// include function bodies in output\n bool vcg_ast; /// write out codegen-ast\n bool skipConstraints; // skip constraints when doing templates\n@@ -4096,7 +4097,9 @@ private void visitFuncIdentWithPostfix(TypeFunction t, const char[] ident, ref O\n buf.write(\"static \");\n if (t.next)\n {\n+ hgs.inFuncReturn = true;\n typeToBuffer(t.next, null, buf, hgs);\n+ hgs.inFuncReturn = false;\n if (ident)\n buf.put(' ');\n }\n@@ -4165,7 +4168,9 @@ private void visitFuncIdentWithPrefix(TypeFunction t, const Identifier ident, Te\n }\n else if (t.next)\n {\n+ hgs.inFuncReturn = true;\n typeToBuffer(t.next, null, buf, hgs);\n+ hgs.inFuncReturn = false;\n if (ident)\n buf.put(' ');\n }\n@@ -4547,7 +4552,7 @@ private void typeToBufferx(Type t, ref OutBuffer buf, ref HdrGenState hgs)\n buf.put(\"noreturn\");\n }\n \n- if (hgs.importcHdr && !hgs.inCAlias && t.mcache && t.mcache.typedefIdent)\n+ if (hgs.importcHdr && !hgs.inCAlias && !hgs.inFuncReturn && t.mcache && t.mcache.typedefIdent)\n {\n buf.put(t.mcache.typedefIdent.toString());\n return;\ndiff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d\nindex beb3de62b35..2b814a8074d 100644\n--- a/gcc/d/dmd/id.d\n+++ b/gcc/d/dmd/id.d\n@@ -418,6 +418,7 @@ immutable Msgtable[] msgtable =\n { \"isAbstractClass\" },\n { \"isArithmetic\" },\n { \"isAssociativeArray\" },\n+ { \"isOverlapped\" },\n { \"isBitfield\" },\n { \"isFinalClass\" },\n { \"isTemplate\" },\n@@ -483,6 +484,7 @@ immutable Msgtable[] msgtable =\n { \"isCopyable\" },\n { \"toType\" },\n { \"parameters\" },\n+ { \"needsDestruction\" },\n \n // For C++ mangling\n { \"allocator\" },\n@@ -498,6 +500,7 @@ immutable Msgtable[] msgtable =\n { \"udaOptional\", \"optional\"},\n { \"udaMustUse\", \"mustuse\" },\n { \"udaStandalone\", \"standalone\" },\n+ { \"udaSection\", \"section\" },\n \n // Editions\n { \"__edition_latest_do_not_use\", },\n@@ -540,6 +543,9 @@ immutable Msgtable[] msgtable =\n { \"undef\" },\n { \"ident\" },\n { \"packed\" },\n+\n+ // for inline assembler\n+ { \"op\" },\n ];\n \n \ndiff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d\nindex 21ad68fb6ce..644577f72af 100644\n--- a/gcc/d/dmd/initsem.d\n+++ b/gcc/d/dmd/initsem.d\n@@ -1468,6 +1468,22 @@ Expression initializerToExpression(Initializer init, Type itype = null, const bo\n }\n }\n \n+ // enforce the element type only if the dimensions match, otherwise the value\n+ // might be used as an initializer for the whole array at another dimension\n+ Type isTypeArray(Type tn)\n+ {\n+ auto ty = tn ? tn.ty : Tnone;\n+ return ty == Tarray || ty == Tsarray || ty == Taarray || ty == Tvector ? tn : null;\n+ }\n+ Type tnext = isTypeArray(itype);\n+ auto initn = init;\n+ while (tnext && initn)\n+ {\n+ tnext = isTypeArray(tnext.nextOf());\n+ initn = initn.value.length ? initn.value[0].isArrayInitializer() : null;\n+ }\n+ Type telem = itype && !tnext && !initn ? itype.nextOf() : null;\n+\n auto elements = new Expressions(edim);\n elements.zero();\n size_t j = 0;\n@@ -1478,7 +1494,7 @@ Expression initializerToExpression(Initializer init, Type itype = null, const bo\n assert(j < edim);\n if (Initializer iz = init.value[i])\n {\n- if (Expression ex = iz.initializerToExpression(null, isCfile))\n+ if (Expression ex = iz.initializerToExpression(telem, isCfile))\n {\n (*elements)[j] = ex;\n ++j;\ndiff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d\nindex b5b82a91df6..c51fdf6123e 100644\n--- a/gcc/d/dmd/lexer.d\n+++ b/gcc/d/dmd/lexer.d\n@@ -62,7 +62,11 @@ struct CompileEnv\n */\n class Lexer\n {\n- private __gshared OutBuffer stringbuffer;\n+ private __gshared\n+ {\n+ OutBuffer stringbuffer;\n+ OutBuffer stringbuffersecondary; // functions that use stringbuffer can call scan that needs this.\n+ }\n \n BaseLoc* baseLoc; // Used to generate `scanloc`, which is just an index into this data structure\n Loc scanloc; // for error messages\n@@ -1431,7 +1435,7 @@ class Lexer\n p++;\n break;\n default:\n- if (isalpha(*p) || (p != idstart && isdigit(*p)))\n+ if (isAlphaASCII(*p) || (p != idstart && isdigit(*p)))\n continue;\n error(loc, \"unterminated named entity &%.*s;\", cast(int)(p - idstart + 1), idstart);\n c = '?';\n@@ -1766,7 +1770,7 @@ class Lexer\n uint blankrol = 0;\n uint startline = 0;\n p++;\n- stringbuffer.setsize(0);\n+ stringbuffersecondary.setsize(0);\n while (1)\n {\n const s = p;\n@@ -1785,7 +1789,7 @@ class Lexer\n }\n if (hereid)\n {\n- stringbuffer.writeUTF8(c);\n+ stringbuffersecondary.writeUTF8(c);\n continue;\n }\n break;\n@@ -1825,7 +1829,7 @@ class Lexer\n delimright = ']';\n else if (c == '<')\n delimright = '>';\n- else if (isalpha(c) || c == '_' || (c >= 0x80 && charLookup.isStart(c)))\n+ else if (isAlphaASCII(c) || c == '_' || (c >= 0x80 && charLookup.isStart(c)))\n {\n // Start of identifier; must be a heredoc\n Token tok;\n@@ -1875,7 +1879,7 @@ class Lexer\n goto Ldone;\n \n // we're looking for a new identifier token\n- if (startline && (isalpha(c) || c == '_' || (c >= 0x80 && charLookup.isStart(c))) && hereid)\n+ if (startline && (isAlphaASCII(c) || c == '_' || (c >= 0x80 && charLookup.isStart(c))) && hereid)\n {\n Token tok;\n auto psave = p;\n@@ -1890,7 +1894,7 @@ class Lexer\n }\n p = psave;\n }\n- stringbuffer.writeUTF8(c);\n+ stringbuffersecondary.writeUTF8(c);\n startline = 0;\n }\n }\n@@ -1903,7 +1907,7 @@ class Lexer\n error(\"delimited string must end in `\\\"`\");\n else\n error(token.loc, \"delimited string must end in `%c\\\"`\", delimright);\n- result.setString(stringbuffer);\n+ result.setString(stringbuffersecondary);\n stringPostfix(result);\n }\n \n@@ -2404,7 +2408,7 @@ class Lexer\n case '.':\n if (p[1] == '.')\n goto Ldone; // if \"..\"\n- if (isalpha(p[1]) || p[1] == '_' || p[1] & 0x80)\n+ if (isAlphaASCII(p[1]) || p[1] == '_' || p[1] & 0x80)\n {\n if (Ccompile && (p[1] == 'f' || p[1] == 'F' || p[1] == 'l' || p[1] == 'L'))\n goto Lreal; // if `0.f` or `0.L`\n@@ -2477,7 +2481,7 @@ class Lexer\n case '.':\n if (p[1] == '.')\n goto Ldone; // if \"..\"\n- if (base <= 10 && n > 0 && (isalpha(p[1]) || p[1] == '_' || p[1] & 0x80))\n+ if (base <= 10 && n > 0 && (isAlphaASCII(p[1]) || p[1] == '_' || p[1] & 0x80))\n {\n if (Ccompile && base == 10 &&\n (p[1] == 'e' || p[1] == 'E' || p[1] == 'f' || p[1] == 'F' || p[1] == 'l' || p[1] == 'L'))\ndiff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d\nindex 74364d05e3f..a64502bb6cf 100644\n--- a/gcc/d/dmd/mtype.d\n+++ b/gcc/d/dmd/mtype.d\n@@ -404,6 +404,10 @@ extern (C++) abstract class Type : ASTNode\n * we bank on the idea that usually only one of variants exist.\n * It will also speed up code because these are rarely referenced and\n * so need not be in the cache.\n+ *\n+ * NOTE: The cache stores the naked type at the \"identity\" position.\n+ * For example, a \"shared const T\" type will have its naked \"T\" type\n+ * in the field \"scto\". See also: dmd.typesem.nakedOf(Type).\n */\n Type cto; // MODFlags.const_\n Type ito; // MODFlags.immutable_\ndiff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d\nindex c9b8a0275b8..e8dde1414be 100644\n--- a/gcc/d/dmd/nogc.d\n+++ b/gcc/d/dmd/nogc.d\n@@ -294,16 +294,20 @@ Expression checkGC(Expression e, Scope* sc)\n return e;\n }\n \n-extern (D) void printGCUsage(FuncDeclaration fd, Loc loc, const(char)* warn)\n+/// Returns: whether GC usage inside `fd` should be printed for the -vgc flag\n+extern (D) bool vgcEnabled(FuncDeclaration fd)\n {\n if (!global.params.v.gc)\n- return;\n+ return false;\n \n Module m = fd.getModule();\n- if (m && m.isRoot() && !fd.inUnittest())\n- {\n+ return (m && m.isRoot() && !fd.inUnittest());\n+}\n+\n+extern (D) void printGCUsage(FuncDeclaration fd, Loc loc, const(char)* warn)\n+{\n+ if (vgcEnabled(fd))\n message(loc, \"vgc: %s\", warn);\n- }\n }\n \n /**\ndiff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d\nindex c8ca3a1a0f2..1bdcf44c338 100644\n--- a/gcc/d/dmd/parse.d\n+++ b/gcc/d/dmd/parse.d\n@@ -79,6 +79,21 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer\n this.doUnittests = doUnittests;\n }\n \n+ /** Instead of parsing text to get tokens, provide a list of tokens ending with null.\n+ * Note that the token list will be consumed (added to the tokenFreelist) by the lexer4.\n+ * Params:\n+ * pToken = pointer to first token in list, take ownership of list\n+ * linnum = line number to use for the tokens\n+ */\n+ extern (D)\n+ void setTokenList(ref Token* pToken, int linnum)\n+ {\n+ this.token = *pToken;\n+ pToken = null; // take ownership\n+ this.baseLoc.startLine = linnum;\n+ this.linnum = linnum;\n+ }\n+\n /++\n + Parse a module, i.e. the optional `module x.y.z` declaration and all declarations\n + found in the current file.\ndiff --git a/gcc/d/dmd/root/ctfloat.d b/gcc/d/dmd/root/ctfloat.d\nindex 87cac4c3501..f8ffdd009a4 100644\n--- a/gcc/d/dmd/root/ctfloat.d\n+++ b/gcc/d/dmd/root/ctfloat.d\n@@ -25,8 +25,12 @@ extern (C++) struct CTFloat\n \n version (GNU)\n enum yl2x_supported = false;\n+ else version (AArch64)\n+ enum yl2x_supported = false;\t// no x87 FPU\n else\n- enum yl2x_supported = __traits(compiles, core.math.yl2x(1.0L, 2.0L));\n+ enum yl2x_supported = is(real_t == real) &&\n+ __traits(compiles, core.math.yl2x(1.0L, 2.0L));\n+\n enum yl2xp1_supported = yl2x_supported;\n \n pure static real_t fabs(real_t x);\ndiff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d\nindex 15677f1fc6f..c02bb86db73 100644\n--- a/gcc/d/dmd/semantic3.d\n+++ b/gcc/d/dmd/semantic3.d\n@@ -961,8 +961,10 @@ private extern(C++) final class Semantic3Visitor : Visitor\n \n /* https://issues.dlang.org/show_bug.cgi?id=10789\n * If NRVO is not possible, all returned lvalues should call their postblits.\n+ * For functions with a __result variable, postblits will be called later\n+ * during initialization of __result.\n */\n- if (!funcdecl.isNRVO)\n+ if (!funcdecl.isNRVO && !funcdecl.vresult)\n exp = doCopyOrMove(sc2, exp, f.next, true, true);\n \n if (tret.hasPointers())\n@@ -973,13 +975,25 @@ private extern(C++) final class Semantic3Visitor : Visitor\n \n if (funcdecl.vresult)\n {\n- // Create: return vresult = exp;\n- if (canElideCopy(exp, funcdecl.vresult.type, false))\n- exp = new ConstructExp(rs.loc, funcdecl.vresult, exp);\n- else\n- exp = new BlitExp(rs.loc, funcdecl.vresult, exp);\n+ Scope* scret = sc2;\n+\n+ if (rs.fesFunc)\n+ {\n+ // Create a scope with foreach body being `.parent`\n+ // and `funcdecl` as `.func`. So the return value\n+ // is aware of closure access, but picks up\n+ // attributes and instantiates templated copy/move\n+ // ctors in the context of `funcdecl`.\n+ // BUG: remove this fragile hack\n+ scret = rs.fesFunc._scope.push();\n+ scret.parent = rs.fesFunc;\n+ scret.func = funcdecl;\n+ }\n \n- exp.type = funcdecl.vresult.type;\n+ // Create: return (vresult = exp, vresult);\n+ exp = new ConstructExp(rs.loc, funcdecl.vresult, exp);\n+ exp = exp.expressionSemantic(scret);\n+ exp = Expression.combine(exp, new VarExp(rs.loc, funcdecl.vresult));\n \n if (rs.caseDim)\n exp = Expression.combine(exp, new IntegerExp(rs.caseDim));\n@@ -1888,9 +1902,32 @@ extern (D) bool checkClosure(FuncDeclaration fd)\n else\n {\n fd.printGCUsage(fd.loc, \"using closure causes GC allocation\");\n+\n+ findClosureVars(fd, (FuncDeclaration f, VarDeclaration v) {\n+ if (!fd.vgcEnabled)\n+ return;\n+\n+ .message(f.loc, \"vgc: %s `%s` closes over variable `%s`\",\n+ f.kind, f.toErrMsg(), v.toErrMsg());\n+ if (v.ident != Id.This)\n+ .message(v.loc, \"vgc: `%s` declared here\", v.toErrMsg());\n+ });\n return false;\n }\n \n+ findClosureVars(fd, (FuncDeclaration f, VarDeclaration v) {\n+ .errorSupplemental(f.loc, \"%s `%s` closes over variable `%s`\",\n+ f.kind, f.toErrMsg(), v.toErrMsg());\n+ if (v.ident != Id.This)\n+ .errorSupplemental(v.loc, \"`%s` declared here\", v.toErrMsg());\n+ });\n+ return true;\n+}\n+\n+/// For an outer function `fd`, find inner functions that cause a closure to be generated for it.\n+/// Pass to `sink` each nested function along with the local variable that closes over `fd`'s stackframe\n+private void findClosureVars(FuncDeclaration fd, scope void delegate(FuncDeclaration, VarDeclaration) sink)\n+{\n FuncDeclarations a;\n \n if (fd.closureVars.length > 0)\n@@ -1913,16 +1950,11 @@ extern (D) bool checkClosure(FuncDeclaration fd)\n if (!a.contains(f))\n {\n a.push(f);\n- .errorSupplemental(f.loc, \"%s `%s` closes over variable `%s`\",\n- f.kind, f.toErrMsg(), v.toChars());\n- if (v.ident != Id.This)\n- .errorSupplemental(v.loc, \"`%s` declared here\", v.toChars());\n+ sink(f, v);\n }\n break LcheckAncestorsOfANestedRef;\n }\n }\n }\n }\n-\n- return true;\n }\ndiff --git a/gcc/d/dmd/statement.d b/gcc/d/dmd/statement.d\nindex 0641c0a85ce..ff162aa79b7 100644\n--- a/gcc/d/dmd/statement.d\n+++ b/gcc/d/dmd/statement.d\n@@ -1308,6 +1308,7 @@ extern (C++) final class ReturnStatement : Statement\n {\n Expression exp;\n size_t caseDim;\n+ FuncDeclaration fesFunc; // nested function for foreach it is in\n \n extern (D) this(Loc loc, Expression exp) @safe\n {\ndiff --git a/gcc/d/dmd/statement.h b/gcc/d/dmd/statement.h\nindex d49f4e47dbe..7074052fd2e 100644\n--- a/gcc/d/dmd/statement.h\n+++ b/gcc/d/dmd/statement.h\n@@ -518,6 +518,7 @@ class ReturnStatement final : public Statement\n public:\n Expression *exp;\n size_t caseDim;\n+ FuncDeclaration *fesFunc; // nested function for foreach it is in\n \n ReturnStatement *syntaxCopy() override;\n \ndiff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d\nindex d602f8d30e6..2f7b442d3a5 100644\n--- a/gcc/d/dmd/statementsem.d\n+++ b/gcc/d/dmd/statementsem.d\n@@ -1657,7 +1657,8 @@ Statement statementSemanticVisit(Statement s, Scope* sc)\n /* Declare param, which we will set to be the\n * result of condition.\n */\n- auto ei = new ExpInitializer(ifs.loc, ifs.condition);\n+ // Make sure the location of the initializer reflects the condition, not the if statement.\n+ auto ei = new ExpInitializer(ifs.condition.loc, ifs.condition);\n ifs.match = new VarDeclaration(ifs.loc, ifs.param.type, ifs.param.ident, ei);\n ifs.match.parent = scd.func;\n ifs.match.storage_class |= ifs.param.storageClass;\n@@ -2480,8 +2481,12 @@ Statement statementSemanticVisit(Statement s, Scope* sc)\n //printf(\"ReturnStatement.dsymbolSemantic() %s\\n\", toChars(rs));\n \n FuncDeclaration fd = sc.parent.isFuncDeclaration();\n+\n if (fd.fes)\n+ {\n+ rs.fesFunc = fd;\n fd = fd.fes.func; // fd is now function enclosing foreach\n+ }\n \n auto tf = fd.type.isTypeFunction();\n \ndiff --git a/gcc/d/dmd/templatesem.d b/gcc/d/dmd/templatesem.d\nindex a2bed8a7cd1..304a7a8fd1f 100644\n--- a/gcc/d/dmd/templatesem.d\n+++ b/gcc/d/dmd/templatesem.d\n@@ -47,6 +47,7 @@ import dmd.mtype;\n import dmd.opover;\n import dmd.optimize;\n import dmd.root.array;\n+import dmd.root.string : toDString;\n import dmd.common.outbuffer;\n import dmd.rootobject;\n import dmd.semantic2;\n@@ -455,6 +456,44 @@ void computeOneMember(TemplateDeclaration td)\n }\n }\n \n+private void computeIsTrivialAlias(TemplateDeclaration td, Dsymbol s)\n+{\n+ /* Set isTrivialAliasSeq if this fits the pattern:\n+ * template AliasSeq(T...) { alias AliasSeq = T; }\n+ * or set isTrivialAlias if this fits the pattern:\n+ * template Alias(T) { alias Alias = qualifiers(T); }\n+ */\n+ if (!(td.parameters && td.parameters.length == 1))\n+ return;\n+\n+ auto ad = s.isAliasDeclaration();\n+ if (!ad || !ad.type)\n+ return;\n+\n+ auto ti = ad.type.isTypeIdentifier();\n+\n+ if (!ti || ti.idents.length != 0)\n+ return;\n+\n+ if (auto ttp = (*td.parameters)[0].isTemplateTupleParameter())\n+ {\n+ if (ti.ident is ttp.ident &&\n+ ti.mod == 0)\n+ {\n+ //printf(\"found isTrivialAliasSeq %s %s\\n\", s.toChars(), ad.type.toChars());\n+ td.isTrivialAliasSeq = true;\n+ }\n+ }\n+ else if (auto ttp = (*td.parameters)[0].isTemplateTypeParameter())\n+ {\n+ if (ti.ident is ttp.ident)\n+ {\n+ //printf(\"found isTrivialAlias %s %s\\n\", s.toChars(), ad.type.toChars());\n+ td.isTrivialAlias = true;\n+ }\n+ }\n+}\n+\n bool declareParameter(TemplateParameter _this, Scope* sc)\n {\n static bool typeDeclareParameter(TemplateTypeParameter _this, Scope* sc)\n@@ -873,11 +912,10 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList\n }\n \n timeTraceBeginEvent(TimeTraceEventType.sema1TemplateInstance);\n- scope (exit) timeTraceEndEvent(TimeTraceEventType.sema1TemplateInstance, tempinst);\n-\n+ scope (exit) timeTraceEndEvent(TimeTraceEventType.sema1TemplateInstance, tempinst,\n+ () => tempinst.toPrettyChars().toDString());\n // Get the enclosing template instance from the scope tinst\n tempinst.tinst = sc.tinst;\n-\n // Get the instantiating module from the scope minst\n tempinst.minst = sc.minst;\n // https://issues.dlang.org/show_bug.cgi?id=10920\ndiff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d\nindex ecb38c660cf..bcc004047e3 100644\n--- a/gcc/d/dmd/traits.d\n+++ b/gcc/d/dmd/traits.d\n@@ -443,6 +443,27 @@ Expression semanticTraits(TraitsExp e, Scope* sc)\n });\n }\n \n+ if (e.ident == Id.isOverlapped)\n+ {\n+ if (dim != 1)\n+ return dimError(1);\n+\n+ return isDeclX((d)\n+ {\n+ auto v = d.isVarDeclaration();\n+ if (!v || !v.isField())\n+ return false;\n+\n+ // Ensure semantic analysis is complete\n+ if (auto agg = v.toParent().isAggregateDeclaration())\n+ {\n+ if (agg.semanticRun < PASS.semanticdone)\n+ agg.dsymbolSemantic(null);\n+ }\n+\n+ return v.overlapped;\n+ });\n+ }\n if (e.ident == Id.isArithmetic)\n {\n return isTypeX(t => t.isIntegral() || t.isFloating());\n@@ -588,7 +609,8 @@ Expression semanticTraits(TraitsExp e, Scope* sc)\n return ErrorExp.get();\n }\n \n- t = t.toBasetype(); // get the base in case `t` is an `enum`\n+ // get enum base or static array element type\n+ t = t.baseElemOf();\n \n if (auto ts = t.isTypeStruct())\n {\n@@ -597,6 +619,36 @@ Expression semanticTraits(TraitsExp e, Scope* sc)\n \n return isCopyable(t) ? True() : False();\n }\n+ if (e.ident == Id.needsDestruction)\n+ {\n+ if (dim != 1)\n+ return dimError(1);\n+\n+ auto o = (*e.args)[0];\n+ auto t = isType(o);\n+ if (!t)\n+ {\n+ error(e.loc, \"type expected as second argument of __traits `%s` instead of `%s`\",\n+ e.ident.toChars(), o.toChars());\n+ return ErrorExp.get();\n+ }\n+ // FIXME should just check t.needsDestruction() but that doesn't run dsymbolSemantic\n+\n+ // T[0]\n+ if (!t.size())\n+ return False();\n+\n+ // get the base in case `t` is an `enum`\n+ // handle static arrays\n+ t = t.baseElemOf();\n+ if (auto ts = t.isTypeStruct())\n+ {\n+ ts.sym.dsymbolSemantic(sc);\n+ if (ts.sym.dtor)\n+ return True();\n+ }\n+ return False();\n+ }\n \n if (e.ident == Id.isNested)\n {\n@@ -1095,6 +1147,18 @@ Expression semanticTraits(TraitsExp e, Scope* sc)\n // Prevent semantic() from replacing Symbol with its initializer\n die.wantsym = true;\n ex = ex.expressionSemantic(scx);\n+ if (ex)\n+ {\n+ import dmd.access : symbolIsVisible;\n+ import dmd.safe : setUnsafe;\n+ auto msym = getDsymbolWithoutExpCtx(ex);\n+ // https://github.com/dlang/dmd/issues/19721\n+ if (msym && !symbolIsVisible(sc, msym))\n+ {\n+ if (sc.setUnsafe(false, e.loc, \"accessing member `%s`\", id))\n+ return ErrorExp.get();\n+ }\n+ }\n return ex;\n }\n else if (e.ident == Id.getVirtualFunctions ||\n@@ -1684,6 +1748,11 @@ Expression semanticTraits(TraitsExp e, Scope* sc)\n errorSupplemental(e.loc, \"`%s` must evaluate to either a module, a struct, an union, a class, an interface or a template instantiation\", s.toChars());\n return ErrorExp.get();\n }\n+ // https://issues.dlang.org/show_bug.cgi?id=13668\n+ // https://github.com/dlang/dmd/issues/22524\n+ // resolve forward references\n+ if (sds.semanticRun < PASS.semanticdone)\n+ sds.dsymbolSemantic(sc);\n \n auto idents = new Identifiers();\n \n@@ -1762,10 +1831,6 @@ Expression semanticTraits(TraitsExp e, Scope* sc)\n auto cd = sds.isClassDeclaration();\n if (cd && e.ident == Id.allMembers)\n {\n- if (cd.semanticRun < PASS.semanticdone)\n- cd.dsymbolSemantic(null); // https://issues.dlang.org/show_bug.cgi?id=13668\n- // Try to resolve forward reference\n-\n void pushBaseMembersDg(ClassDeclaration cd)\n {\n for (size_t i = 0; i < cd.baseclasses.length; i++)\n@@ -2344,7 +2409,7 @@ private void traitNotFound(TraitsExp e)\n initialized = true; // lazy initialization\n \n // All possible traits\n- __gshared Identifier*[59] idents =\n+ __gshared Identifier*[60] idents =\n [\n &Id.allMembers,\n &Id.child,\n@@ -2376,6 +2441,7 @@ private void traitNotFound(TraitsExp e)\n &Id.identifier,\n &Id.isAbstractClass,\n &Id.isAbstractFunction,\n+ &Id.isOverlapped,\n &Id.isArithmetic,\n &Id.isAssociativeArray,\n &Id.isCopyable,\ndiff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d\nindex 779e6bfd7f5..34bb80cf03c 100644\n--- a/gcc/d/dmd/typesem.d\n+++ b/gcc/d/dmd/typesem.d\n@@ -464,57 +464,62 @@ void check(Type _this)\n * For our new type '_this', which is type-constructed from t,\n * fill in the cto, ito, sto, scto, wto shortcuts.\n */\n-void fixTo(Type _this, Type t)\n+private void fixTo(Type _this, Type t)\n {\n // If fixing this: immutable(T*) by t: immutable(T)*,\n // cache t to this.xto won't break transitivity.\n- Type mto = null;\n+ Type mto = null; // the naked type of `t`\n Type tn = _this.nextOf();\n+ if (_this.mod || t.mod)\n+ {\n+ _this.getMcache();\n+ t.getMcache();\n+ }\n if (!tn || _this.ty != Tsarray && tn.mod == t.nextOf().mod)\n {\n switch (t.mod)\n {\n case 0:\n- mto = t;\n+ mto = t; // t is naked\n break;\n \n case MODFlags.const_:\n- _this.getMcache();\n+ mto = t.mcache.cto; // cto is naked\n _this.mcache.cto = t;\n break;\n \n case MODFlags.wild:\n- _this.getMcache();\n+ mto = t.mcache.wto; // wto is naked\n _this.mcache.wto = t;\n break;\n \n case MODFlags.wildconst:\n- _this.getMcache();\n+ mto = t.mcache.wcto; // wcto is naked\n _this.mcache.wcto = t;\n break;\n \n case MODFlags.shared_:\n- _this.getMcache();\n+ mto = t.mcache.sto; // sto is naked\n _this.mcache.sto = t;\n break;\n \n case MODFlags.shared_ | MODFlags.const_:\n- _this.getMcache();\n+ mto = t.mcache.scto; // scto is naked\n _this.mcache.scto = t;\n break;\n \n case MODFlags.shared_ | MODFlags.wild:\n- _this.getMcache();\n+ mto = t.mcache.swto; // swto is naked\n _this.mcache.swto = t;\n break;\n \n case MODFlags.shared_ | MODFlags.wildconst:\n- _this.getMcache();\n+ mto = t.mcache.swcto; // swcto is naked\n _this.mcache.swcto = t;\n break;\n \n case MODFlags.immutable_:\n- _this.getMcache();\n+ mto = t.mcache.ito; // ito is naked\n _this.mcache.ito = t;\n break;\n \n@@ -524,11 +529,6 @@ void fixTo(Type _this, Type t)\n }\n assert(_this.mod != t.mod);\n \n- if (_this.mod)\n- {\n- _this.getMcache();\n- t.getMcache();\n- }\n switch (_this.mod)\n {\n case 0:\n@@ -3314,6 +3314,15 @@ Type typeSemantic(Type type, Loc loc, Scope* sc)\n Type tbn = tn.toBasetype();\n if (mtype.dim)\n {\n+ if (auto ide = mtype.dim.isIdentifierExp())\n+ {\n+ if (ide.ident == Id.dollar)\n+ {\n+ mtype.next = tn;\n+ mtype.transitive();\n+ return mtype.addMod(tn.mod).merge();\n+ }\n+ }\n auto errors = global.errors;\n mtype.dim = semanticLength(sc, tbn, mtype.dim);\n mtype.dim = mtype.dim.implicitCastTo(sc, Type.tsize_t);\n@@ -8536,15 +8545,12 @@ Type mutableOf(Type type)\n type.getMcache();\n if (type.isShared())\n {\n- if (type.isWild())\n- t = type.mcache.swcto; // shared wild const -> shared\n- else\n- t = type.mcache.sto; // shared const => shared\n+ t = type.mcache.sto; // shared (wild) const => shared\n }\n else\n {\n if (type.isWild())\n- t = type.mcache.wcto; // wild const -> naked\n+ t = type.mcache.wcto; // wild const => naked\n else\n t = type.mcache.cto; // const => naked\n }\n@@ -8646,7 +8652,6 @@ Type unSharedOf(Type type)\n {\n t = type.nullAttributes();\n t.mod = type.mod & ~MODFlags.shared_;\n- t.ctype = type.ctype;\n t = t.merge();\n t.fixTo(type);\n }\n@@ -9224,6 +9229,9 @@ MATCH implicitConvToWithoutAliasThis(TypeStruct from, Type to)\n /* Check all the fields. If they can all be converted,\n * allow the conversion.\n */\n+ import dmd.dsymbolsem : size;\n+ if (from.sym.size(Loc.initial) == SIZE_INVALID)\n+ return MATCH.nomatch;\n MATCH m = MATCH.constant;\n uint offset = ~0; // must never match a field offset\n foreach (v; from.sym.fields[])\ndiff --git a/gcc/d/expr.cc b/gcc/d/expr.cc\nindex 75a8b4e726d..5ce1f510dca 100644\n--- a/gcc/d/expr.cc\n+++ b/gcc/d/expr.cc\n@@ -2608,6 +2608,8 @@ public:\n \t tree var = build_deref (e->sym);\n \t init = compound_expr (modify_expr (var, init), var);\n \t }\n+\telse if (e->type->isMutable ())\n+\t init = force_target_expr (init);\n \n \tthis->result_ = init;\n \treturn;\ndiff --git a/gcc/d/runtime.def b/gcc/d/runtime.def\nindex 016f58756bf..fac37e90709 100644\n--- a/gcc/d/runtime.def\n+++ b/gcc/d/runtime.def\n@@ -66,26 +66,10 @@ DEF_D_RUNTIME (CALLFINALIZER, \"_d_callfinalizer\", RT(VOID), P1(VOIDPTR), 0)\n DEF_D_RUNTIME (CALLINTERFACEFINALIZER, \"_d_callinterfacefinalizer\", RT(VOID),\n \t P1(VOIDPTR), 0)\n \n-/* Used for (array.length = n) expressions. The `i' variant is for when the\n- initializer is nonzero. */\n-DEF_D_RUNTIME (ARRAYSETLENGTHT, \"_d_arraysetlengthT\", RT(ARRAY_VOID),\n-\t P3(CONST_TYPEINFO, SIZE_T, ARRAYPTR_VOID), 0)\n-DEF_D_RUNTIME (ARRAYSETLENGTHIT, \"_d_arraysetlengthiT\", RT(ARRAY_VOID),\n-\t P3(CONST_TYPEINFO, SIZE_T, ARRAYPTR_VOID), 0)\n-\n /* Used for allocating closures on the GC heap. */\n DEF_D_RUNTIME (ALLOCMEMORY, \"_d_allocmemory\", RT(VOIDPTR), P1(SIZE_T),\n \t ECF_MALLOC)\n \n-/* Used for copying an array into a slice, adds an enforcment that the source\n- and destination are equal in size and do not overlap. */\n-DEF_D_RUNTIME (ARRAYCOPY, \"_d_arraycopy\", RT(ARRAY_VOID),\n-\t P3(SIZE_T, ARRAY_VOID, ARRAY_VOID), 0)\n-\n-/* Used for appending a single element to an array. */\n-DEF_D_RUNTIME (ARRAYAPPENDCTX, \"_d_arrayappendcTX\", RT(ARRAY_BYTE),\n-\t P3(CONST_TYPEINFO, ARRAYPTR_BYTE, SIZE_T), 0)\n-\n /* Same as appending a single element to an array, but specific for when the\n source is a UTF-32 character, and the destination is a UTF-8 or 16 array. */\n DEF_D_RUNTIME (ARRAYAPPENDCD, \"_d_arrayappendcd\", RT(ARRAY_VOID),\ndiff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc\nindex 340a1d67e17..c976179bb03 100644\n--- a/gcc/d/typeinfo.cc\n+++ b/gcc/d/typeinfo.cc\n@@ -925,13 +925,10 @@ public:\n \n \tfor (ClassDeclaration *bcd = cd; bcd; bcd = bcd->baseClass)\n \t {\n-\t if (!bcd->members)\n-\t continue;\n-\n-\t for (size_t i = 0; i < bcd->members->length; i++)\n+\t for (size_t i = 0; i < bcd->fields.length; i++)\n \t {\n-\t\tDsymbol *sm = (*bcd->members)[i];\n-\t\tif (dmd::hasPointers (sm))\n+\t\tVarDeclaration *vd = bcd->fields[i];\n+\t\tif (dmd::hasPointers (vd))\n \t\t goto Lhaspointers;\n \t }\n \t }\ndiff --git a/gcc/testsuite/gdc.test/compilable/diag20916.d b/gcc/testsuite/gdc.test/compilable/diag20916.d\nnew file mode 100644\nindex 00000000000..aa30c94fcf3\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/compilable/diag20916.d\n@@ -0,0 +1,64 @@\n+// REQUIRED_ARGS: -verrors=simple\n+/*\n+TEST_OUTPUT:\n+---\n+compilable/diag20916.d(32): Deprecation: `alias fb this` is deprecated\n+compilable/diag20916.d(37): instantiated from here: `jump2!(Foo)`\n+compilable/diag20916.d(42): instantiated from here: `jump1!(Foo)`\n+compilable/diag20916.d(32): Deprecation: function `diag20916.FooBar.toString` is deprecated\n+compilable/diag20916.d(37): instantiated from here: `jump2!(Foo)`\n+compilable/diag20916.d(42): instantiated from here: `jump1!(Foo)`\n+compilable/diag20916.d(32): Deprecation: template `diag20916.Bar.toString()() const` is deprecated\n+compilable/diag20916.d(37): instantiated from here: `jump2!(Bar)`\n+compilable/diag20916.d(43): instantiated from here: `jump1!(Bar)`\n+compilable/diag20916.d(21): Deprecation: variable `diag20916.Something.something` is deprecated\n+compilable/diag20916.d(24): instantiated from here: `nestedCheck!(Something)`\n+---\n+ */\n+\n+#line 1\n+struct FooBar\n+{\n+ deprecated string toString() const { return \"42\"; }\n+ int value = 42;\n+}\n+\n+struct Foo\n+{\n+ FooBar fb;\n+ deprecated alias fb this;\n+}\n+\n+struct Bar\n+{\n+ deprecated string toString()() const { return \"42\"; }\n+ int value = 42;\n+}\n+\n+template nestedCheck(T)\n+{\n+ enum nestedCheck = T.something.init == 0;\n+}\n+\n+struct Constraint (T) if(nestedCheck!T)\n+{\n+ T value;\n+}\n+struct Something { deprecated int something; }\n+\n+void jump2(T) (T value)\n+{\n+ assert(value.toString() == \"42\");\n+}\n+\n+void jump1(T) (T value)\n+{\n+ jump2(value);\n+}\n+\n+void main ()\n+{\n+ jump1(Foo.init);\n+ jump1(Bar.init);\n+ Constraint!Something c1;\n+}\ndiff --git a/gcc/testsuite/gdc.test/compilable/imports/test22480b.d b/gcc/testsuite/gdc.test/compilable/imports/test22480b.d\nnew file mode 100644\nindex 00000000000..93f9202f091\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/compilable/imports/test22480b.d\n@@ -0,0 +1,13 @@\n+module immports.test22480b;\n+\n+auto parseAA()\n+{\n+\tbool[string] aa;\n+\taa[\"key\"] = true;\n+\tassert(\"key\" in aa);\n+\tassert(aa[\"key\"]);\n+\tassert(aa.length == 1);\n+\tassert(aa == aa);\n+\taa.rehash();\n+\treturn true;\n+}\ndiff --git a/gcc/testsuite/gdc.test/compilable/issue22769.d b/gcc/testsuite/gdc.test/compilable/issue22769.d\nnew file mode 100644\nindex 00000000000..986fee38b95\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/compilable/issue22769.d\n@@ -0,0 +1,19 @@\n+// https://github.com/dlang/dmd/issues/22769\n+\n+int foo()() => 0;\n+\n+void bar()\n+{\n+ cast(void) i\"$(foo)\";\n+}\n+\n+struct OutBuffer\n+{\n+ void opOpAssign(string op, T...)(T args) {}\n+}\n+\n+void qux()\n+{\n+ OutBuffer buf;\n+ buf ~= i\"$(foo)\";\n+}\ndiff --git a/gcc/testsuite/gdc.test/compilable/new_xdtor.d b/gcc/testsuite/gdc.test/compilable/new_xdtor.d\nnew file mode 100644\nindex 00000000000..e757a9fd637\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/compilable/new_xdtor.d\n@@ -0,0 +1,10 @@\n+// https://github.com/dlang/dmd/issues/22609\n+struct S\n+{\n+ private ~this() {}\n+}\n+\n+void f()\n+{\n+ auto x = new S;\n+}\ndiff --git a/gcc/testsuite/gdc.test/compilable/struct_allMembers.d b/gcc/testsuite/gdc.test/compilable/struct_allMembers.d\nnew file mode 100644\nindex 00000000000..0304e944aab\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/compilable/struct_allMembers.d\n@@ -0,0 +1,14 @@\n+/*\n+TEST_OUTPUT:\n+---\n+S2: AliasSeq!(\"__dtor\", \"__xdtor\", \"opAssign\")\n+S3: AliasSeq!(\"field\", \"__xdtor\", \"opAssign\")\n+---\n+*/\n+\n+// allMembers should include __xdtor\n+pragma(msg, \"S2: \", __traits(allMembers, S2));\n+pragma(msg, \"S3: \", __traits(allMembers, S3));\n+\n+static struct S2 { ~this() {} }\n+static struct S3 { S2 field; }\ndiff --git a/gcc/testsuite/gdc.test/compilable/test22480.d b/gcc/testsuite/gdc.test/compilable/test22480.d\nnew file mode 100644\nindex 00000000000..bd187d0b938\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/compilable/test22480.d\n@@ -0,0 +1,10 @@\n+// EXTRA_FILES: imports/test22480b.d\n+import imports.test22480b;\n+\n+@nogc nothrow:\n+enum a = parseAA();\n+\n+extern(C) int main()\n+{\n+\treturn 0;\n+}\ndiff --git a/gcc/testsuite/gdc.test/compilable/test22501.d b/gcc/testsuite/gdc.test/compilable/test22501.d\nnew file mode 100644\nindex 00000000000..dc6fb2dbd68\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/compilable/test22501.d\n@@ -0,0 +1,12 @@\n+// https://github.com/dlang/dmd/issues/22501\n+\n+struct A {\n+ ubyte[16] bytes;\n+\n+ enum something = A(cast(ubyte[16])[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);\n+\n+ @nogc nothrow pure\n+ bool isB() const {\n+ return bytes[0..12] == something.bytes[0..12];\n+ }\n+}\ndiff --git a/gcc/testsuite/gdc.test/compilable/test22543.d b/gcc/testsuite/gdc.test/compilable/test22543.d\nnew file mode 100644\nindex 00000000000..7a6a36f2490\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/compilable/test22543.d\n@@ -0,0 +1,11 @@\n+// https://github.com/dlang/dmd/issues/22543\n+\n+enum int[string] aa = [\n+ \"a\": 42,\n+];\n+\n+int i = aa[\"a\"];\n+\n+void foo() {\n+ static int j = aa[\"a\"];\n+}\ndiff --git a/gcc/testsuite/gdc.test/compilable/test22544.d b/gcc/testsuite/gdc.test/compilable/test22544.d\nnew file mode 100644\nindex 00000000000..b9d18f18b03\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/compilable/test22544.d\n@@ -0,0 +1,11 @@\n+// https://github.com/dlang/dmd/issues/22544\n+\n+struct S {\n+ int bar() { return 1; }\n+}\n+\n+void foo(string key) {\n+ int[string] aa;\n+ with (S())\n+ aa[key] = bar();\n+}\ndiff --git a/gcc/testsuite/gdc.test/compilable/test22752.d b/gcc/testsuite/gdc.test/compilable/test22752.d\nnew file mode 100644\nindex 00000000000..6dc880550b4\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/compilable/test22752.d\n@@ -0,0 +1,23 @@\n+/*\n+REQUIRED_ARGS:\n+PERMUTE_ARGS:\n+*/\n+\n+struct S\n+{\n+ int isnot;\n+ int[] arguments;\n+}\n+\n+struct Array(T)\n+{\n+ static if (is(const(T) : T))\n+ {\n+ void insert()\n+ {\n+ static assert (is(const(T) : T));\n+ }\n+ }\n+}\n+\n+alias A = Array!S;\ndiff --git a/gcc/testsuite/gdc.test/compilable/test24295.d b/gcc/testsuite/gdc.test/compilable/test24295.d\nnew file mode 100644\nindex 00000000000..b80c18e306e\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/compilable/test24295.d\n@@ -0,0 +1,11 @@\n+// REQUIRED_ARGS: -betterC\n+\n+int f()\n+{\n+ int[] overlaps = new int[1];\n+ overlaps[0] = 3;\n+ return overlaps[0];\n+}\n+\n+enum res_f = f();\n+static assert(res_f == 3);\ndiff --git a/gcc/testsuite/gdc.test/compilable/test_isOverlapped.d b/gcc/testsuite/gdc.test/compilable/test_isOverlapped.d\nnew file mode 100644\nindex 00000000000..a32eb2df334\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/compilable/test_isOverlapped.d\n@@ -0,0 +1,181 @@\n+// REQUIRED_ARGS:\n+\n+struct S1\n+{\n+ int a;\n+ union\n+ {\n+ int x;\n+ float y;\n+ }\n+ int b;\n+}\n+\n+// Anonymous union fields are overlapped\n+static assert(__traits(isOverlapped, S1.x));\n+static assert(__traits(isOverlapped, S1.y));\n+// Regular fields are not overlapped\n+static assert(!__traits(isOverlapped, S1.a));\n+static assert(!__traits(isOverlapped, S1.b));\n+\n+// Named union as a field type\n+struct S2\n+{\n+ union U\n+ {\n+ int x;\n+ float y;\n+ }\n+ U u;\n+}\n+// The instance 'u' itself is not overlapped (it's a regular field)\n+static assert(!__traits(isOverlapped, S2.u));\n+static assert(__traits(isOverlapped, S2.U.x));\n+static assert(__traits(isOverlapped, S2.U.y));\n+\n+// Named union accessed directly - its fields are overlapped\n+union NamedUnion\n+{\n+ int x;\n+ float y;\n+}\n+static assert(__traits(isOverlapped, NamedUnion.x));\n+static assert(__traits(isOverlapped, NamedUnion.y));\n+\n+// Anonymous struct (not a union) - fields are NOT overlapped\n+struct S3\n+{\n+ struct\n+ {\n+ int x;\n+ float y;\n+ }\n+}\n+static assert(!__traits(isOverlapped, S3.x));\n+static assert(!__traits(isOverlapped, S3.y));\n+\n+// Named union with nested anonymous union\n+struct S4\n+{\n+ union Outer\n+ {\n+ int x; // This IS overlapped (it's in a named union)\n+ // Anonymous union nested inside the named union Outer\n+ union\n+ {\n+ int nested1;\n+ float nested2;\n+ }\n+ }\n+ Outer outer;\n+}\n+static assert(!__traits(isOverlapped, S4.outer)); // regular field, not overlapped\n+static assert(__traits(isOverlapped, S4.Outer.nested1)); // in union (both named and anonymous)\n+static assert(__traits(isOverlapped, S4.Outer.nested2)); // in union (both named and anonymous)\n+static assert(__traits(isOverlapped, S4.Outer.x)); // in named union - NOW true!\n+\n+// Class with anonymous union\n+class C1\n+{\n+ union\n+ {\n+ int x;\n+ float y;\n+ }\n+}\n+static assert(__traits(isOverlapped, C1.x));\n+static assert(__traits(isOverlapped, C1.y));\n+\n+// Non-field arguments should return false (not error)\n+static assert(!__traits(isOverlapped, S1)); // aggregate type\n+static assert(!__traits(isOverlapped, int)); // type\n+static assert(!__traits(isOverlapped, 42)); // literal value\n+\n+// Deeply nested anonymous unions within anonymous structs\n+struct S5\n+{\n+ union\n+ {\n+ int x;\n+ struct\n+ {\n+ union\n+ {\n+ int y;\n+ float z;\n+ }\n+ }\n+ }\n+}\n+static assert(__traits(isOverlapped, S5.x)); // outer anonymous union\n+static assert(__traits(isOverlapped, S5.y)); // inner anonymous union\n+static assert(__traits(isOverlapped, S5.z)); // inner anonymous union\n+\n+// Union as top-level type\n+union TopLevelUnion1\n+{\n+ int a;\n+ float b;\n+ struct\n+ {\n+ int c;\n+ int d;\n+ }\n+}\n+static assert(__traits(isOverlapped, TopLevelUnion1.a));\n+static assert(__traits(isOverlapped, TopLevelUnion1.b));\n+static assert(__traits(isOverlapped, TopLevelUnion1.c));\n+static assert(!__traits(isOverlapped, TopLevelUnion1.d));\n+\n+union TopLevelUnion2\n+{\n+ int a;\n+ double b;\n+ struct\n+ {\n+ int c;\n+ int d; // Now d is overlapped with b\n+ }\n+}\n+static assert(__traits(isOverlapped, TopLevelUnion2.a));\n+static assert(__traits(isOverlapped, TopLevelUnion2.b));\n+static assert(__traits(isOverlapped, TopLevelUnion2.c));\n+static assert(__traits(isOverlapped, TopLevelUnion2.d));\n+\n+// Bug #22621\n+struct Bug22621\n+{\n+ struct D\n+ {\n+ void* ptr;\n+ }\n+\n+ union\n+ {\n+ struct\n+ {\n+ D d;\n+ }\n+ uint b;\n+ }\n+}\n+static assert(__traits(isOverlapped, Bug22621.b));\n+// Bug #22621: DMD correctly detects that d is overlapped, but the destructor\n+// logic doesn't properly handle it - it calls d's destructor even when only b was initialized\n+static assert(__traits(isOverlapped, Bug22621.d)); // Correctly detected!\n+\n+// Struct with both overlapped and non-overlapped fields\n+struct S6\n+{\n+ int regular1;\n+ union\n+ {\n+ int overlapped1;\n+ float overlapped2;\n+ }\n+ int regular2;\n+}\n+static assert(!__traits(isOverlapped, S6.regular1));\n+static assert(__traits(isOverlapped, S6.overlapped1));\n+static assert(__traits(isOverlapped, S6.overlapped2));\n+static assert(!__traits(isOverlapped, S6.regular2));\ndiff --git a/gcc/testsuite/gdc.test/compilable/test_nosharedaccess_ctor_nested_new.d b/gcc/testsuite/gdc.test/compilable/test_nosharedaccess_ctor_nested_new.d\nnew file mode 100644\nindex 00000000000..3b28e232912\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/compilable/test_nosharedaccess_ctor_nested_new.d\n@@ -0,0 +1,13 @@\n+// REQUIRED_ARGS: -preview=nosharedaccess\n+\n+class Outer\n+{\n+ class Inner\n+ {\n+ }\n+\n+ shared this()\n+ {\n+ auto i = new shared Inner;\n+ }\n+}\ndiff --git a/gcc/testsuite/gdc.test/compilable/test_nosharedaccess_shared_struct_literal.d b/gcc/testsuite/gdc.test/compilable/test_nosharedaccess_shared_struct_literal.d\nnew file mode 100644\nindex 00000000000..4bb99010b84\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/compilable/test_nosharedaccess_shared_struct_literal.d\n@@ -0,0 +1,15 @@\n+// REQUIRED_ARGS: -preview=nosharedaccess\n+\n+import core.atomic;\n+\n+struct List\n+{\n+ size_t gen;\n+ List* next;\n+}\n+\n+void main()\n+{\n+ shared(List) head;\n+ assert(cas(&head, shared(List)(0, null), shared(List)(1, cast(List*)1)));\n+}\ndiff --git a/gcc/testsuite/gdc.test/compilable/traits.d b/gcc/testsuite/gdc.test/compilable/traits.d\nindex 09538b1dd4b..025a82c9795 100644\n--- a/gcc/testsuite/gdc.test/compilable/traits.d\n+++ b/gcc/testsuite/gdc.test/compilable/traits.d\n@@ -169,6 +169,7 @@ class C1 {}\n static assert( __traits(isCopyable, S1));\n static assert( __traits(isCopyable, S2));\n static assert(!__traits(isCopyable, S3));\n+static assert(!__traits(isCopyable, S3[1]));\n static assert(!__traits(isCopyable, S4));\n static assert(__traits(isCopyable, C1));\n static assert(__traits(isCopyable, int));\ndiff --git a/gcc/testsuite/gdc.test/compilable/vgc3.d b/gcc/testsuite/gdc.test/compilable/vgc3.d\nindex efdc5cd5eb3..6e587530d33 100644\n--- a/gcc/testsuite/gdc.test/compilable/vgc3.d\n+++ b/gcc/testsuite/gdc.test/compilable/vgc3.d\n@@ -44,8 +44,12 @@ void testCall()\n /*\n TEST_OUTPUT:\n ---\n-compilable/vgc3.d(51): vgc: using closure causes GC allocation\n-compilable/vgc3.d(63): vgc: using closure causes GC allocation\n+compilable/vgc3.d(55): vgc: using closure causes GC allocation\n+compilable/vgc3.d(58): vgc: function `bar` closes over variable `x`\n+compilable/vgc3.d(57): vgc: `x` declared here\n+compilable/vgc3.d(67): vgc: using closure causes GC allocation\n+compilable/vgc3.d(70): vgc: function `bar` closes over variable `x`\n+compilable/vgc3.d(69): vgc: `x` declared here\n ---\n */\n auto testClosure1()\ndiff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19898a.d b/gcc/testsuite/gdc.test/fail_compilation/fail19898a.d\nindex e23ed04305f..1ff06ca20f6 100644\n--- a/gcc/testsuite/gdc.test/fail_compilation/fail19898a.d\n+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19898a.d\n@@ -2,7 +2,7 @@\n REQUIRED_ARGS: -m64\n TEST_OUTPUT:\n ---\n-fail_compilation/fail19898a.d(10): Error: expression `__key2 < __limit3` of type `__vector(int[4])` does not have a boolean value\n+fail_compilation/fail19898a.d(10): Error: expression `__key$n$ < __limit$n$` of type `__vector(int[4])` does not have a boolean value\n ---\n */\n void f (__vector(int[4]) n)\ndiff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19898b.d b/gcc/testsuite/gdc.test/fail_compilation/fail19898b.d\nindex 5101da5617b..a59af4a688f 100644\n--- a/gcc/testsuite/gdc.test/fail_compilation/fail19898b.d\n+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19898b.d\n@@ -3,8 +3,8 @@ REQUIRED_ARGS: -m64\n TEST_OUTPUT:\n ---\n fail_compilation/fail19898b.d(17): Error: cannot implicitly convert expression `m` of type `S` to `__vector(int[4])`\n-fail_compilation/fail19898b.d(17): Error: expression `__key2 != __limit3` of type `__vector(int[4])` does not have a boolean value\n-fail_compilation/fail19898b.d(17): Error: cannot cast expression `__key2` of type `__vector(int[4])` to `S`\n+fail_compilation/fail19898b.d(17): Error: expression `__key$n$ != __limit$n$` of type `__vector(int[4])` does not have a boolean value\n+fail_compilation/fail19898b.d(17): Error: cannot cast expression `__key$n$` of type `__vector(int[4])` to `S`\n ---\n */\n struct S\ndiff --git a/gcc/testsuite/gdc.test/fail_compilation/getMember_private.d b/gcc/testsuite/gdc.test/fail_compilation/getMember_private.d\nnew file mode 100644\nindex 00000000000..647e6098e3b\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/fail_compilation/getMember_private.d\n@@ -0,0 +1,26 @@\n+/*\n+EXTRA_FILES: imports/fail5385.d\n+TEST_OUTPUT:\n+---\n+fail_compilation/getMember_private.d(17): Error: accessing member `x` is not allowed in a `@safe` function\n+fail_compilation/getMember_private.d(19): Error: accessing member `privX` is not allowed in a `@safe` function\n+---\n+*/\n+\n+import imports.a10169, imports.fail5385;\n+\n+B b;\n+\n+void f() @safe\n+{\n+ // instance field\n+ __traits(getMember, b, \"x\")++;\n+ // static field\n+ __traits(getMember, C, \"privX\")++;\n+}\n+\n+void g() @system // OK\n+{\n+ __traits(getMember, b, \"x\")++;\n+ __traits(getMember, C, \"privX\")++;\n+}\ndiff --git a/gcc/testsuite/gdc.test/fail_compilation/issue22147.d b/gcc/testsuite/gdc.test/fail_compilation/issue22147.d\nnew file mode 100644\nindex 00000000000..77c49678927\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/fail_compilation/issue22147.d\n@@ -0,0 +1,16 @@\n+/*\n+TEST_OUTPUT:\n+---\n+fail_compilation/issue22147.d(15): Error: operator `/` is not defined for type `T`\n+fail_compilation/issue22147.d(9): perhaps overload the operator with `auto opBinaryRight(string op : \"/\")(int lhs) {}`\n+---\n+*/\n+\n+struct T\n+{\n+}\n+\n+void test()\n+{\n+ auto result = 10 / T(); // int / T requires opBinaryRight on T\n+}\ndiff --git a/gcc/testsuite/gdc.test/fail_compilation/safeprintf.d b/gcc/testsuite/gdc.test/fail_compilation/safeprintf.d\nindex 60bff2a8795..4f2dd42e4be 100644\n--- a/gcc/testsuite/gdc.test/fail_compilation/safeprintf.d\n+++ b/gcc/testsuite/gdc.test/fail_compilation/safeprintf.d\n@@ -2,22 +2,41 @@\n DISABLED: win32 win64 freebsd32 openbsd32 linux32 osx32\n TEST_OUTPUT:\n ---\n-fail_compilation/safeprintf.d(20): Error: `@safe` function `safeprintf.func` cannot call `@system` function `safeprintf.printf`\n-fail_compilation/safeprintf.d(15): `safeprintf.printf` is declared here\n-fail_compilation/safeprintf.d(21): Error: `@safe` function `safeprintf.func` cannot call `@system` function `safeprintf.printf`\n-fail_compilation/safeprintf.d(15): `safeprintf.printf` is declared here\n-fail_compilation/safeprintf.d(22): Error: `@safe` function `safeprintf.func` cannot call `@system` function `safeprintf.printf`\n-fail_compilation/safeprintf.d(15): `safeprintf.printf` is declared here\n-fail_compilation/safeprintf.d(22): Deprecation: format specifier `\"%Z\"` is invalid\n+fail_compilation/safeprintf.d(29): Error: calling `pragma(printf)` function `printf` with format string `\"s: %s\\n\"` is not allowed in a `@safe` function\n+fail_compilation/safeprintf.d(21): `safeprintf.printf` is declared here\n+fail_compilation/safeprintf.d(30): Error: calling `pragma(printf)` function `printf` with format string `\"s: %S\\n\"` is not allowed in a `@safe` function\n+fail_compilation/safeprintf.d(21): `safeprintf.printf` is declared here\n+fail_compilation/safeprintf.d(31): Error: calling `pragma(printf)` function `printf` with format string `\"s: %Z\\n\"` is not allowed in a `@safe` function\n+fail_compilation/safeprintf.d(21): `safeprintf.printf` is declared here\n+fail_compilation/safeprintf.d(31): Deprecation: format specifier `\"%Z\"` is invalid\n+fail_compilation/safeprintf.d(32): Error: calling `pragma(printf)` function `printf` with non-literal format string is not allowed in a `@safe` function\n+fail_compilation/safeprintf.d(21): `safeprintf.printf` is declared here\n+fail_compilation/safeprintf.d(33): Error: calling `pragma(printf)` function `bar` with format string `\"%s\"` is not allowed in a `@safe` function\n+fail_compilation/safeprintf.d(22): `safeprintf.bar` is declared here\n+fail_compilation/safeprintf.d(34): Error: `@safe` function `safeprintf.func` cannot call `@system` function `safeprintf.sys_printf`\n+fail_compilation/safeprintf.d(23): `safeprintf.sys_printf` is declared here\n ---\n */\n \n-extern (C) @system pragma(printf) int printf(const(char)* format, ...);\n+extern (C) @trusted pragma(printf) int printf(const(char)* format, ...);\n+extern(C) pragma(printf) @trusted void bar(int, const char*, ...);\n+extern (C) @system pragma(printf) int sys_printf(const(char)* format, ...);\n \n @safe void func(int i, char* s, dchar* d)\n {\n- printf(\"i: %d\\n\", i);\n+ printf(\"no specs\"); // OK\n+ printf(\"i: %d\\n\", i); // OK\n printf(\"s: %s\\n\", s);\n printf(\"s: %S\\n\", d);\n printf(\"s: %Z\\n\", s);\n+ printf(s, i); // non-literal\n+ bar(1, \"%s\", s); // preceding args\n+ sys_printf(\"%d\", i); // not safe\n+}\n+\n+// no errors\n+@system void sys(char* s)\n+{\n+ printf(s); // non-literal\n+ printf(\"%s\", s);\n }\ndiff --git a/gcc/testsuite/gdc.test/fail_compilation/staticarray.d b/gcc/testsuite/gdc.test/fail_compilation/staticarray.d\nnew file mode 100644\nindex 00000000000..87b16ef360f\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/fail_compilation/staticarray.d\n@@ -0,0 +1,12 @@\n+/*\n+TEST_OUTPUT:\n+---\n+fail_compilation/staticarray.d(10): Error: cannot infer static array length from `$`, provide an initializer\n+fail_compilation/staticarray.d(11): Error: cannot infer static array length from `$`, provide an initializer\n+fail_compilation/staticarray.d(12): Error: cannot infer static array length from `$`, provide an initializer\n+---\n+*/\n+\n+int[$] arr1;\n+int[$] arr2 = void;\n+int[$][1] arr3 = 1;\ndiff --git a/gcc/testsuite/gdc.test/fail_compilation/test17977.d b/gcc/testsuite/gdc.test/fail_compilation/test17977.d\nindex b79d36c71fc..30475ae59c8 100644\n--- a/gcc/testsuite/gdc.test/fail_compilation/test17977.d\n+++ b/gcc/testsuite/gdc.test/fail_compilation/test17977.d\n@@ -3,7 +3,7 @@ https://issues.dlang.org/show_bug.cgi?id=15399\n REQUIRED_ARGS: -preview=dip1000\n TEST_OUTPUT:\n ---\n-fail_compilation/test17977.d(19): Error: assigning address of variable `__slList3` to `elem` with longer lifetime is not allowed in a `@safe` function\n+fail_compilation/test17977.d(19): Error: assigning address of variable `__slList$n$` to `elem` with longer lifetime is not allowed in a `@safe` function\n ---\n */\n \ndiff --git a/gcc/testsuite/gdc.test/fail_compilation/test24295.d b/gcc/testsuite/gdc.test/fail_compilation/test24295.d\ndeleted file mode 100644\nindex 58b6e92df8f..00000000000\n--- a/gcc/testsuite/gdc.test/fail_compilation/test24295.d\n+++ /dev/null\n@@ -1,13 +0,0 @@\n-// REQUIRED_ARGS: -betterC\n-\n-/*\n-TEST_OUTPUT:\n----\n-fail_compilation/test24295.d(12): Error: expression `new int[](1$?:32=u|64=LU$)` allocates with the GC and cannot be used with switch `-betterC`\n----\n-*/\n-\n-void f()\n-{\n- int[] overlaps = new int[1];\n-}\ndiff --git a/gcc/testsuite/gdc.test/fail_compilation/test9150.d b/gcc/testsuite/gdc.test/fail_compilation/test9150.d\nindex 5f66b360fec..bad84438db8 100644\n--- a/gcc/testsuite/gdc.test/fail_compilation/test9150.d\n+++ b/gcc/testsuite/gdc.test/fail_compilation/test9150.d\n@@ -3,7 +3,7 @@\n /*\n TEST_OUTPUT:\n ---\n-fail_compilation/test9150.d(14): Error: mismatched array lengths 5 and 3 for assignment `row[] = __r2[__key3]`\n+fail_compilation/test9150.d(14): Error: mismatched array lengths 5 and 3 for assignment `row[] = __r$n$[__key$n$]`\n ---\n */\n \ndiff --git a/gcc/testsuite/gdc.test/fail_compilation/test_isOverlapped_errors.d b/gcc/testsuite/gdc.test/fail_compilation/test_isOverlapped_errors.d\nnew file mode 100644\nindex 00000000000..ef0a1782dd8\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/fail_compilation/test_isOverlapped_errors.d\n@@ -0,0 +1,17 @@\n+/*\n+TEST_OUTPUT:\n+---\n+fail_compilation/test_isOverlapped_errors.d(100): Error: expected 1 arguments for `isOverlapped` but had 0\n+fail_compilation/test_isOverlapped_errors.d(101): Error: expected 1 arguments for `isOverlapped` but had 2\n+---\n+*/\n+\n+struct S\n+{\n+ union { int x; }\n+ int y;\n+}\n+\n+#line 100\n+enum a = __traits(isOverlapped);\n+enum b = __traits(isOverlapped, S, S.x);\ndiff --git a/gcc/testsuite/gdc.test/runnable/b10562.d b/gcc/testsuite/gdc.test/runnable/b10562.d\nindex cf79d164461..01ac9b8dea3 100644\n--- a/gcc/testsuite/gdc.test/runnable/b10562.d\n+++ b/gcc/testsuite/gdc.test/runnable/b10562.d\n@@ -90,4 +90,12 @@ void main()\n // arr = slice;\n // assert(arr == [[ slice, slice, slice ], [ slice, slice, slice ]]);\n }\n+ {\n+ // https://github.com/dlang/dmd/issues/22386\n+ const int[3][2] a = [[1:2, 3],[0: 0, 1:2, 2:3]];\n+ assert(a == [ [ 0, 2, 3 ], [ 0, 2, 3 ] ]);\n+\n+ const int[3][2] b = [[1:2, 2:3],[0: 0, 1:2, 2:3]];\n+ assert(b == [ [ 0, 2, 3 ], [ 0, 2, 3 ] ]);\n+ }\n }\ndiff --git a/gcc/testsuite/gdc.test/runnable/extra-files/sectiondefs.d b/gcc/testsuite/gdc.test/runnable/extra-files/sectiondefs.d\nnew file mode 100644\nindex 00000000000..764057839ad\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/runnable/extra-files/sectiondefs.d\n@@ -0,0 +1,13 @@\n+module extrafiles.sectiondefs;\n+import core.attribute;\n+\n+version(Windows)\n+ enum PlatformEntryName(string Name) = \".\" ~ Name ~ \"$N\";\n+else\n+ enum PlatformEntryName(string Name) = Name;\n+\n+@section(PlatformEntryName!\"myInts\")\n+__gshared int anInt = 9;\n+\n+@section(PlatformEntryName!\"my8Ints\")\n+__gshared int[8] an8Int = [64, 72, 9, 81, 21, 59, 45, 2];\ndiff --git a/gcc/testsuite/gdc.test/runnable/foreach5.d b/gcc/testsuite/gdc.test/runnable/foreach5.d\nindex b0befcceb62..024db2a864c 100644\n--- a/gcc/testsuite/gdc.test/runnable/foreach5.d\n+++ b/gcc/testsuite/gdc.test/runnable/foreach5.d\n@@ -1208,6 +1208,36 @@ void testLDC326()\n }\n }\n \n+/***************************************/\n+// https://github.com/dlang/dmd/issues/22629\n+\n+struct Collection2\n+{\n+ this(ref Collection2) {}\n+\n+ int opApply(int delegate(Collection2))\n+ {\n+ return 0;\n+ }\n+}\n+\n+Collection2 testForeach2(ref Collection2 level1, ref Collection2 level2)\n+{\n+ foreach (first; level1) {\n+ foreach (second; level2)\n+ return second;\n+ }\n+\n+ return Collection2();\n+}\n+\n+void test22629()\n+{\n+ Collection2 c1, c2;\n+ testForeach2(c1, c2);\n+}\n+\n+\n /***************************************/\n \n int main()\n@@ -1241,6 +1271,7 @@ int main()\n test14653();\n test17041();\n testLDC326();\n+ test22629();\n \n printf(\"Success\\n\");\n return 0;\ndiff --git a/gcc/testsuite/gdc.test/runnable/issue22621.d b/gcc/testsuite/gdc.test/runnable/issue22621.d\nnew file mode 100644\nindex 00000000000..e596341c630\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/runnable/issue22621.d\n@@ -0,0 +1,40 @@\n+// Test for Issue 22621\n+// Destructor should not be called on uninitialized overlapped field\n+\n+int dtorCalls = 0;\n+\n+struct D\n+{\n+ int magic = 0xC0FFEE;\n+\n+ ~this() @safe\n+ {\n+ // d's destructor should NOT be called,\n+ // while dd's destructor should be called.\n+ dtorCalls++;\n+ assert(magic == 0xC0FFEE, \"Destructor called on uninitialized field!\");\n+ }\n+}\n+\n+struct SUS\n+{\n+ union {\n+ struct {\n+ D d;\n+ }\n+ uint b;\n+ }\n+ D dd;\n+}\n+\n+void main()\n+{\n+ {\n+ // Initialize only 'b', not 'd'\n+ // Without the fix, d's destructor would be called on garbage memory\n+ SUS sus = SUS(b:0xDEADBEEF);\n+ }\n+\n+ // Just dd's destructor should be called, so dtorCalls should be 1\n+ assert(dtorCalls == 1, \"Destructor was incorrectly called!\");\n+}\ndiff --git a/gcc/testsuite/gdc.test/runnable/issue22639.d b/gcc/testsuite/gdc.test/runnable/issue22639.d\nnew file mode 100644\nindex 00000000000..4a1a99faafd\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/runnable/issue22639.d\n@@ -0,0 +1,35 @@\n+// REQUIRED_ARGS: -betterC\n+\n+struct Arr(T, int CAPACITY)\n+{\n+ int count = 0;\n+ T[CAPACITY] items;\n+ int opApply(scope int delegate(T) dg)\n+ {\n+ int result;\n+ for (int i = 0; i < count; i++)\n+ if ((result = dg(items[i])) != 0)\n+ break;\n+ return result;\n+ }\n+}\n+\n+struct Foo {}\n+struct Bar {\n+ Arr!(Foo*, 32) array;\n+ Foo* get()\n+ {\n+ foreach(Foo* it; array)\n+ {\n+ return it;\n+ }\n+ return null;\n+ }\n+}\n+\n+Foo* foo;\n+Bar bar;\n+extern(C) void main()\n+{\n+ foo = bar.get();\n+}\ndiff --git a/gcc/testsuite/gdc.test/runnable/lexer.d b/gcc/testsuite/gdc.test/runnable/lexer.d\nindex 0e1068a4289..daae3fa9876 100644\n--- a/gcc/testsuite/gdc.test/runnable/lexer.d\n+++ b/gcc/testsuite/gdc.test/runnable/lexer.d\n@@ -42,6 +42,18 @@ foo\n \n s = q{{foo}\"}\"};\n assert(s == \"{foo}\\\"}\\\"\");\n+\n+ // https://github.com/dlang/dmd/issues/22535\n+ s = q\"EOS\n+*ζ―ζ―ζ―*\n+ηηη.\n+*000*\n+EOS\";\n+ assert(s == \"*ζ―ζ―ζ―*\n+ηηη.\n+*000*\n+\");\n+ assert(s.length == 29);\n }\n \n /*********************************************************/\ndiff --git a/gcc/testsuite/gdc.test/runnable/rvalue1.d b/gcc/testsuite/gdc.test/runnable/rvalue1.d\nindex e50ccd08395..78c50919899 100644\n--- a/gcc/testsuite/gdc.test/runnable/rvalue1.d\n+++ b/gcc/testsuite/gdc.test/runnable/rvalue1.d\n@@ -286,6 +286,7 @@ struct V12\n {\n S12 s;\n this(int) { s = S12(1); }\n+ int opApply(int delegate(Object)) { return 0; }\n }\n \n S12 foo12()\n@@ -293,10 +294,33 @@ S12 foo12()\n return __rvalue(V12(1).s);\n }\n \n+S12 bar12()\n+{\n+ S12 s = S12(1); // NRVO\n+ foreach (_; V12(1))\n+ return s;\n+ return s;\n+}\n+\n+S12 baz12()\n+{\n+ S12 s1 = S12(1);\n+ S12 s2 = S12(1); // No NRVO\n+ foreach (_; V12(1))\n+ return s1;\n+ return s2;\n+}\n+\n void test12()\n {\n S12 s = foo12();\n assert(&s == s.ptr);\n+\n+ S12 s2 = bar12();\n+ assert(&s2 == s2.ptr);\n+\n+ S12 s3 = baz12();\n+ assert(&s3 == s3.ptr);\n }\n \n /********************************/\ndiff --git a/gcc/testsuite/gdc.test/runnable/sctor.d b/gcc/testsuite/gdc.test/runnable/sctor.d\nindex b587e6efe80..ad418d4d176 100644\n--- a/gcc/testsuite/gdc.test/runnable/sctor.d\n+++ b/gcc/testsuite/gdc.test/runnable/sctor.d\n@@ -465,6 +465,42 @@ void test19389()\n assert(bar.b.x == 7); // fails\n }\n \n+/***************************************************/\n+// https://github.com/dlang/dmd/issues/22604\n+\n+struct S22604\n+{\n+ S22604* ptr;\n+\n+ this(int)\n+ {\n+ ptr = &this;\n+ }\n+\n+ this(this)\n+ {\n+ ptr = &this;\n+ }\n+}\n+\n+struct T22604\n+{\n+ S22604 a, b, c, d;\n+\n+ this(int)\n+ {\n+ a = b = c = d = S22604(1);\n+ }\n+}\n+\n+void test22604()\n+{\n+ T22604 t = T22604(1);\n+ assert(t.a.ptr is &t.a);\n+ assert(t.b.ptr is &t.b);\n+ assert(t.c.ptr is &t.c);\n+ assert(t.d.ptr is &t.d);\n+}\n \n /***************************************************/\n \n@@ -478,6 +514,7 @@ int main()\n test14944();\n test15869();\n test19389();\n+ test22604();\n \n printf(\"Success\\n\");\n return 0;\ndiff --git a/gcc/testsuite/gdc.test/runnable/staticarray.d b/gcc/testsuite/gdc.test/runnable/staticarray.d\nnew file mode 100644\nindex 00000000000..39cfb0a439a\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/runnable/staticarray.d\n@@ -0,0 +1,83 @@\n+void main()\n+{\n+\tint[3] arr1 = [1,2,3];\n+\tint[$] arr2 = [1,2,3];\n+\tconst(int)[$] arr13 = [1,2,3];\n+\tassert(arr1.length == 3);\n+\tassert(arr2.length == 3);\n+\tassert(arr13.length == 3);\n+\tstatic assert(arr2.length == 3);\n+\tstatic assert(arr13.length == 3);\n+\tstatic assert(is(typeof(arr13) == const(int)[3]));\n+\tassert(arr1 == arr2);\n+\n+\tint[$] arr3 = [10] ~ [20];\n+\tassert(arr3.length == 2);\n+\tassert(arr3[0] == 10);\n+\tassert(arr3[1] == 20);\n+\tstatic assert(arr3.length == 2);\n+\n+\tint[$] arrConcatA = [2];\n+\tint[$] arrConcatB = [2];\n+\tint[$] arrConcatC = arrConcatA ~ arrConcatB;\n+\tassert(arrConcatC.length == 2);\n+\tassert(arrConcatC[0] == 2);\n+\tassert(arrConcatC[1] == 2);\n+\tstatic assert(arrConcatC.length == 2);\n+\tstatic assert(is(typeof(arrConcatC) == int[2]));\n+\n+\tint[$][$] arr4 = [[10], [10]];\n+\tassert(arr4.length == 2);\n+\tassert(arr4[0].length == 1);\n+\tstatic assert(arr4.length == 2);\n+\tstatic assert(arr4[0].length == 1);\n+\n+\tstatic assert(!__traits(compiles,\n+\t{\n+\t\tint[$] arr5 = 3;\n+\t}));\n+\n+\tstatic assert(!__traits(compiles,\n+\t{\n+\t\tint[$] arr6 = new int[2];\n+\t}));\n+\n+\tint[N] arrn(size_t N)()\n+\t{\n+\t int[N] res;\n+\t return res;\n+\t}\n+\tint[$] arr7 = arrn!(2)();\n+\tassert(arr7.length == 2);\n+\tstatic assert(arr7.length == 2);\n+\n+\tint[2][$] arr8 = [[1, 2], [3, 4], [5, 6]];\n+\tassert(arr8.length == 3);\n+\tassert(arr8[0].length == 2);\n+\tstatic assert(arr8.length == 3);\n+\tstatic assert(arr8[0].length == 2);\n+\n+\tint[$][$][$] arr9 = [[[1, 2]], [[3, 4]]];\n+\tassert(arr9.length == 2);\n+\tassert(arr9[0].length == 1);\n+\tassert(arr9[0][0].length == 2);\n+\tstatic assert(arr9.length == 2);\n+\tstatic assert(arr9[0].length == 1);\n+\tstatic assert(arr9[0][0].length == 2);\n+\n+\tstatic assert(!__traits(compiles,\n+\t{\n+\t\tfloat[$] arr10 = 3.0f;\n+\t}));\n+\n+\tstatic assert(!__traits(compiles,\n+\t{\n+\t\tstring[$] arr11 = \"abc\";\n+\t}));\n+\n+\tchar[$] arr12 = \"abc\";\n+\tassert(arr12.length == 3);\n+\tassert(arr12[0] == 'a');\n+\tassert(arr12[1] == 'b');\n+\tassert(arr12[2] == 'c');\n+}\ndiff --git a/gcc/testsuite/gdc.test/runnable/structlit_rvalue.d b/gcc/testsuite/gdc.test/runnable/structlit_rvalue.d\nindex c8f63c71f3d..86ef405c1f1 100644\n--- a/gcc/testsuite/gdc.test/runnable/structlit_rvalue.d\n+++ b/gcc/testsuite/gdc.test/runnable/structlit_rvalue.d\n@@ -1,15 +1,67 @@\n-void refCounted(ProcessPipes val)\n+struct S22585_1\n {\n- val = ProcessPipes.init;\n+ char[32] a;\n+ int b = 1;\n+\n+ this(ref S22585_1 s)\n+ {\n+ s.b = 2;\n+ }\n+}\n+\n+struct T22585_1\n+{\n+ S22585_1 s;\n+}\n+\n+void copyConstruct(S22585_1) {}\n+\n+void mutate(ref S22585_1 s)\n+{\n+ s.b = 2;\n+}\n+\n+struct S22585_2\n+{\n+ char[32] a;\n+ int b = 1;\n+ ~this() {}\n+}\n+\n+struct T22585_2\n+{\n+ S22585_2 s;\n+}\n+\n+pragma(inline, true)\n+S22585_2 inlinedRvalue1()\n+{\n+ bool b;\n+ return (b ? T22585_2.init : T22585_2.init).s;\n+}\n+\n+void mutateCopyOf(S22585_2 s)\n+{\n+ s.b = 2;\n+}\n+\n+pragma(inline, true)\n+S22585_2 inlinedRvalue2()\n+{\n+ return S22585_2.init;\n }\n \n-struct ProcessPipes\n+void assignCopyOf(S22585_2 s)\n {\n- char[33] arr;\n- ~this() @safe {}\n+ s = S22585_2.init;\n }\n \n void main()\n {\n- refCounted(ProcessPipes.init);\n+ bool b;\n+ copyConstruct((b ? T22585_1.init : T22585_1.init).s);\n+ mutate((b ? T22585_1.init : T22585_1.init).s);\n+ mutateCopyOf(inlinedRvalue1());\n+ inlinedRvalue2.b = 2;\n+ assignCopyOf(S22585_2.init);\n }\ndiff --git a/gcc/testsuite/gdc.test/runnable/test20275.d b/gcc/testsuite/gdc.test/runnable/test20275.d\nindex cbdf1f6e7f8..1288397264b 100644\n--- a/gcc/testsuite/gdc.test/runnable/test20275.d\n+++ b/gcc/testsuite/gdc.test/runnable/test20275.d\n@@ -1,4 +1,5 @@\n // EXTRA_SOURCES: imports/δ½ ε₯½.d\n+// UNICODE_NAMES:\n \n import imports.δ½ ε₯½;\n \ndiff --git a/gcc/testsuite/gdc.test/runnable/test22422.d b/gcc/testsuite/gdc.test/runnable/test22422.d\nnew file mode 100644\nindex 00000000000..d51b93799aa\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/runnable/test22422.d\n@@ -0,0 +1,21 @@\n+// https://github.com/dlang/dmd/issues/22422\n+\n+class C {}\n+class D {}\n+\n+struct S {\n+ ~this() {}\n+ D opIndex(size_t) { return new D; }\n+}\n+\n+S makeS() {\n+ return S();\n+}\n+\n+C foo() {\n+ return cast(C) makeS()[0];\n+}\n+\n+void main() {\n+ assert(foo() is null);\n+}\ndiff --git a/gcc/testsuite/gdc.test/runnable/test22594.d b/gcc/testsuite/gdc.test/runnable/test22594.d\nnew file mode 100644\nindex 00000000000..0c16ba6e17a\n--- /dev/null\n+++ b/gcc/testsuite/gdc.test/runnable/test22594.d\n@@ -0,0 +1,23 @@\n+// https://github.com/dlang/dmd/issues/22594\n+// PERMUTE_ARGS:\n+\n+import core.memory : GC;\n+\n+class C(Ts...) {\n+ Ts tuple;\n+}\n+\n+void main() {\n+ alias NoPointers = C!int;\n+ alias WithPointers = C!(void*);\n+\n+ assert(typeid(NoPointers).m_flags & TypeInfo_Class.ClassFlags.noPointers);\n+ assert(!(typeid(WithPointers).m_flags & TypeInfo_Class.ClassFlags.noPointers));\n+\n+ auto noPointers = new NoPointers;\n+ // FIXME: regressed with v2.103\n+ //assert(GC.getAttr(cast(void*) noPointers) & GC.BlkAttr.NO_SCAN);\n+\n+ auto withPointers = new WithPointers;\n+ assert(!(GC.getAttr(cast(void*) withPointers) & GC.BlkAttr.NO_SCAN));\n+}\ndiff --git a/gcc/testsuite/gdc.test/runnable/testaa2.d b/gcc/testsuite/gdc.test/runnable/testaa2.d\nindex 9247bbf84e7..7104b12dd8c 100644\n--- a/gcc/testsuite/gdc.test/runnable/testaa2.d\n+++ b/gcc/testsuite/gdc.test/runnable/testaa2.d\n@@ -335,6 +335,14 @@ void foo() @safe\n aa[key] = 123;\n }\n \n+// https://github.com/dlang/dmd/issues/22560\n+void test22560()\n+{\n+ enum E { a }\n+ bool[E] aa;\n+ static assert(!__traits(compiles, aa[0]));\n+}\n+\n /************************************************/\n \n void testEvaluationOrder()\ndiff --git a/gcc/testsuite/gdc.test/runnable/testaa3.d b/gcc/testsuite/gdc.test/runnable/testaa3.d\nindex 734c0c4cba0..1ba165b55e6 100644\n--- a/gcc/testsuite/gdc.test/runnable/testaa3.d\n+++ b/gcc/testsuite/gdc.test/runnable/testaa3.d\n@@ -393,6 +393,73 @@ void test22354()\n assert(aa[\"x\"].length == 1); // FAILS: length is still 0\n }\n \n+// https://github.com/dlang/dmd/issues/22406\n+void testShared()\n+{\n+ shared int[int] processes = [1: 1, 2:4, 3:9];\n+\n+ cast(void)processes.sizeof;\n+ cast(void)processes.length;\n+ cast(void)processes.dup;\n+ cast(void)processes.rehash;\n+ //cast(void)processes.clear;\n+ //cast(void)processes.keys;\n+ //cast(void)processes.values;\n+ //cast(void)processes.byKey;\n+ //cast(void)processes.byValue;\n+ //cast(void)processes.byKeyValue;\n+ processes.remove(3);\n+ assert(2 in processes);\n+\n+ immutable int[int] iprocesses = [1: 1, 2:4, 3:9];\n+\n+ cast(void)iprocesses.sizeof;\n+ cast(void)iprocesses.length;\n+ cast(void)iprocesses.dup;\n+ //cast(void)iprocesses.rehash;\n+ //cast(void)iprocesses.clear;\n+ cast(void)iprocesses.keys;\n+ cast(void)iprocesses.values;\n+ cast(void)iprocesses.byKey;\n+ cast(void)iprocesses.byValue;\n+ cast(void)iprocesses.byKeyValue;\n+ //iprocesses.remove(3);\n+ assert(2 in iprocesses);\n+}\n+\n+// https://github.com/dlang/dmd/issues/22556\n+void test22556()\n+{\n+ static struct RefCounted(T)\n+ {\n+ this(this) {}\n+ }\n+ struct S {}\n+ alias R = RefCounted!S;\n+ shared R[string] foo;\n+\n+ (cast (R[string]) foo).clear; // WORKS\n+ (cast() foo).clear; // FAILS with 2.112.0, WORKS with 2.111.0\n+ static assert(!__traits(compiles, foo.clear));\n+}\n+\n+/***************************************************/\n+\n+// https://github.com/dlang/dmd/issues/22567\n+void test22567()\n+{\n+ struct S\n+ {\n+ string[string] data;\n+ alias this = data;\n+ }\n+\n+ S[string] foo;\n+ foo[\"bar\"] = S();\n+ foo[\"bar\"][\"baz\"] = \"boom\";\n+ assert(foo[\"bar\"][\"baz\"] == \"boom\");\n+}\n+\n /***************************************************/\n \n void main()\n@@ -421,4 +488,7 @@ void main()\n test12403();\n test21066();\n test22354();\n+ testShared();\n+ test22567();\n+ test22556();\n }\ndiff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE\nindex 434ad554b84..a5b457e873c 100644\n--- a/libphobos/libdruntime/MERGE\n+++ b/libphobos/libdruntime/MERGE\n@@ -1,4 +1,4 @@\n-e7c34c13de2930f2becc484e12b2c2cf1a16f6e8\n+662104f52607c175ecb80633bd261932aa004561\n \n The first line of this file holds the git revision number of the last\n merge done from the dlang/dmd repository.\ndiff --git a/libphobos/libdruntime/core/atomic.d b/libphobos/libdruntime/core/atomic.d\nindex 7e97b9d53fa..7ca0ecd4e12 100644\n--- a/libphobos/libdruntime/core/atomic.d\n+++ b/libphobos/libdruntime/core/atomic.d\n@@ -33,6 +33,13 @@ import core.internal.atomic;\n import core.internal.attributes : betterC;\n import core.internal.traits : hasUnsharedIndirections;\n \n+// Low-level atomic helpers still need to hand shared reference payloads to the\n+// backend intrinsics under `-preview=nosharedaccess`.\n+private T unsharedLoadRef(T)(scope ref shared T value) pure nothrow @nogc @trusted\n+{\n+ return *cast(T*)&value;\n+}\n+\n /**\n * Specifies the memory ordering semantics of an atomic operation.\n *\n@@ -259,7 +266,7 @@ in (atomicPtrIsProperlyAligned(here), \"Argument `here` is not properly aligned\")\n {\n static assert (is (V : T), \"Can't assign `exchangeWith` of type `\" ~ shared(V).stringof ~ \"` to `\" ~ shared(T).stringof ~ \"`.\");\n \n- return cast(shared)core.internal.atomic.atomicExchange!ms(cast(T*)here, cast(V)exchangeWith);\n+ return cast(shared)core.internal.atomic.atomicExchange!ms(cast(T*)here, unsharedLoadRef(exchangeWith));\n }\n \n /**\n@@ -326,7 +333,7 @@ template cas(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.\n in (atomicPtrIsProperlyAligned(here), \"Argument `here` is not properly aligned\")\n {\n return atomicCompareExchangeStrongNoResult!(succ, fail)(\n- cast(T*)here, cast(V1)ifThis, cast(V2)writeThis);\n+ cast(T*)here, unsharedLoadRef(ifThis), unsharedLoadRef(writeThis));\n }\n \n /// Compare-and-exchange for non-`shared` types\n@@ -378,7 +385,7 @@ template cas(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.\n in (atomicPtrIsProperlyAligned(here), \"Argument `here` is not properly aligned\")\n {\n return atomicCompareExchangeStrong!(succ, fail)(\n- cast(T*)here, cast(T*)ifThis, cast(V)writeThis);\n+ cast(T*)here, cast(T*)ifThis, unsharedLoadRef(writeThis));\n }\n }\n \n@@ -835,11 +842,11 @@ version (CoreUnittest)\n T base = cast(T)null;\n shared(T) atom = cast(shared(T))null;\n \n- assert(base !is val, T.stringof);\n- assert(atom is base, T.stringof);\n+ assert(atomicLoad(base) !is atomicLoad(val), T.stringof);\n+ assert(atomicLoad(atom) is atomicLoad(base), T.stringof);\n \n- assert(atomicExchange(&atom, val) is base, T.stringof);\n- assert(atom is val, T.stringof);\n+ assert(atomicExchange(&atom, atomicLoad(val)) is atomicLoad(base), T.stringof);\n+ assert(atomicLoad(atom) is atomicLoad(val), T.stringof);\n }\n \n void testCAS(T)(T val) pure nothrow @nogc @trusted\n@@ -852,25 +859,26 @@ version (CoreUnittest)\n T base = cast(T)null;\n shared(T) atom = cast(shared(T))null;\n \n- assert(base !is val, T.stringof);\n- assert(atom is base, T.stringof);\n+ assert(atomicLoad(base) !is atomicLoad(val), T.stringof);\n+ assert(atomicLoad(atom) is atomicLoad(base), T.stringof);\n \n- assert(cas(&atom, base, val), T.stringof);\n- assert(atom is val, T.stringof);\n- assert(!cas(&atom, base, base), T.stringof);\n- assert(atom is val, T.stringof);\n+ assert(cas(&atom, atomicLoad(base), atomicLoad(val)), T.stringof);\n+ assert(atomicLoad(atom) is atomicLoad(val), T.stringof);\n+ assert(!cas(&atom, atomicLoad(base), atomicLoad(base)), T.stringof);\n+ assert(atomicLoad(atom) is atomicLoad(val), T.stringof);\n \n- atom = cast(shared(T))null;\n+ atomicStore(atom, cast(shared(T))null);\n \n- shared(T) arg = base;\n- assert(cas(&atom, &arg, val), T.stringof);\n- assert(arg is base, T.stringof);\n- assert(atom is val, T.stringof);\n+ shared(T) arg = cast(shared(T))null;\n+ atomicStore(arg, atomicLoad(base));\n+ assert(cas(&atom, &arg, atomicLoad(val)), T.stringof);\n+ assert(atomicLoad(arg) is atomicLoad(base), T.stringof);\n+ assert(atomicLoad(atom) is atomicLoad(val), T.stringof);\n \n- arg = base;\n- assert(!cas(&atom, &arg, base), T.stringof);\n- assert(arg is val, T.stringof);\n- assert(atom is val, T.stringof);\n+ atomicStore(arg, atomicLoad(base));\n+ assert(!cas(&atom, &arg, atomicLoad(base)), T.stringof);\n+ assert(atomicLoad(arg) is atomicLoad(val), T.stringof);\n+ assert(atomicLoad(atom) is atomicLoad(val), T.stringof);\n }\n \n void testLoadStore(MemoryOrder ms = MemoryOrder.seq, T)(T val = T.init + 1) pure nothrow @nogc @trusted\n@@ -878,23 +886,34 @@ version (CoreUnittest)\n T base = cast(T) 0;\n shared(T) atom = cast(T) 0;\n \n- assert(base !is val);\n- assert(atom is base);\n- atomicStore!(ms)(atom, val);\n- base = atomicLoad!(ms)(atom);\n+ assert(atomicLoad(base) !is atomicLoad(val));\n+ assert(atomicLoad(atom) is atomicLoad(base));\n+ atomicStore!(ms)(atom, atomicLoad(val));\n+ auto loaded = atomicLoad!(ms)(atom);\n \n- assert(base is val, T.stringof);\n- assert(atom is val);\n+ assert(loaded is atomicLoad(val), T.stringof);\n+ assert(atomicLoad(atom) is atomicLoad(val));\n }\n \n \n- void testType(T)(T val = T.init + 1) pure nothrow @nogc @safe\n+ // This test-only helper synthesizes distinct sentinel values for low-level\n+ // atomic operations, including shared pointers that cannot be formed in\n+ // @safe code.\n+ private T testValue(T)() pure nothrow @nogc @trusted\n+ {\n+ static if (is(T == U*, U))\n+ return cast(T)1;\n+ else\n+ return T.init + 1;\n+ }\n+\n+ void testType(T)(T val = testValue!T()) pure nothrow @nogc @safe\n {\n static if (T.sizeof < 8 || has64BitXCHG)\n- testXCHG!(T)(val);\n- testCAS!(T)(val);\n- testLoadStore!(MemoryOrder.seq, T)(val);\n- testLoadStore!(MemoryOrder.raw, T)(val);\n+ testXCHG!(T)(atomicLoad(val));\n+ testCAS!(T)(atomicLoad(val));\n+ testLoadStore!(MemoryOrder.seq, T)(atomicLoad(val));\n+ testLoadStore!(MemoryOrder.raw, T)(atomicLoad(val));\n }\n \n @betterC @safe pure nothrow unittest\n@@ -946,30 +965,30 @@ version (CoreUnittest)\n shared(Big) arg;\n shared(Big) val = Big(1, 2);\n \n- assert(cas(&atom, arg, val), Big.stringof);\n- assert(atom is val, Big.stringof);\n- assert(!cas(&atom, arg, val), Big.stringof);\n- assert(atom is val, Big.stringof);\n+ assert(cas(&atom, atomicLoad(arg), atomicLoad(val)), Big.stringof);\n+ assert(atomicLoad(atom) is atomicLoad(val), Big.stringof);\n+ assert(!cas(&atom, atomicLoad(arg), atomicLoad(val)), Big.stringof);\n+ assert(atomicLoad(atom) is atomicLoad(val), Big.stringof);\n \n- atom = Big();\n- assert(cas(&atom, &arg, val), Big.stringof);\n- assert(arg is base, Big.stringof);\n- assert(atom is val, Big.stringof);\n+ atomicStore(atom, Big());\n+ assert(cas(&atom, &arg, atomicLoad(val)), Big.stringof);\n+ assert(atomicLoad(arg) is atomicLoad(base), Big.stringof);\n+ assert(atomicLoad(atom) is atomicLoad(val), Big.stringof);\n \n- arg = Big();\n- assert(!cas(&atom, &arg, base), Big.stringof);\n- assert(arg is val, Big.stringof);\n- assert(atom is val, Big.stringof);\n+ atomicStore(arg, Big());\n+ assert(!cas(&atom, &arg, atomicLoad(base)), Big.stringof);\n+ assert(atomicLoad(arg) is atomicLoad(val), Big.stringof);\n+ assert(atomicLoad(atom) is atomicLoad(val), Big.stringof);\n }();\n }\n \n shared(size_t) i;\n \n atomicOp!\"+=\"(i, cast(size_t) 1);\n- assert(i == 1);\n+ assert(atomicLoad(i) == 1);\n \n atomicOp!\"-=\"(i, cast(size_t) 1);\n- assert(i == 0);\n+ assert(atomicLoad(i) == 0);\n \n shared float f = 0.1f;\n atomicOp!\"+=\"(f, 0.1f);\n@@ -995,10 +1014,12 @@ version (CoreUnittest)\n \n align(16) shared DoubleValue a;\n atomicStore(a, DoubleValue(1,2));\n- assert(a.value1 == 1 && a.value2 ==2);\n+ auto initial = atomicLoad(a);\n+ assert(initial.value1 == 1 && initial.value2 == 2);\n \n while (!cas(&a, DoubleValue(1,2), DoubleValue(3,4))){}\n- assert(a.value1 == 3 && a.value2 ==4);\n+ auto updated = atomicLoad(a);\n+ assert(updated.value1 == 3 && updated.value2 == 4);\n \n align(16) DoubleValue b = atomicLoad(a);\n assert(b.value1 == 3 && b.value2 ==4);\n@@ -1056,7 +1077,8 @@ version (CoreUnittest)\n @betterC pure nothrow unittest\n {\n static struct S { int val; }\n- auto s = shared(S)(1);\n+ shared S s;\n+ atomicStore(s, S(1));\n \n shared(S*) ptr;\n \n@@ -1070,7 +1092,7 @@ version (CoreUnittest)\n // head shared\n shared(S*) ifThis2 = writeThis;\n shared(S*) writeThis2 = null;\n- assert(cas(&ptr, ifThis2, writeThis2));\n+ assert(cas(&ptr, atomicLoad(ifThis2), atomicLoad(writeThis2)));\n assert(ptr is null);\n }\n \n@@ -1174,12 +1196,12 @@ version (CoreUnittest)\n shared ulong a = 2;\n uint b = 1;\n atomicOp!\"-=\"(a, b);\n- assert(a == 1);\n+ assert(atomicLoad(a) == 1);\n \n shared uint c = 2;\n ubyte d = 1;\n atomicOp!\"-=\"(c, d);\n- assert(c == 1);\n+ assert(atomicLoad(c) == 1);\n }\n \n pure nothrow @safe unittest // https://issues.dlang.org/show_bug.cgi?id=16230\n@@ -1232,6 +1254,6 @@ version (CoreUnittest)\n shared uint si2 = 38;\n shared uint* psi = &si1;\n \n- assert((&psi).cas(cast(const) psi, &si2));\n+ assert((&psi).cas(cast(const) atomicLoad(psi), &si2));\n }\n }\ndiff --git a/libphobos/libdruntime/core/attribute.d b/libphobos/libdruntime/core/attribute.d\nindex 2b35b8d7c0e..5e9a97ff987 100644\n--- a/libphobos/libdruntime/core/attribute.d\n+++ b/libphobos/libdruntime/core/attribute.d\n@@ -83,6 +83,32 @@ else\n // GDC and LDC declare this attribute in their own modules.\n }\n \n+/**\n+* When applied to a global variable, causes it to be emitted to a\n+* non-standard object file/executable section.\n+*\n+* The target platform might impose certain restrictions on the format for\n+* section names.\n+*\n+* Examples:\n+* ---\n+* import core.attributes;\n+*\n+* @section(\"mySection\") int myGlobal;\n+* ---\n+*/\n+version (DigitalMars)\n+{\n+ struct section\n+ {\n+ string name;\n+ }\n+}\n+else\n+{\n+ // GDC and LDC declare this attribute in their own modules.\n+}\n+\n /**\n * Use this attribute to attach an Objective-C selector to a method.\n *\ndiff --git a/libphobos/libdruntime/core/gc/config.d b/libphobos/libdruntime/core/gc/config.d\nindex 32de5ab1409..c3b79e0926b 100644\n--- a/libphobos/libdruntime/core/gc/config.d\n+++ b/libphobos/libdruntime/core/gc/config.d\n@@ -25,6 +25,12 @@ struct Config\n @MemVal size_t minPoolSize = 1 << 20; // initial and minimum pool size (bytes)\n @MemVal size_t maxPoolSize = 64 << 20; // maximum pool size (bytes)\n @MemVal size_t incPoolSize = 3 << 20; // pool size increment (bytes)\n+\n+ // Limit under which the GC will try to keep its heap (bytes)\n+ // The GC does this on a best effort basis, and exceeding this size\n+ // might lead to a performance cliff.\n+ @MemVal size_t heapSizeLimit = size_t.max;\n+\n uint parallel = 99; // number of additional threads for marking (limited by cpuid.threadsPerCPU-1)\n float heapSizeFactor = 2.0; // heap size to used memory ratio\n string cleanup = \"collect\"; // select gc cleanup method none|collect|finalize\ndiff --git a/libphobos/libdruntime/core/internal/array/capacity.d b/libphobos/libdruntime/core/internal/array/capacity.d\nindex 833918664d9..cbcc3d3b6d2 100644\n--- a/libphobos/libdruntime/core/internal/array/capacity.d\n+++ b/libphobos/libdruntime/core/internal/array/capacity.d\n@@ -142,7 +142,10 @@ do\n auto attrs = __typeAttrs!T((*p).ptr) | BlkAttr.APPENDABLE;\n \n // use this static enum to avoid recomputing TypeInfo for every call.\n- static enum ti = typeid(T);\n+ version (D_TypeInfo)\n+ static enum ti = typeid(T);\n+ else\n+ static enum ti = null;\n auto ptr = GC.malloc(reqsize, attrs, ti);\n if (ptr is null)\n {\n@@ -222,7 +225,16 @@ size_t _d_arraysetlengthT(Tarr : T[], T)(return ref scope Tarr arr, size_t newle\n // Call the implementation with the unqualified array and sharedness flag\n size_t result = _d_arraysetlengthT_(unqual_arr, newlength, isShared);\n \n- arr = cast(Tarr) unqual_arr;\n+ static if (isShared)\n+ {\n+ // This low-level primitive mutates the caller's shared slice header, so\n+ // the caller must already provide whatever synchronization makes that\n+ // header update valid; the cast only preserves that existing contract\n+ // under `-preview=nosharedaccess`.\n+ *cast(UnqT[]*) &arr = unqual_arr;\n+ }\n+ else\n+ arr = cast(Tarr) unqual_arr;\n // Return the result\n return result;\n }\n@@ -392,6 +404,8 @@ version (D_ProfileGC)\n shared S[] arr2;\n _d_arraysetlengthT!(typeof(arr2))(arr2, 16);\n assert(arr2.length == 16);\n- foreach (s; arr2)\n+ // The resized slice has not been published yet, so the test may inspect\n+ // the backing storage directly to verify initialization.\n+ foreach (s; (() @trusted => *cast(S[]*) &arr2)())\n assert(s == S.init);\n }\ndiff --git a/libphobos/libdruntime/core/internal/array/construction.d b/libphobos/libdruntime/core/internal/array/construction.d\nindex 4797244993f..4b47e20b0a4 100644\n--- a/libphobos/libdruntime/core/internal/array/construction.d\n+++ b/libphobos/libdruntime/core/internal/array/construction.d\n@@ -672,7 +672,10 @@ void* _d_arrayliteralTX(T)(size_t length) @trusted pure nothrow\n static if (is(T == struct) && hasElaborateDestructor!T)\n attrs |= BlkAttr.FINALIZE;\n \n- return GC.malloc(allocsize, attrs, typeid(T));\n+ version (D_TypeInfo)\n+ return GC.malloc(allocsize, attrs, typeid(T));\n+ else\n+ return GC.malloc(allocsize, attrs, null);\n }\n }\n \ndiff --git a/libphobos/libdruntime/core/internal/array/duplication.d b/libphobos/libdruntime/core/internal/array/duplication.d\nindex a9b599cfc35..ff9e1edb4da 100644\n--- a/libphobos/libdruntime/core/internal/array/duplication.d\n+++ b/libphobos/libdruntime/core/internal/array/duplication.d\n@@ -29,13 +29,32 @@ U[] _dup(T, U)(scope T[] a) pure nothrow @trusted if (__traits(isPOD, T))\n \n U[] _dupCtfe(T, U)(scope T[] a)\n {\n+ import core.internal.traits : Unqual;\n+\n static if (is(T : void))\n assert(0, \"Cannot dup a void[] array at compile time.\");\n else\n {\n U[] res;\n- foreach (ref e; a)\n- res ~= e;\n+ static if (is(T == shared SharedPayload, SharedPayload))\n+ {\n+ // CTFE still needs a low-level element copy path for shared POD\n+ // arrays because `.dup` models the runtime bitcopy before any\n+ // synchronization policy is applied to the duplicated slice.\n+ Unqual!U[] tmp;\n+ foreach (i; 0 .. a.length)\n+ // This cast is only to make the CTFE path express the same raw\n+ // element copy that the runtime POD implementation performs\n+ // with memcpy; it is not meant as a synchronized access pattern\n+ // for published shared data.\n+ tmp ~= (cast(Unqual!T[]) a)[i];\n+ res = cast(typeof(res)) tmp;\n+ }\n+ else\n+ {\n+ foreach (ref e; a)\n+ res ~= e;\n+ }\n return res;\n }\n }\n@@ -327,9 +346,9 @@ U[] _dup(T, U)(T[] a) if (!__traits(isPOD, T))\n {\n if (l != 0xDEADBEEF)\n {\n- import core.stdc.stdio : fflush, printf, stdout;\n+ import core.stdc.stdio : fflush, printf;\n printf(\"Unexpected value: %lld\\n\", l);\n- fflush(stdout);\n+ fflush(null);\n assert(false);\n }\n }\ndiff --git a/libphobos/libdruntime/core/internal/array/equality.d b/libphobos/libdruntime/core/internal/array/equality.d\nindex 7a7dc5ceb26..a94c6b6a887 100644\n--- a/libphobos/libdruntime/core/internal/array/equality.d\n+++ b/libphobos/libdruntime/core/internal/array/equality.d\n@@ -49,25 +49,39 @@ bool __equals(T1, T2, size_t N, size_t M)(scope ref T1[N] lhs, scope ref T2[M] r\n private\n bool isEqual(T1, T2)(scope T1[] lhs, scope T2[] rhs, size_t length)\n {\n- // Returns a reference to an array element, eliding bounds check and\n- // casting void to ubyte.\n- pragma(inline, true)\n- static ref at(T)(scope T[] r, size_t i) @trusted\n- // exclude opaque structs due to https://issues.dlang.org/show_bug.cgi?id=20959\n- if (!(is(T == struct) && !is(typeof(T.sizeof))))\n+ static if (is(T1 == T2) &&\n+ (__traits(isIntegral, T1) || is(T1 == char) || is(T1 == wchar) ||\n+ is(T1 == dchar) || is(T1 == bool) || is(T1 == class)))\n {\n- static if (is(T == void))\n- return (cast(ubyte[]) r)[i];\n- else\n- return r[i];\n+ foreach (i; 0 .. length)\n+ {\n+ if (lhs.ptr[i] != rhs.ptr[i])\n+ return false;\n+ }\n+ return true;\n }\n-\n- foreach (const i; 0 .. length)\n+ else\n {\n- if (at(lhs, i) != at(rhs, i))\n- return false;\n+ // Returns a reference to an array element, eliding bounds check and\n+ // casting void to ubyte.\n+ pragma(inline, true)\n+ static ref at(T)(scope T[] r, size_t i) @trusted\n+ // exclude opaque structs due to https://issues.dlang.org/show_bug.cgi?id=20959\n+ if (!(is(T == struct) && !is(typeof(T.sizeof))))\n+ {\n+ static if (is(T == void))\n+ return (cast(ubyte[]) r)[i];\n+ else\n+ return r[i];\n+ }\n+\n+ foreach (const i; 0 .. length)\n+ {\n+ if (at(lhs, i) != at(rhs, i))\n+ return false;\n+ }\n+ return true;\n }\n- return true;\n }\n \n @safe unittest\ndiff --git a/libphobos/libdruntime/core/internal/array/utils.d b/libphobos/libdruntime/core/internal/array/utils.d\nindex 9eae8f092b2..40caa39c89e 100644\n--- a/libphobos/libdruntime/core/internal/array/utils.d\n+++ b/libphobos/libdruntime/core/internal/array/utils.d\n@@ -151,12 +151,22 @@ void[] __arrayAlloc(T)(size_t arrSize) @trusted\n static if (!hasIndirections!T)\n attr |= BlkAttr.NO_SCAN;\n \n- auto ptr = GC.malloc(arrSize, attr, typeid(T));\n+ version(D_TypeInfo)\n+ auto ptr = GC.malloc(arrSize, attr, typeid(T));\n+ else\n+ auto ptr = GC.malloc(arrSize, attr, null);\n if (ptr)\n return ptr[0 .. arrSize];\n return null;\n }\n \n+// https://github.com/dlang/dmd/issues/22517\n+@system unittest\n+{\n+ auto arr = new void[10];\n+ assert((GC.getAttr(&arr[0]) & BlkAttr.NO_SCAN) == 0);\n+}\n+\n /**\n Given an array of length `size` that needs to be expanded to `newlength`,\n compute a new capacity.\ndiff --git a/libphobos/libdruntime/core/internal/atomic.d b/libphobos/libdruntime/core/internal/atomic.d\nindex 43e50acacb7..9daddf844a7 100644\n--- a/libphobos/libdruntime/core/internal/atomic.d\n+++ b/libphobos/libdruntime/core/internal/atomic.d\n@@ -13,6 +13,84 @@ module core.internal.atomic;\n import core.atomic : has128BitCAS, MemoryOrder;\n \n version (DigitalMars)\n+version (AArch64)\n+{\n+ /* These functions are all stubbed out. They await someone who knows what\n+ they are doing with AArch64 atomics.\n+ TODO AArch64\n+ */\n+ enum IsAtomicLockFree(T) = T.sizeof <= size_t.sizeof * 2;\n+\n+ inout(T) atomicLoad(MemoryOrder order = MemoryOrder.seq, T)(inout(T)* src) pure nothrow @nogc @trusted\n+ if (CanCAS!T)\n+ {\n+ return *src;\n+ }\n+\n+ void atomicStore(MemoryOrder order = MemoryOrder.seq, T)(T* dest, T value) pure nothrow @nogc @trusted\n+ if (CanCAS!T)\n+ {\n+ *dest = value;\n+ }\n+\n+ T atomicFetchAdd(MemoryOrder order = MemoryOrder.seq, bool result = true, T)(T* dest, T value) pure nothrow @nogc @trusted\n+ if (is(T : ulong))\n+ {\n+\treturn *dest + value;\n+ }\n+\n+ T atomicFetchSub(MemoryOrder order = MemoryOrder.seq, bool result = true, T)(T* dest, T value) pure nothrow @nogc @trusted\n+ if (is(T : ulong))\n+ {\n+ return atomicFetchAdd(dest, cast(T)-cast(IntOrLong!T)value);\n+ }\n+\n+ T atomicExchange(MemoryOrder order = MemoryOrder.seq, bool result = true, T)(T* dest, T value) pure nothrow @nogc @trusted\n+ if (CanCAS!T)\n+ {\n+ size_t storage = void;\n+ return *cast(T*)&storage;\n+ }\n+\n+ alias atomicCompareExchangeWeak = atomicCompareExchangeStrong;\n+\n+ bool atomicCompareExchangeStrong(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T)(T* dest, T* compare, T value) pure nothrow @nogc @trusted\n+ if (CanCAS!T)\n+ {\n+ if (*dest != *compare)\n+ {\n+ *compare = *dest;\n+ return false;\n+ }\n+ *dest = value;\n+ return true;\n+ }\n+\n+ alias atomicCompareExchangeWeakNoResult = atomicCompareExchangeStrongNoResult;\n+\n+ bool atomicCompareExchangeStrongNoResult(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T)(T* dest, const T compare, T value) pure nothrow @nogc @trusted\n+ if (CanCAS!T)\n+ {\n+ if (*dest != compare)\n+ return false;\n+ *dest = value;\n+ return true;\n+ }\n+\n+ void atomicFence(MemoryOrder order = MemoryOrder.seq)() pure nothrow @nogc @trusted\n+ {\n+ }\n+\n+ void atomicSignalFence(MemoryOrder order = MemoryOrder.seq)() pure nothrow @nogc @trusted\n+ {\n+ // no-op, dmd doesn't reorder instructions\n+ }\n+\n+ void pause() pure nothrow @nogc @trusted\n+ {\n+ }\n+}\n+else // X86 and X86_64\n {\n private\n {\ndiff --git a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d\nindex ae40bd363da..1c7025a2062 100644\n--- a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d\n+++ b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d\n@@ -2113,10 +2113,25 @@ struct Gcx\n */\n void updateCollectThresholds() nothrow\n {\n- static float max(float a, float b) nothrow\n- {\n- return a >= b ? a : b;\n- }\n+ import core.internal.util.math : min, max;\n+\n+ // Reserve half of the remaining heap budget to small and large heaps.\n+ immutable maxPageUsed = config.heapSizeLimit / PAGESIZE;\n+ immutable usedPages = usedSmallPages + usedLargePages;\n+ immutable heapBudget = maxPageUsed > usedPages\n+ ? maxPageUsed - usedPages\n+ : 0;\n+\n+ immutable smTargetHeap = usedSmallPages + heapBudget / 2;\n+ immutable lgTargetHeap = usedLargePages + heapBudget / 2;\n+\n+ // Compute the target sizes based on the growth factor.\n+ immutable smTargetGrowth = usedSmallPages * config.heapSizeFactor;\n+ immutable lgTargetGrowth = usedLargePages * config.heapSizeFactor;\n+\n+ // Collect when either is reached.\n+ immutable smTarget = min(smTargetHeap, smTargetGrowth);\n+ immutable lgTarget = min(lgTargetHeap, lgTargetGrowth);\n \n // instantly increases, slowly decreases\n static float smoothDecay(float oldVal, float newVal) nothrow\n@@ -2128,9 +2143,7 @@ struct Gcx\n return max(newVal, decay);\n }\n \n- immutable smTarget = usedSmallPages * config.heapSizeFactor;\n smallCollectThreshold = smoothDecay(smallCollectThreshold, smTarget);\n- immutable lgTarget = usedLargePages * config.heapSizeFactor;\n largeCollectThreshold = smoothDecay(largeCollectThreshold, lgTarget);\n }\n \n@@ -3525,8 +3538,8 @@ Lmark:\n cstdlib.free(Gcx.instance.scanThreadData);\n Gcx.instance.numScanThreads = 0;\n Gcx.instance.scanThreadData = null;\n- Gcx.instance.busyThreads = 0;\n- Gcx.instance.stackLock = shared(AlignedSpinLock)(SpinLock.Contention.brief);\n+ atomicStore(Gcx.instance.busyThreads, 0);\n+ (cast() Gcx.instance.stackLock) = AlignedSpinLock(SpinLock.Contention.brief);\n \n memset(&Gcx.instance.evStackFilled, 0, Gcx.instance.evStackFilled.sizeof);\n memset(&Gcx.instance.evDone, 0, Gcx.instance.evDone.sizeof);\ndiff --git a/libphobos/libdruntime/core/internal/lifetime.d b/libphobos/libdruntime/core/internal/lifetime.d\nindex 053b3edc69d..fb28b11f084 100644\n--- a/libphobos/libdruntime/core/internal/lifetime.d\n+++ b/libphobos/libdruntime/core/internal/lifetime.d\n@@ -94,7 +94,14 @@ if (!is(T == const) && !is(T == immutable) && !is(T == inout))\n {\n import core.internal.traits : hasElaborateAssign;\n \n- static if (__traits(isZeroInit, T))\n+ static if (is(T == shared U, U))\n+ {\n+ // Initialization happens before the shared object is published, so the\n+ // helper has to operate on the backing storage instead of performing an\n+ // ordinary shared write that `-preview=nosharedaccess` rejects.\n+ emplaceInitializer(*cast(U*) &chunk);\n+ }\n+ else static if (__traits(isZeroInit, T))\n {\n import core.stdc.string : memset;\n memset(cast(void*) &chunk, 0, T.sizeof);\n@@ -135,7 +142,9 @@ if (!is(T == const) && !is(T == immutable) && !is(T == inout))\n {\n shared T dst = void;\n emplaceInitializer(dst);\n- assert(dst is shared(T).init);\n+ // The initializer has not been published yet, so the test may read\n+ // the backing storage directly to verify that emplace wrote T.init.\n+ assert((() @trusted => (*cast(T*) &dst) is T.init)());\n }\n \n // const T\ndiff --git a/libphobos/libdruntime/core/internal/newaa.d b/libphobos/libdruntime/core/internal/newaa.d\nindex 55bc16e5e8b..bd95fb1ea6b 100644\n--- a/libphobos/libdruntime/core/internal/newaa.d\n+++ b/libphobos/libdruntime/core/internal/newaa.d\n@@ -463,6 +463,18 @@ size_t _d_aaLen(K, V)(inout V[K] a)\n auto aa = _toAA!(K, V)(a);\n return aa ? aa.length : 0;\n }\n+/// ditto\n+size_t _d_aaLen(K, V)(shared V[K] a)\n+{\n+ // accept shared for backward compatibility, should be deprecated\n+ return _d_aaLen(cast(V[K]) a);\n+}\n+/// ditto\n+size_t _d_aaLen(K, V)(const shared V[K] a)\n+{\n+ // accept shared for backward compatibility, should be deprecated\n+ return _d_aaLen(cast(V[K]) a);\n+}\n \n /******************************\n * Lookup key in aa.\n@@ -631,6 +643,18 @@ auto _d_aaIn(T : V[K], K, V, K2)(inout T a, auto ref scope K2 key)\n return &p.entry.value;\n return null;\n }\n+/// ditto\n+auto _d_aaIn(T : V[K], K, V, K2)(shared T a, auto ref scope K2 key)\n+{\n+ // accept shared for backward compatibility, should be deprecated\n+ return _d_aaIn(cast(V[K]) a, key);\n+}\n+/// ditto\n+auto _d_aaIn(T : V[K], K, V, K2)(const shared T a, auto ref scope K2 key)\n+{\n+ // accept shared for backward compatibility, should be deprecated\n+ return _d_aaIn(cast(V[K]) a, key);\n+}\n \n // fake purity for backward compatibility with runtime hooks\n private extern(C) bool gc_inFinalizer() pure nothrow @safe;\ndiff --git a/libphobos/libdruntime/core/internal/traits.d b/libphobos/libdruntime/core/internal/traits.d\nindex 7ffee2ec0be..df9f4200e54 100644\n--- a/libphobos/libdruntime/core/internal/traits.d\n+++ b/libphobos/libdruntime/core/internal/traits.d\n@@ -285,38 +285,9 @@ template hasElaborateMove(S)\n }\n }\n \n-// std.traits.hasElaborateDestructor\n-template hasElaborateDestructor(S)\n-{\n- static if (__traits(isStaticArray, S))\n- {\n- enum bool hasElaborateDestructor = S.sizeof && hasElaborateDestructor!(BaseElemOf!S);\n- }\n- else static if (is(S == struct))\n- {\n- // Once https://issues.dlang.org/show_bug.cgi?id=24865 is fixed, then\n- // this should be the implementation, but until that's fixed, we need the\n- // uncommented code.\n- // enum hasElaborateDestructor = __traits(hasMember, S, \"__xdtor\");\n-\n- enum hasElaborateDestructor = hasDtor([__traits(allMembers, S)]);\n- }\n- else\n- {\n- enum bool hasElaborateDestructor = false;\n- }\n-}\n-\n-private bool hasDtor(string[] members)\n-{\n- foreach (name; members)\n- {\n- if (name == \"__xdtor\")\n- return true;\n- }\n-\n- return false;\n-}\n+// Used by std.traits.hasElaborateDestructor\n+// TODO inline this in druntime\n+enum hasElaborateDestructor(S) = __traits(needsDestruction, S);\n \n @safe unittest\n {\n@@ -331,6 +302,7 @@ private bool hasDtor(string[] members)\n static assert( hasElaborateDestructor!(HasDestructor[42]));\n static assert(!hasElaborateDestructor!(HasDestructor[0]));\n static assert(!hasElaborateDestructor!(HasDestructor[]));\n+ static assert( hasElaborateDestructor!(immutable HasDestructor));\n \n static struct HasDestructor2 { HasDestructor s; }\n static assert( hasElaborateDestructor!HasDestructor2);\n@@ -365,6 +337,25 @@ private bool hasDtor(string[] members)\n static assert(!hasElaborateDestructor!S6);\n }\n \n+// https://github.com/dlang/dmd/issues/21967\n+version (CoreUnittest)\n+private struct Test21967\n+{\n+ // Note: Foward referencing was failing due to:\n+ // https://github.com/dlang/dmd/issues/22524\n+ static assert(hasElaborateDestructor!C);\n+ enum before = hasElaborateDestructor!C;\n+ static assert(before);\n+\n+ struct C\n+ {\n+ ~this() {}\n+ }\n+ static assert(hasElaborateDestructor!C);\n+ enum after = hasElaborateDestructor!C;\n+ static assert(after);\n+}\n+\n // std.traits.hasElaborateCopyDestructor\n template hasElaborateCopyConstructor(S)\n {\n@@ -572,9 +563,11 @@ template hasIndirections(T)\n else static if (__traits(isAssociativeArray, T) || is(T == class) || is(T == interface))\n enum hasIndirections = true;\n else static if (is(T == E[N], E, size_t N))\n- enum hasIndirections = T.sizeof && (is(immutable E == immutable void) || hasIndirections!(BaseElemOf!E));\n+ enum hasIndirections = T.sizeof && hasIndirections!(BaseElemOf!E);\n else static if (isFunctionPointer!T)\n enum hasIndirections = false;\n+ else static if (is(immutable(T) == immutable(void)))\n+ enum hasIndirections = true;\n else\n enum hasIndirections = isPointer!T || isDelegate!T || isDynamicArray!T;\n }\n@@ -735,11 +728,11 @@ template hasIndirections(T)\n // https://github.com/dlang/dmd/issues/20812\n @safe unittest\n {\n- static assert(!hasIndirections!void);\n- static assert(!hasIndirections!(const void));\n- static assert(!hasIndirections!(inout void));\n- static assert(!hasIndirections!(immutable void));\n- static assert(!hasIndirections!(shared void));\n+ static assert( hasIndirections!void);\n+ static assert( hasIndirections!(const void));\n+ static assert( hasIndirections!(inout void));\n+ static assert( hasIndirections!(immutable void));\n+ static assert( hasIndirections!(shared void));\n \n static assert( hasIndirections!(void*));\n static assert( hasIndirections!(const void*));\ndiff --git a/libphobos/libdruntime/core/lifetime.d b/libphobos/libdruntime/core/lifetime.d\nindex ad98b2f2c56..cd38648bc22 100644\n--- a/libphobos/libdruntime/core/lifetime.d\n+++ b/libphobos/libdruntime/core/lifetime.d\n@@ -77,9 +77,11 @@ T* emplace(T, Args...)(T* chunk, auto ref Args args)\n @betterC\n @system unittest\n {\n+ import core.atomic : atomicLoad;\n+\n shared int i;\n emplace(&i, 42);\n- assert(i == 42);\n+ assert(atomicLoad(i) == 42);\n }\n \n /**\n@@ -1246,9 +1248,21 @@ void copyEmplace(S, T)(ref S source, ref T target) @system\n if (is(immutable S == immutable T))\n {\n import core.internal.traits : BaseElemOf, hasElaborateCopyConstructor, Unconst, Unqual;\n+ enum isSharedReference = is(S == shared U, U) && is(T == shared V, V) &&\n+ (is(U == class) || is(U == interface)) &&\n+ (is(V == class) || is(V == interface));\n \n // cannot have the following as simple template constraint due to nested-struct special case...\n- static if (!__traits(compiles, (ref S src) { T tgt = src; }))\n+ static if (isSharedReference)\n+ {\n+ static assert(__traits(compiles, (ref S src, ref T tgt)\n+ {\n+ import core.atomic : atomicLoad, atomicStore;\n+ atomicStore(tgt, atomicLoad(src));\n+ }), \"cannot copy shared reference \" ~ T.stringof ~ \" from \" ~ S.stringof ~\n+ \" via atomic load/store\");\n+ }\n+ else static if (!__traits(compiles, (ref S src) { T tgt = src; }))\n {\n alias B = BaseElemOf!T;\n enum isNestedStruct = is(B == struct) && __traits(isNested, B);\n@@ -1308,6 +1322,11 @@ void copyEmplace(S, T)(ref S source, ref T target) @system\n blit(); // all elements at once\n }\n }\n+ else static if (isSharedReference)\n+ {\n+ import core.atomic : atomicLoad, atomicStore;\n+ atomicStore(target, atomicLoad(source));\n+ }\n else\n {\n *cast(Unconst!(T)*) &target = *cast(Unconst!(T)*) &source;\n@@ -2396,7 +2415,7 @@ template _d_delstructImpl(T)\n private enum errorMessage = \"Cannot delete struct if compiling without support for runtime type information!\";\n \n /**\n- * TraceGC wrapper around $(REF _d_delstruct, core,lifetime,_d_delstructImpl).\n+ * TraceGC wrapper around $(REF _d_delstruct, core,lifetime).\n *\n * Bugs:\n * This function template was ported from a much older runtime hook that\n@@ -2762,7 +2781,10 @@ if (is(T == class))\n static if (!hasIndirections!T)\n attr |= BlkAttr.NO_SCAN;\n \n- p = GC.malloc(init.length, attr, typeid(T));\n+ version(D_TypeInfo)\n+ p = GC.malloc(init.length, attr, typeid(T));\n+ else\n+ p = GC.malloc(init.length, attr, null);\n debug(PRINTF) printf(\" p = %p\\n\", p);\n }\n \n@@ -2834,7 +2856,10 @@ T* _d_newitemT(T)() @trusted\n if (TypeInfoSize!T)\n flags |= GC.BlkAttr.FINALIZE;\n \n- auto p = GC.malloc(itemSize, flags, typeid(T));\n+ version(D_TypeInfo)\n+ auto p = GC.malloc(itemSize, flags, typeid(T));\n+ else\n+ auto p = GC.malloc(itemSize, flags, null);\n \n emplaceInitializer(*(cast(T*) p));\n \ndiff --git a/libphobos/libdruntime/core/memory.d b/libphobos/libdruntime/core/memory.d\nindex 3b3cb8e6a66..a4e2d1f2694 100644\n--- a/libphobos/libdruntime/core/memory.d\n+++ b/libphobos/libdruntime/core/memory.d\n@@ -141,7 +141,7 @@ private\n extern (C) GC.ProfileStats gc_profileStats ( ) nothrow @nogc @safe;\n }\n \n-version (CoreDoc)\n+version (CoreDdoc)\n {\n /**\n * The minimum size of a system page in bytes.\ndiff --git a/libphobos/libdruntime/core/stdc/stdatomic.d b/libphobos/libdruntime/core/stdc/stdatomic.d\nindex 966d29d8084..8f4bc6e2e1f 100644\n--- a/libphobos/libdruntime/core/stdc/stdatomic.d\n+++ b/libphobos/libdruntime/core/stdc/stdatomic.d\n@@ -244,7 +244,10 @@ bool atomic_flag_test_and_set_explicit_impl()(atomic_flag* obj, memory_order ord\n pragma(inline, true)\n void atomic_init(A, C)(out shared(A) obj, C desired) @trusted\n {\n- obj = cast(shared) desired;\n+ // C11 atomic_init is a low-level initialization primitive for atomic storage\n+ // before it is published for concurrent access, so it must be able to write\n+ // the backing object without demonstrating ordinary shared access.\n+ *cast(A*) &obj = cast(A) desired;\n }\n \n ///\ndiff --git a/libphobos/libdruntime/core/stdc/stdint.d b/libphobos/libdruntime/core/stdc/stdint.d\nindex 4f9b98cd8ce..385f4ca5dde 100644\n--- a/libphobos/libdruntime/core/stdc/stdint.d\n+++ b/libphobos/libdruntime/core/stdc/stdint.d\n@@ -337,7 +337,10 @@ else version (OpenBSD)\n }\n else version (Solaris)\n {\n- alias int8_t = char; ///\n+ version (GNU)\n+ alias int8_t = byte; ///\n+ else\n+ alias int8_t = char; ///\n alias int16_t = short; ///\n alias uint8_t = ubyte; ///\n alias uint16_t = ushort; ///\n@@ -346,7 +349,10 @@ else version (Solaris)\n alias int64_t = long; ///\n alias uint64_t = ulong; ///\n \n- alias int_least8_t = char; ///\n+ version (GNU)\n+ alias int_least8_t = byte; ///\n+ else\n+ alias int_least8_t = char; ///\n alias uint_least8_t = ubyte; ///\n alias int_least16_t = short; ///\n alias uint_least16_t = ushort; ///\n@@ -355,7 +361,10 @@ else version (Solaris)\n alias int_least64_t = long; ///\n alias uint_least64_t = ulong; ///\n \n- alias int_fast8_t = char; ///\n+ version (GNU)\n+ alias int_fast8_t = byte; ///\n+ else\n+ alias int_fast8_t = char; ///\n alias uint_fast8_t = ubyte; ///\n alias int_fast16_t = int; ///\n alias uint_fast16_t = uint; ///\ndiff --git a/libphobos/libdruntime/core/stdc/stdio.d b/libphobos/libdruntime/core/stdc/stdio.d\nindex fcecb9ed562..adb9f9d9a00 100644\n--- a/libphobos/libdruntime/core/stdc/stdio.d\n+++ b/libphobos/libdruntime/core/stdc/stdio.d\n@@ -1475,10 +1475,22 @@ size_t fwrite(scope const void* ptr, size_t size, size_t nmemb, FILE* stream);\n // No unsafe pointer manipulation.\n @trusted\n {\n- ///\n- int fgetpos(FILE* stream, scope fpos_t * pos);\n- ///\n- int fsetpos(FILE* stream, scope const fpos_t* pos);\n+ version (NetBSD)\n+ {\n+ ///\n+ pragma(mangle, \"__fgetpos50\")\n+ int fgetpos(FILE* stream, scope fpos_t * pos);\n+ ///\n+ pragma(mangle, \"__fsetpos50\")\n+ int fsetpos(FILE* stream, scope const fpos_t* pos);\n+ }\n+ else\n+ {\n+ ///\n+ int fgetpos(FILE* stream, scope fpos_t * pos);\n+ ///\n+ int fsetpos(FILE* stream, scope const fpos_t* pos);\n+ }\n \n ///\n int fseek(FILE* stream, c_long offset, int whence);\ndiff --git a/libphobos/libdruntime/core/stdc/time.d b/libphobos/libdruntime/core/stdc/time.d\nindex d7a57655fab..ead533718b7 100644\n--- a/libphobos/libdruntime/core/stdc/time.d\n+++ b/libphobos/libdruntime/core/stdc/time.d\n@@ -29,26 +29,55 @@ extern (C):\n nothrow:\n @nogc:\n \n-///\n-pragma(mangle, muslRedirTime64Mangle!(\"difftime\", \"__difftime64\"))\n-pure double difftime(time_t time1, time_t time0); // MT-Safe\n-///\n-pragma(mangle, muslRedirTime64Mangle!(\"mktime\", \"__mktime64\"))\n-@system time_t mktime(scope tm* timeptr); // @system: MT-Safe env locale\n-///\n-pragma(mangle, muslRedirTime64Mangle!(\"time\", \"__time64\"))\n-time_t time(scope time_t* timer);\n+version (NetBSD)\n+{\n+ ///\n+ pragma(mangle, \"__difftime50\")\n+ pure double difftime(time_t time1, time_t time0); // MT-Safe\n+ ///\n+ pragma(mangle, \"__mktime50\")\n+ @system time_t mktime(scope tm* timeptr); // @system: MT-Safe env locale\n+ ///\n+ pragma(mangle, \"__time50\")\n+ time_t time(scope time_t* timer);\n \n-///\n-@system char* asctime(const scope tm* timeptr); // @system: MT-Unsafe race:asctime locale\n-///\n-pragma(mangle, muslRedirTime64Mangle!(\"ctime\", \"__ctime64\"))\n-@system char* ctime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf race:asctime env locale\n-///\n-pragma(mangle, muslRedirTime64Mangle!(\"gmtime\", \"__gmtime64\"))\n-@system tm* gmtime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf env locale\n-///\n-pragma(mangle, muslRedirTime64Mangle!(\"localtime\", \"__localtime64\"))\n-@system tm* localtime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf env locale\n-///\n-@system size_t strftime(scope char* s, size_t maxsize, const scope char* format, const scope tm* timeptr); // @system: MT-Safe env locale\n+ ///\n+ @system char* asctime(const scope tm* timeptr); // @system: MT-Unsafe race:asctime locale\n+ ///\n+ pragma(mangle, \"__ctime50\")\n+ @system char* ctime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf race:asctime env locale\n+ ///\n+ pragma(mangle, \"__gmtime50\")\n+ @system tm* gmtime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf env locale\n+ ///\n+ pragma(mangle, \"__locatime50\")\n+ @system tm* localtime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf env locale\n+ ///\n+ @system size_t strftime(scope char* s, size_t maxsize, const scope char* format, const scope tm* timeptr); // @system: MT-Safe env locale\n+}\n+else\n+{\n+ ///\n+ pragma(mangle, muslRedirTime64Mangle!(\"difftime\", \"__difftime64\"))\n+ pure double difftime(time_t time1, time_t time0); // MT-Safe\n+ ///\n+ pragma(mangle, muslRedirTime64Mangle!(\"mktime\", \"__mktime64\"))\n+ @system time_t mktime(scope tm* timeptr); // @system: MT-Safe env locale\n+ ///\n+ pragma(mangle, muslRedirTime64Mangle!(\"time\", \"__time64\"))\n+ time_t time(scope time_t* timer);\n+\n+ ///\n+ @system char* asctime(const scope tm* timeptr); // @system: MT-Unsafe race:asctime locale\n+ ///\n+ pragma(mangle, muslRedirTime64Mangle!(\"ctime\", \"__ctime64\"))\n+ @system char* ctime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf race:asctime env locale\n+ ///\n+ pragma(mangle, muslRedirTime64Mangle!(\"gmtime\", \"__gmtime64\"))\n+ @system tm* gmtime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf env locale\n+ ///\n+ pragma(mangle, muslRedirTime64Mangle!(\"localtime\", \"__localtime64\"))\n+ @system tm* localtime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf env locale\n+ ///\n+ @system size_t strftime(scope char* s, size_t maxsize, const scope char* format, const scope tm* timeptr); // @system: MT-Safe env locale\n+}\ndiff --git a/libphobos/libdruntime/core/sync/condition.d b/libphobos/libdruntime/core/sync/condition.d\nindex 3acee7a7f45..9328f6d4886 100644\n--- a/libphobos/libdruntime/core/sync/condition.d\n+++ b/libphobos/libdruntime/core/sync/condition.d\n@@ -246,7 +246,7 @@ class Condition\n }\n else version (Posix)\n {\n- int rc = pthread_cond_wait( cast(pthread_cond_t*) &m_hndl, (cast(Mutex) m_assocMutex).handleAddr() );\n+ int rc = pthread_cond_wait( cast(pthread_cond_t*) &m_hndl, (cast(Mutex) mutex()).handleAddr() );\n if ( rc )\n throw staticError!AssertError(\"Unable to wait for condition\", __FILE__, __LINE__);\n }\n@@ -307,7 +307,7 @@ class Condition\n mktspec( t, val );\n \n int rc = pthread_cond_timedwait( cast(pthread_cond_t*) &m_hndl,\n- (cast(Mutex) m_assocMutex).handleAddr(),\n+ (cast(Mutex) mutex()).handleAddr(),\n &t );\n if ( !rc )\n return true;\ndiff --git a/libphobos/libdruntime/core/sync/mutex.d b/libphobos/libdruntime/core/sync/mutex.d\nindex 8993f85071b..86a112119d8 100644\n--- a/libphobos/libdruntime/core/sync/mutex.d\n+++ b/libphobos/libdruntime/core/sync/mutex.d\n@@ -100,7 +100,8 @@ class Mutex :\n abort(\"Error: pthread_mutex_init failed.\");\n }\n \n- m_proxy.link = this;\n+ auto self = cast(Mutex) this;\n+ self.m_proxy.link = self;\n this.__monitor = cast(void*) &m_proxy;\n }\n \n@@ -183,13 +184,14 @@ class Mutex :\n final void lock_nothrow(this Q)() nothrow @trusted @nogc\n if (is(Q == Mutex) || is(Q == shared Mutex))\n {\n+ auto self = cast(Mutex) this;\n version (Windows)\n {\n- EnterCriticalSection(&m_hndl);\n+ EnterCriticalSection(&self.m_hndl);\n }\n else version (Posix)\n {\n- if (pthread_mutex_lock(&m_hndl) == 0)\n+ if (pthread_mutex_lock(&self.m_hndl) == 0)\n return;\n \n SyncError syncErr = cast(SyncError) __traits(initSymbol, SyncError).ptr;\n@@ -221,13 +223,14 @@ class Mutex :\n final void unlock_nothrow(this Q)() nothrow @trusted @nogc\n if (is(Q == Mutex) || is(Q == shared Mutex))\n {\n+ auto self = cast(Mutex) this;\n version (Windows)\n {\n- LeaveCriticalSection(&m_hndl);\n+ LeaveCriticalSection(&self.m_hndl);\n }\n else version (Posix)\n {\n- if (pthread_mutex_unlock(&m_hndl) == 0)\n+ if (pthread_mutex_unlock(&self.m_hndl) == 0)\n return;\n \n SyncError syncErr = cast(SyncError) __traits(initSymbol, SyncError).ptr;\n@@ -263,13 +266,14 @@ class Mutex :\n final bool tryLock_nothrow(this Q)() nothrow @trusted @nogc\n if (is(Q == Mutex) || is(Q == shared Mutex))\n {\n+ auto self = cast(Mutex) this;\n version (Windows)\n {\n- return TryEnterCriticalSection(&m_hndl) != 0;\n+ return TryEnterCriticalSection(&self.m_hndl) != 0;\n }\n else version (Posix)\n {\n- return pthread_mutex_trylock(&m_hndl) == 0;\n+ return pthread_mutex_trylock(&self.m_hndl) == 0;\n }\n }\n \ndiff --git a/libphobos/libdruntime/core/sync/rwmutex.d b/libphobos/libdruntime/core/sync/rwmutex.d\nindex cb581621ec5..e46b2f736f4 100644\n--- a/libphobos/libdruntime/core/sync/rwmutex.d\n+++ b/libphobos/libdruntime/core/sync/rwmutex.d\n@@ -20,6 +20,7 @@ public import core.sync.exception;\n import core.sync.condition;\n import core.sync.mutex;\n import core.memory;\n+import core.atomic : atomicLoad;\n \n \n ////////////////////////////////////////////////////////////////////////////////\n@@ -107,11 +108,11 @@ class ReadWriteMutex\n if ( !m_commonMutex )\n throw new SyncError( \"Unable to initialize mutex\" );\n \n- m_readerQueue = new shared Condition( m_commonMutex );\n+ m_readerQueue = new shared Condition(atomicLoad(m_commonMutex));\n if ( !m_readerQueue )\n throw new SyncError( \"Unable to initialize mutex\" );\n \n- m_writerQueue = new shared Condition( m_commonMutex );\n+ m_writerQueue = new shared Condition(atomicLoad(m_commonMutex));\n if ( !m_writerQueue )\n throw new SyncError( \"Unable to initialize mutex\" );\n \n@@ -139,7 +140,7 @@ class ReadWriteMutex\n ///ditto\n @property Policy policy() shared @safe nothrow\n {\n- return m_policy;\n+ return atomicLoad(m_policy);\n }\n \n ////////////////////////////////////////////////////////////////////////////\n@@ -161,7 +162,7 @@ class ReadWriteMutex\n ///ditto\n @property shared(Reader) reader() shared @safe nothrow\n {\n- return m_reader;\n+ return atomicLoad(m_reader);\n }\n \n /**\n@@ -178,7 +179,7 @@ class ReadWriteMutex\n ///ditto\n @property shared(Writer) writer() shared @safe nothrow\n {\n- return m_writer;\n+ return atomicLoad(m_writer);\n }\n \n \n@@ -200,7 +201,7 @@ class ReadWriteMutex\n this(this Q)() @trusted nothrow\n if (is(Q == Reader) || is(Q == shared Reader))\n {\n- m_proxy.link = this;\n+ m_proxy.link = cast(typeof(m_proxy.link)) this;\n this.__monitor = cast(void*) &m_proxy;\n }\n \n@@ -223,15 +224,7 @@ class ReadWriteMutex\n /// ditto\n @trusted void lock() shared\n {\n- synchronized( m_commonMutex )\n- {\n- ++(cast()m_numQueuedReaders);\n- scope(exit) --(cast()m_numQueuedReaders);\n-\n- while ( shouldQueueReader )\n- m_readerQueue.wait();\n- ++(cast()m_numActiveReaders);\n- }\n+ (cast() this).lock();\n }\n \n /**\n@@ -252,14 +245,7 @@ class ReadWriteMutex\n /// ditto\n @trusted void unlock() shared\n {\n- synchronized( m_commonMutex )\n- {\n- if ( --(cast()m_numActiveReaders) < 1 )\n- {\n- if ( m_numQueuedWriters > 0 )\n- m_writerQueue.notify();\n- }\n- }\n+ (cast() this).unlock();\n }\n \n /**\n@@ -284,13 +270,7 @@ class ReadWriteMutex\n /// ditto\n @trusted bool tryLock() shared\n {\n- synchronized( m_commonMutex )\n- {\n- if ( shouldQueueReader )\n- return false;\n- ++(cast()m_numActiveReaders);\n- return true;\n- }\n+ return (cast() this).tryLock();\n }\n \n /**\n@@ -341,25 +321,7 @@ class ReadWriteMutex\n /// ditto\n @trusted bool tryLock(Duration timeout) shared\n {\n- const initialTime = MonoTime.currTime;\n- synchronized( m_commonMutex )\n- {\n- ++(cast()m_numQueuedReaders);\n- scope(exit) --(cast()m_numQueuedReaders);\n-\n- while (shouldQueueReader)\n- {\n- const timeElapsed = MonoTime.currTime - initialTime;\n- if (timeElapsed >= timeout)\n- return false;\n- auto nextWait = timeout - timeElapsed;\n- // Avoid problems calling wait(Duration) with huge arguments.\n- enum maxWaitPerCall = dur!\"hours\"(24 * 365);\n- m_readerQueue.wait(nextWait < maxWaitPerCall ? nextWait : maxWaitPerCall);\n- }\n- ++(cast()m_numActiveReaders);\n- return true;\n- }\n+ return (cast() this).tryLock(timeout);\n }\n \n \n@@ -410,7 +372,7 @@ class ReadWriteMutex\n this(this Q)() @trusted nothrow\n if (is(Q == Writer) || is(Q == shared Writer))\n {\n- m_proxy.link = this;\n+ m_proxy.link = cast(typeof(m_proxy.link)) this;\n this.__monitor = cast(void*) &m_proxy;\n }\n \n@@ -434,15 +396,7 @@ class ReadWriteMutex\n /// ditto\n @trusted void lock() shared\n {\n- synchronized( m_commonMutex )\n- {\n- ++(cast()m_numQueuedWriters);\n- scope(exit) --(cast()m_numQueuedWriters);\n-\n- while ( shouldQueueWriter )\n- m_writerQueue.wait();\n- ++(cast()m_numActiveWriters);\n- }\n+ (cast() this).lock();\n }\n \n \n@@ -477,27 +431,7 @@ class ReadWriteMutex\n /// ditto\n @trusted void unlock() shared\n {\n- synchronized( m_commonMutex )\n- {\n- if ( --(cast()m_numActiveWriters) < 1 )\n- {\n- switch ( m_policy )\n- {\n- default:\n- case Policy.PREFER_READERS:\n- if ( m_numQueuedReaders > 0 )\n- m_readerQueue.notifyAll();\n- else if ( m_numQueuedWriters > 0 )\n- m_writerQueue.notify();\n- break;\n- case Policy.PREFER_WRITERS:\n- if ( m_numQueuedWriters > 0 )\n- m_writerQueue.notify();\n- else if ( m_numQueuedReaders > 0 )\n- m_readerQueue.notifyAll();\n- }\n- }\n- }\n+ (cast() this).unlock();\n }\n \n \n@@ -523,13 +457,7 @@ class ReadWriteMutex\n /// ditto\n @trusted bool tryLock() shared\n {\n- synchronized( m_commonMutex )\n- {\n- if ( shouldQueueWriter )\n- return false;\n- ++(cast()m_numActiveWriters);\n- return true;\n- }\n+ return (cast() this).tryLock();\n }\n \n /**\n@@ -580,25 +508,7 @@ class ReadWriteMutex\n /// ditto\n @trusted bool tryLock(Duration timeout) shared\n {\n- const initialTime = MonoTime.currTime;\n- synchronized( m_commonMutex )\n- {\n- ++(cast()m_numQueuedWriters);\n- scope(exit) --(cast()m_numQueuedWriters);\n-\n- while (shouldQueueWriter)\n- {\n- const timeElapsed = MonoTime.currTime - initialTime;\n- if (timeElapsed >= timeout)\n- return false;\n- auto nextWait = timeout - timeElapsed;\n- // Avoid problems calling wait(Duration) with huge arguments.\n- enum maxWaitPerCall = dur!\"hours\"(24 * 365);\n- m_writerQueue.wait(nextWait < maxWaitPerCall ? nextWait : maxWaitPerCall);\n- }\n- ++(cast()m_numActiveWriters);\n- return true;\n- }\n+ return (cast() this).tryLock(timeout);\n }\n \n private:\ndiff --git a/libphobos/libdruntime/core/sys/darwin/crt_externs.d b/libphobos/libdruntime/core/sys/darwin/crt_externs.d\nindex ec0788d7de4..a34db83c9d5 100644\n--- a/libphobos/libdruntime/core/sys/darwin/crt_externs.d\n+++ b/libphobos/libdruntime/core/sys/darwin/crt_externs.d\n@@ -8,7 +8,7 @@\n */\n module core.sys.darwin.crt_externs;\n \n-version (CoreDoc)\n+version (CoreDdoc)\n {\n /**\n * In reality this will be $(REF mach_header, core, sys, darwin, mach, loader)\ndiff --git a/libphobos/libdruntime/core/sys/freebsd/config.d b/libphobos/libdruntime/core/sys/freebsd/config.d\nindex 932f166d2d0..144ef055372 100644\n--- a/libphobos/libdruntime/core/sys/freebsd/config.d\n+++ b/libphobos/libdruntime/core/sys/freebsd/config.d\n@@ -14,7 +14,8 @@ public import core.sys.posix.config;\n // NOTE: When adding newer versions of FreeBSD, verify all current versioned\n // bindings are still compatible with the release.\n \n- version (FreeBSD_16) enum __FreeBSD_version = 1600011;\n+ version (CoreDdoc) enum __FreeBSD_version = 1600011; // keep at latest\n+else version (FreeBSD_16) enum __FreeBSD_version = 1600011;\n else version (FreeBSD_15) enum __FreeBSD_version = 1500063;\n else version (FreeBSD_14) enum __FreeBSD_version = 1400097;\n else version (FreeBSD_13) enum __FreeBSD_version = 1301000;\ndiff --git a/libphobos/libdruntime/core/sys/posix/aio.d b/libphobos/libdruntime/core/sys/posix/aio.d\nindex 3a537a4a575..674fab9fc99 100644\n--- a/libphobos/libdruntime/core/sys/posix/aio.d\n+++ b/libphobos/libdruntime/core/sys/posix/aio.d\n@@ -386,6 +386,18 @@ else version (OpenBSD)\n {\n // OpenBSD does not implement aio.h\n }\n+else version (NetBSD)\n+{\n+ int aio_cancel(int fd, aiocb* aiocbp);\n+ int aio_error(const(aiocb)* aiocbp);\n+ int aio_fsync(int op, aiocb* aiocbp);\n+ int aio_read(aiocb* aiocbp);\n+ ssize_t aio_return(aiocb* aiocbp);\n+ pragma(mangle, \"__aio_suspend50\")\n+ int aio_suspend(const(aiocb*)* aiocb_list, int nitems, const(timespec)* timeout);\n+ int aio_write(aiocb* aiocbp);\n+ int lio_listio(int mode, const(aiocb*)* aiocb_list, int nitems, sigevent* sevp);\n+}\n else\n {\n int aio_read(aiocb* aiocbp);\ndiff --git a/libphobos/libdruntime/core/sys/posix/dirent.d b/libphobos/libdruntime/core/sys/posix/dirent.d\nindex 18cee4c43cd..c77d6da22b2 100644\n--- a/libphobos/libdruntime/core/sys/posix/dirent.d\n+++ b/libphobos/libdruntime/core/sys/posix/dirent.d\n@@ -441,6 +441,26 @@ else\n static assert(false, \"Unsupported platform\");\n }\n \n+//\n+// POSIX.1-2008\n+//\n+/*\n+int dirfd(DIR*);\n+*/\n+version (NetBSD)\n+{\n+ // On NetBSD, this is a macro in dirent.h, not a function.\n+ extern (D) int dirfd()(DIR* dir) nothrow @nogc\n+ {\n+ // ABI guarantees dd_fd remains the first field\n+ return *(cast(int*) dir);\n+ }\n+}\n+else\n+{\n+ nothrow @nogc int dirfd(DIR* dir);\n+}\n+\n // Only OS X out of the Darwin family needs special treatment. Other Darwins\n // (iOS, TVOS, WatchOS) are fine with normal symbol names for these functions\n // in else below.\ndiff --git a/libphobos/libdruntime/core/sys/posix/locale.d b/libphobos/libdruntime/core/sys/posix/locale.d\nindex 0864f7c6325..821487afd29 100644\n--- a/libphobos/libdruntime/core/sys/posix/locale.d\n+++ b/libphobos/libdruntime/core/sys/posix/locale.d\n@@ -118,8 +118,17 @@ version (DarwinBSDLocale)\n lconv* localeconv();\n /// Create a new locale\n locale_t newlocale(int mask, const char* locale, locale_t base);\n- /// Set the C library's notion of natural language formatting style\n- char* setlocale(int category, const char* locale);\n+ version (NetBSD)\n+ {\n+ /// Set the C library's notion of natural language formatting style\n+ pragma(mangle, \"__setlocale50\")\n+ char* setlocale(int category, const char* locale);\n+ }\n+ else\n+ {\n+ /// Set the C library's notion of natural language formatting style\n+ char* setlocale(int category, const char* locale);\n+ }\n /// Set the per-thread locale\n locale_t uselocale (locale_t locale);\n }\ndiff --git a/libphobos/libdruntime/core/sys/posix/netinet/in_.d b/libphobos/libdruntime/core/sys/posix/netinet/in_.d\nindex 09a4a5e07d1..75359ea213a 100644\n--- a/libphobos/libdruntime/core/sys/posix/netinet/in_.d\n+++ b/libphobos/libdruntime/core/sys/posix/netinet/in_.d\n@@ -547,7 +547,7 @@ version (CRuntime_Glibc)\n }\n \n // macros\n- extern (D) int IN6_IS_ADDR_UNSPECIFIED()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_UNSPECIFIED()(const scope in6_addr* addr) pure\n {\n return (cast(uint32_t*) addr)[0] == 0 &&\n (cast(uint32_t*) addr)[1] == 0 &&\n@@ -555,7 +555,7 @@ version (CRuntime_Glibc)\n (cast(uint32_t*) addr)[3] == 0;\n }\n \n- extern (D) int IN6_IS_ADDR_LOOPBACK()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_LOOPBACK()(const scope in6_addr* addr) pure\n {\n return (cast(uint32_t*) addr)[0] == 0 &&\n (cast(uint32_t*) addr)[1] == 0 &&\n@@ -563,29 +563,29 @@ version (CRuntime_Glibc)\n (cast(uint32_t*) addr)[3] == htonl( 1 );\n }\n \n- extern (D) int IN6_IS_ADDR_MULTICAST()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_MULTICAST()(const scope in6_addr* addr) pure\n {\n return (cast(uint8_t*) addr)[0] == 0xff;\n }\n \n- extern (D) int IN6_IS_ADDR_LINKLOCAL()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_LINKLOCAL()(const scope in6_addr* addr) pure\n {\n return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfe800000 );\n }\n \n- extern (D) int IN6_IS_ADDR_SITELOCAL()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_SITELOCAL()(const scope in6_addr* addr) pure\n {\n return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfec00000 );\n }\n \n- extern (D) int IN6_IS_ADDR_V4MAPPED()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_V4MAPPED()(const scope in6_addr* addr) pure\n {\n return (cast(uint32_t*) addr)[0] == 0 &&\n (cast(uint32_t*) addr)[1] == 0 &&\n (cast(uint32_t*) addr)[2] == htonl( 0xffff );\n }\n \n- extern (D) int IN6_IS_ADDR_V4COMPAT()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_V4COMPAT()(const scope in6_addr* addr) pure\n {\n return (cast(uint32_t*) addr)[0] == 0 &&\n (cast(uint32_t*) addr)[1] == 0 &&\n@@ -593,31 +593,31 @@ version (CRuntime_Glibc)\n ntohl( (cast(uint32_t*) addr)[3] ) > 1;\n }\n \n- extern (D) int IN6_IS_ADDR_MC_NODELOCAL()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_MC_NODELOCAL()(const scope in6_addr* addr) pure\n {\n return IN6_IS_ADDR_MULTICAST( addr ) &&\n ((cast(uint8_t*) addr)[1] & 0xf) == 0x1;\n }\n \n- extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()(const scope in6_addr* addr) pure\n {\n return IN6_IS_ADDR_MULTICAST( addr ) &&\n ((cast(uint8_t*) addr)[1] & 0xf) == 0x2;\n }\n \n- extern (D) int IN6_IS_ADDR_MC_SITELOCAL()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_MC_SITELOCAL()(const scope in6_addr* addr) pure\n {\n return IN6_IS_ADDR_MULTICAST(addr) &&\n ((cast(uint8_t*) addr)[1] & 0xf) == 0x5;\n }\n \n- extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()(const scope in6_addr* addr) pure\n {\n return IN6_IS_ADDR_MULTICAST( addr) &&\n ((cast(uint8_t*) addr)[1] & 0xf) == 0x8;\n }\n \n- extern (D) int IN6_IS_ADDR_MC_GLOBAL()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_MC_GLOBAL()(const scope in6_addr* addr) pure\n {\n return IN6_IS_ADDR_MULTICAST( addr ) &&\n ((cast(uint8_t*) addr)[1] & 0xf) == 0xe;\n@@ -670,7 +670,7 @@ else version (Darwin)\n }\n \n // macros\n- extern (D) int IN6_IS_ADDR_UNSPECIFIED()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_UNSPECIFIED()(const scope in6_addr* addr) pure\n {\n return (cast(uint32_t*) addr)[0] == 0 &&\n (cast(uint32_t*) addr)[1] == 0 &&\n@@ -678,7 +678,7 @@ else version (Darwin)\n (cast(uint32_t*) addr)[3] == 0;\n }\n \n- extern (D) int IN6_IS_ADDR_LOOPBACK()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_LOOPBACK()(const scope in6_addr* addr) pure\n {\n return (cast(uint32_t*) addr)[0] == 0 &&\n (cast(uint32_t*) addr)[1] == 0 &&\n@@ -686,29 +686,29 @@ else version (Darwin)\n (cast(uint32_t*) addr)[3] == ntohl( 1 );\n }\n \n- extern (D) int IN6_IS_ADDR_MULTICAST()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_MULTICAST()(const scope in6_addr* addr) pure\n {\n return addr.s6_addr[0] == 0xff;\n }\n \n- extern (D) int IN6_IS_ADDR_LINKLOCAL()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_LINKLOCAL()(const scope in6_addr* addr) pure\n {\n return addr.s6_addr[0] == 0xfe && (addr.s6_addr[1] & 0xc0) == 0x80;\n }\n \n- extern (D) int IN6_IS_ADDR_SITELOCAL()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_SITELOCAL()(const scope in6_addr* addr) pure\n {\n return addr.s6_addr[0] == 0xfe && (addr.s6_addr[1] & 0xc0) == 0xc0;\n }\n \n- extern (D) int IN6_IS_ADDR_V4MAPPED()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_V4MAPPED()(const scope in6_addr* addr) pure\n {\n return (cast(uint32_t*) addr)[0] == 0 &&\n (cast(uint32_t*) addr)[1] == 0 &&\n (cast(uint32_t*) addr)[2] == ntohl( 0x0000ffff );\n }\n \n- extern (D) int IN6_IS_ADDR_V4COMPAT()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_V4COMPAT()(const scope in6_addr* addr) pure\n {\n return (cast(uint32_t*) addr)[0] == 0 &&\n (cast(uint32_t*) addr)[1] == 0 &&\n@@ -717,31 +717,31 @@ else version (Darwin)\n (cast(uint32_t*) addr)[3] != ntohl( 1 );\n }\n \n- extern (D) int IN6_IS_ADDR_MC_NODELOCAL()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_MC_NODELOCAL()(const scope in6_addr* addr) pure\n {\n return IN6_IS_ADDR_MULTICAST( addr ) &&\n ((cast(uint8_t*) addr)[1] & 0xf) == 0x1;\n }\n \n- extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()(const scope in6_addr* addr) pure\n {\n return IN6_IS_ADDR_MULTICAST( addr ) &&\n ((cast(uint8_t*) addr)[1] & 0xf) == 0x2;\n }\n \n- extern (D) int IN6_IS_ADDR_MC_SITELOCAL()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_MC_SITELOCAL()(const scope in6_addr* addr) pure\n {\n return IN6_IS_ADDR_MULTICAST(addr) &&\n ((cast(uint8_t*) addr)[1] & 0xf) == 0x5;\n }\n \n- extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()(const scope in6_addr* addr) pure\n {\n return IN6_IS_ADDR_MULTICAST( addr) &&\n ((cast(uint8_t*) addr)[1] & 0xf) == 0x8;\n }\n \n- extern (D) int IN6_IS_ADDR_MC_GLOBAL()(const scope in6_addr* add) pure\n+ extern (D) int IN6_IS_ADDR_MC_GLOBAL()(const scope in6_addr* addr) pure\n {\n return IN6_IS_ADDR_MULTICAST( addr ) &&\n ((cast(uint8_t*) addr)[1] & 0xf) == 0xe;\ndiff --git a/libphobos/libdruntime/core/sys/posix/pwd.d b/libphobos/libdruntime/core/sys/posix/pwd.d\nindex d4b4a07673a..3402a9e263a 100644\n--- a/libphobos/libdruntime/core/sys/posix/pwd.d\n+++ b/libphobos/libdruntime/core/sys/posix/pwd.d\n@@ -201,8 +201,16 @@ else\n static assert(false, \"Unsupported platform\");\n }\n \n-passwd* getpwnam(const scope char*);\n-passwd* getpwuid(uid_t);\n+version (NetBSD)\n+{\n+ pragma(mangle, \"__getpwnam50\") passwd* getpwnam(const scope char*);\n+ pragma(mangle, \"__getpwuid50\") passwd* getpwuid(uid_t);\n+}\n+else\n+{\n+ passwd* getpwnam(const scope char*);\n+ passwd* getpwuid(uid_t);\n+}\n \n //\n // Thread-Safe Functions (TSF)\n@@ -301,7 +309,7 @@ else version (FreeBSD)\n else version (NetBSD)\n {\n void endpwent();\n- passwd* getpwent();\n+ pragma(mangle, \"__getpwent50\") passwd* getpwent();\n void setpwent();\n }\n else version (OpenBSD)\ndiff --git a/libphobos/libdruntime/core/sys/posix/sched.d b/libphobos/libdruntime/core/sys/posix/sched.d\nindex d5798358415..273be5e8191 100644\n--- a/libphobos/libdruntime/core/sys/posix/sched.d\n+++ b/libphobos/libdruntime/core/sys/posix/sched.d\n@@ -262,6 +262,7 @@ else version (NetBSD)\n {\n int sched_get_priority_min(int);\n int sched_get_priority_max(int);\n+ pragma(mangle, \"__sched_rr_get_interval50\")\n int sched_rr_get_interval(pid_t, timespec*);\n }\n else version (OpenBSD)\ndiff --git a/libphobos/libdruntime/core/sys/posix/setjmp.d b/libphobos/libdruntime/core/sys/posix/setjmp.d\nindex 24497a27ae2..d1fcb1947c2 100644\n--- a/libphobos/libdruntime/core/sys/posix/setjmp.d\n+++ b/libphobos/libdruntime/core/sys/posix/setjmp.d\n@@ -257,8 +257,8 @@ else version (NetBSD)\n static assert(0);\n alias jmp_buf = _jmp_buf[_JBLEN];\n \n- int setjmp(ref jmp_buf);\n- void longjmp(ref jmp_buf, int);\n+ pragma(mangle, \"__setjmp14\") int setjmp(ref jmp_buf);\n+ pragma(mangle, \"__longjmp14\") void longjmp(ref jmp_buf, int);\n }\n else version (OpenBSD)\n {\n@@ -486,8 +486,8 @@ else version (NetBSD)\n static assert(0);\n alias sigjmp_buf = _sigjmp_buf[_JBLEN + 1];\n \n- int sigsetjmp(ref sigjmp_buf);\n- void siglongjmp(ref sigjmp_buf, int);\n+ pragma(mangle, \"__sigsetjmp14\") int sigsetjmp(ref sigjmp_buf);\n+ pragma(mangle, \"__siglongjmp14\") void siglongjmp(ref sigjmp_buf, int);\n }\n else version (OpenBSD)\n {\ndiff --git a/libphobos/libdruntime/core/sys/posix/signal.d b/libphobos/libdruntime/core/sys/posix/signal.d\nindex 73da7607c57..94ddd0403da 100644\n--- a/libphobos/libdruntime/core/sys/posix/signal.d\n+++ b/libphobos/libdruntime/core/sys/posix/signal.d\n@@ -3019,6 +3019,7 @@ else version (FreeBSD)\n else version (NetBSD)\n {\n int sigqueue(pid_t, int, const sigval);\n+ pragma(mangle, \"__sigtimedwait50\")\n int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);\n int sigwaitinfo(const scope sigset_t*, siginfo_t*);\n }\ndiff --git a/libphobos/libdruntime/core/sys/posix/stdc/time.d b/libphobos/libdruntime/core/sys/posix/stdc/time.d\nindex dee81ecc342..abeb715ad73 100644\n--- a/libphobos/libdruntime/core/sys/posix/stdc/time.d\n+++ b/libphobos/libdruntime/core/sys/posix/stdc/time.d\n@@ -146,6 +146,7 @@ else version (FreeBSD)\n else version (NetBSD)\n {\n ///\n+ pragma(mangle, \"__tzset50\")\n void tzset(); // non-standard\n ///\n extern __gshared const(char)*[2] tzname; // non-standard\ndiff --git a/libphobos/libdruntime/core/sys/posix/stdlib.d b/libphobos/libdruntime/core/sys/posix/stdlib.d\nindex 8e8c16fab53..3a6a5d2407d 100644\n--- a/libphobos/libdruntime/core/sys/posix/stdlib.d\n+++ b/libphobos/libdruntime/core/sys/posix/stdlib.d\n@@ -459,14 +459,14 @@ else version (NetBSD)\n c_long nrand48(ref ushort[3]);\n int posix_openpt(int);\n char* ptsname(int);\n- int putenv(char*);\n+ pragma(mangle, \"__putenv50\") int putenv(char*);\n c_long random();\n char* realpath(const scope char*, char*);\n ushort *seed48(ref ushort[3]);\n void setkey(const scope char*);\n char* setstate(const scope char*);\n void srand48(c_long);\n- void srandom(uint);\n+ pragma(mangle, \"__srandom60\") void srandom(uint);\n int unlockpt(int);\n }\n else version (OpenBSD)\ndiff --git a/libphobos/libdruntime/core/sys/posix/sys/msg.d b/libphobos/libdruntime/core/sys/posix/sys/msg.d\nindex 19e07bd6468..519811820f6 100644\n--- a/libphobos/libdruntime/core/sys/posix/sys/msg.d\n+++ b/libphobos/libdruntime/core/sys/posix/sys/msg.d\n@@ -200,7 +200,10 @@ struct msgbuf\n char[1] mtext = 0;\n }\n \n-int msgctl(int msqid, int cmd, msqid_ds* __buf);\n+version (NetBSD)\n+ pragma(mangle, \"__msgctl50\") int msgctl(int msqid, int cmd, msqid_ds* __buf);\n+else\n+ int msgctl(int msqid, int cmd, msqid_ds* __buf);\n int msgget(key_t key, int msgflg);\n ssize_t msgrcv(int msqid, void* msgp, size_t msgsz, c_long msgtyp, int msgflg);\n int msgsnd(int msqid, msgbuf* msgp, int msgsz, int msgflg);\ndiff --git a/libphobos/libdruntime/core/sys/posix/sys/resource.d b/libphobos/libdruntime/core/sys/posix/sys/resource.d\nindex 3da8411d6af..eb62e4950fd 100644\n--- a/libphobos/libdruntime/core/sys/posix/sys/resource.d\n+++ b/libphobos/libdruntime/core/sys/posix/sys/resource.d\n@@ -530,7 +530,7 @@ else version (NetBSD)\n {\n int getpriority(int, int);\n int getrlimit(int, rlimit*);\n- int getrusage(int, rusage*);\n+ pragma(mangle, \"__getrusage50\") int getrusage(int, rusage*);\n int setpriority(int, int, int);\n int setrlimit(int, const scope rlimit*);\n }\ndiff --git a/libphobos/libdruntime/core/sys/posix/sys/select.d b/libphobos/libdruntime/core/sys/posix/sys/select.d\nindex 064dfbcc5f8..5152d0fe17d 100644\n--- a/libphobos/libdruntime/core/sys/posix/sys/select.d\n+++ b/libphobos/libdruntime/core/sys/posix/sys/select.d\n@@ -268,7 +268,9 @@ else version (NetBSD)\n _p.fds_bits[--_n] = 0;\n }\n \n+ pragma(mangle, \"__pselect50\")\n int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);\n+ pragma(mangle, \"__select50\")\n int select(int, fd_set*, fd_set*, fd_set*, timeval*);\n }\n else version (OpenBSD)\ndiff --git a/libphobos/libdruntime/core/sys/posix/sys/shm.d b/libphobos/libdruntime/core/sys/posix/sys/shm.d\nindex 927778dd2a6..358fcf9e322 100644\n--- a/libphobos/libdruntime/core/sys/posix/sys/shm.d\n+++ b/libphobos/libdruntime/core/sys/posix/sys/shm.d\n@@ -219,7 +219,7 @@ else version (NetBSD)\n enum SHMLBA = 1 << 12; // PAGE_SIZE = (1<<PAGE_SHIFT)\n \n void* shmat(int, const scope void*, int);\n- int shmctl(int, int, shmid_ds*);\n+ pragma(mangle, \"__shmctl50\") int shmctl(int, int, shmid_ds*);\n int shmdt(const scope void*);\n int shmget(key_t, size_t, int);\n }\ndiff --git a/libphobos/libdruntime/core/sys/posix/sys/socket.d b/libphobos/libdruntime/core/sys/posix/sys/socket.d\nindex 35f316bd935..0ae101db098 100644\n--- a/libphobos/libdruntime/core/sys/posix/sys/socket.d\n+++ b/libphobos/libdruntime/core/sys/posix/sys/socket.d\n@@ -1704,7 +1704,7 @@ else version (NetBSD)\n ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);\n int setsockopt(int, int, int, const scope void*, socklen_t);\n int shutdown(int, int) @safe;\n- int socket(int, int, int) @safe;\n+ pragma(mangle, \"__socket30\") int socket(int, int, int) @safe;\n int sockatmark(int) @safe;\n int socketpair(int, int, int, ref int[2]) @safe;\n }\ndiff --git a/libphobos/libdruntime/core/sys/posix/sys/stat.d b/libphobos/libdruntime/core/sys/posix/sys/stat.d\nindex ad59019e181..a14fc149d70 100644\n--- a/libphobos/libdruntime/core/sys/posix/sys/stat.d\n+++ b/libphobos/libdruntime/core/sys/posix/sys/stat.d\n@@ -2010,12 +2010,14 @@ else version (Darwin)\n version (AArch64)\n {\n int fstat(int, stat_t*);\n+ int fstatat(int, const scope char*, stat_t*, int);\n int lstat(const scope char*, stat_t*);\n int stat(const scope char*, stat_t*);\n }\n else\n {\n pragma(mangle, \"fstat$INODE64\") int fstat(int, stat_t*);\n+ pragma(mangle, \"fstatat$INODE64\") int fstatat(int, const scope char*, stat_t*, int);\n pragma(mangle, \"lstat$INODE64\") int lstat(const scope char*, stat_t*);\n pragma(mangle, \"stat$INODE64\") int stat(const scope char*, stat_t*);\n }\n@@ -2023,11 +2025,11 @@ else version (Darwin)\n else\n {\n int fstat(int, stat_t*);\n+ int fstatat(int, const scope char*, stat_t*, int);\n int lstat(const scope char*, stat_t*);\n int stat(const scope char*, stat_t*);\n }\n int fchmodat(int, const scope char*, mode_t, int);\n- int fstatat(int, const scope char*, stat_t*, int);\n int futimens(int, ref const(timespec)[2]);\n int mkdirat(int, const scope char*, mode_t);\n int mkfifoat(int, const scope char*, mode_t);\n@@ -2352,7 +2354,7 @@ else version (FreeBSD)\n }\n else version (NetBSD)\n {\n- int mknod(const scope char*, mode_t, dev_t);\n+ pragma(mangle, \"__mknod50\") int mknod(const scope char*, mode_t, dev_t);\n int mknodat(int, const scope char*, mode_t, dev_t);\n }\n else version (OpenBSD)\ndiff --git a/libphobos/libdruntime/core/sys/posix/sys/statvfs.d b/libphobos/libdruntime/core/sys/posix/sys/statvfs.d\nindex dec253d3005..a8f3dd50654 100644\n--- a/libphobos/libdruntime/core/sys/posix/sys/statvfs.d\n+++ b/libphobos/libdruntime/core/sys/posix/sys/statvfs.d\n@@ -180,7 +180,9 @@ else version (NetBSD)\n ST_NOSUID = 2\n }\n \n+ pragma(mangle, \"__statvfs90\")\n int statvfs (const char * file, statvfs_t* buf);\n+ pragma(mangle, \"__fstatvfs90\")\n int fstatvfs (int fildes, statvfs_t *buf) @trusted;\n }\n else version (OpenBSD)\ndiff --git a/libphobos/libdruntime/core/sys/posix/sys/time.d b/libphobos/libdruntime/core/sys/posix/sys/time.d\nindex dda4caf0bf3..6dcd4878d19 100644\n--- a/libphobos/libdruntime/core/sys/posix/sys/time.d\n+++ b/libphobos/libdruntime/core/sys/posix/sys/time.d\n@@ -160,9 +160,13 @@ else version (NetBSD)\n timeval it_value;\n }\n \n+ pragma(mangle, \"__getitimer50\")\n int getitimer(int, itimerval*);\n+ pragma(mangle, \"__gettimeofday50\")\n int gettimeofday(timeval*, void*); // timezone_t* is normally void*\n+ pragma(mangle, \"__setitimer50\")\n int setitimer(int, const scope itimerval*, itimerval*);\n+ pragma(mangle, \"__utimes50\")\n int utimes(const scope char*, ref const(timeval)[2]);\n }\n else version (OpenBSD)\ndiff --git a/libphobos/libdruntime/core/sys/posix/sys/types.d b/libphobos/libdruntime/core/sys/posix/sys/types.d\nindex b6febde7136..cad60b4da4d 100644\n--- a/libphobos/libdruntime/core/sys/posix/sys/types.d\n+++ b/libphobos/libdruntime/core/sys/posix/sys/types.d\n@@ -251,7 +251,7 @@ else version (NetBSD)\n alias pid_t = int;\n //size_t (defined in core.stdc.stddef)\n alias ssize_t = c_long;\n- alias time_t = c_long;\n+ alias time_t = long; // _BSD_TIME_T_ mapped to __int64_t\n alias uid_t = uint;\n }\n else version (OpenBSD)\n@@ -388,10 +388,10 @@ else version (NetBSD)\n {\n alias fsblkcnt_t = ulong;\n alias fsfilcnt_t = ulong;\n- alias clock_t = c_long;\n+ alias clock_t = uint; // unsigned int\n alias id_t = long;\n alias key_t = c_long;\n- alias suseconds_t = c_long;\n+ alias suseconds_t = int; // int\n alias useconds_t = uint;\n }\n else version (OpenBSD)\ndiff --git a/libphobos/libdruntime/core/sys/posix/time.d b/libphobos/libdruntime/core/sys/posix/time.d\nindex a631ddc2bcb..4fc73aab8c5 100644\n--- a/libphobos/libdruntime/core/sys/posix/time.d\n+++ b/libphobos/libdruntime/core/sys/posix/time.d\n@@ -64,6 +64,7 @@ else version (FreeBSD)\n }\n else version (NetBSD)\n {\n+ pragma(mangle, \"__timegm50\")\n time_t timegm(tm*); // non-standard\n }\n else version (OpenBSD)\n@@ -378,14 +379,20 @@ else version (NetBSD)\n alias clockid_t = int; // <sys/_types.h>\n alias timer_t = int;\n \n+ pragma(mangle, \"__clock_getres50\")\n int clock_getres(clockid_t, timespec*);\n+ pragma(mangle, \"__clock_gettime50\")\n int clock_gettime(clockid_t, timespec*);\n+ pragma(mangle, \"__clock_settime50\")\n int clock_settime(clockid_t, const scope timespec*);\n+ pragma(mangle, \"__nanosleep50\")\n int nanosleep(const scope timespec*, timespec*);\n int timer_create(clockid_t, sigevent*, timer_t*);\n int timer_delete(timer_t);\n+ pragma(mangle, \"__timer_gettime50\")\n int timer_gettime(timer_t, itimerspec*);\n int timer_getoverrun(timer_t);\n+ pragma(mangle, \"__timer_settime50\")\n int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*);\n }\n else version (OpenBSD)\n@@ -576,8 +583,11 @@ else version (FreeBSD)\n else version (NetBSD)\n {\n char* asctime_r(const scope tm*, char*);\n+ pragma(mangle, \"__ctime_r50\")\n char* ctime_r(const scope time_t*, char*);\n+ pragma(mangle, \"__gmtime_r50\")\n tm* gmtime_r(const scope time_t*, tm*);\n+ pragma(mangle, \"__localtime_r50\")\n tm* localtime_r(const scope time_t*, tm*);\n }\n else version (OpenBSD)\ndiff --git a/libphobos/libdruntime/core/sys/posix/unistd.d b/libphobos/libdruntime/core/sys/posix/unistd.d\nindex 71d501be8c2..ea6d866999c 100644\n--- a/libphobos/libdruntime/core/sys/posix/unistd.d\n+++ b/libphobos/libdruntime/core/sys/posix/unistd.d\n@@ -188,6 +188,8 @@ else version (NetBSD)\n {\n off_t lseek(int, off_t, int) @trusted;\n int ftruncate(int, off_t) @trusted;\n+ // NetBSD 10.0\n+ pragma(mangle, \"__dup3100\") int dup3(int, int, int) @trusted;\n int faccessat(int, const scope char*, int, int);\n int fchownat(int, const scope char*, uid_t, gid_t, int);\n int fexecve(int, const scope char**, const scope char**);\n@@ -671,7 +673,21 @@ version (CRuntime_Glibc)\n _SC_LEVEL4_CACHE_LINESIZE,\n \n _SC_IPV6 = _SC_LEVEL1_ICACHE_SIZE + 50,\n- _SC_RAW_SOCKETS\n+ _SC_RAW_SOCKETS,\n+ _SC_V7_ILP32_OFF32,\n+ _SC_V7_ILP32_OFFBIG,\n+ _SC_V7_LP64_OFF64,\n+ _SC_V7_LPBIG_OFFBIG,\n+ _SC_SS_REPL_MAX,\n+ _SC_TRACE_EVENT_NAME_MAX,\n+ _SC_TRACE_NAME_MAX,\n+ _SC_TRACE_SYS_MAX,\n+ _SC_TRACE_USER_EVENT_MAX,\n+ _SC_XOPEN_STREAMS,\n+ _SC_THREAD_ROBUST_PRIO_INHERIT,\n+ _SC_THREAD_ROBUST_PRIO_PROTECT,\n+ _SC_MINSIGSTKSZ,\n+ _SC_SIGSTKSZ,\n }\n }\n else version (Darwin)\n@@ -2702,7 +2718,7 @@ else version (NetBSD)\n int truncate(const scope char*, off_t);\n useconds_t ualarm(useconds_t, useconds_t) @trusted;\n int usleep(useconds_t) @trusted;\n- pid_t vfork();\n+ pragma(mangle, \"__vfork14\") pid_t vfork();\n }\n else version (OpenBSD)\n {\ndiff --git a/libphobos/libdruntime/core/sys/posix/utime.d b/libphobos/libdruntime/core/sys/posix/utime.d\nindex e7059d71283..16a26b23d95 100644\n--- a/libphobos/libdruntime/core/sys/posix/utime.d\n+++ b/libphobos/libdruntime/core/sys/posix/utime.d\n@@ -93,7 +93,7 @@ else version (NetBSD)\n time_t modtime;\n }\n \n- int utime(const scope char*, const scope utimbuf*);\n+ pragma(mangle, \"__utime50\") int utime(const scope char*, const scope utimbuf*);\n }\n else version (OpenBSD)\n {\ndiff --git a/libphobos/libdruntime/core/sys/windows/winuser.d b/libphobos/libdruntime/core/sys/windows/winuser.d\nindex dddaeb0535a..9d8c26440ed 100644\n--- a/libphobos/libdruntime/core/sys/windows/winuser.d\n+++ b/libphobos/libdruntime/core/sys/windows/winuser.d\n@@ -3720,8 +3720,8 @@ nothrow @nogc {\n alias GetNextWindow = GetWindow;\n \n extern (Windows) nothrow @nogc:\n-LONG DispatchMessageA(const(MSG)*);\n-LONG DispatchMessageW(const(MSG)*);\n+LRESULT DispatchMessageA(const(MSG)*);\n+LRESULT DispatchMessageW(const(MSG)*);\n int DlgDirListA(HWND, LPSTR, int, int, UINT);\n int DlgDirListW(HWND, LPWSTR, int, int, UINT);\n int DlgDirListComboBoxA(HWND, LPSTR, int, int, UINT);\n@@ -4034,8 +4034,8 @@ BOOL ScreenToClient(HWND, LPPOINT);\n BOOL ScrollDC(HDC, int, int, LPCRECT, LPCRECT, HRGN, LPRECT);\n BOOL ScrollWindow(HWND, int, int, LPCRECT, LPCRECT);\n int ScrollWindowEx(HWND, int, int, LPCRECT, LPCRECT, HRGN, LPRECT, UINT);\n-LONG SendDlgItemMessageA(HWND, int, UINT, WPARAM, LPARAM);\n-LONG SendDlgItemMessageW(HWND, int, UINT, WPARAM, LPARAM);\n+LRESULT SendDlgItemMessageA(HWND, int, UINT, WPARAM, LPARAM);\n+LRESULT SendDlgItemMessageW(HWND, int, UINT, WPARAM, LPARAM);\n LRESULT SendMessageA(HWND, UINT, WPARAM, LPARAM);\n BOOL SendMessageCallbackA(HWND, UINT, WPARAM, LPARAM, SENDASYNCPROC, ULONG_PTR);\n BOOL SendMessageCallbackW(HWND, UINT, WPARAM, LPARAM, SENDASYNCPROC, ULONG_PTR);\ndiff --git a/libphobos/libdruntime/core/thread/context.d b/libphobos/libdruntime/core/thread/context.d\nindex e477269b849..81b7478a6d8 100644\n--- a/libphobos/libdruntime/core/thread/context.d\n+++ b/libphobos/libdruntime/core/thread/context.d\n@@ -11,6 +11,7 @@\n \n module core.thread.context;\n \n+///\n struct StackContext\n {\n void* bstack, tstack;\ndiff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d\nindex 6827dad6199..d2e6060a286 100644\n--- a/libphobos/libdruntime/core/thread/osthread.d\n+++ b/libphobos/libdruntime/core/thread/osthread.d\n@@ -653,7 +653,9 @@ class Thread : ThreadBase\n auto local = atomicLoad(mixin(\"cache.\" ~ which));\n if (local != local.min) return local;\n // There will be benign races\n- cache = loadPriorities;\n+ auto loaded = loadPriorities;\n+ static foreach (i, _; loaded.tupleof)\n+ atomicStore(cache.tupleof[i], loaded.tupleof[i]);\n return atomicLoad(mixin(\"cache.\" ~ which));\n }\n \n@@ -1527,6 +1529,27 @@ in (fn)\n mov sp[RBP], RSP;\n }\n }\n+ else version (AArch64)\n+ {\n+\t// Callee-save registers, x19-x28 according to AAPCS64, section\n+\t// 5.1.1. Include x29 fp because it optionally can be a callee\n+\t// saved reg\n+\tsize_t[11] regs = void;\n+\t// store the registers in pairs\n+\tasm pure nothrow @nogc\n+\t{\n+\t/*\n+\t stp x19, x20, regs[0];\n+\t stp x21, x22, regs[2];\n+\t stp x23, x24, regs[4];\n+\t stp x25, x26, regs[6];\n+\t stp x27, x28, regs[8];\n+\t str x29, regs[10];\n+\t mov [sp], sp;\n+\t */\n+\t}\n+\tassert(0, \"implement AArch64 inline assembler for callWithStackShell()\"); // TODO AArch64\n+ }\n else\n {\n static assert(false, \"Architecture not supported.\");\n@@ -1576,6 +1599,11 @@ private extern(D) void* getStackTop() nothrow @nogc\n asm pure nothrow @nogc { naked; mov EAX, ESP; ret; }\n else version (D_InlineAsm_X86_64)\n asm pure nothrow @nogc { naked; mov RAX, RSP; ret; }\n+ else version (AArch64)\n+ //asm pure nothrow @nogc { naked; mov x0, SP; ret; } // TODO AArch64\n+ {\n+ return null;\n+ }\n else version (GNU)\n return __builtin_frame_address(0);\n else\ndiff --git a/libphobos/libdruntime/core/thread/package.d b/libphobos/libdruntime/core/thread/package.d\nindex d81ebbdcc82..a54442b3f13 100644\n--- a/libphobos/libdruntime/core/thread/package.d\n+++ b/libphobos/libdruntime/core/thread/package.d\n@@ -22,38 +22,36 @@ public import core.thread.context;\n \n // this test is here to avoid a cyclic dependency between\n // core.thread and core.atomic\n-unittest\n+@system unittest\n {\n import core.atomic;\n \n- // Use heap memory to ensure an optimizing\n- // compiler doesn't put things in registers.\n- uint* x = new uint();\n- bool* f = new bool();\n- uint* r = new uint();\n+ shared uint x;\n+ shared bool f;\n+ shared uint r;\n \n auto thr = new Thread(()\n {\n- while (!*f)\n+ while (!atomicLoad(f))\n {\n }\n \n- atomicFence();\n+ atomicFence(); // make sure load+store below happens after waiting for f\n \n- *r = *x;\n+ cast() r = cast() x;\n });\n \n- thr.start();\n+ thr.start(); // new thread will wait until f is set\n \n- *x = 42;\n+ cast() x = 42;\n \n- atomicFence();\n+ atomicFence(); // make sure x is set before setting f\n \n- *f = true;\n+ cast() f = true;\n \n atomicFence();\n \n thr.join();\n \n- assert(*r == 42);\n+ assert(cast() r == 42);\n }\ndiff --git a/libphobos/libdruntime/core/thread/types.d b/libphobos/libdruntime/core/thread/types.d\nindex c816010e5ce..e630c39668e 100644\n--- a/libphobos/libdruntime/core/thread/types.d\n+++ b/libphobos/libdruntime/core/thread/types.d\n@@ -42,12 +42,21 @@ version (GNU)\n else\n enum isStackGrowingDown = false;\n }\n-else\n+else version (LDC)\n+{\n+ // The only LLVM targets as of LLVM 16 with stack growing *upwards* are\n+ // apparently NVPTX and AMDGPU, both without druntime support.\n+ // Note that there's an analogous `version = StackGrowsDown` in\n+ // core.thread.fiber.\n+ enum isStackGrowingDown = true;\n+}\n+else version (DigitalMars)\n {\n- version (X86) enum isStackGrowingDown = true;\n- else version (X86_64) enum isStackGrowingDown = true;\n- else static assert(0, \"It is undefined how the stack grows on this architecture.\");\n+ // All dmd targets grow down\n+ enum isStackGrowingDown = true;\n }\n+else\n+ static assert(0, \"It is undefined how the stack grows on this architecture.\");\n \n package\n {\ndiff --git a/libphobos/libdruntime/etc/valgrind/valgrind.d b/libphobos/libdruntime/etc/valgrind/valgrind.d\nindex 21829fc23bf..3b70e75be0e 100644\n--- a/libphobos/libdruntime/etc/valgrind/valgrind.d\n+++ b/libphobos/libdruntime/etc/valgrind/valgrind.d\n@@ -3,7 +3,7 @@\n /// and compile with `-debug=VALGRIND` to access the declarations below.\n module etc.valgrind.valgrind;\n \n-version (StdDdoc)\n+version (CoreDdoc)\n {\n /// Mark the memory covered by `mem` as unaddressable.\n void makeMemNoAccess (const(void)[] mem) nothrow @nogc;\ndiff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d\nindex bb0c3d3c273..e6c6db6e5ba 100644\n--- a/libphobos/libdruntime/object.d\n+++ b/libphobos/libdruntime/object.d\n@@ -518,11 +518,15 @@ unittest\n // https://issues.dlang.org/show_bug.cgi?id=23291\n @system unittest\n {\n+ import core.atomic : atomicLoad;\n+\n static shared class C { bool opEquals(const(shared(C)) rhs) const shared { return true;}}\n const(C) c = new C();\n const(C)[] a = [c];\n const(C)[] b = [c];\n- assert(a[0] == b[0]);\n+ // Call the shared-aware overload directly to avoid `==` introducing\n+ // additional shared reads during lowering.\n+ assert(atomicLoad(a[0]).opEquals(atomicLoad(b[0])));\n }\n \n private extern(C) void _d_setSameMutex(shared Object ownee, shared Object owner) nothrow;\n@@ -541,6 +545,8 @@ void setSameMutex(shared Object ownee, shared Object owner)\n \n @system unittest\n {\n+ import core.atomic : atomicLoad;\n+\n shared Object obj1 = new Object;\n synchronized class C\n {\n@@ -552,7 +558,7 @@ void setSameMutex(shared Object ownee, shared Object owner)\n assert(obj1.__monitor != obj2.__monitor);\n assert(obj1.__monitor is null);\n \n- setSameMutex(obj1, obj2);\n+ setSameMutex(atomicLoad(obj1), atomicLoad(obj2));\n assert(obj1.__monitor == obj2.__monitor);\n assert(obj1.__monitor !is null);\n }\n@@ -2986,16 +2992,30 @@ alias AssociativeArray(Key, Value) = Value[Key];\n * aa = The associative array.\n */\n void clear(Value, Key)(Value[Key] aa) @trusted\n+if (!is(Value == shared))\n {\n _aaClear(aa);\n }\n \n /** ditto */\n void clear(Value, Key)(Value[Key]* aa) @trusted\n+if (!is(Value == shared))\n {\n (*aa).clear();\n }\n \n+/** ditto */\n+void clear(Value, Key)(shared(Value)[Key] aa)\n+{\n+ return (cast(Value[Key])aa).clear();\n+}\n+\n+/** ditto */\n+void clear(Value, Key)(shared(Value)[Key]* aa)\n+{\n+ (cast(Value[Key])*aa).clear();\n+}\n+\n ///\n @safe unittest\n {\n@@ -3066,11 +3086,23 @@ Value[Key] rehash(T : shared Value[Key], Value, Key)(T* aa)\n */\n auto dup(T : V[K], K, V)(T aa)\n {\n+ import core.internal.traits : substInout, Unconst;\n+\n // Bug10720 - check whether V is copyable\n- static assert(is(typeof({ V v = aa[K.init]; })),\n- \"cannot call \" ~ T.stringof ~ \".dup because \" ~ V.stringof ~ \" is not copyable\");\n+ static if (is(typeof({ Unconst!V v = aa[K.init]; })))\n+ alias Vret = Unconst!V;\n+ else static if (is(typeof({ V v = aa[K.init]; })))\n+ alias Vret = V;\n+ else\n+ static assert(false, \"cannot call \" ~ T.stringof ~ \".dup because \" ~ V.stringof ~ \" is not copyable\");\n+ alias Kret = typeof([K.init][0]); // strip const if possible by copy\n+\n+ alias K1 = substInout!K;\n+ alias V1 = substInout!Vret;\n \n- return _aaDup(aa);\n+ auto naa = _aaDup((() @trusted => cast(V1[K1])aa)());\n+ auto maa = ((inout T) @trusted => cast(Vret[Kret])naa)(aa);\n+ return maa;\n }\n \n /** ditto */\ndiff --git a/libphobos/libdruntime/rt/critical_.d b/libphobos/libdruntime/rt/critical_.d\nindex 36552a3ce1a..8513c67037b 100644\n--- a/libphobos/libdruntime/rt/critical_.d\n+++ b/libphobos/libdruntime/rt/critical_.d\n@@ -21,14 +21,14 @@ import rt.monitor_, core.atomic;\n extern (C) void _d_critical_init() @nogc nothrow\n {\n initMutex(cast(Mutex*)&gcs.mtx);\n- head = &gcs;\n+ atomicStore(head, &gcs);\n }\n \n extern (C) void _d_critical_term() @nogc nothrow\n {\n // This function is only ever called by the runtime shutdown code\n // and therefore is single threaded so the following cast is fine.\n- auto h = cast()head;\n+ auto h = cast(D_CRITICAL_SECTION*) atomicLoad(head);\n for (auto p = h; p; p = p.next)\n destroyMutex(cast(Mutex*)&p.mtx);\n }\n@@ -81,8 +81,8 @@ void ensureMutex(shared(D_CRITICAL_SECTION)* cs)\n if (atomicLoad!(MemoryOrder.raw)(cs.next) is null)\n {\n initMutex(cast(Mutex*)&cs.mtx);\n- auto ohead = head;\n- head = cs;\n+ auto ohead = atomicLoad(head);\n+ atomicStore(head, cs);\n atomicStore!(MemoryOrder.rel)(cs.next, ohead);\n }\n unlockMutex(cast(Mutex*)&gcs.mtx);\ndiff --git a/libphobos/libdruntime/rt/dmain2.d b/libphobos/libdruntime/rt/dmain2.d\nindex 0f7c8161527..ce1e03bbf34 100644\n--- a/libphobos/libdruntime/rt/dmain2.d\n+++ b/libphobos/libdruntime/rt/dmain2.d\n@@ -44,6 +44,9 @@ else version (Posix)\n import core.stdc.string : strlen;\n }\n \n+version (DigitalMars) version (AArch64)\n+ version = UseMalloc; // cuz alloca() is not implemented yet\n+\n // not sure why we can't define this in one place, but this is to keep this\n // module from importing core.runtime.\n struct UnitTestResult\n@@ -279,14 +282,30 @@ extern (C) int _d_run_main(int argc, char** argv, MainFunc mainFunc)\n // assert(wargc == argc); /* argc can be broken by Unicode arguments */\n \n // Allocate args[] on the stack - use wargc\n- char[][] args = (cast(char[]*) alloca(wargc * (char[]).sizeof))[0 .. wargc];\n+ version (UseMalloc)\n+ {\n+ char[][] args = (cast(char[]*) malloc(wargc * (char[]).sizeof))[0 .. wargc];\n+ if (wargc)\n+ assert(args.ptr);\n+ scope (exit) free(args.ptr);\n+ }\n+ else\n+ char[][] args = (cast(char[]*) alloca(wargc * (char[]).sizeof))[0 .. wargc];\n \n // This is required because WideCharToMultiByte requires int as input.\n assert(wCommandLineLength <= cast(size_t) int.max, \"Wide char command line length must not exceed int.max\");\n \n immutable size_t totalArgsLength = WideCharToMultiByte(CP_UTF8, 0, wCommandLine, cast(int)wCommandLineLength, null, 0, null, null);\n {\n- char* totalArgsBuff = cast(char*) alloca(totalArgsLength);\n+ version (UseMalloc)\n+ {\n+ char* totalArgsBuff = cast(char*) malloc(totalArgsLength);\n+ if (totalArgsLength)\n+ assert(totalArgsBuff);\n+ scope (exit) free(totalArgsBuff);\n+ }\n+ else\n+ char* totalArgsBuff = cast(char*) alloca(totalArgsLength);\n size_t j = 0;\n foreach (i; 0 .. wargc)\n {\n@@ -308,7 +327,15 @@ extern (C) int _d_run_main(int argc, char** argv, MainFunc mainFunc)\n else version (Posix)\n {\n // Allocate args[] on the stack\n- char[][] args = (cast(char[]*) alloca(argc * (char[]).sizeof))[0 .. argc];\n+ version (UseMalloc)\n+ {\n+ char[][] args = (cast(char[]*) malloc(argc * (char[]).sizeof))[0 .. argc];\n+ if (argc)\n+ assert(args.ptr);\n+ scope (exit) free(args.ptr);\n+ }\n+ else\n+ char[][] args = (cast(char[]*) alloca(argc * (char[]).sizeof))[0 .. argc];\n \n size_t totalArgsLength = 0;\n foreach (i, ref arg; args)\n@@ -434,7 +461,17 @@ private extern (C) int _d_run_main2(char[][] args, size_t totalArgsLength, MainF\n */\n {\n _d_args = cast(string[]) args;\n- auto buff = cast(char[]*) alloca(args.length * (char[]).sizeof + totalArgsLength);\n+\n+ auto length = args.length * (char[]).sizeof + totalArgsLength;\n+ version (UseMalloc)\n+ {\n+ auto buff = cast(char[]*) malloc(length);\n+ if (length)\n+ assert(buff);\n+ //scope (exit) buff;\n+ }\n+ else\n+ auto buff = cast(char[]*) alloca(length);\n \n char[][] argsCopy = buff[0 .. args.length];\n auto argBuff = cast(char*) (buff + args.length);\n@@ -515,9 +552,9 @@ private extern (C) int _d_run_main2(char[][] args, size_t totalArgsLength, MainF\n if (utResult.summarize)\n {\n if (utResult.passed == 0)\n- .fprintf(.stderr, \"No unittests run\\n\");\n+ .fprintf(cast().stderr, \"No unittests run\\n\");\n else\n- .fprintf(.stderr, \"%d modules passed unittests\\n\",\n+ .fprintf(cast().stderr, \"%d modules passed unittests\\n\",\n cast(int)utResult.passed);\n }\n if (utResult.runMain)\n@@ -528,7 +565,7 @@ private extern (C) int _d_run_main2(char[][] args, size_t totalArgsLength, MainF\n else\n {\n if (utResult.summarize)\n- .fprintf(.stderr, \"%d/%d modules FAILED unittests\\n\",\n+ .fprintf(cast().stderr, \"%d/%d modules FAILED unittests\\n\",\n cast(int)(utResult.executed - utResult.passed),\n cast(int)utResult.executed);\n result = EXIT_FAILURE;\n@@ -549,9 +586,9 @@ private extern (C) int _d_run_main2(char[][] args, size_t totalArgsLength, MainF\n tryExec(&runAll);\n \n // Issue 10344: flush stdout and return nonzero on failure\n- if (.fflush(.stdout) != 0)\n+ if (.fflush(cast().stdout) != 0)\n {\n- .fprintf(.stderr, \"Failed to flush stdout: %s\\n\", .strerror(.errno));\n+ .fprintf(cast().stderr, \"Failed to flush stdout: %s\\n\", .strerror(.errno));\n if (result == 0)\n {\n result = EXIT_FAILURE;\n@@ -628,7 +665,7 @@ extern (C) void _d_print_throwable(Throwable t)\n \n // ensure the exception is shown at the beginning of the line, while also\n // checking whether stderr is a valid file\n- int written = fprintf(stderr, \"\\n\");\n+ int written = fprintf(cast()stderr, \"\\n\");\n if (written <= 0)\n {\n WSink buf;\n@@ -654,7 +691,7 @@ extern (C) void _d_print_throwable(Throwable t)\n }\n return;\n }\n- auto hStdErr = windowsHandle(fileno(stderr));\n+ auto hStdErr = windowsHandle(fileno(cast()stderr));\n CONSOLE_SCREEN_BUFFER_INFO sbi = void;\n const isConsole = GetConsoleScreenBufferInfo(hStdErr, &sbi) != 0;\n if (isConsole)\n@@ -682,7 +719,7 @@ extern (C) void _d_print_throwable(Throwable t)\n \n void sink(in char[] buf) scope nothrow\n {\n- fwrite(buf.ptr, char.sizeof, buf.length, stderr);\n+ fwrite(buf.ptr, char.sizeof, buf.length, cast()stderr);\n }\n formatThrowable(t, &sink);\n }\ndiff --git a/libphobos/libdruntime/rt/minfo.d b/libphobos/libdruntime/rt/minfo.d\nindex 6f096744127..a70aabbeb64 100644\n--- a/libphobos/libdruntime/rt/minfo.d\n+++ b/libphobos/libdruntime/rt/minfo.d\n@@ -183,7 +183,7 @@ struct ModuleGroup\n {\n case \"deprecate\":\n // Option deprecated in 2.101, remove in 2.111\n- fprintf(stderr, \"`--DRT-oncycle=deprecate` is no longer supported, using `abort` instead\\n\");\n+ fprintf(cast()stderr, \"`--DRT-oncycle=deprecate` is no longer supported, using `abort` instead\\n\");\n break;\n case \"abort\":\n onCycle = abort;\n@@ -375,7 +375,7 @@ struct ModuleGroup\n case print:\n // print the message\n buildCycleMessage(idx, midx, (string x) {\n- fprintf(stderr, \"%.*s\", cast(int) x.length, x.ptr);\n+ fprintf(cast()stderr, \"%.*s\", cast(int) x.length, x.ptr);\n });\n // continue on as if this is correct.\n break;\n@@ -520,7 +520,7 @@ struct ModuleGroup\n !doSort(MItlsctor | MItlsdtor, _tlsctors))\n {\n // print a warning\n- fprintf(stderr, \"Deprecation 16211 warning:\\n\"\n+ fprintf(cast()stderr, \"Deprecation 16211 warning:\\n\"\n ~ \"A cycle has been detected in your program that was undetected prior to DMD\\n\"\n ~ \"2.072. This program will continue, but will not operate when using DMD 2.074\\n\"\n ~ \"to compile. Use runtime option --DRT-oncycle=print to see the cycle details.\\n\");\ndiff --git a/libphobos/libdruntime/rt/monitor_.d b/libphobos/libdruntime/rt/monitor_.d\nindex 1d4ed2ea8fc..b63707ee959 100644\n--- a/libphobos/libdruntime/rt/monitor_.d\n+++ b/libphobos/libdruntime/rt/monitor_.d\n@@ -36,14 +36,14 @@ else\n // may not be safe or desirable. Thus, devt is only valid if impl is\n // null.\n \n-extern (C) void _d_setSameMutex(shared Object ownee, shared Object owner) nothrow\n+extern (C) void _d_setSameMutex(shared Object ownee, shared Object owner) @trusted nothrow\n in\n {\n assert(ownee.__monitor is null);\n }\n do\n {\n- auto m = ensureMonitor(cast(Object) owner);\n+ auto m = ensureMonitor(cast(Object) cast(void*) owner);\n if (m.impl is null)\n {\n atomicOp!\"+=\"(m.refs, size_t(1));\n@@ -238,19 +238,19 @@ private:\n \n __gshared Mutex gmtx;\n \n-@property ref shared(Monitor*) monitor(return scope Object h) pure nothrow @nogc\n+shared(Monitor*)* monitorPtr(return scope Object h) pure nothrow @nogc @trusted\n {\n- return *cast(shared Monitor**)&h.__monitor;\n+ return cast(shared(Monitor*)*) &h.__monitor;\n }\n \n shared(Monitor)* getMonitor(Object h) pure @nogc\n {\n- return atomicLoad!(MemoryOrder.acq)(h.monitor);\n+ return atomicLoad!(MemoryOrder.acq)(*monitorPtr(h));\n }\n \n void setMonitor(Object h, shared(Monitor)* m) pure @nogc\n {\n- atomicStore!(MemoryOrder.rel)(h.monitor, m);\n+ atomicStore!(MemoryOrder.rel)(*monitorPtr(h), m);\n }\n \n shared(Monitor)* ensureMonitor(Object h)\ndiff --git a/libphobos/libdruntime/rt/profilegc.d b/libphobos/libdruntime/rt/profilegc.d\nindex e7d4f03e53a..dd12995f422 100644\n--- a/libphobos/libdruntime/rt/profilegc.d\n+++ b/libphobos/libdruntime/rt/profilegc.d\n@@ -151,7 +151,7 @@ shared static ~this()\n {\n qsort(counts.ptr, counts.length, Result.sizeof, &Result.qsort_cmp);\n \n- FILE* fp = logfilename == \"\\0\" ? stdout : fopen((logfilename).ptr, \"w\");\n+ FILE* fp = logfilename == \"\\0\" ? cast()stdout : fopen((logfilename).ptr, \"w\");\n if (fp)\n {\n fprintf(fp, \"bytes allocated, allocations, type, function, file:line\\n\");\n@@ -167,7 +167,7 @@ shared static ~this()\n else\n {\n const err = errno;\n- fprintf(stderr, \"cannot write profilegc log file '%.*s' (errno=%d)\",\n+ fprintf(cast()stderr, \"cannot write profilegc log file '%.*s' (errno=%d)\",\n cast(int) logfilename.length,\n logfilename.ptr,\n cast(int) err);\ndiff --git a/libphobos/libdruntime/rt/sections.d b/libphobos/libdruntime/rt/sections.d\nindex ce5a6682dfe..98a09a94eb0 100644\n--- a/libphobos/libdruntime/rt/sections.d\n+++ b/libphobos/libdruntime/rt/sections.d\n@@ -45,9 +45,11 @@ else version (Solaris)\n else version (Darwin)\n {\n version (X86_64)\n- public import rt.sections_osx_x86_64;\n+ public import rt.sections_osx_64;\n else version (X86)\n public import rt.sections_osx_x86;\n+ else version (AArch64)\n+ public import rt.sections_osx_64;\n else\n static assert(0, \"unimplemented\");\n }\ndiff --git a/libphobos/src/MERGE b/libphobos/src/MERGE\nindex d5e9b11a68c..25a0815d39d 100644\n--- a/libphobos/src/MERGE\n+++ b/libphobos/src/MERGE\n@@ -1,4 +1,4 @@\n-0c5c9e98443de1bb75c7c3560f58baa6ce725209\n+0c519ae39c00ebbb69b0e3a2e6e02710d7730915\n \n The first line of this file holds the git revision number of the last\n merge done from the dlang/phobos repository.\ndiff --git a/libphobos/src/Makefile.am b/libphobos/src/Makefile.am\nindex 13c35c22ddd..de74f5c3a27 100644\n--- a/libphobos/src/Makefile.am\n+++ b/libphobos/src/Makefile.am\n@@ -146,14 +146,15 @@ PHOBOS_DSOURCES = etc/c/curl.d etc/c/odbc/odbc32.d etc/c/odbc/odbc64.d \\\n \tstd/internal/unicode_comp.d std/internal/unicode_decomp.d \\\n \tstd/internal/unicode_grapheme.d std/internal/unicode_norm.d \\\n \tstd/internal/unicode_tables.d std/internal/windows/advapi32.d \\\n-\tstd/json.d std/logger/core.d std/logger/filelogger.d \\\n-\tstd/logger/multilogger.d std/logger/nulllogger.d std/logger/package.d \\\n-\tstd/math/algebraic.d std/math/constants.d std/math/exponential.d \\\n-\tstd/math/hardware.d std/math/operations.d std/math/package.d \\\n-\tstd/math/remainder.d std/math/rounding.d std/math/traits.d \\\n-\tstd/math/trigonometry.d std/mathspecial.d std/meta.d std/mmfile.d \\\n-\tstd/net/curl.d std/net/isemail.d std/numeric.d std/outbuffer.d \\\n-\tstd/package.d std/parallelism.d std/path.d std/process.d std/random.d \\\n+\tstd/internal/windows/bcrypt.d std/json.d std/logger/core.d \\\n+\tstd/logger/filelogger.d std/logger/multilogger.d \\\n+\tstd/logger/nulllogger.d std/logger/package.d std/math/algebraic.d \\\n+\tstd/math/constants.d std/math/exponential.d std/math/hardware.d \\\n+\tstd/math/operations.d std/math/package.d std/math/remainder.d \\\n+\tstd/math/rounding.d std/math/traits.d std/math/trigonometry.d \\\n+\tstd/mathspecial.d std/meta.d std/mmfile.d std/net/curl.d \\\n+\tstd/net/isemail.d std/numeric.d std/outbuffer.d std/package.d \\\n+\tstd/parallelism.d std/path.d std/process.d std/random.d \\\n \tstd/range/interfaces.d std/range/package.d std/range/primitives.d \\\n \tstd/regex/internal/backtracking.d std/regex/internal/generator.d \\\n \tstd/regex/internal/ir.d std/regex/internal/kickstart.d \\\ndiff --git a/libphobos/src/Makefile.in b/libphobos/src/Makefile.in\nindex 960ca98cc1d..c7dd55aac7b 100644\n--- a/libphobos/src/Makefile.in\n+++ b/libphobos/src/Makefile.in\n@@ -255,6 +255,7 @@ am__dirstamp = $(am__leading_dot)dirstamp\n @ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/internal/unicode_norm.lo \\\n @ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/internal/unicode_tables.lo \\\n @ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/internal/windows/advapi32.lo \\\n+@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/internal/windows/bcrypt.lo \\\n @ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/json.lo std/logger/core.lo \\\n @ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/logger/filelogger.lo \\\n @ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/logger/multilogger.lo \\\n@@ -619,14 +620,15 @@ libgphobos_la_LINK = $(LIBTOOL) --tag=D $(libgphobos_la_LIBTOOLFLAGS) \\\n @ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/internal/unicode_comp.d std/internal/unicode_decomp.d \\\n @ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/internal/unicode_grapheme.d std/internal/unicode_norm.d \\\n @ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/internal/unicode_tables.d std/internal/windows/advapi32.d \\\n-@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/json.d std/logger/core.d std/logger/filelogger.d \\\n-@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/logger/multilogger.d std/logger/nulllogger.d std/logger/package.d \\\n-@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/math/algebraic.d std/math/constants.d std/math/exponential.d \\\n-@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/math/hardware.d std/math/operations.d std/math/package.d \\\n-@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/math/remainder.d std/math/rounding.d std/math/traits.d \\\n-@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/math/trigonometry.d std/mathspecial.d std/meta.d std/mmfile.d \\\n-@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/net/curl.d std/net/isemail.d std/numeric.d std/outbuffer.d \\\n-@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/package.d std/parallelism.d std/path.d std/process.d std/random.d \\\n+@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/internal/windows/bcrypt.d std/json.d std/logger/core.d \\\n+@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/logger/filelogger.d std/logger/multilogger.d \\\n+@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/logger/nulllogger.d std/logger/package.d std/math/algebraic.d \\\n+@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/math/constants.d std/math/exponential.d std/math/hardware.d \\\n+@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/math/operations.d std/math/package.d std/math/remainder.d \\\n+@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/math/rounding.d std/math/traits.d std/math/trigonometry.d \\\n+@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/mathspecial.d std/meta.d std/mmfile.d std/net/curl.d \\\n+@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/net/isemail.d std/numeric.d std/outbuffer.d std/package.d \\\n+@ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/parallelism.d std/path.d std/process.d std/random.d \\\n @ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/range/interfaces.d std/range/package.d std/range/primitives.d \\\n @ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/regex/internal/backtracking.d std/regex/internal/generator.d \\\n @ENABLE_LIBDRUNTIME_ONLY_FALSE@\tstd/regex/internal/ir.d std/regex/internal/kickstart.d \\\n@@ -909,6 +911,7 @@ std/internal/windows/$(am__dirstamp):\n \t@: > std/internal/windows/$(am__dirstamp)\n std/internal/windows/advapi32.lo: \\\n \tstd/internal/windows/$(am__dirstamp)\n+std/internal/windows/bcrypt.lo: std/internal/windows/$(am__dirstamp)\n std/json.lo: std/$(am__dirstamp)\n std/logger/$(am__dirstamp):\n \t@$(MKDIR_P) std/logger\ndiff --git a/libphobos/src/index.dd b/libphobos/src/index.dd\nindex ed8e46ba8bb..2483bcbb8e1 100644\n--- a/libphobos/src/index.dd\n+++ b/libphobos/src/index.dd\n@@ -3,10 +3,13 @@ Ddoc\n $(P Phobos is the standard runtime library that comes with the D language\n compiler.)\n \n-$(P Generally, the `std` namespace is used for the main modules in the\n-Phobos standard library. The `etc` namespace is used for external C/C++\n-library bindings. The `core` namespace is used for low-level D runtime\n-functions.)\n+- The `std` namespace is used for the main modules in the\n+ Phobos standard library.\n+- The $(LREF etc) namespace is used for external C/C++ library bindings.\n+- The `core` namespace is mainly used for low-level D runtime functions.\n+- $(RELATIVE_LINK2 stdc, `core.stdc`) wraps the C standard library.\n+- $(RELATIVE_LINK2 stdcpp, `core.stdcpp`) wraps some of the C++ standard library.\n+- `core.sys` wraps OS headers.\n \n $(P The following table is a quick reference guide for which Phobos modules to\n use for a given category of functionality. Note that some modules may appear in\n@@ -130,7 +133,7 @@ $(BOOKTABLE ,\n $(TD Defines built-in exception types and low-level\n language hooks required by the compiler.)\n )\n- $(LEADINGROW External library bindings)\n+ $(LEADINGROW $(LNAME2 etc, External library bindings))\n $(TR\n $(TDNW $(MREF etc,c,curl))\n $(TD Interface to libcurl C library.)\n@@ -156,6 +159,14 @@ $(BOOKTABLE ,\n $(TDNW $(MREF etc,c,zlib))\n $(TD Interface to zlib C library.)\n )\n+ $(TR\n+ $(TDNW $(MREF etc,linux,memoryerror))\n+ $(TD Handle memory errors on Linux.)\n+ )\n+ $(TR\n+ $(TDNW $(MREF etc,valgrind,valgrind))\n+ $(TD Interface to $(LINK2 https://valgrind.org, Valgrind) for dynamic analysis.)\n+ )\n $(LEADINGROW I/O & File system)\n $(TR\n $(TDNW $(MREF std,file))\n@@ -194,12 +205,31 @@ $(BOOKTABLE ,\n $(MREF core,stdc,wctype)$(BR)\n )\n $(TD\n- D bindings for standard C headers.$(BR)$(BR)\n+ D bindings for $(LNAME2 stdc, standard C) headers.$(BR)$(BR)\n These are mostly undocumented, as documentation\n for the functions these declarations provide\n bindings to can be found on external resources.\n )\n )\n+ $(TR\n+ $(TDNW\n+ $(MREF core,stdcpp,allocator)$(BR)\n+ $(MREF core,stdcpp,array)$(BR)\n+ $(MREF core,stdcpp,exception)$(BR)\n+ $(MREF core,stdcpp,memory)$(BR)\n+ $(MREF core,stdcpp,new_)$(BR)\n+ $(MREF core,stdcpp,string)$(BR)\n+ $(MREF core,stdcpp,string_view)$(BR)\n+ $(MREF core,stdcpp,type_traits)$(BR)\n+ $(MREF core,stdcpp,typeinfo)$(BR)\n+ $(MREF core,stdcpp,utility)$(BR)\n+ $(MREF core,stdcpp,vector)$(BR)\n+ $(MREF core,stdcpp,xutility)$(BR)\n+ )\n+ $(TD\n+ Partial D bindings for $(LNAME2 stdcpp, standard C++) headers.$(BR)$(BR)\n+ )\n+ )\n $(LEADINGROW Memory management)\n $(TR\n $(TDNW $(MREF core,memory))\n@@ -307,8 +337,10 @@ $(BOOKTABLE ,\n $(TD An arbitrary-precision integer type.)\n )\n $(TR\n- $(TDNW $(MREF std,int128))\n- $(TDNW $(MREF core,int128))\n+ $(TDNW\n+ $(MREF std,int128)$(BR)\n+ $(MREF core,int128)\n+ )\n $(TD 128 bit-precision integer type.)\n )\n $(TR\ndiff --git a/libphobos/src/std/algorithm/setops.d b/libphobos/src/std/algorithm/setops.d\nindex 10873a7cabc..f373fe74e70 100644\n--- a/libphobos/src/std/algorithm/setops.d\n+++ b/libphobos/src/std/algorithm/setops.d\n@@ -365,6 +365,8 @@ if (ranges.length >= 2 &&\n // For infinite ranges or non-forward ranges, we fall back to the old\n // implementation which expands an exponential number of templates.\n import std.typecons : tuple;\n+ import std.meta : allSatisfy;\n+ import std.range.primitives : hasLength;\n \n static struct Result\n {\n@@ -413,13 +415,37 @@ if (ranges.length >= 2 &&\n }\n return copy;\n }\n+ static if (allSatisfy!(hasLength, RR))\n+ {\n+ @property size_t length()\n+ {\n+ size_t result = 1;\n+ foreach (r; ranges)\n+ {\n+ result *= r.length;\n+ }\n+ return result;\n+ }\n+ }\n }\n static assert(isForwardRange!Result, Result.stringof ~ \" must be a forward\"\n ~ \" range\");\n \n return Result(ranges);\n }\n+@safe unittest\n+{\n+ import std.algorithm.setops : cartesianProduct;\n+\n+ // 2 ranges\n+ assert(cartesianProduct([1, 2], [3, 4]).length == 4);\n \n+ // different sizes\n+ assert(cartesianProduct([1, 2, 3], [4, 5]).length == 6);\n+\n+ // 3 ranges\n+ assert(cartesianProduct([1, 2], [3, 4], [5]).length == 4);\n+}\n // cartesian product of empty ranges should be empty\n // https://issues.dlang.org/show_bug.cgi?id=10693\n @safe unittest\ndiff --git a/libphobos/src/std/array.d b/libphobos/src/std/array.d\nindex e85eadb4090..dfcffdd8882 100644\n--- a/libphobos/src/std/array.d\n+++ b/libphobos/src/std/array.d\n@@ -1083,14 +1083,6 @@ if (isDynamicArray!T && allSatisfy!(isIntegral, I))\n }\n }\n \n-// from rt/lifetime.d\n-private extern(C) void[] _d_newarrayU(const TypeInfo ti, size_t length) pure nothrow;\n-\n-// from rt/tracegc.d\n-version (D_ProfileGC)\n-private extern (C) void[] _d_newarrayUTrace(string file, size_t line,\n- string funcname, const scope TypeInfo ti, size_t length) pure nothrow;\n-\n private auto arrayAllocImpl(bool minimallyInitialized, T, I...)(I sizes) nothrow\n {\n static assert(I.length <= nDimensions!T,\n@@ -1141,18 +1133,19 @@ private auto arrayAllocImpl(bool minimallyInitialized, T, I...)(I sizes) nothrow\n which will inform the GC how to destroy the items in the block\n when it gets collected.\n \n- _d_newarrayU returns a void[], but with the length set according\n- to E.sizeof.\n+ _d_newarrayU returns a E[], with the length set according to\n+ to the size parameter.\n +/\n+ enum isShared = is (E == shared);\n version (D_ProfileGC)\n {\n // FIXME: file, line, function should be propagated from the\n // caller, not here.\n- *(cast(void[]*)&ret) = _d_newarrayUTrace(__FILE__, __LINE__,\n- __FUNCTION__, typeid(E[]), size);\n+ ret = _d_newarrayUTrace!E(size, isShared,\n+ __FILE__, __LINE__, __FUNCTION__);\n }\n else\n- *(cast(void[]*)&ret) = _d_newarrayU(typeid(E[]), size);\n+ ret = _d_newarrayU!E(size, isShared);\n static if (minimallyInitialized && hasIndirections!E)\n // _d_newarrayU would have asserted if the multiplication below\n // had overflowed, so we don't have to check it again.\n@@ -3581,11 +3574,18 @@ See_Also: $(LREF appender)\n struct Appender(A)\n if (isDynamicArray!A)\n {\n- import std.format.spec : FormatSpec;\n+ import core.memory : GC;\n \n private alias T = ElementEncodingType!A;\n \n- InPlaceAppender!A* impl;\n+ private struct Data\n+ {\n+ size_t capacity;\n+ Unqual!T[] arr;\n+ bool tryExtendBlock = false;\n+ }\n+\n+ private Data* _data;\n \n /**\n * Constructs an `Appender` with a given array. Note that this does not copy the\n@@ -3593,17 +3593,27 @@ if (isDynamicArray!A)\n * it will be used by the appender. After initializing an appender on an array,\n * appending to the original array will reallocate.\n */\n- this(A arr) @safe\n+ this(A arr) @trusted\n {\n- impl = new InPlaceAppender!A(arr);\n- }\n+ // initialize to a given array.\n+ _data = new Data;\n+ _data.arr = cast(Unqual!T[]) arr; //trusted\n \n- private void ensureInit() @safe\n- {\n- if (impl is null)\n+ if (__ctfe)\n+ return;\n+\n+ // We want to use up as much of the block the array is in as possible.\n+ // if we consume all the block that we can, then array appending is\n+ // safe WRT built-in append, and we can use the entire block.\n+ // We only do this for mutable types that can be extended.\n+ static if (isMutable!T && is(typeof(arr.length = size_t.max)))\n {\n- impl = new InPlaceAppender!A;\n+ immutable cap = arr.capacity; //trusted\n+ // Replace with \"GC.setAttr( Not Appendable )\" once pure (and fixed)\n+ if (cap > arr.length)\n+ arr.length = cap;\n }\n+ _data.capacity = arr.length;\n }\n \n /**\n@@ -3616,10 +3626,14 @@ if (isDynamicArray!A)\n */\n void reserve(size_t newCapacity)\n {\n- if (newCapacity != 0)\n+ if (_data)\n+ {\n+ if (newCapacity > _data.capacity)\n+ ensureAddable(newCapacity - _data.arr.length);\n+ }\n+ else\n {\n- ensureInit();\n- impl.reserve(newCapacity);\n+ ensureAddable(newCapacity);\n }\n }\n \n@@ -3630,11 +3644,11 @@ if (isDynamicArray!A)\n */\n @property size_t capacity() const\n {\n- return impl ? impl.capacity : 0;\n+ return _data ? _data.capacity : 0;\n }\n \n /// Returns: The number of elements appended.\n- @property size_t length() const => (impl is null) ? 0 : impl.length;\n+ @property size_t length() const => _data ? _data.arr.length : 0;\n \n /**\n * Use opSlice() from now on.\n@@ -3642,219 +3656,29 @@ if (isDynamicArray!A)\n */\n @property inout(T)[] data() inout\n {\n- return opSlice();\n+ return this[];\n }\n \n /**\n * Returns: The managed array.\n */\n- @property inout(T)[] opSlice() inout @safe\n- {\n- return impl ? impl.opSlice() : null;\n- }\n-\n- /**\n- * Appends `item` to the managed array. Performs encoding for\n- * `char` types if `A` is a differently typed `char` array.\n- *\n- * Params:\n- * item = the single item to append\n- */\n- void put(U)(U item)\n- if (InPlaceAppender!A.canPutItem!U)\n- {\n- ensureInit();\n- impl.put(item);\n- }\n-\n- // Const fixing hack.\n- void put(Range)(Range items)\n- if (InPlaceAppender!A.canPutConstRange!Range)\n- {\n- if (!items.empty)\n- {\n- ensureInit();\n- impl.put(items);\n- }\n- }\n-\n- /**\n- * Appends an entire range to the managed array. Performs encoding for\n- * `char` elements if `A` is a differently typed `char` array.\n- *\n- * Params:\n- * items = the range of items to append\n- */\n- void put(Range)(Range items)\n- if (InPlaceAppender!A.canPutRange!Range)\n- {\n- if (!items.empty)\n- {\n- ensureInit();\n- impl.put(items);\n- }\n- }\n-\n- /**\n- * Appends to the managed array.\n- *\n- * See_Also: $(LREF Appender.put)\n- */\n- alias opOpAssign(string op : \"~\") = put;\n-\n-\n- // only allow overwriting data on non-immutable and non-const data\n- static if (isMutable!T)\n- {\n- /**\n- * Clears the managed array. This allows the elements of the array to be reused\n- * for appending.\n- *\n- * Note: clear is disabled for immutable or const element types, due to the\n- * possibility that `Appender` might overwrite immutable data.\n- */\n- void clear() @safe pure nothrow\n- {\n- if (impl)\n- {\n- impl.clear();\n- }\n- }\n-\n- /**\n- * Shrinks the managed array to the given length.\n- *\n- * Throws: `Exception` if newlength is greater than the current array length.\n- * Note: shrinkTo is disabled for immutable or const element types.\n- */\n- void shrinkTo(size_t newlength) @safe pure\n- {\n- import std.exception : enforce;\n- if (impl)\n- {\n- impl.shrinkTo(newlength);\n- }\n- else\n- {\n- enforce(newlength == 0, \"Attempting to shrink empty Appender with non-zero newlength\");\n- }\n- }\n- }\n-\n- /**\n- * Gives a string in the form of `Appender!(A)(data)`.\n- *\n- * Params:\n- * w = A `char` accepting\n- * $(REF_ALTTEXT output range, isOutputRange, std, range, primitives).\n- * fmt = A $(REF FormatSpec, std, format) which controls how the array\n- * is formatted.\n- * Returns:\n- * A `string` if `writer` is not set; `void` otherwise.\n- */\n- string toString()() const\n- {\n- return InPlaceAppender!A.toStringImpl(Unqual!(typeof(this)).stringof, impl ? impl.data : null);\n- }\n-\n- /// ditto\n- template toString(Writer)\n- if (isOutputRange!(Writer, char))\n- {\n- void toString(scope ref Writer w, scope const ref FormatSpec!char fmt) const\n- {\n- InPlaceAppender!A.toStringImpl(Unqual!(typeof(this)).stringof, impl ? impl.data : null, w, fmt);\n- }\n- }\n-}\n-\n-///\n-@safe pure nothrow unittest\n-{\n- auto app = appender!string();\n- string b = \"abcdefg\";\n- foreach (char c; b)\n- app.put(c);\n- assert(app[] == \"abcdefg\");\n-\n- int[] a = [ 1, 2 ];\n- auto app2 = appender(a);\n- app2.put(3);\n- app2.put([ 4, 5, 6 ]);\n- assert(app2[] == [ 1, 2, 3, 4, 5, 6 ]);\n-}\n-\n-package(std) struct InPlaceAppender(A)\n-if (isDynamicArray!A)\n-{\n- import core.memory : GC;\n- import std.format.spec : FormatSpec;\n-\n- private alias T = ElementEncodingType!A;\n-\n- private\n- {\n- size_t _capacity;\n- Unqual!T[] arr;\n- bool tryExtendBlock = false;\n- }\n-\n- @disable this(ref InPlaceAppender);\n-\n- this(A arrIn) @trusted\n- {\n- arr = cast(Unqual!T[]) arrIn; //trusted\n-\n- if (__ctfe)\n- return;\n-\n- // We want to use up as much of the block the array is in as possible.\n- // if we consume all the block that we can, then array appending is\n- // safe WRT built-in append, and we can use the entire block.\n- // We only do this for mutable types that can be extended.\n- static if (isMutable!T && is(typeof(arrIn.length = size_t.max)))\n- {\n- immutable cap = arrIn.capacity; //trusted\n- // Replace with \"GC.setAttr( Not Appendable )\" once pure (and fixed)\n- if (cap > arrIn.length)\n- arrIn.length = cap;\n- }\n- _capacity = arrIn.length;\n- }\n-\n- void reserve(size_t newCapacity)\n- {\n- if (newCapacity > _capacity)\n- ensureAddable(newCapacity - arr.length);\n- }\n-\n- @property size_t capacity() const\n- {\n- return _capacity;\n- }\n-\n- @property size_t length() const => arr.length;\n-\n- @property inout(T)[] data() inout\n- {\n- return this[];\n- }\n-\n- inout(T)[] opSlice() inout @trusted\n+ @property inout(T)[] opSlice() inout @trusted\n {\n /* @trusted operation:\n * casting Unqual!T[] to inout(T)[]\n */\n- return cast(typeof(return)) arr;\n+ return cast(typeof(return))(_data ? _data.arr : null);\n }\n \n // ensure we can add nelems elements, resizing as necessary\n private void ensureAddable(size_t nelems)\n {\n- immutable len = arr.length;\n+ if (!_data)\n+ _data = new Data;\n+ immutable len = _data.arr.length;\n immutable reqlen = len + nelems;\n \n- if (_capacity >= reqlen)\n+ if (_data.capacity >= reqlen)\n return;\n \n // need to increase capacity\n@@ -3862,17 +3686,17 @@ if (isDynamicArray!A)\n {\n static if (__traits(compiles, new Unqual!T[1]))\n {\n- arr.length = reqlen;\n+ _data.arr.length = reqlen;\n }\n else\n {\n // avoid restriction of @disable this()\n- arr = arr[0 .. _capacity];\n- foreach (i; _capacity .. reqlen)\n- arr ~= Unqual!T.init;\n+ _data.arr = _data.arr[0 .. _data.capacity];\n+ foreach (i; _data.capacity .. reqlen)\n+ _data.arr ~= Unqual!T.init;\n }\n- arr = arr[0 .. len];\n- _capacity = reqlen;\n+ _data.arr = _data.arr[0 .. len];\n+ _data.capacity = reqlen;\n }\n else\n {\n@@ -3880,11 +3704,11 @@ if (isDynamicArray!A)\n // Time to reallocate.\n // We need to almost duplicate what's in druntime, except we\n // have better access to the capacity field.\n- auto newlen = appenderNewCapacity!(T.sizeof)(_capacity, reqlen);\n+ auto newlen = appenderNewCapacity!(T.sizeof)(_data.capacity, reqlen);\n // first, try extending the current block\n- if (tryExtendBlock)\n+ if (_data.tryExtendBlock)\n {\n- immutable u = (() @trusted => GC.extend(arr.ptr, nelems * T.sizeof, (newlen - len) * T.sizeof))();\n+ immutable u = (() @trusted => GC.extend(_data.arr.ptr, nelems * T.sizeof, (newlen - len) * T.sizeof))();\n if (u)\n {\n // extend worked, update the capacity\n@@ -3893,10 +3717,11 @@ if (isDynamicArray!A)\n // at large unused blocks.\n static if (hasIndirections!T)\n {\n- immutable addedSize = u - (_capacity * T.sizeof);\n- () @trusted { memset(arr.ptr + _capacity, 0, addedSize); }();\n+ immutable addedSize = u - (_data.capacity * T.sizeof);\n+ () @trusted { memset(_data.arr.ptr + _data.capacity, 0, addedSize); }();\n }\n- _capacity = u / T.sizeof;\n+\n+ _data.capacity = u / T.sizeof;\n return;\n }\n }\n@@ -3910,11 +3735,11 @@ if (isDynamicArray!A)\n ~ \"available pointer range\");\n \n auto bi = (() @trusted => GC.qalloc(nbytes, blockAttribute!T))();\n- _capacity = bi.size / T.sizeof;\n- import core.stdc.string : memcpy;\n+ _data.capacity = bi.size / T.sizeof;\n if (len)\n- () @trusted { memcpy(bi.base, arr.ptr, len * T.sizeof); }();\n- arr = (() @trusted => (cast(Unqual!T*) bi.base)[0 .. len])();\n+ () @trusted { memcpy(bi.base, _data.arr.ptr, len * T.sizeof); }();\n+\n+ _data.arr = (() @trusted => (cast(Unqual!T*) bi.base)[0 .. len])();\n \n // we requested new bytes that are not in the existing\n // data. If T has pointers, then this new data could point at stale\n@@ -3925,7 +3750,7 @@ if (isDynamicArray!A)\n memset(bi.base + (len * T.sizeof), 0, (newlen - len) * T.sizeof);\n }();\n \n- tryExtendBlock = true;\n+ _data.tryExtendBlock = true;\n // leave the old data, for safety reasons\n }\n }\n@@ -3941,13 +3766,13 @@ if (isDynamicArray!A)\n enum bool canPutConstRange =\n isInputRange!(Unqual!Range) &&\n !isInputRange!Range &&\n- is(typeof(InPlaceAppender.init.put(Range.init.front)));\n+ is(typeof(Appender.init.put(Range.init.front)));\n }\n private template canPutRange(Range)\n {\n enum bool canPutRange =\n isInputRange!Range &&\n- is(typeof(InPlaceAppender.init.put(Range.init.front)));\n+ is(typeof(Appender.init.put(Range.init.front)));\n }\n \n /**\n@@ -3976,13 +3801,13 @@ if (isDynamicArray!A)\n import core.lifetime : emplace;\n \n ensureAddable(1);\n- immutable len = arr.length;\n+ immutable len = _data.arr.length;\n \n- auto bigData = (() @trusted => arr.ptr[0 .. len + 1])();\n+ auto bigData = (() @trusted => _data.arr.ptr[0 .. len + 1])();\n auto itemUnqual = (() @trusted => & cast() item)();\n emplace(&bigData[len], *itemUnqual);\n //We do this at the end, in case of exceptions\n- arr = bigData;\n+ _data.arr = bigData;\n }\n }\n \n@@ -4026,16 +3851,16 @@ if (isDynamicArray!A)\n auto bigDataFun(size_t extra)\n {\n ensureAddable(extra);\n- return (() @trusted => arr.ptr[0 .. arr.length + extra])();\n+ return (() @trusted => _data.arr.ptr[0 .. _data.arr.length + extra])();\n }\n auto bigData = bigDataFun(items.length);\n \n- immutable len = arr.length;\n+ immutable len = _data.arr.length;\n immutable newlen = bigData.length;\n \n alias UT = Unqual!T;\n \n- static if (is(typeof(arr[] = items[])) &&\n+ static if (is(typeof(_data.arr[] = items[])) &&\n !hasElaborateAssign!UT && isAssignable!(UT, ElementEncodingType!Range))\n {\n bigData[len .. newlen] = items[];\n@@ -4051,7 +3876,7 @@ if (isDynamicArray!A)\n }\n \n //We do this at the end, in case of exceptions\n- arr = bigData;\n+ _data.arr = bigData;\n }\n else static if (isSomeChar!T && isSomeChar!(ElementType!Range) &&\n !is(immutable T == immutable ElementType!Range))\n@@ -4094,7 +3919,10 @@ if (isDynamicArray!A)\n */\n void clear() @trusted pure nothrow\n {\n- arr = arr.ptr[0 .. 0];\n+ if (_data)\n+ {\n+ _data.arr = _data.arr.ptr[0 .. 0];\n+ }\n }\n \n /**\n@@ -4106,8 +3934,13 @@ if (isDynamicArray!A)\n void shrinkTo(size_t newlength) @trusted pure\n {\n import std.exception : enforce;\n- enforce(newlength <= arr.length, \"Attempting to shrink Appender with newlength > length\");\n- arr = arr.ptr[0 .. newlength];\n+ if (_data)\n+ {\n+ enforce(newlength <= _data.arr.length, \"Attempting to shrink Appender with newlength > length\");\n+ _data.arr = _data.arr.ptr[0 .. newlength];\n+ }\n+ else\n+ enforce(newlength == 0, \"Attempting to shrink empty Appender with non-zero newlength\");\n }\n }\n \n@@ -4122,18 +3955,13 @@ if (isDynamicArray!A)\n * Returns:\n * A `string` if `writer` is not set; `void` otherwise.\n */\n- auto toString() const\n- {\n- return toStringImpl(Unqual!(typeof(this)).stringof, data);\n- }\n-\n- static auto toStringImpl(string typeName, const T[] arr)\n+ string toString()() const\n {\n import std.format.spec : singleSpec;\n \n- InPlaceAppender!string app;\n+ auto app = appender!string();\n auto spec = singleSpec(\"%s\");\n- immutable len = arr.length;\n+ immutable len = _data ? _data.arr.length : 0;\n // different reserve lengths because each element in a\n // non-string-like array uses two extra characters for `, `.\n static if (isSomeString!A)\n@@ -4146,25 +3974,25 @@ if (isDynamicArray!A)\n // length, as it assumes each element is only one char\n app.reserve((len * 3) + 25);\n }\n- toStringImpl(typeName, arr, app, spec);\n+ toString(app, spec);\n return app.data;\n }\n \n- void toString(Writer)(scope ref Writer w, scope const ref FormatSpec!char fmt) const\n- if (isOutputRange!(Writer, char))\n- {\n- toStringImpl(Unqual!(typeof(this)).stringof, data, w, fmt);\n- }\n+ import std.format.spec : FormatSpec;\n \n- static void toStringImpl(Writer)(string typeName, const T[] data, scope ref Writer w,\n- scope const ref FormatSpec!char fmt)\n+ /// ditto\n+ template toString(Writer)\n+ if (isOutputRange!(Writer, char))\n {\n- import std.format.write : formatValue;\n- import std.range.primitives : put;\n- put(w, typeName);\n- put(w, '(');\n- formatValue(w, data, fmt);\n- put(w, ')');\n+ void toString(ref Writer w, scope const ref FormatSpec!char fmt) const\n+ {\n+ import std.format.write : formatValue;\n+ import std.range.primitives : put;\n+ put(w, Unqual!(typeof(this)).stringof);\n+ put(w, '(');\n+ formatValue(w, data, fmt);\n+ put(w, ')');\n+ }\n }\n }\n \n@@ -4207,16 +4035,6 @@ if (isDynamicArray!A)\n assert(app3[] == \"Appender!(int[])(0001, 0002, 0003)\");\n }\n \n-@safe pure unittest\n-{\n- auto app = appender!(char[])();\n- app ~= \"hello\";\n- app.clear;\n- // not a promise, just nothing else exercises capacity\n- // and this is the expected sort of behaviour\n- assert(app.capacity >= 5);\n-}\n-\n // https://issues.dlang.org/show_bug.cgi?id=17251\n @safe pure nothrow unittest\n {\n@@ -4347,6 +4165,25 @@ if (isDynamicArray!A)\n writeln(\"WARNING: test of Appender zeroing did not occur\");\n }\n \n+// https://github.com/dlang/phobos/issues/10747\n+@system unittest\n+{\n+ static struct A10747\n+ {\n+ this(ref A10747 rhs) { }\n+ }\n+\n+ static class R10747\n+ {\n+ A10747 front() { return A10747.init; }\n+ void popFront() { }\n+ bool empty = true;\n+ }\n+\n+ auto a = new R10747();\n+ a.array();\n+}\n+\n //Calculates an efficient growth scheme based on the old capacity\n //of data, and the minimum requested capacity.\n //arg curLen: The current length\n@@ -4479,24 +4316,6 @@ unittest\n assert(app2.capacity >= 5);\n }\n \n-/++\n- Convenience function that returns a $(LREF InPlaceAppender) instance,\n- optionally initialized with `array`.\n- +/\n-package(std) InPlaceAppender!A inPlaceAppender(A)()\n-if (isDynamicArray!A)\n-{\n- return InPlaceAppender!A(null);\n-}\n-/// ditto\n-package(std) InPlaceAppender!(E[]) inPlaceAppender(A : E[], E)(auto ref A array)\n-{\n- static assert(!isStaticArray!A || __traits(isRef, array),\n- \"Cannot create InPlaceAppender from an rvalue static array\");\n-\n- return InPlaceAppender!(E[])(array);\n-}\n-\n /++\n Convenience function that returns an $(LREF Appender) instance,\n optionally initialized with `array`.\ndiff --git a/libphobos/src/std/container/rbtree.d b/libphobos/src/std/container/rbtree.d\nindex b5c8fa3352c..5b3964f659f 100644\n--- a/libphobos/src/std/container/rbtree.d\n+++ b/libphobos/src/std/container/rbtree.d\n@@ -88,6 +88,14 @@ struct RBNode(V)\n private Node _right;\n private Node _parent;\n \n+ private this(Node left, Node right, Node parent, V value)\n+ {\n+ this._left = left;\n+ this._right = right;\n+ this._parent = parent;\n+ this.value = value;\n+ }\n+\n /**\n * The value held by this node\n */\n@@ -747,7 +755,7 @@ private struct RBRange(N)\n * inserted after all existing duplicate elements.\n */\n final class RedBlackTree(T, alias less = \"a < b\", bool allowDuplicates = false)\n-if (is(typeof((ref const T a) => binaryFun!less(a, a))))\n+if (isSuitablePredicate!(less, T))\n {\n import std.meta : allSatisfy;\n import std.range : Take;\n@@ -1995,7 +2003,9 @@ assert(equal(rbt[], [5]));\n }\n \n import std.range.primitives : isInputRange, ElementType;\n-import std.traits : isArray, isSomeString;\n+import std.traits : isArray, isSomeString, lvalueOf;\n+\n+private enum isSuitablePredicate(alias less, T) = is(typeof(binaryFun!less(lvalueOf!(const T), lvalueOf!(const T))));\n \n /++\n Convenience function for creating a `RedBlackTree!E` from a list of\n@@ -2020,14 +2030,14 @@ auto redBlackTree(bool allowDuplicates, E)(E[] elems...)\n \n /++ Ditto +/\n auto redBlackTree(alias less, E)(E[] elems...)\n-if (is(typeof(binaryFun!less(E.init, E.init))))\n+if (isSuitablePredicate!(less, E))\n {\n return new RedBlackTree!(E, less)(elems);\n }\n \n /++ Ditto +/\n auto redBlackTree(alias less, bool allowDuplicates, E)(E[] elems...)\n-if (is(typeof(binaryFun!less(E.init, E.init))))\n+if (isSuitablePredicate!(less, E))\n {\n //We shouldn't need to instantiate less here, but for some reason,\n //dmd can't handle it if we don't (even though the template which\n@@ -2051,7 +2061,7 @@ if (isInputRange!Stuff && !isArray!(Stuff))\n \n /++ Ditto +/\n auto redBlackTree(alias less, Stuff)(Stuff range)\n-if ( is(typeof(binaryFun!less((ElementType!Stuff).init, (ElementType!Stuff).init)))\n+if (isSuitablePredicate!(less, ElementType!Stuff)\n && isInputRange!Stuff && !isArray!(Stuff))\n {\n return new RedBlackTree!(ElementType!Stuff, less)(range);\n@@ -2059,7 +2069,7 @@ if ( is(typeof(binaryFun!less((ElementType!Stuff).init, (ElementType!Stuff).init\n \n /++ Ditto +/\n auto redBlackTree(alias less, bool allowDuplicates, Stuff)(Stuff range)\n-if ( is(typeof(binaryFun!less((ElementType!Stuff).init, (ElementType!Stuff).init)))\n+if (isSuitablePredicate!(less, ElementType!Stuff)\n && isInputRange!Stuff && !isArray!(Stuff))\n {\n //We shouldn't need to instantiate less here, but for some reason,\n@@ -2276,3 +2286,17 @@ if ( is(typeof(binaryFun!less((ElementType!Stuff).init, (ElementType!Stuff).init\n \n cast(void) new RedBlackTree!(S, (ref const S a, ref const S b) => a.value > b.value);\n }\n+\n+// struct with move constructor\n+@safe unittest\n+{\n+ static struct S {\n+ int i;\n+ this(S s) { this.i = s.i; }\n+ this(int i) { this.i = i; }\n+ int opCmp(ref const S other) const @safe nothrow { return i - other.i; }\n+ }\n+\n+ auto tree = new RedBlackTree!(S, \"a.i < b.i\", false);\n+ tree.insert(S(0));\n+}\ndiff --git a/libphobos/src/std/experimental/allocator/common.d b/libphobos/src/std/experimental/allocator/common.d\nindex 245157258c1..b06fb627d71 100644\n--- a/libphobos/src/std/experimental/allocator/common.d\n+++ b/libphobos/src/std/experimental/allocator/common.d\n@@ -63,8 +63,7 @@ unittest\n class C2 { char c; }\n static assert(stateSize!C2 == 4 * size_t.sizeof);\n static class C3 { char c; }\n- // Uncomment test after dmd issue closed https://github.com/dlang/dmd/issues/21065\n- //static assert(stateSize!C3 == 3 * size_t.sizeof);\n+ static assert(stateSize!C3 == 2 * size_t.sizeof + char.sizeof);\n }\n \n /**\ndiff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d\nindex a5b53270f95..0d4959b226f 100644\n--- a/libphobos/src/std/file.d\n+++ b/libphobos/src/std/file.d\n@@ -969,6 +969,19 @@ if (isConvertibleToString!RF || isConvertibleToString!RT)\n assert(t2.readText == \"2\");\n }\n \n+\n+@safe unittest\n+{\n+ import std.file;\n+ import std.exception : assertThrown;\n+\n+ string f = null;\n+\n+ // Check if FileException is thrown for invalid rename\n+ assertThrown!FileException(rename(\"\", f));\n+ assertThrown!FileException(rename(f, \"\"));\n+}\n+\n private void renameImpl(scope const(char)[] f, scope const(char)[] t,\n scope const(FSChar)* fromz, scope const(FSChar)* toz) @trusted\n {\n@@ -983,10 +996,10 @@ private void renameImpl(scope const(char)[] f, scope const(char)[] t,\n import std.conv : to, text;\n \n if (!f)\n- f = to!(typeof(f))(fromz[0 .. wcslen(fromz)]);\n+ f = fromz ? to!(typeof(f))(fromz[0 .. wcslen(fromz)]) : \"(null)\";\n \n if (!t)\n- t = to!(typeof(t))(toz[0 .. wcslen(toz)]);\n+ t = toz ? to!(typeof(t))(toz[0 .. wcslen(toz)]) : \"(null)\";\n \n enforce(false,\n new FileException(\ndiff --git a/libphobos/src/std/format/write.d b/libphobos/src/std/format/write.d\nindex d704c14f5fa..68a96d48625 100644\n--- a/libphobos/src/std/format/write.d\n+++ b/libphobos/src/std/format/write.d\n@@ -534,6 +534,8 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[]\n \n // Are we already done with formats? Then just dump each parameter in turn\n uint currentArg = 0;\n+ bool lastWasConsumeAll;\n+\n while (spec.writeUpToNextSpec(w))\n {\n if (currentArg == Args.length && !spec.indexStart)\n@@ -649,7 +651,10 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[]\n }\n default:\n if (spec.indexEnd == spec.indexEnd.max)\n+ {\n+ lastWasConsumeAll = true;\n break;\n+ }\n else if (spec.indexEnd == spec.indexStart)\n throw new FormatException(\n text(\"Positional specifier %\", spec.indexStart, '$', spec.spec,\n@@ -660,7 +665,8 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[]\n \" index exceeds \", Args.length));\n }\n }\n- return currentArg;\n+\n+ return lastWasConsumeAll ? Args.length : currentArg;\n }\n \n ///\n@@ -1212,7 +1218,8 @@ if (isSomeString!(typeof(fmt)))\n import std.array : appender;\n auto w = appender!(char[])();\n \n- formattedWrite(w, \"%1:$d\", 1, 2, 3);\n+ uint count = formattedWrite(w, \"%1:$d\", 1, 2, 3);\n+ assert(count == 3);\n assert(w.data == \"123\");\n }\n \ndiff --git a/libphobos/src/std/internal/math/errorfunction.d b/libphobos/src/std/internal/math/errorfunction.d\nindex 8894ffb92ea..bb132ce8dea 100644\n--- a/libphobos/src/std/internal/math/errorfunction.d\n+++ b/libphobos/src/std/internal/math/errorfunction.d\n@@ -984,6 +984,9 @@ Journal of Statistical Software <b>11</b>, (July 2004).\n */\n real normalDistributionImpl(real a)\n {\n+ if (a is -real.infinity) return 0.0L;\n+ if (a is real.infinity) return 1.0L;\n+\n real x = a * SQRT1_2;\n real z = fabs(x);\n \n@@ -1005,6 +1008,8 @@ real normalDistributionImpl(real a)\n {\n assert(fabs(normalDistributionImpl(1L) - (0.841344746068543L)) < 0.0000000000000005L);\n assert(isIdentical(normalDistributionImpl(NaN(0x325)), NaN(0x325)));\n+assert(normalDistributionImpl(-real.infinity) == 0.0L);\n+assert(normalDistributionImpl(real.infinity) == 1.0L);\n }\n \n /*\ndiff --git a/libphobos/src/std/internal/math/gammafunction.d b/libphobos/src/std/internal/math/gammafunction.d\nindex d4e51f5653a..1b05ebd48a2 100644\n--- a/libphobos/src/std/internal/math/gammafunction.d\n+++ b/libphobos/src/std/internal/math/gammafunction.d\n@@ -168,12 +168,19 @@ real gammaStirling(real x)\n }\n \n /*\n- * Helper function: Incomplete gamma function computed by Temme's expansion.\n+ * Regularized incomplete gamma function computed by Temme's expansion. If\n+ * `compl` is true, it computes the complement of the regularized incomplete\n+ * gamma function instead.\n+ *\n+ * For a derivation of the algorithm, see A \"Set of Algorithms for the\n+ * Incomplete Gamma Functions\", N. M. Temme, Probability in the Engineering and\n+ * Informational Sciences, Volume 8, Issue 2, April 1994, pp. 291-307, DOI:\n+ * https://doi.org/10.1017/S0269964800003417.\n *\n * This is a port of igamma_temme_large from Boost.\n *\n */\n-real igammaTemmeLarge(real a, real x)\n+real igammaTemmeLarge(real a, real x, bool compl)\n {\n static immutable real[][13] coef = [\n [ -0.333333333333333333333L, 0.0833333333333333333333L,\n@@ -250,13 +257,12 @@ real igammaTemmeLarge(real a, real x)\n \n // avoid nans when one of the arguments is inf:\n if (x == real.infinity && a != real.infinity)\n- return 0;\n-\n+ return compl ? 0.0L : 1.0L;\n if (x != real.infinity && a == real.infinity)\n- return 1;\n+ return compl ? 1.0L : 0.0L;\n \n real sigma = (x - a) / a;\n- real phi = sigma - log(sigma + 1);\n+ real phi = sigma - log1p(sigma);\n \n real y = a * phi;\n real z = sqrt(2 * phi);\n@@ -267,14 +273,40 @@ real igammaTemmeLarge(real a, real x)\n foreach (i; 0 .. coef.length)\n workspace[i] = poly(z, coef[i]);\n \n- real result = poly(1 / a, workspace);\n- result *= exp(-y) / sqrt(2 * PI * a);\n- if (x < a)\n- result = -result;\n+ // Rβ(π) = [exp(-aπΒ²/2)/β(2πa)]Sβ(π)\n+ const r = exp(-y)/sqrt(2.0L*PI*a) * poly(1.0L/a, workspace);\n+\n+ if (compl)\n+ {\n+ // Q(a,x) = erfc(+πβ(a/2))/2 + Rβ(π)\n+ return erfc(+sgn(sigma)*sqrt(y))/2.0L + r;\n+ }\n+ else\n+ {\n+ // P(a,x) = erfc(-πβ(a/2))/2 - Rβ(π)\n+ return erfc(-sgn(sigma)*sqrt(y))/2.0L - r;\n+ }\n+}\n+\n+@safe unittest\n+{\n+ // Values were generated using scipy, which restricts values to double precision.\n+ assert(feqrel(igammaTemmeLarge(25.0, 25.0, true), 0.47339_84685_56349_37L) >= double.mant_dig);\n+ assert(feqrel(igammaTemmeLarge(25.0, 26.0, true), 0.39592_65699_99828_5L) >= double.mant_dig);\n+ assert(feqrel(igammaTemmeLarge(26.0, 25.0, true), 0.55292_14200_24414_8L) >= double.mant_dig);\n+\n+ assert(feqrel(igammaTemmeLarge(25.0, 25.0, false), 0.52660_15314_43650_6L) >= double.mant_dig);\n+ assert(feqrel(igammaTemmeLarge(26.0, 25.0, false), 0.44707_85799_75585_2L) >= double.mant_dig);\n+\n+ assert(\n+ feqrel(igammaTemmeLarge(30.0L,31.0L,true), 1.0L-igammaTemmeLarge(30.0L,31.0L,false))\n+ >= real.mant_dig - 1);\n \n- result += erfc(sqrt(y)) / 2;\n+ assert(feqrel(igammaTemmeLarge(1e9, 1.1e9, false), 1.0) >= double.mant_dig);\n+ assert(feqrel(igammaTemmeLarge(1.1e9, 1e9, false), 0.0) >= double.mant_dig);\n \n- return result;\n+ assert(\n+ feqrel(igammaTemmeLarge(1e6, 1e6 + 1.0, true), 0.49946_80772_57932_46L) >= double.mant_dig);\n }\n \n } // private\n@@ -692,35 +724,34 @@ private pragma(inline, true) real betaLarge(in real x, in real y)\n */\n real beta(in real x, in real y)\n {\n+ // When one of the input parameters is NaN, return the NaN with the larger\n+ // payload. This mimics the behavior of the + operator.\n+ if (isNaN(x) || isNaN(y)) return cmp(abs(x), abs(y)) >= 0 ? x : y;\n+\n real res;\n \n+ // Take advantage of the symmetry B(x,y) = B(y,x)\n+ // smaller β€ larger\n+ const larger = cmp(x, y) >= 0 ? x : y;\n+ const smaller = cmp(x, y) >= 0 ? y : x;\n+ const sum = larger + smaller;\n+\n // the main algorithm\n- if (x > MAXGAMMA || y > MAXGAMMA || x + y > MAXGAMMA)\n+ if (larger > MAXGAMMA || sum > MAXGAMMA)\n {\n- res = betaLarge(x, y);\n+ res = betaLarge(smaller, larger);\n }\n else\n {\n- res = gamma(x) * gamma(y) / gamma(x+y);\n+ res = gamma(smaller) * gamma(larger) / gamma(sum);\n \n // There are several regions near the asymptotes and inflection lines\n // gamma cannot be computed but logGamma can.\n- if (!isFinite(res)) res = betaLarge(x,y);\n+ if (!isFinite(res)) res = betaLarge(smaller, larger);\n }\n \n if (!isNaN(res)) return res;\n \n- // For valid NaN results, always return the response from the main algorithm\n- // in order to preserve signaling NaNs.\n-\n- if (isNaN(x) || isNaN(y)) return res;\n-\n- // Take advantage of the symmetry B(x,y) = B(y,x)\n- // smaller β€ larger\n- const larger = cmp(x, y) >= 0 ? x : y;\n- const smaller = cmp(x, y) >= 0 ? y : x;\n- const sum = larger + smaller;\n-\n // in a quadrant of the (smaller,larger) cartesian plane\n const inQ1 = cmp(smaller, +0.0L) >= 0;\n const inQ2 = !inQ1 && cmp(larger, +0.0L) >= 0;\n@@ -749,28 +780,35 @@ real beta(in real x, in real y)\n \n if (inQ1)\n {\n- // 4) On the larger axis and larger is finite, B = +β\n- // 5) On the larger axis, and larger is +β, B = nan\n+ // 4) At origin, B = +β\n+ if (nextToOrigin) return +real.infinity;\n+\n+ // 5) On the larger axis and larger is finite, B = +β\n+ // 6) On the larger axis, and larger is +β, B = nan\n if (nextToSmallAxis) return larger < +real.infinity ? +real.infinity : res;\n \n- // 6) Not on the larger axis, and the larger is +β, B = +0\n+ // 7) Not on the larger axis, and the larger is +β, B = +0\n if (!nextToSmallAxis && larger == +real.infinity) return +0.;\n+\n+ // not on larger axis, but near origin, case 4, or larger is very large,\n+ // case 7\n+ if (!nextToSmallAxis) return larger < 1 ? +real.infinity : +0.;\n }\n \n if (inQ2)\n {\n- // 7) Next to the origin, B = nan\n- // 8) Next to the larger axis, but not the origin, B = -β\n+ // 8) Next to the origin, B = nan\n+ // 9) Next to the larger axis, but not the origin, B = -β\n if (nextToSmallAxis) return nextToOrigin ? res : -real.infinity;\n \n- // 9) Larger is +β, B = β * sgn(Ξ(smaller))\n+ // 10) Larger is +β, B = β * sgn(Ξ(smaller))\n if (larger == +real.infinity) return copysign(real.infinity, sgnGamma(smaller));\n \n- // 10) next to smaller axis, but not on an asymptote or at the origin,\n+ // 11) next to smaller axis, but not on an asymptote or at the origin,\n // B = +β.\n if (nextToLargeAxis && !onSmallAsymptote && !nextToOrigin) return +real.infinity;\n \n- // larger very large, case 9\n+ // larger very large, case 10\n // larger so large that ln|Ξ(larger)| and ln|Ξ(sum)| are too large to\n // represent as reals. Thus they each are approximated as β, and the\n // main algorithm resolves to NaN instead of Β±β.\n@@ -779,10 +817,10 @@ real beta(in real x, in real y)\n \n if (inQ3)\n {\n- // 11) next to the smaller axis, but not on an asymptote, B = -β.\n+ // 12) next to the smaller axis, but not on an asymptote, B = -β.\n if (nextToLargeAxis && !onSmallAsymptote) return -real.infinity;\n \n- // near origin, case 11\n+ // near origin, case 12\n // -larger and -sum are so small that ln|Ξ(larger)| and ln|Ξ(sum)| are\n // too large to be represented as reals. Thus they each are approximated\n // as β, and the main algorithm resolves to NaN instead of -β.\n@@ -795,14 +833,20 @@ real beta(in real x, in real y)\n \n @safe unittest\n {\n+ // Test NaN payload propagation\n+ assert(isIdentical(beta(NaN(0x1), 7), NaN(0x1)));\n assert(isIdentical(beta(2, NaN(0xABC)), NaN(0xABC)));\n+ assert(isIdentical(beta(NaN(0x1), NaN(0x2)), NaN(0x2)));\n \n // Test symmetry\n+ assert(beta(1, 2) is beta(2, 1));\n \n // Test first quadrant\n+ assert(beta(+0., +0.) == +real.infinity);\n assert(beta(+0., 1) == +real.infinity);\n- assert(beta(nextUp(+0.0L), nextUp(+0.0L) > 0), \"B(Ξ΅β,Ξ΅π) > 0\");\n+ assert(isClose(beta(nextUp(+0.0L), nextUp(+0.0L)), real.infinity), \"B(Ξ΅β,Ξ΅π) β² +β\");\n assert(!isNaN(beta(nextUp(+0.0L), 1)), \"B(Ξ΅,y), y > 0 should exist\");\n+ assert(isClose(beta(nextUp(+0.0L), nextDown(real.infinity)), +0.0L), \"B(Ξ΅,y) β³ 0, y large\");\n assert(beta(1, +real.infinity) is +0.0L, \"lim{yβ+β} B(x,y) = 0βΊ, x > 0\");\n assert(beta(1, 1) > 0);\n assert(beta(0.6*MAXGAMMA, 0.5*MAXGAMMA) > 0);\n@@ -1817,6 +1861,9 @@ do\n if ( (x > 1.0L) && (x > a ) )\n return 1.0L - gammaIncompleteCompl(a,x);\n \n+ if (a > 25.0L && abs(x-a) < 0.2L*a)\n+ return igammaTemmeLarge(a, x, false);\n+\n real ax = a * log(x) - x - logGamma(a);\n /+\n if ( ax < MINLOGL ) return 0; // underflow\n@@ -1872,7 +1919,7 @@ do\n // log(x)-x = NaN when x = real.infinity\n const real MAXLOGL = 1.1356523406294143949492E4L;\n if (x > MAXLOGL)\n- return igammaTemmeLarge(a, x);\n+ return igammaTemmeLarge(a, x, true);\n \n real ax = a * log(x) - x - logGamma(a);\n //const real MINLOGL = -1.1355137111933024058873E4L;\n@@ -1945,12 +1992,29 @@ do\n real gammaIncompleteComplInv(real a, real p)\n in\n {\n- assert(p >= 0 && p <= 1);\n- assert(a>0);\n+ if (!any!isNaN(only(a, p)))\n+ {\n+ assert(signbit(a) == 0);\n+ assert(p >= 0.0L && p <= 1.0L);\n+ }\n }\n do\n {\n- if (p == 0) return real.infinity;\n+ // pass p first, so that if p and a are NaNs with the same payload but with\n+ // opposite signs, return p.\n+ if (any!isNaN(only(a, p))) return largestNaNPayload(p, a);\n+\n+ // domain violations\n+ if (signbit(a) == 1) return real.nan;\n+ if (p < 0.0L || p > 1.0L) return real.nan;\n+\n+ // places where not invertible\n+ if (a is +0.0L && p < 1.0L) return real.nan;\n+ if (a is real.infinity && p > 0.0L) return real.nan;\n+\n+ // edge cases for p\n+ if (p == 0.0L) return real.infinity;\n+ if (p == 1.0L) return 0.0L;\n \n real y0 = p;\n const real MAXLOGL = 1.1356523406294143949492E4L;\n@@ -2093,6 +2157,9 @@ assert(gammaIncomplete(1, 0)==0);\n assert(gammaIncompleteCompl(1, 0)==1);\n assert(gammaIncomplete(4545, real.infinity)==1);\n \n+// Value was generated using scipy, which restricts values to double precision.\n+assert(feqrel(gammaIncomplete(1e20, 1e20), 0.50000_00000_13298) >= double.mant_dig);\n+\n // Values from Excel's (1-GammaDist(x, alpha, 1, TRUE))\n \n assert(fabs(1.0L-gammaIncompleteCompl(0.5L, 2) - 0.954499729507309L) < 0.00000005L);\n@@ -2107,6 +2174,13 @@ static if (real.mant_dig >= 64) // incl. 80-bit reals\n assert(fabs(gammaIncompleteCompl(100000, 100001) - 0.49831792109L) < 0.000000000005L);\n else\n assert(fabs(gammaIncompleteCompl(100000, 100001) - 0.49831792109L) < 0.00000005L);\n+\n+assert(gammaIncompleteComplInv(NaN(0x5UL), -NaN(0x5UL)) is -NaN(0x5UL));\n+assert(!isNaN(gammaIncompleteComplInv(+0.0L, 1.0L)));\n+assert(isNaN(gammaIncompleteComplInv(+0.0L, nextDown(1.0L))));\n+assert(!isNaN(gammaIncompleteComplInv(real.infinity, -0.0L)));\n+assert(isNaN(gammaIncompleteComplInv(real.infinity, nextUp(+0.0L))));\n+assert(gammaIncompleteComplInv(2.0L, 1.0L) == 0.0L);\n }\n \n \n@@ -2305,12 +2379,14 @@ real logmdigammaInverse(real y)\n immutable maxY = logmdigamma(real.min_normal);\n assert(maxY > 0 && maxY <= real.max);\n \n+ if (isNaN(y)) return y;\n+\n if (y >= maxY)\n {\n //lim x->0 (log(x)-digamma(x))*x == 1\n return 1 / y;\n }\n- if (y < 0)\n+ if (signbit(y) == 1) // y is negative\n {\n return real.nan;\n }\n@@ -2319,13 +2395,10 @@ real logmdigammaInverse(real y)\n //6.3.18\n return 0.5 / y;\n }\n- if (y > 0)\n- {\n- // x/2 <= logmdigamma(1 / x) <= x, x > 0\n- // calls logmdigamma ~6 times\n- return 1 / findRoot((real x) => logmdigamma(1 / x) - y, y, 2*y);\n- }\n- return y; //NaN\n+\n+ // x/2 <= logmdigamma(1 / x) <= x, x > 0\n+ // calls logmdigamma ~6 times\n+ return 1 / findRoot((real x) => logmdigamma(1 / x) - y, y, 2*y);\n }\n \n @safe unittest\n@@ -2348,4 +2421,6 @@ real logmdigammaInverse(real y)\n assert(isClose(logmdigammaInverse(logmdigamma(1)), 1, 1e-15L));\n assert(isClose(logmdigammaInverse(logmdigamma(real.min_normal)), real.min_normal, 1e-15L));\n assert(isClose(logmdigammaInverse(logmdigamma(real.max/2)), real.max/2, 1e-15L));\n+ assert(logmdigammaInverse(NaN(0x1)) is NaN(0x1));\n+ assert(isNaN(logmdigammaInverse(-0.)));\n }\ndiff --git a/libphobos/src/std/internal/windows/bcrypt.d b/libphobos/src/std/internal/windows/bcrypt.d\nnew file mode 100644\nindex 00000000000..239dcd52e66\n--- /dev/null\n+++ b/libphobos/src/std/internal/windows/bcrypt.d\n@@ -0,0 +1,65 @@\n+module std.internal.windows.bcrypt;\n+\n+version (Windows):\n+\n+import core.sys.windows.bcrypt : BCryptGenRandom, BCRYPT_USE_SYSTEM_PREFERRED_RNG;\n+import core.sys.windows.windef : HMODULE, PUCHAR, ULONG;\n+import core.sys.windows.ntdef : NT_SUCCESS;\n+\n+pragma(lib, \"Bcrypt.lib\");\n+\n+package(std) bool bcryptGenRandom(T)(out T result) @trusted\n+{\n+ loadBcrypt();\n+\n+ const gotRandom = ptrBCryptGenRandom(\n+ null,\n+ cast(PUCHAR) &result,\n+ ULONG(T.sizeof),\n+ BCRYPT_USE_SYSTEM_PREFERRED_RNG,\n+ );\n+\n+ return NT_SUCCESS(gotRandom);\n+}\n+\n+private\n+{\n+ HMODULE hBcrypt = null;\n+ typeof(BCryptGenRandom)* ptrBCryptGenRandom;\n+}\n+\n+private void loadBcrypt() @nogc nothrow\n+{\n+ import core.sys.windows.winbase : GetProcAddress, LoadLibraryA;\n+\n+ if (!hBcrypt)\n+ {\n+ hBcrypt = LoadLibraryA(\"Bcrypt.dll\");\n+ if (!hBcrypt)\n+ assert(false, `LoadLibraryA(\"Bcrypt.dll\") failed.`); // `@nogc`\n+\n+ ptrBCryptGenRandom = cast(typeof(ptrBCryptGenRandom)) GetProcAddress(hBcrypt , \"BCryptGenRandom\");\n+ if (!ptrBCryptGenRandom)\n+ assert(false, `GetProcAddress(hBcrypt , \"BCryptGenRandom\") failed.`); // `@nogc`\n+ }\n+}\n+\n+// Will free `Bcrypt.dll`.\n+private void freeBcrypt() @nogc nothrow\n+{\n+ import core.sys.windows.winbase : FreeLibrary;\n+\n+ if (hBcrypt)\n+ {\n+ if (!FreeLibrary(hBcrypt))\n+ assert(false, `FreeLibrary(\"Bcrypt.dll\") failed.`); // `@nogc`\n+\n+ hBcrypt = null;\n+ ptrBCryptGenRandom = null;\n+ }\n+}\n+\n+static ~this()\n+{\n+ freeBcrypt();\n+}\ndiff --git a/libphobos/src/std/logger/core.d b/libphobos/src/std/logger/core.d\nindex 1e879fd6c56..58328eb6e9a 100644\n--- a/libphobos/src/std/logger/core.d\n+++ b/libphobos/src/std/logger/core.d\n@@ -13,6 +13,17 @@ import std.traits;\n \n import std.logger.filelogger;\n \n+/+\n+ Donβt forget to update the documentation of `std.logger` (`package.d`)\n+ when changing this test. This is a copy of example code found in its\n+ doc comment.\n+ +/\n+@system unittest\n+{\n+ assert(globalLogLevel == LogLevel.all);\n+ assert((cast() sharedLog).logLevel == LogLevel.info);\n+}\n+\n /** This functions is used at runtime to determine if a `LogLevel` is\n active. The same previously defined version statements are used to disable\n certain levels. Again the version statements are associated with a compile\ndiff --git a/libphobos/src/std/logger/package.d b/libphobos/src/std/logger/package.d\nindex 5a847491478..568510fec2d 100644\n--- a/libphobos/src/std/logger/package.d\n+++ b/libphobos/src/std/logger/package.d\n@@ -24,6 +24,76 @@ This will print a message to the `stderr` device. The message will contain\n the filename, the line number, the name of the surrounding function, the time\n and the message.\n \n+$(H4 Quickstart)\n+\n+$(B $(RED Pitfall:)) The $(B defaults) of this package are meant to be $(B reasonable for those who do $(I not) use logging).\n+Users who intend to use logging are expected to set it up accordingly.\n+\n+The logging machinery is basically a pipeline.\n+Convenience functions like `log()`, `info()` and `trace()` are on the very top end of it.\n+When one calls `trace()`, it sends a log message with `LogLevel.trace` down the pipes.\n+\n+One of the first checks is for `globalLogLevel`, where any message of a lesser log level is filtered out;\n+the default here is `LogLevel.all` which allows all log messages to be passed down further.\n+\n+Eventually, the logged message is passed into a logger which will perform an output operation.\n+Keep in mind, loggers themselves also have an assigned log level they filter for.\n+\n+On default settings, a log message will eventually reach `sharedLog`;\n+this one is a [FileLogger] writing to `stderr` with a threshold of `LogLevel.info`.\n+This default was chosen because of concerns regarding spamming trace messages to unsuspecting downstream library users.\n+\n+As consequence of this design decision, the `LogLevel` of `FileLogger` needs to be adjusted\n+in order to have `trace()` or `log()` actually print something.\n+\n+-------------\n+import std.logger;\n+\n+void main() @system\n+{\n+ // `globalLogLevel` defaults to `LogLevel.all`.\n+ // `sharedLog.logLevel` defaults to `LogLevel.info`.\n+ assert(globalLogLevel == LogLevel.all);\n+ assert((cast() sharedLog).logLevel == LogLevel.info);\n+\n+ // Log a few messages. These will be printed to `stderr` output.\n+ info(\"Works out of the box.\");\n+ warning(\"Works out of the box.\");\n+ error(\"Works out of the box.\");\n+ critical(\"Works out of the box.\");\n+\n+ // `log()` and `trace()` will not actually print anything as-is.\n+ log(\"Does *not* work out of the box.\");\n+ trace(\"Does *not* work out of the box.\");\n+\n+ // Enable trace logging output.\n+ (cast() sharedLog).logLevel = LogLevel.trace;\n+\n+ // Emit a log message with `LogLevel.trace`.\n+ trace(\"Tracing the World\");\n+\n+ // Set the log level to the most permissive option, i.e. `LogLevel.all`.\n+ (cast() sharedLog).logLevel = LogLevel.all;\n+\n+ // Emit a log message with `LogLevel.all`.\n+ log(\"All aboard!\");\n+\n+ // Logging a fatal message also throws an `Error`, i.e. crashes the program.\n+ fatal(\"C u l8r, alligator!\");\n+}\n+-------------\n+\n+$(H5 Rationale)\n+\n+$(UL\n+ $(LI $(LINK2 https://bugzilla-archive.dlang.org/bugs/22532/, Bugzilla Issue 22532 (archived)))\n+ $(LI $(LINK2 https://github.com/dlang/phobos/pull/8336, GitHub: dlang/phobos Pull request #8336))\n+ $(LI $(LINK2 https://github.com/dlang/phobos/pull/8406, GitHub: dlang/phobos Pull request #8406))\n+ $(LI $(LINK2 https://github.com/dlang/phobos/issues/10858, GitHub: dlang/phobos Issue #10858))\n+)\n+\n+$(H3 Advanced Usage)\n+\n More complex log call can go along the lines like:\n -------------\n log(\"Logging to the sharedLog with its default LogLevel\");\n@@ -35,14 +105,14 @@ errorf(\"Logging %s the sharedLog %s its error LogLevel\", \"to\", \"with\");\n critical(\"Logging to the\",\" sharedLog with its error LogLevel\");\n fatal(\"Logging to the sharedLog with its fatal LogLevel\");\n \n-auto fLogger = new FileLogger(\"NameOfTheLogFile\");\n-fLogger.log(\"Logging to the fileLogger with its default LogLevel\");\n-fLogger.info(\"Logging to the fileLogger with its default LogLevel\");\n-fLogger.warning(5 < 6, \"Logging to the fileLogger with its LogLevel.warning if 5 is less than 6\");\n-fLogger.warningf(5 < 6, \"Logging to the fileLogger with its LogLevel.warning if %s is %s than 6\", 5, \"less\");\n-fLogger.critical(\"Logging to the fileLogger with its info LogLevel\");\n-fLogger.log(LogLevel.trace, 5 < 6, \"Logging to the fileLogger\",\" with its default LogLevel if 5 is less than 6\");\n-fLogger.fatal(\"Logging to the fileLogger with its warning LogLevel\");\n+auto fileLogger = new FileLogger(\"NameOfTheLogFile\");\n+fileLogger.log(\"Logging to the fileLogger with its default LogLevel\");\n+fileLogger.info(\"Logging to the fileLogger with its default LogLevel\");\n+fileLogger.warning(5 < 6, \"Logging to the fileLogger with its LogLevel.warning if 5 is less than 6\");\n+fileLogger.warningf(5 < 6, \"Logging to the fileLogger with its LogLevel.warning if %s is %s than 6\", 5, \"less\");\n+fileLogger.critical(\"Logging to the fileLogger with its info LogLevel\");\n+fileLogger.log(LogLevel.trace, 5 < 6, \"Logging to the fileLogger\",\" with its default LogLevel if 5 is less than 6\");\n+fileLogger.fatal(\"Logging to the fileLogger with its warning LogLevel\");\n -------------\n Additionally, this example shows how a new `FileLogger` is created.\n Individual `Logger` and the global log functions share commonly named\ndiff --git a/libphobos/src/std/math/hardware.d b/libphobos/src/std/math/hardware.d\nindex 3e3d0da0e9d..302f041b1f6 100644\n--- a/libphobos/src/std/math/hardware.d\n+++ b/libphobos/src/std/math/hardware.d\n@@ -63,6 +63,7 @@ else version (RISCV_Any) version = IeeeFlagsSupport;\n else version (MIPS_Any) version = IeeeFlagsSupport;\n else version (LoongArch_Any) version = IeeeFlagsSupport;\n else version (ARM_Any) version = IeeeFlagsSupport;\n+else version (SPARC_Any) version = IeeeFlagsSupport;\n \n // Struct FloatingPointControl is only available if hardware FP units are available.\n version (D_HardFloat)\n@@ -90,7 +91,7 @@ private:\n // The x87 FPU status register is 16 bits.\n // The Pentium SSE2 status register is 32 bits.\n // The ARM and PowerPC FPSCR is a 32-bit register.\n- // The SPARC FSR is a 32bit register (64 bits for SPARC 7 & 8, but high bits are uninteresting).\n+ // The SPARC FSR is a 32-bit register (64 bits for SPARC V9, but high bits are uninteresting).\n // The RISC-V (32 & 64 bit) fcsr is 32-bit register.\n // THe LoongArch fcsr (fcsr0) is a 32-bit register.\n uint flags;\n@@ -112,6 +113,36 @@ private:\n // Don't bother about subnormals, they are not supported on most CPUs.\n // SUBNORMAL_MASK = 0x02;\n }\n+ else version (Solaris)\n+ {\n+ // Solaris <fenv.h> uses hardware-incompatible floating-point status flags.\n+ // Use the <sys/fsr.h> AEXC (Accrued EXCeption) bit field of fsr instead.\n+ version (SPARC_Any)\n+ {\n+ enum : int\n+ {\n+ INEXACT_MASK = 0x020,\n+ UNDERFLOW_MASK = 0x080,\n+ OVERFLOW_MASK = 0x100,\n+ DIVBYZERO_MASK = 0x040,\n+ INVALID_MASK = 0x200,\n+ EXCEPTIONS_MASK = 0x3E0,\n+ }\n+ }\n+ // Use the <sys/fp.h> masks for 80387 control word or SSE/SSE2 MXCSR instead.\n+ else version (X86_Any)\n+ {\n+ enum : int\n+ {\n+ INEXACT_MASK = 0x20,\n+ UNDERFLOW_MASK = 0x10,\n+ OVERFLOW_MASK = 0x08,\n+ DIVBYZERO_MASK = 0x04,\n+ INVALID_MASK = 0x01,\n+ EXCEPTIONS_MASK = 0x3D,\n+ }\n+ }\n+ }\n else\n {\n enum : int\n@@ -648,6 +679,36 @@ nothrow @nogc:\n | roundUp | roundToZero,\n }\n }\n+ else version (Solaris)\n+ {\n+ // Solaris <fenv.h> uses hardware-incompatible floating-point status flags.\n+ // Use the <sys/fsr.h> RD (Rounding Direction) field of fsr instead.\n+ version (SPARC_Any)\n+ {\n+ enum : RoundingMode\n+ {\n+ roundToNearest = 0x00000000,\n+ roundDown = 0xC0000000,\n+ roundUp = 0x80000000,\n+ roundToZero = 0x40000000,\n+ roundingMask = roundToNearest | roundDown\n+ | roundUp | roundToZero,\n+ }\n+ }\n+ // Use the <sys/fp.h> rounding options in control word instead.\n+ else version (X86_Any)\n+ {\n+ enum : RoundingMode\n+ {\n+ roundToNearest = 0x000,\n+ roundDown = 0x400,\n+ roundUp = 0x800,\n+ roundToZero = 0xc00,\n+ roundingMask = roundToNearest | roundDown\n+ | roundUp | roundToZero,\n+ }\n+ }\n+ }\n else\n {\n enum : RoundingMode\n@@ -878,6 +939,8 @@ nothrow @nogc:\n return true;\n else version (SPARC_Any)\n return true;\n+ else version (SPARC_Any)\n+ return true;\n else version (ARM_Any)\n {\n // The hasExceptionTraps_impl function is basically pure,\n@@ -961,7 +1024,7 @@ private:\n }\n else version (SPARC_Any)\n {\n- alias ControlState = ulong;\n+ alias ControlState = uint;\n }\n else version (IBMZ_Any)\n {\ndiff --git a/libphobos/src/std/mathspecial.d b/libphobos/src/std/mathspecial.d\nindex fc33c921191..0646f2c733c 100644\n--- a/libphobos/src/std/mathspecial.d\n+++ b/libphobos/src/std/mathspecial.d\n@@ -187,21 +187,6 @@ pragma(inline, true) real beta(real x, real y)\n @safe unittest\n {\n assert(beta(1, 2) == 0.5);\n- assert(isIdentical(beta(NaN(0xABC), 4), NaN(0xABC)));\n- assert(beta(3, 4) == beta(4, 3));\n- assert(isNaN(beta(-real.infinity, +0.)));\n- assert(isNaN(beta(-1, 2)));\n- assert(beta(-0.5, 0.5) is -0.0L);\n- assert(beta(-1.5, 0.5) is +0.0L);\n- assert(beta(+0., +0.) == +real.infinity);\n- assert(isNaN(beta(+0., +real.infinity)));\n- assert(beta(1, +real.infinity) is +0.0L);\n- assert(isNaN(beta(-0., +0.)));\n- assert(beta(-0., nextUp(+0.0L)) == -real.infinity);\n- assert(beta(-0.5, +real.infinity) == -real.infinity);\n- assert(beta(nextDown(-1.0L), real.infinity) == real.infinity);\n- assert(beta(nextDown(-0.0L), +0.) == +real.infinity);\n- assert(beta(-0.5, -0.) == -real.infinity);\n }\n \n /** Digamma function, $(PSI)(x)\n@@ -505,23 +490,59 @@ do\n assert(isClose(gammaIncompleteCompl(1, 2), 1-gammaIncomplete(1, 2)));\n }\n \n-/** Inverse of complemented incomplete gamma integral\n+/** Inverse regularized upper incomplete gamma function Q$(SUP -1)(a,p) with respect to p\n *\n- * Given a and p, the function finds x such that\n+ * Given a and p, the function finds x such that p = Q(a,x).\n *\n- * gammaIncompleteCompl( a, x ) = p.\n+ * Params:\n+ * a = the shape parameter, must be positive\n+ * p = Q(a,x), must be in the interval [0,1]\n+ *\n+ * Returns:\n+ * It returns x, a value $(GE) 0\n+ *\n+ * $(TABLE_SV\n+ * $(TR $(TH a) $(TH p) $(TH gammaIncompleteComplInverse(a, p)) )\n+ * $(TR $(TD negative) $(TD) $(TD $(NAN)) )\n+ * $(TR $(TD) $(TD $(LT) 0) $(TD $(NAN)) )\n+ * $(TR $(TD) $(TD $(GT) 1) $(TD $(NAN)) )\n+ * $(TR $(TD +0) $(TD $(LT) 1) $(TD $(NAN)) )\n+ * $(TR $(TD $(INFIN)) $(TD $(GT) 0) $(TD $(NAN)) )\n+ * $(TR $(TD $(GT) 0) $(TD 0) $(TD $(INFIN)) )\n+ * $(TR $(TD $(LT) $(INFIN)) $(TD 1) $(TD 0) )\n+ * )\n+ *\n+ * See_Also: $(LREF gammaIncompleteCompl)\n */\n real gammaIncompleteComplInverse(real a, real p)\n in\n {\n- assert(p >= 0 && p <= 1);\n- assert(a > 0);\n+ // allow NaN input to pass through so that it can be addressed by the\n+ // internal NaN payload propagation logic\n+ if (!isNaN(a) && !isNaN(p))\n+ {\n+ assert(signbit(a) == 0, \"a must be positive\");\n+ assert(p >= 0.0L && p <= 1.0L, \"p must be in the interval [0,1]\");\n+ }\n }\n+out(x; isNaN(x) || x >= 0.0L)\n do\n {\n return std.internal.math.gammafunction.gammaIncompleteComplInv(a, p);\n }\n \n+///\n+@safe unittest\n+{\n+ const a = 2, p = 0.5L;\n+ assert(isClose(gammaIncompleteComplInverse(a, gammaIncompleteCompl(a, p)), p));\n+\n+ assert(isClose(gammaIncompleteComplInverse(1, 1/E), 1));\n+ assert(isNaN(gammaIncompleteComplInverse(+0.0L, 0.1)));\n+ assert(isNaN(gammaIncompleteComplInverse(real.infinity, 0.2)));\n+ assert(gammaIncompleteComplInverse(3, 0) is real.infinity);\n+ assert(gammaIncompleteComplInverse(4, 1) == 0);\n+}\n \n /* ***********************************************\n * ERROR FUNCTIONS & NORMAL DISTRIBUTION *\ndiff --git a/libphobos/src/std/signals.d b/libphobos/src/std/signals.d\nindex 97004d52ddd..14b082fc20d 100644\n--- a/libphobos/src/std/signals.d\n+++ b/libphobos/src/std/signals.d\n@@ -66,11 +66,6 @@ import core.exception : onOutOfMemoryError;\n import core.stdc.stdlib : calloc, realloc, free;\n import std.stdio;\n \n-// Special function for internal use only.\n-// Use of this is where the slot had better be a delegate\n-// to an object or an interface that is part of an object.\n-extern (C) Object _d_toObject(void* p);\n-\n // Used in place of Object.notifyRegister and Object.notifyUnRegister.\n alias DisposeEvt = void delegate(Object);\n extern (C) void rt_attachDisposeEvent( Object obj, DisposeEvt evt );\ndiff --git a/libphobos/src/std/socket.d b/libphobos/src/std/socket.d\nindex 8f29c78f59f..1c04e67dbd7 100644\n--- a/libphobos/src/std/socket.d\n+++ b/libphobos/src/std/socket.d\n@@ -3560,7 +3560,7 @@ public:\n if (checkError) checkError.setMinCapacity(n);\n }\n \n- int result = .select(n, fr, fw, fe, &timeout.ctimeval);\n+ int result = .select(n, fr, fw, fe, timeout !is null ? &timeout.ctimeval : null);\n \n version (Windows)\n {\ndiff --git a/libphobos/src/std/traits.d b/libphobos/src/std/traits.d\nindex 759ccb94fcf..0f04afb55ff 100644\n--- a/libphobos/src/std/traits.d\n+++ b/libphobos/src/std/traits.d\n@@ -2246,8 +2246,8 @@ if (isCallable!func)\n static assert(is( typeof(test) == FunctionTypeOf!test ));\n static assert(is( typeof(test) == FunctionTypeOf!test_fp ));\n static assert(is( typeof(test) == FunctionTypeOf!test_dg ));\n- alias int GetterType() @property;\n- alias int SetterType(int) @property;\n+ alias GetterType = int() @property;\n+ alias SetterType = int(int) @property;\n static assert(is( FunctionTypeOf!propGet == GetterType ));\n static assert(is( FunctionTypeOf!propSet == SetterType ));\n \ndiff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d\nindex a2039006c8b..b957394d523 100644\n--- a/libphobos/src/std/typecons.d\n+++ b/libphobos/src/std/typecons.d\n@@ -7586,12 +7586,12 @@ private template TypeMod(T)\n }\n alias methods = GetOverloadedMethods!A;\n \n- alias int F1();\n- alias @property int F2();\n- alias string F3();\n- alias nothrow @trusted uint F4();\n- alias int F5(Object);\n- alias bool F6(Object);\n+ alias F1 = int();\n+ alias F2 = @property int();\n+ alias F3 = string();\n+ alias F4 = nothrow @trusted uint();\n+ alias F5 = int(Object);\n+ alias F6 = bool(Object);\n static assert(methods.length == 3 + 4);\n static assert(__traits(identifier, methods[0]) == \"draw\" && is(typeof(&methods[0]) == F1*));\n static assert(__traits(identifier, methods[1]) == \"value\" && is(typeof(&methods[1]) == F2*));\n@@ -7675,49 +7675,49 @@ package template DerivedFunctionType(T...)\n @safe unittest\n {\n // attribute covariance\n- alias int F1();\n+ alias F1 = int();\n static assert(is(DerivedFunctionType!(F1, F1) == F1));\n- alias int F2() pure nothrow;\n+ alias F2 = int() pure nothrow;\n static assert(is(DerivedFunctionType!(F1, F2) == F2));\n- alias int F3() @safe;\n- alias int F23() @safe pure nothrow;\n+ alias F3 = int() @safe;\n+ alias F23 = int() @safe pure nothrow;\n static assert(is(DerivedFunctionType!(F2, F3) == F23));\n \n // return type covariance\n- alias long F4();\n+ alias F4 = long();\n static assert(is(DerivedFunctionType!(F1, F4) == void));\n class C {}\n class D : C {}\n- alias C F5();\n- alias D F6();\n+ alias F5 = C();\n+ alias F6 = D();\n static assert(is(DerivedFunctionType!(F5, F6) == F6));\n- alias typeof(null) F7();\n- alias int[] F8();\n- alias int* F9();\n+ alias F7 = typeof(null)();\n+ alias F8 = int[]();\n+ alias F9 = int*();\n static assert(is(DerivedFunctionType!(F5, F7) == F7));\n static assert(is(DerivedFunctionType!(F7, F8) == void));\n static assert(is(DerivedFunctionType!(F7, F9) == F7));\n \n // variadic type equality\n- alias int F10(int);\n- alias int F11(int...);\n- alias int F12(int, ...);\n+ alias F10 = int(int);\n+ alias F11 = int(int...);\n+ alias F12 = int(int, ...);\n static assert(is(DerivedFunctionType!(F10, F11) == void));\n static assert(is(DerivedFunctionType!(F10, F12) == void));\n static assert(is(DerivedFunctionType!(F11, F12) == void));\n \n // linkage equality\n- alias extern(C) int F13(int);\n- alias extern(D) int F14(int);\n- alias extern(Windows) int F15(int);\n+ alias F13 = extern(C) int(int);\n+ alias F14 = extern(D) int(int);\n+ alias F15 = extern(Windows) int(int);\n static assert(is(DerivedFunctionType!(F13, F14) == void));\n static assert(is(DerivedFunctionType!(F13, F15) == void));\n static assert(is(DerivedFunctionType!(F14, F15) == void));\n \n // ref & @property equality\n- alias int F16(int);\n- alias ref int F17(int);\n- alias @property int F18(int);\n+ alias F16 = int(int);\n+ alias F17 = ref int(int);\n+ alias F18 = @property int(int);\n static assert(is(DerivedFunctionType!(F16, F17) == void));\n static assert(is(DerivedFunctionType!(F16, F18) == void));\n static assert(is(DerivedFunctionType!(F17, F18) == void));\ndiff --git a/libphobos/src/std/uni/package.d b/libphobos/src/std/uni/package.d\nindex 34d15e034ba..d689f08e538 100644\n--- a/libphobos/src/std/uni/package.d\n+++ b/libphobos/src/std/uni/package.d\n@@ -1785,6 +1785,7 @@ alias sharSwitchLowerBound = sharMethod!switchUniformLowerBound;\n {\n debug\n {\n+ assert(accessIsSafe);\n arr[] = cast(typeof(T.init[0]))(0xdead_beef);\n }\n arr = null;\n@@ -1795,6 +1796,18 @@ alias sharSwitchLowerBound = sharMethod!switchUniformLowerBound;\n {\n arr = null;\n }\n+\n+ // This is unfortunately necessary to \"fake pure\". It will only ever be called\n+ // in the destructor for a GC-allocated CowArray, which is the only place where\n+ // this might return false. Current code expects this to be pure, so we can't\n+ // break that. But before this change, the code would access the referenced\n+ // array inside a GC finalizer, which is invalid.\n+ pragma(mangle, \"gc_inFinalizer\") private static extern(C) bool pureInGCFinalizer() @safe pure nothrow;\n+\n+ static @property bool accessIsSafe() @safe nothrow pure\n+ {\n+ return __ctfe || !pureInGCFinalizer;\n+ }\n }\n \n // ditto\n@@ -1892,6 +1905,8 @@ alias sharSwitchLowerBound = sharMethod!switchUniformLowerBound;\n pureFree(arr.ptr);\n arr = null;\n }\n+\n+ enum accessIsSafe = true;\n }\n \n //build hack\n@@ -3234,6 +3249,10 @@ struct CowArray(SP=GcPolicy)\n \n ~this()\n {\n+ if (!SP.accessIsSafe)\n+ // detach from the array, we can no longer access it.\n+ data = null;\n+\n if (!empty)\n {\n immutable cnt = refCount;\ndiff --git a/libphobos/src/std/variant.d b/libphobos/src/std/variant.d\nindex 1760f5fd694..74b6065162d 100644\n--- a/libphobos/src/std/variant.d\n+++ b/libphobos/src/std/variant.d\n@@ -37,6 +37,7 @@ Source: $(PHOBOSSRC std/variant.d)\n module std.variant;\n \n import std.meta, std.traits, std.typecons;\n+import core.memory : GC;\n \n ///\n @system unittest\n@@ -428,8 +429,8 @@ private:\n }\n else\n {\n- // object will be intialized later. Using ubyte buffer in case `this()` is disabled\n- A* p = cast(A*) (new ubyte[A.sizeof]).ptr;\n+ // object will be intialized later. Using malloc in case `this()` is disabled\n+ A* p = cast(A*) GC.malloc(A.sizeof, 0, typeid(A));\n }\n *cast(A**)&target.store = p;\n }\n@@ -679,8 +680,8 @@ switchStmtTupAssign:\n static if (is(A == U[n], U, size_t n))\n auto p = cast(A*) (new U[n]).ptr;\n else\n- // object will be intialized later. Using ubyte buffer in case `this()` is disabled\n- A* p = cast(A*) (new ubyte[A.sizeof]).ptr;\n+ // object will be intialized later. Using malloc in case `this()` is disabled\n+ A* p = cast(A*) GC.malloc(A.sizeof, 0, typeid(A));\n // Emplace will run the postblit of `A` us, no need to do it manually, then\n copyEmplace(*zis, *p);\n *(cast(A**) pStore) = p;\n@@ -789,8 +790,8 @@ public:\n static if (is(T == U[n], U, size_t n))\n T* p = cast(T*) (new U[n]).ptr;\n else\n- // object will be intialized later. Using ubyte buffer in case `this()` is disabled\n- T* p = cast(T*) (new ubyte[T.sizeof]).ptr;\n+ // object will be intialized later. Using malloc in case `this()` is disabled\n+ T* p = cast(T*) GC.malloc(T.sizeof, 0, typeid(T));\n copyEmplace(rhs, *p);\n *(cast(T**) &store) = p;\n }\n@@ -1274,7 +1275,7 @@ public:\n auto arr = get!(A[]);\n foreach (ref e; arr)\n {\n- if (dg(e)) return 1;\n+ if (auto r = dg(e)) return r;\n }\n }\n else static if (is(A == VariantN))\n@@ -1286,7 +1287,7 @@ public:\n // Variant when in fact they are only changing tmp.\n auto tmp = this[i];\n debug scope(exit) assert(tmp == this[i]);\n- if (dg(tmp)) return 1;\n+ if (auto r = dg(tmp)) return r;\n }\n }\n else\ndiff --git a/libphobos/testsuite/libphobos.aa/test_aa.d b/libphobos/testsuite/libphobos.aa/test_aa.d\nindex 214bc9a12b2..aef99e8ab5a 100644\n--- a/libphobos/testsuite/libphobos.aa/test_aa.d\n+++ b/libphobos/testsuite/libphobos.aa/test_aa.d\n@@ -1048,3 +1048,38 @@ void testAliasThis2()\n assert(B(5) in aa);\n assert(A(false, 5) in aa);\n }\n+\n+void test22510()\n+{\n+ static struct S(AA)\n+ {\n+ AA aa_;\n+ auto aa() inout => this.aa_.dup;\n+ }\n+ auto testDup(AA)()\n+ {\n+ S!AA s;\n+ return s.aa();\n+ }\n+ auto aa_ii = testDup!(int[int])();\n+ static assert(is(typeof(aa_ii) == int[int]));\n+\n+ auto aa_cii = testDup!(const(int[int]))();\n+ static assert(is(typeof(aa_cii) == int[int]));\n+\n+ static struct T\n+ {\n+ char[] s; // non const indirection disallows conversion of const(T) -> T when copying\n+ }\n+ auto aa_it = testDup!(int[T])();\n+ static assert(is(typeof(aa_it) == int[T]));\n+\n+ auto aa_cit = testDup!(const(int[T]))();\n+ static assert(is(typeof(aa_cit) == int[T]));\n+\n+ auto aa_ti = testDup!(T[int])();\n+ static assert(is(typeof(aa_ti) == T[int]));\n+\n+ auto aa_cti = testDup!(const(T[int]))();\n+ static assert(is(typeof(aa_cti) == const(T)[int]));\n+}\ndiff --git a/libphobos/testsuite/libphobos.phobos/std_array.d b/libphobos/testsuite/libphobos.phobos/std_array.d\nindex b74b19a3e92..9d1c0216935 100644\n--- a/libphobos/testsuite/libphobos.phobos/std_array.d\n+++ b/libphobos/testsuite/libphobos.phobos/std_array.d\n@@ -442,23 +442,6 @@\n assert(b == [1, 0, 0, 0, 5]);\n }\n \n-@safe pure nothrow unittest\n-{\n- import std.array;\n-\n- auto app = appender!string();\n- string b = \"abcdefg\";\n- foreach (char c; b)\n- app.put(c);\n- assert(app[] == \"abcdefg\");\n-\n- int[] a = [ 1, 2 ];\n- auto app2 = appender(a);\n- app2.put(3);\n- app2.put([ 4, 5, 6 ]);\n- assert(app2[] == [ 1, 2, 3, 4, 5, 6 ]);\n-}\n-\n @safe pure nothrow unittest\n {\n import std.array;\ndiff --git a/libphobos/testsuite/libphobos.phobos/std_mathspecial.d b/libphobos/testsuite/libphobos.phobos/std_mathspecial.d\nindex 84a90c81345..10521eece3f 100644\n--- a/libphobos/testsuite/libphobos.phobos/std_mathspecial.d\n+++ b/libphobos/testsuite/libphobos.phobos/std_mathspecial.d\n@@ -10,21 +10,6 @@\n import std.mathspecial;\n \n assert(beta(1, 2) == 0.5);\n- assert(isIdentical(beta(NaN(0xABC), 4), NaN(0xABC)));\n- assert(beta(3, 4) == beta(4, 3));\n- assert(isNaN(beta(-real.infinity, +0.)));\n- assert(isNaN(beta(-1, 2)));\n- assert(beta(-0.5, 0.5) is -0.0L);\n- assert(beta(-1.5, 0.5) is +0.0L);\n- assert(beta(+0., +0.) == +real.infinity);\n- assert(isNaN(beta(+0., +real.infinity)));\n- assert(beta(1, +real.infinity) is +0.0L);\n- assert(isNaN(beta(-0., +0.)));\n- assert(beta(-0., nextUp(+0.0L)) == -real.infinity);\n- assert(beta(-0.5, +real.infinity) == -real.infinity);\n- assert(beta(nextDown(-1.0L), real.infinity) == real.infinity);\n- assert(beta(nextDown(-0.0L), +0.) == +real.infinity);\n- assert(beta(-0.5, -0.) == -real.infinity);\n }\n \n @safe unittest\n@@ -84,3 +69,17 @@\n assert(isClose(gammaIncompleteCompl(1, 2), 1-gammaIncomplete(1, 2)));\n }\n \n+@safe unittest\n+{\n+ import std.mathspecial;\n+\n+ const a = 2, p = 0.5L;\n+ assert(isClose(gammaIncompleteComplInverse(a, gammaIncompleteCompl(a, p)), p));\n+\n+ assert(isClose(gammaIncompleteComplInverse(1, 1/E), 1));\n+ assert(isNaN(gammaIncompleteComplInverse(+0.0L, 0.1)));\n+ assert(isNaN(gammaIncompleteComplInverse(real.infinity, 0.2)));\n+ assert(gammaIncompleteComplInverse(3, 0) is real.infinity);\n+ assert(gammaIncompleteComplInverse(4, 1) == 0);\n+}\n+\n", "prefixes": [ "committed" ] }