From patchwork Wed Jun 22 15:58:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 1646614 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=yaE6NcP0; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Received: from sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4LSp3m2P7Kz9sGD for ; Thu, 23 Jun 2022 01:59:30 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 86248386F0C6 for ; Wed, 22 Jun 2022 15:59:27 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 86248386F0C6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1655913567; bh=JlemckU5NB+0FDW5AQGUO9OAjSYLviLdBlNeRJKHFNE=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=yaE6NcP0/luYL5v8RtUDNYu5Y395dipXU4QPeDHukHdOTGiP3mDuGelJFyF9N/fxv WdjpLgAnnPtH3HjQegrGKOPhWt0V5/KKHNTYRg4d0MHeZHm+qw0y0leKQ1awmx5o/5 NvNlh/D5x7YFZOyOiv7iUT7e5AXw/uTforw5/IgE= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [IPv6:2001:67c:2050:0:465::101]) by sourceware.org (Postfix) with ESMTPS id EE45B3857433 for ; Wed, 22 Jun 2022 15:58:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org EE45B3857433 Received: from smtp202.mailbox.org (smtp202.mailbox.org [10.196.197.202]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4LSp2z43r9z9sN4; Wed, 22 Jun 2022 17:58:51 +0200 (CEST) To: gcc-patches@gcc.gnu.org Subject: [committed] d: Merge upstream dmd 6203135dc, druntime e150cca1, phobos a4a18d21c. Date: Wed, 22 Jun 2022 17:58:46 +0200 Message-Id: <20220622155846.1041560-1-ibuclaw@gdcproject.org> MIME-Version: 1.0 X-Spam-Status: No, score=-10.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SOMETLD_ARE_BAD_TLD, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE, URI_HEX autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Iain Buclaw via Gcc-patches From: Iain Buclaw Reply-To: Iain Buclaw Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Hi, This patch merges the D front-end with upstream dmd 6203135dc, and the D run-time library with upstream druntime e150cca1, and phobos a4a18d21c. D front-end changes: - Input parameters can now be applied on extern(C++) functions to bind to `const &' when the `-fpreview=in' flag is in effect. D runtime changes: - Run-time flag `--DRT-oncycle=deprecate' has been removed. Phobos changes: - Removed std.experimental.logger's capability to set the minimal LogLevel at compile time. Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, and committed to mainline. Regards, Iain. --- gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 6203135dc. * typeinfo.cc (TypeInfoVisitor::visit (TypeInfoStructDeclaration *)): Update for new front-end interface. (SpeculativeTypeVisitor::visit (TypeStruct *)): Likewise. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime e150cca1. * src/MERGE: Merge upstream phobos a4a18d21c. * testsuite/libphobos.cycles/cycles.exp (cycle_test_list): Update expected result of deprecate test. --- gcc/d/dmd/MERGE | 2 +- gcc/d/dmd/aggregate.h | 36 +- gcc/d/dmd/clone.d | 9 +- gcc/d/dmd/denum.d | 14 +- gcc/d/dmd/dstruct.d | 33 +- gcc/d/dmd/dsymbolsem.d | 29 +- gcc/d/dmd/enum.h | 13 +- gcc/d/dmd/escape.d | 40 ++- gcc/d/dmd/expression.d | 2 +- gcc/d/dmd/func.d | 21 +- gcc/d/dmd/parse.d | 4 +- gcc/d/dmd/statementsem.d | 25 +- gcc/d/dmd/typesem.d | 31 +- gcc/d/typeinfo.cc | 4 +- gcc/testsuite/gdc.test/compilable/b16360.d | 39 --- gcc/testsuite/gdc.test/compilable/inliner.d | 21 ++ gcc/testsuite/gdc.test/compilable/inliner2.d | 27 ++ .../gdc.test/fail_compilation/fail17927.d | 8 +- .../gdc.test/fail_compilation/fail20108.d | 2 +- .../gdc.test/fail_compilation/fail_scope.d | 8 +- .../gdc.test/fail_compilation/ice12574.d | 2 +- .../gdc.test/fail_compilation/previewin.d | 2 +- .../gdc.test/fail_compilation/previewin2.d | 18 + .../gdc.test/fail_compilation/retscope.d | 12 +- .../gdc.test/fail_compilation/retscope2.d | 4 +- .../gdc.test/fail_compilation/retscope6.d | 12 +- .../gdc.test/fail_compilation/test14238.d | 2 +- .../gdc.test/fail_compilation/test17423.d | 2 +- .../gdc.test/fail_compilation/test17450.d | 4 +- .../gdc.test/fail_compilation/test20245.d | 8 +- .../gdc.test/fail_compilation/test22818.d | 2 +- .../gdc.test/fail_compilation/typeerrors.d | 2 +- .../gdc.test/fail_compilation/udaparams.d | 4 +- .../gdc.test/fail_compilation/udatypes.d | 8 + gcc/testsuite/gdc.test/runnable/ice10086b.d | 50 +++ gcc/testsuite/gdc.test/runnable/inline3.d | 44 +++ .../gdc.test/runnable/staticforeach.d | 29 ++ gcc/testsuite/gdc.test/runnable_cxx/cppa.d | 20 +- .../runnable_cxx/extra-files/cppb.cpp | 30 +- libphobos/libdruntime/MERGE | 2 +- libphobos/libdruntime/core/stdc/config.d | 31 ++ libphobos/libdruntime/core/stdc/errno.d | 137 ++++++++ libphobos/libdruntime/core/stdc/stdarg.d | 21 ++ libphobos/libdruntime/core/stdc/stddef.d | 5 + libphobos/libdruntime/core/stdc/stdint.d | 35 ++ libphobos/libdruntime/core/stdc/stdio.d | 72 ++++ libphobos/libdruntime/core/stdc/stdlib.d | 1 + libphobos/libdruntime/core/sys/elf/package.d | 63 ++++ libphobos/libdruntime/core/sys/posix/fcntl.d | 6 + .../libdruntime/core/sys/windows/winsock2.d | 14 +- libphobos/libdruntime/core/thread/osthread.d | 4 +- .../libdruntime/core/thread/threadbase.d | 12 +- libphobos/libdruntime/core/time.d | 4 +- libphobos/libdruntime/core/vararg.d | 17 + libphobos/libdruntime/rt/critical_.d | 4 +- libphobos/libdruntime/rt/dmain2.d | 16 +- libphobos/libdruntime/rt/lifetime.d | 6 +- libphobos/libdruntime/rt/minfo.d | 216 +----------- libphobos/libdruntime/rt/monitor_.d | 6 +- libphobos/src/MERGE | 2 +- libphobos/src/std/complex.d | 2 +- libphobos/src/std/experimental/logger/core.d | 329 +++--------------- .../src/std/experimental/logger/package.d | 20 -- libphobos/src/std/file.d | 30 +- libphobos/src/std/math/algebraic.d | 6 +- libphobos/src/std/math/hardware.d | 6 +- libphobos/src/std/math/trigonometry.d | 46 +-- libphobos/src/std/numeric.d | 44 ++- libphobos/src/std/stdio.d | 12 +- libphobos/src/std/sumtype.d | 50 ++- .../testsuite/libphobos.cycles/cycles.exp | 2 +- 71 files changed, 1071 insertions(+), 773 deletions(-) delete mode 100644 gcc/testsuite/gdc.test/compilable/b16360.d create mode 100644 gcc/testsuite/gdc.test/compilable/inliner.d create mode 100644 gcc/testsuite/gdc.test/compilable/inliner2.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/previewin2.d create mode 100644 gcc/testsuite/gdc.test/fail_compilation/udatypes.d create mode 100644 gcc/testsuite/gdc.test/runnable/inline3.d diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index d39658a808e..d1e3dc16312 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -821ed393d428c7db5a48623e77d43f5647d5c6a2 +6203135dcf0112d3211add0cbfb22fecc5df1af4 The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h index f27ca0769c9..d91e35ee8c2 100644 --- a/gcc/d/dmd/aggregate.h +++ b/gcc/d/dmd/aggregate.h @@ -159,17 +159,6 @@ struct StructFlags class StructDeclaration : public AggregateDeclaration { public: - bool zeroInit; // !=0 if initialize with 0 fill - bool hasIdentityAssign; // true if has identity opAssign - bool hasBlitAssign; // true if opAssign is a blit - bool hasIdentityEquals; // true if has identity opEquals - bool hasNoFields; // has no fields - bool hasCopyCtor; // copy constructor - // Even if struct is defined as non-root symbol, some built-in operations - // (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo. - // For those, today TypeInfo_Struct is generated in COMDAT. - bool requestTypeInfo; - FuncDeclarations postblits; // Array of postblit functions FuncDeclaration *postblit; // aggregate postblit @@ -179,18 +168,37 @@ public: static FuncDeclaration *xerreq; // object.xopEquals static FuncDeclaration *xerrcmp; // object.xopCmp - structalign_t alignment; // alignment applied outside of the struct - ThreeState ispod; // if struct is POD - // ABI-specific type(s) if the struct can be passed in registers TypeTuple *argTypes; + structalign_t alignment; // alignment applied outside of the struct + ThreeState ispod; // if struct is POD +private: + uint8_t bitFields; +public: static StructDeclaration *create(const Loc &loc, Identifier *id, bool inObject); StructDeclaration *syntaxCopy(Dsymbol *s) override; Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final; const char *kind() const override; void finalizeSize() override final; bool isPOD(); + bool zeroInit() const; // !=0 if initialize with 0 fill + bool zeroInit(bool v); + bool hasIdentityAssign() const; // true if has identity opAssign + bool hasIdentityAssign(bool v); + bool hasBlitAssign() const; // true if opAssign is a blit + bool hasBlitAssign(bool v); + bool hasIdentityEquals() const; // true if has identity opEquals + bool hasIdentityEquals(bool v); + bool hasNoFields() const; // has no fields + bool hasNoFields(bool v); + bool hasCopyCtor() const; // copy constructor + bool hasCopyCtor(bool v); + // Even if struct is defined as non-root symbol, some built-in operations + // (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo. + // For those, today TypeInfo_Struct is generated in COMDAT. + bool requestTypeInfo() const; + bool requestTypeInfo(bool v); StructDeclaration *isStructDeclaration() override final { return this; } void accept(Visitor *v) override { v->visit(this); } diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d index 75a16bd2da4..cf4ccbb955c 100644 --- a/gcc/d/dmd/clone.d +++ b/gcc/d/dmd/clone.d @@ -404,7 +404,12 @@ bool needOpEquals(StructDeclaration sd) { //printf("StructDeclaration::needOpEquals() %s\n", sd.toChars()); if (sd.isUnionDeclaration()) - goto Ldontneed; + { + /* If a union has only one field, treat it like a struct + */ + if (sd.fields.length != 1) + goto Ldontneed; + } if (sd.hasIdentityEquals) goto Lneed; /* If any of the fields has an opEquals, then we @@ -421,7 +426,7 @@ bool needOpEquals(StructDeclaration sd) if (tvbase.ty == Tstruct) { TypeStruct ts = cast(TypeStruct)tvbase; - if (ts.sym.isUnionDeclaration()) + if (ts.sym.isUnionDeclaration() && ts.sym.fields.length != 1) continue; if (needOpEquals(ts.sym)) goto Lneed; diff --git a/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d index aba290bed05..ef322f13da5 100644 --- a/gcc/d/dmd/denum.d +++ b/gcc/d/dmd/denum.d @@ -54,9 +54,17 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol Expression maxval; Expression minval; Expression defaultval; // default initializer - bool isdeprecated; - bool added; - int inuse; + + // `bool` fields that are compacted into bit fields in a string mixin + private extern (D) static struct BitFields + { + bool isdeprecated; + bool added; + bool inuse; + } + + import dmd.common.bitfields : generateBitFields; + mixin(generateBitFields!(BitFields, ubyte)); extern (D) this(const ref Loc loc, Identifier ident, Type memtype) { diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d index de5f1453c9a..4126a8adc68 100644 --- a/gcc/d/dmd/dstruct.d +++ b/gcc/d/dmd/dstruct.d @@ -192,17 +192,6 @@ enum StructFlags : int */ extern (C++) class StructDeclaration : AggregateDeclaration { - bool zeroInit; // !=0 if initialize with 0 fill - bool hasIdentityAssign; // true if has identity opAssign - bool hasBlitAssign; // true if opAssign is a blit - bool hasIdentityEquals; // true if has identity opEquals - bool hasNoFields; // has no fields - bool hasCopyCtor; // copy constructor - // Even if struct is defined as non-root symbol, some built-in operations - // (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo. - // For those, today TypeInfo_Struct is generated in COMDAT. - bool requestTypeInfo; - FuncDeclarations postblits; // Array of postblit functions FuncDeclaration postblit; // aggregate postblit @@ -212,11 +201,29 @@ extern (C++) class StructDeclaration : AggregateDeclaration extern (C++) __gshared FuncDeclaration xerreq; // object.xopEquals extern (C++) __gshared FuncDeclaration xerrcmp; // object.xopCmp + // ABI-specific type(s) if the struct can be passed in registers + TypeTuple argTypes; + structalign_t alignment; // alignment applied outside of the struct ThreeState ispod; // if struct is POD - // ABI-specific type(s) if the struct can be passed in registers - TypeTuple argTypes; + // `bool` fields that are compacted into bit fields in a string mixin + private extern (D) static struct BitFields + { + bool zeroInit; // !=0 if initialize with 0 fill + bool hasIdentityAssign; // true if has identity opAssign + bool hasBlitAssign; // true if opAssign is a blit + bool hasIdentityEquals; // true if has identity opEquals + bool hasNoFields; // has no fields + bool hasCopyCtor; // copy constructor + // Even if struct is defined as non-root symbol, some built-in operations + // (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo. + // For those, today TypeInfo_Struct is generated in COMDAT. + bool requestTypeInfo; + } + + import dmd.common.bitfields : generateBitFields; + mixin(generateBitFields!(BitFields, ubyte)); extern (D) this(const ref Loc loc, Identifier id, bool inObject) { diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index 6dbc129baaf..7fd47818759 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -49,6 +49,7 @@ import dmd.identifier; import dmd.importc; import dmd.init; import dmd.initsem; +import dmd.intrange; import dmd.hdrgen; import dmd.mtype; import dmd.mustuse; @@ -2177,6 +2178,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor assert(ed.memtype); int nextValue = 0; // C11 6.7.2.2-3 first member value defaults to 0 + // C11 6.7.2.2-2 value must be representable as an int. + // The sizemask represents all values that int will fit into, + // from 0..uint.max. We want to cover int.min..uint.max. + const mask = Type.tint32.sizemask(); + IntRange ir = IntRange(SignExtendedNumber(~(mask >> 1), true), + SignExtendedNumber(mask)); + void emSemantic(EnumMember em, ref int nextValue) { static void errorReturn(EnumMember em) @@ -2206,21 +2214,32 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor em.error("enum member must be an integral constant expression, not `%s` of type `%s`", e.toChars(), e.type.toChars()); return errorReturn(em); } - const sinteger_t v = ie.toInteger(); - if (v < int.min || v > uint.max) + if (!ir.contains(getIntRange(ie))) { // C11 6.7.2.2-2 em.error("enum member value `%s` does not fit in an `int`", e.toChars()); return errorReturn(em); } - em.value = new IntegerExp(em.loc, cast(int)v, Type.tint32); - nextValue = cast(int)v; + nextValue = cast(int)ie.toInteger(); + em.value = new IntegerExp(em.loc, nextValue, Type.tint32); } else { + // C11 6.7.2.2-3 add 1 to value of previous enumeration constant + bool first = (em == (*em.ed.members)[0]); + if (!first) + { + import core.checkedint : adds; + bool overflow; + nextValue = adds(nextValue, 1, overflow); + if (overflow) + { + em.error("initialization with `%d+1` causes overflow for type `int`", nextValue - 1); + return errorReturn(em); + } + } em.value = new IntegerExp(em.loc, nextValue, Type.tint32); } - ++nextValue; // C11 6.7.2.2-3 add 1 to value of previous enumeration constant em.semanticRun = PASS.semanticdone; } diff --git a/gcc/d/dmd/enum.h b/gcc/d/dmd/enum.h index 9ec130099fe..723cebc7e0a 100644 --- a/gcc/d/dmd/enum.h +++ b/gcc/d/dmd/enum.h @@ -35,10 +35,15 @@ public: Expression *maxval; Expression *minval; Expression *defaultval; // default initializer - - bool isdeprecated; - bool added; - int inuse; +private: + uint8_t bitFields; +public: + bool isdeprecated() const; + bool isdeprecated(bool v); + bool added() const; + bool added(bool v); + bool inuse() const; + bool inuse(bool v); EnumDeclaration *syntaxCopy(Dsymbol *s) override; void addMember(Scope *sc, ScopeDsymbol *sds) override; diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d index 97a655289b5..0646f57c5cd 100644 --- a/gcc/d/dmd/escape.d +++ b/gcc/d/dmd/escape.d @@ -328,12 +328,12 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, STC else if (par) { result |= sc.setUnsafeDIP1000(gag, arg.loc, - desc ~ " `%s` assigned to non-scope parameter `%s`", v, par); + desc ~ " `%s` assigned to non-scope parameter `%s` calling `%s`", v, par, fdc); } else { result |= sc.setUnsafeDIP1000(gag, arg.loc, - desc ~ " `%s` assigned to non-scope parameter `this`", v); + desc ~ " `%s` assigned to non-scope parameter `this` calling `%s`", v, fdc); } } @@ -1230,9 +1230,24 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) !(!refs && sc.func.isFuncDeclaration().getLevel(pfunc, sc.intypeof) > 0) ) { - // https://issues.dlang.org/show_bug.cgi?id=17029 - result |= sc.setUnsafeDIP1000(gag, e.loc, "scope variable `%s` may not be returned", v); - continue; + if (v.isParameter() && !(v.storage_class & STC.return_)) + { + // https://issues.dlang.org/show_bug.cgi?id=23191 + if (!gag) + { + previewErrorFunc(sc.isDeprecated(), global.params.useDIP1000)(e.loc, + "scope parameter `%s` may not be returned", v.toChars() + ); + result = true; + continue; + } + } + else + { + // https://issues.dlang.org/show_bug.cgi?id=17029 + result |= sc.setUnsafeDIP1000(gag, e.loc, "scope variable `%s` may not be returned", v); + continue; + } } } else if (v.storage_class & STC.variadic && p == sc.func) @@ -2492,9 +2507,11 @@ private void addMaybe(VarDeclaration va, VarDeclaration v) * fmt = printf-style format string * arg0 = (optional) argument for first %s format specifier * arg1 = (optional) argument for second %s format specifier + * arg2 = (optional) argument for third %s format specifier * Returns: whether an actual safe error (not deprecation) occured */ -private bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)* msg, RootObject arg0 = null, RootObject arg1 = null) +private bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)* msg, + RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) { if (fs == FeatureState.disabled) { @@ -2502,7 +2519,7 @@ private bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, con } else if (fs == FeatureState.enabled) { - return sc.setUnsafe(gag, loc, msg, arg0, arg1); + return sc.setUnsafe(gag, loc, msg, arg0, arg1, arg2); } else { @@ -2510,22 +2527,23 @@ private bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, con { if (!gag) previewErrorFunc(sc.isDeprecated(), fs)( - loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "" + loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "" ); } else if (!sc.func.safetyViolation) { import dmd.func : AttributeViolation; - sc.func.safetyViolation = new AttributeViolation(loc, msg, arg0, arg1); + sc.func.safetyViolation = new AttributeViolation(loc, msg, arg0, arg1, arg2); } return false; } } // `setUnsafePreview` partially evaluated for dip1000 -private bool setUnsafeDIP1000(Scope* sc, bool gag, Loc loc, const(char)* msg, RootObject arg0 = null, RootObject arg1 = null) +private bool setUnsafeDIP1000(Scope* sc, bool gag, Loc loc, const(char)* msg, + RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) { - return setUnsafePreview(sc, global.params.useDIP1000, gag, loc, msg, arg0, arg1); + return setUnsafePreview(sc, global.params.useDIP1000, gag, loc, msg, arg0, arg1, arg2); } /*************************************** diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d index 4d171059306..ceecf4b5e74 100644 --- a/gcc/d/dmd/expression.d +++ b/gcc/d/dmd/expression.d @@ -1438,7 +1438,7 @@ extern (C++) abstract class Expression : ASTNode else if (!sc.func.safetyViolation) { import dmd.func : AttributeViolation; - sc.func.safetyViolation = new AttributeViolation(this.loc, null, f, null); + sc.func.safetyViolation = new AttributeViolation(this.loc, null, f, null, null); } } return false; diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index d42925990a9..83bc2eab1fe 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -1476,17 +1476,19 @@ extern (C++) class FuncDeclaration : Declaration * fmt = printf-style format string * arg0 = (optional) argument for first %s format specifier * arg1 = (optional) argument for second %s format specifier + * arg2 = (optional) argument for third %s format specifier * Returns: whether there's a safe error */ extern (D) final bool setUnsafe( - bool gag = false, Loc loc = Loc.init, const(char)* fmt = null, RootObject arg0 = null, RootObject arg1 = null) + bool gag = false, Loc loc = Loc.init, const(char)* fmt = null, + RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) { if (flags & FUNCFLAG.safetyInprocess) { flags &= ~FUNCFLAG.safetyInprocess; type.toTypeFunction().trust = TRUST.system; if (fmt || arg0) - safetyViolation = new AttributeViolation(loc, fmt, arg0, arg1); + safetyViolation = new AttributeViolation(loc, fmt, arg0, arg1, arg2); if (fes) fes.func.setUnsafe(); @@ -1494,7 +1496,7 @@ extern (C++) class FuncDeclaration : Declaration else if (isSafe()) { if (!gag && fmt) - .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : ""); + .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); return true; } @@ -4370,10 +4372,12 @@ extern (C++) final class NewDeclaration : FuncDeclaration * fmt = printf-style format string * arg0 = (optional) argument for first %s format specifier * arg1 = (optional) argument for second %s format specifier + * arg2 = (optional) argument for third %s format specifier * Returns: whether there's a safe error */ bool setUnsafe(Scope* sc, - bool gag = false, Loc loc = Loc.init, const(char)* fmt = null, RootObject arg0 = null, RootObject arg1 = null) + bool gag = false, Loc loc = Loc.init, const(char)* fmt = null, + RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) { // TODO: // For @system variables, unsafe initializers at global scope should mark @@ -4394,13 +4398,13 @@ bool setUnsafe(Scope* sc, { // Message wil be gagged, but still call error() to update global.errors and for // -verrors=spec - .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : ""); + .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); return true; } return false; } - return sc.func.setUnsafe(gag, loc, fmt, arg0, arg1); + return sc.func.setUnsafe(gag, loc, fmt, arg0, arg1, arg2); } /// Stores a reason why a function failed to infer a function attribute like `@safe` or `pure` @@ -4421,6 +4425,8 @@ struct AttributeViolation RootObject arg0 = null; /// ditto RootObject arg1 = null; + /// ditto + RootObject arg2 = null; } /// Print the reason why `fd` was inferred `@system` as a supplemental error @@ -4438,7 +4444,8 @@ void errorSupplementalInferredSafety(FuncDeclaration fd, int maxDepth, bool depr errorFunc(s.loc, deprecation ? "which would be `@system` because of:" : "which was inferred `@system` because of:"); - errorFunc(s.loc, s.fmtStr, s.arg0 ? s.arg0.toChars() : "", s.arg1 ? s.arg1.toChars() : ""); + errorFunc(s.loc, s.fmtStr, + s.arg0 ? s.arg0.toChars() : "", s.arg1 ? s.arg1.toChars() : "", s.arg2 ? s.arg2.toChars() : ""); } else if (FuncDeclaration fd2 = cast(FuncDeclaration) s.arg0) { diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index 89f8ae3470f..eb5e6942948 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -4862,7 +4862,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (udas !is null) { if (storage_class != 0) - error("cannot put a storage-class in an alias declaration."); + error("cannot put a storage-class in an `alias` declaration."); // parseAttributes shouldn't have set these variables assert(link == linkage && !setAlignment && ealign is null); auto tpl_ = cast(AST.TemplateDeclaration) s; @@ -4887,7 +4887,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer parseAttributes(); // type if (udas) - error("user-defined attributes not allowed for alias declarations"); + error("user-defined attributes not allowed for `alias` declarations"); auto t = parseType(); diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d index 06e28a4819d..f23b9882ae0 100644 --- a/gcc/d/dmd/statementsem.d +++ b/gcc/d/dmd/statementsem.d @@ -4401,19 +4401,21 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState Dsymbol ds = null; if (!(storageClass & STC.manifest)) { - if ((isStatic || tb.ty == Tfunction || storageClass&STC.alias_) && e.op == EXP.variable) - ds = (cast(VarExp)e).var; - else if (e.op == EXP.template_) - ds = (cast(TemplateExp)e).td; - else if (e.op == EXP.scope_) - ds = (cast(ScopeExp)e).sds; - else if (e.op == EXP.function_) + if (isStatic || tb.ty == Tfunction || storageClass & STC.alias_) { - auto fe = cast(FuncExp)e; - ds = fe.td ? cast(Dsymbol)fe.td : fe.fd; + if (auto ve = e.isVarExp()) + ds = ve.var; + else if (auto dve = e.isDotVarExp()) + ds = dve.var; } - else if (e.op == EXP.overloadSet) - ds = (cast(OverExp)e).vars; + if (auto te = e.isTemplateExp()) + ds = te.td; + else if (auto se = e.isScopeExp()) + ds = se.sds; + else if (auto fe = e.isFuncExp()) + ds = fe.td ? fe.td : fe.fd; + else if (auto oe = e.isOverExp()) + ds = oe.vars; } else if (storageClass & STC.alias_) { @@ -4530,6 +4532,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState auto field = Identifier.idPool(StaticForeach.tupleFieldName.ptr,StaticForeach.tupleFieldName.length); Expression access = new DotIdExp(loc, e, field); access = expressionSemantic(access, sc); + access = access.optimize(WANTvalue); if (!tuple) return returnEarly(); //printf("%s\n",tuple.toChars()); foreach (l; 0 .. dim) diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index 31ecbd246e6..8cacdb10a26 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -119,7 +119,7 @@ private void resolveTupleIndex(const ref Loc loc, Scope* sc, Dsymbol s, out Expr const(uinteger_t) d = eindex.toUInteger(); if (d >= tup.objects.dim) { - .error(loc, "tuple index `%llu` exceeds length %llu", d, cast(ulong)tup.objects.dim); + .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong)tup.objects.dim); pt = Type.terror; return; } @@ -554,7 +554,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) uinteger_t d = mtype.dim.toUInteger(); if (d >= tup.objects.dim) { - .error(loc, "tuple index %llu exceeds %llu", cast(ulong)d, cast(ulong)tup.objects.dim); + .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tup.objects.dim); return error(); } @@ -649,7 +649,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) uinteger_t d = mtype.dim.toUInteger(); if (d >= tt.arguments.dim) { - .error(loc, "tuple index %llu exceeds %llu", cast(ulong)d, cast(ulong)tt.arguments.dim); + .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tt.arguments.dim); return error(); } Type telem = (*tt.arguments)[cast(size_t)d].type; @@ -1224,6 +1224,25 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) continue; } + // -preview=in: Always add `ref` when used with `extern(C++)` functions + // Done here to allow passing opaque types with `in` + if (global.params.previewIn && (fparam.storageClass & (STC.in_ | STC.ref_)) == STC.in_) + { + switch (tf.linkage) + { + case LINK.cpp: + fparam.storageClass |= STC.ref_; + break; + case LINK.default_, LINK.d: + break; + default: + .error(loc, "cannot use `in` parameters with `extern(%s)` functions", + linkageToChars(tf.linkage)); + .errorSupplemental(loc, "parameter `%s` declared as `in` here", fparam.toChars()); + break; + } + } + if (t.ty == Tfunction) { .error(loc, "cannot have parameter of function type `%s`", fparam.type.toChars()); @@ -2572,7 +2591,7 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type const d = mt.dim.toUInteger(); if (d >= tup.objects.dim) { - error(loc, "tuple index `%llu` exceeds length %llu", d, cast(ulong) tup.objects.dim); + error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong) tup.objects.dim); return returnError(); } @@ -4891,9 +4910,9 @@ Expression getMaxMinValue(EnumDeclaration ed, const ref Loc loc, Identifier id) */ Expression e = em.value; Expression ec = new CmpExp(id == Id.max ? EXP.greaterThan : EXP.lessThan, em.loc, e, *pval); - ed.inuse++; + ed.inuse = true; ec = ec.expressionSemantic(em._scope); - ed.inuse--; + ed.inuse = false; ec = ec.ctfeInterpret(); if (ec.op == EXP.error) { diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc index 1f8afdd2c74..d1f0d59952f 100644 --- a/gcc/d/typeinfo.cc +++ b/gcc/d/typeinfo.cc @@ -1050,7 +1050,7 @@ public: this->layout_string (ti->deco); /* Default initializer for struct. */ - tree ptr = (sd->zeroInit) ? null_pointer_node + tree ptr = (sd->zeroInit ()) ? null_pointer_node : build_address (aggregate_initializer_decl (sd)); this->layout_field (d_array_value (array_type_node, size_int (sd->structsize), ptr)); @@ -1771,7 +1771,7 @@ public: { if (!ti->needsCodegen ()) { - if (ti->minst || sd->requestTypeInfo) + if (ti->minst || sd->requestTypeInfo ()) return; this->result_ |= true; diff --git a/gcc/testsuite/gdc.test/compilable/b16360.d b/gcc/testsuite/gdc.test/compilable/b16360.d deleted file mode 100644 index 11415791b65..00000000000 --- a/gcc/testsuite/gdc.test/compilable/b16360.d +++ /dev/null @@ -1,39 +0,0 @@ -/* -REQUIRED_ARGS: -inline -wi - -TEST_OUTPUT: ---- -compilable/b16360.d(12): Warning: cannot inline function `b16360.foo` -compilable/b16360.d(25): Warning: cannot inline function `b16360.bar` ---- -*/ - -pragma(inline, true) -auto foo() -{ - static struct U - { - int a = 42; - float b; - ~this(){} // __dtor: inline not allowed - } - U u; - return u.a; -} - -pragma(inline, true) -auto bar() -{ - class U // class : inline not allowed - { - int a = 42; - float b; - } - return (new U).a; -} - -void main() -{ - auto f = foo(); - auto b = bar(); -} diff --git a/gcc/testsuite/gdc.test/compilable/inliner.d b/gcc/testsuite/gdc.test/compilable/inliner.d new file mode 100644 index 00000000000..1273809b8db --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/inliner.d @@ -0,0 +1,21 @@ +// REQUIRED_ARGS: -inline -O -unittest + +struct Cent +{ + ulong lo; + ulong hi; +} + +Cent add(Cent, Cent); + +Cent sub(Cent c1, Cent c2) +{ + return add(c1, c2); +} + +Cent udivmod(Cent c3, Cent c4) +{ + Cent quotient; + Cent rem = sub(c3, c4); + return quotient; +} diff --git a/gcc/testsuite/gdc.test/compilable/inliner2.d b/gcc/testsuite/gdc.test/compilable/inliner2.d new file mode 100644 index 00000000000..7ffa5cca31b --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/inliner2.d @@ -0,0 +1,27 @@ +// REQUIRED_ARGS: -O -inline + +struct Cent +{ + ulong lo; // low 64 bits + ulong hi; // high 64 bits +} + +pure bool tst(Cent c) +{ + return c.hi || c.lo; +} + +pure Cent dec(Cent c); +pure Cent shl(Cent c, uint n); + +pure Cent udivmod(Cent c1, Cent c2, out Cent modulus) +{ + ulong v1 = shl(c2, 3).hi; + + Cent quotient; + + if (tst(quotient)) + quotient = dec(quotient); + + return quotient; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail17927.d b/gcc/testsuite/gdc.test/fail_compilation/fail17927.d index 410f3077706..cf610ff8d97 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail17927.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail17927.d @@ -1,10 +1,10 @@ /* REQUIRED_ARGS: -preview=dip1000 * TEST_OUTPUT: --- -fail_compilation/fail17927.d(13): Error: scope variable `this` may not be returned -fail_compilation/fail17927.d(15): Error: scope variable `this` may not be returned -fail_compilation/fail17927.d(21): Error: scope variable `ptr` may not be returned -fail_compilation/fail17927.d(23): Error: scope variable `ptr` may not be returned +fail_compilation/fail17927.d(13): Error: scope parameter `this` may not be returned +fail_compilation/fail17927.d(15): Error: scope parameter `this` may not be returned +fail_compilation/fail17927.d(21): Error: scope parameter `ptr` may not be returned +fail_compilation/fail17927.d(23): Error: scope parameter `ptr` may not be returned --- */ // https://issues.dlang.org/show_bug.cgi?id=17927 diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail20108.d b/gcc/testsuite/gdc.test/fail_compilation/fail20108.d index f768b89e6a4..15845e1d2fc 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail20108.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail20108.d @@ -3,7 +3,7 @@ TEST_OUTPUT: --- fail_compilation/fail20108.d(15): Error: address of variable `y` assigned to `x` with longer lifetime -fail_compilation/fail20108.d(16): Error: scope variable `x` may not be returned +fail_compilation/fail20108.d(16): Error: scope parameter `x` may not be returned fail_compilation/fail20108.d(23): Error: address of variable `y` assigned to `x` with longer lifetime fail_compilation/fail20108.d(24): Error: scope variable `x` may not be returned --- diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d b/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d index 3e7637ff667..3fac1678e69 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d @@ -2,7 +2,10 @@ REQUIRED_ARGS: TEST_OUTPUT: --- -fail_compilation/fail_scope.d(40): Deprecation: scope variable `p` may not be returned +fail_compilation/fail_scope.d(30): Deprecation: scope parameter `da` may not be returned +fail_compilation/fail_scope.d(32): Deprecation: scope parameter `o` may not be returned +fail_compilation/fail_scope.d(33): Deprecation: scope parameter `dg` may not be returned +fail_compilation/fail_scope.d(40): Deprecation: scope parameter `p` may not be returned fail_compilation/fail_scope.d(45): Error: returning `cast(char[])string` escapes a reference to local variable `string` fail_compilation/fail_scope.d(63): Error: returning `s.bar()` escapes a reference to local variable `s` fail_compilation/fail_scope.d(74): Error: `fail_scope.foo8` called with argument types `(int)` matches both: @@ -16,9 +19,6 @@ fail_compilation/fail_scope.d(108): Deprecation: escaping reference to outer loc fail_compilation/fail_scope.d(127): Deprecation: returning `s.bar()` escapes a reference to local variable `s` fail_compilation/fail_scope.d(137): Error: returning `foo16226(i)` escapes a reference to local variable `i` --- -//fail_compilation/fail_scope.d(30): Error: scope variable `da` may not be returned -//fail_compilation/fail_scope.d(32): Error: scope variable `o` may not be returned -//fail_compilation/fail_scope.d(33): Error: scope variable `dg` may not be returned //fail_compilation/fail_scope.d(35): Error: scope variable `da` may not be returned //fail_compilation/fail_scope.d(37): Error: scope variable `o` may not be returned //fail_compilation/fail_scope.d(38): Error: scope variable `dg` may not be returned diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice12574.d b/gcc/testsuite/gdc.test/fail_compilation/ice12574.d index 420b6b70078..93e5f1d8cc0 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice12574.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice12574.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/ice12574.d(40): Error: tuple index `2` exceeds length 2 +fail_compilation/ice12574.d(40): Error: tuple index `2` out of bounds `[0 .. 2]` fail_compilation/ice12574.d(53): Error: template instance `ice12574.reduce!("a", "a").reduce!(Tuple!(int, int, int))` error instantiating --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/previewin.d b/gcc/testsuite/gdc.test/fail_compilation/previewin.d index b3beaf4c9d8..ce0cf926a13 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/previewin.d +++ b/gcc/testsuite/gdc.test/fail_compilation/previewin.d @@ -10,7 +10,7 @@ fail_compilation/previewin.d(6): Error: function `previewin.takeFunction(void fu fail_compilation/previewin.d(6): cannot pass argument `__lambda3` of type `void function(ref const(real) x) pure nothrow @nogc @safe` to parameter `void function(in real) f` fail_compilation/previewin.d(15): Error: scope variable `arg` assigned to non-scope `myGlobal` fail_compilation/previewin.d(16): Error: scope variable `arg` assigned to non-scope `myGlobal` -fail_compilation/previewin.d(17): Error: scope variable `arg` may not be returned +fail_compilation/previewin.d(17): Error: scope parameter `arg` may not be returned fail_compilation/previewin.d(18): Error: scope variable `arg` assigned to `escape` with longer lifetime fail_compilation/previewin.d(22): Error: returning `arg` escapes a reference to parameter `arg` fail_compilation/previewin.d(22): perhaps annotate the parameter with `return` diff --git a/gcc/testsuite/gdc.test/fail_compilation/previewin2.d b/gcc/testsuite/gdc.test/fail_compilation/previewin2.d new file mode 100644 index 00000000000..e9fe6a1fa88 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/previewin2.d @@ -0,0 +1,18 @@ +/* +REQUIRED_ARGS: -preview=in -preview=dip1000 +TEST_OUTPUT: +--- +fail_compilation/previewin2.d(1): Error: cannot use `in` parameters with `extern(C)` functions +fail_compilation/previewin2.d(1): parameter `a` declared as `in` here +fail_compilation/previewin2.d(2): Error: cannot use `in` parameters with `extern(Windows)` functions +fail_compilation/previewin2.d(2): parameter `a` declared as `in` here +fail_compilation/previewin2.d(4): Error: cannot use `in` parameters with `extern(C)` functions +fail_compilation/previewin2.d(4): parameter `__anonymous_param` declared as `in` here +--- +*/ + +#line 1 +extern(C) void wrongLink1 (in int a); +extern(Windows) void wrongLink2 (in void* a); +struct Large { ulong[64] data; } +extern(C) void wrongLink3 (in Large); diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope.d b/gcc/testsuite/gdc.test/fail_compilation/retscope.d index 27d566362bd..93944040db9 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/retscope.d +++ b/gcc/testsuite/gdc.test/fail_compilation/retscope.d @@ -2,7 +2,7 @@ REQUIRED_ARGS: -preview=dip1000 TEST_OUTPUT: --- -fail_compilation/retscope.d(22): Error: scope variable `p` may not be returned +fail_compilation/retscope.d(22): Error: scope parameter `p` may not be returned fail_compilation/retscope.d(32): Error: returning `b ? nested1(& i) : nested2(& j)` escapes a reference to local variable `j` fail_compilation/retscope.d(45): Error: scope variable `p` assigned to non-scope `q` fail_compilation/retscope.d(47): Error: address of variable `i` assigned to `q` with longer lifetime @@ -85,7 +85,7 @@ struct HTTP /* TEST_OUTPUT: --- -fail_compilation/retscope.d(96): Error: reference to local variable `sa` assigned to non-scope parameter `a` +fail_compilation/retscope.d(96): Error: reference to local variable `sa` assigned to non-scope parameter `a` calling `bar8` --- */ // https://issues.dlang.org/show_bug.cgi?id=8838 @@ -149,7 +149,7 @@ S10* test10() /* TEST_OUTPUT: --- -fail_compilation/retscope.d(158): Error: scope variable `this` may not be returned +fail_compilation/retscope.d(158): Error: scope parameter `this` may not be returned --- */ @@ -218,7 +218,7 @@ void* escape3 (scope void* p) @safe { /* TEST_OUTPUT: --- -fail_compilation/retscope.d(229): Error: scope variable `ptr` may not be returned +fail_compilation/retscope.d(229): Error: scope parameter `ptr` may not be returned --- */ @@ -403,7 +403,7 @@ class Foo13 /* TEST_OUTPUT: --- -fail_compilation/retscope.d(1205): Error: scope variable `f14` assigned to non-scope parameter `this` +fail_compilation/retscope.d(1205): Error: scope variable `f14` assigned to non-scope parameter `this` calling `foo` --- */ @@ -454,7 +454,7 @@ fail_compilation/retscope.d(1311): Error: scope variable `u2` assigned to `ek` w /* TEST_OUTPUT: --- -fail_compilation/retscope.d(1405): Error: reference to local variable `buf` assigned to non-scope parameter `__anonymous_param` +fail_compilation/retscope.d(1405): Error: reference to local variable `buf` assigned to non-scope parameter `__anonymous_param` calling `myprintf` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope2.d b/gcc/testsuite/gdc.test/fail_compilation/retscope2.d index 17d2182b454..9f1e13dde98 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/retscope2.d +++ b/gcc/testsuite/gdc.test/fail_compilation/retscope2.d @@ -86,8 +86,8 @@ fail_compilation/retscope2.d(504): Error: scope variable `c` may not be returned /* TEST_OUTPUT: --- -fail_compilation/retscope2.d(604): Error: scope variable `_param_0` assigned to non-scope parameter `__anonymous_param` -fail_compilation/retscope2.d(604): Error: scope variable `_param_1` assigned to non-scope parameter `__anonymous_param` +fail_compilation/retscope2.d(604): Error: scope variable `_param_0` assigned to non-scope parameter `__anonymous_param` calling `foo600` +fail_compilation/retscope2.d(604): Error: scope variable `_param_1` assigned to non-scope parameter `__anonymous_param` calling `foo600` fail_compilation/retscope2.d(614): Error: template instance `retscope2.test600!(int*, int*)` error instantiating --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope6.d b/gcc/testsuite/gdc.test/fail_compilation/retscope6.d index b9a85aeddc1..a8e5de5dc6d 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/retscope6.d +++ b/gcc/testsuite/gdc.test/fail_compilation/retscope6.d @@ -76,9 +76,9 @@ void foo() @safe /* TEST_OUTPUT: --- fail_compilation/retscope6.d(8016): Error: address of variable `i` assigned to `p` with longer lifetime -fail_compilation/retscope6.d(8031): Error: reference to local variable `i` assigned to non-scope parameter `p` -fail_compilation/retscope6.d(8031): Error: reference to local variable `j` assigned to non-scope parameter `q` -fail_compilation/retscope6.d(8048): Error: reference to local variable `j` assigned to non-scope parameter `q` +fail_compilation/retscope6.d(8031): Error: reference to local variable `i` assigned to non-scope parameter `p` calling `betty` +fail_compilation/retscope6.d(8031): Error: reference to local variable `j` assigned to non-scope parameter `q` calling `betty` +fail_compilation/retscope6.d(8048): Error: reference to local variable `j` assigned to non-scope parameter `q` calling `archie` --- */ @@ -172,7 +172,7 @@ T9 testfred() /* TEST_OUTPUT: --- -fail_compilation/retscope6.d(10003): Error: scope variable `values` assigned to non-scope parameter `values` +fail_compilation/retscope6.d(10003): Error: scope variable `values` assigned to non-scope parameter `values` calling `escape` --- */ @@ -234,7 +234,7 @@ const(int)* f_c_20150() @safe nothrow /* TEST_OUTPUT: --- -fail_compilation/retscope6.d(13010): Error: reference to local variable `str` assigned to non-scope parameter `x` +fail_compilation/retscope6.d(13010): Error: reference to local variable `str` assigned to non-scope parameter `x` calling `f_throw` --- */ @@ -254,7 +254,7 @@ void escape_throw_20150() @safe /* TEST_OUTPUT: --- -fail_compilation/retscope6.d(14019): Error: scope variable `scopePtr` assigned to non-scope parameter `x` +fail_compilation/retscope6.d(14019): Error: scope variable `scopePtr` assigned to non-scope parameter `x` calling `noInfer23021` fail_compilation/retscope6.d(14022): Error: scope variable `scopePtr` may not be returned --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test14238.d b/gcc/testsuite/gdc.test/fail_compilation/test14238.d index e0d0b35c4d6..a0e4d69b361 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test14238.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test14238.d @@ -1,7 +1,7 @@ /* REQUIRED_ARGS: -preview=dip1000 TEST_OUTPUT: --- -fail_compilation/test14238.d(20): Error: scope variable `fn` may not be returned +fail_compilation/test14238.d(20): Error: scope parameter `fn` may not be returned fail_compilation/test14238.d(28): Error: escaping reference to stack allocated value returned by `&baz` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17423.d b/gcc/testsuite/gdc.test/fail_compilation/test17423.d index ec86646fc5a..3afb63b591b 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test17423.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test17423.d @@ -1,7 +1,7 @@ /* REQUIRED_ARGS: -preview=dip1000 TEST_OUTPUT: --- -fail_compilation/test17423.d(26): Error: reference to local `this` assigned to non-scope parameter `dlg` +fail_compilation/test17423.d(26): Error: reference to local `this` assigned to non-scope parameter `dlg` calling `opApply` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17450.d b/gcc/testsuite/gdc.test/fail_compilation/test17450.d index 098adaae648..ddf3f46fb12 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test17450.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test17450.d @@ -33,8 +33,8 @@ struct S { /* TEST_OUTPUT: --- -fail_compilation/test17450.d(103): Error: scope variable `c` may not be returned -fail_compilation/test17450.d(106): Error: scope variable `this` may not be returned +fail_compilation/test17450.d(103): Error: scope parameter `c` may not be returned +fail_compilation/test17450.d(106): Error: scope parameter `this` may not be returned --- */ // https://issues.dlang.org/show_bug.cgi?id=17450 diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20245.d b/gcc/testsuite/gdc.test/fail_compilation/test20245.d index daa0697cffd..1713c9d8c27 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test20245.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test20245.d @@ -2,15 +2,15 @@ REQUIRED_ARGS: -preview=dip1000 TEST_OUTPUT: --- -fail_compilation/test20245.d(20): Error: reference to local variable `x` assigned to non-scope parameter `ptr` +fail_compilation/test20245.d(20): Error: reference to local variable `x` assigned to non-scope parameter `ptr` calling `escape` fail_compilation/test20245.d(21): Error: copying `&x` into allocated memory escapes a reference to parameter `x` fail_compilation/test20245.d(22): Error: scope variable `a` may not be returned fail_compilation/test20245.d(26): Error: cannot take address of `scope` variable `x` since `scope` applies to first indirection only -fail_compilation/test20245.d(32): Error: reference to local variable `x` assigned to non-scope parameter `ptr` +fail_compilation/test20245.d(32): Error: reference to local variable `x` assigned to non-scope parameter `ptr` calling `escape` fail_compilation/test20245.d(33): Error: copying `&x` into allocated memory escapes a reference to parameter `x` fail_compilation/test20245.d(49): Error: reference to local variable `price` assigned to non-scope `this.minPrice` -fail_compilation/test20245.d(68): Error: reference to local variable `this` assigned to non-scope parameter `msg` -fail_compilation/test20245.d(88): Error: reference to local variable `this` assigned to non-scope parameter `content` +fail_compilation/test20245.d(68): Error: reference to local variable `this` assigned to non-scope parameter `msg` calling `this` +fail_compilation/test20245.d(88): Error: reference to local variable `this` assigned to non-scope parameter `content` calling `listUp` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22818.d b/gcc/testsuite/gdc.test/fail_compilation/test22818.d index ae96b3bc109..5759415ead2 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test22818.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test22818.d @@ -1,7 +1,7 @@ /* REQUIRED_ARGS: -preview=dip1000 * TEST_OUTPUT: --- -fail_compilation/test22818.d(104): Error: scope variable `c` may not be returned +fail_compilation/test22818.d(104): Error: scope parameter `c` may not be returned --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/typeerrors.d b/gcc/testsuite/gdc.test/fail_compilation/typeerrors.d index 37395d4b897..9d527b75d71 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/typeerrors.d +++ b/gcc/testsuite/gdc.test/fail_compilation/typeerrors.d @@ -2,7 +2,7 @@ TEST_OUTPUT: --- fail_compilation/typeerrors.d(32): Deprecation: `scope` as a type constraint is deprecated. Use `scope` at the usage site. -fail_compilation/typeerrors.d(37): Error: tuple index 4 exceeds 4 +fail_compilation/typeerrors.d(37): Error: tuple index `4` out of bounds `[0 .. 4]` fail_compilation/typeerrors.d(39): Error: variable `x` cannot be read at compile time fail_compilation/typeerrors.d(40): Error: cannot have array of `void()` fail_compilation/typeerrors.d(41): Error: cannot have array of scope `typeerrors.C` diff --git a/gcc/testsuite/gdc.test/fail_compilation/udaparams.d b/gcc/testsuite/gdc.test/fail_compilation/udaparams.d index 5d0390f4f29..ec4796789ac 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/udaparams.d +++ b/gcc/testsuite/gdc.test/fail_compilation/udaparams.d @@ -12,8 +12,8 @@ fail_compilation/udaparams.d(40): Error: `@safe` attribute for function paramete fail_compilation/udaparams.d(43): Error: `@system` attribute for function parameter is not supported fail_compilation/udaparams.d(44): Error: `@trusted` attribute for function parameter is not supported fail_compilation/udaparams.d(45): Error: `@nogc` attribute for function parameter is not supported -fail_compilation/udaparams.d(51): Error: cannot put a storage-class in an alias declaration. -fail_compilation/udaparams.d(52): Error: cannot put a storage-class in an alias declaration. +fail_compilation/udaparams.d(51): Error: cannot put a storage-class in an `alias` declaration. +fail_compilation/udaparams.d(52): Error: cannot put a storage-class in an `alias` declaration. fail_compilation/udaparams.d(53): Error: semicolon expected to close `alias` declaration fail_compilation/udaparams.d(53): Error: declaration expected, not `=>` fail_compilation/udaparams.d(54): Error: semicolon expected to close `alias` declaration diff --git a/gcc/testsuite/gdc.test/fail_compilation/udatypes.d b/gcc/testsuite/gdc.test/fail_compilation/udatypes.d new file mode 100644 index 00000000000..a7f2bfc521f --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/udatypes.d @@ -0,0 +1,8 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/udatypes.d(8): Error: user-defined attributes not allowed for `alias` declarations +--- +*/ + +alias c_typedef = extern(C) @(1) void* function(size_t); diff --git a/gcc/testsuite/gdc.test/runnable/ice10086b.d b/gcc/testsuite/gdc.test/runnable/ice10086b.d index abb6f78a4ac..910c5c4a7a2 100644 --- a/gcc/testsuite/gdc.test/runnable/ice10086b.d +++ b/gcc/testsuite/gdc.test/runnable/ice10086b.d @@ -5,3 +5,53 @@ import imports.ice10086y; import imports.ice10086x; void main() { test(); } + +static if (0) +{ +/* this is a reduced one-file version that triggers a seg fault +because the use of OPframeptr gets inlined, and the offests +to it are not updated. +Compile with: -O -inline +*/ + +pragma(inline, false) +auto bind(alias f, bindValues...)() +{ + pragma(inline, false) + auto bind(Types...)(Types values) + { + return f(bindValues, values); + } + return bind(); +} + + +struct SS +{ + int a1 = 123; +} + +pragma(inline, false) +@safe auto ff(SS rr) +{ + return rr; +} + +// pragma(inline, false) +@safe auto gg(SS ss) // this getting inlined triggers the problem +{ + return bind!(ff, ss); +} + +pragma(inline, false) +void test() +{ + SS s1; + + auto zb = bind!(gg, s1)(); + assert(zb.a1 == 123); +} + + +void main() { test(); } +} diff --git a/gcc/testsuite/gdc.test/runnable/inline3.d b/gcc/testsuite/gdc.test/runnable/inline3.d new file mode 100644 index 00000000000..01af5c8cbe5 --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable/inline3.d @@ -0,0 +1,44 @@ +// REQUIRED_ARGS: -inline -O + +// Test operator overloading + +extern (C) int printf(const(char*) fmt, ...); + +struct Tuple6798(T...) +{ + T field; + alias field this; + + bool opEquals(Tuple6798 rxx) + { + foreach (i, _; T) + { + if (!__equals(this[i], rxx[i])) + assert(0); + //return false; + } + return true; + } +} + +auto tuple(T...)(T args) +{ + return Tuple6798!T(args); +} + +int zzzz() +{ + if (!__equals("mno", "mno")) + assert(0); + + assert(tuple("abcd", "x") == tuple("abcd", "x")); + return 0; +} + +int main() +{ + zzzz(); + + printf("Success\n"); + return 0; +} diff --git a/gcc/testsuite/gdc.test/runnable/staticforeach.d b/gcc/testsuite/gdc.test/runnable/staticforeach.d index bf6dc983935..6a9ac5deb2f 100644 --- a/gcc/testsuite/gdc.test/runnable/staticforeach.d +++ b/gcc/testsuite/gdc.test/runnable/staticforeach.d @@ -39,7 +39,36 @@ void test19479() } } +/**********************************/ +// https://issues.dlang.org/show_bug.cgi?id=23192 + +alias AliasSeq(Args...) = Args; + +struct S23192 +{ + int x; + int y; + + int fun() + { + static foreach (sym; AliasSeq!(S23192.x)) + int i = sym; + + static foreach (sym; AliasSeq!(this.y)) + int j = sym; + + return i + j; + } +} + +void test23192() +{ + assert(S23192(1, 2).fun() == 3); + static assert(S23192(1, 2).fun() == 3); +} + void main() { test19479(); + test23192(); } diff --git a/gcc/testsuite/gdc.test/runnable_cxx/cppa.d b/gcc/testsuite/gdc.test/runnable_cxx/cppa.d index e31588948a6..cd91dd55834 100644 --- a/gcc/testsuite/gdc.test/runnable_cxx/cppa.d +++ b/gcc/testsuite/gdc.test/runnable_cxx/cppa.d @@ -1,3 +1,4 @@ +// REQUIRED_ARGS: -preview=in // PERMUTE_ARGS: -g // EXTRA_CPP_SOURCES: cppb.cpp // EXTRA_FILES: extra-files/cppb.h @@ -1637,7 +1638,13 @@ void test19134() } // https://issues.dlang.org/show_bug.cgi?id=18955 -alias std_string = std.basic_string!(char); +version (linux) + alias std_string = std.basic_string!(char); +else +{ + import core.stdcpp.string : core_basic_string = basic_string; + alias std_string = core_basic_string!(char); +} extern(C++) void callback18955(ref const(std_string) str) { @@ -1646,6 +1653,16 @@ extern(C++) void test18955(); /****************************************/ +extern(C++) void testPreviewIn(); + +extern(C++) void previewInFunction(in int a, in std_string b, ref const(std_string) c) +{ + assert(a == 42); + assert(&b is &c); +} + +/****************************************/ + void main() { test1(); @@ -1695,6 +1712,7 @@ void main() test18966(); test19134(); test18955(); + testPreviewIn(); printf("Success\n"); } diff --git a/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cppb.cpp b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cppb.cpp index 4fa87efcfff..83667cbddc7 100644 --- a/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cppb.cpp +++ b/gcc/testsuite/gdc.test/runnable_cxx/extra-files/cppb.cpp @@ -4,30 +4,8 @@ #include #include -#if _WIN32 // otherwise defined in C header files! -// https://issues.dlang.org/show_bug.cgi?id=18955 -namespace std -{ - template - struct char_traits - { - }; - template - class allocator - { - }; - template - class basic_string - { - }; - typedef basic_string, allocator > string; -} -#else // if POSIX - #include -#endif // _WIN32 - #include "cppb.h" /**************************************/ @@ -936,3 +914,11 @@ void test18955() callback18955(s); #endif } + +void previewInFunction(const int& a, const std::string& b, const std::string& c); + +void testPreviewIn() +{ + std::string s = "Hello World"; + previewInFunction(42, s, s); +} diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index 8b2839da46c..3f4a0ec63e3 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -1,4 +1,4 @@ -454471d8077d12ec6bf0ae8fcd9571aad1bce7be +e150cca179515ce5113e828aac94c20c0b983b7c The first line of this file holds the git revision number of the last merge done from the dlang/druntime repository. diff --git a/libphobos/libdruntime/core/stdc/config.d b/libphobos/libdruntime/core/stdc/config.d index 037af25a675..c576e991db5 100644 --- a/libphobos/libdruntime/core/stdc/config.d +++ b/libphobos/libdruntime/core/stdc/config.d @@ -185,6 +185,37 @@ else version (Posix) alias ulong cpp_ulonglong; } } +else version (WASI) +{ + static if ( (void*).sizeof > int.sizeof ) + { + enum __c_longlong : long; + enum __c_ulonglong : ulong; + + alias long c_long; + alias ulong c_ulong; + + alias long cpp_long; + alias ulong cpp_ulong; + + alias __c_longlong cpp_longlong; + alias __c_ulonglong cpp_ulonglong; + } + else + { + enum __c_long : int; + enum __c_ulong : uint; + + alias int c_long; + alias uint c_ulong; + + alias __c_long cpp_long; + alias __c_ulong cpp_ulong; + + alias long cpp_longlong; + alias ulong cpp_ulonglong; + } +} version (GNU) alias c_long_double = real; diff --git a/libphobos/libdruntime/core/stdc/errno.d b/libphobos/libdruntime/core/stdc/errno.d index 57bc15da6eb..24b4138153d 100644 --- a/libphobos/libdruntime/core/stdc/errno.d +++ b/libphobos/libdruntime/core/stdc/errno.d @@ -2079,6 +2079,143 @@ else version (Haiku) enum B_NO_TRANSLATOR = (B_TRANSLATION_ERROR_BASE + 1); enum B_ILLEGAL_DATA = (B_TRANSLATION_ERROR_BASE + 2); } +else version (WASI) +{ + enum EPERM = 1; + enum ENOENT = 2; + enum ESRCH = 3; + enum EINTR = 4; + enum EIO = 5; + enum ENXIO = 6; + enum E2BIG = 7; + enum ENOEXEC = 8; + enum EBADF = 9; + enum ECHILD = 10; + enum EAGAIN = 11; + enum ENOMEM = 12; + enum EACCES = 13; + enum EFAULT = 14; + enum ENOTBLK = 15; + enum EBUSY = 16; + enum EEXIST = 17; + enum EXDEV = 18; + enum ENODEV = 19; + enum ENOTDIR = 20; + enum EISDIR = 21; + enum EINVAL = 22; + enum ENFILE = 23; + enum EMFILE = 24; + enum ENOTTY = 25; + enum ETXTBSY = 26; + enum EFBIG = 27; + enum ENOSPC = 28; + enum ESPIPE = 29; + enum EROFS = 30; + enum EMLINK = 31; + enum EPIPE = 32; + enum EDOM = 33; + enum ERANGE = 34; + enum EDEADLK = 35; + enum ENAMETOOLONG = 36; + enum ENOLCK = 37; + enum ENOSYS = 38; + enum ENOTEMPTY = 39; + enum ELOOP = 40; + enum EWOULDBLOCK = EAGAIN; + enum ENOMSG = 42; + enum EIDRM = 43; + enum ECHRNG = 44; + enum EL2NSYNC = 45; + enum EL3HLT = 46; + enum EL3RST = 47; + enum ELNRNG = 48; + enum EUNATCH = 49; + enum ENOCSI = 50; + enum EL2HLT = 51; + enum EBADE = 52; + enum EBADR = 53; + enum EXFULL = 54; + enum ENOANO = 55; + enum EBADRQC = 56; + enum EBADSLT = 57; + enum EDEADLOCK = EDEADLK; + enum EBFONT = 59; + enum ENOSTR = 60; + enum ENODATA = 61; + enum ETIME = 62; + enum ENOSR = 63; + enum ENONET = 64; + enum ENOPKG = 65; + enum EREMOTE = 66; + enum ENOLINK = 67; + enum EADV = 68; + enum ESRMNT = 69; + enum ECOMM = 70; + enum EPROTO = 71; + enum EMULTIHOP = 72; + enum EDOTDOT = 73; + enum EBADMSG = 74; + enum EOVERFLOW = 75; + enum ENOTUNIQ = 76; + enum EBADFD = 77; + enum EREMCHG = 78; + enum ELIBACC = 79; + enum ELIBBAD = 80; + enum ELIBSCN = 81; + enum ELIBMAX = 82; + enum ELIBEXEC = 83; + enum EILSEQ = 84; + enum ERESTART = 85; + enum ESTRPIPE = 86; + enum EUSERS = 87; + enum ENOTSOCK = 88; + enum EDESTADDRREQ = 89; + enum EMSGSIZE = 90; + enum EPROTOTYPE = 91; + enum ENOPROTOOPT = 92; + enum EPROTONOSUPPORT = 93; + enum ESOCKTNOSUPPORT = 94; + enum EOPNOTSUPP = 95; + enum ENOTSUP = EOPNOTSUPP; + enum EPFNOSUPPORT = 96; + enum EAFNOSUPPORT = 97; + enum EADDRINUSE = 98; + enum EADDRNOTAVAIL = 99; + enum ENETDOWN = 100; + enum ENETUNREACH = 101; + enum ENETRESET = 102; + enum ECONNABORTED = 103; + enum ECONNRESET = 104; + enum ENOBUFS = 105; + enum EISCONN = 106; + enum ENOTCONN = 107; + enum ESHUTDOWN = 108; + enum ETOOMANYREFS = 109; + enum ETIMEDOUT = 110; + enum ECONNREFUSED = 111; + enum EHOSTDOWN = 112; + enum EHOSTUNREACH = 113; + enum EALREADY = 114; + enum EINPROGRESS = 115; + enum ESTALE = 116; + enum EUCLEAN = 117; + enum ENOTNAM = 118; + enum ENAVAIL = 119; + enum EISNAM = 120; + enum EREMOTEIO = 121; + enum EDQUOT = 122; + enum ENOMEDIUM = 123; + enum EMEDIUMTYPE = 124; + enum ECANCELED = 125; + enum ENOKEY = 126; + enum EKEYEXPIRED = 127; + enum EKEYREVOKED = 128; + enum EKEYREJECTED = 129; + enum EOWNERDEAD = 130; + enum ENOTRECOVERABLE = 131; + enum ERFKILL = 132; + enum EHWPOISON = 133; +} else { static assert(false, "Unsupported platform"); diff --git a/libphobos/libdruntime/core/stdc/stdarg.d b/libphobos/libdruntime/core/stdc/stdarg.d index 9a67f2e8e4d..646905eaffb 100644 --- a/libphobos/libdruntime/core/stdc/stdarg.d +++ b/libphobos/libdruntime/core/stdc/stdarg.d @@ -47,6 +47,8 @@ version (MIPS32) version = MIPS_Any; version (MIPS64) version = MIPS_Any; version (PPC) version = PPC_Any; version (PPC64) version = PPC_Any; +version (RISCV32) version = RISCV_Any; +version (RISCV64) version = RISCV_Any; version (GNU) { @@ -130,6 +132,12 @@ else version (AAPCS64) { alias va_list = core.internal.vararg.aarch64.va_list; } +else version (RISCV_Any) +{ + // The va_list type is void*, according to RISCV Calling Convention + // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc + alias va_list = void*; +} else { alias va_list = char*; // incl. unknown platforms @@ -259,6 +267,19 @@ T va_arg(T)(ref va_list ap) ap += T.sizeof.alignUp; return *p; } + else version (RISCV_Any) + { + static if (T.sizeof > (size_t.sizeof << 1)) + auto p = *cast(T**) ap; + else + { + static if (T.alignof == (size_t.sizeof << 1)) + ap = ap.alignUp!(size_t.sizeof << 1); + auto p = cast(T*) ap; + } + ap += T.sizeof.alignUp; + return *p; + } else static assert(0, "Unsupported platform"); } diff --git a/libphobos/libdruntime/core/stdc/stddef.d b/libphobos/libdruntime/core/stdc/stddef.d index 1d1d96255b9..56b3c9b3f90 100644 --- a/libphobos/libdruntime/core/stdc/stddef.d +++ b/libphobos/libdruntime/core/stdc/stddef.d @@ -34,3 +34,8 @@ else version (Posix) /// alias dchar wchar_t; } +else version (WASI) +{ + /// + alias dchar wchar_t; +} diff --git a/libphobos/libdruntime/core/stdc/stdint.d b/libphobos/libdruntime/core/stdc/stdint.d index 556ac019eeb..476c42f08ee 100644 --- a/libphobos/libdruntime/core/stdc/stdint.d +++ b/libphobos/libdruntime/core/stdc/stdint.d @@ -377,6 +377,41 @@ else version (Solaris) alias intmax_t = long; /// alias uintmax_t = ulong; /// } +else version (WASI) +{ + alias int8_t = byte; /// + alias int16_t = short; /// + alias uint8_t = ubyte; /// + alias uint16_t = ushort; /// + alias int32_t = int; /// + alias uint32_t = uint; /// + alias int64_t = long; /// + alias uint64_t = ulong; /// + + alias int_least8_t = byte; /// + alias uint_least8_t = ubyte; /// + alias int_least16_t = short; /// + alias uint_least16_t = ushort; /// + alias int_least32_t = int; /// + alias uint_least32_t = uint; /// + alias int_least64_t = long; /// + alias uint_least64_t = ulong; /// + + alias int_fast8_t = byte; /// + alias uint_fast8_t = ubyte; /// + alias int_fast16_t = ptrdiff_t; /// + alias uint_fast16_t = size_t; /// + alias int_fast32_t = ptrdiff_t; /// + alias uint_fast32_t = size_t; /// + + alias int_fast64_t = long; /// + alias uint_fast64_t = ulong; /// + + alias intptr_t = ptrdiff_t; /// + alias uintptr_t = size_t; /// + alias intmax_t = long; /// + alias uintmax_t = ulong; /// +} else { static assert(false, "Unsupported architecture."); diff --git a/libphobos/libdruntime/core/stdc/stdio.d b/libphobos/libdruntime/core/stdc/stdio.d index cd53f0ab50b..2e8381180db 100644 --- a/libphobos/libdruntime/core/stdc/stdio.d +++ b/libphobos/libdruntime/core/stdc/stdio.d @@ -347,6 +347,24 @@ else version (CRuntime_UClibc) L_tmpnam = 20 } } +else version (WASI) +{ + enum + { + /// + BUFSIZ = 1024, + /// + EOF = -1, + /// + FOPEN_MAX = 1000, + /// + FILENAME_MAX = 4096, + /// + TMP_MAX = 10000, + /// + L_tmpnam = 20 + } +} else { static assert( false, "Unsupported platform" ); @@ -449,6 +467,20 @@ else version (CRuntime_Glibc) /// alias shared(_IO_FILE) FILE; } +else version (WASI) +{ + union fpos_t + { + char[16] __opaque = 0; + double __align; + } + struct _IO_FILE; + + /// + alias _IO_FILE _iobuf; // needed for phobos + /// + alias shared(_IO_FILE) FILE; +} else version (CRuntime_Musl) { union fpos_t @@ -1125,6 +1157,24 @@ else version (CRuntime_UClibc) /// extern shared FILE* stderr; } +else version (WASI) +{ + // needs tail const + extern shared FILE* stdin; + /// + extern shared FILE* stdout; + /// + extern shared FILE* stderr; + enum + { + /// + _IOFBF = 0, + /// + _IOLBF = 1, + /// + _IONBF = 2, + } +} else { static assert( false, "Unsupported platform" ); @@ -1793,6 +1843,28 @@ else version (CRuntime_UClibc) pragma(printf) int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); } +else version (WASI) +{ + // No unsafe pointer manipulation. + @trusted + { + /// + void rewind(FILE* stream); + /// + pure void clearerr(FILE* stream); + /// + pure int feof(FILE* stream); + /// + pure int ferror(FILE* stream); + /// + int fileno(FILE *); + } + + /// + int snprintf(scope char* s, size_t n, scope const char* format, ...); + /// + int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg); +} else { static assert( false, "Unsupported platform" ); diff --git a/libphobos/libdruntime/core/stdc/stdlib.d b/libphobos/libdruntime/core/stdc/stdlib.d index dbe55a4b340..920c3117732 100644 --- a/libphobos/libdruntime/core/stdc/stdlib.d +++ b/libphobos/libdruntime/core/stdc/stdlib.d @@ -99,6 +99,7 @@ else version (Solaris) enum RAND_MAX = 0x7fff; else version (CRuntime_Bionic) enum RAND_MAX = 0x7fffffff; else version (CRuntime_Musl) enum RAND_MAX = 0x7fffffff; else version (CRuntime_UClibc) enum RAND_MAX = 0x7fffffff; +else version (WASI) enum RAND_MAX = 0x7fffffff; else static assert( false, "Unsupported platform" ); /// diff --git a/libphobos/libdruntime/core/sys/elf/package.d b/libphobos/libdruntime/core/sys/elf/package.d index 69e52093dc3..2dcfd201dd5 100644 --- a/libphobos/libdruntime/core/sys/elf/package.d +++ b/libphobos/libdruntime/core/sys/elf/package.d @@ -2510,3 +2510,66 @@ enum R_TILEGX_GNU_VTINHERIT = 128; enum R_TILEGX_GNU_VTENTRY = 129; enum R_TILEGX_NUM = 130; + +enum EF_RISCV_RVC = 0x0001; +enum EF_RISCV_FLOAT_ABI = 0x0006; +enum EF_RISCV_FLOAT_ABI_SOFT = 0x0000; +enum EF_RISCV_FLOAT_ABI_SINGLE = 0x0002; +enum EF_RISCV_FLOAT_ABI_DOUBLE = 0x0004; +enum EF_RISCV_FLOAT_ABI_QUAD = 0x0006; +enum R_RISCV_NONE = 0; +enum R_RISCV_32 = 1; +enum R_RISCV_64 = 2; +enum R_RISCV_RELATIVE = 3; +enum R_RISCV_COPY = 4; +enum R_RISCV_JUMP_SLOT = 5; +enum R_RISCV_TLS_DTPMOD32 = 6; +enum R_RISCV_TLS_DTPMOD64 = 7; +enum R_RISCV_TLS_DTPREL32 = 8; +enum R_RISCV_TLS_DTPREL64 = 9; +enum R_RISCV_TLS_TPREL32 = 10; +enum R_RISCV_TLS_TPREL64 = 11; +enum R_RISCV_BRANCH = 16; +enum R_RISCV_JAL = 17; +enum R_RISCV_CALL = 18; +enum R_RISCV_CALL_PLT = 19; +enum R_RISCV_GOT_HI20 = 20; +enum R_RISCV_TLS_GOT_HI20 = 21; +enum R_RISCV_TLS_GD_HI20 = 22; +enum R_RISCV_PCREL_HI20 = 23; +enum R_RISCV_PCREL_LO12_I = 24; +enum R_RISCV_PCREL_LO12_S = 25; +enum R_RISCV_HI20 = 26; +enum R_RISCV_LO12_I = 27; +enum R_RISCV_LO12_S = 28; +enum R_RISCV_TPREL_HI20 = 29; +enum R_RISCV_TPREL_LO12_I = 30; +enum R_RISCV_TPREL_LO12_S = 31; +enum R_RISCV_TPREL_ADD = 32; +enum R_RISCV_ADD8 = 33; +enum R_RISCV_ADD16 = 34; +enum R_RISCV_ADD32 = 35; +enum R_RISCV_ADD64 = 36; +enum R_RISCV_SUB8 = 37; +enum R_RISCV_SUB16 = 38; +enum R_RISCV_SUB32 = 39; +enum R_RISCV_SUB64 = 40; +enum R_RISCV_GNU_VTINHERIT = 41; +enum R_RISCV_GNU_VTENTRY = 42; +enum R_RISCV_ALIGN = 43; +enum R_RISCV_RVC_BRANCH = 44; +enum R_RISCV_RVC_JUMP = 45; +enum R_RISCV_RVC_LUI = 46; +enum R_RISCV_GPREL_I = 47; +enum R_RISCV_GPREL_S = 48; +enum R_RISCV_TPREL_I = 49; +enum R_RISCV_TPREL_S = 50; +enum R_RISCV_RELAX = 51; +enum R_RISCV_SUB6 = 52; +enum R_RISCV_SET6 = 53; +enum R_RISCV_SET8 = 54; +enum R_RISCV_SET16 = 55; +enum R_RISCV_SET32 = 56; +enum R_RISCV_32_PCREL = 57; +enum R_RISCV_IRELATIVE = 58; +enum R_RISCV_NUM = 59; diff --git a/libphobos/libdruntime/core/sys/posix/fcntl.d b/libphobos/libdruntime/core/sys/posix/fcntl.d index 3c196d29f22..dc0a183f25e 100644 --- a/libphobos/libdruntime/core/sys/posix/fcntl.d +++ b/libphobos/libdruntime/core/sys/posix/fcntl.d @@ -123,6 +123,12 @@ version (linux) enum F_SETLK = 6; enum F_SETLKW = 7; } + else version (RISCV64) + { + enum F_GETLK = 5; + enum F_SETLK = 6; + enum F_SETLKW = 7; + } else version (SystemZ) { static assert(off_t.sizeof == 8); diff --git a/libphobos/libdruntime/core/sys/windows/winsock2.d b/libphobos/libdruntime/core/sys/windows/winsock2.d index 55a45be85bf..8a4b1fda274 100644 --- a/libphobos/libdruntime/core/sys/windows/winsock2.d +++ b/libphobos/libdruntime/core/sys/windows/winsock2.d @@ -45,15 +45,15 @@ enum NI_MAXSERV = 32; @nogc { int WSAStartup(ushort wVersionRequested, LPWSADATA lpWSAData); -int WSACleanup(); -SOCKET socket(int af, int type, int protocol); +@trusted int WSACleanup(); +@trusted SOCKET socket(int af, int type, int protocol); int ioctlsocket(SOCKET s, int cmd, uint* argp); int bind(SOCKET s, const(sockaddr)* name, socklen_t namelen); int connect(SOCKET s, const(sockaddr)* name, socklen_t namelen); -int listen(SOCKET s, int backlog); +@trusted int listen(SOCKET s, int backlog); SOCKET accept(SOCKET s, sockaddr* addr, socklen_t* addrlen); -int closesocket(SOCKET s); -int shutdown(SOCKET s, int how); +@trusted int closesocket(SOCKET s); +@trusted int shutdown(SOCKET s, int how); int getpeername(SOCKET s, sockaddr* name, socklen_t* namelen); int getsockname(SOCKET s, sockaddr* name, socklen_t* namelen); int send(SOCKET s, const(void)* buf, int len, int flags); @@ -64,11 +64,11 @@ int getsockopt(SOCKET s, int level, int optname, void* optval, socklen_t* optlen int setsockopt(SOCKET s, int level, int optname, const(void)* optval, socklen_t optlen); uint inet_addr(const char* cp); int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, const(timeval)* timeout); -char* inet_ntoa(in_addr ina); +@trusted char* inet_ntoa(in_addr ina); hostent* gethostbyname(const char* name); hostent* gethostbyaddr(const(void)* addr, int len, int type); protoent* getprotobyname(const char* name); -protoent* getprotobynumber(int number); +@trusted protoent* getprotobynumber(int number); servent* getservbyname(const char* name, const char* proto); servent* getservbyport(int port, const char* proto); } diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d index ef073a93324..1165320f8f8 100644 --- a/libphobos/libdruntime/core/thread/osthread.d +++ b/libphobos/libdruntime/core/thread/osthread.d @@ -2104,7 +2104,7 @@ private extern (D) void resume(ThreadBase _t) nothrow @nogc * garbage collector on startup and before any other thread routines * are called. */ -extern (C) void thread_init() @nogc +extern (C) void thread_init() @nogc nothrow { // NOTE: If thread_init itself performs any allocations then the thread // routines reserved for garbage collector use may be called while @@ -2191,7 +2191,7 @@ package __gshared align(__traits(classInstanceAlignment, Thread)) MainThreadStor * Terminates the thread module. No other thread routine may be called * afterwards. */ -extern (C) void thread_term() @nogc +extern (C) void thread_term() @nogc nothrow { thread_term_tpl!(Thread)(_mainThreadStore); } diff --git a/libphobos/libdruntime/core/thread/threadbase.d b/libphobos/libdruntime/core/thread/threadbase.d index 217a33a0cf0..909bffc162b 100644 --- a/libphobos/libdruntime/core/thread/threadbase.d +++ b/libphobos/libdruntime/core/thread/threadbase.d @@ -569,14 +569,14 @@ package(core.thread): __gshared align(mutexAlign) void[mutexClassInstanceSize] _slock; __gshared align(mutexAlign) void[mutexClassInstanceSize] _criticalRegionLock; - static void initLocks() @nogc + static void initLocks() @nogc nothrow { import core.lifetime : emplace; emplace!Mutex(_slock[]); emplace!Mutex(_criticalRegionLock[]); } - static void termLocks() @nogc + static void termLocks() @nogc nothrow { (cast(Mutex)_slock.ptr).__dtor(); (cast(Mutex)_criticalRegionLock.ptr).__dtor(); @@ -756,13 +756,13 @@ package(core.thread): private alias attachThread = externDFunc!("core.thread.osthread.attachThread", ThreadBase function(ThreadBase) @nogc nothrow); -extern (C) void _d_monitordelete_nogc(Object h) @nogc; +extern (C) void _d_monitordelete_nogc(Object h) @nogc nothrow; /** * Terminates the thread module. No other thread routine may be called * afterwards. */ -package void thread_term_tpl(ThreadT, MainThreadStore)(ref MainThreadStore _mainThreadStore) @nogc +package void thread_term_tpl(ThreadT, MainThreadStore)(ref MainThreadStore _mainThreadStore) @nogc nothrow { assert(_mainThreadStore.ptr is cast(void*) ThreadBase.sm_main); @@ -1332,13 +1332,13 @@ package return cast(Mutex)ll_lock.ptr; } - void initLowlevelThreads() @nogc + void initLowlevelThreads() @nogc nothrow { import core.lifetime : emplace; emplace(lowlevelLock()); } - void termLowlevelThreads() @nogc + void termLowlevelThreads() @nogc nothrow { lowlevelLock.__dtor(); } diff --git a/libphobos/libdruntime/core/time.d b/libphobos/libdruntime/core/time.d index 91f218e27fb..9b8391e7207 100644 --- a/libphobos/libdruntime/core/time.d +++ b/libphobos/libdruntime/core/time.d @@ -2488,7 +2488,7 @@ private immutable long[__traits(allMembers, ClockType).length] _ticksPerSecond; // https://issues.dlang.org/show_bug.cgi?id=14863 // The assert will occur when someone attempts to use _ticksPerSecond for that // value. -extern(C) void _d_initMonoTime() +extern(C) void _d_initMonoTime() @nogc nothrow { // We need a mutable pointer to the ticksPerSecond array. Although this // would appear to break immutability, it is logically the same as a static @@ -3823,7 +3823,7 @@ unittest } version (Darwin) -long machTicksPerSecond() +long machTicksPerSecond() @nogc nothrow { // Be optimistic that ticksPerSecond (1e9*denom/numer) is integral. So far // so good on Darwin based platforms OS X, iOS. diff --git a/libphobos/libdruntime/core/vararg.d b/libphobos/libdruntime/core/vararg.d index 935b2bdb287..2c3e9659fb6 100644 --- a/libphobos/libdruntime/core/vararg.d +++ b/libphobos/libdruntime/core/vararg.d @@ -28,6 +28,8 @@ version (MIPS32) version = MIPS_Any; version (MIPS64) version = MIPS_Any; version (PPC) version = PPC_Any; version (PPC64) version = PPC_Any; +version (RISCV32) version = RISCV_Any; +version (RISCV64) version = RISCV_Any; version (ARM_Any) { @@ -136,6 +138,21 @@ void va_arg()(ref va_list ap, TypeInfo ti, void* parmn) ap += tsize.alignUp; parmn[0..tsize] = p[0..tsize]; } + else version (RISCV_Any) + { + const tsize = ti.tsize; + void* p; + if (tsize > (size_t.sizeof << 1)) + p = *cast(void**) ap; + else + { + if (tsize == (size_t.sizeof << 1)) + ap = ap.alignUp!(size_t.sizeof << 1); + p = cast(void*) ap; + } + ap += tsize.alignUp; + parmn[0..tsize] = p[0..tsize]; + } else static assert(0, "Unsupported platform"); } diff --git a/libphobos/libdruntime/rt/critical_.d b/libphobos/libdruntime/rt/critical_.d index ae181228b5c..36552a3ce1a 100644 --- a/libphobos/libdruntime/rt/critical_.d +++ b/libphobos/libdruntime/rt/critical_.d @@ -18,13 +18,13 @@ nothrow: import rt.monitor_, core.atomic; -extern (C) void _d_critical_init() +extern (C) void _d_critical_init() @nogc nothrow { initMutex(cast(Mutex*)&gcs.mtx); head = &gcs; } -extern (C) void _d_critical_term() +extern (C) void _d_critical_term() @nogc nothrow { // This function is only ever called by the runtime shutdown code // and therefore is single threaded so the following cast is fine. diff --git a/libphobos/libdruntime/rt/dmain2.d b/libphobos/libdruntime/rt/dmain2.d index 5ef26954890..0739b7451fd 100644 --- a/libphobos/libdruntime/rt/dmain2.d +++ b/libphobos/libdruntime/rt/dmain2.d @@ -62,22 +62,21 @@ struct UnitTestResult bool summarize; } -extern (C) void _d_monitor_staticctor(); -extern (C) void _d_monitor_staticdtor(); -extern (C) void _d_critical_init(); -extern (C) void _d_critical_term(); +extern (C) void _d_monitor_staticctor() @nogc nothrow; +extern (C) void _d_monitor_staticdtor() @nogc nothrow; +extern (C) void _d_critical_init() @nogc nothrow; +extern (C) void _d_critical_term() @nogc nothrow; extern (C) void gc_init(); extern (C) void gc_term(); -extern (C) void thread_init() @nogc; -extern (C) void thread_term() @nogc; -extern (C) void lifetime_init(); +extern (C) void thread_init() @nogc nothrow; +extern (C) void thread_term() @nogc nothrow; extern (C) void rt_moduleCtor(); extern (C) void rt_moduleTlsCtor(); extern (C) void rt_moduleDtor(); extern (C) void rt_moduleTlsDtor(); extern (C) void thread_joinAll(); extern (C) UnitTestResult runModuleUnitTests(); -extern (C) void _d_initMonoTime(); +extern (C) void _d_initMonoTime() @nogc nothrow; version (CRuntime_Microsoft) { @@ -134,7 +133,6 @@ extern (C) int rt_init() thread_init(); // TODO: fixme - calls GC.addRange -> Initializes GC initStaticDataGC(); - lifetime_init(); rt_moduleCtor(); rt_moduleTlsCtor(); return 1; diff --git a/libphobos/libdruntime/rt/lifetime.d b/libphobos/libdruntime/rt/lifetime.d index 5a18968f6ee..18ecc31311c 100644 --- a/libphobos/libdruntime/rt/lifetime.d +++ b/libphobos/libdruntime/rt/lifetime.d @@ -40,9 +40,11 @@ private } } -extern (C) void lifetime_init() +// Now-removed symbol, kept around for ABI +// Some programs are dynamically linked, so best to err on the side of keeping symbols around for a while (especially extern(C) ones) +// https://github.com/dlang/druntime/pull/3361 +deprecated extern (C) void lifetime_init() { - // this is run before static ctors, so it is safe to modify immutables } /** diff --git a/libphobos/libdruntime/rt/minfo.d b/libphobos/libdruntime/rt/minfo.d index 0d5cd22b1aa..74891506364 100644 --- a/libphobos/libdruntime/rt/minfo.d +++ b/libphobos/libdruntime/rt/minfo.d @@ -58,7 +58,7 @@ struct ModuleGroup // target modules are involved in a cycle. // // The return value is malloc'd using C, so it must be freed after use. - private size_t[] genCyclePath(size_t srcidx, size_t targetidx, int[][] edges) + private size_t[] genCyclePath(size_t srcidx, size_t targetidx, int[][] edges) nothrow { import core.bitop : bt, btc, bts; @@ -109,7 +109,7 @@ struct ModuleGroup // release mode. if (distance[target] != curdist) { - throw new Error("internal error printing module cycle"); + assert(0, "internal error printing module cycle"); } // determine the path. This is tricky, because we have to @@ -162,14 +162,13 @@ struct ModuleGroup * Throws: * Exception if it fails. */ - void sortCtors(string cycleHandling) + void sortCtors(string cycleHandling) nothrow { import core.bitop : bts, btr, bt, BitRange; import core.internal.container.hashtab; enum OnCycle { - deprecate, abort, print, ignore @@ -180,7 +179,9 @@ struct ModuleGroup switch (cycleHandling) with(OnCycle) { case "deprecate": - onCycle = deprecate; + import core.stdc.stdio : fprintf, stderr; + // Option deprecated in 2.101, remove in 2.111 + fprintf(stderr, "`--DRT-oncycle=deprecate` is no longer supported, using `abort` instead\n"); break; case "abort": onCycle = abort; @@ -196,7 +197,7 @@ struct ModuleGroup break; default: // invalid cycle handling option. - throw new Error("DRT invalid cycle handling option: " ~ cycleHandling); + assert(0, "DRT invalid cycle handling option: " ~ cycleHandling); } debug (printModuleDependencies) @@ -280,7 +281,7 @@ struct ModuleGroup .free(edges.ptr); } - void buildCycleMessage(size_t sourceIdx, size_t cycleIdx, scope void delegate(string) sink) + void buildCycleMessage(size_t sourceIdx, size_t cycleIdx, scope void delegate(string) nothrow sink) { version (Windows) enum EOL = "\r\n"; @@ -312,7 +313,7 @@ struct ModuleGroup // // If a cycle is detected, returns the index of the module that completes the cycle. // Returns: true for success, false for a deprecated cycle error - bool findDeps(size_t idx, size_t* reachable) + bool findDeps(size_t idx, size_t* reachable) nothrow { static struct stackFrame { @@ -356,14 +357,6 @@ struct ModuleGroup // was already started, this is a cycle. final switch (onCycle) with(OnCycle) { - case deprecate: - // check with old algorithm - if (sortCtorsOld(edges)) - { - // unwind to print deprecation message. - return false; // deprecated cycle error - } - goto case abort; // fall through case abort: string errmsg = ""; @@ -418,7 +411,7 @@ struct ModuleGroup // ctor/dtors that must be dealt with. It recurses only when it finds // dependencies that also have static ctor/dtors. // Returns: true for success, false for a deprecated cycle error - bool processMod(size_t curidx) + bool processMod(size_t curidx) nothrow { immutable ModuleInfo* current = _modules[curidx]; @@ -461,7 +454,7 @@ struct ModuleGroup } // returns `false` if deprecated cycle error otherwise set `result`. - bool doSort(size_t relevantFlags, ref immutable(ModuleInfo)*[] result) + bool doSort(size_t relevantFlags, ref immutable(ModuleInfo)*[] result) nothrow { clearFlags(relevant); clearFlags(ctorstart); @@ -533,193 +526,6 @@ struct ModuleGroup sortCtors(rt_configOption("oncycle")); } - /****************************** - * This is the old ctor sorting algorithm that does not find all cycles. - * - * It is here to allow the deprecated behavior from the original algorithm - * until people have fixed their code. - * - * If no cycles are found, the _ctors and _tlsctors are replaced with the - * ones generated by this algorithm to preserve the old incorrect ordering - * behavior. - * - * Params: - * edges = The module edges as found in the `importedModules` member of - * each ModuleInfo. Generated in sortCtors. - * Returns: - * true if no cycle is found, false if one was. - */ - bool sortCtorsOld(int[][] edges) - { - immutable len = edges.length; - assert(len == _modules.length); - - static struct StackRec - { - @property int mod() - { - return _mods[_idx]; - } - - int[] _mods; - size_t _idx; - } - - auto stack = (cast(StackRec*).calloc(len, StackRec.sizeof))[0 .. len]; - // TODO: reuse GCBits by moving it to core.internal.container - immutable nwords = (len + 8 * size_t.sizeof - 1) / (8 * size_t.sizeof); - auto ctorstart = cast(size_t*).malloc(nwords * size_t.sizeof); - auto ctordone = cast(size_t*).malloc(nwords * size_t.sizeof); - int[] initialEdges = (cast(int *)malloc(int.sizeof * len))[0 .. len]; - if (!stack.ptr || ctorstart is null || ctordone is null || !initialEdges.ptr) - assert(0); - scope (exit) - { - .free(stack.ptr); - .free(ctorstart); - .free(ctordone); - .free(initialEdges.ptr); - } - - // initialize the initial edges - foreach (i, ref v; initialEdges) - v = cast(int)i; - - bool sort(ref immutable(ModuleInfo)*[] ctors, uint mask) - { - import core.bitop; - - ctors = (cast(immutable(ModuleInfo)**).malloc(len * size_t.sizeof))[0 .. len]; - if (!ctors.ptr) - assert(0); - - // clean flags - memset(ctorstart, 0, nwords * size_t.sizeof); - memset(ctordone, 0, nwords * size_t.sizeof); - size_t stackidx = 0; - size_t cidx; - - int[] mods = initialEdges; - - size_t idx; - while (true) - { - while (idx < mods.length) - { - auto m = mods[idx]; - - if (bt(ctordone, m)) - { - // this module has already been processed, skip - ++idx; - continue; - } - else if (bt(ctorstart, m)) - { - /* Trace back to the begin of the cycle. - */ - bool ctorInCycle; - size_t start = stackidx; - while (start--) - { - auto sm = stack[start].mod; - if (sm == m) - break; - assert(sm >= 0); - if (bt(ctorstart, sm)) - ctorInCycle = true; - } - assert(stack[start].mod == m); - if (ctorInCycle) - { - return false; - } - else - { - /* This is also a cycle, but the import chain does not constrain - * the order of initialization, either because the imported - * modules have no ctors or the ctors are standalone. - */ - ++idx; - } - } - else - { - auto curmod = _modules[m]; - if (curmod.flags & mask) - { - if (curmod.flags & MIstandalone || !edges[m].length) - { // trivial ctor => sort in - ctors[cidx++] = curmod; - bts(ctordone, m); - } - else - { // non-trivial ctor => defer - bts(ctorstart, m); - } - } - else // no ctor => mark as visited - { - bts(ctordone, m); - } - - if (edges[m].length) - { - /* Internal runtime error, recursion exceeds number of modules. - */ - (stackidx < len) || assert(0); - - // recurse - stack[stackidx++] = StackRec(mods, idx); - idx = 0; - mods = edges[m]; - } - } - } - - if (stackidx) - { // pop old value from stack - --stackidx; - mods = stack[stackidx]._mods; - idx = stack[stackidx]._idx; - auto m = mods[idx++]; - if (bt(ctorstart, m) && !bts(ctordone, m)) - ctors[cidx++] = _modules[m]; - } - else // done - break; - } - // store final number and shrink array - ctors = (cast(immutable(ModuleInfo)**).realloc(ctors.ptr, cidx * size_t.sizeof))[0 .. cidx]; - return true; - } - - /* Do two passes: ctor/dtor, tlsctor/tlsdtor - */ - immutable(ModuleInfo)*[] _ctors2; - immutable(ModuleInfo)*[] _tlsctors2; - auto result = sort(_ctors2, MIctor | MIdtor) && sort(_tlsctors2, MItlsctor | MItlsdtor); - if (result) // no cycle - { - // fall back to original ordering as part of the deprecation. - if (_ctors.ptr) - .free(_ctors.ptr); - _ctors = _ctors2; - if (_tlsctors.ptr) - .free(_tlsctors.ptr); - _tlsctors = _tlsctors2; - } - else - { - // free any allocated memory that will be forgotten - if (_ctors2.ptr) - .free(_ctors2.ptr); - if (_tlsctors2.ptr) - .free(_tlsctors2.ptr); - } - return result; - } - void runCtors() { // run independent ctors diff --git a/libphobos/libdruntime/rt/monitor_.d b/libphobos/libdruntime/rt/monitor_.d index 0f1d0e97004..c1f3f3cb9a7 100644 --- a/libphobos/libdruntime/rt/monitor_.d +++ b/libphobos/libdruntime/rt/monitor_.d @@ -54,7 +54,7 @@ extern (C) void _d_monitordelete(Object h, bool det) } // does not call dispose events, for internal use only -extern (C) void _d_monitordelete_nogc(Object h) @nogc +extern (C) void _d_monitordelete_nogc(Object h) @nogc nothrow { auto m = getMonitor(h); if (m is null) @@ -148,7 +148,7 @@ extern (C) void rt_detachDisposeEvent(Object h, DEvent e) nothrow: -extern (C) void _d_monitor_staticctor() +extern (C) void _d_monitor_staticctor() @nogc nothrow { version (Posix) { @@ -158,7 +158,7 @@ extern (C) void _d_monitor_staticctor() initMutex(&gmtx); } -extern (C) void _d_monitor_staticdtor() +extern (C) void _d_monitor_staticdtor() @nogc nothrow { destroyMutex(&gmtx); version (Posix) diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE index 30e9e80092f..a4daa8419bf 100644 --- a/libphobos/src/MERGE +++ b/libphobos/src/MERGE @@ -1,4 +1,4 @@ -1206fc94f967b0183667a109049cbf596deaa696 +a4a18d21c4ea7930f80309f85e38c571c5f6d4b8 The first line of this file holds the git revision number of the last merge done from the dlang/phobos repository. diff --git a/libphobos/src/std/complex.d b/libphobos/src/std/complex.d index 485b548b049..6b1541a2532 100644 --- a/libphobos/src/std/complex.d +++ b/libphobos/src/std/complex.d @@ -935,7 +935,7 @@ Complex!(CommonType!(T, U)) fromPolar(T, U)(const T modulus, const U argument) import std.math.operations : isClose; import std.math.algebraic : sqrt; import std.math.constants : PI_4; - auto z = fromPolar(core.math.sqrt(2.0), PI_4); + auto z = fromPolar(core.math.sqrt(2.0L), PI_4); assert(isClose(z.re, 1.0L)); assert(isClose(z.im, 1.0L)); } diff --git a/libphobos/src/std/experimental/logger/core.d b/libphobos/src/std/experimental/logger/core.d index efc4ef7f74a..d899db70793 100644 --- a/libphobos/src/std/experimental/logger/core.d +++ b/libphobos/src/std/experimental/logger/core.d @@ -12,56 +12,6 @@ import std.traits; import std.experimental.logger.filelogger; -/** This template evaluates if the passed `LogLevel` is active. -The previously described version statements are used to decide if the -`LogLevel` is active. The version statements only influence the compile -unit they are used with, therefore this function can only disable logging this -specific compile unit. -*/ -template isLoggingActiveAt(LogLevel ll) -{ - version (StdLoggerDisableLogging) - { - enum isLoggingActiveAt = false; - } - else - { - static if (ll == LogLevel.trace) - { - version (StdLoggerDisableTrace) enum isLoggingActiveAt = false; - } - else static if (ll == LogLevel.info) - { - version (StdLoggerDisableInfo) enum isLoggingActiveAt = false; - } - else static if (ll == LogLevel.warning) - { - version (StdLoggerDisableWarning) enum isLoggingActiveAt = false; - } - else static if (ll == LogLevel.error) - { - version (StdLoggerDisableError) enum isLoggingActiveAt = false; - } - else static if (ll == LogLevel.critical) - { - version (StdLoggerDisableCritical) enum isLoggingActiveAt = false; - } - else static if (ll == LogLevel.fatal) - { - version (StdLoggerDisableFatal) enum isLoggingActiveAt = false; - } - // If `isLoggingActiveAt` didn't get defined above to false, - // we default it to true. - static if (!is(typeof(isLoggingActiveAt) == bool)) - { - enum isLoggingActiveAt = true; - } - } -} - -/// This compile-time flag is `true` if logging is not statically disabled. -enum isLoggingActive = isLoggingActiveAt!(LogLevel.all); - /** This functions is used at runtime to determine if a `LogLevel` is active. The same previously defined version statements are used to disable certain levels. Again the version statements are associated with a compile @@ -71,26 +21,6 @@ pure bool isLoggingEnabled()(LogLevel ll) @safe nothrow @nogc bool isLoggingEnabled()(LogLevel ll, LogLevel loggerLL, LogLevel globalLL, lazy bool condition = true) @safe { - switch (ll) - { - case LogLevel.trace: - version (StdLoggerDisableTrace) return false; - else break; - case LogLevel.info: - version (StdLoggerDisableInfo) return false; - else break; - case LogLevel.warning: - version (StdLoggerDisableWarning) return false; - else break; - case LogLevel.critical: - version (StdLoggerDisableCritical) return false; - else break; - case LogLevel.fatal: - version (StdLoggerDisableFatal) return false; - else break; - default: break; - } - return ll >= globalLL && ll >= loggerLL && ll != LogLevel.off @@ -99,66 +29,6 @@ bool isLoggingEnabled()(LogLevel ll, LogLevel loggerLL, && condition; } -/** This template returns the `LogLevel` named "logLevel" of type $(D -LogLevel) defined in a user defined module where the filename has the -suffix "_loggerconfig.d". This `LogLevel` sets the minimal `LogLevel` -of the module. - -A minimal `LogLevel` can be defined on a per module basis. -In order to define a module `LogLevel` a file with a modulename -"MODULENAME_loggerconfig" must be found. If no such module exists and the -module is a nested module, it is checked if there exists a -"PARENT_MODULE_loggerconfig" module with such a symbol. -If this module exists and it contains a `LogLevel` called logLevel this $(D -LogLevel) will be used. This parent lookup is continued until there is no -parent module. Then the moduleLogLevel is `LogLevel.all`. -*/ -template moduleLogLevel(string moduleName) -if (!moduleName.length) -{ - // default - enum moduleLogLevel = LogLevel.all; -} - -/// -@system unittest -{ - static assert(moduleLogLevel!"" == LogLevel.all); -} - -/// ditto -template moduleLogLevel(string moduleName) -if (moduleName.length) -{ - import std.string : format; - mixin(q{ - static if (__traits(compiles, {import %1$s : logLevel;})) - { - import %1$s : logLevel; - static assert(is(typeof(logLevel) : LogLevel), - "Expect 'logLevel' to be of Type 'LogLevel'."); - // don't enforce enum here - alias moduleLogLevel = logLevel; - } - else - // use logLevel of package or default - alias moduleLogLevel = moduleLogLevel!(parentOf(moduleName)); - }.format(moduleName ~ "_loggerconfig")); -} - -/// -@system unittest -{ - static assert(moduleLogLevel!"not.amodule.path" == LogLevel.all); -} - -private string parentOf(string mod) -{ - foreach_reverse (i, c; mod) - if (c == '.') return mod[0 .. i]; - return null; -} - /* This function formates a `SysTime` into an `OutputRange`. The `SysTime` is formatted similar to @@ -200,14 +70,8 @@ void log(int line = __LINE__, string file = __FILE__, lazy bool condition, lazy A args) if (args.length != 1) { - static if (isLoggingActive) - { - if (ll >= moduleLogLevel!moduleName) - { - stdThreadLocalLog.log!(line, file, funcName, prettyFuncName, moduleName) - (ll, condition, args); - } - } + stdThreadLocalLog.log!(line, file, funcName, prettyFuncName, moduleName) + (ll, condition, args); } /// Ditto @@ -215,14 +79,8 @@ void log(T, string moduleName = __MODULE__)(const LogLevel ll, lazy bool condition, lazy T arg, int line = __LINE__, string file = __FILE__, string funcName = __FUNCTION__, string prettyFuncName = __PRETTY_FUNCTION__) { - static if (isLoggingActive) - { - if (ll >= moduleLogLevel!moduleName) - { - stdThreadLocalLog.log!(T,moduleName)(ll, condition, arg, line, file, funcName, - prettyFuncName); - } - } + stdThreadLocalLog.log!(T,moduleName)(ll, condition, arg, line, file, funcName, + prettyFuncName); } /** This function logs data. @@ -244,14 +102,8 @@ void log(int line = __LINE__, string file = __FILE__, string moduleName = __MODULE__, A...)(const LogLevel ll, lazy A args) if (args.length > 1 && !is(Unqual!(A[0]) : bool)) { - static if (isLoggingActive) - { - if (ll >= moduleLogLevel!moduleName) - { - stdThreadLocalLog.log!(line, file, funcName, prettyFuncName, moduleName) - (ll, args); - } - } + stdThreadLocalLog.log!(line, file, funcName, prettyFuncName, moduleName) + (ll, args); } /// Ditto @@ -259,14 +111,8 @@ void log(T, string moduleName = __MODULE__)(const LogLevel ll, lazy T arg, int line = __LINE__, string file = __FILE__, string funcName = __FUNCTION__, string prettyFuncName = __PRETTY_FUNCTION__) { - static if (isLoggingActive) - { - if (ll >= moduleLogLevel!moduleName) - { - stdThreadLocalLog.log!T(ll, arg, line, file, funcName, prettyFuncName, - moduleName); - } - } + stdThreadLocalLog.log!T(ll, arg, line, file, funcName, prettyFuncName, + moduleName); } /** This function logs data. @@ -289,11 +135,8 @@ void log(int line = __LINE__, string file = __FILE__, string moduleName = __MODULE__, A...)(lazy bool condition, lazy A args) if (args.length != 1) { - static if (isLoggingActive) - { - stdThreadLocalLog.log!(line, file, funcName, prettyFuncName, moduleName) - (stdThreadLocalLog.logLevel, condition, args); - } + stdThreadLocalLog.log!(line, file, funcName, prettyFuncName, moduleName) + (stdThreadLocalLog.logLevel, condition, args); } /// Ditto @@ -301,11 +144,8 @@ void log(T, string moduleName = __MODULE__)(lazy bool condition, lazy T arg, int line = __LINE__, string file = __FILE__, string funcName = __FUNCTION__, string prettyFuncName = __PRETTY_FUNCTION__) { - static if (isLoggingActive) - { - stdThreadLocalLog.log!(T,moduleName)(stdThreadLocalLog.logLevel, - condition, arg, line, file, funcName, prettyFuncName); - } + stdThreadLocalLog.log!(T,moduleName)(stdThreadLocalLog.logLevel, + condition, arg, line, file, funcName, prettyFuncName); } /** This function logs data. @@ -328,22 +168,16 @@ if ((args.length > 1 && !is(Unqual!(A[0]) : bool) && !is(Unqual!(A[0]) == LogLevel)) || args.length == 0) { - static if (isLoggingActive) - { - stdThreadLocalLog.log!(line, file, funcName, - prettyFuncName, moduleName)(stdThreadLocalLog.logLevel, args); - } + stdThreadLocalLog.log!(line, file, funcName, + prettyFuncName, moduleName)(stdThreadLocalLog.logLevel, args); } void log(T)(lazy T arg, int line = __LINE__, string file = __FILE__, string funcName = __FUNCTION__, string prettyFuncName = __PRETTY_FUNCTION__, string moduleName = __MODULE__) { - static if (isLoggingActive) - { - stdThreadLocalLog.log!T(stdThreadLocalLog.logLevel, arg, line, file, - funcName, prettyFuncName, moduleName); - } + stdThreadLocalLog.log!T(stdThreadLocalLog.logLevel, arg, line, file, + funcName, prettyFuncName, moduleName); } /** This function logs data in a `printf`-style manner. @@ -369,14 +203,8 @@ void logf(int line = __LINE__, string file = __FILE__, string moduleName = __MODULE__, A...)(const LogLevel ll, lazy bool condition, lazy string msg, lazy A args) { - static if (isLoggingActive) - { - if (ll >= moduleLogLevel!moduleName) - { - stdThreadLocalLog.logf!(line, file, funcName, prettyFuncName, moduleName) - (ll, condition, msg, args); - } - } + stdThreadLocalLog.logf!(line, file, funcName, prettyFuncName, moduleName) + (ll, condition, msg, args); } /** This function logs data in a `printf`-style manner. @@ -400,14 +228,8 @@ void logf(int line = __LINE__, string file = __FILE__, string moduleName = __MODULE__, A...)(const LogLevel ll, lazy string msg, lazy A args) { - static if (isLoggingActive) - { - if (ll >= moduleLogLevel!moduleName) - { - stdThreadLocalLog.logf!(line, file, funcName, prettyFuncName, moduleName) - (ll, msg, args); - } - } + stdThreadLocalLog.logf!(line, file, funcName, prettyFuncName, moduleName) + (ll, msg, args); } /** This function logs data in a `printf`-style manner. @@ -431,11 +253,8 @@ void logf(int line = __LINE__, string file = __FILE__, string moduleName = __MODULE__, A...)(lazy bool condition, lazy string msg, lazy A args) { - static if (isLoggingActive) - { - stdThreadLocalLog.logf!(line, file, funcName, prettyFuncName, moduleName) - (stdThreadLocalLog.logLevel, condition, msg, args); - } + stdThreadLocalLog.logf!(line, file, funcName, prettyFuncName, moduleName) + (stdThreadLocalLog.logLevel, condition, msg, args); } /** This function logs data in a `printf`-style manner. @@ -457,11 +276,8 @@ void logf(int line = __LINE__, string file = __FILE__, string prettyFuncName = __PRETTY_FUNCTION__, string moduleName = __MODULE__, A...)(lazy string msg, lazy A args) { - static if (isLoggingActive) - { - stdThreadLocalLog.logf!(line, file, funcName,prettyFuncName, moduleName) - (stdThreadLocalLog.logLevel, msg, args); - } + stdThreadLocalLog.logf!(line, file, funcName,prettyFuncName, moduleName) + (stdThreadLocalLog.logLevel, msg, args); } /** This template provides the global log functions with the `LogLevel` @@ -478,11 +294,8 @@ template defaultLogFunction(LogLevel ll) string moduleName = __MODULE__, A...)(lazy A args) if ((args.length > 0 && !is(Unqual!(A[0]) : bool)) || args.length == 0) { - static if (isLoggingActiveAt!ll && ll >= moduleLogLevel!moduleName) - { stdThreadLocalLog.memLogFunctions!(ll).logImpl!(line, file, funcName, prettyFuncName, moduleName)(args); - } } void defaultLogFunction(int line = __LINE__, string file = __FILE__, @@ -490,11 +303,8 @@ template defaultLogFunction(LogLevel ll) string prettyFuncName = __PRETTY_FUNCTION__, string moduleName = __MODULE__, A...)(lazy bool condition, lazy A args) { - static if (isLoggingActiveAt!ll && ll >= moduleLogLevel!moduleName) - { - stdThreadLocalLog.memLogFunctions!(ll).logImpl!(line, file, funcName, - prettyFuncName, moduleName)(condition, args); - } + stdThreadLocalLog.memLogFunctions!(ll).logImpl!(line, file, funcName, + prettyFuncName, moduleName)(condition, args); } } @@ -551,11 +361,8 @@ template defaultLogFunctionf(LogLevel ll) string prettyFuncName = __PRETTY_FUNCTION__, string moduleName = __MODULE__, A...)(lazy string msg, lazy A args) { - static if (isLoggingActiveAt!ll && ll >= moduleLogLevel!moduleName) - { - stdThreadLocalLog.memLogFunctions!(ll).logImplf!(line, file, funcName, - prettyFuncName, moduleName)(msg, args); - } + stdThreadLocalLog.memLogFunctions!(ll).logImplf!(line, file, funcName, + prettyFuncName, moduleName)(msg, args); } void defaultLogFunctionf(int line = __LINE__, string file = __FILE__, @@ -564,11 +371,8 @@ template defaultLogFunctionf(LogLevel ll) string moduleName = __MODULE__, A...)(lazy bool condition, lazy string msg, lazy A args) { - static if (isLoggingActiveAt!ll && ll >= moduleLogLevel!moduleName) - { - stdThreadLocalLog.memLogFunctions!(ll).logImplf!(line, file, funcName, - prettyFuncName, moduleName)(condition, msg, args); - } + stdThreadLocalLog.memLogFunctions!(ll).logImplf!(line, file, funcName, + prettyFuncName, moduleName)(condition, msg, args); } } @@ -816,32 +620,23 @@ abstract class Logger Tid threadId, SysTime timestamp, Logger logger) @safe { - static if (isLoggingActive) - { - msgAppender = appender!string(); - header = LogEntry(file, line, funcName, prettyFuncName, - moduleName, logLevel, threadId, timestamp, null, logger); - } + msgAppender = appender!string(); + header = LogEntry(file, line, funcName, prettyFuncName, + moduleName, logLevel, threadId, timestamp, null, logger); } /** Logs a part of the log message. */ protected void logMsgPart(scope const(char)[] msg) @safe { - static if (isLoggingActive) - { - msgAppender.put(msg); - } + msgAppender.put(msg); } /** Signals that the message has been written and no more calls to `logMsgPart` follow. */ protected void finishLogMsg() @safe { - static if (isLoggingActive) - { - header.msg = msgAppender.data; - this.writeLogMsg(header); - } + header.msg = msgAppender.data; + this.writeLogMsg(header); } /** The `LogLevel` determines if the log call are processed or dropped @@ -895,16 +690,13 @@ abstract class Logger */ void forwardMsg(ref LogEntry payload) @trusted { - static if (isLoggingActive) synchronized (mutex) + if (isLoggingEnabled(payload.logLevel, this.logLevel_, + globalLogLevel)) { - if (isLoggingEnabled(payload.logLevel, this.logLevel_, - globalLogLevel)) - { - this.writeLogMsg(payload); + this.writeLogMsg(payload); - if (payload.logLevel == LogLevel.fatal) - this.fatalHandler_(); - } + if (payload.logLevel == LogLevel.fatal) + this.fatalHandler_(); } } @@ -944,8 +736,7 @@ abstract class Logger string moduleName = __MODULE__, A...)(lazy A args) if (args.length == 0 || (args.length > 0 && !is(A[0] : bool))) { - static if (isLoggingActiveAt!ll && ll >= moduleLogLevel!moduleName) - synchronized (mutex) + synchronized (mutex) { if (isLoggingEnabled(ll, this.logLevel_, globalLogLevel)) { @@ -991,8 +782,7 @@ abstract class Logger string moduleName = __MODULE__, A...)(lazy bool condition, lazy A args) { - static if (isLoggingActiveAt!ll && ll >= moduleLogLevel!moduleName) - synchronized (mutex) + synchronized (mutex) { if (isLoggingEnabled(ll, this.logLevel_, globalLogLevel, condition)) @@ -1040,8 +830,7 @@ abstract class Logger string moduleName = __MODULE__, A...)(lazy bool condition, lazy string msg, lazy A args) { - static if (isLoggingActiveAt!ll && ll >= moduleLogLevel!moduleName) - synchronized (mutex) + synchronized (mutex) { import std.format.write : formattedWrite; @@ -1088,8 +877,7 @@ abstract class Logger string prettyFuncName = __PRETTY_FUNCTION__, string moduleName = __MODULE__, A...)(lazy string msg, lazy A args) { - static if (isLoggingActiveAt!ll && ll >= moduleLogLevel!moduleName) - synchronized (mutex) + synchronized (mutex) { import std.format.write : formattedWrite; @@ -1161,7 +949,7 @@ abstract class Logger lazy bool condition, lazy A args) if (args.length != 1) { - static if (isLoggingActive) synchronized (mutex) + synchronized (mutex) { if (isLoggingEnabled(ll, this.logLevel_, globalLogLevel, condition)) { @@ -1185,10 +973,9 @@ abstract class Logger string file = __FILE__, string funcName = __FUNCTION__, string prettyFuncName = __PRETTY_FUNCTION__) { - static if (isLoggingActive) synchronized (mutex) + synchronized (mutex) { - if (isLoggingEnabled(ll, this.logLevel_, globalLogLevel, - condition) && ll >= moduleLogLevel!moduleName) + if (isLoggingEnabled(ll, this.logLevel_, globalLogLevel, condition)) { this.beginLogMsg(file, line, funcName, prettyFuncName, moduleName, ll, thisTid, Clock.currTime, this); @@ -1230,7 +1017,7 @@ abstract class Logger string moduleName = __MODULE__, A...)(const LogLevel ll, lazy A args) if ((args.length > 1 && !is(Unqual!(A[0]) : bool)) || args.length == 0) { - static if (isLoggingActive) synchronized (mutex) + synchronized (mutex) { if (isLoggingEnabled(ll, this.logLevel_, globalLogLevel)) { @@ -1254,7 +1041,7 @@ abstract class Logger string prettyFuncName = __PRETTY_FUNCTION__, string moduleName = __MODULE__) { - static if (isLoggingActive) synchronized (mutex) + synchronized (mutex) { if (isLoggingEnabled(ll, this.logLevel_, globalLogLevel)) { @@ -1299,7 +1086,7 @@ abstract class Logger string moduleName = __MODULE__, A...)(lazy bool condition, lazy A args) if (args.length != 1) { - static if (isLoggingActive) synchronized (mutex) + synchronized (mutex) { if (isLoggingEnabled(this.logLevel_, this.logLevel_, globalLogLevel, condition)) @@ -1324,7 +1111,7 @@ abstract class Logger string prettyFuncName = __PRETTY_FUNCTION__, string moduleName = __MODULE__) { - static if (isLoggingActive) synchronized (mutex) + synchronized (mutex) { if (isLoggingEnabled(this.logLevel_, this.logLevel_, globalLogLevel, condition)) @@ -1371,7 +1158,7 @@ abstract class Logger && !is(immutable A[0] == immutable LogLevel)) || args.length == 0) { - static if (isLoggingActive) synchronized (mutex) + synchronized (mutex) { if (isLoggingEnabled(this.logLevel_, this.logLevel_, globalLogLevel)) @@ -1395,7 +1182,7 @@ abstract class Logger string prettyFuncName = __PRETTY_FUNCTION__, string moduleName = __MODULE__) { - static if (isLoggingActive) synchronized (mutex) + synchronized (mutex) { if (isLoggingEnabled(this.logLevel_, this.logLevel_, globalLogLevel)) { @@ -1442,7 +1229,7 @@ abstract class Logger string moduleName = __MODULE__, A...)(const LogLevel ll, lazy bool condition, lazy string msg, lazy A args) { - static if (isLoggingActive) synchronized (mutex) + synchronized (mutex) { import std.format.write : formattedWrite; @@ -1490,7 +1277,7 @@ abstract class Logger string moduleName = __MODULE__, A...)(const LogLevel ll, lazy string msg, lazy A args) { - static if (isLoggingActive) synchronized (mutex) + synchronized (mutex) { import std.format.write : formattedWrite; @@ -1539,7 +1326,7 @@ abstract class Logger string moduleName = __MODULE__, A...)(lazy bool condition, lazy string msg, lazy A args) { - static if (isLoggingActive) synchronized (mutex) + synchronized (mutex) { import std.format.write : formattedWrite; @@ -1585,7 +1372,7 @@ abstract class Logger string prettyFuncName = __PRETTY_FUNCTION__, string moduleName = __MODULE__, A...)(lazy string msg, lazy A args) { - static if (isLoggingActive) synchronized (mutex) + synchronized (mutex) { import std.format.write : formattedWrite; diff --git a/libphobos/src/std/experimental/logger/package.d b/libphobos/src/std/experimental/logger/package.d index 79245ec4767..89dc7131fb3 100644 --- a/libphobos/src/std/experimental/logger/package.d +++ b/libphobos/src/std/experimental/logger/package.d @@ -146,26 +146,6 @@ To gain more precise control over the logging process, additionally to overriding the `writeLogMsg` method the methods `beginLogMsg`, `logMsgPart` and `finishLogMsg` can be overridden. -$(H3 Compile Time Disabling of `Logger`) -In order to disable logging at compile time, pass `StdLoggerDisableLogging` as a -version argument to the `D` compiler when compiling your program code. -This will disable all logging functionality. -Specific `LogLevel` can be disabled at compile time as well. -In order to disable logging with the `trace` `LogLevel` pass -`StdLoggerDisableTrace` as a version. -The following table shows which version statement disables which -`LogLevel`. -$(TABLE - $(TR $(TD `LogLevel.trace` ) $(TD StdLoggerDisableTrace)) - $(TR $(TD `LogLevel.info` ) $(TD StdLoggerDisableInfo)) - $(TR $(TD `LogLevel.warning` ) $(TD StdLoggerDisableWarning)) - $(TR $(TD `LogLevel.error` ) $(TD StdLoggerDisableError)) - $(TR $(TD `LogLevel.critical` ) $(TD StdLoggerDisableCritical)) - $(TR $(TD `LogLevel.fatal` ) $(TD StdLoggerDisableFatal)) -) -Such a version statement will only disable logging in the associated compile -unit. - $(H3 Provided Logger) By default four `Logger` implementations are given. The `FileLogger` logs data to files. It can also be used to log to `stdout` and `stderr` diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d index 6bc7d4d9113..05fad6724e0 100644 --- a/libphobos/src/std/file.d +++ b/libphobos/src/std/file.d @@ -3610,7 +3610,7 @@ version (StdDdoc) Throws: $(LREF FileException) if the file does not exist. +/ - this(string path); + this(return scope string path); version (Windows) { @@ -3772,7 +3772,7 @@ else version (Windows) public: alias name this; - this(string path) + this(return scope string path) { import std.datetime.systime : FILETIMEToSysTime; @@ -3881,7 +3881,7 @@ else version (Posix) public: alias name this; - this(string path) + this(return scope string path) { if (!path.exists) throw new FileException(path, "File does not exist"); @@ -4424,7 +4424,7 @@ void rmdirRecurse(scope const(char)[] pathname) @safe } /// ditto -void rmdirRecurse(ref DirEntry de) @safe +void rmdirRecurse(ref scope DirEntry de) @safe { if (!de.isDir) throw new FileException(de.name, "Not a directory"); @@ -4459,7 +4459,7 @@ void rmdirRecurse(ref DirEntry de) @safe //"rmdirRecurse(in char[] pathname)" implementation. That is needlessly //expensive. //A DirEntry is a bit big (72B), so keeping the "by ref" signature is desirable. -void rmdirRecurse(DirEntry de) @safe +void rmdirRecurse(scope DirEntry de) @safe { rmdirRecurse(de); } @@ -4511,22 +4511,20 @@ version (Posix) @system unittest enforce(!exists(deleteme)); } -@system unittest +@safe unittest { - void[] buf; - - buf = new void[10]; - (cast(byte[]) buf)[] = 3; + ubyte[] buf = new ubyte[10]; + buf[] = 3; string unit_file = deleteme ~ "-unittest_write.tmp"; if (exists(unit_file)) remove(unit_file); - write(unit_file, buf); + write(unit_file, cast(void[]) buf); void[] buf2 = read(unit_file); - assert(buf == buf2); + assert(cast(void[]) buf == buf2); string unit2_file = deleteme ~ "-unittest_write2.tmp"; copy(unit_file, unit2_file); buf2 = read(unit2_file); - assert(buf == buf2); + assert(cast(void[]) buf == buf2); remove(unit_file); assert(!exists(unit_file)); @@ -5042,7 +5040,7 @@ auto dirEntries(string path, string pattern, SpanMode mode, return filter!f(DirIterator(path, mode, followSymlink)); } -@system unittest +@safe unittest { import std.stdio : writefln; immutable dpath = deleteme ~ "_dir"; @@ -5059,11 +5057,11 @@ auto dirEntries(string path, string pattern, SpanMode mode, mkdir(dpath); write(fpath, "hello world"); - version (Posix) + version (Posix) () @trusted { core.sys.posix.unistd.symlink((dpath ~ '\0').ptr, (sdpath ~ '\0').ptr); core.sys.posix.unistd.symlink((fpath ~ '\0').ptr, (sfpath ~ '\0').ptr); - } + } (); static struct Flags { bool dir, file, link; } auto tests = [dpath : Flags(true), fpath : Flags(false, true)]; diff --git a/libphobos/src/std/math/algebraic.d b/libphobos/src/std/math/algebraic.d index db70b7a5552..4791766ab3a 100644 --- a/libphobos/src/std/math/algebraic.d +++ b/libphobos/src/std/math/algebraic.d @@ -496,9 +496,9 @@ if (isFloatingPoint!T) [ 1.0L, 4.0L, 8.0L, 9.0L ], [ 4.0L, 4.0L, 7.0L, 9.0L ], [ 12.0L, 16.0L, 21.0L, 29.0L ], - [ 1e+8L, 1.0L, 1e-8L, 1e+8L ], - [ 1.0L, 1e+8L, 1e-8L, 1e+8L ], - [ 1e-8L, 1.0L, 1e+8L, 1e+8L ], + [ 1e+8L, 1.0L, 1e-8L, 1e+8L+5e-9L ], + [ 1.0L, 1e+8L, 1e-8L, 1e+8L+5e-9L ], + [ 1e-8L, 1.0L, 1e+8L, 1e+8L+5e-9L ], [ 1e-2L, 1e-4L, 1e-4L, 0.010000999950004999375L ], [ 2147483647.0L, 2147483647.0L, 2147483647.0L, 3719550785.027307813987L ] ]; diff --git a/libphobos/src/std/math/hardware.d b/libphobos/src/std/math/hardware.d index 7bff07e86d4..40e42da74f9 100644 --- a/libphobos/src/std/math/hardware.d +++ b/libphobos/src/std/math/hardware.d @@ -674,9 +674,9 @@ nothrow @nogc: enum : ExceptionMask { inexactException = 0x01, - divByZeroException = 0x02, - underflowException = 0x04, - overflowException = 0x08, + divByZeroException = 0x08, + underflowException = 0x02, + overflowException = 0x04, invalidException = 0x10, severeExceptions = overflowException | divByZeroException | invalidException, diff --git a/libphobos/src/std/math/trigonometry.d b/libphobos/src/std/math/trigonometry.d index 06a7cb10b35..a3d04c60402 100644 --- a/libphobos/src/std/math/trigonometry.d +++ b/libphobos/src/std/math/trigonometry.d @@ -467,20 +467,20 @@ private T tanImpl(T)(T x) @safe pure nothrow @nogc static immutable T[2][] vals = [ // angle, tan - [ .5, .54630248984], - [ 1, 1.5574077247], - [ 1.5, 14.101419947], - [ 2, -2.1850398633], - [ 2.5,-.74702229724], - [ 3, -.14254654307], - [ 3.5, .37458564016], - [ 4, 1.1578212823], - [ 4.5, 4.6373320546], - [ 5, -3.3805150062], - [ 5.5,-.99558405221], - [ 6, -.29100619138], - [ 6.5, .22027720035], - [ 10, .64836082746], + [ .5, .546302489843790513255L], + [ 1, 1.55740772465490223050L], + [ 1.5, 14.1014199471717193876L], + [ 2, -2.18503986326151899164L], + [ 2.5,-.747022297238660279355L], + [ 3, -.142546543074277805295L], + [ 3.5, .374585640158594666330L], + [ 4, 1.15782128234957758313L], + [ 4.5, 4.63733205455118446831L], + [ 5, -3.38051500624658563698L], + [ 5.5,-.995584052213885017701L], + [ 6, -.291006191384749157053L], + [ 6.5, .220277200345896811825L], + [ 10, .648360827459086671259L], // special angles [ PI_4, 1], @@ -857,11 +857,11 @@ private T atanImpl(T)(T x) @safe pure nothrow @nogc static immutable T[2][] vals = [ // x, atan(x) - [ 0.25, 0.24497866313 ], - [ 0.5, 0.46364760900 ], - [ 1, PI_4 ], - [ 1.5, 0.98279372325 ], - [ 10, 1.47112767430 ], + [ 0.25, 0.244978663126864154172L ], + [ 0.5, 0.463647609000806116214L ], + [ 1, PI_4 ], + [ 1.5, 0.982793723247329067985L ], + [ 10, 1.471127674303734591852L ], ]; foreach (ref val; vals) @@ -1075,10 +1075,10 @@ private T atan2Impl(T)(T y, T x) @safe pure nothrow @nogc [ 3.0, -3.0, 3 * PI_4 ], [ -4.0, -4.0, -3 * PI_4 ], - [ 0.75, 0.25, 1.249045772398 ], - [ -0.5, 0.375, -0.927295218002 ], - [ 0.5, -0.125, 1.815774989922 ], - [ -0.75, -0.5, -2.158798930342 ], + [ 0.75, 0.25, 1.2490457723982544258299L ], + [ -0.5, 0.375, -0.9272952180016122324285L ], + [ 0.5, -0.125, 1.8157749899217607734034L ], + [ -0.75, -0.5, -2.1587989303424641704769L ], ]; foreach (ref val; vals) diff --git a/libphobos/src/std/numeric.d b/libphobos/src/std/numeric.d index fd532b2ce40..96d20c233d8 100644 --- a/libphobos/src/std/numeric.d +++ b/libphobos/src/std/numeric.d @@ -79,10 +79,12 @@ public enum CustomFloatFlags none = 0 } +private enum isIEEEQuadruple = floatTraits!real.realFormat == RealFormat.ieeeQuadruple; + private template CustomFloatParams(uint bits) { enum CustomFloatFlags flags = CustomFloatFlags.ieee - ^ ((bits == 80) ? CustomFloatFlags.storeNormalized : CustomFloatFlags.none); + ^ ((bits == 80 && !isIEEEQuadruple) ? CustomFloatFlags.storeNormalized : CustomFloatFlags.none); static if (bits == 8) alias CustomFloatParams = CustomFloatParams!( 4, 3, flags); static if (bits == 16) alias CustomFloatParams = CustomFloatParams!(10, 5, flags); static if (bits == 32) alias CustomFloatParams = CustomFloatParams!(23, 8, flags); @@ -367,11 +369,36 @@ private: public: static if (precision == 64) // CustomFloat!80 support hack { - ulong significand; - enum ulong significand_max = ulong.max; - mixin(bitfields!( - T_exp , "exponent", exponentWidth, - bool , "sign" , flags & flags.signed )); + static if (isIEEEQuadruple) + { + // Only use highest 64 significand bits from 112 explicitly stored + align (1): + enum ulong significand_max = ulong.max; + version (LittleEndian) + { + private ubyte[6] _padding; // 48-bit of padding + ulong significand; + mixin(bitfields!( + T_exp , "exponent", exponentWidth, + bool , "sign" , flags & flags.signed )); + } + else + { + mixin(bitfields!( + T_exp , "exponent", exponentWidth, + bool , "sign" , flags & flags.signed )); + ulong significand; + private ubyte[6] _padding; // 48-bit of padding + } + } + else + { + ulong significand; + enum ulong significand_max = ulong.max; + mixin(bitfields!( + T_exp , "exponent", exponentWidth, + bool , "sign" , flags & flags.signed )); + } } else { @@ -631,23 +658,28 @@ public: auto x = F(0.125); assert(x.get!float == 0.125F); assert(x.get!double == 0.125); + assert(x.get!real == 0.125L); x -= 0.0625; assert(x.get!float == 0.0625F); assert(x.get!double == 0.0625); + assert(x.get!real == 0.0625L); x *= 2; assert(x.get!float == 0.125F); assert(x.get!double == 0.125); + assert(x.get!real == 0.125L); x /= 4; assert(x.get!float == 0.03125); assert(x.get!double == 0.03125); + assert(x.get!real == 0.03125L); x = 0.5; x ^^= 4; assert(x.get!float == 1 / 16.0F); assert(x.get!double == 1 / 16.0); + assert(x.get!real == 1 / 16.0L); } } diff --git a/libphobos/src/std/stdio.d b/libphobos/src/std/stdio.d index 1bde73d628d..8614dc96901 100644 --- a/libphobos/src/std/stdio.d +++ b/libphobos/src/std/stdio.d @@ -498,17 +498,21 @@ struct File private Impl* _p; private string _name; - package this(FILE* handle, string name, uint refs = 1, bool isPopened = false) @trusted + package this(FILE* handle, string name, uint refs = 1, bool isPopened = false) @trusted @nogc nothrow { import core.stdc.stdlib : malloc; - import std.exception : enforce; assert(!_p); - _p = cast(Impl*) enforce(malloc(Impl.sizeof), "Out of memory"); + _p = cast(Impl*) malloc(Impl.sizeof); + if (!_p) + { + import core.exception : onOutOfMemoryError; + onOutOfMemoryError(); + } initImpl(handle, name, refs, isPopened); } - private void initImpl(FILE* handle, string name, uint refs = 1, bool isPopened = false) + private void initImpl(FILE* handle, string name, uint refs = 1, bool isPopened = false) @nogc nothrow pure @safe { assert(_p); _p.handle = handle; diff --git a/libphobos/src/std/sumtype.d b/libphobos/src/std/sumtype.d index f3d3152b347..1d375ef4d7e 100644 --- a/libphobos/src/std/sumtype.d +++ b/libphobos/src/std/sumtype.d @@ -635,9 +635,19 @@ public: this.match!destroyIfOwner; - mixin("Storage newStorage = { ", - Storage.memberName!T, ": forward!rhs", - " };"); + static if (isCopyable!T) + { + // Workaround for https://issues.dlang.org/show_bug.cgi?id=21542 + mixin("Storage newStorage = { ", + Storage.memberName!T, ": __ctfe ? rhs : forward!rhs", + " };"); + } + else + { + mixin("Storage newStorage = { ", + Storage.memberName!T, ": forward!rhs", + " };"); + } storage = newStorage; tag = tid; @@ -678,7 +688,17 @@ public: { import core.lifetime : move; - rhs.match!((ref value) { this = move(value); }); + rhs.match!((ref value) { + static if (isCopyable!(typeof(value))) + { + // Workaround for https://issues.dlang.org/show_bug.cgi?id=21542 + this = __ctfe ? value : move(value); + } + else + { + this = move(value); + } + }); return this; } } @@ -1569,6 +1589,28 @@ version (D_BetterC) {} else } } +// Assignment of struct with overloaded opAssign in CTFE +// https://issues.dlang.org/show_bug.cgi?id=23182 +@safe unittest +{ + static struct HasOpAssign + { + void opAssign(HasOpAssign rhs) {} + } + + static SumType!HasOpAssign test() + { + SumType!HasOpAssign s; + // Test both overloads + s = HasOpAssign(); + s = SumType!HasOpAssign(); + return s; + } + + // Force CTFE + enum result = test(); +} + /// True if `T` is an instance of the `SumType` template, otherwise false. private enum bool isSumTypeInstance(T) = is(T == SumType!Args, Args...); diff --git a/libphobos/testsuite/libphobos.cycles/cycles.exp b/libphobos/testsuite/libphobos.cycles/cycles.exp index 80bdf0e85c9..fa3dfd4819a 100644 --- a/libphobos/testsuite/libphobos.cycles/cycles.exp +++ b/libphobos/testsuite/libphobos.cycles/cycles.exp @@ -23,7 +23,7 @@ set cycle_test_list [list \ { ignore "" 0 } \ { abort "object.Error@.*: Cyclic dependency between module mod. and mod." 1 } \ { print "Cyclic dependency between module mod. and mod." 0 } \ - { deprecate "Deprecation 16211 warning:" 0 } \ + { deprecate "deprecate is no longer supported, using abort instead" 1 } \ ] # Initialize dg.