From 8f02a0574d7a47fe8637153cdb9ff8db064354fe Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 1 Jan 2023 08:29:17 +0100 Subject: [PATCH 001/177] Update copyright years of dmd sources to 2023 --- dmd/access.d | 2 +- dmd/aggregate.d | 2 +- dmd/aggregate.h | 2 +- dmd/aliasthis.d | 2 +- dmd/aliasthis.h | 2 +- dmd/apply.d | 2 +- dmd/argtypes_aarch64.d | 2 +- dmd/argtypes_sysv_x64.d | 2 +- dmd/argtypes_x86.d | 2 +- dmd/arrayop.d | 2 +- dmd/arraytypes.d | 2 +- dmd/arraytypes.h | 2 +- dmd/ast_node.d | 2 +- dmd/ast_node.h | 2 +- dmd/astenums.d | 2 +- dmd/asttypename.d | 2 +- dmd/attrib.d | 2 +- dmd/attrib.h | 2 +- dmd/blockexit.d | 2 +- dmd/builtin.d | 2 +- dmd/canthrow.d | 2 +- dmd/chkformat.d | 2 +- dmd/cli.d | 2 +- dmd/clone.d | 2 +- dmd/common/bitfields.d | 2 +- dmd/common/file.d | 2 +- dmd/common/outbuffer.d | 2 +- dmd/common/outbuffer.h | 2 +- dmd/common/string.d | 2 +- dmd/compiler.d | 2 +- dmd/compiler.h | 2 +- dmd/cond.d | 2 +- dmd/cond.h | 2 +- dmd/console.d | 2 +- dmd/constfold.d | 2 +- dmd/cparse.d | 2 +- dmd/cppmangle.d | 2 +- dmd/cppmanglewin.d | 2 +- dmd/ctfe.h | 2 +- dmd/ctfeexpr.d | 2 +- dmd/ctorflow.d | 2 +- dmd/dcast.d | 2 +- dmd/dclass.d | 2 +- dmd/declaration.d | 2 +- dmd/declaration.h | 2 +- dmd/delegatize.d | 2 +- dmd/denum.d | 2 +- dmd/dimport.d | 2 +- dmd/dinterpret.d | 2 +- dmd/dmacro.d | 2 +- dmd/dmangle.d | 2 +- dmd/dmodule.d | 2 +- dmd/doc.d | 2 +- dmd/doc.h | 2 +- dmd/dscope.d | 2 +- dmd/dstruct.d | 2 +- dmd/dsymbol.d | 2 +- dmd/dsymbol.h | 2 +- dmd/dsymbolsem.d | 2 +- dmd/dtemplate.d | 2 +- dmd/dtoh.d | 2 +- dmd/dversion.d | 2 +- dmd/entity.d | 2 +- dmd/enum.h | 2 +- dmd/errors.d | 2 +- dmd/errors.h | 2 +- dmd/escape.d | 2 +- dmd/expression.d | 2 +- dmd/expression.h | 2 +- dmd/expressionsem.d | 2 +- dmd/file_manager.d | 2 +- dmd/foreachvar.d | 2 +- dmd/frontend.h | 4 ++-- dmd/func.d | 2 +- dmd/globals.d | 4 ++-- dmd/globals.h | 2 +- dmd/gluelayer.d | 2 +- dmd/hdrgen.d | 2 +- dmd/hdrgen.h | 2 +- dmd/iasmgcc.d | 2 +- dmd/id.d | 2 +- dmd/id.h | 2 +- dmd/identifier.d | 2 +- dmd/identifier.h | 2 +- dmd/impcnvtab.d | 2 +- dmd/imphint.d | 2 +- dmd/import.h | 2 +- dmd/importc.d | 2 +- dmd/init.d | 2 +- dmd/init.h | 2 +- dmd/initsem.d | 2 +- dmd/inline.d | 2 +- dmd/inlinecost.d | 2 +- dmd/intrange.d | 2 +- dmd/json.d | 2 +- dmd/json.h | 2 +- dmd/lambdacomp.d | 2 +- dmd/lexer.d | 2 +- dmd/location.d | 2 +- dmd/mangle.h | 2 +- dmd/mars.d | 2 +- dmd/module.h | 2 +- dmd/mtype.d | 2 +- dmd/mtype.h | 2 +- dmd/mustuse.d | 2 +- dmd/nogc.d | 2 +- dmd/nspace.d | 2 +- dmd/nspace.h | 2 +- dmd/ob.d | 2 +- dmd/objc.d | 2 +- dmd/objc.h | 2 +- dmd/opover.d | 2 +- dmd/optimize.d | 2 +- dmd/parse.d | 2 +- dmd/printast.d | 2 +- dmd/root/aav.d | 2 +- dmd/root/array.d | 2 +- dmd/root/array.h | 2 +- dmd/root/bitarray.d | 2 +- dmd/root/bitarray.h | 2 +- dmd/root/complex.d | 2 +- dmd/root/complex_t.h | 2 +- dmd/root/ctfloat.d | 2 +- dmd/root/ctfloat.h | 2 +- dmd/root/dcompat.h | 2 +- dmd/root/dsystem.h | 2 +- dmd/root/file.d | 2 +- dmd/root/filename.d | 2 +- dmd/root/filename.h | 2 +- dmd/root/hash.d | 2 +- dmd/root/longdouble.d | 2 +- dmd/root/longdouble.h | 2 +- dmd/root/man.d | 2 +- dmd/root/object.h | 2 +- dmd/root/optional.d | 2 +- dmd/root/optional.h | 2 +- dmd/root/port.d | 2 +- dmd/root/port.h | 2 +- dmd/root/region.d | 2 +- dmd/root/rmem.d | 2 +- dmd/root/rmem.h | 2 +- dmd/root/rootobject.d | 2 +- dmd/root/speller.d | 2 +- dmd/root/string.d | 2 +- dmd/root/stringtable.d | 2 +- dmd/root/utf.d | 2 +- dmd/safe.d | 2 +- dmd/sapply.d | 2 +- dmd/scope.h | 2 +- dmd/semantic2.d | 2 +- dmd/semantic3.d | 2 +- dmd/sideeffect.d | 2 +- dmd/statement.d | 2 +- dmd/statement.h | 2 +- dmd/statement_rewrite_walker.d | 2 +- dmd/statementsem.d | 2 +- dmd/staticassert.d | 2 +- dmd/staticassert.h | 2 +- dmd/staticcond.d | 2 +- dmd/stmtstate.d | 2 +- dmd/target.d | 2 +- dmd/target.h | 2 +- dmd/template.h | 2 +- dmd/templateparamsem.d | 2 +- dmd/tokens.d | 2 +- dmd/tokens.h | 2 +- dmd/traits.d | 2 +- dmd/typesem.d | 2 +- dmd/typinf.d | 2 +- dmd/utils.d | 2 +- dmd/version.h | 2 +- dmd/visitor.d | 2 +- dmd/visitor.h | 2 +- dmd/vsoptions.d | 2 +- dmd/vsoptions.h | 2 +- 175 files changed, 177 insertions(+), 177 deletions(-) diff --git a/dmd/access.d b/dmd/access.d index 462afbfae1b..f2d68d53d75 100644 --- a/dmd/access.d +++ b/dmd/access.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/attribute.html#visibility_attributes, Visibility Attributes) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/access.d, _access.d) diff --git a/dmd/aggregate.d b/dmd/aggregate.d index 77321606349..1306a104fff 100644 --- a/dmd/aggregate.d +++ b/dmd/aggregate.d @@ -4,7 +4,7 @@ * Specification: $(LINK2 https://dlang.org/spec/struct.html, Structs, Unions), * $(LINK2 https://dlang.org/spec/class.html, Class). * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/aggregate.d, _aggregate.d) diff --git a/dmd/aggregate.h b/dmd/aggregate.h index dfbfb2de6f8..9f9098f7f2b 100644 --- a/dmd/aggregate.h +++ b/dmd/aggregate.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/aliasthis.d b/dmd/aliasthis.d index 5f428cc7ecf..ef839fae536 100644 --- a/dmd/aliasthis.d +++ b/dmd/aliasthis.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/class.html#alias-this, Alias This) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/aliasthis.d, _aliasthis.d) diff --git a/dmd/aliasthis.h b/dmd/aliasthis.h index c63d717a7bd..389cff40054 100644 --- a/dmd/aliasthis.h +++ b/dmd/aliasthis.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 2009-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 2009-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/apply.d b/dmd/apply.d index 3b73771ef22..f5855c4758a 100644 --- a/dmd/apply.d +++ b/dmd/apply.d @@ -1,7 +1,7 @@ /** * A depth-first visitor for expressions. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/apply.d, _apply.d) diff --git a/dmd/argtypes_aarch64.d b/dmd/argtypes_aarch64.d index 83ee3f329e0..6fbf3ee8bef 100644 --- a/dmd/argtypes_aarch64.d +++ b/dmd/argtypes_aarch64.d @@ -1,7 +1,7 @@ /** * Break down a D type into basic (register) types for the AArch64 ABI. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Martin Kinkelin * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/argtypes_aarch64.d, _argtypes_aarch64.d) diff --git a/dmd/argtypes_sysv_x64.d b/dmd/argtypes_sysv_x64.d index 8a2cf6d7427..da8bc8d22cf 100644 --- a/dmd/argtypes_sysv_x64.d +++ b/dmd/argtypes_sysv_x64.d @@ -1,7 +1,7 @@ /** * Break down a D type into basic (register) types for the x86_64 System V ABI. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Martin Kinkelin * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/argtypes_sysv_x64.d, _argtypes_sysv_x64.d) diff --git a/dmd/argtypes_x86.d b/dmd/argtypes_x86.d index a8e7b9880d5..6dc2c8deeff 100644 --- a/dmd/argtypes_x86.d +++ b/dmd/argtypes_x86.d @@ -1,7 +1,7 @@ /** * Break down a D type into basic (register) types for the 32-bit x86 ABI. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/argtypes_x86.d, _argtypes_x86.d) diff --git a/dmd/arrayop.d b/dmd/arrayop.d index 6bacb8b6fd7..da2f8000fc1 100644 --- a/dmd/arrayop.d +++ b/dmd/arrayop.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/arrays.html#array-operations, Array Operations) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/arrayop.d, _arrayop.d) diff --git a/dmd/arraytypes.d b/dmd/arraytypes.d index 29b3a3ddc33..34ffa6eb8fd 100644 --- a/dmd/arraytypes.d +++ b/dmd/arraytypes.d @@ -1,7 +1,7 @@ /** * Provide aliases for arrays of certain declarations or statements. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/arraytypes.d, _arraytypes.d) diff --git a/dmd/arraytypes.h b/dmd/arraytypes.h index ca2051cf5f4..05126a53d7e 100644 --- a/dmd/arraytypes.h +++ b/dmd/arraytypes.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 2006-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 2006-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/ast_node.d b/dmd/ast_node.d index 843cc023735..c0dd186628a 100644 --- a/dmd/ast_node.d +++ b/dmd/ast_node.d @@ -1,7 +1,7 @@ /** * Defines the base class for all nodes which are part of the AST. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ast_node.d, _ast_node.d) diff --git a/dmd/ast_node.h b/dmd/ast_node.h index 0e04e38f728..6154c6d1b3a 100644 --- a/dmd/ast_node.h +++ b/dmd/ast_node.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/astenums.d b/dmd/astenums.d index 091e96a82c1..6e882082bed 100644 --- a/dmd/astenums.d +++ b/dmd/astenums.d @@ -1,7 +1,7 @@ /** * Defines enums common to dmd and dmd as parse library. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/astenums.d, _astenums.d) * Documentation: https://dlang.org/phobos/dmd_astenums.html diff --git a/dmd/asttypename.d b/dmd/asttypename.d index 182239a8e46..53cde6ea284 100644 --- a/dmd/asttypename.d +++ b/dmd/asttypename.d @@ -1,7 +1,7 @@ /** * Development utility for printing AST nodes by their internal name, instead of as D source code. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Stefan Koch * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/asttypename.d, _asttypename.d) diff --git a/dmd/attrib.d b/dmd/attrib.d index 8f4d7a7e850..712099ed333 100644 --- a/dmd/attrib.d +++ b/dmd/attrib.d @@ -14,7 +14,7 @@ * - Protection (`private`, `public`) * - Deprecated declarations (`@deprecated`) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/attrib.d, _attrib.d) diff --git a/dmd/attrib.h b/dmd/attrib.h index b153229ccaa..96c46e8f718 100644 --- a/dmd/attrib.h +++ b/dmd/attrib.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/blockexit.d b/dmd/blockexit.d index 86a668e1d64..6369b5ab04b 100644 --- a/dmd/blockexit.d +++ b/dmd/blockexit.d @@ -1,7 +1,7 @@ /** * Find out in what ways control flow can exit a statement block. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/blockexit.d, _blockexit.d) diff --git a/dmd/builtin.d b/dmd/builtin.d index 989335d77e3..1736a485281 100644 --- a/dmd/builtin.d +++ b/dmd/builtin.d @@ -3,7 +3,7 @@ * * Currently includes functions from `std.math`, `core.math` and `core.bitop`. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/builtin.d, _builtin.d) diff --git a/dmd/canthrow.d b/dmd/canthrow.d index cb9289fd773..7c18040eb02 100644 --- a/dmd/canthrow.d +++ b/dmd/canthrow.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/function.html#nothrow-functions, Nothrow Functions) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/canthrow.d, _canthrow.d) diff --git a/dmd/chkformat.d b/dmd/chkformat.d index fc7a7b8b91e..21a1b5e6def 100644 --- a/dmd/chkformat.d +++ b/dmd/chkformat.d @@ -1,7 +1,7 @@ /** * Check the arguments to `printf` and `scanf` against the `format` string. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/chkformat.d, _chkformat.d) diff --git a/dmd/cli.d b/dmd/cli.d index 788f438be54..de1f26534d7 100644 --- a/dmd/cli.d +++ b/dmd/cli.d @@ -5,7 +5,7 @@ * However, this file will be used to generate the * $(LINK2 https://dlang.org/dmd-linux.html, online documentation) and MAN pages. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cli.d, _cli.d) diff --git a/dmd/clone.d b/dmd/clone.d index d4338cfdca4..ef5464d75e0 100644 --- a/dmd/clone.d +++ b/dmd/clone.d @@ -2,7 +2,7 @@ * Builds struct member functions if needed and not defined by the user. * Includes `opEquals`, `opAssign`, post blit, copy constructor and destructor. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/clone.d, _clone.d) diff --git a/dmd/common/bitfields.d b/dmd/common/bitfields.d index bba61ad3715..b9fcb0995c9 100644 --- a/dmd/common/bitfields.d +++ b/dmd/common/bitfields.d @@ -1,7 +1,7 @@ /** * A library bitfields utility * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Dennis Korpel * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/bitfields.d, common/bitfields.d) diff --git a/dmd/common/file.d b/dmd/common/file.d index 89e702703e6..ae13c41d310 100644 --- a/dmd/common/file.d +++ b/dmd/common/file.d @@ -4,7 +4,7 @@ * Functions and objects dedicated to file I/O and management. TODO: Move here artifacts * from places such as root/ so both the frontend and the backend have access to them. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/file.d, common/_file.d) diff --git a/dmd/common/outbuffer.d b/dmd/common/outbuffer.d index 9d544a400fe..276928a6bd8 100644 --- a/dmd/common/outbuffer.d +++ b/dmd/common/outbuffer.d @@ -1,7 +1,7 @@ /** * An expandable buffer in which you can write text or binary data. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/outbuffer.d, root/_outbuffer.d) diff --git a/dmd/common/outbuffer.h b/dmd/common/outbuffer.h index fed25c0d030..b672842e74d 100644 --- a/dmd/common/outbuffer.h +++ b/dmd/common/outbuffer.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/common/string.d b/dmd/common/string.d index 48bf9bb5b55..1111cec2cf1 100644 --- a/dmd/common/string.d +++ b/dmd/common/string.d @@ -1,7 +1,7 @@ /** * Common string functions including filename manipulation. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/string.d, common/_string.d) diff --git a/dmd/compiler.d b/dmd/compiler.d index f428427763e..a0a1732047d 100644 --- a/dmd/compiler.d +++ b/dmd/compiler.d @@ -1,7 +1,7 @@ /** * Describes a back-end compiler and implements compiler-specific actions. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/compiler.d, _compiler.d) diff --git a/dmd/compiler.h b/dmd/compiler.h index e8b7704b043..c7cbce3bd7f 100644 --- a/dmd/compiler.h +++ b/dmd/compiler.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/cond.d b/dmd/cond.d index 66cfb50bab2..c0c4cf1ce82 100644 --- a/dmd/cond.d +++ b/dmd/cond.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/version.html, Conditional Compilation) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cond.d, _cond.d) diff --git a/dmd/cond.h b/dmd/cond.h index b33f288f9df..422a715bdba 100644 --- a/dmd/cond.h +++ b/dmd/cond.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/console.d b/dmd/console.d index d3dd4f23c5c..38af8c0d0b8 100644 --- a/dmd/console.d +++ b/dmd/console.d @@ -2,7 +2,7 @@ * Control the various text mode attributes, such as color, when writing text * to the console. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/console.d, _console.d) diff --git a/dmd/constfold.d b/dmd/constfold.d index fde9c38079a..79bbd5dead5 100644 --- a/dmd/constfold.d +++ b/dmd/constfold.d @@ -5,7 +5,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/float.html#fp_const_folding, Floating Point Constant Folding) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/constfold.d, _constfold.d) diff --git a/dmd/cparse.d b/dmd/cparse.d index 3cffde1f0c0..a6bc42b1014 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -3,7 +3,7 @@ * * Specification: C11 * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cparse.d, _cparse.d) diff --git a/dmd/cppmangle.d b/dmd/cppmangle.d index 0dfa1e14eb6..d3effa99ddd 100644 --- a/dmd/cppmangle.d +++ b/dmd/cppmangle.d @@ -4,7 +4,7 @@ * This is the POSIX side of the implementation. * It exports two functions to C++, `toCppMangleItanium` and `cppTypeInfoMangleItanium`. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cppmangle.d, _cppmangle.d) diff --git a/dmd/cppmanglewin.d b/dmd/cppmanglewin.d index ac9379d2f01..ba8c6646e09 100644 --- a/dmd/cppmanglewin.d +++ b/dmd/cppmanglewin.d @@ -1,7 +1,7 @@ /** * Do mangling for C++ linkage for Digital Mars C++ and Microsoft Visual C++. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cppmanglewin.d, _cppmanglewin.d) diff --git a/dmd/ctfe.h b/dmd/ctfe.h index ab022ff505e..1071edf7c93 100644 --- a/dmd/ctfe.h +++ b/dmd/ctfe.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/ctfeexpr.d b/dmd/ctfeexpr.d index db15d6d0229..c902149e2b5 100644 --- a/dmd/ctfeexpr.d +++ b/dmd/ctfeexpr.d @@ -1,7 +1,7 @@ /** * CTFE for expressions involving pointers, slices, array concatenation etc. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ctfeexpr.d, _ctfeexpr.d) diff --git a/dmd/ctorflow.d b/dmd/ctorflow.d index 0e654373792..a3953af6ce8 100644 --- a/dmd/ctorflow.d +++ b/dmd/ctorflow.d @@ -1,7 +1,7 @@ /** * Manage flow analysis for constructors. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ctorflow.d, _ctorflow.d) diff --git a/dmd/dcast.d b/dmd/dcast.d index 997e947bc36..b305360a3ab 100644 --- a/dmd/dcast.d +++ b/dmd/dcast.d @@ -1,7 +1,7 @@ /** * Semantic analysis for cast-expressions. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dcast.d, _dcast.d) diff --git a/dmd/dclass.d b/dmd/dclass.d index 171f93e323a..1fdd0730fcf 100644 --- a/dmd/dclass.d +++ b/dmd/dclass.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/class.html, Classes) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dclass.d, _dclass.d) diff --git a/dmd/declaration.d b/dmd/declaration.d index 1ff32c94a62..51737cef2c6 100644 --- a/dmd/declaration.d +++ b/dmd/declaration.d @@ -2,7 +2,7 @@ * Miscellaneous declarations, including typedef, alias, variable declarations including the * implicit this declaration, type tuples, ClassInfo, ModuleInfo and various TypeInfos. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/declaration.d, _declaration.d) diff --git a/dmd/declaration.h b/dmd/declaration.h index 2668b6ec05e..5d5c4234b74 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/delegatize.d b/dmd/delegatize.d index 9efe26aea83..3f982b3faf7 100644 --- a/dmd/delegatize.d +++ b/dmd/delegatize.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/function.html#lazy-params, Lazy Parameters) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/delegatize.d, _delegatize.d) diff --git a/dmd/denum.d b/dmd/denum.d index 070a7281a49..221250b27e0 100644 --- a/dmd/denum.d +++ b/dmd/denum.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/enum.html, Enums) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/denum.d, _denum.d) diff --git a/dmd/dimport.d b/dmd/dimport.d index 803eb5a27af..b653d9bbf89 100644 --- a/dmd/dimport.d +++ b/dmd/dimport.d @@ -1,7 +1,7 @@ /** * A `Dsymbol` representing a renamed import. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dimport.d, _dimport.d) diff --git a/dmd/dinterpret.d b/dmd/dinterpret.d index 776dc83980a..7920df79991 100644 --- a/dmd/dinterpret.d +++ b/dmd/dinterpret.d @@ -3,7 +3,7 @@ * * Specification: ($LINK2 https://dlang.org/spec/function.html#interpretation, Compile Time Function Execution (CTFE)) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dinterpret.d, _dinterpret.d) diff --git a/dmd/dmacro.d b/dmd/dmacro.d index 358712b884c..6fc23e99e86 100644 --- a/dmd/dmacro.d +++ b/dmd/dmacro.d @@ -1,7 +1,7 @@ /** * Text macro processor for Ddoc. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dmacro.d, _dmacro.d) diff --git a/dmd/dmangle.d b/dmd/dmangle.d index 6ecaa5235f2..867d3cacb2f 100644 --- a/dmd/dmangle.d +++ b/dmd/dmangle.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/abi.html#name_mangling, Name Mangling) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dmangle.d, _dmangle.d) diff --git a/dmd/dmodule.d b/dmd/dmodule.d index da794b2ee8d..e1234e5bde9 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/module.html, Modules) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dmodule.d, _dmodule.d) diff --git a/dmd/doc.d b/dmd/doc.d index ba45dc21fb7..732a7370a77 100644 --- a/dmd/doc.d +++ b/dmd/doc.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/ddoc.html, Documentation Generator) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/doc.d, _doc.d) diff --git a/dmd/doc.h b/dmd/doc.h index 8dc2d9f659c..d16806beda2 100644 --- a/dmd/doc.h +++ b/dmd/doc.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/dscope.d b/dmd/dscope.d index 76ab7144392..8f196266c79 100644 --- a/dmd/dscope.d +++ b/dmd/dscope.d @@ -3,7 +3,7 @@ * * Not to be confused with the `scope` storage class. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dscope.d, _dscope.d) diff --git a/dmd/dstruct.d b/dmd/dstruct.d index 6905ea5de24..6ab93d4c39c 100644 --- a/dmd/dstruct.d +++ b/dmd/dstruct.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/struct.html, Structs, Unions) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dstruct.d, _dstruct.d) diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index 3327c073703..3611e09c286 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -1,7 +1,7 @@ /** * The base class for a D symbol, which can be a module, variable, function, enum, etc. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dsymbol.d, _dsymbol.d) diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index 5b8d5aadbc9..88110e1f5d2 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index f714ad46782..49e1c597879 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -2,7 +2,7 @@ * Does the semantic 1 pass on the AST, which looks at symbol declarations but not initializers * or function bodies. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dsymbolsem.d, _dsymbolsem.d) diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 6033368892e..32799aa04e3 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -28,7 +28,7 @@ * arguments, and uses it if found. * - Otherwise, the rest of semantic is run on the `TemplateInstance`. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dtemplate.d, _dtemplate.d) diff --git a/dmd/dtoh.d b/dmd/dtoh.d index f972789eaf4..30ca3d1f8c6 100644 --- a/dmd/dtoh.d +++ b/dmd/dtoh.d @@ -2,7 +2,7 @@ * This module contains the implementation of the C++ header generation available through * the command line switch -Hc. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dtohd, _dtoh.d) diff --git a/dmd/dversion.d b/dmd/dversion.d index fa074de578b..259f85c5128 100644 --- a/dmd/dversion.d +++ b/dmd/dversion.d @@ -4,7 +4,7 @@ * Specification: $(LINK2 https://dlang.org/spec/version.html#version-specification, Version Specification), * $(LINK2 https://dlang.org/spec/version.html#debug_specification, Debug Specification). * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dversion.d, _dversion.d) diff --git a/dmd/entity.d b/dmd/entity.d index 2b499c14fcc..c31883f11d9 100644 --- a/dmd/entity.d +++ b/dmd/entity.d @@ -3,7 +3,7 @@ * * Specification $(LINK2 https://dlang.org/spec/entity.html, Named Character Entities) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/entity.d, _entity.d) diff --git a/dmd/enum.h b/dmd/enum.h index 723cebc7e0a..be12c65e6d6 100644 --- a/dmd/enum.h +++ b/dmd/enum.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/errors.d b/dmd/errors.d index c47756aa1a7..9265ded030b 100644 --- a/dmd/errors.d +++ b/dmd/errors.d @@ -1,7 +1,7 @@ /** * Functions for raising errors. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/errors.d, _errors.d) diff --git a/dmd/errors.h b/dmd/errors.h index 000242ce49f..cc72811b112 100644 --- a/dmd/errors.h +++ b/dmd/errors.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/escape.d b/dmd/escape.d index 2a36b188879..7bc018e1e32 100644 --- a/dmd/escape.d +++ b/dmd/escape.d @@ -1,7 +1,7 @@ /** * Most of the logic to implement scoped pointers and scoped references is here. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/escape.d, _escape.d) diff --git a/dmd/expression.d b/dmd/expression.d index 511bc3c53f6..e0f258c5a57 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -3,7 +3,7 @@ * * Specification: ($LINK2 https://dlang.org/spec/expression.html, Expressions) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/expression.d, _expression.d) diff --git a/dmd/expression.h b/dmd/expression.h index 79bc5288577..7202960af63 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 6b3f922f783..63236cdb882 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -3,7 +3,7 @@ * * Specification: ($LINK2 https://dlang.org/spec/expression.html, Expressions) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/expressionsem.d, _expressionsem.d) diff --git a/dmd/file_manager.d b/dmd/file_manager.d index 173a4dac358..a0e5d0519c8 100644 --- a/dmd/file_manager.d +++ b/dmd/file_manager.d @@ -1,7 +1,7 @@ /** * Read a file from disk and store it in memory. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/file_manager.d, _file_manager.d) * Documentation: https://dlang.org/phobos/dmd_file_manager.html diff --git a/dmd/foreachvar.d b/dmd/foreachvar.d index 63281b5760c..7c4df0deca8 100644 --- a/dmd/foreachvar.d +++ b/dmd/foreachvar.d @@ -1,7 +1,7 @@ /** * Utility to visit every variable in an expression. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/foreachvar.d, _foreachvar.d) diff --git a/dmd/frontend.h b/dmd/frontend.h index ebe7220b8b5..19fa0a5f2fa 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -3360,7 +3360,7 @@ struct Global final const char* const versionChars(); Global() : inifilename(), - copyright(73, "Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved"), + copyright(73, "Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved"), written(24, "written by Walter Bright"), path(), filePath(), @@ -3380,7 +3380,7 @@ struct Global final preprocess() { } - Global(_d_dynamicArray< const char > inifilename, _d_dynamicArray< const char > copyright = { 73, "Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved" }, _d_dynamicArray< const char > written = { 24, "written by Walter Bright" }, Array* path = nullptr, Array* filePath = nullptr, _d_dynamicArray< const char > vendor = {}, Param params = Param(), uint32_t errors = 0u, uint32_t warnings = 0u, uint32_t gag = 0u, uint32_t gaggedErrors = 0u, uint32_t gaggedWarnings = 0u, void* console = nullptr, Array* versionids = nullptr, Array* debugids = nullptr, bool hasMainFunction = false, uint32_t varSequenceNumber = 1u, FileManager* fileManager = nullptr, FileName(*preprocess)(FileName , const Loc& , bool& , OutBuffer* ) = nullptr) : + Global(_d_dynamicArray< const char > inifilename, _d_dynamicArray< const char > copyright = { 73, "Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved" }, _d_dynamicArray< const char > written = { 24, "written by Walter Bright" }, Array* path = nullptr, Array* filePath = nullptr, _d_dynamicArray< const char > vendor = {}, Param params = Param(), uint32_t errors = 0u, uint32_t warnings = 0u, uint32_t gag = 0u, uint32_t gaggedErrors = 0u, uint32_t gaggedWarnings = 0u, void* console = nullptr, Array* versionids = nullptr, Array* debugids = nullptr, bool hasMainFunction = false, uint32_t varSequenceNumber = 1u, FileManager* fileManager = nullptr, FileName(*preprocess)(FileName , const Loc& , bool& , OutBuffer* ) = nullptr) : inifilename(inifilename), copyright(copyright), written(written), diff --git a/dmd/func.d b/dmd/func.d index 6b8bda40cd5..3a85679626c 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -8,7 +8,7 @@ * - `invariant` * - `unittest` * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/func.d, _func.d) diff --git a/dmd/globals.d b/dmd/globals.d index 0fda039937d..80c183e5a77 100644 --- a/dmd/globals.d +++ b/dmd/globals.d @@ -1,7 +1,7 @@ /** * Stores command line options and contains other miscellaneous declarations. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/globals.d, _globals.d) @@ -260,7 +260,7 @@ extern (C++) struct Global { const(char)[] inifilename; /// filename of configuration file as given by `-conf=`, or default value - string copyright = "Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved"; + string copyright = "Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved"; string written = "written by Walter Bright"; Array!(const(char)*)* path; /// Array of char*'s which form the import lookup path diff --git a/dmd/globals.h b/dmd/globals.h index dfb21f37aa7..45c5624b19c 100644 --- a/dmd/globals.h +++ b/dmd/globals.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/gluelayer.d b/dmd/gluelayer.d index 89070fa6b13..4a022ec3d11 100644 --- a/dmd/gluelayer.d +++ b/dmd/gluelayer.d @@ -3,7 +3,7 @@ * * This 'glues' either the DMC or GCC back-end to the front-end. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/gluelayer.d, _gluelayer.d) diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index ef1b2468c19..68670d929e5 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -3,7 +3,7 @@ * * Also used to convert AST nodes to D code in general, e.g. for error messages or `printf` debugging. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/hdrgen.d, _hdrgen.d) diff --git a/dmd/hdrgen.h b/dmd/hdrgen.h index 0488c51b9e6..43fea34255f 100644 --- a/dmd/hdrgen.h +++ b/dmd/hdrgen.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Dave Fladebo * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/iasmgcc.d b/dmd/iasmgcc.d index e1608d33d09..baf6b14b97d 100644 --- a/dmd/iasmgcc.d +++ b/dmd/iasmgcc.d @@ -1,7 +1,7 @@ /** * Inline assembler for the GCC D compiler. * - * Copyright (C) 2018-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 2018-2023 by The D Language Foundation, All Rights Reserved * Authors: Iain Buclaw * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/iasmgcc.d, _iasmgcc.d) diff --git a/dmd/id.d b/dmd/id.d index 48ca7665eae..40a5c6e47f6 100644 --- a/dmd/id.d +++ b/dmd/id.d @@ -1,7 +1,7 @@ /** * Contains the `Id` struct with a list of predefined symbols the compiler knows about. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/id.d, _id.d) diff --git a/dmd/id.h b/dmd/id.h index 984c20313ce..f6cf6e59c34 100644 --- a/dmd/id.h +++ b/dmd/id.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 2017-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 2017-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/identifier.d b/dmd/identifier.d index edd4408ad49..2233d777770 100644 --- a/dmd/identifier.d +++ b/dmd/identifier.d @@ -1,7 +1,7 @@ /** * Defines an identifier, which is the name of a `Dsymbol`. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/identifier.d, _identifier.d) diff --git a/dmd/identifier.h b/dmd/identifier.h index fa7a25aaaa1..c12c3554c1b 100644 --- a/dmd/identifier.h +++ b/dmd/identifier.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/impcnvtab.d b/dmd/impcnvtab.d index 832c331c314..b45880a2887 100644 --- a/dmd/impcnvtab.d +++ b/dmd/impcnvtab.d @@ -6,7 +6,7 @@ * Specification: $(LINK2 https://dlang.org/spec/type.html#integer-promotions, Integer Promotions), * $(LINK2 https://dlang.org/spec/type.html#usual-arithmetic-conversions, Usual Arithmetic Conversions). * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/impcnvtab.d, _impcnvtab.d) diff --git a/dmd/imphint.d b/dmd/imphint.d index f03113dc657..913de9fa61c 100644 --- a/dmd/imphint.d +++ b/dmd/imphint.d @@ -3,7 +3,7 @@ * * For example, prompt to `import std.stdio` when using `writeln`. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/imphint.d, _imphint.d) diff --git a/dmd/import.h b/dmd/import.h index f749ef5b5f6..ff25ba2045d 100644 --- a/dmd/import.h +++ b/dmd/import.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/importc.d b/dmd/importc.d index afec5ef1ead..97710b88199 100644 --- a/dmd/importc.d +++ b/dmd/importc.d @@ -3,7 +3,7 @@ * * Specification: C11 * - * Copyright: Copyright (C) 2021-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 2021-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/importc.d, _importc.d) diff --git a/dmd/init.d b/dmd/init.d index e062d7c17fa..f646d0382eb 100644 --- a/dmd/init.d +++ b/dmd/init.d @@ -1,7 +1,7 @@ /** * Defines initializers of variables, e.g. the array literal in `int[3] x = [0, 1, 2]`. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/init.d, _init.d) diff --git a/dmd/init.h b/dmd/init.h index 977157f5c41..66b874c91b5 100644 --- a/dmd/init.h +++ b/dmd/init.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/initsem.d b/dmd/initsem.d index 178b631abd9..572753b2dd8 100644 --- a/dmd/initsem.d +++ b/dmd/initsem.d @@ -1,7 +1,7 @@ /** * Semantic analysis of initializers. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/initsem.d, _initsem.d) diff --git a/dmd/inline.d b/dmd/inline.d index 01a07720207..cc50b0eed80 100644 --- a/dmd/inline.d +++ b/dmd/inline.d @@ -4,7 +4,7 @@ * The AST is traversed, and every function call is considered for inlining using `inlinecost.d`. * The function call is then inlined if this cost is below a threshold. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/inline.d, _inline.d) diff --git a/dmd/inlinecost.d b/dmd/inlinecost.d index bde042cbad8..b8b58019529 100644 --- a/dmd/inlinecost.d +++ b/dmd/inlinecost.d @@ -1,7 +1,7 @@ /** * Compute the cost of inlining a function call by counting expressions. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/inlinecost.d, _inlinecost.d) diff --git a/dmd/intrange.d b/dmd/intrange.d index d0206b6ff97..d67e0f5958d 100644 --- a/dmd/intrange.d +++ b/dmd/intrange.d @@ -1,7 +1,7 @@ /** * Implement $(LINK2 https://digitalmars.com/articles/b62.html, Value Range Propagation). * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/intrange.d, _intrange.d) diff --git a/dmd/json.d b/dmd/json.d index c79c22b29af..38e03e7d20d 100644 --- a/dmd/json.d +++ b/dmd/json.d @@ -1,7 +1,7 @@ /** * Code for generating .json descriptions of the module when passing the `-X` flag to dmd. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/json.d, _json.d) diff --git a/dmd/json.h b/dmd/json.h index 979440cd308..7a238979e20 100644 --- a/dmd/json.h +++ b/dmd/json.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/lambdacomp.d b/dmd/lambdacomp.d index e1ed717ab85..c800273e2d4 100644 --- a/dmd/lambdacomp.d +++ b/dmd/lambdacomp.d @@ -5,7 +5,7 @@ * The serialization is a string which contains the type of the parameters and the string * represantation of the lambda expression. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/lamdbacomp.d, _lambdacomp.d) diff --git a/dmd/lexer.d b/dmd/lexer.d index 9528966b85d..bd53433d6c8 100644 --- a/dmd/lexer.d +++ b/dmd/lexer.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/lex.html, Lexical) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/lexer.d, _lexer.d) diff --git a/dmd/location.d b/dmd/location.d index 215c96b6590..020d297b06d 100644 --- a/dmd/location.d +++ b/dmd/location.d @@ -1,7 +1,7 @@ /** * Encapsulates file/line/column locations. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/location.d, _location.d) diff --git a/dmd/mangle.h b/dmd/mangle.h index 512184ae9aa..37953c2ca4a 100644 --- a/dmd/mangle.h +++ b/dmd/mangle.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/mars.d b/dmd/mars.d index 1668ea1e946..73d0ddbbfc7 100644 --- a/dmd/mars.d +++ b/dmd/mars.d @@ -6,7 +6,7 @@ * utilities needed for arguments parsing, path manipulation, etc... * This file is not shared with other compilers which use the DMD front-end. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/mars.d, _mars.d) diff --git a/dmd/module.h b/dmd/module.h index 2181c7b826d..bc89ac4677e 100644 --- a/dmd/module.h +++ b/dmd/module.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/mtype.d b/dmd/mtype.d index 047d3e6a459..232042d9f4f 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -1,7 +1,7 @@ /** * Defines a D type. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/mtype.d, _mtype.d) diff --git a/dmd/mtype.h b/dmd/mtype.h index c81c25a0d79..d0775f2f5fb 100644 --- a/dmd/mtype.h +++ b/dmd/mtype.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/mustuse.d b/dmd/mustuse.d index 640a76848e4..11cc3b8d6d8 100644 --- a/dmd/mustuse.d +++ b/dmd/mustuse.d @@ -1,7 +1,7 @@ /** * Compile-time checks associated with the @mustuse attribute. * - * Copyright: Copyright (C) 2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 2022-2023 by The D Language Foundation, All Rights Reserved * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/mustuse.d, _mustuse.d) * Documentation: https://dlang.org/phobos/dmd_mustuse.html diff --git a/dmd/nogc.d b/dmd/nogc.d index 3329c14afbf..370e3b81d20 100644 --- a/dmd/nogc.d +++ b/dmd/nogc.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/function.html#nogc-functions, No-GC Functions) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/nogc.d, _nogc.d) diff --git a/dmd/nspace.d b/dmd/nspace.d index 392e6074b67..551db5b7475 100644 --- a/dmd/nspace.d +++ b/dmd/nspace.d @@ -36,7 +36,7 @@ * are valid D identifier. * * See_Also: https://github.com/dlang/dmd/pull/10031 - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/nspace.d, _nspace.d) diff --git a/dmd/nspace.h b/dmd/nspace.h index 9dbbdf2fd0a..e9fb7bdc777 100644 --- a/dmd/nspace.h +++ b/dmd/nspace.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/ob.d b/dmd/ob.d index 18c02bbe526..31e93a7637f 100644 --- a/dmd/ob.d +++ b/dmd/ob.d @@ -1,7 +1,7 @@ /** * Flow analysis for Ownership/Borrowing * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ob.d, _ob.d) diff --git a/dmd/objc.d b/dmd/objc.d index 5a3bc3a0029..c493323e238 100644 --- a/dmd/objc.d +++ b/dmd/objc.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/objc_interface.html, Interfacing to Objective-C) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/objc.d, _objc.d) diff --git a/dmd/objc.h b/dmd/objc.h index a03015489a4..305ce812487 100644 --- a/dmd/objc.h +++ b/dmd/objc.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 2015-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 2015-2023 by The D Language Foundation, All Rights Reserved * written by Michel Fortin * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/opover.d b/dmd/opover.d index 25e4b773d57..4d7fe9fcea3 100644 --- a/dmd/opover.d +++ b/dmd/opover.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/operatoroverloading.html, Operator Overloading) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/opover.d, _opover.d) diff --git a/dmd/optimize.d b/dmd/optimize.d index 7074af7e66e..b5d32b2932d 100644 --- a/dmd/optimize.d +++ b/dmd/optimize.d @@ -1,7 +1,7 @@ /** * Perform constant folding. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/optimize.d, _optimize.d) diff --git a/dmd/parse.d b/dmd/parse.d index 9a497b5823d..6eb3021dd82 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/grammar.html, D Grammar) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/parse.d, _parse.d) diff --git a/dmd/printast.d b/dmd/printast.d index 8c71a1a36aa..9975c9c1f1e 100644 --- a/dmd/printast.d +++ b/dmd/printast.d @@ -1,7 +1,7 @@ /** * Provides an AST printer for debugging. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/printast.d, _printast.d) diff --git a/dmd/root/aav.d b/dmd/root/aav.d index beceb0f0707..42d13994126 100644 --- a/dmd/root/aav.d +++ b/dmd/root/aav.d @@ -1,7 +1,7 @@ /** * Associative array implementation. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/aav.d, root/_aav.d) diff --git a/dmd/root/array.d b/dmd/root/array.d index 5c01940dadb..e352c61ce6b 100644 --- a/dmd/root/array.d +++ b/dmd/root/array.d @@ -2,7 +2,7 @@ /** * Dynamic array implementation. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/array.d, root/_array.d) diff --git a/dmd/root/array.h b/dmd/root/array.h index 52bed5e9d7f..ebe2c47d0a0 100644 --- a/dmd/root/array.h +++ b/dmd/root/array.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2011-2022 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 2011-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/bitarray.d b/dmd/root/bitarray.d index 90cbaed4981..66adab65877 100644 --- a/dmd/root/bitarray.d +++ b/dmd/root/bitarray.d @@ -1,7 +1,7 @@ /** * Implementation of a bit array. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/bitarray.d, root/_bitarray.d) diff --git a/dmd/root/bitarray.h b/dmd/root/bitarray.h index c5c5d3a94bb..617cc9e2cfa 100644 --- a/dmd/root/bitarray.h +++ b/dmd/root/bitarray.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2011-2022 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 2011-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/complex.d b/dmd/root/complex.d index a7a74381ef9..fc93bd7d404 100644 --- a/dmd/root/complex.d +++ b/dmd/root/complex.d @@ -1,7 +1,7 @@ /** * Implements a complex number type. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/complex.d, _complex.d) diff --git a/dmd/root/complex_t.h b/dmd/root/complex_t.h index c384848e9ec..de2040b88f7 100644 --- a/dmd/root/complex_t.h +++ b/dmd/root/complex_t.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/ctfloat.d b/dmd/root/ctfloat.d index 3352a821570..74505f86b1a 100644 --- a/dmd/root/ctfloat.d +++ b/dmd/root/ctfloat.d @@ -1,7 +1,7 @@ /** * Collects functions for compile-time floating-point calculations. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/ctfloat.d, root/_ctfloat.d) diff --git a/dmd/root/ctfloat.h b/dmd/root/ctfloat.h index 5a6cf258ed8..44bd959edd9 100644 --- a/dmd/root/ctfloat.h +++ b/dmd/root/ctfloat.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/dcompat.h b/dmd/root/dcompat.h index 5823e7c4886..0bc23b7a8b3 100644 --- a/dmd/root/dcompat.h +++ b/dmd/root/dcompat.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/dsystem.h b/dmd/root/dsystem.h index 53aece82e2c..c0634d66bb5 100644 --- a/dmd/root/dsystem.h +++ b/dmd/root/dsystem.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/file.d b/dmd/root/file.d index b40413c9ef1..1fb105682ea 100644 --- a/dmd/root/file.d +++ b/dmd/root/file.d @@ -1,7 +1,7 @@ /** * Read a file from disk and store it in memory. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/file.d, root/_file.d) diff --git a/dmd/root/filename.d b/dmd/root/filename.d index f6a451596bb..33f4a7aa4b1 100644 --- a/dmd/root/filename.d +++ b/dmd/root/filename.d @@ -1,7 +1,7 @@ /** * Encapsulate path and file names. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/filename.d, root/_filename.d) diff --git a/dmd/root/filename.h b/dmd/root/filename.h index 419a4c9ae68..89774119d4d 100644 --- a/dmd/root/filename.h +++ b/dmd/root/filename.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/hash.d b/dmd/root/hash.d index fe97c421ab6..2acee35c4f3 100644 --- a/dmd/root/hash.d +++ b/dmd/root/hash.d @@ -1,7 +1,7 @@ /** * Hash functions for arbitrary binary data. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Martin Nowak, Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/hash.d, root/_hash.d) diff --git a/dmd/root/longdouble.d b/dmd/root/longdouble.d index bbffc35a4b5..64ad1c98b6a 100644 --- a/dmd/root/longdouble.d +++ b/dmd/root/longdouble.d @@ -1,7 +1,7 @@ /** * 80-bit floating point value implementation if the C/D compiler does not support them natively. * - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * All Rights Reserved, written by Rainer Schuetze * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/longdouble.h b/dmd/root/longdouble.h index 4803697395d..7ba827ccf96 100644 --- a/dmd/root/longdouble.h +++ b/dmd/root/longdouble.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Rainer Schuetze * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/man.d b/dmd/root/man.d index 54217d4f768..916542886af 100644 --- a/dmd/root/man.d +++ b/dmd/root/man.d @@ -1,7 +1,7 @@ /** * Open an online manual page. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/man.d, root/_man.d) diff --git a/dmd/root/object.h b/dmd/root/object.h index b735dd98728..8e505f036c7 100644 --- a/dmd/root/object.h +++ b/dmd/root/object.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/optional.d b/dmd/root/optional.d index 266846bcb0b..bc1016b102a 100644 --- a/dmd/root/optional.d +++ b/dmd/root/optional.d @@ -1,7 +1,7 @@ /** * Implementation of an 'Optional' type * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/optional.d, root/_optional.d) diff --git a/dmd/root/optional.h b/dmd/root/optional.h index e4a41a06100..cc2ee79edeb 100644 --- a/dmd/root/optional.h +++ b/dmd/root/optional.h @@ -3,7 +3,7 @@ /** * Optional implementation. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/optional.h, root/_optional.h) diff --git a/dmd/root/port.d b/dmd/root/port.d index 319f48edb7b..ac53b7d385f 100644 --- a/dmd/root/port.d +++ b/dmd/root/port.d @@ -1,7 +1,7 @@ /** * Portable routines for functions that have different implementations on different platforms. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/port.d, root/_port.d) diff --git a/dmd/root/port.h b/dmd/root/port.h index 66a67605b5c..6fa3c000e5a 100644 --- a/dmd/root/port.h +++ b/dmd/root/port.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/region.d b/dmd/root/region.d index 1e86f32fa60..9fc57f1e3a8 100644 --- a/dmd/root/region.d +++ b/dmd/root/region.d @@ -1,7 +1,7 @@ /** * Region storage allocator implementation. * - * Copyright: Copyright (C) 2019-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 2019-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/region.d, root/_region.d) diff --git a/dmd/root/rmem.d b/dmd/root/rmem.d index ffe5ee10fef..9b1d9fba524 100644 --- a/dmd/root/rmem.d +++ b/dmd/root/rmem.d @@ -1,7 +1,7 @@ /** * Allocate memory using `malloc` or the GC depending on the configuration. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/rmem.d, root/_rmem.d) diff --git a/dmd/root/rmem.h b/dmd/root/rmem.h index 1338d7c6e46..36aa2646fdc 100644 --- a/dmd/root/rmem.h +++ b/dmd/root/rmem.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/rootobject.d b/dmd/root/rootobject.d index 7390d07cacc..4437d1622e4 100644 --- a/dmd/root/rootobject.d +++ b/dmd/root/rootobject.d @@ -1,7 +1,7 @@ /** * Provide the root object that classes in dmd inherit from. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/rootobject.d, root/_rootobject.d) diff --git a/dmd/root/speller.d b/dmd/root/speller.d index 9b9460d3269..b646bdda0cc 100644 --- a/dmd/root/speller.d +++ b/dmd/root/speller.d @@ -3,7 +3,7 @@ * * Does not have any dependencies on the rest of DMD. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/speller.d, root/_speller.d) diff --git a/dmd/root/string.d b/dmd/root/string.d index 93c596ff0cd..8b204ab4cad 100644 --- a/dmd/root/string.d +++ b/dmd/root/string.d @@ -1,7 +1,7 @@ /** * Contains various string related functions. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/string.d, root/_string.d) diff --git a/dmd/root/stringtable.d b/dmd/root/stringtable.d index 20316faeccf..de293eb9b55 100644 --- a/dmd/root/stringtable.d +++ b/dmd/root/stringtable.d @@ -1,7 +1,7 @@ /** * A specialized associative array with string keys stored in a variable length structure. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/stringtable.d, root/_stringtable.d) diff --git a/dmd/root/utf.d b/dmd/root/utf.d index 0d230e764c3..c9781a46bc6 100644 --- a/dmd/root/utf.d +++ b/dmd/root/utf.d @@ -1,7 +1,7 @@ /** * Functions related to UTF encoding. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/utf.d, _utf.d) diff --git a/dmd/safe.d b/dmd/safe.d index 397fd2ef472..c3fa90d7f79 100644 --- a/dmd/safe.d +++ b/dmd/safe.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/function.html#function-safety, Function Safety) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/safe.d, _safe.d) diff --git a/dmd/sapply.d b/dmd/sapply.d index adfae329e06..848602897b9 100644 --- a/dmd/sapply.d +++ b/dmd/sapply.d @@ -1,7 +1,7 @@ /** * Provides a depth-first statement visitor. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/sparse.d, _sparse.d) diff --git a/dmd/scope.h b/dmd/scope.h index 8b9e59e3aae..b25c26afff2 100644 --- a/dmd/scope.h +++ b/dmd/scope.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/semantic2.d b/dmd/semantic2.d index 0801e3471f9..c103f60689b 100644 --- a/dmd/semantic2.d +++ b/dmd/semantic2.d @@ -1,7 +1,7 @@ /** * Performs the semantic2 stage, which deals with initializer expressions. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/semantic2.d, _semantic2.d) diff --git a/dmd/semantic3.d b/dmd/semantic3.d index ca7e0c87c32..78da4a15a42 100644 --- a/dmd/semantic3.d +++ b/dmd/semantic3.d @@ -1,7 +1,7 @@ /** * Performs the semantic3 stage, which deals with function bodies. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/semantic3.d, _semantic3.d) diff --git a/dmd/sideeffect.d b/dmd/sideeffect.d index f7a3836961c..ed938762bab 100644 --- a/dmd/sideeffect.d +++ b/dmd/sideeffect.d @@ -1,7 +1,7 @@ /** * Find side-effects of expressions. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/sideeffect.d, _sideeffect.d) diff --git a/dmd/statement.d b/dmd/statement.d index 3e5f9ba3e86..96c59ba219c 100644 --- a/dmd/statement.d +++ b/dmd/statement.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/statement.html, Statements) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/statement.d, _statement.d) diff --git a/dmd/statement.h b/dmd/statement.h index 681b4816320..76a39912718 100644 --- a/dmd/statement.h +++ b/dmd/statement.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/statement_rewrite_walker.d b/dmd/statement_rewrite_walker.d index 7b3a13b40bc..dcdd9630002 100644 --- a/dmd/statement_rewrite_walker.d +++ b/dmd/statement_rewrite_walker.d @@ -1,7 +1,7 @@ /** * Provides a visitor for statements that allows rewriting the currently visited node. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/statement_rewrite_walker.d, _statement_rewrite_walker.d) diff --git a/dmd/statementsem.d b/dmd/statementsem.d index c8120676940..5764efd60fd 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/statement.html, Statements) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/statementsem.d, _statementsem.d) diff --git a/dmd/staticassert.d b/dmd/staticassert.d index 0cf24420c8c..15c46b304ba 100644 --- a/dmd/staticassert.d +++ b/dmd/staticassert.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/version.html#static-assert, Static Assert) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/staticassert.d, _staticassert.d) diff --git a/dmd/staticassert.h b/dmd/staticassert.h index 922e7ec7c9d..2b7d300f6af 100644 --- a/dmd/staticassert.h +++ b/dmd/staticassert.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/staticcond.d b/dmd/staticcond.d index 0cbdd963afa..aa6f37ca67b 100644 --- a/dmd/staticcond.d +++ b/dmd/staticcond.d @@ -1,7 +1,7 @@ /** * Lazily evaluate static conditions for `static if`, `static assert` and template constraints. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/staticcond.d, _staticcond.d) diff --git a/dmd/stmtstate.d b/dmd/stmtstate.d index 3e26b8f9bd5..7b2ea972f0e 100644 --- a/dmd/stmtstate.d +++ b/dmd/stmtstate.d @@ -1,7 +1,7 @@ /** * Used to help transform statement AST into flow graph. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/stmtstate.d, _stmtstate.d) diff --git a/dmd/target.d b/dmd/target.d index e7e0cb5299f..944f09f2d2d 100644 --- a/dmd/target.d +++ b/dmd/target.d @@ -15,7 +15,7 @@ * - $(LINK2 https://github.com/ldc-developers/ldc, LDC repository) * - $(LINK2 https://github.com/D-Programming-GDC/gcc, GDC repository) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/target.d, _target.d) diff --git a/dmd/target.h b/dmd/target.h index 096c16fd610..ef2c09d4147 100644 --- a/dmd/target.h +++ b/dmd/target.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 2013-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 2013-2023 by The D Language Foundation, All Rights Reserved * written by Iain Buclaw * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/template.h b/dmd/template.h index d19a0578128..8e8ba16c0ab 100644 --- a/dmd/template.h +++ b/dmd/template.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/templateparamsem.d b/dmd/templateparamsem.d index 10cf670cb7b..432daeea5c7 100644 --- a/dmd/templateparamsem.d +++ b/dmd/templateparamsem.d @@ -1,7 +1,7 @@ /** * Semantic analysis of template parameters. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/templateparamsem.d, _templateparamsem.d) diff --git a/dmd/tokens.d b/dmd/tokens.d index 25f92730115..b3cd2d3c403 100644 --- a/dmd/tokens.d +++ b/dmd/tokens.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/lex.html#tokens, Tokens) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/tokens.d, _tokens.d) diff --git a/dmd/tokens.h b/dmd/tokens.h index 35fd68b0ba5..32ae5f437c4 100644 --- a/dmd/tokens.h +++ b/dmd/tokens.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/traits.d b/dmd/traits.d index 62802866c8b..048c24f7b22 100644 --- a/dmd/traits.d +++ b/dmd/traits.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/traits.html, Traits) * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/traits.d, _traits.d) diff --git a/dmd/typesem.d b/dmd/typesem.d index 7dc83345c7f..0d64ba46a50 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -1,7 +1,7 @@ /** * Semantic analysis for D types. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/typesem.d, _typesem.d) diff --git a/dmd/typinf.d b/dmd/typinf.d index b64e7aa3ae7..cbac0fd6e4e 100644 --- a/dmd/typinf.d +++ b/dmd/typinf.d @@ -1,7 +1,7 @@ /** * Generate `TypeInfo` objects, which are needed for run-time introspection of types. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/typeinf.d, _typeinf.d) diff --git a/dmd/utils.d b/dmd/utils.d index 7fc693ced73..dfb4cb5ee2d 100644 --- a/dmd/utils.d +++ b/dmd/utils.d @@ -1,7 +1,7 @@ /** * This module defines some utility functions for DMD. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/utils.d, _utils.d) diff --git a/dmd/version.h b/dmd/version.h index b76393bc1ec..697d46ee211 100644 --- a/dmd/version.h +++ b/dmd/version.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/visitor.d b/dmd/visitor.d index e6dfa1173cf..e4c2a91e7f7 100644 --- a/dmd/visitor.d +++ b/dmd/visitor.d @@ -1,7 +1,7 @@ /** * Provides a visitor class visiting all AST nodes present in the compiler. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/visitor.d, _visitor.d) diff --git a/dmd/visitor.h b/dmd/visitor.h index b45ef790de3..f8cbdb48c92 100644 --- a/dmd/visitor.h +++ b/dmd/visitor.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 2013-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 2013-2023 by The D Language Foundation, All Rights Reserved * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. * https://www.boost.org/LICENSE_1_0.txt diff --git a/dmd/vsoptions.d b/dmd/vsoptions.d index ce6b4d23425..d735040c1b6 100644 --- a/dmd/vsoptions.d +++ b/dmd/vsoptions.d @@ -1,7 +1,7 @@ /** * When compiling on Windows with the Microsoft toolchain, try to detect the Visual Studio setup. * - * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/link.d, _vsoptions.d) diff --git a/dmd/vsoptions.h b/dmd/vsoptions.h index 0d09e85988a..fc63e1c1b9b 100644 --- a/dmd/vsoptions.h +++ b/dmd/vsoptions.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 2009-2022 by The D Language Foundation, All Rights Reserved + * Copyright (C) 2009-2023 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. From 3479b18ddbe0739d2d57bb15f3f3490a55eabfdc Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Mon, 2 Jan 2023 18:11:14 +0100 Subject: [PATCH 002/177] Makefile: stub out all auto-tester-build and auto-tester-test recipes --- runtime/druntime/posix.mak | 16 ---------------- runtime/druntime/win32.mak | 6 ------ runtime/druntime/win64.mak | 6 ------ tests/dmd/Makefile | 9 --------- 4 files changed, 37 deletions(-) diff --git a/runtime/druntime/posix.mak b/runtime/druntime/posix.mak index b3068696492..da0f1ddad0d 100644 --- a/runtime/druntime/posix.mak +++ b/runtime/druntime/posix.mak @@ -581,22 +581,6 @@ publictests: $(addsuffix .publictests, $(basename $(SRCS))) ################################################################################ -.PHONY : auto-tester-build -ifneq (,$(findstring Darwin_64_32, $(PWD))) -auto-tester-build: - echo "Darwin_64_32_disabled" -else -auto-tester-build: target checkwhitespace -endif - -.PHONY : auto-tester-test -ifneq (,$(findstring Darwin_64_32, $(PWD))) -auto-tester-test: - echo "Darwin_64_32_disabled" -else -auto-tester-test: unittest benchmark-compile-only -endif - .PHONY : buildkite-test buildkite-test: unittest benchmark-compile-only diff --git a/runtime/druntime/win32.mak b/runtime/druntime/win32.mak index 960d62c4366..c43f3e9326e 100644 --- a/runtime/druntime/win32.mak +++ b/runtime/druntime/win32.mak @@ -164,9 +164,3 @@ install: druntime.zip clean: del $(DRUNTIME) $(OBJS_TO_DELETE) rmdir /S /Q $(DOCDIR) $(IMPDIR) - -auto-tester-build: - echo "Windows builds have been disabled on auto-tester" - -auto-tester-test: - echo "Windows builds have been disabled on auto-tester" diff --git a/runtime/druntime/win64.mak b/runtime/druntime/win64.mak index 848cb8005a3..ef137916bd9 100644 --- a/runtime/druntime/win64.mak +++ b/runtime/druntime/win64.mak @@ -135,9 +135,3 @@ install: druntime.zip clean: del $(DRUNTIME) $(OBJS_TO_DELETE) rmdir /S /Q $(DOCDIR) $(IMPDIR) - -auto-tester-build: - echo "Windows builds have been disabled on auto-tester" - -auto-tester-test: - echo "Windows builds have been disabled on auto-tester" diff --git a/tests/dmd/Makefile b/tests/dmd/Makefile index 28fe3871aa5..c682429b773 100644 --- a/tests/dmd/Makefile +++ b/tests/dmd/Makefile @@ -213,15 +213,6 @@ start_all_tests: $(RUNNER) @echo "Running all tests" $(EXECUTE_RUNNER) all -# The auto-tester cannot run runnable_cxx as its compiler is too old -ifeq (windows,$(OS)) -auto-tester-test: - echo "Windows builds have been disabled" -else -auto-tester-test: $(RUNNER) - $(EXECUTE_RUNNER) runnable compilable fail_compilation dshell -endif - $(RESULTS_DIR)/d_do_test$(EXE): tools/d_do_test.d tools/sanitize_json.d $(RESULTS_DIR)/.created @echo "Building d_do_test tool" @echo "OS: '$(OS)'" From c3dbaa991528626dd0a564b25bd4a2a51867879e Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Mon, 2 Jan 2023 20:15:23 +0100 Subject: [PATCH 003/177] ci: Update cirrus macOS image to M1-based runners (dlang/dmd!14772) * druntime/test: Force makefile to x86 on Apple ARM cpu (dmd does not support ARM) * ci: Update cirrus macOS image to M1-based runners * compiler/test/Makefile: Workaround issue 23517 --- runtime/druntime/test/common.mak | 5 +++++ tests/dmd/Makefile | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/runtime/druntime/test/common.mak b/runtime/druntime/test/common.mak index c4a73566307..c4afbefa700 100644 --- a/runtime/druntime/test/common.mak +++ b/runtime/druntime/test/common.mak @@ -18,6 +18,11 @@ ifneq (default,$(MODEL)) MODEL_FLAG:=-m$(MODEL) endif CFLAGS_BASE:= $(MODEL_FLAG) $(PIC) -Wall +ifeq (osx,$(OS)) + ifeq (64,$(MODEL)) + CFLAGS_BASE+=--target=x86_64-darwin-apple # ARM cpu is not supported by dmd + endif +endif DFLAGS:=$(MODEL_FLAG) $(PIC) -w -I../../src -I../../import -I$(SRC) -defaultlib= -debuglib= -preview=dip1000 -L-lpthread -L-lm $(LINKDL) # LINK_SHARED may be set by importing makefile DFLAGS+=$(if $(LINK_SHARED),-L$(DRUNTIMESO),-L$(DRUNTIME)) diff --git a/tests/dmd/Makefile b/tests/dmd/Makefile index c682429b773..c08cec65e51 100644 --- a/tests/dmd/Makefile +++ b/tests/dmd/Makefile @@ -142,6 +142,11 @@ ifneq ($(N),) EXECUTE_RUNNER:=$(EXECUTE_RUNNER) --jobs=$N endif +# Workaround https://issues.dlang.org/show_bug.cgi?id=23517 +ifeq (osx,$(OS)) + export MACOSX_DEPLOYMENT_TARGET=11 +endif + ifeq (windows,$(OS)) all: echo "Windows builds have been disabled" From dbba06b188b7293f24398e2f0d6949f304c187cb Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Mon, 2 Jan 2023 14:27:51 +0100 Subject: [PATCH 004/177] Remove old 'Calling member function before dip1000' --- dmd/escape.d | 92 ++++++++++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 54 deletions(-) diff --git a/dmd/escape.d b/dmd/escape.d index 7bc018e1e32..06be24538d8 100644 --- a/dmd/escape.d +++ b/dmd/escape.d @@ -1768,67 +1768,51 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re { DotVarExp dve = e.e1.isDotVarExp(); FuncDeclaration fd = dve.var.isFuncDeclaration(); - if (1) + if (fd && fd.isThis()) { - if (fd && fd.isThis()) - { - /* Calling a non-static member function dve.var, which is returning `this`, and with dve.e1 representing `this` - */ - - /***************************** - * Concoct storage class for member function's implicit `this` parameter. - * Params: - * fd = member function - * Returns: - * storage class for fd's `this` - */ - StorageClass getThisStorageClass(FuncDeclaration fd) - { - StorageClass stc; - auto tf = fd.type.toBasetype().isTypeFunction(); - if (tf.isreturn) - stc |= STC.return_; - if (tf.isreturnscope) - stc |= STC.returnScope | STC.scope_; - auto ad = fd.isThis(); - if (ad.isClassDeclaration() || tf.isScopeQual) - stc |= STC.scope_; - if (ad.isStructDeclaration()) - stc |= STC.ref_; // `this` for a struct member function is passed by `ref` - return stc; - } + /* Calling a non-static member function dve.var, which is returning `this`, and with dve.e1 representing `this` + */ - const psr = buildScopeRef(getThisStorageClass(fd)); - if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope) - escapeByValue(dve.e1, er, live, retRefTransition); - else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope) - { - if (tf.isref) - { - /* Treat calling: - * struct S { ref S foo() return; } - * as: - * this; - */ - escapeByValue(dve.e1, er, live, retRefTransition); - } - else - escapeByRef(dve.e1, er, live, psr == ScopeRef.ReturnRef_Scope); - } + /***************************** + * Concoct storage class for member function's implicit `this` parameter. + * Params: + * fd = member function + * Returns: + * storage class for fd's `this` + */ + StorageClass getThisStorageClass(FuncDeclaration fd) + { + StorageClass stc; + auto tf = fd.type.toBasetype().isTypeFunction(); + if (tf.isreturn) + stc |= STC.return_; + if (tf.isreturnscope) + stc |= STC.returnScope | STC.scope_; + auto ad = fd.isThis(); + if (ad.isClassDeclaration() || tf.isScopeQual) + stc |= STC.scope_; + if (ad.isStructDeclaration()) + stc |= STC.ref_; // `this` for a struct member function is passed by `ref` + return stc; } - } - else - { - // Calling member function before dip1000 - StorageClass stc = dve.var.storage_class & (STC.return_ | STC.scope_ | STC.ref_); - if (tf.isreturn) - stc |= STC.return_; - const psr = buildScopeRef(stc); + const psr = buildScopeRef(getThisStorageClass(fd)); if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope) escapeByValue(dve.e1, er, live, retRefTransition); else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope) - escapeByRef(dve.e1, er, live, retRefTransition); + { + if (tf.isref) + { + /* Treat calling: + * struct S { ref S foo() return; } + * as: + * this; + */ + escapeByValue(dve.e1, er, live, retRefTransition); + } + else + escapeByRef(dve.e1, er, live, psr == ScopeRef.ReturnRef_Scope); + } } // If it's also a nested function that is 'return scope' From 12b5b088bc6cf5729e5cbda3bc5eb1418e7783a5 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Thu, 5 Jan 2023 08:34:05 +0000 Subject: [PATCH 005/177] [dsymbolsem] Tweak punctuation for 3 error messages (dlang/dmd!14780) * Tweak punctuation for 3 error messages Fix Issue 13656 - clarify error when trying to declare a variable of type ref. Tweak 2 inout errors. * Use hyphen & fix `auto Type` error too --- dmd/dsymbolsem.d | 8 ++++---- tests/dmd/fail_compilation/diag9679.d | 4 ++-- tests/dmd/fail_compilation/fail253.d | 5 +++-- tests/dmd/fail_compilation/failinout2.d | 8 +++++++- tests/dmd/fail_compilation/failinout3748a.d | 10 ---------- tests/dmd/fail_compilation/failinout3748b.d | 10 ---------- 6 files changed, 16 insertions(+), 29 deletions(-) delete mode 100644 tests/dmd/fail_compilation/failinout3748a.d delete mode 100644 tests/dmd/fail_compilation/failinout3748b.d diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 49e1c597879..4b6d565deee 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -544,7 +544,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } } if ((dsym.storage_class & STC.auto_) && !inferred) - dsym.error("storage class `auto` has no effect if type is not inferred, did you mean `scope`?"); + dsym.error("- storage class `auto` has no effect if type is not inferred, did you mean `scope`?"); if (auto tt = tb.isTypeTuple()) { @@ -811,14 +811,14 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if ((dsym.storage_class & (STC.ref_ | STC.parameter | STC.foreach_ | STC.temp | STC.result)) == STC.ref_ && dsym.ident != Id.This) { - dsym.error("only parameters or `foreach` declarations can be `ref`"); + dsym.error("- only parameters, functions and `foreach` declarations can be `ref`"); } if (dsym.type.hasWild()) { if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field) || dsym.isDataseg()) { - dsym.error("only parameters or stack based variables can be `inout`"); + dsym.error("- only parameters or stack-based variables can be `inout`"); } FuncDeclaration func = sc.func; if (func) @@ -836,7 +836,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } if (!isWild) { - dsym.error("`inout` variables can only be declared inside `inout` functions"); + dsym.error("- `inout` variables can only be declared inside `inout` functions"); } } } diff --git a/tests/dmd/fail_compilation/diag9679.d b/tests/dmd/fail_compilation/diag9679.d index 4496f0c8920..85923b7189e 100644 --- a/tests/dmd/fail_compilation/diag9679.d +++ b/tests/dmd/fail_compilation/diag9679.d @@ -1,8 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/diag9679.d(11): Error: variable `diag9679.main.n` only parameters or `foreach` declarations can be `ref` -fail_compilation/diag9679.d(12): Error: variable `diag9679.main.n` storage class `auto` has no effect if type is not inferred, did you mean `scope`? +fail_compilation/diag9679.d(11): Error: variable `diag9679.main.n` - only parameters, functions and `foreach` declarations can be `ref` +fail_compilation/diag9679.d(12): Error: variable `diag9679.main.n` - storage class `auto` has no effect if type is not inferred, did you mean `scope`? --- */ diff --git a/tests/dmd/fail_compilation/fail253.d b/tests/dmd/fail_compilation/fail253.d index bee7e31eb3d..e6bfbedc7a3 100644 --- a/tests/dmd/fail_compilation/fail253.d +++ b/tests/dmd/fail_compilation/fail253.d @@ -1,11 +1,11 @@ /* TEST_OUTPUT: --- -fail_compilation/fail253.d(13): Error: variable `fail253.main.x` `inout` variables can only be declared inside `inout` functions +fail_compilation/fail253.d(13): Error: variable `fail253.main.x` - `inout` variables can only be declared inside `inout` functions fail_compilation/fail253.d(16): Error: cannot modify `inout` expression `x` +fail_compilation/fail253.d(19): Error: variable `fail253.main.err11` - `inout` variables can only be declared inside `inout` functions --- */ - void main() { foreach (i; 0 .. 2) @@ -16,4 +16,5 @@ void main() x = '?'; } } + inout(int)* err11; } diff --git a/tests/dmd/fail_compilation/failinout2.d b/tests/dmd/fail_compilation/failinout2.d index e1553636ab7..6fe86434e29 100644 --- a/tests/dmd/fail_compilation/failinout2.d +++ b/tests/dmd/fail_compilation/failinout2.d @@ -1,7 +1,13 @@ /* TEST_OUTPUT: --- -fail_compilation/failinout2.d(7): Error: variable `failinout2.x` only parameters or stack based variables can be `inout` +fail_compilation/failinout2.d(8): Error: variable `failinout2.x` - only parameters or stack-based variables can be `inout` +fail_compilation/failinout2.d(12): Error: variable `failinout2.S3748.err8` - only parameters or stack-based variables can be `inout` --- */ inout int x; + +struct S3748 +{ + inout(int) err8; +} diff --git a/tests/dmd/fail_compilation/failinout3748a.d b/tests/dmd/fail_compilation/failinout3748a.d deleted file mode 100644 index 77edb7e523d..00000000000 --- a/tests/dmd/fail_compilation/failinout3748a.d +++ /dev/null @@ -1,10 +0,0 @@ -/* -TEST_OUTPUT: ---- -fail_compilation/failinout3748a.d(9): Error: variable `failinout3748a.S3748.err8` only parameters or stack based variables can be `inout` ---- -*/ -struct S3748 -{ - inout(int) err8; -} diff --git a/tests/dmd/fail_compilation/failinout3748b.d b/tests/dmd/fail_compilation/failinout3748b.d deleted file mode 100644 index b6dddd879ca..00000000000 --- a/tests/dmd/fail_compilation/failinout3748b.d +++ /dev/null @@ -1,10 +0,0 @@ -/* -TEST_OUTPUT: ---- -fail_compilation/failinout3748b.d(9): Error: variable `failinout3748b.main.err11` `inout` variables can only be declared inside `inout` functions ---- -*/ -void main() -{ - inout(int)* err11; -} From 041379844bc4676b830ce21cb5b0bb5580d15feb Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Thu, 5 Jan 2023 08:34:15 +0000 Subject: [PATCH 006/177] [dsymbolsem] Fix error punctuation (part 2) (dlang/dmd!14784) --- dmd/dsymbolsem.d | 14 +++++++------- tests/dmd/fail_compilation/enum_init.d | 2 +- tests/dmd/fail_compilation/fail14406.d | 4 ++-- tests/dmd/fail_compilation/fail17955.d | 2 +- tests/dmd/fail_compilation/fail346.d | 2 +- tests/dmd/fail_compilation/fail4269a.d | 2 +- tests/dmd/fail_compilation/failcstuff4.c | 2 +- tests/dmd/fail_compilation/gag4269f.d | 2 +- tests/dmd/fail_compilation/ice12902.d | 2 +- tests/dmd/fail_compilation/ice18753.d | 2 +- tests/dmd/fail_compilation/test20549.d | 2 +- tests/dmd/fail_compilation/testscopestatic.d | 2 +- 12 files changed, 19 insertions(+), 19 deletions(-) diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 4b6d565deee..33814fef7df 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -509,10 +509,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor { if (inferred) { - dsym.error("type `%s` is inferred from initializer `%s`, and variables cannot be of type `void`", dsym.type.toChars(), dsym._init.toChars()); + dsym.error("- type `%s` is inferred from initializer `%s`, and variables cannot be of type `void`", dsym.type.toChars(), dsym._init.toChars()); } else - dsym.error("variables cannot be of type `void`"); + dsym.error("- variables cannot be of type `void`"); dsym.type = Type.terror; tb = dsym.type; } @@ -528,7 +528,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor // or when the variable is defined externally if (!ts.sym.members && !(dsym.storage_class & (STC.ref_ | STC.extern_))) { - dsym.error("no definition of struct `%s`", ts.toChars()); + dsym.error("- no definition of struct `%s`", ts.toChars()); // Explain why the definition is required when it's part of another type if (!dsym.type.isTypeStruct()) @@ -742,7 +742,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } else if (dsym.isMember()) { - dsym.error("field cannot be `scope`"); + error(dsym.loc, "field `%s` cannot be `scope`", dsym.toChars()); } else if (!dsym.type.hasPointers()) { @@ -780,11 +780,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor InterfaceDeclaration id = parent.isInterfaceDeclaration(); if (id) { - dsym.error("field not allowed in interface"); + error(dsym.loc, "field `%s` not allowed in interface", dsym.toChars()); } else if (aad && aad.sizeok == Sizeok.done) { - dsym.error("cannot be further field because it will change the determined %s size", aad.toChars()); + error(dsym.loc, "cannot declare field `%s` because it will change the determined size of `%s`", dsym.toChars(), aad.toChars()); } /* Templates cannot add fields to aggregates @@ -804,7 +804,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor AggregateDeclaration ad2 = ti.tempdecl.isMember(); if (ad2 && dsym.storage_class != STC.undefined_) { - dsym.error("cannot use template to add field to aggregate `%s`", ad2.toChars()); + dsym.error("- cannot use template to add field to aggregate `%s`", ad2.toChars()); } } } diff --git a/tests/dmd/fail_compilation/enum_init.d b/tests/dmd/fail_compilation/enum_init.d index ab6ba308550..8344a4701c7 100644 --- a/tests/dmd/fail_compilation/enum_init.d +++ b/tests/dmd/fail_compilation/enum_init.d @@ -56,7 +56,7 @@ https://issues.dlang.org/show_bug.cgi?id=21785 TEST_OUTPUT: --- -fail_compilation/enum_init.d(306): Error: variable `enum_init.fooOB.ob` no definition of struct `S` +fail_compilation/enum_init.d(306): Error: variable `enum_init.fooOB.ob` - no definition of struct `S` fail_compilation/enum_init.d(302): required by type `OpaqueBase` --- */ diff --git a/tests/dmd/fail_compilation/fail14406.d b/tests/dmd/fail_compilation/fail14406.d index 3725a913c5b..f6c8fbb6804 100644 --- a/tests/dmd/fail_compilation/fail14406.d +++ b/tests/dmd/fail_compilation/fail14406.d @@ -1,8 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/fail14406.d-mixin-20(20): Error: variable `fail14406.CFrop.bar_obj` cannot be further field because it will change the determined CFrop size -fail_compilation/fail14406.d-mixin-25(25): Error: variable `fail14406.IFrop.bar_obj` field not allowed in interface +fail_compilation/fail14406.d-mixin-20(20): Error: cannot declare field `bar_obj` because it will change the determined size of `CFrop` +fail_compilation/fail14406.d-mixin-25(25): Error: field `bar_obj` not allowed in interface --- */ diff --git a/tests/dmd/fail_compilation/fail17955.d b/tests/dmd/fail_compilation/fail17955.d index f33149ea94d..95eb5cc8c1f 100644 --- a/tests/dmd/fail_compilation/fail17955.d +++ b/tests/dmd/fail_compilation/fail17955.d @@ -13,7 +13,7 @@ fail_compilation/fail17955.d(32): instantiated from here: `indicesOf!(isR fail_compilation/fail17955.d(67): instantiated from here: `RedisStripped!(User, true)` fail_compilation/fail17955.d(93): Error: need `this` for `fromISOExtString` of type `pure nothrow @nogc @safe immutable(SimpleTimeZone)(dstring _param_0)` fail_compilation/fail17955.d(95): Error: undefined identifier `DateTimeException` -fail_compilation/fail17955.d(25): Error: variable `fail17955.isISOExtStringSerializable!(SysTime).isISOExtStringSerializable` type `void` is inferred from initializer `fromISOExtString("")`, and variables cannot be of type `void` +fail_compilation/fail17955.d(25): Error: variable `fail17955.isISOExtStringSerializable!(SysTime).isISOExtStringSerializable` - type `void` is inferred from initializer `fromISOExtString("")`, and variables cannot be of type `void` fail_compilation/fail17955.d(54): Error: function `fail17955.toRedis!(SysTime).toRedis` has no `return` statement, but is expected to return a value of type `string` --- */ diff --git a/tests/dmd/fail_compilation/fail346.d b/tests/dmd/fail_compilation/fail346.d index 77042cc111b..5b51f54498f 100644 --- a/tests/dmd/fail_compilation/fail346.d +++ b/tests/dmd/fail_compilation/fail346.d @@ -2,7 +2,7 @@ TEST_OUTPUT: --- fail_compilation/fail346.d(15): Error: undefined identifier `P` -fail_compilation/fail346.d(15): Error: variable `fail346.S.T!0.T` cannot use template to add field to aggregate `S` +fail_compilation/fail346.d(15): Error: variable `fail346.S.T!0.T` - cannot use template to add field to aggregate `S` fail_compilation/fail346.d(20): Error: template instance `fail346.S.T!0` error instantiating fail_compilation/fail346.d(23): instantiated from here: `V!(S, 0)` --- diff --git a/tests/dmd/fail_compilation/fail4269a.d b/tests/dmd/fail_compilation/fail4269a.d index be59e1f72b0..1ce98065882 100644 --- a/tests/dmd/fail_compilation/fail4269a.d +++ b/tests/dmd/fail_compilation/fail4269a.d @@ -2,7 +2,7 @@ TEST_OUTPUT: --- fail_compilation/fail4269a.d(12): Error: undefined identifier `B` -fail_compilation/fail4269a.d(12): Error: variable `fail4269a.A.blah` field not allowed in interface +fail_compilation/fail4269a.d(12): Error: field `blah` not allowed in interface fail_compilation/fail4269a.d(13): Error: undefined identifier `B` --- */ diff --git a/tests/dmd/fail_compilation/failcstuff4.c b/tests/dmd/fail_compilation/failcstuff4.c index 664680ebdbb..41f9ab5556b 100644 --- a/tests/dmd/fail_compilation/failcstuff4.c +++ b/tests/dmd/fail_compilation/failcstuff4.c @@ -2,7 +2,7 @@ /* TEST_OUTPUT: --- fail_compilation/failcstuff4.c(100): Error: can only `*` a pointer, not a `int` -fail_compilation/failcstuff4.c(157): Error: variable `failcstuff4.T22106.f1` no definition of struct `S22106_t` +fail_compilation/failcstuff4.c(157): Error: variable `failcstuff4.T22106.f1` - no definition of struct `S22106_t` --- */ diff --git a/tests/dmd/fail_compilation/gag4269f.d b/tests/dmd/fail_compilation/gag4269f.d index 84d39ebae50..b571059eb45 100644 --- a/tests/dmd/fail_compilation/gag4269f.d +++ b/tests/dmd/fail_compilation/gag4269f.d @@ -3,7 +3,7 @@ TEST_OUTPUT: --- fail_compilation/gag4269f.d(11): Error: undefined identifier `Y9`, did you mean interface `X9`? -fail_compilation/gag4269f.d(11): Error: variable `gag4269f.X9.y` field not allowed in interface +fail_compilation/gag4269f.d(11): Error: field `y` not allowed in interface --- */ diff --git a/tests/dmd/fail_compilation/ice12902.d b/tests/dmd/fail_compilation/ice12902.d index ac430120d49..03763f7c18a 100644 --- a/tests/dmd/fail_compilation/ice12902.d +++ b/tests/dmd/fail_compilation/ice12902.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/ice12902.d(20): Error: variable `ice12902.main.__dollar` type `void` is inferred from initializer `s.opDollar()`, and variables cannot be of type `void` +fail_compilation/ice12902.d(20): Error: variable `ice12902.main.__dollar` - type `void` is inferred from initializer `s.opDollar()`, and variables cannot be of type `void` fail_compilation/ice12902.d(20): Error: expression `s.opDollar()` is `void` and has no value --- */ diff --git a/tests/dmd/fail_compilation/ice18753.d b/tests/dmd/fail_compilation/ice18753.d index 253025cdc7a..f41ab3e754f 100644 --- a/tests/dmd/fail_compilation/ice18753.d +++ b/tests/dmd/fail_compilation/ice18753.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/ice18753.d(21): Error: variable `ice18753.isInputRange!(Group).isInputRange` type `void` is inferred from initializer `ReturnType(func...)`, and variables cannot be of type `void` +fail_compilation/ice18753.d(21): Error: variable `ice18753.isInputRange!(Group).isInputRange` - type `void` is inferred from initializer `ReturnType(func...)`, and variables cannot be of type `void` fail_compilation/ice18753.d(23): Error: template instance `ice18753.isInputRange!(Group)` error instantiating fail_compilation/ice18753.d(18): instantiated from here: `isForwardRange!(Group)` fail_compilation/ice18753.d(18): while evaluating: `static assert(isForwardRange!(Group))` diff --git a/tests/dmd/fail_compilation/test20549.d b/tests/dmd/fail_compilation/test20549.d index 2cafc1be9e2..dc95da10eb5 100644 --- a/tests/dmd/fail_compilation/test20549.d +++ b/tests/dmd/fail_compilation/test20549.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: ---- -fail_compilation/test20549.d(12): Error: variable `test.__a_field_0` variables cannot be of type `void` +fail_compilation/test20549.d(12): Error: variable `test.__a_field_0` - variables cannot be of type `void` ---- */ diff --git a/tests/dmd/fail_compilation/testscopestatic.d b/tests/dmd/fail_compilation/testscopestatic.d index 86c6328e9e4..cc7b0125953 100644 --- a/tests/dmd/fail_compilation/testscopestatic.d +++ b/tests/dmd/fail_compilation/testscopestatic.d @@ -4,7 +4,7 @@ fail_compilation/testscopestatic.d(15): Error: variable `testscopestatic.foo.p` cannot be `scope` and `static` fail_compilation/testscopestatic.d(16): Error: variable `testscopestatic.foo.b` cannot be `scope` and `extern` fail_compilation/testscopestatic.d(17): Error: variable `testscopestatic.foo.c` cannot be `scope` and `__gshared` -fail_compilation/testscopestatic.d(21): Error: variable `testscopestatic.foo.S.x` field cannot be `scope` +fail_compilation/testscopestatic.d(21): Error: field `x` cannot be `scope` --- */ From d56968f05579e2c4482df039531ca52aff4aefea Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Thu, 5 Jan 2023 08:35:01 +0000 Subject: [PATCH 007/177] [dsymbolsem] Fix error punctuation (part 3) (dlang/dmd!14785) --- dmd/dsymbolsem.d | 6 +++--- tests/dmd/fail_compilation/diag10099.d | 2 +- tests/dmd/fail_compilation/enum9921.d | 4 +++- tests/dmd/fail_compilation/fail10102.d | 4 ++-- tests/dmd/fail_compilation/test17451.d | 2 +- tests/dmd/fail_compilation/test20719.d | 2 +- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 33814fef7df..46ea6b449e6 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -856,7 +856,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor { } else - dsym.error("default construction is disabled for type `%s`", dsym.type.toChars()); + dsym.error("- default construction is disabled for type `%s`", dsym.type.toChars()); } } @@ -911,7 +911,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (dsym._init) { } // remember we had an explicit initializer else if (dsym.storage_class & STC.manifest) - dsym.error("manifest constants must have initializers"); + dsym.error("- manifest constants must have initializers"); // Don't allow non-extern, non-__gshared variables to be interfaced with C++ if (dsym._linkage == LINK.cpp && !(dsym.storage_class & (STC.ctfe | STC.extern_ | STC.gshared)) && dsym.isDataseg()) @@ -939,7 +939,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor //printf("Providing default initializer for '%s'\n", dsym.toChars()); if (sz == SIZE_INVALID && dsym.type.ty != Terror) - dsym.error("size of type `%s` is invalid", dsym.type.toChars()); + dsym.error("- size of type `%s` is invalid", dsym.type.toChars()); Type tv = dsym.type; while (tv.ty == Tsarray) // Don't skip Tenum diff --git a/tests/dmd/fail_compilation/diag10099.d b/tests/dmd/fail_compilation/diag10099.d index cf1b6459436..46109247fb6 100644 --- a/tests/dmd/fail_compilation/diag10099.d +++ b/tests/dmd/fail_compilation/diag10099.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/diag10099.d(15): Error: variable `diag10099.main.s` default construction is disabled for type `S` +fail_compilation/diag10099.d(15): Error: variable `diag10099.main.s` - default construction is disabled for type `S` --- */ diff --git a/tests/dmd/fail_compilation/enum9921.d b/tests/dmd/fail_compilation/enum9921.d index 90d8802d6d8..51c8b1a6653 100644 --- a/tests/dmd/fail_compilation/enum9921.d +++ b/tests/dmd/fail_compilation/enum9921.d @@ -3,9 +3,11 @@ TEST_OUTPUT: --- fail_compilation/enum9921.d(9): Error: enum `enum9921.X` base type must not be `void` fail_compilation/enum9921.d(11): Error: enum `enum9921.Z` base type must not be `void` +fail_compilation/enum9921.d(13): Error: variable `enum9921.x` - manifest constants must have initializers --- */ - enum X : void; enum Z : void { Y }; + +enum int x; diff --git a/tests/dmd/fail_compilation/fail10102.d b/tests/dmd/fail_compilation/fail10102.d index 4847413ffea..17577ec84f4 100644 --- a/tests/dmd/fail_compilation/fail10102.d +++ b/tests/dmd/fail_compilation/fail10102.d @@ -1,8 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/fail10102.d(48): Error: variable `fail10102.main.m` default construction is disabled for type `NotNull!(int*)` -fail_compilation/fail10102.d(49): Error: variable `fail10102.main.a` default construction is disabled for type `NotNull!(int*)[3]` +fail_compilation/fail10102.d(48): Error: variable `fail10102.main.m` - default construction is disabled for type `NotNull!(int*)` +fail_compilation/fail10102.d(49): Error: variable `fail10102.main.a` - default construction is disabled for type `NotNull!(int*)[3]` fail_compilation/fail10102.d(50): Error: default construction is disabled for type `NotNull!(int*)` fail_compilation/fail10102.d(51): Error: field `S.m` must be initialized because it has no default constructor --- diff --git a/tests/dmd/fail_compilation/test17451.d b/tests/dmd/fail_compilation/test17451.d index a7ef88a0dba..b0cda2105a2 100644 --- a/tests/dmd/fail_compilation/test17451.d +++ b/tests/dmd/fail_compilation/test17451.d @@ -2,7 +2,7 @@ --- fail_compilation/test17451.d(22): Error: undefined identifier `allocator` fail_compilation/test17451.d(23): Error: `false` has no effect -fail_compilation/test17451.d(30): Error: variable `test17451.HashMap!(ThreadSlot).HashMap.__lambda2.v` size of type `ThreadSlot` is invalid +fail_compilation/test17451.d(30): Error: variable `test17451.HashMap!(ThreadSlot).HashMap.__lambda2.v` - size of type `ThreadSlot` is invalid fail_compilation/test17451.d(44): Error: template instance `test17451.HashMap!(ThreadSlot)` error instantiating --- */ diff --git a/tests/dmd/fail_compilation/test20719.d b/tests/dmd/fail_compilation/test20719.d index 44d3d5a36a3..b9305f20f80 100644 --- a/tests/dmd/fail_compilation/test20719.d +++ b/tests/dmd/fail_compilation/test20719.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- fail_compilation/test20719.d(13): Error: struct `test20719.SumType` no size because of forward reference -fail_compilation/test20719.d(32): Error: variable `test20719.isCopyable!(SumType).__lambda2.foo` size of type `SumType` is invalid +fail_compilation/test20719.d(32): Error: variable `test20719.isCopyable!(SumType).__lambda2.foo` - size of type `SumType` is invalid fail_compilation/test20719.d(18): Error: template instance `test20719.isCopyable!(SumType)` error instantiating --- */ From d253d877eaa84b201e321f2a6657573f86d6d189 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Thu, 5 Jan 2023 08:36:36 +0000 Subject: [PATCH 008/177] [dsymbolsem] Fix error punctuation (part 4) (dlang/dmd!14786) * [dsymbolsem] Fix error punctuation (part 4) Also move fail233.d test into diag12312.d. * 3 pragma(mangle) errors * Fix line no --- dmd/dsymbolsem.d | 12 ++++++------ tests/dmd/fail_compilation/biterrors2.d | 2 +- tests/dmd/fail_compilation/diag12312.d | 9 +++++++-- tests/dmd/fail_compilation/fail233.d | 12 ------------ tests/dmd/fail_compilation/fix22104.c | 4 ++-- tests/dmd/fail_compilation/ice13788.d | 6 +++--- 6 files changed, 19 insertions(+), 26 deletions(-) delete mode 100644 tests/dmd/fail_compilation/fail233.d diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 46ea6b449e6..322f43ea40c 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -974,7 +974,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } if (dsym.type.baseElemOf().ty == Tvoid) { - dsym.error("`%s` does not have a default initializer", dsym.type.toChars()); + dsym.error("of type `%s` does not have a default initializer", dsym.type.toChars()); } else if (auto e = dsym.type.defaultInit(dsym.loc)) { @@ -995,7 +995,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor dsym._init.isVoidInitializer() && !(dsym.storage_class & STC.field)) { - dsym.error("incomplete array type must have initializer"); + dsym.error("- incomplete array type must have initializer"); } ExpInitializer ei = dsym._init.isExpInitializer(); @@ -1244,7 +1244,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (!dsym.parent.isStructDeclaration() && !dsym.parent.isClassDeclaration()) { - dsym.error("bit-field must be member of struct, union, or class"); + dsym.error("- bit-field must be member of struct, union, or class"); } sc = sc.startCTFE(); @@ -1534,12 +1534,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor e = se; if (!se.len) { - pd.error("zero-length string not allowed for mangled name"); + pd.error("- zero-length string not allowed for mangled name"); return null; } if (se.sz != 1) { - pd.error("mangled name characters can only be of type `char`"); + pd.error("- mangled name characters can only be of type `char`"); return null; } version (all) @@ -1742,7 +1742,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor pd.args = new Expressions(); if (pd.args.length == 0 || pd.args.length > 2) { - pd.error(pd.args.length == 0 ? "string expected for mangled name" + pd.error(pd.args.length == 0 ? "- string expected for mangled name" : "expected 1 or 2 arguments"); pd.args.setDim(1); (*pd.args)[0] = ErrorExp.get(); // error recovery diff --git a/tests/dmd/fail_compilation/biterrors2.d b/tests/dmd/fail_compilation/biterrors2.d index c8390ba7dc3..77671eb853f 100644 --- a/tests/dmd/fail_compilation/biterrors2.d +++ b/tests/dmd/fail_compilation/biterrors2.d @@ -1,7 +1,7 @@ /* REQUIRED_ARGS: -preview=bitfields * TEST_OUTPUT: --- -fail_compilation/biterrors2.d(100): Error: variable `biterrors2.a` bit-field must be member of struct, union, or class +fail_compilation/biterrors2.d(100): Error: variable `biterrors2.a` - bit-field must be member of struct, union, or class fail_compilation/biterrors2.d(104): Error: bit-field `b` has zero width fail_compilation/biterrors2.d(105): Error: bit-field type `float` is not an integer type --- diff --git a/tests/dmd/fail_compilation/diag12312.d b/tests/dmd/fail_compilation/diag12312.d index e015cfea7ac..307c6be1d09 100644 --- a/tests/dmd/fail_compilation/diag12312.d +++ b/tests/dmd/fail_compilation/diag12312.d @@ -1,11 +1,16 @@ /* TEST_OUTPUT: --- -fail_compilation/diag12312.d(10): Error: variable `diag12312.main.arr` `void[16]` does not have a default initializer +fail_compilation/diag12312.d(10): Error: variable `diag12312.main.arr` of type `void[16]` does not have a default initializer +fail_compilation/diag12312.d(15): Error: variable `diag12312.bug1176.v` of type `void[1]` does not have a default initializer --- */ - void main() { void[16] arr; } + +void bug1176() +{ + void[1] v; +} diff --git a/tests/dmd/fail_compilation/fail233.d b/tests/dmd/fail_compilation/fail233.d deleted file mode 100644 index 7d4d97892dd..00000000000 --- a/tests/dmd/fail_compilation/fail233.d +++ /dev/null @@ -1,12 +0,0 @@ -// REQUIRED_ARGS: -o- -/* -TEST_OUTPUT: ---- -fail_compilation/fail233.d(11): Error: variable `fail233.bug1176.v` `void[1]` does not have a default initializer ---- -*/ - -void bug1176() -{ - void[1] v; -} diff --git a/tests/dmd/fail_compilation/fix22104.c b/tests/dmd/fail_compilation/fix22104.c index 845ec804ec4..e8079f54df2 100644 --- a/tests/dmd/fail_compilation/fix22104.c +++ b/tests/dmd/fail_compilation/fix22104.c @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fix22104.c(103): Error: variable `fix22104.test1.array1` incomplete array type must have initializer -fail_compilation/fix22104.c(108): Error: variable `fix22104.test2.array2` incomplete array type must have initializer +fail_compilation/fix22104.c(103): Error: variable `fix22104.test1.array1` - incomplete array type must have initializer +fail_compilation/fix22104.c(108): Error: variable `fix22104.test2.array2` - incomplete array type must have initializer --- */ diff --git a/tests/dmd/fail_compilation/ice13788.d b/tests/dmd/fail_compilation/ice13788.d index 99f3c4a6c35..3e3989bc290 100644 --- a/tests/dmd/fail_compilation/ice13788.d +++ b/tests/dmd/fail_compilation/ice13788.d @@ -1,10 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/ice13788.d(11): Error: pragma `mangle` string expected for mangled name +fail_compilation/ice13788.d(11): Error: pragma `mangle` - string expected for mangled name fail_compilation/ice13788.d(12): Error: `string` expected for mangled name, not `(1)` of type `int` -fail_compilation/ice13788.d(13): Error: pragma `mangle` zero-length string not allowed for mangled name -fail_compilation/ice13788.d(14): Error: pragma `mangle` mangled name characters can only be of type `char` +fail_compilation/ice13788.d(13): Error: pragma `mangle` - zero-length string not allowed for mangled name +fail_compilation/ice13788.d(14): Error: pragma `mangle` - mangled name characters can only be of type `char` --- */ From 43e2826f8730c969312748942136ddd263a33f83 Mon Sep 17 00:00:00 2001 From: Vladimir Panteleev Date: Thu, 5 Jan 2023 10:38:12 +0000 Subject: [PATCH 009/177] Fix Issue 23597 - .di files not compatible with -i (dlang/dmd!14783) --- dmd/compiler.d | 2 +- tests/dmd/compilable/imports/test23597.di | 3 +++ tests/dmd/compilable/issue23597.d | 7 +++++++ 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/compilable/imports/test23597.di create mode 100644 tests/dmd/compilable/issue23597.d diff --git a/dmd/compiler.d b/dmd/compiler.d index a0a1732047d..84c2c6c9c6d 100644 --- a/dmd/compiler.d +++ b/dmd/compiler.d @@ -142,7 +142,7 @@ extern (C++) struct Compiler */ extern(C++) static bool onImport(Module m) { - if (includeImports) + if (includeImports && m.filetype == FileType.d) { if (includeImportedModuleCheck(ModuleComponentRange( m.md ? m.md.packages : [], m.ident, m.isPackageFile))) diff --git a/tests/dmd/compilable/imports/test23597.di b/tests/dmd/compilable/imports/test23597.di new file mode 100644 index 00000000000..d21a0f76491 --- /dev/null +++ b/tests/dmd/compilable/imports/test23597.di @@ -0,0 +1,3 @@ +module imports.test23597; + +void fun()() {} diff --git a/tests/dmd/compilable/issue23597.d b/tests/dmd/compilable/issue23597.d new file mode 100644 index 00000000000..9299d744cea --- /dev/null +++ b/tests/dmd/compilable/issue23597.d @@ -0,0 +1,7 @@ +/** +PERMUTE_ARGS: -i +LINK: +**/ +import imports.test23597; + +void main() { fun(); } From 59c87bfeef8b361fbeb46a05cce4a57696a6a723 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Thu, 5 Jan 2023 09:39:08 -0800 Subject: [PATCH 010/177] add support for 64 bit memset (dlang/dmd!14788) --- tests/dmd/runnable/test19946.d | 37 ++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests/dmd/runnable/test19946.d diff --git a/tests/dmd/runnable/test19946.d b/tests/dmd/runnable/test19946.d new file mode 100644 index 00000000000..9f9d3bc9824 --- /dev/null +++ b/tests/dmd/runnable/test19946.d @@ -0,0 +1,37 @@ +// https://issues.dlang.org/show_bug.cgi?id=19946 + +import core.stdc.stdio; + +template Tests(TY) +{ + void test1() + { + TY[24] ba; + ba[0..23] = 0x40; + check1(ba[]); + } + + void check1(TY[] ba) + { + foreach (i; 0 .. 23) + { + //printf("ba[%d] = 0x%02x\n", i, ba[i]); + assert(ba[i] == 0x40); + } + assert(ba[23] == 0); + } +} + +int main() +{ + Tests!byte.test1(); + Tests!short.test1(); + Tests!int.test1(); + Tests!long.test1(); + + Tests!ubyte.test1(); + Tests!ushort.test1(); + Tests!uint.test1(); + Tests!ulong.test1(); + return 0; +} From 28a4f452bb416564a2d44f94b8103b28df2a6ea6 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Fri, 6 Jan 2023 15:43:24 +0800 Subject: [PATCH 011/177] Fix Issue 23261 - druntime core.std.attribute.Tagged1_2 constructor is unsafe (dlang/dmd!14771) --- runtime/druntime/src/core/attribute.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/druntime/src/core/attribute.d b/runtime/druntime/src/core/attribute.d index 8a1dc8add89..c2a7c334eb7 100644 --- a/runtime/druntime/src/core/attribute.d +++ b/runtime/druntime/src/core/attribute.d @@ -236,9 +236,9 @@ version (UdaGNUAbiTag) struct gnuAbiTag { string[] tags; - this(string[] tags...) + this(string[] tags...) @safe pure nothrow { - this.tags = tags; + this.tags = tags.dup; } } From 5fadcec15459180553fc051ec3eeb13999a1a8b5 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 6 Jan 2023 19:03:50 -0800 Subject: [PATCH 012/177] fix Issue 20101 - BetterC: Template instantiation in CTFE only context should skip codegen (dlang/dmd!14789) --- dmd/dtemplate.d | 2 ++ dmd/expressionsem.d | 2 ++ dmd/traits.d | 2 +- tests/dmd/compilable/test20201.d | 16 ++++++++++++++++ 4 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/compilable/test20201.d diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 32799aa04e3..d80bb366a0a 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -6247,6 +6247,8 @@ extern (C++) class TemplateInstance : ScopeDsymbol */ final bool needsCodegen() { + //printf("needsCodegen() %s\n", toChars()); + // minst is finalized after the 1st invocation. // tnext and tinst are only needed for the 1st invocation and // cleared for further invocations. diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 63236cdb882..50233bd00d1 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -105,6 +105,8 @@ bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps) if (!ex) continue; auto sc2 = sc.startCTFE(); + sc2.tinst = null; + sc2.minst = null; // prevents emission of any instantiated templates to object file auto e2 = ex.expressionSemantic(sc2); auto e3 = resolveProperties(sc2, e2); sc2.endCTFE(); diff --git a/dmd/traits.d b/dmd/traits.d index 048c24f7b22..a64b57b5a29 100644 --- a/dmd/traits.d +++ b/dmd/traits.d @@ -1676,7 +1676,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc) uint errors = global.startGagging(); Scope* sc2 = sc.push(); sc2.tinst = null; - sc2.minst = null; + sc2.minst = null; // this is why code for these are not emitted to object file sc2.flags = (sc.flags & ~(SCOPE.ctfe | SCOPE.condition)) | SCOPE.compile | SCOPE.fullinst; bool err = false; diff --git a/tests/dmd/compilable/test20201.d b/tests/dmd/compilable/test20201.d new file mode 100644 index 00000000000..b0419d6a345 --- /dev/null +++ b/tests/dmd/compilable/test20201.d @@ -0,0 +1,16 @@ +/* REQUIRED_ARGS: -betterC + */ + +// https://issues.dlang.org/show_bug.cgi?id=20101 + +public string ctfeHelper()(string a) +{ + return "int " ~ a ~ " = 42;"; +} + +extern(C) int main() +{ + int b = __traits(compiles, ctfeHelper("a")); + mixin(ctfeHelper("a")); + return !(a + b); +} From a8b20f8b942d677643c361417be528c96aa6c6f6 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 9 Jan 2023 11:02:49 -0800 Subject: [PATCH 013/177] fix Issue 23584 - ImportC: __builtin_bit_cast not supported (dlang/dmd!14795) --- runtime/druntime/src/importc.h | 2 ++ tests/dmd/compilable/test22809.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/runtime/druntime/src/importc.h b/runtime/druntime/src/importc.h index bcdfb8b5f2e..d54ca1b1d66 100644 --- a/runtime/druntime/src/importc.h +++ b/runtime/druntime/src/importc.h @@ -71,6 +71,8 @@ */ #define __builtin_offsetof(t,i) ((typeof(sizeof(0)))((char *)&((t *)0)->i - (char *)0)) +#define __builtin_bit_cast(t,e) (*(t*)(void*)&(e)) + /*************************** * C11 6.10.8.3 Conditional feature macros */ diff --git a/tests/dmd/compilable/test22809.c b/tests/dmd/compilable/test22809.c index 1f41da0dad6..68752d50a04 100644 --- a/tests/dmd/compilable/test22809.c +++ b/tests/dmd/compilable/test22809.c @@ -13,3 +13,17 @@ struct Foo { int y = ((size_t)((char *)&((struct Foo *)1)->x - (char *)1)); _Static_assert(((size_t)((char *)&((struct Foo *)0)->y - (char *)0))==4, ""); + + +// https://issues.dlang.org/show_bug.cgi?id=23584 + +int foo(float bar) +{ + return __builtin_bit_cast(unsigned int, bar); +} + +void test23584() +{ + int i = foo(3.5); + _Static_assert(foo(3.5) == 0x40600000, "1"); +} From 76e1f01c6d328be3f793c478e6df139ba87627ab Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 9 Jan 2023 14:20:46 -0800 Subject: [PATCH 014/177] ImportC better error message for __int128 (dlang/dmd!14797) --- dmd/cparse.d | 21 +++++++++++++++++++++ dmd/frontend.h | 3 ++- dmd/tokens.d | 6 +++++- dmd/tokens.h | 1 + tests/dmd/fail_compilation/test128.i | 15 +++++++++++++++ tests/dmd/unit/lexer/location_offset.d | 1 + 6 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 tests/dmd/fail_compilation/test128.i diff --git a/dmd/cparse.d b/dmd/cparse.d index a6bc42b1014..d08cbe35ee5 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -286,6 +286,7 @@ final class CParser(AST) : Parser!AST case TOK.int16: case TOK.int32: case TOK.int64: + case TOK.__int128: case TOK.float32: case TOK.float64: case TOK.signed: @@ -2183,6 +2184,7 @@ final class CParser(AST) : Parser!AST ximaginary = 0x8000, xcomplex = 0x10000, x_Atomic = 0x20000, + xint128 = 0x40000, } AST.Type t; @@ -2227,6 +2229,7 @@ final class CParser(AST) : Parser!AST case TOK.int16: tkwx = TKW.xshort; break; case TOK.int32: tkwx = TKW.xint; break; case TOK.int64: tkwx = TKW.xlong; break; + case TOK.__int128: tkwx = TKW.xint128; break; case TOK.float32: tkwx = TKW.xfloat; break; case TOK.float64: tkwx = TKW.xdouble; break; case TOK.void_: tkwx = TKW.xvoid; break; @@ -2505,6 +2508,11 @@ final class CParser(AST) : Parser!AST case TKW.xunsigned | TKW.xllong | TKW.xint: case TKW.xunsigned | TKW.xllong: t = unsignedTypeForSize(long_longsize); break; + case TKW.xint128: + case TKW.xsigned | TKW.xint128: t = integerTypeForSize(16); break; + + case TKW.xunsigned | TKW.xint128: t = unsignedTypeForSize(16); break; + case TKW.xvoid: t = AST.Type.tvoid; break; case TKW.xbool: t = boolsize == 1 ? AST.Type.tbool : integerTypeForSize(boolsize); break; @@ -3270,6 +3278,7 @@ final class CParser(AST) : Parser!AST case TOK._Complex: case TOK._Thread_local: case TOK.int32: + case TOK.__int128: case TOK.char_: case TOK.float32: case TOK.float64: @@ -3940,6 +3949,7 @@ final class CParser(AST) : Parser!AST case TOK.int16: case TOK.int32: case TOK.int64: + case TOK.__int128: case TOK.float32: case TOK.float64: case TOK.signed: @@ -4304,6 +4314,7 @@ final class CParser(AST) : Parser!AST case TOK.int16: case TOK.int32: case TOK.int64: + case TOK.__int128: case TOK.float32: case TOK.float64: case TOK.void_: @@ -4702,6 +4713,11 @@ final class CParser(AST) : Parser!AST return AST.Type.tint32; if (size <= 8) return AST.Type.tint64; + if (size == 16) + { + error("__int128 not supported"); + return AST.Type.terror; + } error("unsupported integer type"); return AST.Type.terror; } @@ -4723,6 +4739,11 @@ final class CParser(AST) : Parser!AST return AST.Type.tuns32; if (size <= 8) return AST.Type.tuns64; + if (size == 16) + { + error("unsigned __int128 not supported"); + return AST.Type.terror; + } error("unsupported integer type"); return AST.Type.terror; } diff --git a/dmd/frontend.h b/dmd/frontend.h index 19fa0a5f2fa..51498b2e2f9 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -1816,7 +1816,8 @@ enum class TOK : uint8_t __declspec_ = 217u, __stdcall_ = 218u, __pragma_ = 219u, - __attribute___ = 220u, + __int128_ = 220u, + __attribute___ = 221u, }; enum class MemorySet diff --git a/dmd/tokens.d b/dmd/tokens.d index b3cd2d3c403..cad24cc5162 100644 --- a/dmd/tokens.d +++ b/dmd/tokens.d @@ -274,6 +274,7 @@ enum TOK : ubyte __declspec, __stdcall, __pragma, + __int128, __attribute__, } @@ -584,6 +585,7 @@ private immutable TOK[] keywords = TOK.__declspec, TOK.__stdcall, TOK.__pragma, + TOK.__int128, TOK.__attribute__, ]; @@ -612,7 +614,8 @@ static immutable TOK[TOK.max + 1] Ckeywords = restrict, return_, int16, signed, sizeof_, static_, struct_, switch_, typedef_, union_, unsigned, void_, volatile, while_, asm_, typeof_, _Alignas, _Alignof, _Atomic, _Bool, _Complex, _Generic, _Imaginary, _Noreturn, - _Static_assert, _Thread_local, _import, __cdecl, __declspec, __stdcall, __pragma, __attribute__ ]; + _Static_assert, _Thread_local, + _import, __cdecl, __declspec, __stdcall, __pragma, __int128, __attribute__ ]; foreach (kw; Ckwds) tab[kw] = cast(TOK) kw; @@ -883,6 +886,7 @@ extern (C++) struct Token TOK.__declspec : "__declspec", TOK.__stdcall : "__stdcall", TOK.__pragma : "__pragma", + TOK.__int128 : "__int128", TOK.__attribute__ : "__attribute__", ]; diff --git a/dmd/tokens.h b/dmd/tokens.h index 32ae5f437c4..8444f8114ac 100644 --- a/dmd/tokens.h +++ b/dmd/tokens.h @@ -283,6 +283,7 @@ enum class TOK : unsigned char declspec, stdcall, pragma, + int128_, attribute__, MAX, diff --git a/tests/dmd/fail_compilation/test128.i b/tests/dmd/fail_compilation/test128.i new file mode 100644 index 00000000000..fbbd5e7d758 --- /dev/null +++ b/tests/dmd/fail_compilation/test128.i @@ -0,0 +1,15 @@ +/* TEST_OUTPUT: +--- +fail_compilation/test128.i(12): Error: unsigned __int128 not supported +fail_compilation/test128.i(12): Error: __int128 not supported +--- + */ + +// https://issues.dlang.org/show_bug.cgi?id=23614 + +unsigned long long _mulx_u64(unsigned long long __X, unsigned long long __Y, unsigned long long *__P) +{ + unsigned __int128 __res = (__int128) __X * __Y; + *__P = (unsigned long long) (__res >> 64); + return (unsigned long long) __res; +} diff --git a/tests/dmd/unit/lexer/location_offset.d b/tests/dmd/unit/lexer/location_offset.d index 9eaa7eb38eb..813125c2066 100644 --- a/tests/dmd/unit/lexer/location_offset.d +++ b/tests/dmd/unit/lexer/location_offset.d @@ -541,6 +541,7 @@ enum ignoreTokens __declspec, __stdcall, __pragma, + __int128, __attribute__, max_, From 74c9c49db600f7d06f429347e8c1d22bc9631c2a Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 9 Jan 2023 19:55:50 -0800 Subject: [PATCH 015/177] fix Issue 23606 - betterC with CTFE and gc (dlang/dmd!14791) --- dmd/declaration.h | 1 + dmd/dscope.d | 4 ++ dmd/frontend.h | 2 + dmd/func.d | 1 + dmd/inline.d | 3 ++ dmd/nogc.d | 66 +++++++++++++++++++++++++++++++- tests/dmd/compilable/test23606.d | 12 ++++++ 7 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 tests/dmd/compilable/test23606.d diff --git a/dmd/declaration.h b/dmd/declaration.h index 5d5c4234b74..e5fe57fd10c 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -600,6 +600,7 @@ class FuncDeclaration : public Declaration // set if someone took the address of this function int tookAddressOf; bool requiresClosure; // this function needs a closure + bool skipCodegen; // do not generate code for this function // local variables in this function which are referenced by nested functions VarDeclarations closureVars; diff --git a/dmd/dscope.d b/dmd/dscope.d index 8f196266c79..73b09d270dc 100644 --- a/dmd/dscope.d +++ b/dmd/dscope.d @@ -272,6 +272,10 @@ extern (C++) struct Scope * // To call x.toString in runtime, compiler should unspeculative S!int. * assert(x.toString() == "instantiated"); * } + * + * This results in an undefined reference to `RTInfoImpl`: + * class C { int a,b,c; int* p,q; } + * void test() { C c = new C(); } */ // If a template is instantiated from CT evaluated expression, // compiler can elide its code generation. diff --git a/dmd/frontend.h b/dmd/frontend.h index 51498b2e2f9..fdbac678fec 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -2472,6 +2472,7 @@ class FuncDeclaration : public Declaration BUILTIN builtin; int32_t tookAddressOf; bool requiresClosure; + bool skipCodegen; Array closureVars; Array outerVars; Array siblingCallers; @@ -7927,6 +7928,7 @@ class NOGCVisitor final : public StoppableVisitor public: using StoppableVisitor::visit; FuncDeclaration* f; + bool checkOnly; bool err; void doCond(Expression* exp); void visit(Expression* e) override; diff --git a/dmd/func.d b/dmd/func.d index 3a85679626c..2da7e858f84 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -329,6 +329,7 @@ extern (C++) class FuncDeclaration : Declaration int tookAddressOf; bool requiresClosure; // this function needs a closure + bool skipCodegen; // do not generate code for this function /** local variables in this function which are referenced by nested functions * (They'll get put into the "closure" for this function.) diff --git a/dmd/inline.d b/dmd/inline.d index cc50b0eed80..6d4e3e041b3 100644 --- a/dmd/inline.d +++ b/dmd/inline.d @@ -1661,6 +1661,9 @@ private bool canInline(FuncDeclaration fd, bool hasthis, bool hdrscan, bool stat assert(fd.semanticRun >= PASS.semantic3done); } + if (fd.skipCodegen) + return false; + final switch (statementsToo ? fd.inlineStatusStmt : fd.inlineStatusExp) { case ILS.yes: diff --git a/dmd/nogc.d b/dmd/nogc.d index 370e3b81d20..746313f77c4 100644 --- a/dmd/nogc.d +++ b/dmd/nogc.d @@ -34,6 +34,7 @@ extern (C++) final class NOGCVisitor : StoppableVisitor alias visit = typeof(super).visit; public: FuncDeclaration f; + bool checkOnly; // don't print errors bool err; extern (D) this(FuncDeclaration f) @@ -75,6 +76,11 @@ public: auto fd = stripHookTraceImpl(e.f); if (fd.ident == Id._d_arraysetlengthT) { + if (checkOnly) + { + err = true; + return; + } if (f.setGC()) { e.error("setting `length` in `@nogc` %s `%s` may cause a GC allocation", @@ -86,6 +92,11 @@ public: } else if (fd.ident == Id._d_arrayappendT || fd.ident == Id._d_arrayappendcTX) { + if (checkOnly) + { + err = true; + return; + } if (f.setGC()) { e.error("cannot use operator `~=` in `@nogc` %s `%s`", @@ -101,6 +112,11 @@ public: { if (e.type.ty != Tarray || !e.elements || !e.elements.length || e.onstack) return; + if (checkOnly) + { + err = true; + return; + } if (f.setGC()) { e.error("array literal in `@nogc` %s `%s` may cause a GC allocation", @@ -115,6 +131,11 @@ public: { if (!e.keys.length) return; + if (checkOnly) + { + err = true; + return; + } if (f.setGC()) { e.error("associative array literal in `@nogc` %s `%s` may cause a GC allocation", @@ -136,6 +157,11 @@ public: return; if (global.params.ehnogc && e.thrownew) return; // separate allocator is called for this, not the GC + if (checkOnly) + { + err = true; + return; + } if (f.setGC()) { e.error("cannot use `new` in `@nogc` %s `%s`", @@ -164,6 +190,11 @@ public: Type t1b = e.e1.type.toBasetype(); if (e.modifiable && t1b.ty == Taarray) { + if (checkOnly) + { + err = true; + return; + } if (f.setGC()) { e.error("assigning an associative array element in `@nogc` %s `%s` may cause a GC allocation", @@ -179,6 +210,11 @@ public: { if (e.e1.op == EXP.arrayLength) { + if (checkOnly) + { + err = true; + return; + } if (f.setGC()) { e.error("setting `length` in `@nogc` %s `%s` may cause a GC allocation", @@ -196,6 +232,11 @@ public: * The other branch will be `_d_arrayappendcTX(e1, 1), e1[$-1]=e2` which will generate the warning about * GC usage. See visit(CallExp). */ + if (checkOnly) + { + err = true; + return; + } if (f.setGC()) { err = true; @@ -205,6 +246,11 @@ public: override void visit(CatExp e) { + if (checkOnly) + { + err = true; + return; + } if (f.setGC()) { e.error("cannot use operator `~` in `@nogc` %s `%s`", @@ -218,16 +264,32 @@ public: Expression checkGC(Scope* sc, Expression e) { + /* If betterC, allow GC to happen in non-CTFE code. + * Just don't generate code for it. + * Detect non-CTFE use of the GC in betterC code. + */ + const betterC = global.params.betterC; FuncDeclaration f = sc.func; - if (e && e.op != EXP.error && f && sc.intypeof != 1 && !(sc.flags & SCOPE.ctfe) && + if (e && e.op != EXP.error && f && sc.intypeof != 1 && + (!(sc.flags & SCOPE.ctfe) || betterC) && (f.type.ty == Tfunction && (cast(TypeFunction)f.type).isnogc || f.nogcInprocess || global.params.vgc) && !(sc.flags & SCOPE.debug_)) { scope NOGCVisitor gcv = new NOGCVisitor(f); + gcv.checkOnly = betterC; walkPostorder(e, gcv); if (gcv.err) - return ErrorExp.get(); + { + if (betterC) + { + /* Allow ctfe to use the gc code, but don't let it into the runtime + */ + f.skipCodegen = true; + } + else + return ErrorExp.get(); + } } return e; } diff --git a/tests/dmd/compilable/test23606.d b/tests/dmd/compilable/test23606.d new file mode 100644 index 00000000000..4d8ab2472ba --- /dev/null +++ b/tests/dmd/compilable/test23606.d @@ -0,0 +1,12 @@ +/* REQUIRED_ARGS: -betterC + */ + +// https://issues.dlang.org/show_bug.cgi?id=23606 + +string foo()() +{ + string a, b; + return a ~ b; +} + +enum s = foo(); From 90751678d48a5d2ef49e623552f1142319a57468 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 10 Jan 2023 10:30:58 -0800 Subject: [PATCH 016/177] fix Issue 23616 - ImportC: clang __has_feature and __has_extension not recognized (dlang/dmd!14799) --- runtime/druntime/src/importc.h | 12 ++++++++++++ tests/dmd/compilable/test23616.c | 8 ++++++++ 2 files changed, 20 insertions(+) create mode 100644 tests/dmd/compilable/test23616.c diff --git a/runtime/druntime/src/importc.h b/runtime/druntime/src/importc.h index d54ca1b1d66..bf5ac518940 100644 --- a/runtime/druntime/src/importc.h +++ b/runtime/druntime/src/importc.h @@ -66,6 +66,18 @@ */ #define __extension__ /* ignore it, as ImportC doesn't do warnings */ +/******************************** + * __has_extension is a clang thing: + * https://clang.llvm.org/docs/LanguageExtensions.html + * ImportC doesn't has those extensions. + */ +#undef __has_feature +#define __has_feature(x) 0 + +#undef __has_extension +#define __has_extension(x) 0 + + /**************************** * Define it to do what other C compilers do. */ diff --git a/tests/dmd/compilable/test23616.c b/tests/dmd/compilable/test23616.c new file mode 100644 index 00000000000..4b9ebca4fe8 --- /dev/null +++ b/tests/dmd/compilable/test23616.c @@ -0,0 +1,8 @@ +// https://issues.dlang.org/show_bug.cgi?id=23616 + +#if __has_extension(gnu_asm) +void _hreset(int __eax) +{ + __asm__ ("hreset $0" :: "a"(__eax)); +} +#endif From 3f6238b5fd448e0f2216bd63aec0e756cc6048c3 Mon Sep 17 00:00:00 2001 From: Dennis Date: Wed, 11 Jan 2023 12:16:49 +0100 Subject: [PATCH 017/177] Follow up "- betterC with CTFE and gc" (dlang/dmd!14800) --- dmd/declaration.h | 3 +- dmd/frontend.h | 3 +- dmd/func.d | 3 +- dmd/nogc.d | 121 +++++++++++++--------------------------------- 4 files changed, 39 insertions(+), 91 deletions(-) diff --git a/dmd/declaration.h b/dmd/declaration.h index e5fe57fd10c..cf3487cff48 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -600,7 +600,6 @@ class FuncDeclaration : public Declaration // set if someone took the address of this function int tookAddressOf; bool requiresClosure; // this function needs a closure - bool skipCodegen; // do not generate code for this function // local variables in this function which are referenced by nested functions VarDeclarations closureVars; @@ -637,6 +636,8 @@ class FuncDeclaration : public Declaration bool hasCatches(bool v); bool isCompileTimeOnly() const; bool isCompileTimeOnly(bool v); + bool skipCodegen() const; + bool skipCodegen(bool v); bool printf() const; bool printf(bool v); bool scanf() const; diff --git a/dmd/frontend.h b/dmd/frontend.h index fdbac678fec..ade3ef001fa 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -2472,7 +2472,6 @@ class FuncDeclaration : public Declaration BUILTIN builtin; int32_t tookAddressOf; bool requiresClosure; - bool skipCodegen; Array closureVars; Array outerVars; Array siblingCallers; @@ -2496,6 +2495,8 @@ class FuncDeclaration : public Declaration bool hasCatches(bool v); bool isCompileTimeOnly() const; bool isCompileTimeOnly(bool v); + bool skipCodegen() const; + bool skipCodegen(bool v); bool printf() const; bool printf(bool v); bool scanf() const; diff --git a/dmd/func.d b/dmd/func.d index 2da7e858f84..cfeec41c08b 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -203,6 +203,8 @@ private struct FUNCFLAG bool inferScope; /// infer 'scope' for parameters bool hasCatches; /// function has try-catch statements bool isCompileTimeOnly; /// is a compile time only function; no code will be generated for it + bool skipCodegen; /// do not generate code for this function. + // FIXME: redundant with `isCompileTimeOnly`, see https://github.com/dlang/dmd/pull/14791#discussion_r1065066099 bool printf; /// is a printf-like function bool scanf; /// is a scanf-like function bool noreturn; /// the function does not return @@ -329,7 +331,6 @@ extern (C++) class FuncDeclaration : Declaration int tookAddressOf; bool requiresClosure; // this function needs a closure - bool skipCodegen; // do not generate code for this function /** local variables in this function which are referenced by nested functions * (They'll get put into the "closure" for this function.) diff --git a/dmd/nogc.d b/dmd/nogc.d index 746313f77c4..00701da2ccc 100644 --- a/dmd/nogc.d +++ b/dmd/nogc.d @@ -65,6 +65,30 @@ public: } } + /** + * Register that expression `e` requires the GC + * Params: + * e = expression that uses GC + * format = error message when `e` is used in a `@nogc` function. + * Must contain format strings "`@nogc` %s `%s`" referring to the function. + * Returns: `true` if `err` was set, `false` if it's not in a `@nogc` and not checkonly (-betterC) + */ + private bool setGC(Expression e, const(char)* format) + { + if (checkOnly) + { + err = true; + return true; + } + if (f.setGC()) + { + e.error(format, f.kind(), f.toPrettyChars()); + err = true; + return true; + } + return false; + } + override void visit(CallExp e) { import dmd.id : Id; @@ -76,34 +100,14 @@ public: auto fd = stripHookTraceImpl(e.f); if (fd.ident == Id._d_arraysetlengthT) { - if (checkOnly) - { - err = true; + if (setGC(e, "setting `length` in `@nogc` %s `%s` may cause a GC allocation")) return; - } - if (f.setGC()) - { - e.error("setting `length` in `@nogc` %s `%s` may cause a GC allocation", - f.kind(), f.toPrettyChars()); - err = true; - return; - } f.printGCUsage(e.loc, "setting `length` may cause a GC allocation"); } else if (fd.ident == Id._d_arrayappendT || fd.ident == Id._d_arrayappendcTX) { - if (checkOnly) - { - err = true; + if (setGC(e, "cannot use operator `~=` in `@nogc` %s `%s`")) return; - } - if (f.setGC()) - { - e.error("cannot use operator `~=` in `@nogc` %s `%s`", - f.kind(), f.toPrettyChars()); - err = true; - return; - } f.printGCUsage(e.loc, "operator `~=` may cause a GC allocation"); } } @@ -112,18 +116,8 @@ public: { if (e.type.ty != Tarray || !e.elements || !e.elements.length || e.onstack) return; - if (checkOnly) - { - err = true; + if (setGC(e, "array literal in `@nogc` %s `%s` may cause a GC allocation")) return; - } - if (f.setGC()) - { - e.error("array literal in `@nogc` %s `%s` may cause a GC allocation", - f.kind(), f.toPrettyChars()); - err = true; - return; - } f.printGCUsage(e.loc, "array literal may cause a GC allocation"); } @@ -131,18 +125,8 @@ public: { if (!e.keys.length) return; - if (checkOnly) - { - err = true; + if (setGC(e, "associative array literal in `@nogc` %s `%s` may cause a GC allocation")) return; - } - if (f.setGC()) - { - e.error("associative array literal in `@nogc` %s `%s` may cause a GC allocation", - f.kind(), f.toPrettyChars()); - err = true; - return; - } f.printGCUsage(e.loc, "associative array literal may cause a GC allocation"); } @@ -157,18 +141,9 @@ public: return; if (global.params.ehnogc && e.thrownew) return; // separate allocator is called for this, not the GC - if (checkOnly) - { - err = true; - return; - } - if (f.setGC()) - { - e.error("cannot use `new` in `@nogc` %s `%s`", - f.kind(), f.toPrettyChars()); - err = true; + + if (setGC(e, "cannot use `new` in `@nogc` %s `%s`")) return; - } f.printGCUsage(e.loc, "`new` causes a GC allocation"); } @@ -190,18 +165,8 @@ public: Type t1b = e.e1.type.toBasetype(); if (e.modifiable && t1b.ty == Taarray) { - if (checkOnly) - { - err = true; - return; - } - if (f.setGC()) - { - e.error("assigning an associative array element in `@nogc` %s `%s` may cause a GC allocation", - f.kind(), f.toPrettyChars()); - err = true; + if (setGC(e, "assigning an associative array element in `@nogc` %s `%s` may cause a GC allocation")) return; - } f.printGCUsage(e.loc, "assigning an associative array element may cause a GC allocation"); } } @@ -210,18 +175,8 @@ public: { if (e.e1.op == EXP.arrayLength) { - if (checkOnly) - { - err = true; + if (setGC(e, "setting `length` in `@nogc` %s `%s` may cause a GC allocation")) return; - } - if (f.setGC()) - { - e.error("setting `length` in `@nogc` %s `%s` may cause a GC allocation", - f.kind(), f.toPrettyChars()); - err = true; - return; - } f.printGCUsage(e.loc, "setting `length` may cause a GC allocation"); } } @@ -246,18 +201,8 @@ public: override void visit(CatExp e) { - if (checkOnly) - { - err = true; - return; - } - if (f.setGC()) - { - e.error("cannot use operator `~` in `@nogc` %s `%s`", - f.kind(), f.toPrettyChars()); - err = true; + if (setGC(e, "cannot use operator `~` in `@nogc` %s `%s`")) return; - } f.printGCUsage(e.loc, "operator `~` may cause a GC allocation"); } } From db5d6f1e9cbdf9fbcea2ddd504aef652be929bf2 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Thu, 12 Jan 2023 04:46:23 -0800 Subject: [PATCH 018/177] fix Issue 23407 - ImportC: function-local struct definition as part of variable declaration doesn.t shadow global definition (dlang/dmd!14806) --- dmd/cparse.d | 53 ++++++++++++++++++-------------- tests/dmd/compilable/test23407.i | 22 +++++++++++++ 2 files changed, 52 insertions(+), 23 deletions(-) create mode 100644 tests/dmd/compilable/test23407.i diff --git a/dmd/cparse.d b/dmd/cparse.d index d08cbe35ee5..8a5f11c7d10 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -1641,6 +1641,23 @@ final class CParser(AST) : Parser!AST specifier.packalign = this.packalign; auto tspec = cparseDeclarationSpecifiers(level, specifier); + AST.Dsymbol declareTag(AST.TypeTag tt, ref Specifier specifier) + { + /* `struct tag;` and `struct tag { ... };` + * always result in a declaration in the current scope + */ + auto stag = (tt.tok == TOK.struct_) ? new AST.StructDeclaration(tt.loc, tt.id, false) : + (tt.tok == TOK.union_) ? new AST.UnionDeclaration(tt.loc, tt.id) : + new AST.EnumDeclaration(tt.loc, tt.id, tt.base); + stag.members = tt.members; + tt.members = null; + if (!symbols) + symbols = new AST.Dsymbols(); + auto stags = applySpecifier(stag, specifier); + symbols.push(stags); + return stags; + } + /* If a declarator does not follow, it is unnamed */ if (token.value == TOK.semicolon) @@ -1665,22 +1682,12 @@ final class CParser(AST) : Parser!AST !tt.id && (tt.tok == TOK.struct_ || tt.tok == TOK.union_)) return; // legal but meaningless empty declaration, ignore it - /* `struct tag;` and `struct tag { ... };` - * always result in a declaration in the current scope - */ - auto stag = (tt.tok == TOK.struct_) ? new AST.StructDeclaration(tt.loc, tt.id, false) : - (tt.tok == TOK.union_) ? new AST.UnionDeclaration(tt.loc, tt.id) : - new AST.EnumDeclaration(tt.loc, tt.id, tt.base); - stag.members = tt.members; - if (!symbols) - symbols = new AST.Dsymbols(); - auto stags = applySpecifier(stag, specifier); - symbols.push(stags); + auto stags = declareTag(tt, specifier); if (0 && tt.tok == TOK.enum_) // C11 proscribes enums with no members, but we allow it { if (!tt.members) - error(tt.loc, "`enum %s` has no members", stag.toChars()); + error(tt.loc, "`enum %s` has no members", stags.toChars()); } return; } @@ -1824,17 +1831,8 @@ final class CParser(AST) : Parser!AST { if (tt.id || tt.tok == TOK.enum_) { - /* `struct tag;` and `struct tag { ... };` - * always result in a declaration in the current scope - */ - auto stag = (tt.tok == TOK.struct_) ? new AST.StructDeclaration(tt.loc, tt.id, false) : - (tt.tok == TOK.union_) ? new AST.UnionDeclaration(tt.loc, tt.id) : - new AST.EnumDeclaration(tt.loc, tt.id, tt.base); - stag.members = tt.members; - tt.members = null; - if (!symbols) - symbols = new AST.Dsymbols(); - symbols.push(stag); + Specifier spec; + auto stag = declareTag(tt, spec); if (tt.tok == TOK.enum_) { isalias = false; @@ -1848,6 +1846,15 @@ final class CParser(AST) : Parser!AST } else if (id) { + if (auto tt = dt.isTypeTag()) + { + if (tt.members && (tt.id || tt.tok == TOK.enum_)) + { + Specifier spec; + declareTag(tt, spec); + } + } + if (level == LVL.prototype) break; // declared later as Parameter, not VarDeclaration diff --git a/tests/dmd/compilable/test23407.i b/tests/dmd/compilable/test23407.i new file mode 100644 index 00000000000..538c9588142 --- /dev/null +++ b/tests/dmd/compilable/test23407.i @@ -0,0 +1,22 @@ +// https://issues.dlang.org/show_bug.cgi?id=23407 + +struct Foo { int x; }; +_Static_assert(sizeof(struct Foo) == sizeof(int), ""); + +void one(void){ + struct Foo { + int y, z; + }; + struct Foo f = {0}; + _Static_assert(sizeof(struct Foo) == 2*sizeof(int), ""); +} + +void two(void){ + struct Foo { + int y, z; + } + f + ; + _Static_assert(sizeof(f) == 2*sizeof(int), ""); + _Static_assert(sizeof(struct Foo) == 2*sizeof(int), ""); // fails +} From 484601a8244e4e286b9d5b9ac67753538035ffda Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Thu, 12 Jan 2023 20:30:09 +0100 Subject: [PATCH 019/177] Handle `null` elements in `Array.toString` --- dmd/root/array.d | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/dmd/root/array.d b/dmd/root/array.d index e352c61ce6b..192d86e80dd 100644 --- a/dmd/root/array.d +++ b/dmd/root/array.d @@ -69,7 +69,18 @@ public: { foreach (u; 0 .. a.length) { - buf[u] = toStringFunc(a.data[u]); + static if (is(typeof(a.data[u] is null))) + { + if (a.data[u] is null) + buf[u] = "null"; + else + buf[u] = toStringFunc(a.data[u]); + } + else + { + buf[u] = toStringFunc(a.data[u]); + } + len += buf[u].length + seplen; } } @@ -381,6 +392,19 @@ unittest assert(str == `["hello","world"]`); // Test presence of null terminator. assert(str.ptr[str.length] == '\0'); + + // Test printing an array of classes, which can be null + static class C + { + override string toString() const + { + return "x"; + } + } + auto nullarray = Array!C(2); + nullarray[0] = new C(); + nullarray[1] = null; + assert(nullarray.toString() == `[x,null]`); } unittest From 704960ce6f1a6cfbb92444e9bc41d51494f3b71c Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Thu, 12 Jan 2023 14:27:40 +0200 Subject: [PATCH 020/177] Fix Issue 23617 - traits(child) compile error need this for something that doesn't need this --- dmd/typesem.d | 9 ++++++++- tests/dmd/compilable/test23617.d | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/compilable/test23617.d diff --git a/dmd/typesem.d b/dmd/typesem.d index 0d64ba46a50..59962bbaae7 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -3912,8 +3912,15 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag) { /* Rewrite as: * this.d + * + * only if the scope in which we are + * has a `this` that matches the type + * of the lhs of the dot expression. + * + * https://issues.dlang.org/show_bug.cgi?id=23617 */ - if (hasThis(sc)) + auto fd = hasThis(sc); + if (fd && fd.isThis() == mt.sym) { e = new DotVarExp(e.loc, new ThisExp(e.loc), d); return e.expressionSemantic(sc); diff --git a/tests/dmd/compilable/test23617.d b/tests/dmd/compilable/test23617.d new file mode 100644 index 00000000000..2d03ee7fae9 --- /dev/null +++ b/tests/dmd/compilable/test23617.d @@ -0,0 +1,23 @@ +// https://issues.dlang.org/show_bug.cgi?id=23617 + +struct S +{ + void foo() {} +} + +struct Wrapper +{ + size_t currentIndex; + S[] arrayOfS; + + auto opDispatch(string name, T ...)(T t) + { + return __traits(child, arrayOfS[this.currentIndex], __traits(getMember, S, name))(t); + } +} + +void main() +{ + Wrapper w; + w.opDispatch!"foo"(); +} From 1188b7328f06349938e92ebec51922b1e547bbea Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 20 Dec 2022 13:20:14 -0800 Subject: [PATCH 021/177] fix Issue 21772 - [REG2.069] Consecutive different-signed double.nans in an array literal take the sign of the previous nan (same for float and real) --- dmd/constfold.d | 16 ++-------------- dmd/ctfeexpr.d | 24 +++++------------------- dmd/expression.d | 26 ++++++++++++++++++++++++++ dmd/expression.h | 3 +++ dmd/frontend.h | 3 +++ tests/dmd/runnable/test21772.d | 14 ++++++++++++++ 6 files changed, 53 insertions(+), 33 deletions(-) create mode 100644 tests/dmd/runnable/test21772.d diff --git a/dmd/constfold.d b/dmd/constfold.d index 79bbd5dead5..e4be63cda3e 100644 --- a/dmd/constfold.d +++ b/dmd/constfold.d @@ -845,20 +845,8 @@ UnionExp Identity(EXP op, const ref Loc loc, Type type, Expression e1, Expressio } else { - if (e1.type.isreal()) - { - cmp = CTFloat.isIdentical(e1.toReal(), e2.toReal()); - } - else if (e1.type.isimaginary()) - { - cmp = RealIdentical(e1.toImaginary(), e2.toImaginary()); - } - else if (e1.type.iscomplex()) - { - complex_t v1 = e1.toComplex(); - complex_t v2 = e2.toComplex(); - cmp = RealIdentical(creall(v1), creall(v2)) && RealIdentical(cimagl(v1), cimagl(v1)); - } + if (e1.type.isfloating()) + cmp = e1.isIdentical(e2); else { ue = Equal((op == EXP.identity) ? EXP.equal : EXP.notEqual, loc, type, e1, e2); diff --git a/dmd/ctfeexpr.d b/dmd/ctfeexpr.d index c902149e2b5..8109e12d43d 100644 --- a/dmd/ctfeexpr.d +++ b/dmd/ctfeexpr.d @@ -1281,12 +1281,12 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide { return e1.toInteger() != e2.toInteger(); } + if (identity && e1.type.isfloating()) + return !e1.isIdentical(e2); if (e1.type.isreal() || e1.type.isimaginary()) { real_t r1 = e1.type.isreal() ? e1.toReal() : e1.toImaginary(); real_t r2 = e1.type.isreal() ? e2.toReal() : e2.toImaginary(); - if (identity) - return !CTFloat.isIdentical(r1, r2); if (CTFloat.isNaN(r1) || CTFloat.isNaN(r2)) // if unordered { return 1; // they are not equal @@ -1298,13 +1298,7 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide } else if (e1.type.iscomplex()) { - auto c1 = e1.toComplex(); - auto c2 = e2.toComplex(); - if (identity) - { - return !RealIdentical(c1.re, c2.re) && !RealIdentical(c1.im, c2.im); - } - return c1 != c2; + return e1.toComplex() != e2.toComplex(); } if (e1.op == EXP.structLiteral && e2.op == EXP.structLiteral) { @@ -1415,16 +1409,8 @@ bool ctfeIdentity(const ref Loc loc, EXP op, Expression e1, Expression e2) SymOffExp es2 = e2.isSymOffExp(); cmp = (es1.var == es2.var && es1.offset == es2.offset); } - else if (e1.type.isreal()) - cmp = CTFloat.isIdentical(e1.toReal(), e2.toReal()); - else if (e1.type.isimaginary()) - cmp = RealIdentical(e1.toImaginary(), e2.toImaginary()); - else if (e1.type.iscomplex()) - { - complex_t v1 = e1.toComplex(); - complex_t v2 = e2.toComplex(); - cmp = RealIdentical(creall(v1), creall(v2)) && RealIdentical(cimagl(v1), cimagl(v1)); - } + else if (e1.type.isfloating()) + cmp = e1.isIdentical(e2); else { cmp = !ctfeRawCmp(loc, e1, e2, true); diff --git a/dmd/expression.d b/dmd/expression.d index e0f258c5a57..39fc12d54db 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -1647,6 +1647,15 @@ extern (C++) abstract class Expression : ASTNode return .isConst(this); } + /****** + * Identical, not just equal. I.e. NaNs with different bit patterns are not identical + */ + bool isIdentical(const Expression e) const + { + return equals(e); + } + + /// Statically evaluate this expression to a `bool` if possible /// Returns: an optional thath either contains the value or is empty Optional!bool toBool() @@ -2137,6 +2146,13 @@ extern (C++) final class RealExp : Expression return false; } + override bool isIdentical(const Expression e) const + { + if (!equals(e)) + return false; + return CTFloat.isIdentical(value, e.isRealExp().value); + } + override dinteger_t toInteger() { return cast(sinteger_t)toReal(); @@ -2213,6 +2229,16 @@ extern (C++) final class ComplexExp : Expression return false; } + override bool isIdentical(const Expression e) const + { + if (!equals(e)) + return false; + // equals() regards different NaN values as 'equals' + auto c = e.isComplexExp(); + return CTFloat.isIdentical(creall(value), creall(c.value)) && + CTFloat.isIdentical(cimagl(value), cimagl(c.value)); + } + override dinteger_t toInteger() { return cast(sinteger_t)toReal(); diff --git a/dmd/expression.h b/dmd/expression.h index 7202960af63..b809ffe6dfb 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -123,6 +123,7 @@ class Expression : public ASTNode // A compile-time result is required. Give an error if not possible Expression *ctfeInterpret(); int isConst(); + virtual bool isIdentical(const Expression *e) const; virtual Optional toBool(); virtual bool hasCode() { @@ -281,6 +282,7 @@ class RealExp final : public Expression static RealExp *create(const Loc &loc, real_t value, Type *type); static void emplace(UnionExp *pue, const Loc &loc, real_t value, Type *type); bool equals(const RootObject * const o) const override; + bool isIdentical(const Expression *e) const override; dinteger_t toInteger() override; uinteger_t toUInteger() override; real_t toReal() override; @@ -298,6 +300,7 @@ class ComplexExp final : public Expression static ComplexExp *create(const Loc &loc, complex_t value, Type *type); static void emplace(UnionExp *pue, const Loc &loc, complex_t value, Type *type); bool equals(const RootObject * const o) const override; + bool isIdentical(const Expression *e) const override; dinteger_t toInteger() override; uinteger_t toUInteger() override; real_t toReal() override; diff --git a/dmd/frontend.h b/dmd/frontend.h index ade3ef001fa..e6a91e513ae 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -1026,6 +1026,7 @@ class Expression : public ASTNode Expression* optimize(int32_t result, bool keepLvalue = false); Expression* ctfeInterpret(); int32_t isConst(); + virtual bool isIdentical(const Expression* const e) const; virtual Optional toBool(); virtual bool hasCode(); IntegerExp* isIntegerExp(); @@ -6955,6 +6956,7 @@ class RealExp final : public Expression static RealExp* create(const Loc& loc, _d_real value, Type* type); static void emplace(UnionExp* pue, const Loc& loc, _d_real value, Type* type); bool equals(const RootObject* const o) const override; + bool isIdentical(const Expression* const e) const override; dinteger_t toInteger() override; uinteger_t toUInteger() override; _d_real toReal() override; @@ -6971,6 +6973,7 @@ class ComplexExp final : public Expression static ComplexExp* create(const Loc& loc, complex_t value, Type* type); static void emplace(UnionExp* pue, const Loc& loc, complex_t value, Type* type); bool equals(const RootObject* const o) const override; + bool isIdentical(const Expression* const e) const override; dinteger_t toInteger() override; uinteger_t toUInteger() override; _d_real toReal() override; diff --git a/tests/dmd/runnable/test21772.d b/tests/dmd/runnable/test21772.d new file mode 100644 index 00000000000..dcb7b8088db --- /dev/null +++ b/tests/dmd/runnable/test21772.d @@ -0,0 +1,14 @@ +// https://issues.dlang.org/show_bug.cgi?id=21772 + +import core.stdc.string; + +int main() +{ + //import std.stdio : writeln; + + double[] a = [-double.nan, double.nan, double.nan, + 1.0, double.nan, -double.nan]; + //writeln(a); // Writes "[-nan, -nan, -nan, 1, nan, nan]" (Uh-oh!) + assert(memcmp(&a[0], &a[1], double.sizeof) != 0); + return 0; +} From a759d7fec2ae5a442281321de810bee3bf7029d1 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 13 Jan 2023 00:30:20 -0800 Subject: [PATCH 022/177] fix Issue 23622 - ImportC #defines conflict with declarations --- dmd/cparse.d | 2 ++ dmd/declaration.d | 1 + dmd/declaration.h | 2 ++ dmd/dsymbol.d | 6 ++++++ dmd/frontend.h | 2 ++ tests/dmd/compilable/test23622.c | 7 +++++++ 6 files changed, 20 insertions(+) create mode 100644 tests/dmd/compilable/test23622.c diff --git a/dmd/cparse.d b/dmd/cparse.d index 8a5f11c7d10..efb68ea3987 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -5306,6 +5306,8 @@ final class CParser(AST) : Parser!AST void addVar(AST.VarDeclaration v) { + //printf("addVar() %s\n", v.toChars()); + v.isCmacro(true); // mark it as coming from a C #define /* If it's already defined, replace the earlier * definition */ diff --git a/dmd/declaration.d b/dmd/declaration.d index 51737cef2c6..d13236b68db 100644 --- a/dmd/declaration.d +++ b/dmd/declaration.d @@ -1148,6 +1148,7 @@ extern (C++) class VarDeclaration : Declaration bool doNotInferReturn; /// do not infer 'return' for this variable bool isArgDtorVar; /// temporary created to handle scope destruction of a function argument + bool isCmacro; /// it is a C macro turned into a C declaration } import dmd.common.bitfields : generateBitFields; diff --git a/dmd/declaration.h b/dmd/declaration.h index cf3487cff48..c4385d31639 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -270,6 +270,8 @@ class VarDeclaration : public Declaration bool doNotInferReturn(bool v); bool isArgDtorVar() const; // temporary created to handle scope destruction of a function argument bool isArgDtorVar(bool v); + bool isCmacro() const; // if a C macro turned into a C variable + bool isCmacro(bool v); static VarDeclaration *create(const Loc &loc, Type *t, Identifier *id, Initializer *init, StorageClass storage_class = STCundefined); VarDeclaration *syntaxCopy(Dsymbol *) override; void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override final; diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index 3611e09c286..acd50822195 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -2620,6 +2620,12 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy auto vd = s.isVarDeclaration(); // new declaration auto vd2 = s2.isVarDeclaration(); // existing declaration + + if (vd && vd.isCmacro()) + return vd2; + + assert(!(vd2 && vd2.isCmacro())); + if (vd && vd2) { /* if one is `static` and the other isn't, the result is undefined diff --git a/dmd/frontend.h b/dmd/frontend.h index e6a91e513ae..a5778a1784e 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -5944,6 +5944,8 @@ class VarDeclaration : public Declaration bool doNotInferReturn(bool v); bool isArgDtorVar() const; bool isArgDtorVar(bool v); + bool isCmacro() const; + bool isCmacro(bool v); private: uint16_t bitFields; public: diff --git a/tests/dmd/compilable/test23622.c b/tests/dmd/compilable/test23622.c new file mode 100644 index 00000000000..009da1484ba --- /dev/null +++ b/tests/dmd/compilable/test23622.c @@ -0,0 +1,7 @@ +// https://issues.dlang.org/show_bug.cgi?id=23622 + +int FP_NAN = 0; +#define FP_NAN 0 + +enum E { ENUM = 0 }; +#define ENUM 0 From ed337b497d948eb41c535d2ee4dfa7c979cafc64 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 10 Jan 2023 19:10:24 -0800 Subject: [PATCH 023/177] fix Issue 23583 - ImportC: undefined identifier __builtin___memmove_chk --- runtime/druntime/src/importc.h | 22 +++++++++++++++++++++- tests/dmd/compilable/test23583.c | 22 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/compilable/test23583.c diff --git a/runtime/druntime/src/importc.h b/runtime/druntime/src/importc.h index bf5ac518940..3854114608d 100644 --- a/runtime/druntime/src/importc.h +++ b/runtime/druntime/src/importc.h @@ -69,7 +69,7 @@ /******************************** * __has_extension is a clang thing: * https://clang.llvm.org/docs/LanguageExtensions.html - * ImportC doesn't has those extensions. + * ImportC no has extensions. */ #undef __has_feature #define __has_feature(x) 0 @@ -77,6 +77,26 @@ #undef __has_extension #define __has_extension(x) 0 +#undef __has_builtin +#define __has_builtin(x) 0 + +/************************************* + * OS-specific macros + */ +#if __APPLE__ +#define __builtin___memmove_chk(dest, src, len, x) memmove(dest,src,len) // put it back to memmove() +#define __builtin___memcpy_chk(dest, src, len, x) memcpy(dest,src,len) +#define __builtin___memset_chk(dest, val, len, x) memset(dest,val,len) +#define __builtin___stpcpy_chk(dest, src, x) stpcpy(dest,src) +#define __builtin___stpncpy_chk(dest, src, len, x) stpncpy(dest,src,len) +#define __builtin___strcat_chk(dest, src, x) strcat(dest,src) +#define __builtin___strcpy_chk(dest, src, x) strcpy(dest,src) +#define __builtin___strncat_chk(dest, src, len, x) strncat(dest,src,len) +#define __builtin___strncpy_chk(dest, src, len, x) strncpy(dest,src,len) +#endif + +#if __FreeBSD__ +#endif /**************************** * Define it to do what other C compilers do. diff --git a/tests/dmd/compilable/test23583.c b/tests/dmd/compilable/test23583.c new file mode 100644 index 00000000000..53581790108 --- /dev/null +++ b/tests/dmd/compilable/test23583.c @@ -0,0 +1,22 @@ + +// https://issues.dlang.org/show_bug.cgi?id=23580 +// https://issues.dlang.org/show_bug.cgi?id=23581 +// https://issues.dlang.org/show_bug.cgi?id=23582 +// https://issues.dlang.org/show_bug.cgi?id=23583 + +#include + +void foo() +{ + memmove(0, 0, 0); + memcpy(0, 0, 0); + memset(0, 0, 0); +#if __APPLE__ + stpcpy(0, 0); + stpncpy(0, 0, 0); +#endif + strcat(0, 0); + strcpy(0, 0); + strncat(0, 0, 0); + strncpy(0, 0, 0); +} From 96a8380f7f5a5d4e541b56bdd3aba67e429d8cb5 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sat, 14 Jan 2023 21:17:21 +0000 Subject: [PATCH 024/177] =?UTF-8?q?Fix=20Issue=C2=A023624=20-=20Race=20con?= =?UTF-8?q?dition=20in=20test=20runner=20for=20DMD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/dmd/run.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dmd/run.d b/tests/dmd/run.d index e1c1064cb01..eb83593433a 100755 --- a/tests/dmd/run.d +++ b/tests/dmd/run.d @@ -197,7 +197,7 @@ Options: : "`unit` tests"; writeln(">>> TARGET FAILED: ", name); - failedTargets ~= name; + synchronized failedTargets ~= name; } } if (failedTargets.length > 0) From c9529c8bf1d0e029cb5170ea7446dc386714b6a8 Mon Sep 17 00:00:00 2001 From: KytoDragon Date: Sat, 14 Jan 2023 15:29:24 +0100 Subject: [PATCH 025/177] Fix 23625 - Add missing memory functions for windows --- .../druntime/src/core/sys/windows/winbase.d | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/runtime/druntime/src/core/sys/windows/winbase.d b/runtime/druntime/src/core/sys/windows/winbase.d index 3b571ad57da..bbb6e9a7b41 100644 --- a/runtime/druntime/src/core/sys/windows/winbase.d +++ b/runtime/druntime/src/core/sys/windows/winbase.d @@ -38,6 +38,7 @@ import core.sys.windows.basetyps, core.sys.windows.w32api, core.sys.windows.winn // FIXME: //alias void va_list; import core.stdc.stdarg : va_list; +import core.stdc.string : memset, memcpy, memmove; // COMMPROP structure, used by GetCommProperties() @@ -1713,23 +1714,15 @@ extern (Windows) nothrow @nogc { BOOL CopyFileExA(LPCSTR, LPCSTR, LPPROGRESS_ROUTINE, LPVOID, LPBOOL, DWORD); BOOL CopyFileExW(LPCWSTR, LPCWSTR, LPPROGRESS_ROUTINE, LPVOID, LPBOOL, DWORD); - /+ FIXME - alias memmove RtlMoveMemory; - alias memcpy RtlCopyMemory; + alias RtlMoveMemory = memmove; + alias RtlCopyMemory = memcpy; + pragma(inline, true) void RtlFillMemory(PVOID Destination, SIZE_T Length, BYTE Fill) { memset(Destination, Fill, Length); } + pragma(inline, true) void RtlZeroMemory(PVOID Destination, SIZE_T Length) { memset(Destination, 0, Length); } + alias MoveMemory = RtlMoveMemory; + alias CopyMemory = RtlCopyMemory; + alias FillMemory = RtlFillMemory; + alias ZeroMemory = RtlZeroMemory; - void RtlFillMemory(PVOID dest, SIZE_T len, BYTE fill) { - memset(dest, fill, len); - } - - void RtlZeroMemory(PVOID dest, SIZE_T len) { - RtlFillMemory(dest, len, 0); - } - - alias RtlMoveMemory MoveMemory; - alias RtlCopyMemory CopyMemory; - alias RtlFillMemory FillMemory; - alias RtlZeroMemory ZeroMemory; - +/ BOOL CreateDirectoryA(LPCSTR, LPSECURITY_ATTRIBUTES); BOOL CreateDirectoryW(LPCWSTR, LPSECURITY_ATTRIBUTES); BOOL CreateDirectoryExA(LPCSTR, LPCSTR, LPSECURITY_ATTRIBUTES); From 1842a685ab4981ec963831dbee7302d0e8d8e9a9 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sun, 15 Jan 2023 10:58:02 +0000 Subject: [PATCH 026/177] Declare failedTargets shared --- tests/dmd/run.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dmd/run.d b/tests/dmd/run.d index eb83593433a..3d1ddf883fb 100755 --- a/tests/dmd/run.d +++ b/tests/dmd/run.d @@ -185,7 +185,7 @@ Options: if (targets.length > 0) { - string[] failedTargets; + shared string[] failedTargets; foreach (target; parallel(targets, 1)) { log("run: %-(%s %)", target.args); From aedb9714899a86433b136d02acff9f912afa0367 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sat, 14 Jan 2023 22:29:20 +0100 Subject: [PATCH 027/177] =?UTF-8?q?follow-up=20Issue=C2=A023626=20-=20inve?= =?UTF-8?q?rt=20trustSystemEqualsDefault=20initializer=20to=20true?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the desired behaviour for any future users of this function. --- dmd/mtype.d | 4 ++-- dmd/opover.d | 5 ++++- dmd/semantic2.d | 8 ++++++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/dmd/mtype.d b/dmd/mtype.d index 037885f9e08..efc14cf1a2e 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -4828,7 +4828,7 @@ extern (C++) final class TypeFunction : TypeNext override MATCH constConv(Type to) { // Attributes need to match exactly, otherwise it's an implicit conversion - if (this.ty != to.ty || !this.attributesEqual(cast(TypeFunction) to, true)) + if (this.ty != to.ty || !this.attributesEqual(cast(TypeFunction) to)) return MATCH.nomatch; return super.constConv(to); @@ -4871,7 +4871,7 @@ extern (C++) final class TypeFunction : TypeNext } /// Returns: whether `this` function type has the same attributes (`@safe`,...) as `other` - extern (D) bool attributesEqual(const scope TypeFunction other, bool trustSystemEqualsDefault = false) const pure nothrow @safe @nogc + extern (D) bool attributesEqual(const scope TypeFunction other, bool trustSystemEqualsDefault = true) const pure nothrow @safe @nogc { // @@@DEPRECATED_2.112@@@ // See semantic2.d Semantic2Visitor.visit(FuncDeclaration): diff --git a/dmd/opover.d b/dmd/opover.d index 4d7fe9fcea3..3db111b8e61 100644 --- a/dmd/opover.d +++ b/dmd/opover.d @@ -1746,7 +1746,10 @@ private FuncDeclaration findBestOpApplyMatch(Expression ethis, FuncDeclaration f // Found another overload with different attributes? // e.g. @system vs. @safe opApply - bool ambig = tf.attributesEqual(bestTf); + // @@@DEPRECATED_2.112@@@ + // See semantic2.d Semantic2Visitor.visit(FuncDeclaration): + // Remove `false` after deprecation period is over. + bool ambig = tf.attributesEqual(bestTf, false); // opApplies with identical attributes could still accept // different function bodies as delegate diff --git a/dmd/semantic2.d b/dmd/semantic2.d index 26f1c9eb226..50af3f6fb5d 100644 --- a/dmd/semantic2.d +++ b/dmd/semantic2.d @@ -439,7 +439,11 @@ private extern(C++) final class Semantic2Visitor : Visitor if (tf1.mod != tf2.mod || ((f1.storage_class ^ f2.storage_class) & STC.static_)) return 0; - const sameAttr = tf1.attributesEqual(tf2); + // @@@DEPRECATED_2.112@@@ + // This test doesn't catch identical functions that differ only + // in explicit/implicit `@system` - a deprecation has now been + // added below, remove `false` after deprecation period is over. + const sameAttr = tf1.attributesEqual(tf2, false); const sameParams = tf1.parameterList == tf2.parameterList; // Allow the hack to declare overloads with different parameters/STC's @@ -467,7 +471,7 @@ private extern(C++) final class Semantic2Visitor : Visitor // Same as 2.104 deprecation, but also catching explicit/implicit `@system` // At the end of deprecation period, fix Type.attributesEqual and remove // this condition, as well as the error for extern(C) functions above. - if (sameAttr != tf1.attributesEqual(tf2, true)) + if (sameAttr != tf1.attributesEqual(tf2)) { f2.deprecation("cannot overload `extern(%s)` function at %s", linkageToChars(f1._linkage), From dadf9e993510cb27e512d44b3a3499565702a284 Mon Sep 17 00:00:00 2001 From: Vladimir Panteleev Date: Sun, 8 Jan 2023 17:46:35 +0000 Subject: [PATCH 028/177] core.sys.posix.sys.stat: Fix duplicate definition of __mode_t on Musl The definition was conflicting with the other definitions within the same file. --- runtime/druntime/src/core/sys/posix/sys/stat.d | 1 - 1 file changed, 1 deletion(-) diff --git a/runtime/druntime/src/core/sys/posix/sys/stat.d b/runtime/druntime/src/core/sys/posix/sys/stat.d index ecc98ccf0ed..680b424398c 100644 --- a/runtime/druntime/src/core/sys/posix/sys/stat.d +++ b/runtime/druntime/src/core/sys/posix/sys/stat.d @@ -1656,7 +1656,6 @@ else version (CRuntime_Bionic) } else version (CRuntime_Musl) { - alias __mode_t = uint; enum { S_IRUSR = 0x100, // octal 0400 S_IWUSR = 0x080, // octal 0200 From 7b549436e499c0d9756991875e328897f9615e51 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Mon, 16 Jan 2023 14:25:03 +0100 Subject: [PATCH 029/177] src/dmd/errors.d(384): `old_loc` is thread local --- dmd/errors.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmd/errors.d b/dmd/errors.d index 9265ded030b..b9a533565d8 100644 --- a/dmd/errors.d +++ b/dmd/errors.d @@ -381,7 +381,7 @@ private void verrorPrint(const ref Loc loc, Color headerColor, const(char)* head fputs(tmp.peekChars(), stderr); fputc('\n', stderr); - static Loc old_loc; + __gshared Loc old_loc; if (global.params.printErrorContext && // ignore supplemental messages with same loc (loc != old_loc || strchr(header, ':')) && From 8b5ae232e285ca7979521b008cbf875d6b019495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Ferreira?= Date: Tue, 17 Jan 2023 10:22:25 +0000 Subject: [PATCH 030/177] druntime: avoid using compiler tricks of unspeciefied .mangleof (dlang/dmd!14832) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Luís Ferreira Signed-off-by: Luís Ferreira --- runtime/druntime/src/core/memory.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/druntime/src/core/memory.d b/runtime/druntime/src/core/memory.d index 7d1356af0be..96c2af478d3 100644 --- a/runtime/druntime/src/core/memory.d +++ b/runtime/druntime/src/core/memory.d @@ -202,8 +202,8 @@ unittest // make it more difficult to call the function again, manually. private void initialize(); pragma(crt_constructor) -pragma(mangle, `_D` ~ initialize.mangleof) -private extern (C) void initialize() @system +pragma(mangle, initialize.mangleof) +private extern (C) void _initialize() @system { version (Posix) { From 0ccd11c395c2eca370075c948164edaadb9ae9af Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 17 Jan 2023 03:48:06 -0800 Subject: [PATCH 031/177] fix Issue 21492 - betterC: TypeInfo is generated for code guarded by if(__ctfe) (dlang/dmd!14830) --- tests/dmd/runnable/test21492.d | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/dmd/runnable/test21492.d diff --git a/tests/dmd/runnable/test21492.d b/tests/dmd/runnable/test21492.d new file mode 100644 index 00000000000..b235fb4de1b --- /dev/null +++ b/tests/dmd/runnable/test21492.d @@ -0,0 +1,34 @@ +/* REQUIRED_ARGS: -betterC + */ + +// https://issues.dlang.org/show_bug.cgi?id=21492 + +int test(int i) +{ + switch (i) + { + case 0: + break; + case 1: + if (__ctfe) + { + { int[] foo = [1]; } + L3: + i += 2; + case 2: + ++i; + } + return i; + default: + break; + } + goto L3; +} + +extern (C) +int main() +{ + static assert(test(1) == 4); + assert(test(2) == 3); + return 0; +} From 4a2cd0bc4cf1e9dc3d566866a1ffdccaebd63e9c Mon Sep 17 00:00:00 2001 From: Dennis Date: Tue, 17 Jan 2023 13:08:30 +0100 Subject: [PATCH 032/177] Add named arguments to struct literals (dlang/dmd!14776) * Add named argument parsing * Refactor StructInitializer semantic to make it reusable * Move out `resolveStructLiteralNamedArgs` * Resolve named args in struct literal * Add tests * Check for errors returned by `resolveStructLiteralNamedArgs` * Expand names along with tuples * Update error messages in tests * Convert tabs to spaces in named arg test * Fix style of `resolveStructLiteralNamedArgs` * Clarify 'fixme' comment in expandTuples * Add example to `expandTuples` documentation * Update compiler/src/dmd/initsem.d Co-authored-by: Razvan Nitu * Add overlapping initialization supplemental error to Struct Initializer * Improve "too many initializers" error message Co-authored-by: Razvan Nitu --- dmd/expression.d | 66 ++++- dmd/expression.h | 3 +- dmd/expressionsem.d | 30 ++- dmd/frontend.h | 3 +- dmd/initsem.d | 252 +++++++++++------- dmd/parse.d | 46 +++- tests/dmd/compilable/named_argumens_struct.d | 24 ++ tests/dmd/fail_compilation/diag11132.d | 3 +- tests/dmd/fail_compilation/fail155.d | 2 +- tests/dmd/fail_compilation/fail156.d | 4 +- tests/dmd/fail_compilation/fail158.d | 2 +- tests/dmd/fail_compilation/fail22570.d | 4 +- tests/dmd/fail_compilation/fail299.d | 2 +- .../fail_compilation/named_arguments_parse.d | 15 ++ tests/dmd/fail_compilation/test20998.d | 14 +- 15 files changed, 329 insertions(+), 141 deletions(-) create mode 100644 tests/dmd/compilable/named_argumens_struct.d create mode 100644 tests/dmd/fail_compilation/named_arguments_parse.d diff --git a/dmd/expression.d b/dmd/expression.d index 39fc12d54db..2e384dcf6f9 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -249,18 +249,63 @@ bool isDotOpDispatch(Expression e) } /**************************************** - * Expand tuples. - * Input: - * exps aray of Expressions - * Output: - * exps rewritten in place + * Expand tuples in-place. + * + * Example: + * When there's a call `f(10, pair: AliasSeq!(20, 30), single: 40))`, the input is: + * exps = [10, (20, 30), 40] + * names = [null, "pair", "single"]); + * The arrays will be modified to: + * exps = [10, 20, 30, 40] + * names = [null, "pair", null, "single"]); + * + * Params: + * exps = array of Expressions + * names = optional array of names corresponding to Expressions */ -extern (C++) void expandTuples(Expressions* exps) +extern (C++) void expandTuples(Expressions* exps, Identifiers* names = null) { //printf("expandTuples()\n"); if (exps is null) return; + if (names) + { + if (exps.length != names.length) + { + // Fixme: this branch should be removed when CallExp rewrites + // (UFCS/operator overloading) are fixed to take named arguments into account + names.setDim(exps.length); + foreach (i; 0..exps.length) + (*names)[i] = null; + } + if (exps.length != names.length) + { + printf("exps.length = %d, names.length = %d\n", cast(int) exps.length, cast(int) names.length); + printf("exps = %s, names = %s\n", exps.toChars(), names.toChars()); + if (exps.length > 0) + printf("%s\n", (*exps)[0].loc.toChars()); + assert(0); + } + } + + // At `index`, a tuple of length `length` is expanded. Insert corresponding nulls in `names`. + void expandNames(size_t index, size_t length) + { + if (names) + { + if (length == 0) + { + names.remove(index); + return; + } + foreach (i; 1 .. length) + { + names.insert(index + i, cast(Identifier) null); + } + } + } + for (size_t i = 0; i < exps.length; i++) { Expression arg = (*exps)[i]; @@ -275,6 +320,7 @@ extern (C++) void expandTuples(Expressions* exps) if (!tt.arguments || tt.arguments.length == 0) { exps.remove(i); + expandNames(i, 0); if (i == exps.length) return; } @@ -285,6 +331,7 @@ extern (C++) void expandTuples(Expressions* exps) foreach (j, a; *tt.arguments) (*texps)[j] = new TypeExp(e.loc, a.type); exps.insert(i, texps); + expandNames(i, texps.length); } i--; continue; @@ -297,6 +344,7 @@ extern (C++) void expandTuples(Expressions* exps) TupleExp te = cast(TupleExp)arg; exps.remove(i); // remove arg exps.insert(i, te.exps); // replace with tuple contents + expandNames(i, te.exps.length); if (i == exps.length) return; // empty tuple, no more arguments (*exps)[i] = Expression.combine(te.e0, (*exps)[i]); @@ -5079,16 +5127,18 @@ extern (C++) final class DotTypeExp : UnaExp extern (C++) final class CallExp : UnaExp { Expressions* arguments; // function arguments + Identifiers* names; // named argument identifiers FuncDeclaration f; // symbol to call bool directcall; // true if a virtual call is devirtualized bool inDebugStatement; /// true if this was in a debug statement bool ignoreAttributes; /// don't enforce attributes (e.g. call @gc function in @nogc code) VarDeclaration vthis2; // container for multi-context - extern (D) this(const ref Loc loc, Expression e, Expressions* exps) + extern (D) this(const ref Loc loc, Expression e, Expressions* exps, Identifiers* names = null) { super(loc, EXP.call, __traits(classInstanceSize, CallExp), e); this.arguments = exps; + this.names = names; } extern (D) this(const ref Loc loc, Expression e) @@ -5155,7 +5205,7 @@ extern (C++) final class CallExp : UnaExp override CallExp syntaxCopy() { - return new CallExp(loc, e1.syntaxCopy(), arraySyntaxCopy(arguments)); + return new CallExp(loc, e1.syntaxCopy(), arraySyntaxCopy(arguments), names); } override bool isLvalue() diff --git a/dmd/expression.h b/dmd/expression.h index b809ffe6dfb..f491c1d9c27 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -45,7 +45,7 @@ typedef union tree_node Symbol; struct Symbol; // back end symbol #endif -void expandTuples(Expressions *exps); +void expandTuples(Expressions *exps, Identifiers *names = nullptr); bool isTrivialExp(Expression *e); bool hasSideEffect(Expression *e, bool assumeImpureCalls = false); @@ -826,6 +826,7 @@ class CallExp final : public UnaExp { public: Expressions *arguments; // function arguments + Identifiers *names; FuncDeclaration *f; // symbol to call bool directcall; // true if a virtual call is devirtualized bool inDebugStatement; // true if this was in a debug statement diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 4cc7e9a8681..bd04d429f25 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -651,6 +651,9 @@ private Expression resolveUFCS(Scope* sc, CallExp ce) if (!ce.arguments) ce.arguments = new Expressions(); ce.arguments.shift(eleft); + if (!ce.names) + ce.names = new Identifiers(); + ce.names.shift(null); return null; } @@ -1629,12 +1632,12 @@ private Expression rewriteOpAssign(BinExp exp) * Returns: * true a semantic error occurred */ -private bool preFunctionParameters(Scope* sc, Expressions* exps, const bool reportErrors = true) +private bool preFunctionParameters(Scope* sc, Identifiers* names, Expressions* exps, const bool reportErrors = true) { bool err = false; if (exps) { - expandTuples(exps); + expandTuples(exps, names); for (size_t i = 0; i < exps.length; i++) { @@ -3549,7 +3552,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { return setError(); } - if (preFunctionParameters(sc, exp.arguments)) + if (preFunctionParameters(sc, /*names*/ null, exp.arguments)) { return setError(); } @@ -4287,7 +4290,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (FuncExp fe = exp.e1.isFuncExp()) { if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc) || - preFunctionParameters(sc, exp.arguments)) + preFunctionParameters(sc, exp.names, exp.arguments)) return setError(); // Run e1 semantic even if arguments have any errors @@ -4526,7 +4529,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc) || - preFunctionParameters(sc, exp.arguments)) + preFunctionParameters(sc, exp.names, exp.arguments)) return setError(); // Check for call operator overload @@ -4624,7 +4627,22 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor /* It's a struct literal */ Lx: - Expression e = new StructLiteralExp(exp.loc, sd, exp.arguments, exp.e1.type); + Expressions* resolvedArgs = exp.arguments; + if (exp.names) + { + resolvedArgs = resolveStructLiteralNamedArgs(sd, exp.e1.type, sc, exp.loc, + (*exp.names)[], + (size_t i, Type t) => (*exp.arguments)[i], + i => (*exp.arguments)[i].loc + ); + if (!resolvedArgs) + { + result = ErrorExp.get(); + return; + } + } + + Expression e = new StructLiteralExp(exp.loc, sd, resolvedArgs, exp.e1.type); e = e.expressionSemantic(sc); result = e; return; diff --git a/dmd/frontend.h b/dmd/frontend.h index f67e2621de4..fc1058a682a 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -6874,7 +6874,7 @@ class VersionSymbol final : public Dsymbol void accept(Visitor* v) override; }; -extern void expandTuples(Array* exps); +extern void expandTuples(Array* exps, Array* names = nullptr); struct UnionExp final { @@ -7422,6 +7422,7 @@ class CallExp final : public UnaExp { public: Array* arguments; + Array* names; FuncDeclaration* f; bool directcall; bool inDebugStatement; diff --git a/dmd/initsem.d b/dmd/initsem.d index 572753b2dd8..18b10b41a2d 100644 --- a/dmd/initsem.d +++ b/dmd/initsem.d @@ -135,111 +135,19 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ sd.size(i.loc); if (sd.sizeok != Sizeok.done) return err(); - const nfields = sd.nonHiddenFields(); - //expandTuples for non-identity arguments? - auto elements = new Expressions(nfields); - auto elems = (*elements)[]; - foreach (ref elem; elems) - elem = null; - - // Run semantic for explicitly given initializers - // TODO: this part is slightly different from StructLiteralExp::semantic. - bool errors = false; - size_t fieldi = 0; - foreach (j, id; i.field[]) - { - if (id) - { - /* Determine `fieldi` that `id` matches - */ - Dsymbol s = sd.search(i.loc, id); - if (!s) - { - s = sd.search_correct(id); - const initLoc = i.value[j].loc; - if (s) - error(initLoc, "`%s` is not a member of `%s`, did you mean %s `%s`?", id.toChars(), sd.toChars(), s.kind(), s.toChars()); - else - error(initLoc, "`%s` is not a member of `%s`", id.toChars(), sd.toChars()); - return err(); - } - s.checkDeprecated(i.loc, sc); - s = s.toAlias(); - - // Find out which field index `s` is - for (fieldi = 0; 1; fieldi++) - { - if (fieldi >= nfields) - { - error(i.loc, "`%s.%s` is not a per-instance initializable field", sd.toChars(), s.toChars()); - return err(); - } - if (s == sd.fields[fieldi]) - break; - } - } - if (j >= nfields) - { - error(i.value[j].loc, "too many initializers for `%s`", sd.toChars()); - return err(); - } - - VarDeclaration vd = sd.fields[fieldi]; - if (elems[fieldi]) - { - error(i.value[j].loc, "duplicate initializer for field `%s`", vd.toChars()); - errors = true; - elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors - ++fieldi; - continue; - } - - // Check for @safe violations - if (vd.type.hasPointers) - { - if ((!t.alignment.isDefault() && t.alignment.get() < target.ptrsize || - (vd.offset & (target.ptrsize - 1)))) - { - if (sc.setUnsafe(false, i.value[j].loc, - "field `%s.%s` cannot assign to misaligned pointers in `@safe` code", sd, vd)) - { - errors = true; - elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors - ++fieldi; - continue; - } - } - } - - // Check for overlapping initializations (can happen with unions) - foreach (k, v2; sd.fields[0 .. nfields]) - { - if (vd.isOverlappedWith(v2) && elems[k]) - { - error(elems[k].loc, "overlapping initialization for field `%s` and `%s`", v2.toChars(), vd.toChars()); - errors = true; - continue; - } - } - - // Convert initializer to Expression `ex` - assert(sc); - auto tm = vd.type.addMod(t.mod); - auto iz = i.value[j].initializerSemantic(sc, tm, needInterpret); - auto ex = iz.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0); - if (ex.op == EXP.error) - { - errors = true; - elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors - ++fieldi; - continue; - } + Expression getExp(size_t j, Type fieldType) + { + // Convert initializer to Expression `ex` + auto tm = fieldType.addMod(t.mod); + auto iz = i.value[j].initializerSemantic(sc, tm, needInterpret); + auto ex = iz.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0); + if (ex.op != EXP.error) i.value[j] = iz; - elems[fieldi] = doCopyOrMove(sc, ex); - ++fieldi; - } - if (errors) + return ex; + } + auto elements = resolveStructLiteralNamedArgs(sd, t, sc, i.loc, i.field[], &getExp, (size_t j) => i.value[j].loc); + if (!elements) return err(); // Make a StructLiteralExp out of elements[] @@ -1514,3 +1422,141 @@ private bool hasNonConstPointers(Expression e) } return false; } + +/** +Given the names and values of a `StructInitializer` or `CallExp`, +resolve it to a list of expressions to construct a `StructLiteralExp`. + +Params: + sd = struct + t = type of struct (potentially including qualifiers such as `const` or `immutable`) + sc = scope of the expression initializing the struct + iloc = location of expression initializing the struct + names = identifiers passed in argument list, `null` entries for positional arguments + getExp = function that, given an index into `names` and destination type, returns the initializing expression + getLoc = function that, given an index into `names`, returns a location for error messages + +Returns: list of expressions ordered to the struct's fields, or `null` on error +*/ +Expressions* resolveStructLiteralNamedArgs(StructDeclaration sd, Type t, Scope* sc, + Loc iloc, Identifier[] names, scope Expression delegate(size_t i, Type fieldType) getExp, + scope Loc delegate(size_t i) getLoc +) +{ + //expandTuples for non-identity arguments? + const nfields = sd.nonHiddenFields(); + auto elements = new Expressions(nfields); + auto elems = (*elements)[]; + foreach (ref elem; elems) + elem = null; + + // Run semantic for explicitly given initializers + // TODO: this part is slightly different from StructLiteralExp::semantic. + bool errors = false; + size_t fieldi = 0; + foreach (j, id; names) + { + const argLoc = getLoc(j); + if (id) + { + // Determine `fieldi` that `id` matches + Dsymbol s = sd.search(iloc, id); + if (!s) + { + s = sd.search_correct(id); + if (s) + error(argLoc, "`%s` is not a member of `%s`, did you mean %s `%s`?", id.toChars(), sd.toChars(), s.kind(), s.toChars()); + else + error(argLoc, "`%s` is not a member of `%s`", id.toChars(), sd.toChars()); + return null; + } + s.checkDeprecated(iloc, sc); + s = s.toAlias(); + + // Find out which field index `s` is + for (fieldi = 0; 1; fieldi++) + { + if (fieldi >= nfields) + { + error(iloc, "`%s.%s` is not a per-instance initializable field", sd.toChars(), s.toChars()); + return null; + } + if (s == sd.fields[fieldi]) + break; + } + } + if (nfields == 0) + { + error(argLoc, "initializer provided for struct `%s` with no fields", sd.toChars()); + return null; + } + if (j >= nfields) + { + error(argLoc, "too many initializers for `%s` with %d field%s", sd.toChars(), + cast(int) nfields, nfields != 1 ? "s".ptr : "".ptr); + return null; + } + + VarDeclaration vd = sd.fields[fieldi]; + if (elems[fieldi]) + { + error(argLoc, "duplicate initializer for field `%s`", vd.toChars()); + errors = true; + elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors + ++fieldi; + continue; + } + + // Check for @safe violations + if (vd.type.hasPointers) + { + if ((!t.alignment.isDefault() && t.alignment.get() < target.ptrsize || + (vd.offset & (target.ptrsize - 1)))) + { + if (sc.setUnsafe(false, argLoc, + "field `%s.%s` cannot assign to misaligned pointers in `@safe` code", sd, vd)) + { + errors = true; + elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors + ++fieldi; + continue; + } + } + } + + // Check for overlapping initializations (can happen with unions) + foreach (k, v2; sd.fields[0 .. nfields]) + { + if (vd.isOverlappedWith(v2) && elems[k]) + { + error(elems[k].loc, "overlapping initialization for field `%s` and `%s`", v2.toChars(), vd.toChars()); + enum errorMsg = "`struct` initializers that contain anonymous unions" ~ + " must initialize only the first member of a `union`. All subsequent" ~ + " non-overlapping fields are default initialized"; + if (!sd.isUnionDeclaration()) + .errorSupplemental(elems[k].loc, errorMsg); + errors = true; + continue; + } + } + + assert(sc); + + auto ex = getExp(j, vd.type); + + if (ex.op == EXP.error) + { + errors = true; + elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors + ++fieldi; + continue; + } + + elems[fieldi] = doCopyOrMove(sc, ex); + ++fieldi; + } + if (errors) + return null; + + return elements; +} diff --git a/dmd/parse.d b/dmd/parse.d index ee55d214555..4b3f1425089 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -1285,7 +1285,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (token.value == TOK.leftParenthesis) { const loc = token.loc; - exp = new AST.CallExp(loc, exp, parseArguments()); + AST.Expressions* args = new AST.Expressions(); + AST.Identifiers* names = new AST.Identifiers(); + parseNamedArguments(args, names); + exp = new AST.CallExp(loc, exp, args, names); } if (udas is null) @@ -8912,7 +8915,10 @@ LagainStc: break; case TOK.leftParenthesis: - e = new AST.CallExp(loc, e, parseArguments()); + AST.Expressions* args = new AST.Expressions(); + AST.Identifiers* names = new AST.Identifiers(); + parseNamedArguments(args, names); + e = new AST.CallExp(loc, e, args, names); continue; case TOK.leftBracket: @@ -9347,26 +9353,52 @@ LagainStc: private AST.Expressions* parseArguments() { // function call - AST.Expressions* arguments; + AST.Expressions* arguments = new AST.Expressions(); + parseNamedArguments(arguments, null); + return arguments; + } + + /************************* + * Collect argument list. + * Assume current token is ',', '$(LPAREN)' or '['. + */ + private void parseNamedArguments(AST.Expressions* arguments, AST.Identifiers* names) + { + assert(arguments); - arguments = new AST.Expressions(); const endtok = token.value == TOK.leftBracket ? TOK.rightBracket : TOK.rightParenthesis; nextToken(); while (token.value != endtok && token.value != TOK.endOfFile) { + if (peekNext() == TOK.colon) + { + // Named argument `name: exp` + auto loc = token.loc; + auto ident = token.ident; + check(TOK.identifier); + check(TOK.colon); + if (names) + names.push(ident); + else + error(loc, "named arguments not allowed here"); + } + else + { + if (names) + names.push(null); + } + auto arg = parseAssignExp(); arguments.push(arg); + if (token.value != TOK.comma) break; nextToken(); //comma } - check(endtok); - - return arguments; } /******************************************* diff --git a/tests/dmd/compilable/named_argumens_struct.d b/tests/dmd/compilable/named_argumens_struct.d new file mode 100644 index 00000000000..0c60509dda8 --- /dev/null +++ b/tests/dmd/compilable/named_argumens_struct.d @@ -0,0 +1,24 @@ + +struct S +{ + string name; + int x; + int y; +} + + +immutable S s = S(x: 2, 3, name: "boo"); + +static assert(s.x == 2); +static assert(s.y == 3); +static assert(s.name == "boo"); + +union U +{ + float f; + int i; +} + +immutable U u = U(i: 2); + +static assert(u.i == 2); diff --git a/tests/dmd/fail_compilation/diag11132.d b/tests/dmd/fail_compilation/diag11132.d index 64db64d1e97..0bdfe50ca74 100644 --- a/tests/dmd/fail_compilation/diag11132.d +++ b/tests/dmd/fail_compilation/diag11132.d @@ -1,7 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/diag11132.d(22): Error: overlapping initialization for field `a` and `b` +fail_compilation/diag11132.d(23): Error: overlapping initialization for field `a` and `b` +fail_compilation/diag11132.d(23): `struct` initializers that contain anonymous unions must initialize only the first member of a `union`. All subsequent non-overlapping fields are default initialized --- */ diff --git a/tests/dmd/fail_compilation/fail155.d b/tests/dmd/fail_compilation/fail155.d index 6d8f184c9ea..5f73f9a0ea5 100644 --- a/tests/dmd/fail_compilation/fail155.d +++ b/tests/dmd/fail_compilation/fail155.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail155.d(20): Error: overlapping initialization for `y` +fail_compilation/fail155.d(20): Error: overlapping initialization for field `x` and `y` fail_compilation/fail155.d(20): `struct` initializers that contain anonymous unions must initialize only the first member of a `union`. All subsequent non-overlapping fields are default initialized --- */ diff --git a/tests/dmd/fail_compilation/fail156.d b/tests/dmd/fail_compilation/fail156.d index bfc2383b590..ccb325415b2 100644 --- a/tests/dmd/fail_compilation/fail156.d +++ b/tests/dmd/fail_compilation/fail156.d @@ -2,9 +2,9 @@ /* TEST_OUTPUT: --- -fail_compilation/fail156.d(35): Error: overlapping initialization for `y` +fail_compilation/fail156.d(35): Error: overlapping initialization for field `x` and `y` fail_compilation/fail156.d(35): `struct` initializers that contain anonymous unions must initialize only the first member of a `union`. All subsequent non-overlapping fields are default initialized -fail_compilation/fail156.d(42): Error: overlapping initialization for `y` +fail_compilation/fail156.d(42): Error: overlapping initialization for field `x` and `y` fail_compilation/fail156.d(42): `struct` initializers that contain anonymous unions must initialize only the first member of a `union`. All subsequent non-overlapping fields are default initialized --- */ diff --git a/tests/dmd/fail_compilation/fail158.d b/tests/dmd/fail_compilation/fail158.d index 6f09f658487..3253d167162 100644 --- a/tests/dmd/fail_compilation/fail158.d +++ b/tests/dmd/fail_compilation/fail158.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail158.d(17): Error: more initializers than fields (2) of `S` +fail_compilation/fail158.d(17): Error: too many initializers for `S` with 2 fields --- */ diff --git a/tests/dmd/fail_compilation/fail22570.d b/tests/dmd/fail_compilation/fail22570.d index cb8c286650d..e937a480b45 100644 --- a/tests/dmd/fail_compilation/fail22570.d +++ b/tests/dmd/fail_compilation/fail22570.d @@ -3,8 +3,8 @@ /* TEST_OUTPUT: --- -fail_compilation/fail22570.d(19): Error: more initializers than fields (1) of `S` -fail_compilation/fail22570.d(20): Error: more initializers than fields (1) of `S` +fail_compilation/fail22570.d(19): Error: too many initializers for `S` with 1 field +fail_compilation/fail22570.d(20): Error: too many initializers for `S` with 1 field --- */ diff --git a/tests/dmd/fail_compilation/fail299.d b/tests/dmd/fail_compilation/fail299.d index ffe50679282..832a9a8d193 100644 --- a/tests/dmd/fail_compilation/fail299.d +++ b/tests/dmd/fail_compilation/fail299.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail299.d(14): Error: more initializers than fields (0) of `Foo` +fail_compilation/fail299.d(14): Error: initializer provided for struct `Foo` with no fields --- */ diff --git a/tests/dmd/fail_compilation/named_arguments_parse.d b/tests/dmd/fail_compilation/named_arguments_parse.d new file mode 100644 index 00000000000..19e230ee519 --- /dev/null +++ b/tests/dmd/fail_compilation/named_arguments_parse.d @@ -0,0 +1,15 @@ +/** +TEST_OUTPUT: +--- +fail_compilation/named_arguments_parse.d(10): Error: named arguments not allowed here +fail_compilation/named_arguments_parse.d(13): Error: named arguments not allowed here +fail_compilation/named_arguments_parse.d(14): Error: named arguments not allowed here +--- +*/ + +@(attribute: 3) +void main() +{ + mixin(thecode: "{}"); + pragma(msg, themsg: "hello"); +} diff --git a/tests/dmd/fail_compilation/test20998.d b/tests/dmd/fail_compilation/test20998.d index 16eb02622d8..2e137ab7631 100644 --- a/tests/dmd/fail_compilation/test20998.d +++ b/tests/dmd/fail_compilation/test20998.d @@ -6,7 +6,7 @@ TEST_OUTPUT: fail_compilation/test20998.d(76): Error: undefined identifier `invalid` X x = { invalid, 2, "asd" }; ^ -fail_compilation/test20998.d(76): Error: too many initializers for `X` +fail_compilation/test20998.d(76): Error: too many initializers for `X` with 2 fields X x = { invalid, 2, "asd" }; ^ fail_compilation/test20998.d(83): Error: cannot implicitly convert expression `"a"` of type `string` to `int` @@ -15,7 +15,7 @@ X2 x2 = { ptr: null, "a", ptr: 2, 444 }; fail_compilation/test20998.d(83): Error: duplicate initializer for field `ptr` X2 x2 = { ptr: null, "a", ptr: 2, 444 }; ^ -fail_compilation/test20998.d(83): Error: too many initializers for `X2` +fail_compilation/test20998.d(83): Error: too many initializers for `X2` with 3 fields X2 x2 = { ptr: null, "a", ptr: 2, 444 }; ^ fail_compilation/test20998.d(90): Error: overlapping initialization for field `ptr` and `x` @@ -27,7 +27,7 @@ X3 x3 = { ptr: null, "a", ptr: 2, 444 }; fail_compilation/test20998.d(90): Error: duplicate initializer for field `ptr` X3 x3 = { ptr: null, "a", ptr: 2, 444 }; ^ -fail_compilation/test20998.d(90): Error: too many initializers for `X3` +fail_compilation/test20998.d(90): Error: too many initializers for `X3` with 3 fields X3 x3 = { ptr: null, "a", ptr: 2, 444 }; ^ fail_compilation/test20998.d(98): Error: field `X4.ptr` cannot assign to misaligned pointers in `@safe` code @@ -36,7 +36,7 @@ fail_compilation/test20998.d(98): Error: field `X4.ptr` cannot assign to misalig fail_compilation/test20998.d(98): Error: cannot implicitly convert expression `"a"` of type `string` to `int` X4 x4 = { ptr: null, "a", 444, ptr: 2, true }; ^ -fail_compilation/test20998.d(98): Error: too many initializers for `X4` +fail_compilation/test20998.d(98): Error: too many initializers for `X4` with 2 fields X4 x4 = { ptr: null, "a", 444, ptr: 2, true }; ^ fail_compilation/test20998.d(102): called from here: `test()` @@ -51,16 +51,16 @@ X2 a5 = { ptr: 1, ptr: 2, ptr: 444, ptr: 555 }; fail_compilation/test20998.d(104): Error: duplicate initializer for field `ptr` X2 a5 = { ptr: 1, ptr: 2, ptr: 444, ptr: 555 }; ^ -fail_compilation/test20998.d(104): Error: too many initializers for `X2` +fail_compilation/test20998.d(104): Error: too many initializers for `X2` with 3 fields X2 a5 = { ptr: 1, ptr: 2, ptr: 444, ptr: 555 }; ^ -fail_compilation/test20998.d(107): Error: too many initializers for `X2` +fail_compilation/test20998.d(107): Error: too many initializers for `X2` with 3 fields X2 c6 = { null, 2, true, null }; ^ fail_compilation/test20998.d(116): Error: cannot implicitly convert expression `1` of type `int` to `immutable(char*)` immutable Struct iStruct = {1, &ch}; ^ -fail_compilation/test20998.d(116): Error: too many initializers for `Struct` +fail_compilation/test20998.d(116): Error: too many initializers for `Struct` with 1 field immutable Struct iStruct = {1, &ch}; ^ fail_compilation/test20998.d(120): called from here: `test2()` From 29d1e1617f8658b855296615c0297e0d1b1bcc5c Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 17 Jan 2023 06:41:47 -0800 Subject: [PATCH 033/177] remove untag.d from test suite (dlang/dmd!14833) --- tests/dmd/runnable/extra-files/untag.html | 555 ---------------------- tests/dmd/runnable/untag.d | 187 -------- 2 files changed, 742 deletions(-) delete mode 100644 tests/dmd/runnable/extra-files/untag.html delete mode 100644 tests/dmd/runnable/untag.d diff --git a/tests/dmd/runnable/extra-files/untag.html b/tests/dmd/runnable/extra-files/untag.html deleted file mode 100644 index cec0c87a114..00000000000 --- a/tests/dmd/runnable/extra-files/untag.html +++ /dev/null @@ -1,555 +0,0 @@ - - - - - - - Abbott and Costello Meet Frankenstein - Wikipedia, the free encyclopedia - - - - - - - - - - - - -
-
-
- -

Abbott and Costello Meet Frankenstein

-
-

From Wikipedia, the free encyclopedia

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Abbott and Costello Meet Frankenstein

-Abbott and Costello Meet Frankenstein Theatrical Poster
Directed byCharles Barton
Produced byRobert Arthur
Written byRobert Lees
-Frederic I. Rinaldo
-John Grant
StarringBud Abbott
-Lou Costello
-Lon Chaney, Jr.
-Bela Lugosi
-Glenn Strange
Music byFrank Skinner
Editing byFrank Gross
Distributed byUniversal International
Release date(s)June 15, 1948 (U.S. release)
Running time83 min.
LanguageEnglish
Budget$760,000
Preceded byHouse of Dracula (1945)
-The Invisible Man's Revenge (1944)
-The Noose Hangs High (1948)
Followed byMexican Hayride (1948)
-Abbott and Costello Meet the Invisible Man (1951)
-

Abbott and Costello Meet Frankenstein (onscreen title: Bud Abbott Lou Costello Meet Frankenstein) is a 1948 comedy/horror film directed by Charles Barton and starring the comedy team of Abbott and Costello.

-

This is the first of several films where the comedy duo meets classic characters from Universal's film stable. In the film, they encounter Dracula, Frankenstein's monster, and the Wolf Man. Subsequent films pair the duo with the Mummy, the Keystone Kops, and the Invisible Man. On a TV special in the early 1950s, the comedy duo did a sketch where they interacted with the latest original Universal Studios monster being promoted at the time, the Creature from the Black Lagoon.

-

The film is considered the swan song for the "Big Three" Universal horror monsters – Dracula, the Wolf Man and Frankenstein's monster – although it does not appear to fit within the loose continuity of the earlier films.

-

The film was re-released in 1956 along with Abbott and Costello Meet the Killer, Boris Karloff.

-

In 2001, the United States Library of Congress deemed this film "culturally, historically, or aesthetically significant" and selected it for preservation in the National Film Registry.

-

In September 2007, Reader’s Digest selected the movie as one of the top 100 funniest films of all time.

- - - - -
-
-

Contents

-
- -
- -

-

[edit] Plot

-

Chick Young (Bud Abbott) and Wilbur Grey (Lou Costello) work as baggage clerks in LaMirada, Florida. When Wilbur mishandles two crates belonging to 'MacDougal's House of Horrors' museum, Mr. MacDougal (Frank Ferguson) demands that they deliver them in person so that they can be inspected by an insurance agent. MacDougal boasts to Wilbur's girlfriend, Dr. Sandra Mornay (Lénore Aubert), that the crates contain "the remains of the original Count Dracula" (Bela Lugosi) and "the body of the Frankenstein Monster" (Glenn Strange).

-

Dracula awakens, hypnotizes Wilbur, and spirits away his own coffin (and the revived Monster) before anyone else sees them. MacDougal then arrives with the insurance agent. Finding the storage crates empty, he accuses the boys of theft and has them arrested.

-

Mornay receives Dracula and the Monster at her island castle. Sandra is a gifted surgeon who has studied Dr. Frankenstein's notebooks, and has been posing as Wilbur's girlfriend as part of Dracula's scheme to replace the Monster's brutish brain with one more pliable — Wilbur's.

-

Wilbur and Chick are bailed out of jail and mistakenly believe Sandra to be their benefactor. Actually Joan Raymond (Jane Randolph), who also seems to like Wilbur, is responsible for the good deed. Joan is secretly working for the company that is processing MacDougal's insurance claim, and hopes Wilbur will lead her to the missing 'exhibits'.

-

Meanwhile, Larry Talbot (Lon Chaney, Jr.) has taken the apartment across the hall from Wilbur and Chick. He has tracked Dracula and the Monster from Europe, and knows them to be alive. Talbot asks the boys to help him find and destroy the villains. Wilbur is amenable to the plan, but Chick thinks both of them are crazy. Talbot's desperate insistence that he be locked in his room before moonrise impresses Chick even less.

-

The following night, Wilbur, Chick and Joan go to Sandra's castle to pick her up for a costume ball. Sandra has told Wilbur to come alone, and receives the extra guests rather icily.

-

While the ladies powder their noses, Wilbur answers a telephone call from someone wanting to speak to a 'Dr Lejos'. It is Talbot, who informs them that they are in the "house of Dracula". Wilbur reluctantly agrees to search the castle with Chick, and soon stumbles upon an underground passageway, complete with boat and dock. Behind a secret revolving wall, Wilbur again encounters Dracula and the Monster, but escapes. Wilbur's every attempt to get Chick to witness the villains fails - thanks to the revolving wall. Meanwhile, Joan has discovered Dr Frankenstein's notebook in Sandra's bureau, while Sandra has discovered Joan's employee I.D. in her bag.

-

Suavely reattired, Dracula (a.k.a. Dr. Lejos) is introduced by Sandra to Joan and the boys. He commends Sandra on her 'choice', expertly massaging the ego of Wilbur, who does not realize the true context of the remark. Also working at the castle is the naive Dr. Stevens (Charles Bradstreet), who questions some of the specialized equipment that has arrived. Dracula manages to deflect Dr. Stevens' questions by pairing him with Joan and shooing off the 'young people' to their ball. Sandra claims to have a sudden splitting headache and will not be able to attend the event. When Dracula consults Sandra in private, she admits that Dr. Stevens' questions, Joan's insurance credentials and Wilbur's inquiries have made her nervous, and wants to postpone the experiments. Impatient, Dracula asserts his will by hypnotizing her, and biting her in the throat.

-

At the ball, the boys encounter Talbot and MacDougal. Dracula arrives unexpectedly with Sandra, now under his spell. Dracula easily deflects Talbot's accusations, making the man appear disturbed. Dracula takes Joan for a dance while Sandra lures Wilbur to a quiet spot. Just before she can bite Wilbur's neck, Chick and Larry approach looking for Joan, and Sandra flees. As they search the grounds, Talbot transforms into the Wolf Man. Wilbur escapes, but the Wolf Man finds and injures MacDougal. Later noting that Chick is costumed as a werewolf, MacDougal concludes that Chick attacked him for revenge. (The fact that Chick is dressed like Talbot certainly does not help the situation). Chick manages to slip away, only to witness Dracula hypnotizing Wilbur. Chick becomes somewhat hypnotized himself, while Wilbur and an entranced Joan are brought back to the castle by Dracula and Sandra. The next morning, Chick is still on the lam when he finds Larry, who confesses that he was MacDougal's attacker. Now finally convinced, Chick agrees to help Larry rescue Wilbur and Joan.

-

While Wilbur is being held in a pillory, Sandra finally explains to him the plan to transplant his brain into the Monster. She and Dracula leave him to prepare the Monster for the operation. Chick and Talbot arrive, free Wilbur, and head off to save Joan. Wilbur, meanwhile, is lured back to the castle by Dracula, who easily overpowers his mind.

-

While the Monster receives an electrical boost in the lab, Sandra is about to open Wilbur's skull when Talbot storms in and casts her aside. Chick fends off Dracula with a chair, lifting it over his head to swing it at the vampire and inadvertently knocking out Sandra in the process. But just as Talbot is about to untie Wilbur, he once again transforms into the Wolf Man.

-

Dracula returns to the scene, only to have a tug-of-war with the Wolf Man over Wilbur's gurney. Dracula flees, with the Wolf Man giving chase. Chick arrives to untie Wilbur just as the Monster, now fully recovered, breaks his own restraints and rises from his stretcher. Sandra attempts to order him back as Dracula does, but the Monster defiantly tosses her out a window.

-

Dr. Stevens, meanwhile, has managed to find Joan and gets her to the boat. Dracula, in an attempt to escape, transforms into a bat, but the Wolf Man snares him and both fall over a balcony and into the rocky seas below. Joan abruptly wakes from her trance, while the boys escape the castle and head to the pier, with the Monster in pursuit. Once again Chick and Wilbur encounter Mr. MacDougal, who still insists that he wants his exhibits. They loudly reply, "..here comes one of them now!" When the Monster appears, MacDougal and his partner jump off the pier. Chick and Wilbur attempt to escape in a rowboat that is securely tied to the pier. The Monster throws barrels at them, in a series of near misses. Wilbur finally unties the boat, while Stevens and Joan arrive and set the pier ablaze. The Monster turns around and marches into the flames, slowing and succumbing as the pier collapses into the water.

-

Just as Chick and Wilbur relax, they hear a disembodied voice (Vincent Price) and see a cigarette floating in the air: "Allow me to introduce myself, I'm the Invisible Man!" The boys jump off the boat and swim away as the Invisible Man lights his cigarette and laughs. (This scene presaged 1951's Abbott and Costello Meet the Invisible Man, though Price did not star, and all characters were different.

-

-

[edit] Cast

- -

-

[edit] Production

-

The film was originally intended to be titled The Brain of Frankenstein, but its name was changed prior to the filming schedule, which ran from February 5 through March 20, 1948.

-

Walter Lantz, noted for the creation of Woody Woodpecker, provided the animation for Dracula's transformations.

-

In a 1996 documentary, 100 Years of Horror, hosted by Christopher Lee, it was revealed that the studio hired two additional comedians to add laughs between takes on the set.

-

Costello hated the script for Abbott and Costello Meet Frankenstein.[2] He said that his five-year-old daughter could have written something better, but later warmed to the film during production.

-

During the filming of Abbott and Costello Meet Frankenstein, Glenn Strange found Costello so funny he would often break up laughing, necessitating many retakes. There were several pie fights between takes as well, but Abbott and Costello respected the three monsters (Chaney as the Wolfman, Lugosi as Dracula and Strange as the Monster) and made sure no pies were flung at the heavily made-up actors.

-

Boris Karloff was originally approached to play the monster once again, but declined. He did, however, help promote the movie and can be seen in several publicity photos, including one where he is buying a ticket, even though he refused to actually see the film (considering it an insult).

-

The Australian film board required that almost every scene involving a monster should be removed before release.[3]

-

-

[edit] Film mistakes

-

At one point in the film, where Abbott and Costello's characters are going through the revolving panel, Costello calls Abbott by his real name instead of his character's name. In addition, although the film is titled Abbott and Costello Meet Frankenstein, there is no character named Frankenstein in this movie. He is referenced for his work in bringing his creature to life, but the character himself does not appear. In addition, Dracula's reflection can be seen in the mirror when he makes the nurse his next victim. The studio intended to remove the reflection, but failed to do before the theatrical release, and to this day can still be seen in the movie.

-

-

[edit] Cultural references

- - - - - - -
    -
  • In a 2006 episode of Iconoclasts on the Sundance Channel, Quentin Tarantino cited the film as his favorite childhood movie because "when it was supposed to be funny, it was really funny, and when it was supposed to be scary, it was really scary."
  • -
  • The film was unofficially remade in Mexico as Frankenstein, el Vampiro y Compañía (1962) and in Egypt as Haram Alek (1953).[4]
  • -
  • In the Star Trek: Enterprise episode "Horizon", Trip Tucker wanted to show the film.
  • -
  • In an episode of Home Improvement in which Mark is putting together a project for film class, after Tim tells his other sons that film was something he himself appreciated in school, Randy sarcastically quips back that his favorite movie was Abbott and Costello Meet Frankenstein.[citation needed]
  • -
  • In 1954, an Egyptian film studio created Ismil and Abdel Meet Frankenstein, a scene-for-scene remake of the 1948 classic. This version is not commercially available on DVD, but is scheduled for a public film showing at the Mid-Atlantic Nostalgia Convention in September 2008.
  • -
-

-

[edit] Routines

-

The Moving Candle routine previously used in Hold That Ghost was utilized again in this film.

-

-

[edit] DVD releases

- - - - - - -

-

[edit] Notes

-
-
    -
  1. ^ The monster is actually played by two actors. Glenn Strange plays him for most of the film, but when he broke his foot during production, Lon Chaney, Jr. (who previously played the monster in The Ghost of Frankenstein), took over the role for a portion of the laboratory battle sequence.
  2. -
  3. ^ Furmanek, Bob and Ron Palumbo (1991). Abbott and Costello in Hollywood. New York: Perigee Books. ISBN 0-399-51605-0
  4. -
  5. ^ Furmanek, Bob and Ron Palumbo (1991). Abbott and Costello in Hollywood. New York: Perigee Books. ISBN 0-399-51605-0
  6. -
  7. ^ Frankensteinia: The Frankenstein Blog: Frankenstein Gets Knocked-Off
  8. -
-
-

-

[edit] External links

- - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-
- - - -
-
Navigation
- -
- - -
-
Languages
-
- -
-
-
-
- -
- - diff --git a/tests/dmd/runnable/untag.d b/tests/dmd/runnable/untag.d deleted file mode 100644 index 7aaa58cf87d..00000000000 --- a/tests/dmd/runnable/untag.d +++ /dev/null @@ -1,187 +0,0 @@ -// PERMUTE_ARGS: - -import std.algorithm, std.ascii, std.conv, std.exception, - std.file, std.getopt, std.path, std.range, - std.string, std.traits; - -auto binaryFun(string pred, T, U)(T a, U b) -{ - return(mixin(pred)); -} - -/** -If $(D startsWith(r1, r2)), consume the corresponding elements off $(D -r1) and return $(D true). Otherwise, leave $(D r1) unchanged and -return $(D false). -*/ -bool startsWithConsume(alias pred = "a == b", R1, R2)(ref R1 r1, R2 r2) -{ - auto r = r1; // .save(); - while (!r2.empty && !r.empty && binaryFun!pred(r.front, r2.front)) - { - r.popFront(); - r2.popFront(); - } - return r2.empty ? (){ r1 = r; return true;}() : false; -} - - -uint bug = 1; - -int main(string[] args) { - getopt(args, "bug", &bug); - enforce(bug <= 2); - auto txt = readText("runnable/extra-files/untag.html"); - untag(txt, "runnable/extra-files/untag.html"); - return 0; -} - -void untag(string txt, string filename) { - string currentParagraph; - string origtxt = txt; - string origtxtcopy = txt.idup; - - // Find beginning of content - txt = std.algorithm.find(txt, "\n"); - - // Ancillary function that commits the current paragraph for - // writing - void commit() { - writeParagraph(strip(currentParagraph)); - } - - void writeChar(dchar c) { - immutable lastWritten = currentParagraph.length - ? currentParagraph.back - : dchar.init; - if (lastWritten == ' ' && c == ' ') { - // Two consecutive spaces fused - } else { - // Normal case - currentParagraph ~= c; - } - } - - void writeWords(string s) { - if (bug == 0) { - foreach (dchar c; s) { - currentParagraph ~= c; - } - } else if (bug == 1) { - reserve(currentParagraph, currentParagraph.length + s.length); - currentParagraph ~= s; - } else { - currentParagraph = currentParagraph ~ s; - } - } - - // Parse the content - while (!txt.empty) { - size_t i = 0; - while (i < txt.length && txt[i] != '<' && txt[i] != '&') { - ++i; - } - writeWords(txt[0 .. i]); - if (i == txt.length) { - commit(); - return; - } - txt = txt[i .. $]; - auto c = txt[0]; - txt = txt[1 .. $]; - if (c == '<') { // This is a tag - if (startsWithConsume(txt, `/p>`) || - startsWithConsume(txt, `/li>`)) { - // End of paragraph - commit(); - } else { - // This is an uninteresting tag - enforce(findConsume(txt, '>'), - "Could not find closing tag: "~txt); - } - } else { - auto app = appender!string(); - findConsume(txt, ';', app); - switch (app.data) { - case "#160;": case "#32;": case "reg;": case "nbsp;": - writeChar(' '); - break; - case "amp;": - writeChar('&'); - break; - case "gt;": - writeChar('>'); - break; - case "lt;": - writeChar('<'); - break; - case "quot;": - writeChar('"'); - break; - default: - throw new Exception(text("Unknown code: &", app.data)); - break; - } - } - } -} - -void writeParagraph(string sentence) { - static bool isSeparator(dchar a) { - return !(isAlpha(a) /*|| a == '.'*/); - } - - foreach (string cand; std.algorithm.splitter(sentence, ' ')) { - cand = toLower(cand); - } -} - -/** -If $(D r2) can not be found in $(D r1), leave $(D r1) unchanged and -return $(D false). Otherwise, consume elements in $(D r1) until $(D -startsWithConsume(r1, r2)), and return $(D true). Effectively -positions $(D r1) right after $(D r2). - */ -bool findConsume(R1, R2)(ref R1 r1, R2 r2) if (isForwardRange!R2) { - auto r = r1; // .save(); - while (!r.empty) { - if (startsWithConsume(r, r2)) { - r1 = r; - return true; - } - r.popFront(); - } - return false; -} - -/** -If $(D r2) can not be found in $(D r1), leave $(D r1) unchanged and -return $(D false). Otherwise, consume elements in $(D r1) until $(D -startsWith(r1, r2)), and return $(D true). - */ -bool findConsume(R, E)(ref R r, E e) if (is(typeof(r.front == e))) { - auto r1 = std.algorithm.find(r, e); - if (r1.empty) return false; - r = r1; - r.popFront(); - return true; -} - -/** -If $(D r2) can not be found in $(D r1), leave $(D r1) unchanged and -return $(D false). Otherwise, consume elements in $(D r1) until $(D -startsWith(r1, r2)), and return $(D true). - */ -bool findConsume(R1, E, R2)(ref R1 r1, E e, R2 r2) if (is(typeof(r1.front == e))) { - auto r = r1; - while (!r.empty) { - r2.put(r.front); - if (r.front == e) { - r.popFront(); - r1 = r; - return true; - } - r.popFront(); - } - return false; -} From 38f8478a4c59a686caeb0538a09098f0a9fe3f15 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Tue, 17 Jan 2023 16:24:35 +0100 Subject: [PATCH 034/177] Fix parens in expandTuples documentation --- dmd/expression.d | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dmd/expression.d b/dmd/expression.d index 2e384dcf6f9..44b6c55196d 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -253,11 +253,11 @@ bool isDotOpDispatch(Expression e) * * Example: * When there's a call `f(10, pair: AliasSeq!(20, 30), single: 40))`, the input is: - * exps = [10, (20, 30), 40] - * names = [null, "pair", "single"]); + * `exps = [10, (20, 30), 40]` + * `names = [null, "pair", "single"]` * The arrays will be modified to: - * exps = [10, 20, 30, 40] - * names = [null, "pair", null, "single"]); + * `exps = [10, 20, 30, 40]` + * `names = [null, "pair", null, "single"]` * * Params: * exps = array of Expressions From e5b56e41997951603985461255f6aff1fb0c405d Mon Sep 17 00:00:00 2001 From: Vladimir Panteleev Date: Wed, 18 Jan 2023 03:02:39 +0000 Subject: [PATCH 035/177] dmd.expression: Fix another stray paren in DDoc --- dmd/expression.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmd/expression.d b/dmd/expression.d index 44b6c55196d..025976bf6ba 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -252,7 +252,7 @@ bool isDotOpDispatch(Expression e) * Expand tuples in-place. * * Example: - * When there's a call `f(10, pair: AliasSeq!(20, 30), single: 40))`, the input is: + * When there's a call `f(10, pair: AliasSeq!(20, 30), single: 40)`, the input is: * `exps = [10, (20, 30), 40]` * `names = [null, "pair", "single"]` * The arrays will be modified to: From e35d5ef2d59983cb320f605c711412943d54c72c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Ferreira?= Date: Mon, 16 Jan 2023 23:09:13 +0000 Subject: [PATCH 036/177] druntime: refactor PAGESIZE to use core.memory.pageSize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Luís Ferreira --- runtime/druntime/src/core/thread/fiber.d | 18 ++++++++++-------- runtime/druntime/src/core/thread/osthread.d | 8 ++++---- runtime/druntime/src/core/thread/types.d | 18 +----------------- 3 files changed, 15 insertions(+), 29 deletions(-) diff --git a/runtime/druntime/src/core/thread/fiber.d b/runtime/druntime/src/core/thread/fiber.d index 27712e81eca..c23d7f31aa9 100644 --- a/runtime/druntime/src/core/thread/fiber.d +++ b/runtime/druntime/src/core/thread/fiber.d @@ -16,6 +16,8 @@ import core.thread.threadgroup; import core.thread.types; import core.thread.context; +import core.memory : pageSize; + /////////////////////////////////////////////////////////////////////////////// // Fiber Platform Detection /////////////////////////////////////////////////////////////////////////////// @@ -550,7 +552,7 @@ class Fiber version (X86_64) // libunwind on macOS 11 now requires more stack space than 16k, so // default to a larger stack size. This is only applied to X86 as - // the PAGESIZE is still 4k, however on AArch64 it is 16k. + // the pageSize is still 4k, however on AArch64 it is 16k. enum defaultStackPages = 8; else enum defaultStackPages = 4; @@ -573,8 +575,8 @@ class Fiber * In: * fn must not be null. */ - this( void function() fn, size_t sz = PAGESIZE * defaultStackPages, - size_t guardPageSize = PAGESIZE ) nothrow + this( void function() fn, size_t sz = pageSize * defaultStackPages, + size_t guardPageSize = pageSize ) nothrow in { assert( fn ); @@ -601,8 +603,8 @@ class Fiber * In: * dg must not be null. */ - this( void delegate() dg, size_t sz = PAGESIZE * defaultStackPages, - size_t guardPageSize = PAGESIZE ) nothrow + this( void delegate() dg, size_t sz = pageSize * defaultStackPages, + size_t guardPageSize = pageSize ) nothrow { allocStack( sz, guardPageSize ); reset( cast(void delegate() const) dg ); @@ -911,9 +913,9 @@ private: } do { - // adjust alloc size to a multiple of PAGESIZE - sz += PAGESIZE - 1; - sz -= sz % PAGESIZE; + // adjust alloc size to a multiple of pageSize + sz += pageSize - 1; + sz -= sz % pageSize; // NOTE: This instance of Thread.Context is dynamic so Fiber objects // can be collected by the GC so long as no user level references diff --git a/runtime/druntime/src/core/thread/osthread.d b/runtime/druntime/src/core/thread/osthread.d index d483a05cf58..54af6ce0fc8 100644 --- a/runtime/druntime/src/core/thread/osthread.d +++ b/runtime/druntime/src/core/thread/osthread.d @@ -16,7 +16,7 @@ import core.thread.threadbase; import core.thread.context; import core.thread.types; import core.atomic; -import core.memory : GC; +import core.memory : GC, pageSize; import core.time; import core.exception : onOutOfMemoryError; import core.internal.traits : externDFunc; @@ -1049,7 +1049,7 @@ unittest unittest { - // use >PAGESIZE to avoid stack overflow (e.g. in an syscall) + // use >pageSize to avoid stack overflow (e.g. in an syscall) auto thr = new Thread(function{}, 4096 + 1).start(); thr.join(); } @@ -2693,8 +2693,8 @@ private size_t adjustStackSize(size_t sz) nothrow @nogc size_t function() @nogc nothrow)(); } - // stack size must be a multiple of PAGESIZE - sz = ((sz + PAGESIZE - 1) & ~(PAGESIZE - 1)); + // stack size must be a multiple of pageSize + sz = ((sz + pageSize - 1) & ~(pageSize - 1)); return sz; } diff --git a/runtime/druntime/src/core/thread/types.d b/runtime/druntime/src/core/thread/types.d index e50399a59d9..eb84ad74b48 100644 --- a/runtime/druntime/src/core/thread/types.d +++ b/runtime/druntime/src/core/thread/types.d @@ -47,31 +47,15 @@ else package { - static immutable size_t PAGESIZE; version (Posix) static immutable size_t PTHREAD_STACK_MIN; } shared static this() { - version (Windows) - { - import core.sys.windows.winbase; - - SYSTEM_INFO info; - GetSystemInfo(&info); - - PAGESIZE = info.dwPageSize; - assert(PAGESIZE < int.max); - } - else version (Posix) + version (Posix) { import core.sys.posix.unistd; - PAGESIZE = cast(size_t)sysconf(_SC_PAGESIZE); PTHREAD_STACK_MIN = cast(size_t)sysconf(_SC_THREAD_STACK_MIN); } - else - { - static assert(0, "unimplemented"); - } } From ca709bf72d72847e89b3a47993d9dec121877610 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Fri, 20 Jan 2023 16:11:37 +0800 Subject: [PATCH 037/177] Deprecate traits(isVirtualFunction) and traits(getVirtualFunctions) (dlang/dmd!14802) --- dmd/traits.d | 11 +++++ runtime/druntime/src/core/internal/traits.d | 2 +- runtime/druntime/src/object.d | 4 +- tests/dmd/compilable/ice13920.d | 5 -- .../deprecate_getVirtualFunctions.d | 20 ++++++++ tests/dmd/fail_compilation/fail19076.d | 2 +- tests/dmd/fail_compilation/test17096.d | 47 ++++++++++--------- tests/dmd/runnable/e7804.d | 2 - tests/dmd/runnable/traits.d | 38 --------------- 9 files changed, 59 insertions(+), 72 deletions(-) create mode 100644 tests/dmd/fail_compilation/deprecate_getVirtualFunctions.d diff --git a/dmd/traits.d b/dmd/traits.d index a64b57b5a29..f991c0b5673 100644 --- a/dmd/traits.d +++ b/dmd/traits.d @@ -634,6 +634,10 @@ Expression semanticTraits(TraitsExp e, Scope* sc) } if (e.ident == Id.isVirtualFunction) { + // @@@DEPRECATED2.121@@@ + // Deprecated in 2.101 - Can be removed from 2.121 + e.deprecation("`traits(isVirtualFunction)` is deprecated. Use `traits(isVirtualMethod)` instead"); + if (dim != 1) return dimError(1); @@ -995,6 +999,13 @@ Expression semanticTraits(TraitsExp e, Scope* sc) if (errors < global.errors) e.error("`%s` cannot be resolved", eorig.toChars()); + if (e.ident == Id.getVirtualFunctions) + { + // @@@DEPRECATED2.121@@@ + // Deprecated in 2.101 - Can be removed from 2.121 + e.deprecation("`traits(getVirtualFunctions)` is deprecated. Use `traits(getVirtualMethods)` instead"); + } + /* Create tuple of functions of ex */ auto exps = new Expressions(); diff --git a/runtime/druntime/src/core/internal/traits.d b/runtime/druntime/src/core/internal/traits.d index 0b4890cbfa9..966839f176a 100644 --- a/runtime/druntime/src/core/internal/traits.d +++ b/runtime/druntime/src/core/internal/traits.d @@ -654,7 +654,7 @@ if (func.length == 1 /*&& isCallable!func*/) int test(int); int test() @property; } - alias ov = __traits(getVirtualFunctions, Overloads, "test"); + alias ov = __traits(getVirtualMethods, Overloads, "test"); alias F_ov0 = FunctionTypeOf!(ov[0]); alias F_ov1 = FunctionTypeOf!(ov[1]); alias F_ov2 = FunctionTypeOf!(ov[2]); diff --git a/runtime/druntime/src/object.d b/runtime/druntime/src/object.d index 0385b51d60e..d98e698aa63 100644 --- a/runtime/druntime/src/object.d +++ b/runtime/druntime/src/object.d @@ -1417,7 +1417,7 @@ class TypeInfo_Function : TypeInfo int func(int a, int b); } - alias functionTypes = typeof(__traits(getVirtualFunctions, C, "func")); + alias functionTypes = typeof(__traits(getVirtualMethods, C, "func")); assert(typeid(functionTypes[0]).toString() == "void function()"); assert(typeid(functionTypes[1]).toString() == "void function(int)"); assert(typeid(functionTypes[2]).toString() == "int function(int, int)"); @@ -1431,7 +1431,7 @@ class TypeInfo_Function : TypeInfo void func(int a); } - alias functionTypes = typeof(__traits(getVirtualFunctions, C, "func")); + alias functionTypes = typeof(__traits(getVirtualMethods, C, "func")); Object obj = typeid(functionTypes[0]); assert(obj.opEquals(typeid(functionTypes[0]))); diff --git a/tests/dmd/compilable/ice13920.d b/tests/dmd/compilable/ice13920.d index 466b2e0449f..a4540d1eac8 100644 --- a/tests/dmd/compilable/ice13920.d +++ b/tests/dmd/compilable/ice13920.d @@ -14,11 +14,6 @@ class Foo { auto dg = &f; } - - foreach (f; __traits(getVirtualFunctions, typeof(this), "bar")) - { - auto dg = &f; - } } uint bar() { return 0; } diff --git a/tests/dmd/fail_compilation/deprecate_getVirtualFunctions.d b/tests/dmd/fail_compilation/deprecate_getVirtualFunctions.d new file mode 100644 index 00000000000..137482f98ac --- /dev/null +++ b/tests/dmd/fail_compilation/deprecate_getVirtualFunctions.d @@ -0,0 +1,20 @@ +// REQUIRED_ARGS: -de + +/* +TEST_OUTPUT: +--- +fail_compilation/deprecate_getVirtualFunctions.d(18): Deprecation: `traits(isVirtualFunction)` is deprecated. Use `traits(isVirtualMethod)` instead +fail_compilation/deprecate_getVirtualFunctions.d(19): Deprecation: `traits(getVirtualFunctions)` is deprecated. Use `traits(getVirtualMethods)` instead +--- +*/ + +class A +{ + void fun() {} +} + +void main() +{ + auto a = __traits(isVirtualFunction, A.fun); + foreach(f; __traits(getVirtualFunctions, A, "fun")) {} +} diff --git a/tests/dmd/fail_compilation/fail19076.d b/tests/dmd/fail_compilation/fail19076.d index 9bfc0a564eb..2441d6f3cae 100644 --- a/tests/dmd/fail_compilation/fail19076.d +++ b/tests/dmd/fail_compilation/fail19076.d @@ -8,4 +8,4 @@ fail_compilation/fail19076.d(11): Error: `(I).V` cannot be resolved interface P { } interface I : P { } -auto F = __traits(getVirtualFunctions, I, "V"); +auto F = __traits(getVirtualMethods, I, "V"); diff --git a/tests/dmd/fail_compilation/test17096.d b/tests/dmd/fail_compilation/test17096.d index e421419ae2d..2c431a3849b 100644 --- a/tests/dmd/fail_compilation/test17096.d +++ b/tests/dmd/fail_compilation/test17096.d @@ -1,28 +1,29 @@ /* TEST_OUTPUT: --- -fail_compilation/test17096.d(28): Error: expected 1 arguments for `isPOD` but had 2 -fail_compilation/test17096.d(29): Error: expected 1 arguments for `isNested` but had 2 -fail_compilation/test17096.d(30): Error: expected 1 arguments for `isVirtualFunction` but had 2 -fail_compilation/test17096.d(31): Error: expected 1 arguments for `isVirtualMethod` but had 2 -fail_compilation/test17096.d(32): Error: expected 1 arguments for `isAbstractFunction` but had 2 -fail_compilation/test17096.d(33): Error: expected 1 arguments for `isFinalFunction` but had 2 -fail_compilation/test17096.d(34): Error: expected 1 arguments for `isOverrideFunction` but had 2 -fail_compilation/test17096.d(35): Error: expected 1 arguments for `isStaticFunction` but had 2 -fail_compilation/test17096.d(36): Error: expected 1 arguments for `isRef` but had 2 -fail_compilation/test17096.d(37): Error: expected 1 arguments for `isOut` but had 2 -fail_compilation/test17096.d(38): Error: expected 1 arguments for `isLazy` but had 2 -fail_compilation/test17096.d(39): Error: expected 1 arguments for `identifier` but had 2 -fail_compilation/test17096.d(40): Error: expected 1 arguments for `getProtection` but had 2 -fail_compilation/test17096.d(41): Error: expected 1 arguments for `parent` but had 2 -fail_compilation/test17096.d(42): Error: expected 1 arguments for `classInstanceSize` but had 2 -fail_compilation/test17096.d(43): Error: expected 1 arguments for `allMembers` but had 2 -fail_compilation/test17096.d(44): Error: expected 1 arguments for `derivedMembers` but had 2 -fail_compilation/test17096.d(45): Error: expected 1 arguments for `getAliasThis` but had 2 -fail_compilation/test17096.d(46): Error: expected 1 arguments for `getAttributes` but had 2 -fail_compilation/test17096.d(47): Error: expected 1 arguments for `getFunctionAttributes` but had 2 -fail_compilation/test17096.d(48): Error: expected 1 arguments for `getUnitTests` but had 2 -fail_compilation/test17096.d(49): Error: expected 1 arguments for `getVirtualIndex` but had 2 -fail_compilation/test17096.d(50): Error: a single type expected for trait pointerBitmap +fail_compilation/test17096.d(29): Error: expected 1 arguments for `isPOD` but had 2 +fail_compilation/test17096.d(30): Error: expected 1 arguments for `isNested` but had 2 +fail_compilation/test17096.d(31): Deprecation: `traits(isVirtualFunction)` is deprecated. Use `traits(isVirtualMethod)` instead +fail_compilation/test17096.d(31): Error: expected 1 arguments for `isVirtualFunction` but had 2 +fail_compilation/test17096.d(32): Error: expected 1 arguments for `isVirtualMethod` but had 2 +fail_compilation/test17096.d(33): Error: expected 1 arguments for `isAbstractFunction` but had 2 +fail_compilation/test17096.d(34): Error: expected 1 arguments for `isFinalFunction` but had 2 +fail_compilation/test17096.d(35): Error: expected 1 arguments for `isOverrideFunction` but had 2 +fail_compilation/test17096.d(36): Error: expected 1 arguments for `isStaticFunction` but had 2 +fail_compilation/test17096.d(37): Error: expected 1 arguments for `isRef` but had 2 +fail_compilation/test17096.d(38): Error: expected 1 arguments for `isOut` but had 2 +fail_compilation/test17096.d(39): Error: expected 1 arguments for `isLazy` but had 2 +fail_compilation/test17096.d(40): Error: expected 1 arguments for `identifier` but had 2 +fail_compilation/test17096.d(41): Error: expected 1 arguments for `getProtection` but had 2 +fail_compilation/test17096.d(42): Error: expected 1 arguments for `parent` but had 2 +fail_compilation/test17096.d(43): Error: expected 1 arguments for `classInstanceSize` but had 2 +fail_compilation/test17096.d(44): Error: expected 1 arguments for `allMembers` but had 2 +fail_compilation/test17096.d(45): Error: expected 1 arguments for `derivedMembers` but had 2 +fail_compilation/test17096.d(46): Error: expected 1 arguments for `getAliasThis` but had 2 +fail_compilation/test17096.d(47): Error: expected 1 arguments for `getAttributes` but had 2 +fail_compilation/test17096.d(48): Error: expected 1 arguments for `getFunctionAttributes` but had 2 +fail_compilation/test17096.d(49): Error: expected 1 arguments for `getUnitTests` but had 2 +fail_compilation/test17096.d(50): Error: expected 1 arguments for `getVirtualIndex` but had 2 +fail_compilation/test17096.d(51): Error: a single type expected for trait pointerBitmap --- */ enum b03 = __traits(isPOD, 1, 2); diff --git a/tests/dmd/runnable/e7804.d b/tests/dmd/runnable/e7804.d index d32531055f5..ff66310ff2b 100644 --- a/tests/dmd/runnable/e7804.d +++ b/tests/dmd/runnable/e7804.d @@ -63,8 +63,6 @@ TmpPrm!(__traits(getMember, Foo, "MyInt")) tpt = TmpPrm!(__traits(getMember, Foo int virtual(int p){return p;} void test(this T)() { - alias vf = __traits(getVirtualFunctions, Class, "virtual"); - assert(vf.length == 2); alias vm = __traits(getVirtualMethods, Class, "virtual"); assert(vm.length == 1); assert(vm[0](42) == 42); diff --git a/tests/dmd/runnable/traits.d b/tests/dmd/runnable/traits.d index ddd505919d2..5186987deae 100644 --- a/tests/dmd/runnable/traits.d +++ b/tests/dmd/runnable/traits.d @@ -312,14 +312,6 @@ void test9() /********************************************************/ -void test10() -{ - assert(__traits(isVirtualFunction, C.bar) == true); - assert(__traits(isVirtualFunction, S.bar) == false); -} - -/********************************************************/ - void test11() { assert(__traits(isAbstractFunction, C.bar) == false); @@ -403,24 +395,6 @@ class D15 int foo(int) { return 2; } } -void test15() -{ - D15 d = new D15(); - - assert(__traits(getVirtualFunctions, D15, "foo").length == 2); - assert(typeid(typeof(__traits(getVirtualFunctions, D15, "foo")[0])).toString() - == "void function()"); - assert(typeid(typeof(__traits(getVirtualFunctions, D15, "foo")[1])).toString() - == "int function(int)"); - - alias typeof(__traits(getVirtualFunctions, D15, "foo")) b; - assert(typeid(b[0]).toString() == "void function()"); - assert(typeid(b[1]).toString() == "int function(int)"); - - auto i = __traits(getVirtualFunctions, d, "foo")[1](1); - assert(i == 2); -} - /********************************************************/ struct S16 { } @@ -714,14 +688,6 @@ interface AA int YYY(); } -class CC : AA -{ - final int YYY() { return 4; } -} - -static assert(__traits(isVirtualMethod, CC.YYY)); -static assert(__traits(getVirtualMethods, CC, "YYY").length == 1); - class DD { final int YYY() { return 4; } @@ -790,8 +756,6 @@ void test7858() static assert(__traits(isFinalFunction, C.ffunc) == __traits(isFinalFunction, __traits(getOverloads, C, "ffunc")[0])); // NG - static assert(__traits(isVirtualFunction, C.vfunc) == - __traits(isVirtualFunction, __traits(getOverloads, C, "vfunc")[0])); // NG static assert(__traits(isVirtualMethod, C.vfunc) == __traits(isVirtualMethod, __traits(getOverloads, C, "vfunc")[0])); // NG static assert(__traits(isAbstractFunction, C.afunc) == @@ -1456,13 +1420,11 @@ int main() test7(); test8(); test9(); - test10(); test11(); test12(); test13(); test7123(); test14(); - test15(); test16(); test17(); test18(); From f159de7ad0146ea2c185037f845161d32e215beb Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Fri, 20 Jan 2023 20:59:08 +0800 Subject: [PATCH 038/177] Fix Issue 23639 - Casting to shared not allowed with -preview=nosharedaccess (dlang/dmd!14836) --- dmd/expressionsem.d | 4 +++- tests/dmd/compilable/test23639.d | 12 ++++++++++++ tests/dmd/fail_compilation/shared.d | 23 +++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/compilable/test23639.d diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index bd04d429f25..675ef10f43d 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -13185,7 +13185,9 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false) // Error by default bool visit(Expression e) { - if (e.type.isShared()) + // https://issues.dlang.org/show_bug.cgi?id=23639 + // Should be able to cast(shared) + if (!e.isCastExp() && e.type.isShared()) return sharedError(e); return false; } diff --git a/tests/dmd/compilable/test23639.d b/tests/dmd/compilable/test23639.d new file mode 100644 index 00000000000..e2ec002c848 --- /dev/null +++ b/tests/dmd/compilable/test23639.d @@ -0,0 +1,12 @@ +// https://issues.dlang.org/show_bug.cgi?id=23639 + +// REQUIRED_ARGS: -preview=nosharedaccess + +class T {} + +shared(T) allocClassMem() +{ + void *p; + // assume p is allocated here + return cast(shared(T))p; +} diff --git a/tests/dmd/fail_compilation/shared.d b/tests/dmd/fail_compilation/shared.d index 7d15b16bdc1..413905ceb6e 100644 --- a/tests/dmd/fail_compilation/shared.d +++ b/tests/dmd/fail_compilation/shared.d @@ -236,3 +236,26 @@ struct BitRange this.bits++; } } + +/* +TEST_OUTPUT: +--- +fail_compilation/shared.d(3004): Error: cast from `void*` to `shared(int*)` not allowed in safe code +fail_compilation/shared.d(3005): Error: cast from `void*` to `shared(const(int*))` not allowed in safe code +fail_compilation/shared.d(3008): Error: cast from `shared(void*)` to `int*` not allowed in safe code +fail_compilation/shared.d(3009): Error: cast from `shared(void*)` to `shared(const(int*))` not allowed in safe code +--- +*/ + +#line 3000 + +void test_casting_safe() @safe +{ + void *p; + auto t1 = cast(shared(int*))p; + auto t2 = cast(const(shared(int*)))p; + + shared void* s; + auto x1 = cast(int*)s; + auto x2 = cast(const(shared(int*)))s; +} From 06a13c941079a626b11af5d7f67afdee8138e97e Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sat, 21 Jan 2023 16:00:41 +0000 Subject: [PATCH 039/177] =?UTF-8?q?Fix=20Issue=C2=A023635=20-=20Nonsensica?= =?UTF-8?q?l=20"`case`=20must=20be=20a=20`string`=20or=20an=20integral=20c?= =?UTF-8?q?onstant,=20not=20`x`"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dmd/statementsem.d | 2 +- tests/dmd/fail_compilation/diag9358.d | 17 ++++++++++++++--- tests/dmd/fail_compilation/test_switch_error.d | 6 +++--- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/dmd/statementsem.d b/dmd/statementsem.d index 5764efd60fd..81678d01e0c 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -2485,7 +2485,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor cs.exp = se; else if (!cs.exp.isIntegerExp() && !cs.exp.isErrorExp()) { - cs.error("`case` must be a `string` or an integral constant, not `%s`", cs.exp.toChars()); + cs.error("`case` expression must be a compile-time `string` or an integral constant, not `%s`", cs.exp.toChars()); errors = true; } diff --git a/tests/dmd/fail_compilation/diag9358.d b/tests/dmd/fail_compilation/diag9358.d index 5aea6b5f9c1..58dd495ab8e 100644 --- a/tests/dmd/fail_compilation/diag9358.d +++ b/tests/dmd/fail_compilation/diag9358.d @@ -1,9 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/diag9358.d(12): Error: `x` must be of integral or string type, it is a `double` -fail_compilation/diag9358.d(14): Error: `case` must be a `string` or an integral constant, not `1.1` -fail_compilation/diag9358.d(15): Error: `case` must be a `string` or an integral constant, not `2.1` +fail_compilation/diag9358.d(13): Error: `x` must be of integral or string type, it is a `double` +fail_compilation/diag9358.d(15): Error: `case` expression must be a compile-time `string` or an integral constant, not `1.1` +fail_compilation/diag9358.d(16): Error: `case` expression must be a compile-time `string` or an integral constant, not `2.1` +fail_compilation/diag9358.d(26): Error: `case` expression must be a compile-time `string` or an integral constant, not `z` --- */ void main() @@ -16,3 +17,13 @@ void main() default: } } + +void f(immutable string y) +{ + auto z = y[0..2]; + switch (y) + { + case z: break; + default: + } +} diff --git a/tests/dmd/fail_compilation/test_switch_error.d b/tests/dmd/fail_compilation/test_switch_error.d index bfd8803d2f2..41b6e52545e 100644 --- a/tests/dmd/fail_compilation/test_switch_error.d +++ b/tests/dmd/fail_compilation/test_switch_error.d @@ -104,7 +104,7 @@ void test5(int i) TEST_OUTPUT: --- fail_compilation/test_switch_error.d(513): Error: undefined identifier `undefinedFunc` -fail_compilation/test_switch_error.d(517): Error: `case` must be a `string` or an integral constant, not `Strukt(1)` +fail_compilation/test_switch_error.d(517): Error: `case` expression must be a compile-time `string` or an integral constant, not `Strukt(1)` fail_compilation/test_switch_error.d(518): Error: `case` variables have to be `const` or `immutable` fail_compilation/test_switch_error.d(518): Error: `case` variables not allowed in `final switch` statements fail_compilation/test_switch_error.d(519): Error: `case` variables not allowed in `final switch` statements @@ -144,8 +144,8 @@ void errorsWithErrors(int param, immutable int constant) TEST_OUTPUT: --- fail_compilation/test_switch_error.d(622): Error: undefined identifier `undefinedFunc` -fail_compilation/test_switch_error.d(624): Error: `case` must be a `string` or an integral constant, not `SubtypeOfInt(2)` -fail_compilation/test_switch_error.d(625): Error: `case` must be a `string` or an integral constant, not `SubtypeOfIntMethod()` +fail_compilation/test_switch_error.d(624): Error: `case` expression must be a compile-time `string` or an integral constant, not `SubtypeOfInt(2)` +fail_compilation/test_switch_error.d(625): Error: `case` expression must be a compile-time `string` or an integral constant, not `SubtypeOfIntMethod()` --- ++/ #line 600 From e023a6c61ce7ed553614502959f9164fd63caa71 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 21 Jan 2023 21:35:01 -0800 Subject: [PATCH 040/177] fix Issue 16495 - __traits(fullyQualifedName) instead of std.traits.fullyQualifiedName (dlang/dmd!14711) --- dmd/frontend.h | 1 + dmd/id.d | 1 + dmd/traits.d | 39 ++++++++- tests/dmd/compilable/test16495.d | 117 +++++++++++++++++++++++++ tests/dmd/fail_compilation/test16495.d | 18 ++++ 5 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/compilable/test16495.d create mode 100644 tests/dmd/fail_compilation/test16495.d diff --git a/dmd/frontend.h b/dmd/frontend.h index fc1058a682a..d27738667c1 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -8692,6 +8692,7 @@ struct Id final static Identifier* isLazy; static Identifier* hasMember; static Identifier* identifier; + static Identifier* fullyQualifiedName; static Identifier* getProtection; static Identifier* getVisibility; static Identifier* parent; diff --git a/dmd/id.d b/dmd/id.d index 40a5c6e47f6..73fde18ed11 100644 --- a/dmd/id.d +++ b/dmd/id.d @@ -455,6 +455,7 @@ immutable Msgtable[] msgtable = { "isLazy" }, { "hasMember" }, { "identifier" }, + { "fullyQualifiedName" }, { "getProtection" }, { "getVisibility" }, { "parent" }, diff --git a/dmd/traits.d b/dmd/traits.d index f991c0b5673..e4eaa9c596e 100644 --- a/dmd/traits.d +++ b/dmd/traits.d @@ -743,6 +743,42 @@ Expression semanticTraits(TraitsExp e, Scope* sc) auto se = new StringExp(e.loc, id.toString()); return se.expressionSemantic(sc); } + if (e.ident == Id.fullyQualifiedName) // https://dlang.org/spec/traits.html#fullyQualifiedName + { + if (dim != 1) + return dimError(1); + + Scope* sc2 = sc.push(); + sc2.flags = sc.flags | SCOPE.noaccesscheck | SCOPE.ignoresymbolvisibility; + bool ok = TemplateInstance.semanticTiargs(e.loc, sc2, e.args, 1); + sc2.pop(); + if (!ok) + return ErrorExp.get(); + + const(char)[] fqn; + auto o = (*e.args)[0]; + if (auto s = getDsymbolWithoutExpCtx(o)) + { + if (s.semanticRun == PASS.initial) + s.dsymbolSemantic(null); + + fqn = s.toPrettyChars().toDString(); + } + else if (auto t = getType(o)) + { + fqn = t.toPrettyChars(true).toDString(); + } + else + { + if (!isError(o)) + e.error("argument `%s` has no identifier", o.toChars()); + return ErrorExp.get(); + } + assert(fqn); + auto se = new StringExp(e.loc, fqn); + return se.expressionSemantic(sc); + + } if (e.ident == Id.getProtection || e.ident == Id.getVisibility) { if (dim != 1) @@ -2208,7 +2244,7 @@ private void traitNotFound(TraitsExp e) initialized = true; // lazy initialization // All possible traits - __gshared Identifier*[58] idents = + __gshared Identifier*[59] idents = [ &Id.isAbstractClass, &Id.isArithmetic, @@ -2238,6 +2274,7 @@ private void traitNotFound(TraitsExp e) &Id.isReturnOnStack, &Id.hasMember, &Id.identifier, + &Id.fullyQualifiedName, &Id.getProtection, &Id.getVisibility, &Id.parent, diff --git a/tests/dmd/compilable/test16495.d b/tests/dmd/compilable/test16495.d new file mode 100644 index 00000000000..70f11be49b8 --- /dev/null +++ b/tests/dmd/compilable/test16495.d @@ -0,0 +1,117 @@ +// https://issues.dlang.org/show_bug.cgi?id=16495 + +void types() +{ + static assert(__traits(fullyQualifiedName, string) == "string"); + static assert(__traits(fullyQualifiedName, wstring) == "wstring"); + static assert(__traits(fullyQualifiedName, dstring) == "dstring"); + static assert(__traits(fullyQualifiedName, typeof(null)) == "typeof(null)"); + static assert(__traits(fullyQualifiedName, void) == "void"); + static assert(__traits(fullyQualifiedName, const(void)) == "const(void)"); + static assert(__traits(fullyQualifiedName, shared(void)) == "shared(void)"); + static assert(__traits(fullyQualifiedName, shared const(void)) == "shared(const(void))"); + static assert(__traits(fullyQualifiedName, shared inout(void)) == "shared(inout(void))"); + static assert(__traits(fullyQualifiedName, shared inout const(void)) == "shared(inout(const(void)))"); + static assert(__traits(fullyQualifiedName, inout(void)) == "inout(void)"); + static assert(__traits(fullyQualifiedName, inout const(void)) == "inout(const(void))"); + static assert(__traits(fullyQualifiedName, immutable(void)) == "immutable(void)"); +} + +struct QualifiedNameTests +{ + struct Inner + { + bool value; + } + + ref const(Inner[string]) func( ref Inner var1, lazy scope string var2 ); + ref const(Inner[string]) retfunc( return ref Inner var1 ); + Inner inoutFunc(inout Inner) inout; + shared(const(Inner[string])[]) data; + const Inner delegate(double, string) @safe nothrow deleg; + inout(int) delegate(inout int) inout inoutDeleg; + Inner function(out double, string) funcPtr; + extern(C) Inner function(double, string) cFuncPtr; + + extern(C) void cVarArg(int, ...); + void dVarArg(...); + void dVarArg2(int, ...); + void typesafeVarArg(int[] ...); + + Inner[] array; + Inner[16] sarray; + Inner[Inner] aarray; + const(Inner[const(Inner)]) qualAarray; + + shared(immutable(Inner) delegate(ref double, scope string) const shared @trusted nothrow) attrDeleg; + + struct Data(T) { int x; } + void tfunc(T...)(T args) {} + + template Inst(alias A) { int x; } + + class Test12309(T, int x, string s) {} +} + +void symbols() +{ + alias qnTests = QualifiedNameTests; + enum prefix = "test16495.QualifiedNameTests."; + static assert(__traits(fullyQualifiedName, qnTests.Inner) == prefix ~ "Inner"); + static assert(__traits(fullyQualifiedName, qnTests.func) == prefix ~ "func"); + + static assert(__traits(fullyQualifiedName, qnTests.Data!int) == prefix ~ "Data!int.Data"); + static assert(__traits(fullyQualifiedName, qnTests.Data!int.x) == prefix ~ "Data!int.Data.x"); + static assert(__traits(fullyQualifiedName, qnTests.tfunc!(int[])) == prefix ~ "tfunc!(int[]).tfunc"); + static assert(__traits(fullyQualifiedName, qnTests.Inst!(Object)) == prefix ~ "Inst!(Object)"); + static assert(__traits(fullyQualifiedName, qnTests.Inst!(Object).x) == prefix ~ "Inst!(Object).x"); + static assert(__traits(fullyQualifiedName, qnTests.Test12309!(int, 10, "str")) + == prefix ~ "Test12309!(int, 10, \"str\").Test12309"); +} + +void names() +{ + enum prefix = "test16495.QualifiedNameTests"; + enum xx = prefix ~ ".Inner"; + with (QualifiedNameTests) + { + // Basic qualified name + static assert(__traits(fullyQualifiedName, Inner) == xx); + + // Array types + static assert(__traits(fullyQualifiedName, typeof(array)) == xx ~ "[]"); + static assert(__traits(fullyQualifiedName, typeof(sarray)) == xx ~ "[16]"); + static assert(__traits(fullyQualifiedName, typeof(aarray)) == xx ~ "[" ~ xx ~ "]"); + + // qualified key for AA + static assert(__traits(fullyQualifiedName, typeof(qualAarray)) == "const(" ~ xx ~ "[const(" ~ xx ~ ")])"); + + // Qualified composed data types + static assert(__traits(fullyQualifiedName, typeof(data)) == "shared(const(" ~ xx ~ "[string])[])"); + + // Function types + function attributes + static assert(__traits(fullyQualifiedName, typeof(func)) == "ref const(" ~ xx ~ "[string])(ref " ~ xx ~ ", lazy scope string)"); + static assert(__traits(fullyQualifiedName, typeof(retfunc)) == "ref const(" ~ xx ~ "[string])(return ref " ~ xx ~ ")"); + static assert(__traits(fullyQualifiedName, typeof(inoutFunc)) == "inout "~xx~"(inout("~xx~"))"); + static assert(__traits(fullyQualifiedName, typeof(deleg)) == "const(" ~ xx ~ " delegate(double, string) nothrow @safe)"); + static assert(__traits(fullyQualifiedName, typeof(inoutDeleg)) == "inout(int) delegate(inout(int)) inout"); + static assert(__traits(fullyQualifiedName, typeof(funcPtr)) == "" ~ xx ~ " function(out double, string)"); + static assert(__traits(fullyQualifiedName, typeof(cFuncPtr)) == "extern (C) " ~ xx ~ " function(double, string)"); + + // Delegate type with qualified function type + static assert(__traits(fullyQualifiedName, typeof(attrDeleg)) == "shared(immutable(" ~ xx ~ ") "~ + "delegate(ref double, scope string) shared const nothrow @trusted)"); + + // Variable argument function types + static assert(__traits(fullyQualifiedName, typeof(cVarArg)) == "extern (C) void(int, ...)"); + static assert(__traits(fullyQualifiedName, typeof(dVarArg)) == "void(...)"); + static assert(__traits(fullyQualifiedName, typeof(dVarArg2)) == "void(int, ...)"); + static assert(__traits(fullyQualifiedName, typeof(typesafeVarArg)) == "void(int[]...)"); + + // SIMD vector + static if (is(__vector(float[4]))) + { + static assert(__traits(fullyQualifiedName, __vector(float[4])) == "__vector(float[4])"); + } + } +} diff --git a/tests/dmd/fail_compilation/test16495.d b/tests/dmd/fail_compilation/test16495.d new file mode 100644 index 00000000000..667d4c2feb7 --- /dev/null +++ b/tests/dmd/fail_compilation/test16495.d @@ -0,0 +1,18 @@ +/* TEST_OUTPUT: +--- +fail_compilation/test16495.d(12): Error: undefined identifier `q` +fail_compilation/test16495.d(17): Error: expected 1 arguments for `fullyQualifiedName` but had 0 +--- + */ + +// https://issues.dlang.org/show_bug.cgi?id=16495 + +void test1() +{ + auto m = __traits(fullyQualifiedName, q); +} + +void test2() +{ + auto n = __traits(fullyQualifiedName); +} From c80da7d3b4d994edcf5602a2a78aab72fbd7ecad Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 23 Jan 2023 18:57:15 -0800 Subject: [PATCH 041/177] AliasDeclaration semantic --- dmd/dsymbolsem.d | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 322f43ea40c..6125a218e76 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -338,6 +338,17 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor return; assert(dsym.semanticRun <= PASS.semantic); + if (dsym._scope) + { + sc = dsym._scope; + dsym._scope = null; + } + + if (!sc) + return; + + dsym.semanticRun = PASS.semantic; + dsym.storage_class |= sc.stc & STC.deprecated_; dsym.visibility = sc.visibility; dsym.userAttribDecl = sc.userAttribDecl; From 060c55f19ca7b3f23824c9a6f8254254aa2b745d Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 23 Jan 2023 19:50:04 -0800 Subject: [PATCH 042/177] fix Issue 23651 - Order dependency in semantic analysis of template members --- dmd/dsymbolsem.d | 6 ------ dmd/dtemplate.d | 12 ++++++++++- tests/dmd/compilable/test23651.d | 34 ++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 tests/dmd/compilable/test23651.d diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 6125a218e76..5a1434d6984 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -338,12 +338,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor return; assert(dsym.semanticRun <= PASS.semantic); - if (dsym._scope) - { - sc = dsym._scope; - dsym._scope = null; - } - if (!sc) return; diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 6c78a62a94c..305848f72c5 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -6591,7 +6591,17 @@ extern (C++) class TemplateInstance : ScopeDsymbol } TemplateInstance ti = s.parent ? s.parent.isTemplateInstance() : null; - if (ti && (ti.name == s.ident || ti.toAlias().ident == s.ident) && ti.tempdecl) + + /* This avoids the VarDeclaration.toAlias() which runs semantic() too soon + */ + static bool matchId(TemplateInstance ti, Identifier id) + { + if (ti.aliasdecl && ti.aliasdecl.isVarDeclaration()) + return ti.aliasdecl.isVarDeclaration().ident == id; + return ti.toAlias().ident == id; + } + + if (ti && (ti.name == s.ident || matchId(ti, s.ident)) && ti.tempdecl) { /* This is so that one can refer to the enclosing * template, even if it has the same name as a member diff --git a/tests/dmd/compilable/test23651.d b/tests/dmd/compilable/test23651.d new file mode 100644 index 00000000000..8c477b0c0b6 --- /dev/null +++ b/tests/dmd/compilable/test23651.d @@ -0,0 +1,34 @@ +// https://issues.dlang.org/show_bug.cgi?id=23651 + +template isCallable(alias callable) +{ + static if (is(typeof(&callable!()))) + enum bool isCallable = isCallable!(typeof(&callable!())); + else + enum bool isCallable = true; +} + +string foo(); + +template FunctionTypeOf(alias func) +if (isCallable!func) +{ + alias FunctionTypeOf = typeof(foo); +} + +template ReturnType(alias func) +{ + static if (is(FunctionTypeOf!func R == return)) + alias ReturnType = R; +} + +template isAttrRange() +{ + alias NameType = ReturnType!((string r) => r); + //pragma(msg, "isAttrRange ", NameType, " ", string); + static assert(is(NameType == string)); + + enum isAttrRange = is(NameType == string); +} + +static assert(isAttrRange!()); From 498dd3691016109f7778627ecdd9651130d59c94 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Tue, 24 Jan 2023 10:48:00 +0000 Subject: [PATCH 043/177] Fix issue 11051 - Unmatched case in a final switch should throw in both release and non-release mode (dlang/dmd!14841) * Fix issue 11051 Keep a HALT instruction in a final switch statement if the function is @safe and -release mode is enabled. * @system -release test should also be non-zero * don't suppress test errors * Remove unreported error line * Disable core dumps Co-authored-by: Andrej Mitrovic --- dmd/statementsem.d | 2 +- tests/dmd/runnable/extra-files/test11051.d | 30 ++++++++++++++++++++ tests/dmd/runnable/test_safe_final_switch.sh | 29 +++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/runnable/extra-files/test11051.d create mode 100755 tests/dmd/runnable/test_safe_final_switch.sh diff --git a/dmd/statementsem.d b/dmd/statementsem.d index 81678d01e0c..79ec1f5f6de 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -2256,7 +2256,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor } if (!sc.sw.sdefault && - (!ss.isFinal || needswitcherror || global.params.useAssert == CHECKENABLE.on)) + (!ss.isFinal || needswitcherror || global.params.useAssert == CHECKENABLE.on || sc.func.isSafe)) { ss.hasNoDefault = 1; diff --git a/tests/dmd/runnable/extra-files/test11051.d b/tests/dmd/runnable/extra-files/test11051.d new file mode 100644 index 00000000000..c8bfdc278bd --- /dev/null +++ b/tests/dmd/runnable/extra-files/test11051.d @@ -0,0 +1,30 @@ +module test11051; + +version (Safe) +{ + void main() @safe + { + enum E { A, B } + E e = cast(E)-1; + + final switch (e) + { + case E.A: break; + case E.B: break; + } + } +} +else +{ + void main() + { + enum E { A, B } + E e = cast(E)-1; + + final switch (e) + { + case E.A: break; + case E.B: break; + } + } +} diff --git a/tests/dmd/runnable/test_safe_final_switch.sh b/tests/dmd/runnable/test_safe_final_switch.sh new file mode 100755 index 00000000000..ae0312009d5 --- /dev/null +++ b/tests/dmd/runnable/test_safe_final_switch.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +# tests various @safe behavior for final switches in +# -release and non-release builds + +src_file=runnable/extra-files/test11051.d + +die() +{ + echo "test_safe_final_switch.sh error: test #$1 failed" + exit 1 +} + +# some tests cause a core dump rather than throwing an Error +ulimit -c 0 + +# returns 1 (failure) +$DMD -run ${src_file} 2> /dev/null && die 1 + +# returns 1 (failure) +$DMD -release -run ${src_file} 2> /dev/null && die 2 + +# returns 1 (failure) +$DMD -version=Safe -run ${src_file} 2> /dev/null && die 3 + +# returns 1 (failure) +$DMD -release -version=Safe -run ${src_file} 2> /dev/null && die 4 + +exit 0 From 17b9e8f5ca94c6b71c23da9e0293b4620f7c0784 Mon Sep 17 00:00:00 2001 From: Johan Engelen Date: Sat, 22 Oct 2022 16:23:10 +0200 Subject: [PATCH 044/177] Add -verror-supplements, to let the user define how many supplemental error messages he wants to see. In particular this prevents having to rebuild with "-v" flag for ... (18 instantiations, -v to show) to show (and with all the other -v noise). --- dmd/cli.d | 3 ++ dmd/dtemplate.d | 5 ++- dmd/frontend.h | 5 ++- dmd/func.d | 6 ++- dmd/globals.d | 1 + dmd/globals.h | 1 + dmd/mars.d | 8 ++++ dmd/statementsem.d | 4 +- tests/dmd/fail_compilation/diag8101.d | 50 +++++++++++++----------- tests/dmd/fail_compilation/fail15616a.d | 5 ++- tests/dmd/fail_compilation/fail15616c.d | 52 +++++++++++++++++++++++++ tests/dmd/fail_compilation/fail15616d.d | 41 +++++++++++++++++++ 12 files changed, 151 insertions(+), 30 deletions(-) create mode 100644 tests/dmd/fail_compilation/fail15616c.d create mode 100644 tests/dmd/fail_compilation/fail15616d.d diff --git a/dmd/cli.d b/dmd/cli.d index de1f26534d7..9fbb44d3e94 100644 --- a/dmd/cli.d +++ b/dmd/cli.d @@ -768,6 +768,9 @@ dmd -cov -unittest myprog.d $(DT gnu)$(DD 'file:line[:column]: message', conforming to the GNU standard used by gcc and clang.) )`, ), + Option("verror-supplements=", + "limit the number of supplemental messages for each error (0 means unlimited)" + ), Option("verrors=", "limit the number of error messages (0 means unlimited)" ), diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 305848f72c5..17e128b6376 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -6010,7 +6010,10 @@ extern (C++) class TemplateInstance : ScopeDsymbol return; // Print full trace for verbose mode, otherwise only short traces - const(uint) max_shown = !global.params.verbose ? 6 : uint.max; + const(uint) max_shown = !global.params.verbose ? + (global.params.errorSupplementLimit ? global.params.errorSupplementLimit : uint.max) + : uint.max; + const(char)* format = "instantiated from here: `%s`"; // This returns a function pointer diff --git a/dmd/frontend.h b/dmd/frontend.h index d27738667c1..207a5ea263c 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -3097,6 +3097,7 @@ struct Param final CHECKENABLE boundscheck; CHECKACTION checkAction; uint32_t errorLimit; + uint32_t errorSupplementLimit; _d_dynamicArray< const char > argv0; Array modFileAliasStrings; Array* imppath; @@ -3194,6 +3195,7 @@ struct Param final boundscheck((CHECKENABLE)0u), checkAction((CHECKACTION)0u), errorLimit(20u), + errorSupplementLimit(6u), argv0(), modFileAliasStrings(), imppath(), @@ -3227,7 +3229,7 @@ struct Param final mapfile() { } - Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool verbose = false, bool vcg_ast = false, bool showColumns = false, bool vtls = false, bool vtemplates = false, bool vtemplatesListInstances = false, bool vgc = false, bool vfield = false, bool vcomplex = true, bool vin = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting warnings = (DiagnosticReporting)2u, bool color = false, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = false, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, bool showGaggedErrors = false, bool printErrorContext = false, bool manual = false, bool usage = false, bool mcpuUsage = false, bool transitionUsage = false, bool checkUsage = false, bool checkActionUsage = false, bool revertUsage = false, bool previewUsage = false, bool externStdUsage = false, bool hcUsage = false, bool logo = false, FeatureState useDIP25 = (FeatureState)-1, FeatureState useDIP1000 = (FeatureState)-1, bool ehnogc = false, bool useDIP1021 = false, bool fieldwise = false, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)-1, FeatureState noSharedAccess = (FeatureState)-1, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)-1, FeatureState systemVariables = (FeatureState)-1, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, uint32_t errorLimit = 20u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array* imppath = nullptr, Array* fileImppath = nullptr, _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), uint32_t debuglevel = 0u, Array* debugids = nullptr, uint32_t versionlevel = 0u, Array* versionids = nullptr, MessageStyle messageStyle = (MessageStyle)0u, bool run = false, Array runargs = Array(), Array cppswitches = Array(), Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}) : + Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool verbose = false, bool vcg_ast = false, bool showColumns = false, bool vtls = false, bool vtemplates = false, bool vtemplatesListInstances = false, bool vgc = false, bool vfield = false, bool vcomplex = true, bool vin = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting warnings = (DiagnosticReporting)2u, bool color = false, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = false, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, bool showGaggedErrors = false, bool printErrorContext = false, bool manual = false, bool usage = false, bool mcpuUsage = false, bool transitionUsage = false, bool checkUsage = false, bool checkActionUsage = false, bool revertUsage = false, bool previewUsage = false, bool externStdUsage = false, bool hcUsage = false, bool logo = false, FeatureState useDIP25 = (FeatureState)-1, FeatureState useDIP1000 = (FeatureState)-1, bool ehnogc = false, bool useDIP1021 = false, bool fieldwise = false, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)-1, FeatureState noSharedAccess = (FeatureState)-1, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)-1, FeatureState systemVariables = (FeatureState)-1, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, uint32_t errorLimit = 20u, uint32_t errorSupplementLimit = 6u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array* imppath = nullptr, Array* fileImppath = nullptr, _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), uint32_t debuglevel = 0u, Array* debugids = nullptr, uint32_t versionlevel = 0u, Array* versionids = nullptr, MessageStyle messageStyle = (MessageStyle)0u, bool run = false, Array runargs = Array(), Array cppswitches = Array(), Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}) : obj(obj), multiobj(multiobj), trace(trace), @@ -3298,6 +3300,7 @@ struct Param final boundscheck(boundscheck), checkAction(checkAction), errorLimit(errorLimit), + errorSupplementLimit(errorSupplementLimit), argv0(argv0), modFileAliasStrings(modFileAliasStrings), imppath(imppath), diff --git a/dmd/func.d b/dmd/func.d index cfeec41c08b..4e663da1639 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -3364,8 +3364,10 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, private void printCandidates(Decl)(const ref Loc loc, Decl declaration, bool showDeprecated) if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration)) { - // max num of overloads to print (-v overrides this). - enum int DisplayLimit = 5; + // max num of overloads to print (-v or -verror-supplements overrides this). + const int DisplayLimit = !global.params.verbose ? + (global.params.errorSupplementLimit ? global.params.errorSupplementLimit : int.max) + : int.max; const(char)* constraintsTip; // determine if the first candidate was printed int printed; diff --git a/dmd/globals.d b/dmd/globals.d index 80c183e5a77..e6b4e31690a 100644 --- a/dmd/globals.d +++ b/dmd/globals.d @@ -176,6 +176,7 @@ extern (C++) struct Param CHECKACTION checkAction = CHECKACTION.D; // action to take when bounds, asserts or switch defaults are violated uint errorLimit = 20; + uint errorSupplementLimit = 6; // Limit the number of supplemental messages for each error (0 means unlimited) const(char)[] argv0; // program name Array!(const(char)*) modFileAliasStrings; // array of char*'s of -I module filename alias strings diff --git a/dmd/globals.h b/dmd/globals.h index 45c5624b19c..dc637f86c3e 100644 --- a/dmd/globals.h +++ b/dmd/globals.h @@ -179,6 +179,7 @@ struct Param CHECKACTION checkAction; // action to take when bounds, asserts or switch defaults are violated unsigned errorLimit; + unsigned errorSupplementLimit; // Limit the number of supplemental messages for each error (0 means unlimited) DString argv0; // program name Array modFileAliasStrings; // array of char*'s of -I module filename alias strings diff --git a/dmd/mars.d b/dmd/mars.d index 73d0ddbbfc7..48736b18ced 100644 --- a/dmd/mars.d +++ b/dmd/mars.d @@ -1876,6 +1876,14 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param return true; } } + else if (startsWith(p + 1, "verror-supplements")) + { + if (!params.errorSupplementLimit.parseDigits(p.toDString()[20 .. $])) + { + errorInvalidSwitch(p, "Only a number is allowed for `-verror-supplements`"); + return true; + } + } else if (startsWith(p + 1, "verror-style=")) { const(char)[] style = arg["verror-style=".length + 1 .. $]; diff --git a/dmd/statementsem.d b/dmd/statementsem.d index 79ec1f5f6de..5b8883f6941 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -2222,7 +2222,9 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor if (ed && ss.cases.length < ed.members.length) { int missingMembers = 0; - const maxShown = !global.params.verbose ? 6 : int.max; + const maxShown = !global.params.verbose ? + (global.params.errorSupplementLimit ? global.params.errorSupplementLimit : int.max) + : int.max; Lmembers: foreach (es; *ed.members) { diff --git a/tests/dmd/fail_compilation/diag8101.d b/tests/dmd/fail_compilation/diag8101.d index 9644fdd2242..ddc74e28131 100644 --- a/tests/dmd/fail_compilation/diag8101.d +++ b/tests/dmd/fail_compilation/diag8101.d @@ -1,30 +1,32 @@ /* TEST_OUTPUT: --- -fail_compilation/diag8101.d(57): Error: function `diag8101.f_0(int)` is not callable using argument types `()` -fail_compilation/diag8101.d(57): too few arguments, expected 1, got 0 -fail_compilation/diag8101.d(58): Error: none of the overloads of `f_1` are callable using argument types `()` -fail_compilation/diag8101.d(33): Candidates are: `diag8101.f_1(int)` -fail_compilation/diag8101.d(34): `diag8101.f_1(int, int)` -fail_compilation/diag8101.d(59): Error: none of the overloads of `f_2` are callable using argument types `()` -fail_compilation/diag8101.d(36): Candidates are: `diag8101.f_2(int)` -fail_compilation/diag8101.d(37): `diag8101.f_2(int, int)` -fail_compilation/diag8101.d(38): `diag8101.f_2(int, int, int)` -fail_compilation/diag8101.d(39): `diag8101.f_2(int, int, int, int)` -fail_compilation/diag8101.d(40): `diag8101.f_2(int, int, int, int, int)` -fail_compilation/diag8101.d(59): ... (1 more, -v to show) ... -fail_compilation/diag8101.d(61): Error: none of the overloads of template `diag8101.t_0` are callable using argument types `!()()` -fail_compilation/diag8101.d(43): Candidate is: `t_0(T1)()` -fail_compilation/diag8101.d(62): Error: none of the overloads of template `diag8101.t_1` are callable using argument types `!()()` -fail_compilation/diag8101.d(45): Candidates are: `t_1(T1)()` -fail_compilation/diag8101.d(46): `t_1(T1, T2)()` -fail_compilation/diag8101.d(63): Error: none of the overloads of template `diag8101.t_2` are callable using argument types `!()()` -fail_compilation/diag8101.d(48): Candidates are: `t_2(T1)()` -fail_compilation/diag8101.d(49): `t_2(T1, T2)()` -fail_compilation/diag8101.d(50): `t_2(T1, T2, T3)()` -fail_compilation/diag8101.d(51): `t_2(T1, T2, T3, T4)()` -fail_compilation/diag8101.d(52): `t_2(T1, T2, T3, T4, T5)()` +fail_compilation/diag8101.d(61): Error: function `diag8101.f_0(int)` is not callable using argument types `()` +fail_compilation/diag8101.d(61): too few arguments, expected 1, got 0 +fail_compilation/diag8101.d(62): Error: none of the overloads of `f_1` are callable using argument types `()` +fail_compilation/diag8101.d(35): Candidates are: `diag8101.f_1(int)` +fail_compilation/diag8101.d(36): `diag8101.f_1(int, int)` +fail_compilation/diag8101.d(63): Error: none of the overloads of `f_2` are callable using argument types `()` +fail_compilation/diag8101.d(38): Candidates are: `diag8101.f_2(int)` +fail_compilation/diag8101.d(39): `diag8101.f_2(int, int)` +fail_compilation/diag8101.d(40): `diag8101.f_2(int, int, int)` +fail_compilation/diag8101.d(41): `diag8101.f_2(int, int, int, int)` +fail_compilation/diag8101.d(42): `diag8101.f_2(int, int, int, int, int)` +fail_compilation/diag8101.d(43): `diag8101.f_2(int, int, int, int, int, int)` fail_compilation/diag8101.d(63): ... (1 more, -v to show) ... +fail_compilation/diag8101.d(65): Error: none of the overloads of template `diag8101.t_0` are callable using argument types `!()()` +fail_compilation/diag8101.d(46): Candidate is: `t_0(T1)()` +fail_compilation/diag8101.d(66): Error: none of the overloads of template `diag8101.t_1` are callable using argument types `!()()` +fail_compilation/diag8101.d(48): Candidates are: `t_1(T1)()` +fail_compilation/diag8101.d(49): `t_1(T1, T2)()` +fail_compilation/diag8101.d(67): Error: none of the overloads of template `diag8101.t_2` are callable using argument types `!()()` +fail_compilation/diag8101.d(51): Candidates are: `t_2(T1)()` +fail_compilation/diag8101.d(52): `t_2(T1, T2)()` +fail_compilation/diag8101.d(53): `t_2(T1, T2, T3)()` +fail_compilation/diag8101.d(54): `t_2(T1, T2, T3, T4)()` +fail_compilation/diag8101.d(55): `t_2(T1, T2, T3, T4, T5)()` +fail_compilation/diag8101.d(56): `t_2(T1, T2, T3, T4, T5, T6)()` +fail_compilation/diag8101.d(67): ... (1 more, -v to show) ... --- */ @@ -39,6 +41,7 @@ void f_2(int, int, int); void f_2(int, int, int, int); void f_2(int, int, int, int, int); void f_2(int, int, int, int, int, int); +void f_2(int, int, int, int, int, int, int); void t_0(T1)(); @@ -51,6 +54,7 @@ void t_2(T1, T2, T3)(); void t_2(T1, T2, T3, T4)(); void t_2(T1, T2, T3, T4, T5)(); void t_2(T1, T2, T3, T4, T5, T6)(); +void t_2(T1, T2, T3, T4, T5, T6, T7)(); void main() { diff --git a/tests/dmd/fail_compilation/fail15616a.d b/tests/dmd/fail_compilation/fail15616a.d index e047365fbe3..042eee12299 100644 --- a/tests/dmd/fail_compilation/fail15616a.d +++ b/tests/dmd/fail_compilation/fail15616a.d @@ -7,10 +7,11 @@ fail_compilation/fail15616a.d(17): `fail15616a.foo(int a, fail_compilation/fail15616a.d(26): `fail15616a.foo(int a, int b, int c)` fail_compilation/fail15616a.d(29): `fail15616a.foo(string a)` fail_compilation/fail15616a.d(32): `fail15616a.foo(string a, string b)` -fail_compilation/fail15616a.d(41): ... (3 more, -v to show) ... +fail_compilation\fail15616a.d(35): `fail15616a.foo(string a, string b, string c)` +fail_compilation/fail15616a.d(41): ... (2 more, -v to show) ... --- */ - +#line 14 void foo(int a) {} diff --git a/tests/dmd/fail_compilation/fail15616c.d b/tests/dmd/fail_compilation/fail15616c.d new file mode 100644 index 00000000000..092590eff1a --- /dev/null +++ b/tests/dmd/fail_compilation/fail15616c.d @@ -0,0 +1,52 @@ +/* +REQUIRED_ARGS: -verror-supplements=0 +TEST_OUTPUT: +--- +fail_compilation/fail15616c.d(44): Error: none of the overloads of `foo` are callable using argument types `(double)` +fail_compilation/fail15616c.d(17): Candidates are: `fail15616c.foo(int a)` +fail_compilation/fail15616c.d(20): `fail15616c.foo(int a, int b)` +fail_compilation/fail15616c.d(29): `fail15616c.foo(int a, int b, int c)` +fail_compilation/fail15616c.d(32): `fail15616c.foo(string a)` +fail_compilation/fail15616c.d(35): `fail15616c.foo(string a, string b)` +fail_compilation/fail15616c.d(38): `fail15616c.foo(string a, string b, string c)` +fail_compilation/fail15616c.d(23): `foo(T)(T a)` + with `T = double` + must satisfy the following constraint: +` is(T == float)` +fail_compilation/fail15616c.d(26): `foo(T)(T a)` + with `T = double` + must satisfy the following constraint: +` is(T == char)` +--- +*/ + +#line 17 +void foo(int a) +{} + +void foo(int a, int b) +{} + +void foo(T)(T a) if (is(T == float)) +{} + +void foo(T)(T a) if (is(T == char)) +{} + +void foo(int a, int b, int c) +{} + +void foo(string a) +{} + +void foo(string a, string b) +{} + +void foo(string a, string b, string c) +{} + + +void main() +{ + foo(3.14); +} diff --git a/tests/dmd/fail_compilation/fail15616d.d b/tests/dmd/fail_compilation/fail15616d.d new file mode 100644 index 00000000000..a0f85a1df9c --- /dev/null +++ b/tests/dmd/fail_compilation/fail15616d.d @@ -0,0 +1,41 @@ +/* +REQUIRED_ARGS: -verror-supplements=2 +TEST_OUTPUT: +--- +fail_compilation/fail15616d.d(44): Error: none of the overloads of `foo` are callable using argument types `(double)` +fail_compilation/fail15616d.d(17): Candidates are: `fail15616d.foo(int a)` +fail_compilation/fail15616d.d(20): `fail15616d.foo(int a, int b)` +fail_compilation/fail15616d.d(44): ... (6 more, -v to show) ... +--- +*/ + +#line 17 +void foo(int a) +{} + +void foo(int a, int b) +{} + +void foo(T)(T a) if (is(T == float)) +{} + +void foo(T)(T a) if (is(T == char)) +{} + +void foo(int a, int b, int c) +{} + +void foo(string a) +{} + +void foo(string a, string b) +{} + +void foo(string a, string b, string c) +{} + + +void main() +{ + foo(3.14); +} From 75e6e39f095330d9883635ed6810ce5a7eaa59f9 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 25 Jan 2023 00:31:46 -0800 Subject: [PATCH 045/177] rename VarDeclaration.aliassym to aliasTuple (dlang/dmd!14845) --- dmd/declaration.d | 12 +++++------- dmd/declaration.h | 2 +- dmd/dsymbolsem.d | 8 +++----- dmd/dtoh.d | 2 +- dmd/frontend.h | 2 +- dmd/semantic2.d | 4 ++-- 6 files changed, 13 insertions(+), 17 deletions(-) diff --git a/dmd/declaration.d b/dmd/declaration.d index d13236b68db..7f6b13eea3b 100644 --- a/dmd/declaration.d +++ b/dmd/declaration.d @@ -1111,7 +1111,7 @@ extern (C++) class VarDeclaration : Declaration { Initializer _init; FuncDeclarations nestedrefs; // referenced by these lexically nested functions - Dsymbol aliassym; // if redone as alias to another symbol + TupleDeclaration aliasTuple; // when `this` is really a tuple of declarations VarDeclaration lastVar; // Linked list of variables for goto-skips-init detection Expression edtor; // if !=null, does the destruction of the variable IntRange* range; // if !=null, the variable is known to be within the range @@ -1200,12 +1200,10 @@ extern (C++) class VarDeclaration : Declaration { //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars()); - if (aliassym) + if (aliasTuple) { // If this variable was really a tuple, set the offsets for the tuple fields - TupleDeclaration v2 = aliassym.isTupleDeclaration(); - assert(v2); - v2.foreachVar((s) { s.setFieldOffset(ad, fieldState, isunion); }); + aliasTuple.foreachVar((s) { s.setFieldOffset(ad, fieldState, isunion); }); return; } @@ -1698,8 +1696,8 @@ extern (C++) class VarDeclaration : Declaration if ((!type || !type.deco) && _scope) dsymbolSemantic(this, _scope); - assert(this != aliassym); - Dsymbol s = aliassym ? aliassym.toAlias() : this; + assert(this != aliasTuple); + Dsymbol s = aliasTuple ? aliasTuple.toAlias() : this; return s; } diff --git a/dmd/declaration.h b/dmd/declaration.h index c4385d31639..29c8a118d50 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -229,7 +229,7 @@ class VarDeclaration : public Declaration public: Initializer *_init; FuncDeclarations nestedrefs; // referenced by these lexically nested functions - Dsymbol *aliassym; // if redone as alias to another symbol + TupleDeclaration *aliasTuple; // if `this` is really a tuple of declarations VarDeclaration *lastVar; // Linked list of variables for goto-skips-init detection Expression *edtor; // if !=NULL, does the destruction of the variable IntRange *range; // if !NULL, the variable is known to be within the range diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 5a1434d6984..bc4016e8245 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -694,7 +694,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor auto v2 = new TupleDeclaration(dsym.loc, dsym.ident, exps); v2.parent = dsym.parent; v2.isexp = true; - dsym.aliassym = v2; + dsym.aliasTuple = v2; dsym.semanticRun = PASS.semanticdone; return; } @@ -7027,12 +7027,10 @@ bool determineFields(AggregateDeclaration ad) if (ad.sizeok != Sizeok.none) return 1; - if (v.aliassym) + if (v.aliasTuple) { // If this variable was really a tuple, process each element. - if (auto tup = v.aliassym.isTupleDeclaration()) - return tup.foreachVar(tv => tv.apply(&func, ad)); - return 0; + return v.aliasTuple.foreachVar(tv => tv.apply(&func, ad)); } if (v.storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared | STC.manifest | STC.ctfe | STC.templateparameter)) diff --git a/dmd/dtoh.d b/dmd/dtoh.d index 30ca3d1f8c6..dfb24d536c1 100644 --- a/dmd/dtoh.d +++ b/dmd/dtoh.d @@ -875,7 +875,7 @@ public: // (we'll visit them later) if (vd.type && vd.type.isTypeTuple()) { - assert(vd.aliassym); + assert(vd.aliasTuple); vd.toAlias().accept(this); return; } diff --git a/dmd/frontend.h b/dmd/frontend.h index 207a5ea263c..4f4894cd2e5 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -5912,7 +5912,7 @@ class VarDeclaration : public Declaration public: Initializer* _init; Array nestedrefs; - Dsymbol* aliassym; + TupleDeclaration* aliasTuple; VarDeclaration* lastVar; Expression* edtor; IntRange* range; diff --git a/dmd/semantic2.d b/dmd/semantic2.d index 50af3f6fb5d..251134cdab2 100644 --- a/dmd/semantic2.d +++ b/dmd/semantic2.d @@ -248,9 +248,9 @@ private extern(C++) final class Semantic2Visitor : Visitor sc.varDecl = vd; scope(exit) sc.varDecl = null; - if (vd.aliassym) // if it's a tuple + if (vd.aliasTuple) // if it's a tuple { - vd.aliassym.accept(this); + vd.aliasTuple.accept(this); vd.semanticRun = PASS.semantic2done; return; } From ab320cfd5749a1a04de335a4b04a48f635665811 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Wed, 25 Jan 2023 23:37:32 +0800 Subject: [PATCH 046/177] Propagate SCOPE.compiles for nested functions in traits(compiles) blocks (dlang/dmd!14846) --- dmd/expression.d | 6 +++--- dmd/func.d | 22 +++++++++++++++++++++- dmd/semantic3.d | 1 - 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/dmd/expression.d b/dmd/expression.d index 025976bf6ba..8c4d2710cfa 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -1441,7 +1441,7 @@ extern (C++) abstract class Expression : ASTNode */ private static bool checkImpure(Scope* sc) { - return sc.func && (sc.flags & SCOPE.compile + return sc.func && (isRootTraitsCompilesScope(sc) ? sc.func.isPureBypassingInference() >= PURE.weak : sc.func.setImpure()); } @@ -1483,7 +1483,7 @@ extern (C++) abstract class Expression : ASTNode if (!f.isSafe() && !f.isTrusted()) { - if (sc.flags & SCOPE.compile ? sc.func.isSafeBypassingInference() : sc.func.setUnsafeCall(f)) + if (isRootTraitsCompilesScope(sc) ? sc.func.isSafeBypassingInference() : sc.func.setUnsafeCall(f)) { if (!loc.isValid()) // e.g. implicitly generated dtor loc = sc.func.loc; @@ -1536,7 +1536,7 @@ extern (C++) abstract class Expression : ASTNode if (!f.isNogc()) { - if (sc.flags & SCOPE.compile ? sc.func.isNogcBypassingInference() : sc.func.setGC()) + if (isRootTraitsCompilesScope(sc) ? sc.func.isNogcBypassingInference() : sc.func.setGC()) { if (loc.linnum == 0) // e.g. implicitly generated dtor loc = sc.func.loc; diff --git a/dmd/func.d b/dmd/func.d index 4e663da1639..df6cc490093 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -4354,6 +4354,26 @@ extern (C++) final class NewDeclaration : FuncDeclaration } } +/************************************** + * When a traits(compiles) is used on a function literal call + * we need to take into account if the body of the function + * violates any attributes, however, we must not affect the + * attribute inference on the outer function. The attributes + * of the function literal still need to be inferred, therefore + * we need a way to check for the scope that the traits compiles + * introduces. + * + * Params: + * sc = scope to be checked for + * + * Returns: `true` if the provided scope is the root + * of the traits compiles list of scopes. + */ +bool isRootTraitsCompilesScope(Scope* sc) +{ + return (sc.flags & SCOPE.compile) && !(sc.func.flags & SCOPE.compile); +} + /************************************** * A statement / expression in this scope is not `@safe`, * so mark the enclosing function as `@system` @@ -4396,7 +4416,7 @@ bool setUnsafe(Scope* sc, } - if (sc.flags & SCOPE.compile) // __traits(compiles, x) + if (isRootTraitsCompilesScope(sc)) // __traits(compiles, x) { if (sc.func.isSafeBypassingInference()) { diff --git a/dmd/semantic3.d b/dmd/semantic3.d index 78da4a15a42..2785cd6d41a 100644 --- a/dmd/semantic3.d +++ b/dmd/semantic3.d @@ -342,7 +342,6 @@ private extern(C++) final class Semantic3Visitor : Visitor sc2.aligndecl = null; if (funcdecl.ident != Id.require && funcdecl.ident != Id.ensure) sc2.flags = sc.flags & ~SCOPE.contract; - sc2.flags &= ~SCOPE.compile; sc2.tf = null; sc2.os = null; sc2.inLoop = false; From f634e2a6542a8b563d9ba1b680afd5337b4c09ea Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Thu, 26 Jan 2023 01:21:40 -0800 Subject: [PATCH 047/177] core.int128 alignment is adjusted (dlang/dmd!14768) --- runtime/druntime/src/core/int128.d | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/runtime/druntime/src/core/int128.d b/runtime/druntime/src/core/int128.d index 46eb9b27556..20fa7dea170 100644 --- a/runtime/druntime/src/core/int128.d +++ b/runtime/druntime/src/core/int128.d @@ -18,8 +18,23 @@ alias I = long; alias U = ulong; enum Ubits = uint(U.sizeof * 8); -version (X86_64) private enum Cent_alignment = 16; -else private enum Cent_alignment = (size_t.sizeof * 2); +version (DigitalMars) +{ + /* The alignment should follow target.stackAlign(), + * which is `isXmmSupported() ? 16 : (is64bit ? 8 : 4) + */ + version (D_SIMD) + private enum Cent_alignment = 16; + else version (X86_64) + private enum Cent_alignment = 8; + else + private enum Cent_alignment = 4; +} +else +{ + version (X86_64) private enum Cent_alignment = 16; + else private enum Cent_alignment = (size_t.sizeof * 2); +} align(Cent_alignment) struct Cent { From e38b47e4dccc4556fe584a7179337aa6d15f70db Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Thu, 26 Jan 2023 01:28:50 -0800 Subject: [PATCH 048/177] fix Issue 23598 - Circular reference bug with static if and eponymous templates (dlang/dmd!14838) --- dmd/attrib.d | 7 ++- dmd/attrib.h | 3 +- dmd/dsymbol.d | 1 + dmd/dsymbol.h | 2 + dmd/dsymbolsem.d | 13 ++-- dmd/dtemplate.d | 40 +++++++++++- dmd/frontend.h | 5 +- tests/dmd/compilable/test23598.d | 87 +++++++++++++++++++++++++++ tests/dmd/fail_compilation/ice12727.d | 2 +- tests/dmd/fail_compilation/ice13816.d | 6 +- 10 files changed, 154 insertions(+), 12 deletions(-) create mode 100644 tests/dmd/compilable/test23598.d diff --git a/dmd/attrib.d b/dmd/attrib.d index 712099ed333..c7bd3430115 100644 --- a/dmd/attrib.d +++ b/dmd/attrib.d @@ -207,7 +207,7 @@ extern (C++) abstract class AttribDeclaration : Dsymbol objc.addSymbols(this, classes, categories); } - override final inout(AttribDeclaration) isAttribDeclaration() inout pure @safe + override inout(AttribDeclaration) isAttribDeclaration() inout pure @safe { return this; } @@ -1080,6 +1080,11 @@ extern (C++) final class StaticIfDeclaration : ConditionalDeclaration return "static if"; } + override inout(StaticIfDeclaration) isStaticIfDeclaration() inout pure @safe + { + return this; + } + override void accept(Visitor v) { v.visit(this); diff --git a/dmd/attrib.h b/dmd/attrib.h index 96c46e8f718..dd8da6f4702 100644 --- a/dmd/attrib.h +++ b/dmd/attrib.h @@ -37,7 +37,7 @@ class AttribDeclaration : public Dsymbol bool hasStaticCtorOrDtor() override final; void checkCtorConstInit() override final; void addLocalClass(ClassDeclarations *) override final; - AttribDeclaration *isAttribDeclaration() override final { return this; } + AttribDeclaration *isAttribDeclaration() override { return this; } void accept(Visitor *v) override { v->visit(this); } }; @@ -184,6 +184,7 @@ class StaticIfDeclaration final : public ConditionalDeclaration void addMember(Scope *sc, ScopeDsymbol *sds) override; void setScope(Scope *sc) override; void importAll(Scope *sc) override; + StaticIfDeclaration *isStaticIfDeclaration() override { return this; } const char *kind() const override; void accept(Visitor *v) override { v->visit(this); } }; diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index a17c830b6ec..a9ca5b71d86 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -1413,6 +1413,7 @@ extern (C++) class Dsymbol : ASTNode inout(OverloadSet) isOverloadSet() inout { return null; } inout(CompileDeclaration) isCompileDeclaration() inout { return null; } inout(StaticAssert) isStaticAssert() inout { return null; } + inout(StaticIfDeclaration) isStaticIfDeclaration() inout { return null; } } /*********************************************************** diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index 88110e1f5d2..ca9634eaad0 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -72,6 +72,7 @@ class ExpressionDsymbol; class AliasAssign; class OverloadSet; class StaticAssert; +class StaticIfDeclaration; struct AA; #ifdef IN_GCC typedef union tree_node Symbol; @@ -323,6 +324,7 @@ class Dsymbol : public ASTNode virtual OverloadSet *isOverloadSet() { return NULL; } virtual CompileDeclaration *isCompileDeclaration() { return NULL; } virtual StaticAssert *isStaticAssert() { return NULL; } + virtual StaticIfDeclaration *isStaticIfDeclaration() { return NULL; } void accept(Visitor *v) override { v->visit(this); } }; diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index bc4016e8245..cc0c5fe9f82 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -4539,7 +4539,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor override void visit(StructDeclaration sd) { - //printf("StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok); + enum log = false; + if (log) printf("+StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok); //static int count; if (++count == 20) assert(0); @@ -4609,6 +4610,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (!sd.members) // if opaque declaration { + if (log) printf("\topaque declaration %s\n", sd.toChars()); sd.semanticRun = PASS.semanticdone; return; } @@ -4660,7 +4662,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor sc2.pop(); - //printf("\tdeferring %s\n", toChars()); + if (log) printf("\tdeferring %s\n", sd.toChars()); return deferDsymbolSemantic(sd, scx); } @@ -4690,7 +4692,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor sd.inv = buildInv(sd, sc2); sd.semanticRun = PASS.semanticdone; - //printf("-StructDeclaration::semantic(this=%p, '%s')\n", sd, sd.toChars()); + if (log) printf("-StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok); sc2.pop(); @@ -4757,6 +4759,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor // Make an error in 2.110 if (sd.storage_class & STC.scope_) deprecation(sd.loc, "`scope` as a type constraint is deprecated. Use `scope` at the usage site."); + //printf("-StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok); } void interfaceSemantic(ClassDeclaration cd) @@ -6147,7 +6150,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, Expressions* Dsymbol s; if (Dsymbol.oneMembers(tempinst.members, &s, tempdecl.ident) && s) { - //printf("tempdecl.ident = %s, s = '%s'\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars()); + //printf("tempdecl.ident = %s, s = `%s %s`\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars()); //printf("setting aliasdecl\n"); tempinst.aliasdecl = s; } @@ -6194,7 +6197,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, Expressions* { if (!tempinst.aliasdecl || tempinst.aliasdecl != s) { - //printf("tempdecl.ident = %s, s = '%s'\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars()); + //printf("tempdecl.ident = %s, s = `%s %s`\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars()); //printf("setting aliasdecl 2\n"); tempinst.aliasdecl = s; } diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 17e128b6376..e6cabd54578 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -45,6 +45,7 @@ import dmd.aliasthis; import dmd.arraytypes; import dmd.astenums; import dmd.ast_node; +import dmd.attrib; import dmd.dcast; import dmd.dclass; import dmd.declaration; @@ -1226,7 +1227,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol paramscope.pop(); static if (LOGM) { - printf("-TemplateDeclaration.matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m); + printf("-TemplateDeclaration.matchWithInstance(this = %s, ti = %s) = %d\n", toChars(), ti.toChars(), m); } return m; } @@ -7520,6 +7521,43 @@ extern (C++) class TemplateInstance : ScopeDsymbol members.foreachDsymbol( (s) { s.importAll(sc2); } ); + if (!aliasdecl) + { + /* static if's are crucial to evaluating aliasdecl correctly. But + * evaluating the if/else bodies may require aliasdecl. + * So, evaluate the condition for static if's, but not their if/else bodies. + * Then try to set aliasdecl. + * Later do the if/else bodies. + * https://issues.dlang.org/show_bug.cgi?id=23598 + * It might be better to do this by attaching a lambda to the StaticIfDeclaration + * to do the oneMembers call after the sid.include(sc2) is run as part of dsymbolSemantic(). + */ + bool done; + void staticIfDg(Dsymbol s) + { + if (done || aliasdecl) + return; + //printf("\t staticIfDg on '%s %s' in '%s'\n", s.kind(), s.toChars(), this.toChars()); + if (!s.isStaticIfDeclaration()) + { + //s.dsymbolSemantic(sc2); + done = true; + return; + } + auto sid = s.isStaticIfDeclaration(); + sid.include(sc2); + if (members.length) + { + Dsymbol sa; + if (Dsymbol.oneMembers(members, &sa, tempdecl.ident) && sa) + aliasdecl = sa; + } + done = true; + } + + members.foreachDsymbol(&staticIfDg); + } + void symbolDg(Dsymbol s) { //printf("\t semantic on '%s' %p kind %s in '%s'\n", s.toChars(), s, s.kind(), this.toChars()); diff --git a/dmd/frontend.h b/dmd/frontend.h index 4f4894cd2e5..2a3339c513d 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -102,6 +102,7 @@ class VisibilityDeclaration; class OverloadSet; class CompileDeclaration; class StaticAssert; +class StaticIfDeclaration; class DsymbolTable; struct MangleOverride; class AliasThis; @@ -571,6 +572,7 @@ class Dsymbol : public ASTNode virtual OverloadSet* isOverloadSet(); virtual CompileDeclaration* isCompileDeclaration(); virtual StaticAssert* isStaticAssert(); + virtual StaticIfDeclaration* isStaticIfDeclaration(); }; typedef uint64_t size_t; @@ -5387,7 +5389,7 @@ class AttribDeclaration : public Dsymbol void checkCtorConstInit() final override; void addLocalClass(Array* aclasses) final override; void addObjcSymbols(Array* classes, Array* categories) final override; - AttribDeclaration* isAttribDeclaration() final override; + AttribDeclaration* isAttribDeclaration() override; void accept(Visitor* v) override; }; @@ -5524,6 +5526,7 @@ class StaticIfDeclaration final : public ConditionalDeclaration void setScope(Scope* sc) override; void importAll(Scope* sc) override; const char* kind() const override; + StaticIfDeclaration* isStaticIfDeclaration() override; void accept(Visitor* v) override; }; diff --git a/tests/dmd/compilable/test23598.d b/tests/dmd/compilable/test23598.d new file mode 100644 index 00000000000..cdcb5a801d4 --- /dev/null +++ b/tests/dmd/compilable/test23598.d @@ -0,0 +1,87 @@ +// https://issues.dlang.org/show_bug.cgi?id=23598 + +alias AliasSeq(a...) = a; + +static if (1) +{ + +template sort(alias f, a...) +{ + static if (a.length > 0) + { + alias x = f!(a[0]); + alias sort = a; + } + else + alias sort = a; +} + +alias SortedItems = sort!(isDependencyOf, String); + +enum isDependencyOf(Item) = Item.DirectDependencies.length == 0; + +struct String +{ + alias DirectDependencies = AliasSeq!(); + + enum l = SortedItems.length; // (3) +} + +} + +/*****************************************************/ + +static if (1) +{ +enum x = 1; +enum y = 2; + +template f(T) +{ + alias b = int; + static if (x) + { + alias c = x; + } + else + { + alias c = y; + } + + static if (is(typeof(c))) + { + } + else + { + static assert(0); + } +} + +void g() +{ + int x = f!int.c; +} +} + +/*****************************************************/ + +template forward(args...) +{ + template fwd(alias arg) + { + alias fwd = arg; + } + + alias Result = AliasSeq!(); + static foreach (arg; args) + Result = AliasSeq!(Result, fwd!arg); + static if (Result.length == 1) + alias forward = Result[0]; + else + alias forward = Result; +} + +void func(int i, int j) +{ + func(forward!(i, j)); +} diff --git a/tests/dmd/fail_compilation/ice12727.d b/tests/dmd/fail_compilation/ice12727.d index bf6af7b404f..13eb8e09ed8 100644 --- a/tests/dmd/fail_compilation/ice12727.d +++ b/tests/dmd/fail_compilation/ice12727.d @@ -1,13 +1,13 @@ /* TEST_OUTPUT: ---- +fail_compilation/ice12727.d(16): Error: template instance `IndexTuple!(1, 0)` recursive template expansion fail_compilation/ice12727.d(16): Error: alias `ice12727.IndexTuple!(1, 0).IndexTuple` recursive alias declaration fail_compilation/ice12727.d(23): Error: template instance `ice12727.IndexTuple!(1, 0)` error instantiating fail_compilation/ice12727.d(27): instantiated from here: `Matrix!(float, 3)` fail_compilation/ice12727.d(28): instantiated from here: `Vector!(float, 3)` ---- */ - template IndexTuple(int e, int s = 0, T...) { static if (s == e) diff --git a/tests/dmd/fail_compilation/ice13816.d b/tests/dmd/fail_compilation/ice13816.d index e683e339e61..aefe273da0c 100644 --- a/tests/dmd/fail_compilation/ice13816.d +++ b/tests/dmd/fail_compilation/ice13816.d @@ -1,11 +1,13 @@ /* TEST_OUTPUT: --- -fail_compilation/ice13816.d(15): Error: alias `ice13816.ItemProperty!().ItemProperty` recursive alias declaration -fail_compilation/ice13816.d(20): Error: template instance `ice13816.ItemProperty!()` error instantiating +fail_compilation/ice13816.d(17): Error: template instance `TypeTuple!(ItemProperty!())` recursive template expansion +fail_compilation/ice13816.d(17): Error: alias `ice13816.ItemProperty!().ItemProperty` recursive alias declaration +fail_compilation/ice13816.d(22): Error: template instance `ice13816.ItemProperty!()` error instantiating --- */ + alias TypeTuple(T...) = T; template ItemProperty() From d8fcab3077166c4925abe40bcb0c75d0f92c704f Mon Sep 17 00:00:00 2001 From: Dennis Date: Thu, 26 Jan 2023 10:30:47 +0100 Subject: [PATCH 049/177] Add test for calling a function type (dlang/dmd!14848) --- .../dmd/fail_compilation/call_function_type.d | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/dmd/fail_compilation/call_function_type.d diff --git a/tests/dmd/fail_compilation/call_function_type.d b/tests/dmd/fail_compilation/call_function_type.d new file mode 100644 index 00000000000..e60df95d76c --- /dev/null +++ b/tests/dmd/fail_compilation/call_function_type.d @@ -0,0 +1,20 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/call_function_type.d(18): Error: expected 1 function arguments, not 0 +fail_compilation/call_function_type.d(19): Error: cannot call `int(int)(3)` at compile time +--- +*/ + +// This is a rare case where `dmd.expressionsem.functionParameters` catches a missing argument error, +// which is usually caught earlier by `TypeFunction.callMatch`, and had no test coverage yet. +// This was found while implementing named arguments and reduced from `vibe.internal.meta.traits`. + +int f(int); + +void m() +{ + alias FT = typeof(f); + enum X0 = FT(); + enum X1 = FT(3); +} From d0126575b4ad51dddae25275542fa1f21e3d4116 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 3 Dec 2022 17:35:00 -0800 Subject: [PATCH 050/177] fix Issue 19575 - core.cpuid not usable without a runtime --- runtime/druntime/src/core/cpuid.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime/src/core/cpuid.d b/runtime/druntime/src/core/cpuid.d index 1c2ac067704..b79bd1df9c4 100644 --- a/runtime/druntime/src/core/cpuid.d +++ b/runtime/druntime/src/core/cpuid.d @@ -1080,7 +1080,7 @@ void cpuidSparc() } */ -shared static this() +pragma(crt_constructor) void cpuid_initialization() { auto cf = getCpuFeatures(); From 805e6eca375368f1b09b3d4f4c6be3ea4100b717 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Thu, 26 Jan 2023 18:25:34 +0800 Subject: [PATCH 051/177] Fix Issue 23650 - Using typeid with struct defined in __traits(compiles, ...) causes linker error (dlang/dmd!14844) --- dmd/expressionsem.d | 12 +++++++++++- dmd/frontend.h | 4 ++-- dmd/typinf.d | 10 ++++++---- tests/dmd/runnable/test23650.d | 13 +++++++++++++ 4 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 tests/dmd/runnable/test23650.d diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 675ef10f43d..c2afa297a3b 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -5519,8 +5519,18 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { // Handle this in the glue layer e = new TypeidExp(exp.loc, ta); - e.type = getTypeInfoType(exp.loc, ta, sc); + bool genObjCode = true; + + // https://issues.dlang.org/show_bug.cgi?id=23650 + // We generate object code for typeinfo, required + // by typeid, only if in non-speculative context + if (sc.flags & SCOPE.compile) + { + genObjCode = false; + } + + e.type = getTypeInfoType(exp.loc, ta, sc, genObjCode); semanticTypeInfo(sc, ta); if (ea) diff --git a/dmd/frontend.h b/dmd/frontend.h index 2a3339c513d..7fc1fd8a9e8 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -8159,9 +8159,9 @@ extern Target target; extern bool tpsemantic(TemplateParameter* tp, Scope* sc, Array* parameters); -extern void genTypeInfo(Expression* e, const Loc& loc, Type* torig, Scope* sc); +extern void genTypeInfo(Expression* e, const Loc& loc, Type* torig, Scope* sc, bool genObjCode = true); -extern Type* getTypeInfoType(const Loc& loc, Type* t, Scope* sc); +extern Type* getTypeInfoType(const Loc& loc, Type* t, Scope* sc, bool genObjCode = true); extern bool builtinTypeInfo(Type* t); diff --git a/dmd/typinf.d b/dmd/typinf.d index cbac0fd6e4e..54561c5708d 100644 --- a/dmd/typinf.d +++ b/dmd/typinf.d @@ -34,8 +34,9 @@ import core.stdc.stdio; * loc = the location for reporting line numbers in errors * torig = the type to generate the `TypeInfo` object for * sc = the scope + * genObjCode = if true, object code will be generated for the obtained TypeInfo */ -extern (C++) void genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope* sc) +extern (C++) void genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope* sc, bool genObjCode = true) { // printf("genTypeInfo() %s\n", torig.toChars()); @@ -80,7 +81,7 @@ extern (C++) void genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope // generate a COMDAT for other TypeInfos not available as builtins in // druntime - if (!isUnqualifiedClassInfo && !builtinTypeInfo(t)) + if (!isUnqualifiedClassInfo && !builtinTypeInfo(t) && genObjCode) { if (sc) // if in semantic() pass { @@ -105,13 +106,14 @@ extern (C++) void genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope * loc = the location for reporting line nunbers in errors * t = the type to get the type of the `TypeInfo` object for * sc = the scope + * genObjCode = if true, object code will be generated for the obtained TypeInfo * Returns: * The type of the `TypeInfo` object associated with `t` */ -extern (C++) Type getTypeInfoType(const ref Loc loc, Type t, Scope* sc) +extern (C++) Type getTypeInfoType(const ref Loc loc, Type t, Scope* sc, bool genObjCode = true) { assert(t.ty != Terror); - genTypeInfo(null, loc, t, sc); + genTypeInfo(null, loc, t, sc, genObjCode); return t.vtinfo.type; } diff --git a/tests/dmd/runnable/test23650.d b/tests/dmd/runnable/test23650.d new file mode 100644 index 00000000000..3ce8f5f0759 --- /dev/null +++ b/tests/dmd/runnable/test23650.d @@ -0,0 +1,13 @@ +// https://issues.dlang.org/show_bug.cgi?id=23650 + +__gshared int x; + +void main() +{ + + static assert(__traits(compiles, + { + struct S { int *p = &x; } + auto t = typeid(S); + })); +} From a00e99ec94c5bbf367b6124fd831d1e5e50ce2ef Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Wed, 25 Jan 2023 17:48:05 +0200 Subject: [PATCH 052/177] Remove FUNCFLAG.compileTimeOnly --- dmd/declaration.d | 3 +-- dmd/declaration.h | 2 -- dmd/dsymbolsem.d | 2 +- dmd/frontend.h | 2 -- dmd/func.d | 2 -- 5 files changed, 2 insertions(+), 9 deletions(-) diff --git a/dmd/declaration.d b/dmd/declaration.d index 7f6b13eea3b..fac8ba10209 100644 --- a/dmd/declaration.d +++ b/dmd/declaration.d @@ -1658,8 +1658,7 @@ extern (C++) class VarDeclaration : Declaration // Add this VarDeclaration to fdv.closureVars[] if not already there if (!sc.intypeof && !(sc.flags & SCOPE.compile) && // https://issues.dlang.org/show_bug.cgi?id=17605 - (fdv.isCompileTimeOnly || !fdthis.isCompileTimeOnly) - ) + (fdv.skipCodegen || !fdthis.skipCodegen)) { if (!fdv.closureVars.contains(this)) fdv.closureVars.push(this); diff --git a/dmd/declaration.h b/dmd/declaration.h index 29c8a118d50..233e2848530 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -636,8 +636,6 @@ class FuncDeclaration : public Declaration bool inferScope(bool v); bool hasCatches() const; bool hasCatches(bool v); - bool isCompileTimeOnly() const; - bool isCompileTimeOnly(bool v); bool skipCodegen() const; bool skipCodegen(bool v); bool printf() const; diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index cc0c5fe9f82..8c82a7796ca 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -3059,7 +3059,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor //printf("function storage_class = x%llx, sc.stc = x%llx, %x\n", storage_class, sc.stc, Declaration.isFinal()); if (sc.flags & SCOPE.compile) - funcdecl.isCompileTimeOnly = true; // don't emit code for this function + funcdecl.skipCodegen = true; funcdecl._linkage = sc.linkage; if (auto fld = funcdecl.isFuncLiteralDeclaration()) diff --git a/dmd/frontend.h b/dmd/frontend.h index 7fc1fd8a9e8..5cc035758b8 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -2496,8 +2496,6 @@ class FuncDeclaration : public Declaration bool inferScope(bool v); bool hasCatches() const; bool hasCatches(bool v); - bool isCompileTimeOnly() const; - bool isCompileTimeOnly(bool v); bool skipCodegen() const; bool skipCodegen(bool v); bool printf() const; diff --git a/dmd/func.d b/dmd/func.d index df6cc490093..5e2ee758087 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -202,9 +202,7 @@ private struct FUNCFLAG bool inlineScanned; /// function has been scanned for inline possibilities bool inferScope; /// infer 'scope' for parameters bool hasCatches; /// function has try-catch statements - bool isCompileTimeOnly; /// is a compile time only function; no code will be generated for it bool skipCodegen; /// do not generate code for this function. - // FIXME: redundant with `isCompileTimeOnly`, see https://github.com/dlang/dmd/pull/14791#discussion_r1065066099 bool printf; /// is a printf-like function bool scanf; /// is a scanf-like function bool noreturn; /// the function does not return From 48a5fa2a6672f84b182ecf68b663fc65f8118236 Mon Sep 17 00:00:00 2001 From: Teodor Dutu Date: Fri, 27 Jan 2023 10:02:10 +0200 Subject: [PATCH 053/177] Translate `_d_newclass` to a template (dlang/dmd!14837) This makes the following changes: - Add template `_d_newclassT` to `druntime.src.core.lifetime.d` - Replace lowering of `new C()` to `_d_newclassT!C()` - Add `lowering` member to `NewExp`. This field stores the above lowering to be used by e2ir.d - Keep the old `_d_newclass` hook because it's used by `TypeInfo_Class.create()` - Add dummy `_d_newclassT` hook to tests that redefine the `object` module - Remove `new MinHeap!(TestType)()` from `fail308.d`. Otherwise the errror was changed and printed the local path to druntime - Move `err` to global scope in rt.sections.d to avoid the frontend lowering - Account for the `GC.malloc()` called by the template hook in the `-profile=gc` tests Signed-off-by: Teodor Dutu Signed-off-by: Teodor Dutu --- dmd/expression.d | 5 +- dmd/expression.h | 2 + dmd/expressionsem.d | 26 +++++ dmd/frontend.h | 3 + dmd/id.d | 2 + runtime/druntime/src/core/lifetime.d | 105 ++++++++++++++++++ runtime/druntime/src/object.d | 2 + runtime/druntime/src/rt/tracegc.d | 1 - .../profile/myprofilegc.log.freebsd.32.exp | 3 +- .../profile/myprofilegc.log.freebsd.64.exp | 3 +- .../test/profile/myprofilegc.log.linux.32.exp | 3 +- .../test/profile/myprofilegc.log.linux.64.exp | 3 +- .../test/profile/myprofilegc.log.osx.32.exp | 3 +- .../test/profile/myprofilegc.log.osx.64.exp | 3 +- tests/dmd/compilable/test23431_minimal.d | 7 ++ tests/dmd/compilable/test23433.d | 7 ++ tests/dmd/fail_compilation/fail308.d | 2 +- tests/dmd/fail_compilation/ice23569.d | 8 +- 18 files changed, 178 insertions(+), 10 deletions(-) diff --git a/dmd/expression.d b/dmd/expression.d index 8c4d2710cfa..c72995e6d93 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -1544,7 +1544,8 @@ extern (C++) abstract class Expression : ASTNode // Lowered non-@nogc'd hooks will print their own error message inside of nogc.d (NOGCVisitor.visit(CallExp e)), // so don't print anything to avoid double error messages. if (!(f.ident == Id._d_HookTraceImpl || f.ident == Id._d_arraysetlengthT - || f.ident == Id._d_arrayappendT || f.ident == Id._d_arrayappendcTX)) + || f.ident == Id._d_arrayappendT || f.ident == Id._d_arrayappendcTX + || f.ident == Id._d_newclassT)) error("`@nogc` %s `%s` cannot call non-@nogc %s `%s`", sc.func.kind(), sc.func.toPrettyChars(), f.kind(), f.toPrettyChars()); @@ -3650,6 +3651,8 @@ extern (C++) final class NewExp : Expression bool onstack; // allocate on stack bool thrownew; // this NewExp is the expression of a ThrowStatement + Expression lowering; // lowered druntime hook: `_d_newclass` + extern (D) this(const ref Loc loc, Expression thisexp, Type newtype, Expressions* arguments) { super(loc, EXP.new_, __traits(classInstanceSize, NewExp)); diff --git a/dmd/expression.h b/dmd/expression.h index f491c1d9c27..bfd595c28b2 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -539,6 +539,8 @@ class NewExp final : public Expression bool onstack; // allocate on stack bool thrownew; // this NewExp is the expression of a ThrowStatement + Expression lowering; // lowered druntime hook: `_d_newclass` + static NewExp *create(const Loc &loc, Expression *thisexp, Type *newtype, Expressions *arguments); NewExp *syntaxCopy() override; diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index c2afa297a3b..6dfdbd4bb4d 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -3781,6 +3781,32 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor result = id.expressionSemantic(sc); return; } + else if (!exp.onstack && !exp.type.isscope()) + { + auto hook = global.params.tracegc ? Id._d_newclassTTrace : Id._d_newclassT; + if (!verifyHookExist(exp.loc, *sc, hook, "new class")) + return setError(); + + Expression id = new IdentifierExp(exp.loc, Id.empty); + id = new DotIdExp(exp.loc, id, Id.object); + + auto tiargs = new Objects(); + auto t = exp.newtype.unqualify(MODFlags.wild); // remove `inout` + tiargs.push(t); + id = new DotTemplateInstanceExp(exp.loc, id, hook, tiargs); + auto arguments = new Expressions(); + if (global.params.tracegc) + { + auto funcname = (sc.callsc && sc.callsc.func) ? + sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars(); + arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString())); + arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32)); + arguments.push(new StringExp(exp.loc, funcname.toDString())); + } + id = new CallExp(exp.loc, id, arguments); + + exp.lowering = id.expressionSemantic(sc); + } } else if (auto ts = tb.isTypeStruct()) { diff --git a/dmd/frontend.h b/dmd/frontend.h index 5cc035758b8..ae44e58a51a 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -7187,6 +7187,7 @@ class NewExp final : public Expression CtorDeclaration* member; bool onstack; bool thrownew; + Expression* lowering; static NewExp* create(const Loc& loc, Expression* thisexp, Type* newtype, Array* arguments); NewExp* syntaxCopy() override; void accept(Visitor* v) override; @@ -8577,6 +8578,8 @@ struct Id final static Identifier* criticalexit; static Identifier* _d_delThrowable; static Identifier* _d_newThrowable; + static Identifier* _d_newclassT; + static Identifier* _d_newclassTTrace; static Identifier* _d_assert_fail; static Identifier* dup; static Identifier* _aaApply; diff --git a/dmd/id.d b/dmd/id.d index 73fde18ed11..ec5cb25ef28 100644 --- a/dmd/id.d +++ b/dmd/id.d @@ -313,6 +313,8 @@ immutable Msgtable[] msgtable = { "__ArrayDtor" }, { "_d_delThrowable" }, { "_d_newThrowable" }, + { "_d_newclassT" }, + { "_d_newclassTTrace" }, { "_d_assert_fail" }, { "dup" }, { "_aaApply" }, diff --git a/runtime/druntime/src/core/lifetime.d b/runtime/druntime/src/core/lifetime.d index 371308def79..848d4b3e2b0 100644 --- a/runtime/druntime/src/core/lifetime.d +++ b/runtime/druntime/src/core/lifetime.d @@ -2709,3 +2709,108 @@ T _d_newThrowable(T)() @trusted assert(exc.refcount() == 1); assert(e.refcount() == 1); } + +/** + * Create a new class instance. + * Allocates memory and sets fields to their initial value, but does not call a + * constructor. + * --- + * new C() // _d_newclass!(C)() + * --- + * Returns: newly created object + */ +T _d_newclassT(T)() @trusted +if (is(T == class)) +{ + import core.internal.traits : hasIndirections; + import core.exception : onOutOfMemoryError; + import core.memory : GC, pureMalloc; + + alias BlkAttr = GC.BlkAttr; + + auto init = __traits(initSymbol, T); + void* p; + + static if (__traits(getLinkage, T) == "Windows") + { + p = pureMalloc(init.length); + if (!p) + onOutOfMemoryError(); + } + else + { + BlkAttr attr = BlkAttr.NONE; + + /* `extern(C++)`` classes don't have a classinfo pointer in their vtable, + * so the GC can't finalize them. + */ + static if (__traits(hasMember, T, "__dtor") && __traits(getLinkage, T) != "C++") + attr |= BlkAttr.FINALIZE; + static if (!hasIndirections!T) + attr |= BlkAttr.NO_SCAN; + + p = GC.malloc(init.length, attr, typeid(T)); + debug(PRINTF) printf(" p = %p\n", p); + } + + debug(PRINTF) + { + printf("p = %p\n", p); + printf("init.ptr = %p, len = %llu\n", init.ptr, cast(ulong)init.length); + printf("vptr = %p\n", *cast(void**) init); + printf("vtbl[0] = %p\n", (*cast(void***) init)[0]); + printf("vtbl[1] = %p\n", (*cast(void***) init)[1]); + printf("init[0] = %x\n", (cast(uint*) init)[0]); + printf("init[1] = %x\n", (cast(uint*) init)[1]); + printf("init[2] = %x\n", (cast(uint*) init)[2]); + printf("init[3] = %x\n", (cast(uint*) init)[3]); + printf("init[4] = %x\n", (cast(uint*) init)[4]); + } + + // initialize it + p[0 .. init.length] = init[]; + + debug(PRINTF) printf("initialization done\n"); + return cast(T) p; +} + +// Test allocation +@safe unittest +{ + class C { } + C c = _d_newclassT!C(); + + assert(c !is null); +} + +// Test initializers +@safe unittest +{ + { + class C { int x, y; } + C c = _d_newclassT!C(); + + assert(c.x == 0); + assert(c.y == 0); + } + { + class C { int x = 2, y = 3; } + C c = _d_newclassT!C(); + + assert(c.x == 2); + assert(c.y == 3); + } +} + +T _d_newclassTTrace(T)(string file, int line, string funcname) @trusted +{ + version (D_TypeInfo) + { + import core.internal.array.utils: TraceHook, gcStatsPure, accumulatePure; + mixin(TraceHook!(T.stringof, "_d_newclassT")); + + return _d_newclassT!T(); + } + else + assert(0, "Cannot create new class if compiling without support for runtime type information!"); +} diff --git a/runtime/druntime/src/object.d b/runtime/druntime/src/object.d index d98e698aa63..56e01ace2cb 100644 --- a/runtime/druntime/src/object.d +++ b/runtime/druntime/src/object.d @@ -4648,6 +4648,8 @@ public import core.internal.switch_: __switch_error; public import core.lifetime : _d_delstructImpl; public import core.lifetime : _d_newThrowable; +public import core.lifetime : _d_newclassT; +public import core.lifetime : _d_newclassTTrace; public @trusted @nogc nothrow pure extern (C) void _d_delThrowable(scope Throwable); diff --git a/runtime/druntime/src/rt/tracegc.d b/runtime/druntime/src/rt/tracegc.d index 2575a50dab9..29b61468056 100644 --- a/runtime/druntime/src/rt/tracegc.d +++ b/runtime/druntime/src/rt/tracegc.d @@ -17,7 +17,6 @@ module rt.tracegc; // version = tracegc; -extern (C) Object _d_newclass(const ClassInfo ci); extern (C) void[] _d_newarrayT(const TypeInfo ti, size_t length); extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length); extern (C) void[] _d_newarrayiT(const TypeInfo ti, size_t length); diff --git a/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp b/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp index 7e1a05881c6..bcf256b499c 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp @@ -6,6 +6,7 @@ bytes allocated, allocations, type, function, file:line 48 1 float[] D main src/profilegc.d:42 48 1 int[] D main src/profilegc.d:41 32 1 void[] profilegc.main src/profilegc.d:55 + 16 1 C D main src/profilegc.d:12 16 1 char[] D main src/profilegc.d:34 16 1 char[] D main src/profilegc.d:36 16 1 closure profilegc.main.foo src/profilegc.d:45 @@ -15,5 +16,5 @@ bytes allocated, allocations, type, function, file:line 16 1 int[] D main src/profilegc.d:14 16 1 int[] D main src/profilegc.d:22 16 1 int[] D main src/profilegc.d:37 - 16 1 profilegc.main.C D main src/profilegc.d:12 + 16 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2752 16 1 wchar[] D main src/profilegc.d:35 diff --git a/runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp b/runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp index a3e18492074..6a779303247 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp @@ -5,7 +5,8 @@ bytes allocated, allocations, type, function, file:line 64 1 double[] profilegc.main src/profilegc.d:56 48 1 float[] D main src/profilegc.d:42 48 1 int[] D main src/profilegc.d:41 - 32 1 profilegc.main.C D main src/profilegc.d:12 + 32 1 C D main src/profilegc.d:12 + 32 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2752 32 1 void[] profilegc.main src/profilegc.d:55 16 1 char[] D main src/profilegc.d:34 16 1 char[] D main src/profilegc.d:36 diff --git a/runtime/druntime/test/profile/myprofilegc.log.linux.32.exp b/runtime/druntime/test/profile/myprofilegc.log.linux.32.exp index 7e1a05881c6..bcf256b499c 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.linux.32.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.linux.32.exp @@ -6,6 +6,7 @@ bytes allocated, allocations, type, function, file:line 48 1 float[] D main src/profilegc.d:42 48 1 int[] D main src/profilegc.d:41 32 1 void[] profilegc.main src/profilegc.d:55 + 16 1 C D main src/profilegc.d:12 16 1 char[] D main src/profilegc.d:34 16 1 char[] D main src/profilegc.d:36 16 1 closure profilegc.main.foo src/profilegc.d:45 @@ -15,5 +16,5 @@ bytes allocated, allocations, type, function, file:line 16 1 int[] D main src/profilegc.d:14 16 1 int[] D main src/profilegc.d:22 16 1 int[] D main src/profilegc.d:37 - 16 1 profilegc.main.C D main src/profilegc.d:12 + 16 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2752 16 1 wchar[] D main src/profilegc.d:35 diff --git a/runtime/druntime/test/profile/myprofilegc.log.linux.64.exp b/runtime/druntime/test/profile/myprofilegc.log.linux.64.exp index a3e18492074..6a779303247 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.linux.64.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.linux.64.exp @@ -5,7 +5,8 @@ bytes allocated, allocations, type, function, file:line 64 1 double[] profilegc.main src/profilegc.d:56 48 1 float[] D main src/profilegc.d:42 48 1 int[] D main src/profilegc.d:41 - 32 1 profilegc.main.C D main src/profilegc.d:12 + 32 1 C D main src/profilegc.d:12 + 32 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2752 32 1 void[] profilegc.main src/profilegc.d:55 16 1 char[] D main src/profilegc.d:34 16 1 char[] D main src/profilegc.d:36 diff --git a/runtime/druntime/test/profile/myprofilegc.log.osx.32.exp b/runtime/druntime/test/profile/myprofilegc.log.osx.32.exp index a099944c288..b33b547aee1 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.osx.32.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.osx.32.exp @@ -6,6 +6,7 @@ bytes allocated, allocations, type, function, file:line 64 1 int[] D main src/profilegc.d:41 64 1 double[] profilegc.main src/profilegc.d:56 32 1 void[] profilegc.main src/profilegc.d:55 + 16 1 C D main src/profilegc.d:12 16 1 char[] D main src/profilegc.d:34 16 1 char[] D main src/profilegc.d:36 16 1 closure profilegc.main.foo src/profilegc.d:45 @@ -15,5 +16,5 @@ bytes allocated, allocations, type, function, file:line 16 1 int[] D main src/profilegc.d:14 16 1 int[] D main src/profilegc.d:22 16 1 int[] D main src/profilegc.d:37 - 16 1 profilegc.main.C D main src/profilegc.d:12 + 16 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2752 16 1 wchar[] D main src/profilegc.d:35 diff --git a/runtime/druntime/test/profile/myprofilegc.log.osx.64.exp b/runtime/druntime/test/profile/myprofilegc.log.osx.64.exp index a3e18492074..6a779303247 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.osx.64.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.osx.64.exp @@ -5,7 +5,8 @@ bytes allocated, allocations, type, function, file:line 64 1 double[] profilegc.main src/profilegc.d:56 48 1 float[] D main src/profilegc.d:42 48 1 int[] D main src/profilegc.d:41 - 32 1 profilegc.main.C D main src/profilegc.d:12 + 32 1 C D main src/profilegc.d:12 + 32 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2752 32 1 void[] profilegc.main src/profilegc.d:55 16 1 char[] D main src/profilegc.d:34 16 1 char[] D main src/profilegc.d:36 diff --git a/tests/dmd/compilable/test23431_minimal.d b/tests/dmd/compilable/test23431_minimal.d index 0293f127286..c3ae19a21eb 100644 --- a/tests/dmd/compilable/test23431_minimal.d +++ b/tests/dmd/compilable/test23431_minimal.d @@ -13,6 +13,13 @@ class Exception : Throwable class Error { } +// Needed to lower `new Exception("ice")` to it. +T _d_newclassT(T)() +if (is(T == class)) +{ + return null; +} + void test23431() { int a; diff --git a/tests/dmd/compilable/test23433.d b/tests/dmd/compilable/test23433.d index 713267c0ecb..dfffa456c8a 100644 --- a/tests/dmd/compilable/test23433.d +++ b/tests/dmd/compilable/test23433.d @@ -4,6 +4,13 @@ module object; class Throwable { } class Exception : Throwable { this(immutable(char)[]) { } } +// Needed to lower `new Exception("ice")` to it. +T _d_newclassT(T)() +if (is(T == class)) +{ + return null; +} + void test23433() { try diff --git a/tests/dmd/fail_compilation/fail308.d b/tests/dmd/fail_compilation/fail308.d index d885b3ef3ee..603fe51db7b 100644 --- a/tests/dmd/fail_compilation/fail308.d +++ b/tests/dmd/fail_compilation/fail308.d @@ -16,6 +16,6 @@ class MinHeap(NodeType) unittest { struct TestType {} - MinHeap!(TestType) foo = new MinHeap!(TestType)(); + MinHeap!(TestType) foo; } } diff --git a/tests/dmd/fail_compilation/ice23569.d b/tests/dmd/fail_compilation/ice23569.d index 277814f76cf..6fdb71a3976 100644 --- a/tests/dmd/fail_compilation/ice23569.d +++ b/tests/dmd/fail_compilation/ice23569.d @@ -2,11 +2,17 @@ /* TEST_OUTPUT: --- -fail_compilation/ice23569.d(18): Error: cannot compare classes for equality because `object.Object` was not declared +fail_compilation/ice23569.d(24): Error: cannot compare classes for equality because `object.Object` was not declared --- */ module object; +T _d_newclassT(T)() +if (is(T == class)) +{ + return null; +} + @safe unittest1() { class F From d55c5a59d167c027a6def6a75d605b4d842add7e Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sat, 28 Jan 2023 15:06:53 +0000 Subject: [PATCH 054/177] Tweak @live undisposed owner error A pointer 'left dangling' means it refers to an invalid memory address - change to 'not disposed of'. This also is consistent with the 'assigning to Owner without disposing of owned value' error message. --- dmd/ob.d | 2 +- tests/dmd/fail_compilation/failob1.d | 10 +++++----- tests/dmd/fail_compilation/failob2.d | 2 +- tests/dmd/fail_compilation/fob1.d | 4 ++-- tests/dmd/fail_compilation/fob2.d | 8 ++++---- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/dmd/ob.d b/dmd/ob.d index 31e93a7637f..de5bccfd04e 100644 --- a/dmd/ob.d +++ b/dmd/ob.d @@ -2569,7 +2569,7 @@ void checkObErrors(ref ObState obstate) { auto v = obstate.vars[i]; if (v.type.hasPointers()) - v.error(v.loc, "is left dangling at return"); + v.error(v.loc, "is not disposed of before return"); } } } diff --git a/tests/dmd/fail_compilation/failob1.d b/tests/dmd/fail_compilation/failob1.d index 7fe73d3d179..377125d569b 100644 --- a/tests/dmd/fail_compilation/failob1.d +++ b/tests/dmd/fail_compilation/failob1.d @@ -2,11 +2,11 @@ REQUIRED_ARGS:-preview=dip1021 TEST_OUTPUT: --- -fail_compilation/failob1.d(104): Error: variable `failob1.test1.a1` is left dangling at return -fail_compilation/failob1.d(105): Error: variable `failob1.test2.a2` is left dangling at return -fail_compilation/failob1.d(107): Error: variable `failob1.test4.s4` is left dangling at return -fail_compilation/failob1.d(108): Error: variable `failob1.test5.dg5` is left dangling at return -fail_compilation/failob1.d(115): Error: variable `failob1.test12.p12` is left dangling at return +fail_compilation/failob1.d(104): Error: variable `failob1.test1.a1` is not disposed of before return +fail_compilation/failob1.d(105): Error: variable `failob1.test2.a2` is not disposed of before return +fail_compilation/failob1.d(107): Error: variable `failob1.test4.s4` is not disposed of before return +fail_compilation/failob1.d(108): Error: variable `failob1.test5.dg5` is not disposed of before return +fail_compilation/failob1.d(115): Error: variable `failob1.test12.p12` is not disposed of before return --- */ diff --git a/tests/dmd/fail_compilation/failob2.d b/tests/dmd/fail_compilation/failob2.d index bd526485409..c8a4c4d93d4 100644 --- a/tests/dmd/fail_compilation/failob2.d +++ b/tests/dmd/fail_compilation/failob2.d @@ -48,7 +48,7 @@ void test1() { /* TEST_OUTPUT: --- -fail_compilation/failob2.d(205): Error: variable `failob2.foo4!int.foo4.p` is left dangling at return +fail_compilation/failob2.d(205): Error: variable `failob2.foo4!int.foo4.p` is not disposed of before return fail_compilation/failob2.d(209): Error: template instance `failob2.foo4!int` error instantiating --- */ diff --git a/tests/dmd/fail_compilation/fob1.d b/tests/dmd/fail_compilation/fob1.d index 9dfcc4da7df..83a6cd2dcb4 100644 --- a/tests/dmd/fail_compilation/fob1.d +++ b/tests/dmd/fail_compilation/fob1.d @@ -18,7 +18,7 @@ fail_compilation/fob1.d(104): Error: variable `fob1.foo1.p` is returned but is U /* TEST_OUTPUT: --- fail_compilation/fob1.d(204): Error: variable `fob1.foo2.p` assigning to Owner without disposing of owned value -fail_compilation/fob1.d(203): Error: variable `fob1.foo2.p` is left dangling at return +fail_compilation/fob1.d(203): Error: variable `fob1.foo2.p` is not disposed of before return --- */ @@ -35,7 +35,7 @@ fail_compilation/fob1.d(203): Error: variable `fob1.foo2.p` is left dangling at --- fail_compilation/fob1.d(304): Error: variable `fob1.foo3.p` has undefined state and cannot be read fail_compilation/fob1.d(304): Error: variable `fob1.foo3.p` is returned but is Undefined -fail_compilation/fob1.d(303): Error: variable `fob1.foo3.q` is left dangling at return +fail_compilation/fob1.d(303): Error: variable `fob1.foo3.q` is not disposed of before return --- */ diff --git a/tests/dmd/fail_compilation/fob2.d b/tests/dmd/fail_compilation/fob2.d index 6f100ee5124..1fbb0408f84 100644 --- a/tests/dmd/fail_compilation/fob2.d +++ b/tests/dmd/fail_compilation/fob2.d @@ -8,7 +8,7 @@ void free(int*); /* TEST_OUTPUT: --- fail_compilation/fob2.d(110): Error: variable `fob2.foo1.b1` has undefined state and cannot be read -fail_compilation/fob2.d(103): Error: variable `fob2.foo1.p` is left dangling at return +fail_compilation/fob2.d(103): Error: variable `fob2.foo1.p` is not disposed of before return --- */ @@ -29,7 +29,7 @@ fail_compilation/fob2.d(103): Error: variable `fob2.foo1.p` is left dangling at /* TEST_OUTPUT: --- fail_compilation/fob2.d(203): Error: variable `fob2.zoo2.p` is passed as Owner more than once -fail_compilation/fob2.d(202): Error: variable `fob2.zoo2.p` is left dangling at return +fail_compilation/fob2.d(202): Error: variable `fob2.zoo2.p` is not disposed of before return --- */ @@ -44,7 +44,7 @@ fail_compilation/fob2.d(202): Error: variable `fob2.zoo2.p` is left dangling at /* TEST_OUTPUT: --- -fail_compilation/fob2.d(303): Error: variable `fob2.foo3.b` is left dangling at return +fail_compilation/fob2.d(303): Error: variable `fob2.foo3.b` is not disposed of before return --- */ @@ -140,7 +140,7 @@ fail_compilation/fob2.d(515): Error: variable `fob2.test52.p` has undefined stat /* TEST_OUTPUT: --- -fail_compilation/fob2.d(603): Error: variable `fob2.test6.p` is left dangling at return +fail_compilation/fob2.d(603): Error: variable `fob2.test6.p` is not disposed of before return --- */ From 5eb575f3f59fcae6389f91bfb20e1ef76239291d Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 15 Jan 2023 22:54:56 +0100 Subject: [PATCH 055/177] runnable_cxx: Remove new_allocator test from cppa.d --- tests/dmd/runnable_cxx/cppa.d | 52 ----------------------------------- 1 file changed, 52 deletions(-) diff --git a/tests/dmd/runnable_cxx/cppa.d b/tests/dmd/runnable_cxx/cppa.d index cd91dd55834..29d7713ff68 100644 --- a/tests/dmd/runnable_cxx/cppa.d +++ b/tests/dmd/runnable_cxx/cppa.d @@ -444,57 +444,10 @@ void test13161() /****************************************/ -version (linux) -{ - static if (__traits(getTargetInfo, "cppStd") < 201703) - { - // See note on std::allocator below. - extern(C++, __gnu_cxx) - { - struct new_allocator(T) - { - alias size_type = size_t; - static if (is(T : char)) - void deallocate(T*, size_type) { } - else - void deallocate(T*, size_type); - } - } - } -} - extern (C++, std) { - version (linux) - { - static if (__traits(getTargetInfo, "cppStd") >= 201703) - { - // std::allocator no longer derives from __gnu_cxx::new_allocator, - // it derives from std::__new_allocator instead. - struct __new_allocator(T) - { - alias size_type = size_t; - static if (is(T : char)) - void deallocate(T*, size_type) { } - else - void deallocate(T*, size_type); - } - } - } - extern (C++, class) struct allocator(T) { - version (linux) - { - alias size_type = size_t; - void deallocate(T* p, size_type sz) - { - static if (__traits(getTargetInfo, "cppStd") >= 201703) - (cast(std.__new_allocator!T*)&this).deallocate(p, sz); - else - (cast(__gnu_cxx.new_allocator!T*)&this).deallocate(p, sz); - } - } } class vector(T, A = allocator!T) @@ -586,11 +539,6 @@ void test14() version (linux) { - void test14a(std.allocator!int * pa) - { - pa.deallocate(null, 0); - } - void gun(std.vector!int pa) { int x = 42; From 7978943c79d54466bdd63e6bd1f5639da0aa1dfb Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 15 Jan 2023 23:21:24 +0100 Subject: [PATCH 056/177] importc: Remove __has_builtin redefine --- runtime/druntime/src/importc.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/runtime/druntime/src/importc.h b/runtime/druntime/src/importc.h index 60dc618a5ce..7bb6c01332f 100644 --- a/runtime/druntime/src/importc.h +++ b/runtime/druntime/src/importc.h @@ -77,9 +77,6 @@ #undef __has_extension #define __has_extension(x) 0 -#undef __has_builtin -#define __has_builtin(x) 0 - /************************************* * OS-specific macros */ From 041d20792d3c13a8f5035586da3f53f6e82d149d Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 29 Jan 2023 22:49:35 +0100 Subject: [PATCH 057/177] ci: Version out C++ test that doesn't work with DMD --- tests/dmd/runnable_cxx/cppa.d | 144 +++++++++++++++++++--------------- 1 file changed, 79 insertions(+), 65 deletions(-) diff --git a/tests/dmd/runnable_cxx/cppa.d b/tests/dmd/runnable_cxx/cppa.d index 29d7713ff68..398158ed366 100644 --- a/tests/dmd/runnable_cxx/cppa.d +++ b/tests/dmd/runnable_cxx/cppa.d @@ -5,8 +5,6 @@ // CXXFLAGS(linux freebsd osx netbsd dragonflybsd): -std=c++11 // druntime isn't linked, this prevents missing symbols '_d_arraybounds_slicep': // REQUIRED_ARGS: -checkaction=C -// Filter a spurious warning on Semaphore: -// TRANSFORM_OUTPUT: remove_lines("warning: relocation refers to discarded section") // N.B MSVC doesn't have a C++11 switch, but it defaults to the latest fully-supported standard @@ -1063,83 +1061,99 @@ void test15576() /****************************************/ // https://issues.dlang.org/show_bug.cgi?id=15579 -extern (C++) +version (DigitalMars) { - class Base - { - //~this() {} - void based() { } - ubyte x = 4; - } - - interface Interface + version (linux) { - int MethodCPP(); - int MethodD(); + // Test removed for DMD/linux-only. + // https://issues.dlang.org/show_bug.cgi?id=23660 } + else + version = TEST15579; +} +else + version = TEST15579; - class Derived : Base, Interface +version (TEST15579) +{ + extern (C++) { - short y = 5; - int MethodCPP(); - int MethodD() { - printf("Derived.MethodD(): this = %p, x = %d, y = %d\n", this, x, y); - Derived p = this; - //p = cast(Derived)(cast(void*)p - 16); - assert(p.x == 4 || p.x == 7); - assert(p.y == 5 || p.y == 8); - return 3; + class Base + { + //~this() {} + void based() { } + ubyte x = 4; } - int Method() { return 6; } - } - Derived cppfoo(Derived); - Interface cppfooi(Interface); -} - -void test15579() -{ - Derived d = new Derived(); - printf("d = %p\n", d); - assert(d.x == 4); - assert(d.y == 5); - assert((cast(Interface)d).MethodCPP() == 30); - assert((cast(Interface)d).MethodD() == 3); - assert(d.MethodCPP() == 30); - assert(d.MethodD() == 3); - assert(d.Method() == 6); + interface Interface + { + int MethodCPP(); + int MethodD(); + } - d = cppfoo(d); - assert(d.x == 7); - assert(d.y == 8); + class Derived : Base, Interface + { + short y = 5; + int MethodCPP(); + int MethodD() { + printf("Derived.MethodD(): this = %p, x = %d, y = %d\n", this, x, y); + Derived p = this; + //p = cast(Derived)(cast(void*)p - 16); + assert(p.x == 4 || p.x == 7); + assert(p.y == 5 || p.y == 8); + return 3; + } + int Method() { return 6; } + } - printf("d2 = %p\n", d); + Derived cppfoo(Derived); + Interface cppfooi(Interface); + } - /* Casting to an interface involves thunks in the vtbl[]. - * g++ puts the thunks for MethodD in the same COMDAT as MethodD. - * But D doesn't, so when the linker "picks one" of the D generated MethodD - * or the g++ generated MethodD, it may wind up with a messed up thunk, - * resulting in a seg fault. The solution is to not expect objects of the same - * type to be constructed on both sides of the D/C++ divide if the same member - * function (in this case, MethodD) is also defined on both sides. - */ - version (Windows) + void test15579() { + Derived d = new Derived(); + printf("d = %p\n", d); + assert(d.x == 4); + assert(d.y == 5); + assert((cast(Interface)d).MethodCPP() == 30); assert((cast(Interface)d).MethodD() == 3); - } - assert((cast(Interface)d).MethodCPP() == 30); + assert(d.MethodCPP() == 30); + assert(d.MethodD() == 3); + assert(d.Method() == 6); + + d = cppfoo(d); + assert(d.x == 7); + assert(d.y == 8); + + printf("d2 = %p\n", d); + + /* Casting to an interface involves thunks in the vtbl[]. + * g++ puts the thunks for MethodD in the same COMDAT as MethodD. + * But D doesn't, so when the linker "picks one" of the D generated MethodD + * or the g++ generated MethodD, it may wind up with a messed up thunk, + * resulting in a seg fault. The solution is to not expect objects of the same + * type to be constructed on both sides of the D/C++ divide if the same member + * function (in this case, MethodD) is also defined on both sides. + */ + version (Windows) + { + assert((cast(Interface)d).MethodD() == 3); + } + assert((cast(Interface)d).MethodCPP() == 30); - assert(d.Method() == 6); + assert(d.Method() == 6); - printf("d = %p, i = %p\n", d, cast(Interface)d); - version (Windows) - { - Interface i = cppfooi(d); - printf("i2: %p\n", i); - assert(i.MethodD() == 3); - assert(i.MethodCPP() == 30); + printf("d = %p, i = %p\n", d, cast(Interface)d); + version (Windows) + { + Interface i = cppfooi(d); + printf("i2: %p\n", i); + assert(i.MethodD() == 3); + assert(i.MethodCPP() == 30); + } + printf("test15579() done\n"); } - printf("test15579() done\n"); } /****************************************/ @@ -1647,7 +1661,7 @@ void main() testeh2(); testeh3(); test15576(); - test15579(); + version (TEST15579) test15579(); test15610(); test15455(); test15372(); From ba993c875971c944b35f6af8a7a7eef569196981 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Mon, 30 Jan 2023 00:15:07 +0100 Subject: [PATCH 058/177] druntime: Match either _Dmain or D main --- runtime/druntime/test/exceptions/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime/test/exceptions/Makefile b/runtime/druntime/test/exceptions/Makefile index 6be18e4353a..9e74c38e75e 100644 --- a/runtime/druntime/test/exceptions/Makefile +++ b/runtime/druntime/test/exceptions/Makefile @@ -110,7 +110,7 @@ $(ROOT)/rt_trap_exceptions_drt_gdb.done: $(ROOT)/rt_trap_exceptions_drt $(QUIET)$(TIMELIMIT) $(GDB) -n -ex 'set confirm off' -ex run -ex 'bt full' -ex q --args $< --DRT-trapExceptions=0 \ > $(ROOT)/rt_trap_exceptions_drt_gdb.output 2>&1 || true cat $(ROOT)/rt_trap_exceptions_drt_gdb.output - grep "D main (args=...) at .*rt_trap_exceptions_drt.d:9" > /dev/null < $(ROOT)/rt_trap_exceptions_drt_gdb.output + grep "\(D main\|_Dmain\) (args=...) at .*rt_trap_exceptions_drt.d:9" > /dev/null < $(ROOT)/rt_trap_exceptions_drt_gdb.output grep 'myLocal' > /dev/null < $(ROOT)/rt_trap_exceptions_drt_gdb.output ! grep "No stack." > /dev/null < $(ROOT)/rt_trap_exceptions_drt_gdb.output @touch $@ From 92164209de6f0fb9ad498c4e15cf7c7c96002f21 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 31 Jan 2023 03:45:30 -0800 Subject: [PATCH 059/177] fix Issue 23658 - .di generation of variables should turn them into declarations (dlang/dmd!14851) --- dmd/frontend.h | 5 ++- dmd/hdrgen.d | 43 ++++++++++++++++---- tests/dmd/compilable/extra-files/header1.di | 4 +- tests/dmd/compilable/extra-files/header1i.di | 4 +- tests/dmd/compilable/extra-files/header2.di | 6 +-- tests/dmd/compilable/extra-files/header2i.di | 6 +-- 6 files changed, 50 insertions(+), 18 deletions(-) diff --git a/dmd/frontend.h b/dmd/frontend.h index ae44e58a51a..b8b5259847f 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -2812,6 +2812,7 @@ struct HdrGenState final int32_t autoMember; int32_t forStmtInit; int32_t insideFuncBody; + int32_t insideAggregate; bool declstring; EnumDeclaration* inEnumDecl; HdrGenState() : @@ -2823,11 +2824,12 @@ struct HdrGenState final autoMember(), forStmtInit(), insideFuncBody(), + insideAggregate(), declstring(), inEnumDecl() { } - HdrGenState(bool hdrgen, bool ddoc = false, bool fullDump = false, bool fullQual = false, int32_t tpltMember = 0, int32_t autoMember = 0, int32_t forStmtInit = 0, int32_t insideFuncBody = 0, bool declstring = false, EnumDeclaration* inEnumDecl = nullptr) : + HdrGenState(bool hdrgen, bool ddoc = false, bool fullDump = false, bool fullQual = false, int32_t tpltMember = 0, int32_t autoMember = 0, int32_t forStmtInit = 0, int32_t insideFuncBody = 0, int32_t insideAggregate = 0, bool declstring = false, EnumDeclaration* inEnumDecl = nullptr) : hdrgen(hdrgen), ddoc(ddoc), fullDump(fullDump), @@ -2836,6 +2838,7 @@ struct HdrGenState final autoMember(autoMember), forStmtInit(forStmtInit), insideFuncBody(insideFuncBody), + insideAggregate(insideAggregate), declstring(declstring), inEnumDecl(inEnumDecl) {} diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index 68670d929e5..f3f593a2d31 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -65,6 +65,7 @@ struct HdrGenState int autoMember; int forStmtInit; int insideFuncBody; + int insideAggregate; bool declstring; // set while declaring alias for string,wstring or dstring EnumDeclaration inEnumDecl; @@ -1406,8 +1407,10 @@ public: buf.writeByte('{'); buf.writenl(); buf.level++; + hgs.insideAggregate++; foreach (s; *d.members) s.accept(this); + hgs.insideAggregate--; buf.level--; buf.writeByte('}'); buf.writenl(); @@ -1428,8 +1431,10 @@ public: buf.writeByte('{'); buf.writenl(); buf.level++; + hgs.insideAggregate++; foreach (s; *d.members) s.accept(this); + hgs.insideAggregate--; buf.level--; buf.writeByte('}'); } @@ -1521,6 +1526,21 @@ public: void visitVarDecl(VarDeclaration v, bool anywritten) { + const bool isextern = hgs.hdrgen && + !hgs.insideFuncBody && + !hgs.tpltMember && + !hgs.insideAggregate && + !(v.storage_class & STC.manifest); + + void vinit(VarDeclaration v) + { + auto ie = v._init.isExpInitializer(); + if (ie && (ie.exp.op == EXP.construct || ie.exp.op == EXP.blit)) + (cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, hgs); + else + v._init.initializerToBuffer(buf, hgs); + } + if (anywritten) { buf.writestring(", "); @@ -1528,21 +1548,30 @@ public: } else { - if (stcToBuffer(buf, v.storage_class)) + const bool useTypeof = isextern && v._init && !v.type; + auto stc = v.storage_class; + if (isextern) + stc |= STC.extern_; + if (useTypeof) + stc &= ~STC.auto_; + if (stcToBuffer(buf, stc)) buf.writeByte(' '); if (v.type) typeToBuffer(v.type, v.ident, buf, hgs); + else if (useTypeof) + { + buf.writestring("typeof("); + vinit(v); + buf.writestring(") "); + buf.writestring(v.ident.toString()); + } else buf.writestring(v.ident.toString()); } - if (v._init) + if (v._init && !isextern) { buf.writestring(" = "); - auto ie = v._init.isExpInitializer(); - if (ie && (ie.exp.op == EXP.construct || ie.exp.op == EXP.blit)) - (cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, hgs); - else - v._init.initializerToBuffer(buf, hgs); + vinit(v); } } diff --git a/tests/dmd/compilable/extra-files/header1.di b/tests/dmd/compilable/extra-files/header1.di index fa4eb937715..f99d1bcfaa9 100644 --- a/tests/dmd/compilable/extra-files/header1.di +++ b/tests/dmd/compilable/extra-files/header1.di @@ -223,7 +223,7 @@ class Foo3 } } alias myint = int; -static notquit = 1; +static extern typeof(1) notquit; class Test { void a(); @@ -277,7 +277,7 @@ void templ(T)(T val) { pragma (msg, "Invalid destination type."); } -static char[] charArray = ['"', '\'']; +static extern char[] charArray; class Point { auto x = 10; diff --git a/tests/dmd/compilable/extra-files/header1i.di b/tests/dmd/compilable/extra-files/header1i.di index f1b371304f5..61125ef5c95 100644 --- a/tests/dmd/compilable/extra-files/header1i.di +++ b/tests/dmd/compilable/extra-files/header1i.di @@ -241,7 +241,7 @@ class Foo3 } } alias myint = int; -static notquit = 1; +static extern typeof(1) notquit; class Test { void a() @@ -357,7 +357,7 @@ void templ(T)(T val) { pragma (msg, "Invalid destination type."); } -static char[] charArray = ['"', '\'']; +static extern char[] charArray; class Point { auto x = 10; diff --git a/tests/dmd/compilable/extra-files/header2.di b/tests/dmd/compilable/extra-files/header2.di index b78abdcc2dd..c8b66a51a85 100644 --- a/tests/dmd/compilable/extra-files/header2.di +++ b/tests/dmd/compilable/extra-files/header2.di @@ -76,7 +76,7 @@ template templateVariableBar(T) if (is(T == int)) { enum int templateVariableBar = T.stringof.length; } -auto flit = 3 / 2.0; +extern typeof(3 / 2.0) flit; void foo11217()(const int[] arr) { } @@ -170,10 +170,10 @@ class LeClass ; } } -const levar = new class LeClass, LeInterface +extern const typeof(new class LeClass, LeInterface { } -; +) levar; class CC { @safe void fun()() diff --git a/tests/dmd/compilable/extra-files/header2i.di b/tests/dmd/compilable/extra-files/header2i.di index 3a563958c4f..9c57de106e7 100644 --- a/tests/dmd/compilable/extra-files/header2i.di +++ b/tests/dmd/compilable/extra-files/header2i.di @@ -89,7 +89,7 @@ template templateVariableBar(T) if (is(T == int)) { enum int templateVariableBar = T.stringof.length; } -auto flit = 3 / 2.0; +extern typeof(3 / 2.0) flit; void foo11217()(const int[] arr) { } @@ -272,10 +272,10 @@ class LeClass ; } } -const levar = new class LeClass, LeInterface +extern const typeof(new class LeClass, LeInterface { } -; +) levar; class CC { @safe void fun()() From 67e7de3f132f804ee843502c2c88bf54c118bbf1 Mon Sep 17 00:00:00 2001 From: Ben Jones Date: Thu, 2 Feb 2023 11:11:38 -0700 Subject: [PATCH 060/177] add const scope to IN6* functions taking inet 6 address pointers --- .../druntime/src/core/sys/posix/netinet/in_.d | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/runtime/druntime/src/core/sys/posix/netinet/in_.d b/runtime/druntime/src/core/sys/posix/netinet/in_.d index a58fa850d5d..5818ee6e22b 100644 --- a/runtime/druntime/src/core/sys/posix/netinet/in_.d +++ b/runtime/druntime/src/core/sys/posix/netinet/in_.d @@ -547,7 +547,7 @@ version (CRuntime_Glibc) } // macros - extern (D) int IN6_IS_ADDR_UNSPECIFIED( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* addr ) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -555,7 +555,7 @@ version (CRuntime_Glibc) (cast(uint32_t*) addr)[3] == 0; } - extern (D) int IN6_IS_ADDR_LOOPBACK( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* addr ) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -563,29 +563,29 @@ version (CRuntime_Glibc) (cast(uint32_t*) addr)[3] == htonl( 1 ); } - extern (D) int IN6_IS_ADDR_MULTICAST( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* addr ) pure { return (cast(uint8_t*) addr)[0] == 0xff; } - extern (D) int IN6_IS_ADDR_LINKLOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* addr ) pure { return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfe800000 ); } - extern (D) int IN6_IS_ADDR_SITELOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* addr ) pure { return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfec00000 ); } - extern (D) int IN6_IS_ADDR_V4MAPPED( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* addr ) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && (cast(uint32_t*) addr)[2] == htonl( 0xffff ); } - extern (D) int IN6_IS_ADDR_V4COMPAT( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* addr ) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -593,31 +593,31 @@ version (CRuntime_Glibc) ntohl( (cast(uint32_t*) addr)[3] ) > 1; } - extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x1; } - extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x2; } - extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST(addr) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x5; } - extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST( addr) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x8; } - extern (D) int IN6_IS_ADDR_MC_GLOBAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0xe; @@ -670,7 +670,7 @@ else version (Darwin) } // macros - extern (D) int IN6_IS_ADDR_UNSPECIFIED( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* addr ) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -678,7 +678,7 @@ else version (Darwin) (cast(uint32_t*) addr)[3] == 0; } - extern (D) int IN6_IS_ADDR_LOOPBACK( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* addr ) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -686,29 +686,29 @@ else version (Darwin) (cast(uint32_t*) addr)[3] == ntohl( 1 ); } - extern (D) int IN6_IS_ADDR_MULTICAST( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* addr ) pure { return addr.s6_addr[0] == 0xff; } - extern (D) int IN6_IS_ADDR_LINKLOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* addr ) pure { return addr.s6_addr[0] == 0xfe && (addr.s6_addr[1] & 0xc0) == 0x80; } - extern (D) int IN6_IS_ADDR_SITELOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* addr ) pure { return addr.s6_addr[0] == 0xfe && (addr.s6_addr[1] & 0xc0) == 0xc0; } - extern (D) int IN6_IS_ADDR_V4MAPPED( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* addr ) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && (cast(uint32_t*) addr)[2] == ntohl( 0x0000ffff ); } - extern (D) int IN6_IS_ADDR_V4COMPAT( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* addr ) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -717,31 +717,31 @@ else version (Darwin) (cast(uint32_t*) addr)[3] != ntohl( 1 ); } - extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x1; } - extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x2; } - extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST(addr) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x5; } - extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST( addr) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x8; } - extern (D) int IN6_IS_ADDR_MC_GLOBAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* addr ) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0xe; From 817b12764b27a278e342baa9abca64d79db446d0 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Fri, 3 Feb 2023 17:23:59 +0800 Subject: [PATCH 061/177] Fix Issue 23648 - replace uses of sprintf with snprintf in the compiler (dlang/dmd!14854) --- dmd/dmangle.d | 2 +- dmd/frontend.h | 2 +- dmd/hdrgen.d | 4 ++-- dmd/lexer.d | 8 +++---- dmd/mars.d | 2 +- dmd/mtype.d | 2 +- dmd/parse.d | 5 +++-- dmd/root/ctfloat.d | 6 ++--- dmd/root/ctfloat.h | 2 +- dmd/root/longdouble.d | 27 ++++++++++++----------- dmd/root/longdouble.h | 12 +++++----- dmd/statementsem.d | 2 +- dmd/tokens.d | 23 ++++++++++--------- tests/dmd/runnable/extra-files/paranoia.d | 2 +- 14 files changed, 51 insertions(+), 48 deletions(-) diff --git a/dmd/dmangle.d b/dmd/dmangle.d index 867d3cacb2f..eab9eb1bfd6 100644 --- a/dmd/dmangle.d +++ b/dmd/dmangle.d @@ -1322,7 +1322,7 @@ void realToMangleBuffer(OutBuffer* buf, real_t value) char[36] buffer = void; // 'A' format yields [-]0xh.hhhhp+-d - const n = CTFloat.sprint(buffer.ptr, 'A', value); + const n = CTFloat.sprint(buffer.ptr, buffer.length, 'A', value); assert(n < buffer.length); foreach (const c; buffer[2 .. n]) { diff --git a/dmd/frontend.h b/dmd/frontend.h index b8b5259847f..4584156a885 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -8870,7 +8870,7 @@ struct CTFloat final static bool isSNaN(_d_real r); static bool isInfinity(_d_real r); static _d_real parse(const char* literal, bool& isOutOfRange); - static int32_t sprint(char* str, char fmt, _d_real x); + static int32_t sprint(char* str, size_t size, char fmt, _d_real x); static _d_real zero; static _d_real one; static _d_real minusone; diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index f3f593a2d31..176e0a6262c 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -2712,7 +2712,7 @@ void floatToBuffer(Type type, const real_t value, OutBuffer* buf, const bool all Plus one for rounding. */ const(size_t) BUFFER_LEN = value.sizeof * 3 + 8 + 1 + 1; char[BUFFER_LEN] buffer = void; - CTFloat.sprint(buffer.ptr, 'g', value); + CTFloat.sprint(buffer.ptr, BUFFER_LEN, 'g', value); assert(strlen(buffer.ptr) < BUFFER_LEN); if (allowHex) { @@ -2720,7 +2720,7 @@ void floatToBuffer(Type type, const real_t value, OutBuffer* buf, const bool all real_t r = CTFloat.parse(buffer.ptr, isOutOfRange); //assert(!isOutOfRange); // test/compilable/test22725.c asserts here if (r != value) // if exact duplication - CTFloat.sprint(buffer.ptr, 'a', value); + CTFloat.sprint(buffer.ptr, BUFFER_LEN, 'a', value); } buf.writestring(buffer.ptr); if (buffer.ptr[strlen(buffer.ptr) - 1] == '.') diff --git a/dmd/lexer.d b/dmd/lexer.d index bd53433d6c8..9af36cd0186 100644 --- a/dmd/lexer.d +++ b/dmd/lexer.d @@ -3094,9 +3094,9 @@ private struct TimeStampInfo .time(&ct); const p = ctime(&ct); assert(p); - sprintf(&date[0], "%.6s %.4s", p + 4, p + 20); - sprintf(&time[0], "%.8s", p + 11); - sprintf(×tamp[0], "%.24s", p); + snprintf(&date[0], date.length, "%.6s %.4s", p + 4, p + 20); + snprintf(&time[0], time.length, "%.8s", p + 11); + snprintf(×tamp[0], timestamp.length, "%.24s", p); } } @@ -3283,7 +3283,7 @@ unittest gotError = true; char[100] buffer = void; - auto actual = buffer[0 .. vsprintf(buffer.ptr, format, ap)]; + auto actual = buffer[0 .. vsnprintf(buffer.ptr, buffer.length, format, ap)]; assert(expected == actual); return true; } diff --git a/dmd/mars.d b/dmd/mars.d index 48736b18ced..ca0645bbf08 100644 --- a/dmd/mars.d +++ b/dmd/mars.d @@ -712,7 +712,7 @@ bool parseCommandlineAndConfig(size_t argc, const(char)** argv, ref Param params // read from DFLAGS in [Environment{arch}] section char[80] envsection = void; - sprintf(envsection.ptr, "Environment%.*s", cast(int) arch.length, arch.ptr); + snprintf(envsection.ptr, envsection.length, "Environment%.*s", cast(int) arch.length, arch.ptr); sections.push(envsection.ptr); parseConfFile(environment, global.inifilename, inifilepath, inifileBuffer, §ions); getenv_setargv(readFromEnv(environment, "DFLAGS"), &arguments); diff --git a/dmd/mtype.d b/dmd/mtype.d index efc14cf1a2e..dd1ee61fe9c 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -2447,7 +2447,7 @@ extern (C++) abstract class Type : ASTNode const namelen = 19 + size_t.sizeof * 3 + slice.length + 1; auto name = namelen <= namebuf.length ? namebuf.ptr : cast(char*)Mem.check(malloc(namelen)); - const length = sprintf(name, "_D%lluTypeInfo_%.*s6__initZ", + const length = snprintf(name, namelen, "_D%lluTypeInfo_%.*s6__initZ", cast(ulong)(9 + slice.length), cast(int)slice.length, slice.ptr); //printf("%p %s, deco = %s, name = %s\n", this, toChars(), deco, name); assert(0 < length && length < namelen); // don't overflow the buffer diff --git a/dmd/parse.d b/dmd/parse.d index 4824c2296ff..ddf1e824a75 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -64,8 +64,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer /* Create a pseudo-filename for the mixin string, as it may not even exist * in the source file. */ - char* filename = cast(char*)mem.xmalloc(strlen(loc.filename) + 7 + (loc.linnum).sizeof * 3 + 1); - sprintf(filename, "%s-mixin-%d", loc.filename, cast(int)loc.linnum); + auto len = strlen(loc.filename) + 7 + (loc.linnum).sizeof * 3 + 1; + char* filename = cast(char*)mem.xmalloc(len); + snprintf(filename, len, "%s-mixin-%d", loc.filename, cast(int)loc.linnum); scanloc.filename = filename; } diff --git a/dmd/root/ctfloat.d b/dmd/root/ctfloat.d index 74505f86b1a..df1a20606a4 100644 --- a/dmd/root/ctfloat.d +++ b/dmd/root/ctfloat.d @@ -188,17 +188,17 @@ extern (C++) struct CTFloat } @system - static int sprint(char* str, char fmt, real_t x) + static int sprint(char* str, size_t size, char fmt, real_t x) { version(CRuntime_Microsoft) { - auto len = cast(int) ld_sprint(str, fmt, longdouble_soft(x)); + auto len = cast(int) ld_sprint(str, size, fmt, longdouble_soft(x)); } else { char[4] sfmt = "%Lg\0"; sfmt[2] = fmt; - auto len = sprintf(str, sfmt.ptr, x); + auto len = snprintf(str, size, sfmt.ptr, x); } if (fmt != 'a' && fmt != 'A') diff --git a/dmd/root/ctfloat.h b/dmd/root/ctfloat.h index 44bd959edd9..a23fa506a9f 100644 --- a/dmd/root/ctfloat.h +++ b/dmd/root/ctfloat.h @@ -51,7 +51,7 @@ struct CTFloat static bool isInfinity(real_t r); static real_t parse(const char *literal, bool& isOutOfRange); - static int sprint(char *str, char fmt, real_t x); + static int sprint(char *str, size_t size, char fmt, real_t x); static size_t hash(real_t a); diff --git a/dmd/root/longdouble.d b/dmd/root/longdouble.d index 64ad1c98b6a..f26a1a8d989 100644 --- a/dmd/root/longdouble.d +++ b/dmd/root/longdouble.d @@ -732,19 +732,19 @@ int ld_type(longdouble_soft x) return LD_TYPE_QNAN; // qnan, indefinite, pseudo-nan } -// consider sprintf pure -private extern(C) int sprintf(scope char* s, scope const char* format, ...) pure @nogc nothrow; +// consider snprintf pure +private extern(C) int snprintf(scope char* s, size_t size, scope const char* format, ...) pure @nogc nothrow; -size_t ld_sprint(char* str, int fmt, longdouble_soft x) @system +size_t ld_sprint(char* str, size_t size, int fmt, longdouble_soft x) @system { // ensure dmc compatible strings for nan and inf switch(ld_type(x)) { case LD_TYPE_QNAN: case LD_TYPE_SNAN: - return sprintf(str, "nan"); + return snprintf(str, size, "nan"); case LD_TYPE_INFINITE: - return sprintf(str, x.sign ? "-inf" : "inf"); + return snprintf(str, size, x.sign ? "-inf" : "inf"); default: break; } @@ -753,14 +753,14 @@ size_t ld_sprint(char* str, int fmt, longdouble_soft x) @system if(fmt != 'a' && fmt != 'A') { char[3] format = ['%', cast(char)fmt, 0]; - return sprintf(str, format.ptr, ld_read(&x)); + return snprintf(str, size, format.ptr, ld_read(&x)); } ushort exp = x.exponent; ulong mantissa = x.mantissa; if(ld_type(x) == LD_TYPE_ZERO) - return sprintf(str, fmt == 'a' ? "0x0.0L" : "0X0.0L"); + return snprintf(str, size, fmt == 'a' ? "0x0.0L" : "0X0.0L"); size_t len = 0; if(x.sign) @@ -806,20 +806,21 @@ size_t ld_sprint(char* str, int fmt, longdouble_soft x) @system import core.stdc.string; import core.stdc.stdio; - char[32] buffer; - ld_sprint(buffer.ptr, 'a', ld_pi); + const bufflen = 32; + char[bufflen] buffer; + ld_sprint(buffer.ptr, bufflen, 'a', ld_pi); assert(strcmp(buffer.ptr, "0x1.921fb54442d1846ap+1") == 0); - auto len = ld_sprint(buffer.ptr, 'g', longdouble_soft(2.0)); + auto len = ld_sprint(buffer.ptr, bufflen, 'g', longdouble_soft(2.0)); assert(buffer[0 .. len] == "2.00000" || buffer[0 .. len] == "2"); // Win10 - 64bit - ld_sprint(buffer.ptr, 'g', longdouble_soft(1_234_567.89)); + ld_sprint(buffer.ptr, bufflen, 'g', longdouble_soft(1_234_567.89)); assert(strcmp(buffer.ptr, "1.23457e+06") == 0); - ld_sprint(buffer.ptr, 'g', ld_inf); + ld_sprint(buffer.ptr, bufflen, 'g', ld_inf); assert(strcmp(buffer.ptr, "inf") == 0); - ld_sprint(buffer.ptr, 'g', ld_qnan); + ld_sprint(buffer.ptr, bufflen, 'g', ld_qnan); assert(strcmp(buffer.ptr, "nan") == 0); longdouble_soft ldb = longdouble_soft(0.4); diff --git a/dmd/root/longdouble.h b/dmd/root/longdouble.h index 7ba827ccf96..a0dfaea9143 100644 --- a/dmd/root/longdouble.h +++ b/dmd/root/longdouble.h @@ -23,10 +23,10 @@ typedef volatile long double volatile_longdouble; #if __MINGW32__ // MinGW supports 80 bit reals, but the formatting functions map to versions // from the MSVC runtime by default which don't. -#define sprintf __mingw_sprintf +#define snprintf __mingw_snprintf #endif -inline size_t ld_sprint(char* str, int fmt, longdouble x) +inline size_t ld_sprint(char* str, size_t size, int fmt, longdouble x) { if (((longdouble)(unsigned long long)x) == x) { // ((1.5 -> 1 -> 1.0) == 1.5) is false @@ -34,18 +34,18 @@ inline size_t ld_sprint(char* str, int fmt, longdouble x) // see https://en.cppreference.com/w/cpp/io/c/fprintf char sfmt[5] = "%#Lg"; sfmt[3] = fmt; - return sprintf(str, sfmt, x); + return snprintf(str, size, sfmt, x); } else { char sfmt[4] = "%Lg"; sfmt[2] = fmt; - return sprintf(str, sfmt, x); + return snprintf(str, size, sfmt, x); } } #if __MINGW32__ -#undef sprintf +#undef snprintf #endif #else @@ -251,7 +251,7 @@ extern const longdouble_soft ld_pi2; extern const longdouble_soft ld_piOver2; extern const longdouble_soft ld_piOver4; -size_t ld_sprint(char* str, int fmt, longdouble_soft x); +size_t ld_sprint(char* str, size_t size, int fmt, longdouble_soft x); ////////////////////////////////////////////// typedef longdouble_soft longdouble; diff --git a/dmd/statementsem.d b/dmd/statementsem.d index 5b8883f6941..38ae8585f7b 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -1491,7 +1491,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor assert(0); } const(char)* r = (fs.op == TOK.foreach_reverse_) ? "R" : ""; - int j = sprintf(fdname.ptr, "_aApply%s%.*s%llu", r, 2, fntab[flag].ptr, cast(ulong)dim); + int j = snprintf(fdname.ptr, BUFFER_LEN, "_aApply%s%.*s%llu", r, 2, fntab[flag].ptr, cast(ulong)dim); assert(j < BUFFER_LEN); FuncDeclaration fdapply; diff --git a/dmd/tokens.d b/dmd/tokens.d index cad24cc5162..a048934d641 100644 --- a/dmd/tokens.d +++ b/dmd/tokens.d @@ -946,16 +946,17 @@ nothrow: extern (C++) const(char)* toChars() const { - __gshared char[3 + 3 * floatvalue.sizeof + 1] buffer; + const bufflen = 3 + 3 * floatvalue.sizeof + 1; + __gshared char[bufflen] buffer; const(char)* p = &buffer[0]; switch (value) { case TOK.int32Literal: - sprintf(&buffer[0], "%d", cast(int)intvalue); + snprintf(&buffer[0], bufflen, "%d", cast(int)intvalue); break; case TOK.uns32Literal: case TOK.wchar_tLiteral: - sprintf(&buffer[0], "%uU", cast(uint)unsvalue); + snprintf(&buffer[0], bufflen, "%uU", cast(uint)unsvalue); break; case TOK.wcharLiteral: case TOK.dcharLiteral: @@ -968,32 +969,32 @@ nothrow: } break; case TOK.int64Literal: - sprintf(&buffer[0], "%lldL", cast(long)intvalue); + snprintf(&buffer[0], bufflen, "%lldL", cast(long)intvalue); break; case TOK.uns64Literal: - sprintf(&buffer[0], "%lluUL", cast(ulong)unsvalue); + snprintf(&buffer[0], bufflen, "%lluUL", cast(ulong)unsvalue); break; case TOK.float32Literal: - CTFloat.sprint(&buffer[0], 'g', floatvalue); + CTFloat.sprint(&buffer[0], bufflen, 'g', floatvalue); strcat(&buffer[0], "f"); break; case TOK.float64Literal: - CTFloat.sprint(&buffer[0], 'g', floatvalue); + CTFloat.sprint(&buffer[0], bufflen, 'g', floatvalue); break; case TOK.float80Literal: - CTFloat.sprint(&buffer[0], 'g', floatvalue); + CTFloat.sprint(&buffer[0], bufflen, 'g', floatvalue); strcat(&buffer[0], "L"); break; case TOK.imaginary32Literal: - CTFloat.sprint(&buffer[0], 'g', floatvalue); + CTFloat.sprint(&buffer[0], bufflen, 'g', floatvalue); strcat(&buffer[0], "fi"); break; case TOK.imaginary64Literal: - CTFloat.sprint(&buffer[0], 'g', floatvalue); + CTFloat.sprint(&buffer[0], bufflen, 'g', floatvalue); strcat(&buffer[0], "i"); break; case TOK.imaginary80Literal: - CTFloat.sprint(&buffer[0], 'g', floatvalue); + CTFloat.sprint(&buffer[0], bufflen, 'g', floatvalue); strcat(&buffer[0], "Li"); break; case TOK.string_: diff --git a/tests/dmd/runnable/extra-files/paranoia.d b/tests/dmd/runnable/extra-files/paranoia.d index 986fe75387a..9aed89b457d 100644 --- a/tests/dmd/runnable/extra-files/paranoia.d +++ b/tests/dmd/runnable/extra-files/paranoia.d @@ -302,7 +302,7 @@ void printExtended(const(char) *fmt, FLOAT f) printf("%lg", cast(double)f); else { - ld_sprint(str.ptr, 'A', longdouble_soft(f)); + ld_sprint(str.ptr, str.length, 'A', longdouble_soft(f)); printf("%s", str.ptr); } } From 6c3bdc630840d473fd9fd804184e2ab00e2af4d4 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Sat, 4 Feb 2023 23:18:26 +0100 Subject: [PATCH 062/177] Remove dead `return ref` check --- dmd/typesem.d | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/dmd/typesem.d b/dmd/typesem.d index 1e94ba4c012..db4e53e71f4 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -1242,20 +1242,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) if (fparam.storageClass & STC.return_) { - if (fparam.isReference()) - { - // Disabled for the moment awaiting improvement to allow return by ref - // to be transformed into return by scope. - if (0 && !tf.isref) - { - auto stc = fparam.storageClass & (STC.ref_ | STC.out_); - .error(loc, "parameter `%s` is `return %s` but function does not return by `ref`", - fparam.ident ? fparam.ident.toChars() : "", - stcToString(stc).ptr); - errors = true; - } - } - else + if (!fparam.isReference()) { if (!(fparam.storageClass & STC.scope_)) fparam.storageClass |= STC.scope_ | STC.scopeinferred; // 'return' implies 'scope' From 8b278d97576bc55c5bf158948d90e97440d95572 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 8 Oct 2022 23:33:14 -0700 Subject: [PATCH 063/177] fix Issue 23387 - ImportC: identical structs defined in two C files lead to duplicate .init symbol on macOS --- tests/dmd/runnable/imports/freer.i | 5 +++++ tests/dmd/runnable/imports/maker.i | 5 +++++ tests/dmd/runnable/test23387.d | 30 ++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 tests/dmd/runnable/imports/freer.i create mode 100644 tests/dmd/runnable/imports/maker.i create mode 100644 tests/dmd/runnable/test23387.d diff --git a/tests/dmd/runnable/imports/freer.i b/tests/dmd/runnable/imports/freer.i new file mode 100644 index 00000000000..57e8792bd8a --- /dev/null +++ b/tests/dmd/runnable/imports/freer.i @@ -0,0 +1,5 @@ +typedef struct Foo *FooRef; +struct Foo { + int x; +}; +void free_foo(FooRef foo) { } diff --git a/tests/dmd/runnable/imports/maker.i b/tests/dmd/runnable/imports/maker.i new file mode 100644 index 00000000000..d3a7d943834 --- /dev/null +++ b/tests/dmd/runnable/imports/maker.i @@ -0,0 +1,5 @@ +typedef struct Foo *FooRef; +struct Foo { + int x; +}; +FooRef make_foo(void) { return 0; } diff --git a/tests/dmd/runnable/test23387.d b/tests/dmd/runnable/test23387.d new file mode 100644 index 00000000000..4419cf1200e --- /dev/null +++ b/tests/dmd/runnable/test23387.d @@ -0,0 +1,30 @@ +/* COMPILE_SEPARATELY: + * EXTRA_SOURCES: imports/maker.i imports/freer.i + */ + +// https://issues.dlang.org/show_bug.cgi?id=23387 + +/+ maker.i +typedef struct Foo *FooRef; +struct Foo { + int x; +}; +FooRef make_foo(void); ++/ +import imports.maker; + + +/+ freer.i +typedef struct Foo *FooRef; +struct Foo { + int x; +}; +void free_foo(FooRef foo); ++/ +import imports.freer; + +int main(){ + FooRef f = make_foo(); + free_foo(f); + return 0; +} From e1a5a392bcf1b7e7a876ae530530776a528e8589 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 5 Feb 2023 20:52:18 +0100 Subject: [PATCH 064/177] dmd.root.filename: Add FileName::create helper --- dmd/frontend.h | 1 + dmd/root/filename.d | 6 ++++++ dmd/root/filename.h | 1 + 3 files changed, 8 insertions(+) diff --git a/dmd/frontend.h b/dmd/frontend.h index 4584156a885..5951fbb39c1 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -786,6 +786,7 @@ struct FileName final private: _d_dynamicArray< const char > str; public: + static FileName create(const char* name); static bool equals(const char* name1, const char* name2); static bool absolute(const char* name); static const char* toAbsolute(const char* name, const char* base = nullptr); diff --git a/dmd/root/filename.d b/dmd/root/filename.d index 33f4a7aa4b1..387361568e0 100644 --- a/dmd/root/filename.d +++ b/dmd/root/filename.d @@ -85,6 +85,12 @@ nothrow: this.str = str.xarraydup; } + /// + extern (C++) static FileName create(const(char)* name) pure + { + return FileName(name.toDString); + } + /// Compare two name according to the platform's rules (case sensitive or not) extern (C++) static bool equals(const(char)* name1, const(char)* name2) pure @nogc { diff --git a/dmd/root/filename.h b/dmd/root/filename.h index 89774119d4d..62142331013 100644 --- a/dmd/root/filename.h +++ b/dmd/root/filename.h @@ -19,6 +19,7 @@ struct FileName private: DString str; public: + static FileName create(const char *name); static bool equals(const char *name1, const char *name2); static bool absolute(const char *name); static const char *toAbsolute(const char *name, const char *base = NULL); From 389558e38114566a5f60f04ee681f2fa3e79a41b Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 16 Dec 2022 21:02:34 -0800 Subject: [PATCH 065/177] replace addLocalClass() with ScopeDsymbol._foreach --- dmd/aggregate.h | 1 - dmd/attrib.d | 5 ----- dmd/attrib.h | 1 - dmd/dclass.d | 6 ------ dmd/dmodule.d | 31 +++++++++++++++++++++++++++++++ dmd/dsymbol.d | 4 ---- dmd/dsymbol.h | 1 - dmd/frontend.h | 5 ++--- dmd/module.h | 2 ++ 9 files changed, 35 insertions(+), 21 deletions(-) diff --git a/dmd/aggregate.h b/dmd/aggregate.h index 9f9098f7f2b..04e5eb2f0d9 100644 --- a/dmd/aggregate.h +++ b/dmd/aggregate.h @@ -304,7 +304,6 @@ class ClassDeclaration : public AggregateDeclaration virtual int vtblOffset() const; const char *kind() const override; - void addLocalClass(ClassDeclarations *) override final; void addObjcSymbols(ClassDeclarations *classes, ClassDeclarations *categories) override final; // Back end diff --git a/dmd/attrib.d b/dmd/attrib.d index c7bd3430115..dbe78ef74bc 100644 --- a/dmd/attrib.d +++ b/dmd/attrib.d @@ -197,11 +197,6 @@ extern (C++) abstract class AttribDeclaration : Dsymbol /**************************************** */ - override final void addLocalClass(ClassDeclarations* aclasses) - { - include(null).foreachDsymbol( s => s.addLocalClass(aclasses) ); - } - override final void addObjcSymbols(ClassDeclarations* classes, ClassDeclarations* categories) { objc.addSymbols(this, classes, categories); diff --git a/dmd/attrib.h b/dmd/attrib.h index dd8da6f4702..44ceb12e0d0 100644 --- a/dmd/attrib.h +++ b/dmd/attrib.h @@ -36,7 +36,6 @@ class AttribDeclaration : public Dsymbol bool hasPointers() override final; bool hasStaticCtorOrDtor() override final; void checkCtorConstInit() override final; - void addLocalClass(ClassDeclarations *) override final; AttribDeclaration *isAttribDeclaration() override { return this; } void accept(Visitor *v) override { v->visit(this); } diff --git a/dmd/dclass.d b/dmd/dclass.d index 1fdd0730fcf..e4585934089 100644 --- a/dmd/dclass.d +++ b/dmd/dclass.d @@ -963,12 +963,6 @@ extern (C++) class ClassDeclaration : AggregateDeclaration /**************************************** */ - override final void addLocalClass(ClassDeclarations* aclasses) - { - if (classKind != ClassKind.objc) - aclasses.push(this); - } - override final void addObjcSymbols(ClassDeclarations* classes, ClassDeclarations* categories) { .objc.addSymbols(this, classes, categories); diff --git a/dmd/dmodule.d b/dmd/dmodule.d index e1234e5bde9..bb518fa081d 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -1377,6 +1377,37 @@ extern (C++) struct ModuleDeclaration } } +/**************************************** + * Create array of the local classes in the Module, suitable + * for inclusion in ModuleInfo + * Params: + * mod = the Module + * aclasses = array to fill in + * Returns: array of local classes + */ +extern (C++) void getLocalClasses(Module mod, ref ClassDeclarations aclasses) +{ + //printf("members.length = %d\n", mod.members.length); + int pushAddClassDg(size_t n, Dsymbol sm) + { + if (!sm) + return 0; + + if (auto cd = sm.isClassDeclaration()) + { + // compatibility with previous algorithm + if (cd.parent && cd.parent.isTemplateMixin()) + return 0; + + if (cd.classKind != ClassKind.objc) + aclasses.push(cd); + } + return 0; + } + + ScopeDsymbol._foreach(null, mod.members, &pushAddClassDg); +} + /** * Process the content of a source file * diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index a9ca5b71d86..aa478f2fea2 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -1239,10 +1239,6 @@ extern (C++) class Dsymbol : ASTNode return false; } - void addLocalClass(ClassDeclarations*) - { - } - void addObjcSymbols(ClassDeclarations* classes, ClassDeclarations* categories) { } diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index ca9634eaad0..1cee456aa10 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -258,7 +258,6 @@ class Dsymbol : public ASTNode virtual void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion); virtual bool hasPointers(); virtual bool hasStaticCtorOrDtor(); - virtual void addLocalClass(ClassDeclarations *) { } virtual void addObjcSymbols(ClassDeclarations *, ClassDeclarations *) { } virtual void checkCtorConstInit() { } diff --git a/dmd/frontend.h b/dmd/frontend.h index 5951fbb39c1..465837affc8 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -508,7 +508,6 @@ class Dsymbol : public ASTNode virtual void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion); virtual bool hasPointers(); virtual bool hasStaticCtorOrDtor(); - virtual void addLocalClass(Array* _param_0); virtual void addObjcSymbols(Array* classes, Array* categories); virtual void checkCtorConstInit(); virtual void addComment(const char* comment); @@ -5389,7 +5388,6 @@ class AttribDeclaration : public Dsymbol bool hasPointers() final override; bool hasStaticCtorOrDtor() final override; void checkCtorConstInit() final override; - void addLocalClass(Array* aclasses) final override; void addObjcSymbols(Array* classes, Array* categories) final override; AttribDeclaration* isAttribDeclaration() override; void accept(Visitor* v) override; @@ -5788,7 +5786,6 @@ class ClassDeclaration : public AggregateDeclaration bool isAbstract(); virtual int32_t vtblOffset() const; const char* kind() const override; - void addLocalClass(Array* aclasses) final override; void addObjcSymbols(Array* classes, Array* categories) final override; Dsymbol* vtblsym; Dsymbol* vtblSymbol(); @@ -6357,6 +6354,8 @@ struct ModuleDeclaration final } }; +extern void getLocalClasses(Module* mod, Array& aclasses); + extern void gendocfile(Module* m); struct Scope final diff --git a/dmd/module.h b/dmd/module.h index bc89ac4677e..002bb1a875b 100644 --- a/dmd/module.h +++ b/dmd/module.h @@ -170,3 +170,5 @@ struct ModuleDeclaration const char *toChars() const; }; + +extern void getLocalClasses(Module* mod, Array& aclasses); From 40d69b48746f7ae1b572a7e6fd0119c632165520 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Tue, 7 Feb 2023 00:27:49 +0100 Subject: [PATCH 066/177] d_do_test: allow separately compiling c sources --- tests/dmd/tools/d_do_test.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dmd/tools/d_do_test.d b/tests/dmd/tools/d_do_test.d index d202901fd80..b1ffa04b7d9 100755 --- a/tests/dmd/tools/d_do_test.d +++ b/tests/dmd/tools/d_do_test.d @@ -1712,7 +1712,7 @@ int tryMain(string[] args) { foreach (filename; testArgs.sources ~ (autoCompileImports ? null : testArgs.compiledImports)) { - string newo = output_dir ~ envData.sep ~ replace(filename.baseName(), ".d", envData.obj); + string newo = output_dir ~ envData.sep ~ filename.baseName().setExtension(envData.obj); toCleanup ~= newo; command = format("%s -conf= -m%s -I%s %s %s -od%s -c %s %s", envData.dmd, envData.model, input_dir, From a576b28e14e435952737c23870f8dac34103953d Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 7 Feb 2023 00:38:55 -0800 Subject: [PATCH 067/177] fix Issue 20781 - Can call @live function without checking dip1021 rules (dlang/dmd!11071) --- dmd/escape.d | 2 +- dmd/expressionsem.d | 6 +++--- tests/dmd/fail_compilation/fob1.d | 17 +++++++++++++++++ tests/dmd/fail_compilation/fob2.d | 7 +++++-- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/dmd/escape.d b/dmd/escape.d index 06be24538d8..316a55b6582 100644 --- a/dmd/escape.d +++ b/dmd/escape.d @@ -181,7 +181,7 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf, if (!(eb.isMutable || eb2.isMutable)) return; - if (!(global.params.useDIP1000 == FeatureState.enabled && sc.setUnsafe())) + if (!tf.islive && !(global.params.useDIP1000 == FeatureState.enabled && sc.func.setUnsafe())) return; if (!gag) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 6dfdbd4bb4d..56b723d44c6 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -2448,10 +2448,10 @@ private bool functionParameters(const ref Loc loc, Scope* sc, } //if (eprefix) printf("eprefix: %s\n", eprefix.toChars()); - /* Test compliance with DIP1021 + /* Test compliance with DIP1021 Argument Ownership and Function Calls */ - if (global.params.useDIP1021 && - tf.trust != TRUST.system && tf.trust != TRUST.trusted) + if (global.params.useDIP1021 && (tf.trust == TRUST.safe || tf.trust == TRUST.default_) || + tf.islive) err |= checkMutableArguments(sc, fd, tf, ethis, arguments, false); // If D linkage and variadic, add _arguments[] as first argument diff --git a/tests/dmd/fail_compilation/fob1.d b/tests/dmd/fail_compilation/fob1.d index 83a6cd2dcb4..d11a7a69916 100644 --- a/tests/dmd/fail_compilation/fob1.d +++ b/tests/dmd/fail_compilation/fob1.d @@ -62,3 +62,20 @@ fail_compilation/fob1.d(405): Error: variable `fob1.foo4.bq` has undefined state *bq = 1; return p; } + +/* TEST_OUTPUT: +--- +fail_compilation/fob1.d(503): Error: more than one mutable reference to `a` in arguments to `fob1.foo5()` +--- +*/ + +// https://issues.dlang.org/show_bug.cgi?id=20781 + +#line 500 + +void test5() { + int a; + foo5(a, a); +} + +@live void foo5(ref int, ref int); diff --git a/tests/dmd/fail_compilation/fob2.d b/tests/dmd/fail_compilation/fob2.d index 1fbb0408f84..e9179da7405 100644 --- a/tests/dmd/fail_compilation/fob2.d +++ b/tests/dmd/fail_compilation/fob2.d @@ -28,11 +28,13 @@ fail_compilation/fob2.d(103): Error: variable `fob2.foo1.p` is not disposed of b /* TEST_OUTPUT: --- -fail_compilation/fob2.d(203): Error: variable `fob2.zoo2.p` is passed as Owner more than once -fail_compilation/fob2.d(202): Error: variable `fob2.zoo2.p` is not disposed of before return +fail_compilation/fob2.d(203): Error: more than one mutable reference of `p` in arguments to `fob2.foo2()` --- */ +//fail_compilation/fob2.d(203): Error: variable `fob2.zoo2.p` is passed as Owner more than once +//fail_compilation/fob2.d(202): Error: variable `fob2.zoo2.p` is left dangling at return + #line 200 @live void zoo2() { @@ -141,6 +143,7 @@ fail_compilation/fob2.d(515): Error: variable `fob2.test52.p` has undefined stat /* TEST_OUTPUT: --- fail_compilation/fob2.d(603): Error: variable `fob2.test6.p` is not disposed of before return +fail_compilation/fob2.d(612): Error: more than one mutable reference of `p` in arguments to `fob2.foo6b()` --- */ From 8dce0787810b724bf0bca325d269229f30dad6fd Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 7 Feb 2023 02:57:43 -0800 Subject: [PATCH 068/177] ImportC: add __check(assign-expression) extension (dlang/dmd!14026) --- dmd/cparse.d | 9 +++++++++ dmd/frontend.h | 15 ++++++++------- dmd/tokens.d | 6 +++++- dmd/tokens.h | 1 + test/runnable/testcheck.c | 7 +++++++ tests/dmd/unit/lexer/location_offset.d | 1 + 6 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 test/runnable/testcheck.c diff --git a/dmd/cparse.d b/dmd/cparse.d index efb68ea3987..ce0f87a1d98 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -268,6 +268,7 @@ final class CParser(AST) : Parser!AST case TOK.minusMinus: case TOK.sizeof_: case TOK._Generic: + case TOK._assert: Lexp: auto exp = cparseExpression(); if (token.value == TOK.identifier && exp.op == EXP.identifier) @@ -782,6 +783,14 @@ final class CParser(AST) : Parser!AST e = cparseGenericSelection(); break; + case TOK._assert: // __check(assign-exp) extension + nextToken(); + check(TOK.leftParenthesis, "`__check`"); + e = parseAssignExp(); + check(TOK.rightParenthesis); + e = new AST.AssertExp(loc, e, null); + break; + default: error("expression expected, not `%s`", token.toChars()); // Anything for e, as long as it's not NULL diff --git a/dmd/frontend.h b/dmd/frontend.h index 465837affc8..68fa060897e 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -1814,13 +1814,14 @@ enum class TOK : uint8_t _Noreturn = 212u, _Static_assert = 213u, _Thread_local = 214u, - _import = 215u, - __cdecl_ = 216u, - __declspec_ = 217u, - __stdcall_ = 218u, - __pragma_ = 219u, - __int128_ = 220u, - __attribute___ = 221u, + _assert = 215u, + _import = 216u, + __cdecl_ = 217u, + __declspec_ = 218u, + __stdcall_ = 219u, + __pragma_ = 220u, + __int128_ = 221u, + __attribute___ = 222u, }; enum class MemorySet diff --git a/dmd/tokens.d b/dmd/tokens.d index a048934d641..1f4eb792fd3 100644 --- a/dmd/tokens.d +++ b/dmd/tokens.d @@ -269,6 +269,7 @@ enum TOK : ubyte _Thread_local, // C only extended keywords + _assert, _import, __cdecl, __declspec, @@ -580,6 +581,7 @@ private immutable TOK[] keywords = TOK._Thread_local, // C only extended keywords + TOK._assert, TOK._import, TOK.__cdecl, TOK.__declspec, @@ -615,7 +617,8 @@ static immutable TOK[TOK.max + 1] Ckeywords = union_, unsigned, void_, volatile, while_, asm_, typeof_, _Alignas, _Alignof, _Atomic, _Bool, _Complex, _Generic, _Imaginary, _Noreturn, _Static_assert, _Thread_local, - _import, __cdecl, __declspec, __stdcall, __pragma, __int128, __attribute__ ]; + _import, __cdecl, __declspec, __stdcall, __pragma, __int128, __attribute__, + _assert ]; foreach (kw; Ckwds) tab[kw] = cast(TOK) kw; @@ -881,6 +884,7 @@ extern (C++) struct Token TOK._Thread_local : "_Thread_local", // C only extended keywords + TOK._assert : "__check", TOK._import : "__import", TOK.__cdecl : "__cdecl", TOK.__declspec : "__declspec", diff --git a/dmd/tokens.h b/dmd/tokens.h index 8444f8114ac..87361f327a4 100644 --- a/dmd/tokens.h +++ b/dmd/tokens.h @@ -278,6 +278,7 @@ enum class TOK : unsigned char _Thread_local_, // C only extended keywords + _assert, _import, cdecl_, declspec, diff --git a/test/runnable/testcheck.c b/test/runnable/testcheck.c new file mode 100644 index 00000000000..3fcf0e58414 --- /dev/null +++ b/test/runnable/testcheck.c @@ -0,0 +1,7 @@ + +int main() +{ + int i = 3; + __check(i == 3); + return 0; +} diff --git a/tests/dmd/unit/lexer/location_offset.d b/tests/dmd/unit/lexer/location_offset.d index 813125c2066..9ba3c51752b 100644 --- a/tests/dmd/unit/lexer/location_offset.d +++ b/tests/dmd/unit/lexer/location_offset.d @@ -536,6 +536,7 @@ enum ignoreTokens _Static_assert, _Thread_local, + _assert, _import, __cdecl, __declspec, From b794cdf51f32de2d7a26654bb06324bb58d8b165 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 7 Feb 2023 07:23:04 -0800 Subject: [PATCH 069/177] fix Issue 21821 - Optimizer assumes immutables do not change, but they can in @system code (dlang/dmd!12424) --- test/runnable/test21821.d | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 test/runnable/test21821.d diff --git a/test/runnable/test21821.d b/test/runnable/test21821.d new file mode 100644 index 00000000000..d16331d1897 --- /dev/null +++ b/test/runnable/test21821.d @@ -0,0 +1,32 @@ +// REQUIRED_ARGS: -preview=fieldwise -O +// https://issues.dlang.org/show_bug.cgi?id=21821 + +// test case comes from unittests in core.lifetime + +void test() +{ + alias T = immutable(S); + T source; + T target; + copyEmplacex(source, target); + T expectedCopy = source; + assert(target == expectedCopy); +} + +struct S +{ + int x = 42; + this(this) { x += 10; } +} + +void copyEmplacex(ref immutable(S) source, ref immutable(S) target) @system +{ + import core.stdc.string : memcpy; + memcpy(cast(S*) &target, cast(S*) &source, S.sizeof); + (cast() target).__xpostblit(); // casting away immutable +} + +void main() +{ + test(); +} From b1beea5ffbf072eeb7286a51bb43206faf6e127f Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 7 Feb 2023 09:18:03 -0800 Subject: [PATCH 070/177] add scope to constructors (dlang/dmd!14323) --- dmd/apply.d | 2 +- dmd/argtypes_sysv_x64.d | 2 +- dmd/arrayop.d | 2 +- dmd/blockexit.d | 2 +- dmd/canthrow.d | 2 +- dmd/cparse.d | 2 +- dmd/cppmangle.d | 2 +- dmd/cppmanglewin.d | 4 ++-- dmd/delegatize.d | 4 ++-- dmd/dinterpret.d | 2 +- dmd/dmangle.d | 2 +- dmd/doc.d | 4 ++-- dmd/dsymbolsem.d | 4 ++-- dmd/dtemplate.d | 4 ++-- dmd/dtoh.d | 2 +- dmd/expression.d | 24 ++++++++++++------------ dmd/expressionsem.d | 2 +- dmd/foreachvar.d | 2 +- dmd/hdrgen.d | 8 ++++---- dmd/inline.d | 8 ++++---- dmd/inlinecost.d | 6 +++--- dmd/json.d | 2 +- dmd/lambdacomp.d | 2 +- dmd/lexer.d | 4 ++-- dmd/mtype.d | 4 ++-- dmd/nogc.d | 2 +- dmd/ob.d | 6 +++--- dmd/parse.d | 4 ++-- dmd/printast.d | 2 +- dmd/root/aav.d | 2 +- dmd/root/array.d | 2 +- dmd/root/rootobject.d | 2 +- dmd/sapply.d | 2 +- dmd/semantic2.d | 2 +- dmd/semantic3.d | 4 ++-- dmd/sideeffect.d | 4 ++-- dmd/statementsem.d | 2 +- dmd/templateparamsem.d | 2 +- dmd/traits.d | 2 +- dmd/visitor.d | 2 +- 40 files changed, 71 insertions(+), 71 deletions(-) diff --git a/dmd/apply.d b/dmd/apply.d index f5855c4758a..59ba9f5ecd6 100644 --- a/dmd/apply.d +++ b/dmd/apply.d @@ -75,7 +75,7 @@ private extern (C++) final class PostorderExpressionVisitor : StoppableVisitor public: StoppableVisitor v; - extern (D) this(StoppableVisitor v) + extern (D) this(StoppableVisitor v) scope { this.v = v; } diff --git a/dmd/argtypes_sysv_x64.d b/dmd/argtypes_sysv_x64.d index da8bc8d22cf..835544d2c46 100644 --- a/dmd/argtypes_sysv_x64.d +++ b/dmd/argtypes_sysv_x64.d @@ -156,7 +156,7 @@ extern (C++) final class ToClassesVisitor : Visitor int numEightbytes; Class[4] result = Class.noClass; - this(size_t size) + this(size_t size) scope { assert(size > 0); this.size = size; diff --git a/dmd/arrayop.d b/dmd/arrayop.d index da2f8000fc1..d60e584deeb 100644 --- a/dmd/arrayop.d +++ b/dmd/arrayop.d @@ -194,7 +194,7 @@ private Expressions* buildArrayOp(Scope* sc, Expression e, Objects* tiargs) Expressions* args; public: - extern (D) this(Scope* sc, Objects* tiargs) + extern (D) this(Scope* sc, Objects* tiargs) scope { this.sc = sc; this.tiargs = tiargs; diff --git a/dmd/blockexit.d b/dmd/blockexit.d index 6369b5ab04b..bd5b78e92dc 100644 --- a/dmd/blockexit.d +++ b/dmd/blockexit.d @@ -71,7 +71,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow) bool mustNotThrow; int result; - extern (D) this(FuncDeclaration func, bool mustNotThrow) + extern (D) this(FuncDeclaration func, bool mustNotThrow) scope { this.func = func; this.mustNotThrow = mustNotThrow; diff --git a/dmd/canthrow.d b/dmd/canthrow.d index 7c18040eb02..0c237e6da56 100644 --- a/dmd/canthrow.d +++ b/dmd/canthrow.d @@ -63,7 +63,7 @@ extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN CT result; public: - extern (D) this(FuncDeclaration func, bool mustNotThrow) + extern (D) this(FuncDeclaration func, bool mustNotThrow) scope { this.func = func; this.mustNotThrow = mustNotThrow; diff --git a/dmd/cparse.d b/dmd/cparse.d index ce0f87a1d98..3ba7a6e2732 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -69,7 +69,7 @@ final class CParser(AST) : Parser!AST OutBuffer* defines; extern (D) this(TARGET)(AST.Module _module, const(char)[] input, bool doDocComment, - const ref TARGET target, OutBuffer* defines) + const ref TARGET target, OutBuffer* defines) scope { super(_module, input, doDocComment); diff --git a/dmd/cppmangle.d b/dmd/cppmangle.d index d3effa99ddd..b015a642b90 100644 --- a/dmd/cppmangle.d +++ b/dmd/cppmangle.d @@ -173,7 +173,7 @@ private final class CppMangleVisitor : Visitor * buf = `OutBuffer` to write the mangling to * loc = `Loc` of the symbol being mangled */ - this(OutBuffer* buf, Loc loc) + this(OutBuffer* buf, Loc loc) scope { this.buf = buf; this.loc = loc; diff --git a/dmd/cppmanglewin.d b/dmd/cppmanglewin.d index ba8c6646e09..1ae20bac368 100644 --- a/dmd/cppmanglewin.d +++ b/dmd/cppmanglewin.d @@ -122,7 +122,7 @@ private final class VisualCPPMangler : Visitor int flags; OutBuffer buf; - extern (D) this(VisualCPPMangler rvl) + extern (D) this(VisualCPPMangler rvl) scope { flags |= (rvl.flags & IS_DMC); saved_idents[] = rvl.saved_idents[]; @@ -131,7 +131,7 @@ private final class VisualCPPMangler : Visitor } public: - extern (D) this(bool isdmc, Loc loc) + extern (D) this(bool isdmc, Loc loc) scope { if (isdmc) { diff --git a/dmd/delegatize.d b/dmd/delegatize.d index 3f982b3faf7..fd9569105b5 100644 --- a/dmd/delegatize.d +++ b/dmd/delegatize.d @@ -109,7 +109,7 @@ private void lambdaSetParent(Expression e, FuncDeclaration fd) } public: - extern (D) this(FuncDeclaration fd) + extern (D) this(FuncDeclaration fd) scope { this.fd = fd; } @@ -205,7 +205,7 @@ bool lambdaCheckForNestedRef(Expression e, Scope* sc) Scope* sc; bool result; - extern (D) this(Scope* sc) + extern (D) this(Scope* sc) scope { this.sc = sc; } diff --git a/dmd/dinterpret.d b/dmd/dinterpret.d index 7920df79991..9073b0db2f8 100644 --- a/dmd/dinterpret.d +++ b/dmd/dinterpret.d @@ -747,7 +747,7 @@ public: Expression result; UnionExp* pue; // storage for `result` - extern (D) this(UnionExp* pue, InterState* istate, CTFEGoal goal) + extern (D) this(UnionExp* pue, InterState* istate, CTFEGoal goal) scope { this.pue = pue; this.istate = istate; diff --git a/dmd/dmangle.d b/dmd/dmangle.d index eab9eb1bfd6..59bad02fe29 100644 --- a/dmd/dmangle.d +++ b/dmd/dmangle.d @@ -240,7 +240,7 @@ public: OutBuffer* buf; Backref backref; - extern (D) this(OutBuffer* buf, Type rootType = null) + extern (D) this(OutBuffer* buf, Type rootType = null) scope { this.buf = buf; this.backref = Backref(rootType); diff --git a/dmd/doc.d b/dmd/doc.d index 732a7370a77..155406f9919 100644 --- a/dmd/doc.d +++ b/dmd/doc.d @@ -951,7 +951,7 @@ private void emitComment(Dsymbol s, ref OutBuffer buf, Scope* sc) OutBuffer* buf; Scope* sc; - extern (D) this(ref OutBuffer buf, Scope* sc) + extern (D) this(ref OutBuffer buf, Scope* sc) scope { this.buf = &buf; this.sc = sc; @@ -1235,7 +1235,7 @@ private void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc) OutBuffer* buf; Scope* sc; - extern (D) this(ref OutBuffer buf, Scope* sc) + extern (D) this(ref OutBuffer buf, Scope* sc) scope { this.buf = &buf; this.sc = sc; diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index e85fd4891eb..d66602d0914 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -271,7 +271,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor alias visit = Visitor.visit; Scope* sc; - this(Scope* sc) + this(Scope* sc) scope { this.sc = sc; } @@ -6017,7 +6017,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, Expressions* alias visit = Visitor.visit; TemplateInstance inst; - extern (D) this(TemplateInstance inst) + extern (D) this(TemplateInstance inst) scope { this.inst = inst; } diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 1b991d200ac..763a46d2a91 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -5897,7 +5897,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol } } - extern (D) this(const ref Loc loc, Identifier ident, Objects* tiargs) + extern (D) this(const ref Loc loc, Identifier ident, Objects* tiargs) scope { super(loc, null); static if (LOG) @@ -5912,7 +5912,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol * This constructor is only called when we figured out which function * template to instantiate. */ - extern (D) this(const ref Loc loc, TemplateDeclaration td, Objects* tiargs) + extern (D) this(const ref Loc loc, TemplateDeclaration td, Objects* tiargs) scope { super(loc, null); static if (LOG) diff --git a/dmd/dtoh.d b/dmd/dtoh.d index dfb24d536c1..5386787f628 100644 --- a/dmd/dtoh.d +++ b/dmd/dtoh.d @@ -293,7 +293,7 @@ public: Context context; alias context this; - this(OutBuffer* fwdbuf, OutBuffer* donebuf, OutBuffer* buf) + this(OutBuffer* fwdbuf, OutBuffer* donebuf, OutBuffer* buf) scope { this.fwdbuf = fwdbuf; this.donebuf = donebuf; diff --git a/dmd/expression.d b/dmd/expression.d index c72995e6d93..25ea379b7ce 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -734,7 +734,7 @@ extern (C++) abstract class Expression : ASTNode Type type; // !=null means that semantic() has been run Loc loc; // file location - extern (D) this(const ref Loc loc, EXP op, int size) + extern (D) this(const ref Loc loc, EXP op, int size) scope { //printf("Expression::Expression(op = %d) this = %p\n", op, this); this.loc = loc; @@ -2336,7 +2336,7 @@ extern (C++) class IdentifierExp : Expression { Identifier ident; - extern (D) this(const ref Loc loc, Identifier ident) + extern (D) this(const ref Loc loc, Identifier ident) scope { super(loc, EXP.identifier, __traits(classInstanceSize, IdentifierExp)); this.ident = ident; @@ -2491,7 +2491,7 @@ extern (C++) final class SuperExp : ThisExp */ extern (C++) final class NullExp : Expression { - extern (D) this(const ref Loc loc, Type type = null) + extern (D) this(const ref Loc loc, Type type = null) scope { super(loc, EXP.null_, __traits(classInstanceSize, NullExp)); this.type = type; @@ -2550,7 +2550,7 @@ extern (C++) final class StringExp : Expression char postfix = NoPostfix; // 'c', 'w', 'd' OwnedBy ownedByCtfe = OwnedBy.code; - extern (D) this(const ref Loc loc, const(void)[] string) + extern (D) this(const ref Loc loc, const(void)[] string) scope { super(loc, EXP.string_, __traits(classInstanceSize, StringExp)); this.string = cast(char*)string.ptr; // note that this.string should be const @@ -2558,7 +2558,7 @@ extern (C++) final class StringExp : Expression this.sz = 1; // work around LDC bug #1286 } - extern (D) this(const ref Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix = NoPostfix) + extern (D) this(const ref Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix = NoPostfix) scope { super(loc, EXP.string_, __traits(classInstanceSize, StringExp)); this.string = cast(char*)string.ptr; // note that this.string should be const @@ -4294,7 +4294,7 @@ extern (C++) final class IsExp : Expression TOK tok; // ':' or '==' TOK tok2; // 'struct', 'union', etc. - extern (D) this(const ref Loc loc, Type targ, Identifier id, TOK tok, Type tspec, TOK tok2, TemplateParameters* parameters) + extern (D) this(const ref Loc loc, Type targ, Identifier id, TOK tok, Type tspec, TOK tok2, TemplateParameters* parameters) scope { super(loc, EXP.is_, __traits(classInstanceSize, IsExp)); this.targ = targ; @@ -4334,7 +4334,7 @@ extern (C++) abstract class UnaExp : Expression Expression e1; Type att1; // Save alias this type to detect recursion - extern (D) this(const ref Loc loc, EXP op, int size, Expression e1) + extern (D) this(const ref Loc loc, EXP op, int size, Expression e1) scope { super(loc, op, size); this.e1 = e1; @@ -4407,7 +4407,7 @@ extern (C++) abstract class BinExp : Expression Type att1; // Save alias this type to detect recursion Type att2; // Save alias this type to detect recursion - extern (D) this(const ref Loc loc, EXP op, int size, Expression e1, Expression e2) + extern (D) this(const ref Loc loc, EXP op, int size, Expression e1, Expression e2) scope { super(loc, op, size); this.e1 = e1; @@ -4698,7 +4698,7 @@ extern (C++) abstract class BinExp : Expression */ extern (C++) class BinAssignExp : BinExp { - extern (D) this(const ref Loc loc, EXP op, int size, Expression e1, Expression e2) + extern (D) this(const ref Loc loc, EXP op, int size, Expression e1, Expression e2) scope { super(loc, op, size, e1, e2); } @@ -5404,7 +5404,7 @@ extern (C++) final class NegExp : UnaExp */ extern (C++) final class UAddExp : UnaExp { - extern (D) this(const ref Loc loc, Expression e) + extern (D) this(const ref Loc loc, Expression e) scope { super(loc, EXP.uadd, __traits(classInstanceSize, UAddExp), e); } @@ -6466,7 +6466,7 @@ extern (C++) final class MinExp : BinExp */ extern (C++) final class CatExp : BinExp { - extern (D) this(const ref Loc loc, Expression e1, Expression e2) + extern (D) this(const ref Loc loc, Expression e1, Expression e2) scope { super(loc, EXP.concatenate, __traits(classInstanceSize, CatExp), e1, e2); } @@ -6796,7 +6796,7 @@ extern (C++) final class CondExp : BinExp { Expression econd; - extern (D) this(const ref Loc loc, Expression econd, Expression e1, Expression e2) + extern (D) this(const ref Loc loc, Expression econd, Expression e1, Expression e2) scope { super(loc, EXP.question, __traits(classInstanceSize, CondExp), e1, e2); this.econd = econd; diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 56b723d44c6..9c2f277eb59 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -2550,7 +2550,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor Scope* sc; Expression result; - this(Scope* sc) + this(Scope* sc) scope { this.sc = sc; } diff --git a/dmd/foreachvar.d b/dmd/foreachvar.d index 7c4df0deca8..ba2825a3098 100644 --- a/dmd/foreachvar.d +++ b/dmd/foreachvar.d @@ -56,7 +56,7 @@ void foreachVar(Expression e, void delegate(VarDeclaration) dgVar) alias visit = typeof(super).visit; extern (D) void delegate(VarDeclaration) dgVar; - extern (D) this(void delegate(VarDeclaration) dgVar) + extern (D) this(void delegate(VarDeclaration) dgVar) scope { this.dgVar = dgVar; } diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index 176e0a6262c..05586fe9653 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -145,7 +145,7 @@ public: OutBuffer* buf; HdrGenState* hgs; - extern (D) this(OutBuffer* buf, HdrGenState* hgs) + extern (D) this(OutBuffer* buf, HdrGenState* hgs) scope { this.buf = buf; this.hgs = hgs; @@ -806,7 +806,7 @@ public: OutBuffer* buf; HdrGenState* hgs; - extern (D) this(OutBuffer* buf, HdrGenState* hgs) + extern (D) this(OutBuffer* buf, HdrGenState* hgs) scope { this.buf = buf; this.hgs = hgs; @@ -2762,7 +2762,7 @@ public: OutBuffer* buf; HdrGenState* hgs; - extern (D) this(OutBuffer* buf, HdrGenState* hgs) + extern (D) this(OutBuffer* buf, HdrGenState* hgs) scope { this.buf = buf; this.hgs = hgs; @@ -2843,7 +2843,7 @@ public: OutBuffer* buf; HdrGenState* hgs; - extern (D) this(OutBuffer* buf, HdrGenState* hgs) + extern (D) this(OutBuffer* buf, HdrGenState* hgs) scope { this.buf = buf; this.hgs = hgs; diff --git a/dmd/inline.d b/dmd/inline.d index 6d4e3e041b3..3f9d4d56d82 100644 --- a/dmd/inline.d +++ b/dmd/inline.d @@ -142,7 +142,7 @@ private final class InlineDoState // inline result bool foundReturn; - this(Dsymbol parent, FuncDeclaration fd) + this(Dsymbol parent, FuncDeclaration fd) scope { this.parent = parent; this.fd = fd; @@ -167,7 +167,7 @@ public: enum asStatements = is(Result == Statement); - extern (D) this(InlineDoState ids) + extern (D) this(InlineDoState ids) scope { this.ids = ids; } @@ -943,7 +943,7 @@ public: Expression eresult; bool again; - extern (D) this() + extern (D) this() scope { } @@ -2298,7 +2298,7 @@ private bool expNeedsDtor(Expression exp) Expression exp; public: - extern (D) this(Expression exp) + extern (D) this(Expression exp) scope { this.exp = exp; } diff --git a/dmd/inlinecost.d b/dmd/inlinecost.d index b8b58019529..c6ac26bfdb0 100644 --- a/dmd/inlinecost.d +++ b/dmd/inlinecost.d @@ -156,11 +156,11 @@ public: FuncDeclaration fd; int cost; // zero start for subsequent AST - extern (D) this() + extern (D) this() scope { } - extern (D) this(bool hasthis, bool hdrscan, bool allowAlloca, FuncDeclaration fd) + extern (D) this(bool hasthis, bool hdrscan, bool allowAlloca, FuncDeclaration fd) scope { this.hasthis = hasthis; this.hdrscan = hdrscan; @@ -168,7 +168,7 @@ public: this.fd = fd; } - extern (D) this(InlineCostVisitor icv) + extern (D) this(InlineCostVisitor icv) scope { nested = icv.nested; hasthis = icv.hasthis; diff --git a/dmd/json.d b/dmd/json.d index 38e03e7d20d..2af7faec354 100644 --- a/dmd/json.d +++ b/dmd/json.d @@ -54,7 +54,7 @@ public: int indentLevel; const(char)[] filename; - extern (D) this(OutBuffer* buf) + extern (D) this(OutBuffer* buf) scope { this.buf = buf; } diff --git a/dmd/lambdacomp.d b/dmd/lambdacomp.d index c800273e2d4..885a27af905 100644 --- a/dmd/lambdacomp.d +++ b/dmd/lambdacomp.d @@ -120,7 +120,7 @@ public: OutBuffer buf; alias visit = SemanticTimeTransitiveVisitor.visit; - this(Scope* sc) + this(Scope* sc) scope { this.sc = sc; } diff --git a/dmd/lexer.d b/dmd/lexer.d index 9af36cd0186..81830d7307b 100644 --- a/dmd/lexer.d +++ b/dmd/lexer.d @@ -108,7 +108,7 @@ class Lexer */ this(const(char)* filename, const(char)* base, size_t begoffset, size_t endoffset, bool doDocComment, bool commentToken, - const(char)[] vendor = "DLF", uint versionNumber = 1) pure + const(char)[] vendor = "DLF", uint versionNumber = 1) pure scope { scanloc = Loc(filename, 1, 1); // debug printf("Lexer::Lexer(%p)\n", base); @@ -172,7 +172,7 @@ class Lexer /****************** * Used for unittests for a mock Lexer */ - this() { } + this() scope { } /************************************** * Reset lexer to lex #define's diff --git a/dmd/mtype.d b/dmd/mtype.d index dd1ee61fe9c..ce9272c6526 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -456,7 +456,7 @@ extern (C++) abstract class Type : ASTNode return sizeTy; }(); - final extern (D) this(TY ty) + final extern (D) this(TY ty) scope { this.ty = ty; } @@ -3120,7 +3120,7 @@ extern (C++) final class TypeBasic : Type const(char)* dstring; uint flags; - extern (D) this(TY ty) + extern (D) this(TY ty) scope { super(ty); const(char)* d; diff --git a/dmd/nogc.d b/dmd/nogc.d index 00701da2ccc..db4a6569980 100644 --- a/dmd/nogc.d +++ b/dmd/nogc.d @@ -37,7 +37,7 @@ public: bool checkOnly; // don't print errors bool err; - extern (D) this(FuncDeclaration f) + extern (D) this(FuncDeclaration f) scope { this.f = f; } diff --git a/dmd/ob.d b/dmd/ob.d index de5bccfd04e..9cff76b84aa 100644 --- a/dmd/ob.d +++ b/dmd/ob.d @@ -115,7 +115,7 @@ struct ObNode PtrVarState[] input; /// variable states on entry to exp PtrVarState[] output; /// variable states on exit to exp - this(ObNode* tryBlock) + this(ObNode* tryBlock) scope { this.tryBlock = tryBlock; } @@ -1353,7 +1353,7 @@ void genKill(ref ObState obstate, ObNode* ob) extern (D) this(void delegate(ObNode*, VarDeclaration, Expression, bool) dgWriteVar, void delegate(const ref Loc loc, ObNode* ob, VarDeclaration v, bool mutable) dgReadVar, - ObNode* ob, ref ObState obstate) + ObNode* ob, ref ObState obstate) scope { this.dgWriteVar = dgWriteVar; this.dgReadVar = dgReadVar; @@ -2058,7 +2058,7 @@ void checkObErrors(ref ObState obstate) extern (D) this(void delegate(const ref Loc loc, ObNode* ob, VarDeclaration v, bool mutable, PtrVarState[]) dgReadVar, void delegate(ObNode*, PtrVarState[], VarDeclaration, Expression) dgWriteVar, - PtrVarState[] cpvs, ObNode* ob, ref ObState obstate) + PtrVarState[] cpvs, ObNode* ob, ref ObState obstate) scope { this.dgReadVar = dgReadVar; this.dgWriteVar = dgWriteVar; diff --git a/dmd/parse.d b/dmd/parse.d index ddf1e824a75..c233016d220 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -51,7 +51,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer * Input: * loc location in source file of mixin */ - extern (D) this(const ref Loc loc, AST.Module _module, const(char)[] input, bool doDocComment) + extern (D) this(const ref Loc loc, AST.Module _module, const(char)[] input, bool doDocComment) scope { super(_module ? _module.srcfile.toChars() : null, input.ptr, 0, input.length, doDocComment, false, global.vendor, global.versionNumber()); @@ -75,7 +75,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer //nextToken(); // start up the scanner } - extern (D) this(AST.Module _module, const(char)[] input, bool doDocComment) + extern (D) this(AST.Module _module, const(char)[] input, bool doDocComment) scope { super(_module ? _module.srcfile.toChars() : null, input.ptr, 0, input.length, doDocComment, false, global.vendor, global.versionNumber()); diff --git a/dmd/printast.d b/dmd/printast.d index 00a54578639..d85105d6f20 100644 --- a/dmd/printast.d +++ b/dmd/printast.d @@ -39,7 +39,7 @@ extern (C++) final class PrintASTVisitor : Visitor int indent; - extern (D) this(int indent) + extern (D) this(int indent) scope { this.indent = indent; } diff --git a/dmd/root/aav.d b/dmd/root/aav.d index 42d13994126..1d450505a4d 100644 --- a/dmd/root/aav.d +++ b/dmd/root/aav.d @@ -149,7 +149,7 @@ private struct AARange(K,V) size_t bIndex; aaA* current; - this(AA* aa) pure nothrow @nogc + this(AA* aa) pure nothrow @nogc scope { if (aa) { diff --git a/dmd/root/array.d b/dmd/root/array.d index 192d86e80dd..541a12d9e1d 100644 --- a/dmd/root/array.d +++ b/dmd/root/array.d @@ -41,7 +41,7 @@ public: * Params: * dim = initial length of array */ - this(size_t dim) pure nothrow + this(size_t dim) pure nothrow scope { reserve(dim); this.length = dim; diff --git a/dmd/root/rootobject.d b/dmd/root/rootobject.d index 4437d1622e4..7138841caa0 100644 --- a/dmd/root/rootobject.d +++ b/dmd/root/rootobject.d @@ -38,7 +38,7 @@ enum DYNCAST : int extern (C++) class RootObject { - this() nothrow pure @nogc @safe + this() nothrow pure @nogc @safe scope { } diff --git a/dmd/sapply.d b/dmd/sapply.d index 848602897b9..ef0151656b1 100644 --- a/dmd/sapply.d +++ b/dmd/sapply.d @@ -37,7 +37,7 @@ private extern (C++) final class PostorderStatementVisitor : StoppableVisitor public: StoppableVisitor v; - extern (D) this(StoppableVisitor v) + extern (D) this(StoppableVisitor v) scope { this.v = v; } diff --git a/dmd/semantic2.d b/dmd/semantic2.d index 251134cdab2..440e4cbc8e7 100644 --- a/dmd/semantic2.d +++ b/dmd/semantic2.d @@ -83,7 +83,7 @@ private extern(C++) final class Semantic2Visitor : Visitor { alias visit = Visitor.visit; Scope* sc; - this(Scope* sc) + this(Scope* sc) scope { this.sc = sc; } diff --git a/dmd/semantic3.d b/dmd/semantic3.d index 2785cd6d41a..981e2d16f12 100644 --- a/dmd/semantic3.d +++ b/dmd/semantic3.d @@ -88,7 +88,7 @@ private extern(C++) final class Semantic3Visitor : Visitor alias visit = Visitor.visit; Scope* sc; - this(Scope* sc) + this(Scope* sc) scope { this.sc = sc; } @@ -1599,7 +1599,7 @@ private struct FuncDeclSem3 // Scope of analysis Scope* sc; - this(FuncDeclaration fd,Scope* s) + this(FuncDeclaration fd,Scope* s) scope { funcdecl = fd; sc = s; diff --git a/dmd/sideeffect.d b/dmd/sideeffect.d index ed938762bab..60a74cc2812 100644 --- a/dmd/sideeffect.d +++ b/dmd/sideeffect.d @@ -37,7 +37,7 @@ extern (C++) bool isTrivialExp(Expression e) { alias visit = typeof(super).visit; public: - extern (D) this() + extern (D) this() scope { } @@ -75,7 +75,7 @@ extern (C++) bool hasSideEffect(Expression e, bool assumeImpureCalls = false) { alias visit = typeof(super).visit; public: - extern (D) this() + extern (D) this() scope { } diff --git a/dmd/statementsem.d b/dmd/statementsem.d index 38ae8585f7b..20eb3c03fb5 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -160,7 +160,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor Statement result; Scope* sc; - this(Scope* sc) + this(Scope* sc) scope { this.sc = sc; } diff --git a/dmd/templateparamsem.d b/dmd/templateparamsem.d index 432daeea5c7..1a9d2520c84 100644 --- a/dmd/templateparamsem.d +++ b/dmd/templateparamsem.d @@ -50,7 +50,7 @@ private extern (C++) final class TemplateParameterSemanticVisitor : Visitor TemplateParameters* parameters; bool result; - this(Scope* sc, TemplateParameters* parameters) + this(Scope* sc, TemplateParameters* parameters) scope { this.sc = sc; this.parameters = parameters; diff --git a/dmd/traits.d b/dmd/traits.d index e4eaa9c596e..de0129b5b33 100644 --- a/dmd/traits.d +++ b/dmd/traits.d @@ -122,7 +122,7 @@ ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data) { alias visit = Visitor.visit; public: - extern (D) this(Array!(ulong)* _data, ulong _sz_size_t) + extern (D) this(Array!(ulong)* _data, ulong _sz_size_t) scope { this.data = _data; this.sz_size_t = _sz_size_t; diff --git a/dmd/visitor.d b/dmd/visitor.d index e4c2a91e7f7..8990ce49a2a 100644 --- a/dmd/visitor.d +++ b/dmd/visitor.d @@ -248,7 +248,7 @@ extern (C++) class StoppableVisitor : Visitor public: bool stop; - final extern (D) this() + final extern (D) this() scope { } } From 6a19acaf59f8484164c8f44c19d4e1fa586e0eb7 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 7 Feb 2023 16:26:22 -0800 Subject: [PATCH 071/177] fix Issue 15985 - [REG2.068/2.069] Code doesn't link unless compiled with -debug (dlang/dmd!14855) --- dmd/dtemplate.d | 3 +-- tests/dmd/runnable/test15985.d | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 tests/dmd/runnable/test15985.d diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 763a46d2a91..2336c6951fc 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -6263,12 +6263,11 @@ extern (C++) class TemplateInstance : ScopeDsymbol //printf("needsCodegen() %s\n", toChars()); // minst is finalized after the 1st invocation. - // tnext and tinst are only needed for the 1st invocation and + // tnext is only needed for the 1st invocation and // cleared for further invocations. TemplateInstance tnext = this.tnext; TemplateInstance tinst = this.tinst; this.tnext = null; - this.tinst = null; // Don't do codegen if the instance has errors, // is a dummy instance (see evaluateConstraint), diff --git a/tests/dmd/runnable/test15985.d b/tests/dmd/runnable/test15985.d new file mode 100644 index 00000000000..dbf4f4b9817 --- /dev/null +++ b/tests/dmd/runnable/test15985.d @@ -0,0 +1,18 @@ +/* PERMUTE_ARGS: -allinst + */ + +// https://issues.dlang.org/show_bug.cgi?id=15985 + +void ff()() +{ + gg!()(); + hh!()(); +} + +void gg()() { ff!()(); } +void hh()() { ff!()(); } + +enum x = is(typeof(ff!()())); +alias my_g = gg!(); + +int main() { return 0; } From 0b215ec11eb799a0d4330f2322a1c928353f9b12 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 7 Feb 2023 16:27:41 -0800 Subject: [PATCH 072/177] fix Issue 23545 - export int a; should generate dllexport, not dllimport (dlang/dmd!14680) --- dmd/declaration.d | 14 +++++++++++--- tests/dmd/dshell/dll.d | 5 ++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/dmd/declaration.d b/dmd/declaration.d index fac8ba10209..e8d8465a9fa 100644 --- a/dmd/declaration.d +++ b/dmd/declaration.d @@ -1314,9 +1314,17 @@ extern (C++) class VarDeclaration : Declaration override final bool isImportedSymbol() const { - if (visibility.kind == Visibility.Kind.export_ && !_init && (storage_class & STC.static_ || parent.isModule())) - return true; - return false; + /* If global variable has `export` and `extern` then it is imported + * export int sym1; // definition: exported + * export extern int sym2; // declaration: imported + * export extern int sym3 = 0; // error, extern cannot have initializer + */ + bool result = + visibility.kind == Visibility.Kind.export_ && + storage_class & STC.extern_ && + (storage_class & STC.static_ || parent.isModule()); + //printf("isImportedSymbol() %s %d\n", toChars(), result); + return result; } final bool isCtorinit() const pure nothrow @nogc @safe diff --git a/tests/dmd/dshell/dll.d b/tests/dmd/dshell/dll.d index 71b2c04ed30..d7d06e88306 100644 --- a/tests/dmd/dshell/dll.d +++ b/tests/dmd/dshell/dll.d @@ -6,8 +6,11 @@ int main() return DISABLED; version (DigitalMars) - version (OSX) // Shared libraries are not yet supported on OSX + { +// Disable DM Dlls for now, need to redesign it +// version (OSX) // Shared libraries are not yet supported on OSX return DISABLED; + } Vars.set(`SRC`, `$EXTRA_FILES/dll`); Vars.set(`EXE_NAME`, `$OUTPUT_BASE/testdll$EXE`); From 28d4c1ca7e8cd52ac73fb29f72b0e3508ad456df Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 8 Feb 2023 23:29:07 -0800 Subject: [PATCH 073/177] fix Issue 23145 - Stack allocation of scope new variables defeats @safe (dlang/dmd!14175) --- dmd/clone.d | 7 +++--- dmd/dsymbolsem.d | 25 ++++++++++++++++---- dmd/func.d | 3 ++- dmd/nogc.d | 3 +++ tests/dmd/compilable/test23145.d | 39 ++++++++++++++++++++++++++++++++ tests/dmd/runnable/auto1.d | 8 +++---- tests/dmd/runnable/cppdtor.d | 26 ++++++++++----------- tests/dmd/runnable/mixin2.d | 4 ++-- tests/dmd/runnable/test20855.d | 4 ++-- tests/dmd/runnable/test23.d | 12 +++++----- tests/dmd/runnable/test8.d | 4 ++-- tests/dmd/runnable/testdstress.d | 2 +- tests/dmd/runnable_cxx/cppa.d | 8 +++---- 13 files changed, 103 insertions(+), 42 deletions(-) create mode 100644 tests/dmd/compilable/test23145.d diff --git a/dmd/clone.d b/dmd/clone.d index ef5464d75e0..7f6ae21b971 100644 --- a/dmd/clone.d +++ b/dmd/clone.d @@ -1065,7 +1065,7 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara { auto cldec = ad.isClassDeclaration(); if (!cldec || cldec.cppDtorVtblIndex == -1) // scalar deleting dtor not built for non-virtual dtors - return dtor; + return dtor; // perhaps also do this if STC.scope_ is set // generate deleting C++ destructor corresponding to: // void* C::~C(int del) @@ -1077,8 +1077,9 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara Parameter delparam = new Parameter(STC.undefined_, Type.tuns32, Identifier.idPool("del"), new IntegerExp(dtor.loc, 0, Type.tuns32), null); Parameters* params = new Parameters; params.push(delparam); - auto ftype = new TypeFunction(ParameterList(params), Type.tvoidptr, LINK.cpp, dtor.storage_class); - auto func = new DtorDeclaration(dtor.loc, dtor.loc, dtor.storage_class, Id.cppdtor); + const stc = dtor.storage_class & ~STC.scope_; // because we add the `return this;` later + auto ftype = new TypeFunction(ParameterList(params), Type.tvoidptr, LINK.cpp, stc); + auto func = new DtorDeclaration(dtor.loc, dtor.loc, stc, Id.cppdtor); func.type = ftype; // Always generate the function with body, because it is not exported from DLLs. diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index d66602d0914..c9fb5692c7a 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -1090,9 +1090,26 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor ex = (cast(AssignExp)ex).e2; if (auto ne = ex.isNewExp()) { - // See if initializer is a NewExp that can be allocated on the stack + /* See if initializer is a NewExp that can be allocated on the stack. + */ if (dsym.type.toBasetype().ty == Tclass) { + /* Unsafe to allocate on stack if constructor is not `scope` because the `this` can leak. + * https://issues.dlang.org/show_bug.cgi?id=23145 + */ + if (ne.member && !(ne.member.storage_class & STC.scope_)) + { + if (sc.func.isSafe()) + { + // @@@DEPRECATED_2.112@@@ + deprecation(dsym.loc, + "`scope` allocation of `%s` requires that constructor be annotated with `scope`", + dsym.toChars()); + deprecationSupplemental(ne.member.loc, "is the location of the constructor"); + } + else + sc.func.setUnsafe(); + } ne.onstack = 1; dsym.onstack = true; } @@ -4199,8 +4216,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor override void visit(DtorDeclaration dd) { - //printf("DtorDeclaration::semantic() %s\n", toChars()); - //printf("ident: %s, %s, %p, %p\n", ident.toChars(), Id.dtor.toChars(), ident, Id.dtor); + //printf("DtorDeclaration::semantic() %s\n", dd.toChars()); + //printf("ident: %s, %s, %p, %p\n", dd.ident.toChars(), Id.dtor.toChars(), dd.ident, Id.dtor); if (dd.semanticRun >= PASS.semanticdone) return; if (dd._scope) @@ -5342,7 +5359,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor // is less strict (e.g. `preview=dtorfields` might introduce a call to a less qualified dtor) auto ctor = new CtorDeclaration(cldec.loc, Loc.initial, 0, tf); - ctor.storage_class |= STC.inference; + ctor.storage_class |= STC.inference | (fd.storage_class & STC.scope_); ctor.isGenerated = true; ctor.fbody = new CompoundStatement(Loc.initial, new Statements()); diff --git a/dmd/func.d b/dmd/func.d index 5e2ee758087..a5b619403f5 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -2320,6 +2320,7 @@ extern (C++) class FuncDeclaration : Declaration * base.in(); * assert(false, "Logic error: " ~ thr.msg); * } + * } */ foreach (fdv; foverrides) @@ -3861,7 +3862,7 @@ extern (C++) final class CtorDeclaration : FuncDeclaration { super(loc, endloc, Id.ctor, stc, type); this.isCpCtor = isCpCtor; - //printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars()); + //printf("CtorDeclaration(loc = %s) %s %p\n", loc.toChars(), toChars(), this); } override CtorDeclaration syntaxCopy(Dsymbol s) diff --git a/dmd/nogc.d b/dmd/nogc.d index db4a6569980..197d659f4a4 100644 --- a/dmd/nogc.d +++ b/dmd/nogc.d @@ -13,11 +13,14 @@ module dmd.nogc; +import core.stdc.stdio; + import dmd.aggregate; import dmd.apply; import dmd.astenums; import dmd.declaration; import dmd.dscope; +import dmd.errors; import dmd.expression; import dmd.func; import dmd.globals; diff --git a/tests/dmd/compilable/test23145.d b/tests/dmd/compilable/test23145.d new file mode 100644 index 00000000000..45235dc5284 --- /dev/null +++ b/tests/dmd/compilable/test23145.d @@ -0,0 +1,39 @@ +/* TEST_OUTPUT: +--- +compilable/test23145.d(117): Deprecation: `scope` allocation of `c` requires that constructor be annotated with `scope` +compilable/test23145.d(111): is the location of the constructor +compilable/test23145.d(124): Deprecation: `scope` allocation of `c` requires that constructor be annotated with `scope` +compilable/test23145.d(111): is the location of the constructor +--- +*/ + +// https://issues.dlang.org/show_bug.cgi?id=23145 + +#line 100 + +class D +{ + C c; +} + +class C +{ + D d; + int x=3; + this(int i) scope @safe @nogc; + this(D d) @safe @nogc; +} + +C foo(D d)@nogc @safe +{ + scope e = new C(1); // ok + scope c = new C(d); // deprecation + return c.d.c; +} + +C bax(D d) @safe +{ + scope e = new C(1); // ok + scope c = new C(d); // deprecation + return c.d.c; +} diff --git a/tests/dmd/runnable/auto1.d b/tests/dmd/runnable/auto1.d index 6ee075089d1..af95545ccc9 100644 --- a/tests/dmd/runnable/auto1.d +++ b/tests/dmd/runnable/auto1.d @@ -67,13 +67,13 @@ int ax; class A2 { - this() + this() scope { printf("A2.this()\n"); ax += 1; } - ~this() + ~this() scope { printf("A2.~this()\n"); ax += 1000; @@ -102,12 +102,12 @@ class Parent3 class Child3 : Parent3 { - this(){ + this() scope { assert(status3==0); status3=1; } - ~this(){ + ~this() scope { assert(status3==1); status3=2; } diff --git a/tests/dmd/runnable/cppdtor.d b/tests/dmd/runnable/cppdtor.d index 0592d448b1f..711f309b7a2 100644 --- a/tests/dmd/runnable/cppdtor.d +++ b/tests/dmd/runnable/cppdtor.d @@ -38,12 +38,12 @@ extern (C) int printf(scope const char*, ...); extern (C++) class CppA { int num; - this(int num) + this(int num) scope { this.num = num; } - ~this() + ~this() scope { printf("%d: CppA.~this\n", num); } @@ -51,12 +51,12 @@ extern (C++) class CppA extern (C++) class CppB : CppA { - this(int num) + this(int num) scope { super(num); } - ~this() + ~this() scope { printf("%d: CppB.~this\n", num); } @@ -64,12 +64,12 @@ extern (C++) class CppB : CppA extern (C++) class CppC : CppB { - this(int num) + this(int num) scope { super(num); } - ~this() + ~this() scope { printf("%d: CppC.~this\n", num); } @@ -78,12 +78,12 @@ extern (C++) class CppC : CppB extern (D) class DA { int num; - this(int num) + this(int num) scope { this.num = num; } - ~this() + ~this() scope { printf("%d: DA.~this\n", num); } @@ -91,12 +91,12 @@ extern (D) class DA extern (D) class DB : DA { - this(int num) + this(int num) scope { super(num); } - ~this() + ~this() scope { printf("%d: DB.~this\n", num); } @@ -104,12 +104,12 @@ extern (D) class DB : DA extern (D) class DC : DB { - this(int num) + this(int num) scope { super(num); } - ~this() + ~this() scope { printf("%d: DC.~this\n", num); } @@ -118,7 +118,7 @@ extern (D) class DC : DB extern (C++) class CppNoDestruct { int num; - this(int num) + this(int num) scope { this.num = num; } diff --git a/tests/dmd/runnable/mixin2.d b/tests/dmd/runnable/mixin2.d index 7679bbe5b34..70bf051a46f 100644 --- a/tests/dmd/runnable/mixin2.d +++ b/tests/dmd/runnable/mixin2.d @@ -82,13 +82,13 @@ int x5; class Foo5 { - this () + this () scope { printf ("Constructor\n"); assert(x5 == 0); x5++; } - ~this () + ~this () scope { printf ("Destructor\n"); assert(x5 == 2); diff --git a/tests/dmd/runnable/test20855.d b/tests/dmd/runnable/test20855.d index 30152fe3914..1d2ae50919a 100644 --- a/tests/dmd/runnable/test20855.d +++ b/tests/dmd/runnable/test20855.d @@ -4,7 +4,7 @@ string exp() { string s = "a = b + c * d + a;"; - foreach (i; 0 .. 9) + foreach (i; 0 .. 8) s = s ~ s; return s; } @@ -22,6 +22,6 @@ int main() { int a = test(); printf("a = %d\n", a); - assert(test() == 7169); + assert(test() == 3585); return 0; } diff --git a/tests/dmd/runnable/test23.d b/tests/dmd/runnable/test23.d index f1fd4a6c2bc..cb951c17faa 100644 --- a/tests/dmd/runnable/test23.d +++ b/tests/dmd/runnable/test23.d @@ -1322,22 +1322,22 @@ void test70() class C71 { static int cnt; - this() { printf("C()\n"); cnt++; } - ~this() { printf("~C()\n"); cnt--; } + this() scope { printf("C()\n"); cnt++; } + ~this() scope { printf("~C()\n"); cnt--; } } class D71 { static int cnt; - this() { printf("D()\n"); cnt++; } - ~this() { printf("~D()\n"); cnt--; } + this() scope { printf("D()\n"); cnt++; } + ~this() scope { printf("~D()\n"); cnt--; } } class E71 { static int cnt; - this() { printf("E()\n"); cnt++; } - ~this() { printf("~E()\n"); cnt--; } + this() scope { printf("E()\n"); cnt++; } + ~this() scope { printf("~E()\n"); cnt--; } } void test71() diff --git a/tests/dmd/runnable/test8.d b/tests/dmd/runnable/test8.d index d65ba0eb7ad..f10076223d5 100644 --- a/tests/dmd/runnable/test8.d +++ b/tests/dmd/runnable/test8.d @@ -786,8 +786,8 @@ void test42() int x44; class A44 { - this() { printf("A44 ctor\n"); x44 += 1; } - ~this() { printf("A44 dtor\n"); x44 += 0x100; } + this() scope { printf("A44 ctor\n"); x44 += 1; } + ~this() scope { printf("A44 dtor\n"); x44 += 0x100; } } class B44 : A44 { } diff --git a/tests/dmd/runnable/testdstress.d b/tests/dmd/runnable/testdstress.d index 03af20710f2..269949fb0c0 100644 --- a/tests/dmd/runnable/testdstress.d +++ b/tests/dmd/runnable/testdstress.d @@ -494,7 +494,7 @@ void test23() int status24; class C24{ - this(){ + this() scope { assert(status24==0); status24+=2; } diff --git a/tests/dmd/runnable_cxx/cppa.d b/tests/dmd/runnable_cxx/cppa.d index 398158ed366..cb268af0622 100644 --- a/tests/dmd/runnable_cxx/cppa.d +++ b/tests/dmd/runnable_cxx/cppa.d @@ -1324,7 +1324,7 @@ extern(C++) class Cpp15589Derived : Cpp15589Base { public: - this(); + this() scope; final ~this(); int b; } @@ -1334,7 +1334,7 @@ extern(C++) public: void beforeDtor(); - this(); + this() scope; ~this(); void afterDtor(); @@ -1344,7 +1344,7 @@ extern(C++) class Cpp15589DerivedVirtual : Cpp15589BaseVirtual { public: - this(); + this() scope; ~this(); override void afterDtor(); @@ -1355,7 +1355,7 @@ extern(C++) class Cpp15589IntroducingVirtual : Cpp15589Base { public: - this(); + this() scope; void beforeIntroducedVirtual(); ~this(); void afterIntroducedVirtual(int); From 7db0ad0377040d6090ea19fe4b89dc6c7b275c67 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 8 Feb 2023 23:39:00 -0800 Subject: [PATCH 074/177] fix Issue 23195 - Win64 function ABI bug for small non-POD arguments (dlang/dmd!14651) --- dmd/dstruct.d | 10 ++++ dmd/frontend.h | 1 + tests/dmd/runnable_cxx/cpp_abi_tests.d | 48 +++++++++++++++++++ .../extra-files/cpp_abi_tests.cpp | 26 ++++++++++ 4 files changed, 85 insertions(+) diff --git a/dmd/dstruct.d b/dmd/dstruct.d index 6ab93d4c39c..3d893266bcc 100644 --- a/dmd/dstruct.d +++ b/dmd/dstruct.d @@ -480,6 +480,16 @@ extern (C++) class StructDeclaration : AggregateDeclaration return (ispod == ThreeState.yes); } + /*************************************** + * Determine if struct has copy construction (copy constructor or postblit) + * Returns: + * true if struct has copy construction + */ + final bool hasCopyConstruction() + { + return postblit || hasCopyCtor; + } + override final inout(StructDeclaration) isStructDeclaration() inout @nogc nothrow pure @safe { return this; diff --git a/dmd/frontend.h b/dmd/frontend.h index 68fa060897e..fc733316545 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -6532,6 +6532,7 @@ class StructDeclaration : public AggregateDeclaration const char* kind() const override; void finalizeSize() final override; bool isPOD(); + bool hasCopyConstruction(); StructDeclaration* isStructDeclaration() final override; void accept(Visitor* v) override; uint32_t numArgTypes() const; diff --git a/tests/dmd/runnable_cxx/cpp_abi_tests.d b/tests/dmd/runnable_cxx/cpp_abi_tests.d index c677d6e0be8..c0f4e6dd780 100644 --- a/tests/dmd/runnable_cxx/cpp_abi_tests.d +++ b/tests/dmd/runnable_cxx/cpp_abi_tests.d @@ -207,6 +207,8 @@ extern(C++, `ns1`) extern(C++) { + // https://issues.dlang.org/show_bug.cgi?id=19563 + struct SmallStruct { int i; @@ -220,6 +222,50 @@ extern(C++) } } +/*********************************************/ +// https://issues.dlang.org/show_bug.cgi?id=23195 + +extern (C++) +{ + struct FF + { + float x, y; + + ~this() { } + } + + float draw(FF min, FF max); + + void test23195() + { + FF a = { 1, 2 }; + FF b = { 3, 4 }; + float f = draw(a, b); + assert(f == 1234); + } + + /*********************/ + + struct FF2 + { + float x, y; + + this(int i) { } + } + + float draw2(FF2 min, FF2 max); + + void test23195_2() + { + FF2 a; a.x = 1; a.y = 2; + FF2 b; b.x = 3; b.y = 4; + float f = draw2(a, b); + assert(f == 1234); + } +} + +/*********************************************/ + void main() { foreach(bool val; values!bool()) check(val); @@ -268,4 +314,6 @@ else doConsume2(sd); assert(Sdtor.counter == 2); } + test23195(); + test23195_2(); } diff --git a/tests/dmd/runnable_cxx/extra-files/cpp_abi_tests.cpp b/tests/dmd/runnable_cxx/extra-files/cpp_abi_tests.cpp index 8ba613920a4..e1dcc28b8b1 100644 --- a/tests/dmd/runnable_cxx/extra-files/cpp_abi_tests.cpp +++ b/tests/dmd/runnable_cxx/extra-files/cpp_abi_tests.cpp @@ -161,3 +161,29 @@ void doConsume2(Sdtor& value) // fn0 passthrough_fn0 (fn0 value) { return value; } // typedef int (*fn1)(int); // fn1 passthrough_fn1 (fn1 value) { return value; } + +/******************************/ + +struct FF +{ + float x, y; + ~FF(); +}; + +float draw(FF min, FF max) +{ + return min.x * 1000 + min.y * 100 + max.x * 10 + max.y; +} + +/******************************/ + +struct FF2 +{ + float x, y; + FF2(int i) { } +}; + +float draw2(FF2 min, FF2 max) +{ + return min.x * 1000 + min.y * 100 + max.x * 10 + max.y; +} From 4e15f10dba6b2cd6b97f6562e461c6657c4c86fd Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Thu, 9 Feb 2023 01:53:43 -0800 Subject: [PATCH 075/177] fix Issue 23558 - add __traits(getModuleClasses [, module name]) (dlang/dmd!14699) --- dmd/frontend.h | 1 + dmd/id.d | 1 + dmd/traits.d | 55 +++++++++++++++++++++++++- runtime/druntime/src/object.d | 3 +- tests/dmd/compilable/test23558.d | 17 ++++++++ tests/dmd/fail_compilation/test23558.d | 16 ++++++++ 6 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 tests/dmd/compilable/test23558.d create mode 100644 tests/dmd/fail_compilation/test23558.d diff --git a/dmd/frontend.h b/dmd/frontend.h index fc733316545..b46c89b6ffc 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -8709,6 +8709,7 @@ struct Id final static Identifier* getVisibility; static Identifier* parent; static Identifier* child; + static Identifier* getModuleClasses; static Identifier* getMember; static Identifier* getOverloads; static Identifier* getVirtualFunctions; diff --git a/dmd/id.d b/dmd/id.d index ec5cb25ef28..2eed152a8a6 100644 --- a/dmd/id.d +++ b/dmd/id.d @@ -462,6 +462,7 @@ immutable Msgtable[] msgtable = { "getVisibility" }, { "parent" }, { "child" }, + { "getModuleClasses" }, { "getMember" }, { "getOverloads" }, { "getVirtualFunctions" }, diff --git a/dmd/traits.d b/dmd/traits.d index de0129b5b33..3e5ff159645 100644 --- a/dmd/traits.d +++ b/dmd/traits.d @@ -14,6 +14,7 @@ module dmd.traits; import core.stdc.stdio; +import core.stdc.string; import dmd.aggregate; import dmd.arraytypes; @@ -743,6 +744,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc) auto se = new StringExp(e.loc, id.toString()); return se.expressionSemantic(sc); } + if (e.ident == Id.fullyQualifiedName) // https://dlang.org/spec/traits.html#fullyQualifiedName { if (dim != 1) @@ -779,6 +781,56 @@ Expression semanticTraits(TraitsExp e, Scope* sc) return se.expressionSemantic(sc); } + + if (e.ident == Id.getModuleClasses) + { + /* https://dlang.org/spec/traits.html#getModuleClasses + */ + Module m; + if (dim == 0) + { + m = sc._module; // default to current module + if (!m) + return False(); + } + else if (dim == 1) + { + auto o = (*e.args)[0]; + auto s = getDsymbol(o); + if (s) + { + if (auto imp = s.isImport()) + m = imp.mod; + else + m = s.isModule(); + } + if (!m) + { + e.error("in expression `%s` `%s` must be a module", e.toChars(), o.toChars()); + return ErrorExp.get(); + } + } + else + return dimError(0); + + ClassDeclarations aclasses; + getLocalClasses(m, aclasses); + + auto exps = new Expressions(aclasses.length); + foreach (i, cd; aclasses) + { + const p = cd.toPrettyChars(); + //printf("class %s\n", p); + const s = p[0 .. strlen(p)]; + auto se = new StringExp(e.loc, s); + (*exps)[i] = se; + } + + Expression ex = new TupleExp(e.loc, exps); + ex = ex.expressionSemantic(sc); + return ex; + } + if (e.ident == Id.getProtection || e.ident == Id.getVisibility) { if (dim != 1) @@ -2244,7 +2296,7 @@ private void traitNotFound(TraitsExp e) initialized = true; // lazy initialization // All possible traits - __gshared Identifier*[59] idents = + __gshared Identifier*[60] idents = [ &Id.isAbstractClass, &Id.isArithmetic, @@ -2281,6 +2333,7 @@ private void traitNotFound(TraitsExp e) &Id.child, &Id.getLinkage, &Id.getMember, + &Id.getModuleClasses, &Id.getOverloads, &Id.getVirtualFunctions, &Id.getVirtualMethods, diff --git a/runtime/druntime/src/object.d b/runtime/druntime/src/object.d index 56e01ace2cb..25347020612 100644 --- a/runtime/druntime/src/object.d +++ b/runtime/druntime/src/object.d @@ -246,7 +246,8 @@ class Object * } * --- */ - deprecated static Object factory(string classname) + deprecated("use __traits(getModuleClasses) instead") + static Object factory(string classname) { auto ci = TypeInfo_Class.find(classname); if (ci) diff --git a/tests/dmd/compilable/test23558.d b/tests/dmd/compilable/test23558.d new file mode 100644 index 00000000000..c5942fae246 --- /dev/null +++ b/tests/dmd/compilable/test23558.d @@ -0,0 +1,17 @@ +/* TEST_OUTPUT: +--- +getModuleClasses: tuple("test23558.C") +getModuleClasses: tuple("std.stdio.StdioException") +--- +*/ + +// https://issues.dlang.org/show_bug.cgi?id=23558 + +import std.stdio; + +class C { } + +pragma(msg, "getModuleClasses: ", __traits(getModuleClasses)); +pragma(msg, "getModuleClasses: ", __traits(getModuleClasses, std.stdio)); + +//pragma(msg, "getClassInfos: ", __traits(getModuleClasses, 3)); diff --git a/tests/dmd/fail_compilation/test23558.d b/tests/dmd/fail_compilation/test23558.d new file mode 100644 index 00000000000..2c6048f698d --- /dev/null +++ b/tests/dmd/fail_compilation/test23558.d @@ -0,0 +1,16 @@ +/* TEST_OUTPUT: +--- +fail_compilation/test23558.d(103): Error: in expression `__traits(getModuleClasses, S)` `S` must be a module +fail_compilation/test23558.d(105): Error: expected 0 arguments for `getModuleClasses` but had 2 +--- + */ + +// https://issues.dlang.org/show_bug.cgi?id=23558 + +#line 100 + +struct S { } + +auto x = __traits(getModuleClasses, S); + +auto y = __traits(getModuleClasses, 1, 2); From 38073d02b36a3b7c7278019126b117d2db203bf3 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 5 Feb 2023 21:13:46 +0100 Subject: [PATCH 076/177] reapply fix Issue 23479 - ImportC recognizes .i and .c files, but not .h files --- dmd/dmodule.d | 10 +++-- dmd/file_manager.d | 75 +++++++++++++++++--------------- dmd/globals.d | 1 + dmd/mars.d | 2 + tests/dmd/compilable/test23479.h | 2 + 5 files changed, 51 insertions(+), 39 deletions(-) create mode 100644 tests/dmd/compilable/test23479.h diff --git a/dmd/dmodule.d b/dmd/dmodule.d index bb518fa081d..c1a014da3d8 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -458,6 +458,7 @@ extern (C++) final class Module : Package } else if (!FileName.equalsExt(srcfilename, mars_ext) && !FileName.equalsExt(srcfilename, hdr_ext) && + !FileName.equalsExt(srcfilename, h_ext) && !FileName.equalsExt(srcfilename, c_ext) && !FileName.equalsExt(srcfilename, i_ext) && !FileName.equalsExt(srcfilename, dd_ext)) @@ -686,7 +687,8 @@ extern (C++) final class Module : Package } if (global.preprocess && - FileName.equalsExt(srcfile.toString(), c_ext) && + (FileName.equalsExt(srcfile.toString(), c_ext) || + FileName.equalsExt(srcfile.toString(), h_ext)) && FileName.exists(srcfile.toString())) { filename = global.preprocess(srcfile, loc, ifile, &defines); // run C preprocessor @@ -759,10 +761,12 @@ extern (C++) final class Module : Package DsymbolTable dst; Package ppack = null; - /* If it has the extension ".c", it is a "C" file. + /* If it has the extension ".c" or ".h", it is a "C" file. * If it has the extension ".i", it is a preprocessed "C" file. */ - if (FileName.equalsExt(arg, c_ext) || FileName.equalsExt(arg, i_ext)) + if (FileName.equalsExt(arg, c_ext) || + FileName.equalsExt(arg, h_ext) || + FileName.equalsExt(arg, i_ext)) { filetype = FileType.c; diff --git a/dmd/file_manager.d b/dmd/file_manager.d index a0e5d0519c8..ac1c6918540 100644 --- a/dmd/file_manager.d +++ b/dmd/file_manager.d @@ -141,6 +141,15 @@ nothrow: return sd; scope(exit) FileName.free(sd.ptr); + static const(char)[] check(const(char)[] p, const(char)[] sx) + { + auto fn = FileName.combine(p, sx); + if (FileName.exists(fn)) + return fn; + FileName.free(fn.ptr); + return null; + } + if (checkLocal) { auto cached = packageStatus.lookup(filename); @@ -152,15 +161,10 @@ nothrow: * Therefore, the result should be: filename/package.d * iff filename/package.d is a file */ - const ni = FileName.combine(filename, package_di); - if (FileName.exists(ni) == 1) - return ni; - FileName.free(ni.ptr); - - const n = FileName.combine(filename, package_d); - if (FileName.exists(n) == 1) - return n; - FileName.free(n.ptr); + if (auto fn = check(filename, package_di)) + return fn; + if (auto fn = check(filename, package_d)) + return fn; } } @@ -168,29 +172,28 @@ nothrow: return null; if (!path.length) return null; + foreach (entry; path) { const p = entry.toDString(); - const(char)[] n = FileName.combine(p, sdi); - - if (!packageExists(n)) { + { + const(char)[] n = FileName.combine(p, sdi); + if (!packageExists(n)) { + FileName.free(n.ptr); + continue; // no need to check for anything else. + } + if (FileName.exists(n) == 1) { + return n; + } FileName.free(n.ptr); - continue; // no need to check for anything else. } - if (FileName.exists(n) == 1) { - return n; - } - FileName.free(n.ptr); - n = FileName.combine(p, sd); - if (FileName.exists(n) == 1) { - return n; - } - FileName.free(n.ptr); + if (auto fn = check(p, sd)) + return fn; - const b = FileName.removeExt(filename); - n = FileName.combine(p, b); + const(char)[] b = FileName.removeExt(filename); + const(char)[] n = FileName.combine(p, b); FileName.free(b.ptr); scope(exit) FileName.free(n.ptr); @@ -215,13 +218,18 @@ nothrow: } } - /* ImportC: No D modules found, now search along path[] for .i file, then .c file. + /* ImportC: No D modules found, now search along path[] for .i file, then .h file, then .c file. */ const si = FileName.forceExt(filename, i_ext); if (FileName.exists(si) == 1) return si; scope(exit) FileName.free(si.ptr); + const sh = FileName.forceExt(filename, h_ext); + if (FileName.exists(sh) == 1) + return sh; + scope(exit) FileName.free(sh.ptr); + const sc = FileName.forceExt(filename, c_ext); if (FileName.exists(sc) == 1) return sc; @@ -230,17 +238,12 @@ nothrow: { const p = entry.toDString(); - const(char)[] n = FileName.combine(p, si); - if (FileName.exists(n) == 1) { - return n; - } - FileName.free(n.ptr); - - n = FileName.combine(p, sc); - if (FileName.exists(n) == 1) { - return n; - } - FileName.free(n.ptr); + if (auto fn = check(p, si)) + return fn; + if (auto fn = check(p, sh)) + return fn; + if (auto fn = check(p, sc)) + return fn; } return null; } diff --git a/dmd/globals.d b/dmd/globals.d index e6b4e31690a..2e2a8a2e5cc 100644 --- a/dmd/globals.d +++ b/dmd/globals.d @@ -252,6 +252,7 @@ enum hdr_ext = "di"; // for D 'header' import files enum json_ext = "json"; // for JSON files enum map_ext = "map"; // for .map files enum c_ext = "c"; // for C source files +enum h_ext = "h"; // for C header source files enum i_ext = "i"; // for preprocessed C source file /** diff --git a/dmd/mars.d b/dmd/mars.d index ca0645bbf08..3c11b373d8e 100644 --- a/dmd/mars.d +++ b/dmd/mars.d @@ -2532,6 +2532,7 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param FileName.equals(ext, mars_ext) == 0 && FileName.equals(ext, hdr_ext) == 0 && FileName.equals(ext, i_ext) == 0 && + FileName.equals(ext, h_ext) == 0 && FileName.equals(ext, c_ext) == 0) { error("-run must be followed by a source file, not '%s'", arguments[i + 1]); @@ -2876,6 +2877,7 @@ Module createModule(const(char)* file, ref Strings libmodules, const ref Target if (FileName.equals(ext, mars_ext) || FileName.equals(ext, hdr_ext ) || FileName.equals(ext, dd_ext ) || + FileName.equals(ext, h_ext ) || FileName.equals(ext, c_ext ) || FileName.equals(ext, i_ext )) { diff --git a/tests/dmd/compilable/test23479.h b/tests/dmd/compilable/test23479.h new file mode 100644 index 00000000000..791e2dd399c --- /dev/null +++ b/tests/dmd/compilable/test23479.h @@ -0,0 +1,2 @@ + +int foo() { } From eaa911cc5342bbb4cdb02f3a98ff1b7e6b1d6c84 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 12 Feb 2023 15:16:45 +0100 Subject: [PATCH 077/177] fix Issue 23688 - FTBFS: error: cannot convert 'Expression' to 'Expression*' --- dmd/expression.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmd/expression.h b/dmd/expression.h index bfd595c28b2..caddb079b61 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -539,7 +539,7 @@ class NewExp final : public Expression bool onstack; // allocate on stack bool thrownew; // this NewExp is the expression of a ThrowStatement - Expression lowering; // lowered druntime hook: `_d_newclass` + Expression *lowering; // lowered druntime hook: `_d_newclass` static NewExp *create(const Loc &loc, Expression *thisexp, Type *newtype, Expressions *arguments); NewExp *syntaxCopy() override; From cd7ba0ea0e5ddf0828fdaf591eec134afbb66f0a Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sun, 12 Feb 2023 15:30:16 -0800 Subject: [PATCH 078/177] fix Issue 23682 - dip1000 problem with return by ref (dlang/dmd!14869) --- dmd/escape.d | 22 +++++++++++++++- tests/dmd/fail_compilation/retscope6.d | 36 ++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/dmd/escape.d b/dmd/escape.d index 316a55b6582..2516a09500d 100644 --- a/dmd/escape.d +++ b/dmd/escape.d @@ -1744,7 +1744,27 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re Parameter p = tf.parameterList[i - j]; const stc = tf.parameterStorageClass(null, p); ScopeRef psr = buildScopeRef(stc); - if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope) + if (psr == ScopeRef.ReturnScope) + { + if (tf.isref) + { + /* ignore `ref` on struct constructor return because + * struct S { this(return scope int* q) { this.p = q; } int* p; } + * is different from: + * ref char* front(return scope char** q) { return *q; } + * https://github.com/dlang/dmd/pull/14869 + */ + if (auto dve = e.e1.isDotVarExp()) + if (auto fd = dve.var.isFuncDeclaration()) + if (fd.isCtorDeclaration() && tf.next.toBasetype().isTypeStruct()) + { + escapeByValue(arg, er, live, retRefTransition); + } + } + else + escapeByValue(arg, er, live, retRefTransition); + } + else if (psr == ScopeRef.Ref_ReturnScope) escapeByValue(arg, er, live, retRefTransition); else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope) { diff --git a/tests/dmd/fail_compilation/retscope6.d b/tests/dmd/fail_compilation/retscope6.d index 9736d37e949..b43fc26f346 100644 --- a/tests/dmd/fail_compilation/retscope6.d +++ b/tests/dmd/fail_compilation/retscope6.d @@ -141,13 +141,14 @@ void testarchie() /* TEST_OUTPUT: --- -fail_compilation/retscope6.d(9022): Error: returning `fred(& i)` escapes a reference to local variable `i` +fail_compilation/retscope6.d(9023): Error: returning `fred(& i)` escapes a reference to local variable `i` --- */ #line 9000 -@safe: +@safe +{ alias T9 = S9!(); struct S9() { @@ -199,6 +200,7 @@ void hmac(scope ubyte[] secret) ubyte[10] buffer; secret = buffer[]; } +} /* TEST_OUTPUT: --- @@ -289,3 +291,33 @@ ref int escape23021() @safe // ensure we do not infer return ref return infer23021(nonScopePtr); // no error } + +/******************************/ + +// https://issues.dlang.org/show_bug.cgi?id=23682 + +alias VErr = char*; + +@safe ref char* front_p(return scope char** p) { return *p; } + +char* g; + +@safe void test23862() +{ + char* _errors; + g = front_p(&_errors); // should pass +} + +/*******************************************/ + +ref int* monitor(return scope Object h) pure nothrow @nogc +{ + return *cast(int**)&h.__monitor; +} + +int* getMonitor(Object h) pure @nogc +{ + return monitor(h); // should pass +} + +/*******************************************/ From 29ec7be83472d0861e085c4c0300e13d08850b79 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Fri, 14 Oct 2022 17:55:09 +0200 Subject: [PATCH 079/177] Implement named args resolution --- dmd/dtemplate.d | 2 +- dmd/expressionsem.d | 43 ++++-- dmd/func.d | 2 +- dmd/mtype.d | 136 ++++++++++++++++-- tests/dmd/compilable/named_arguments.d | 12 ++ .../fail_compilation/named_arguments_error.d | 25 ++++ .../named_arguments_overload.d | 31 ++++ .../fail_compilation/named_arguments_pragma.d | 14 ++ .../named_arguments_template.d | 10 ++ 9 files changed, 251 insertions(+), 24 deletions(-) create mode 100644 tests/dmd/compilable/named_arguments.d create mode 100644 tests/dmd/fail_compilation/named_arguments_error.d create mode 100644 tests/dmd/fail_compilation/named_arguments_overload.d create mode 100644 tests/dmd/fail_compilation/named_arguments_pragma.d create mode 100644 tests/dmd/fail_compilation/named_arguments_template.d diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 2336c6951fc..11f71529dca 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -2600,7 +2600,7 @@ extern (C++) final class TypeDeduced : Type void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, Objects* tiargs, Type tthis, Expressions* fargs, const(char)** pMessage = null) { - Expression[] fargs_ = fargs.peekSlice(); + alias fargs_ = fargs; version (none) { printf("functionResolve() dstart = %s\n", dstart.toChars()); diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index ab8fa17d611..c7c07944566 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -1403,7 +1403,10 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = if (!e1.type) { - error(loc, "cannot resolve type for %s", e1.toChars()); + if (e1.isNamedArgExp()) + error(loc, "named argument `%s` not allowed here", e1.toChars()); + else + error(loc, "cannot resolve type for %s", e1.toChars()); e1 = ErrorExp.get(); } return e1; @@ -1673,7 +1676,16 @@ private bool preFunctionParameters(Scope* sc, Identifiers* names, Expressions* e arg = ErrorExp.get(); err = true; } - (*exps)[i] = arg; + + if (ne) + { + ne.arg = arg; + (*exps)[i] = ne; + } + else + { + (*exps)[i] = arg; + } } } return err; @@ -1804,8 +1816,13 @@ private bool functionParameters(const ref Loc loc, Scope* sc, arg = inlineCopy(arg, sc); // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__ arg = arg.resolveLoc(loc, sc); - arguments.push(arg); - nargs++; + if (i >= nargs) + { + arguments.push(arg); + nargs++; + } + else + (*arguments)[i] = arg; } else { @@ -5073,8 +5090,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } const(char)* failMessage; - Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null; - if (!tf.callMatch(null, fargs, 0, &failMessage, sc)) + if (!tf.callMatch(null, exp.arguments, 0, &failMessage, sc)) { OutBuffer buf; buf.writeByte('('); @@ -5147,8 +5163,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor exp.f = exp.f.toAliasFunc(); TypeFunction tf = cast(TypeFunction)exp.f.type; const(char)* failMessage; - Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null; - if (!tf.callMatch(null, fargs, 0, &failMessage, sc)) + if (!tf.callMatch(null, exp.arguments, 0, &failMessage, sc)) { OutBuffer buf; buf.writeByte('('); @@ -12489,6 +12504,18 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor result = e; } + + override void visit(NamedArgExp e) + { + //printf("NamedArgExp::semantic('%s')\n", e.toChars()); + if (e.arg.dyncast() == DYNCAST.expression) + { + e.arg = expressionSemantic(cast(Expression) e.arg, sc); + e.type = (cast(Expression) e.arg).type; + } + + result = e; + } } /********************************** diff --git a/dmd/func.d b/dmd/func.d index a5b619403f5..93903306769 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -1089,7 +1089,7 @@ extern (C++) class FuncDeclaration : Declaration args.push(e); } - MATCH m = tg.callMatch(null, args[], 1); + MATCH m = tg.callMatch(null, &args, 1); if (m > MATCH.nomatch) { /* A variadic parameter list is less specialized than a diff --git a/dmd/mtype.d b/dmd/mtype.d index ce9272c6526..b5dd614e9b3 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -4626,14 +4626,14 @@ extern (C++) final class TypeFunction : TypeNext * Determine match level. * Params: * tthis = type of `this` pointer, null if not member function - * args = array of function arguments + * inArgs = array of function arguments. In case of a match, gets reordered based on named arguments. * flag = 1: performing a partial ordering match * pMessage = address to store error message, or null * sc = context * Returns: * MATCHxxxx */ - extern (D) MATCH callMatch(Type tthis, Expression[] args, int flag = 0, const(char)** pMessage = null, Scope* sc = null) + extern (D) MATCH callMatch(Type tthis, Expressions* inArgs, int flag = 0, const(char)** pMessage = null, Scope* sc = null) { //printf("TypeFunction::callMatch() %s\n", toChars()); MATCH match = MATCH.exact; // assume exact match @@ -4669,8 +4669,9 @@ extern (C++) final class TypeFunction : TypeNext } const nparams = parameterList.length; - const nargs = args.length; - if (nargs > nparams) + Expression[] args = inArgs ? (*inArgs)[] : null; + + if (args.length > nparams) { if (parameterList.varargs == VarArg.none) { @@ -4684,22 +4685,33 @@ extern (C++) final class TypeFunction : TypeNext } // https://issues.dlang.org/show_bug.cgi?id=22997 - if (parameterList.varargs == VarArg.none && nparams > nargs && !parameterList[nargs].defaultArg) + if (parameterList.varargs == VarArg.none && nparams > args.length && !parameterList[args.length].defaultArg) { OutBuffer buf; - buf.printf("too few arguments, expected %d, got %d", cast(int)nparams, cast(int)nargs); + buf.printf("too few arguments, expected `%d`, got `%d`", cast(int)nparams, cast(int)args.length); if (pMessage) *pMessage = buf.extractChars(); return MATCH.nomatch; } + if (!resolveNamedArgs(args, pMessage)) + { + if (!pMessage || *pMessage) + return MATCH.nomatch; + + // if no message was provided, it was because of overflow which will be diagnosed below + match = MATCH.nomatch; + } + foreach (u, p; parameterList) { - if (u == nargs) + if (u >= args.length) break; Expression arg = args[u]; - assert(arg); + if (!arg) + continue; // default argument + Type tprm = p.type; Type targ = arg.type; @@ -4733,10 +4745,11 @@ extern (C++) final class TypeFunction : TypeNext assert(p); // One or more arguments remain - if (u < nargs) + if (u < args.length) { Expression arg = args[u]; - assert(arg); + if (!arg) + continue; // default argument m = argumentMatchParameter(this, p, arg, wildmatch, flag, sc, pMessage); } else if (p.defaultArg) @@ -4745,7 +4758,7 @@ extern (C++) final class TypeFunction : TypeNext /* prefer matching the element type rather than the array * type when more arguments are present with T[]... */ - if (parameterList.varargs == VarArg.typesafe && u + 1 == nparams && nargs > nparams) + if (parameterList.varargs == VarArg.typesafe && u + 1 == nparams && args.length > nparams) goto L1; //printf("\tm = %d\n", m); @@ -4760,7 +4773,7 @@ extern (C++) final class TypeFunction : TypeNext // Error message was already generated in `matchTypeSafeVarArgs` return MATCH.nomatch; } - if (pMessage && u >= nargs) + if (pMessage && u >= args.length) *pMessage = getMatchError("missing argument for parameter #%d: `%s`", u + 1, parameterToChars(p, this, false)); // If an error happened previously, `pMessage` was already filled @@ -4773,16 +4786,100 @@ extern (C++) final class TypeFunction : TypeNext match = m; // pick worst match } - if (pMessage && !parameterList.varargs && nargs > nparams) + if (pMessage && !parameterList.varargs && args.length > nparams) { // all parameters had a match, but there are surplus args - *pMessage = getMatchError("expected %d argument(s), not %d", nparams, nargs); + *pMessage = getMatchError("expected %d argument(s), not %d", nparams, args.length); return MATCH.nomatch; } //printf("match = %d\n", match); + if (inArgs) + { + inArgs.setDim(0); + inArgs.pushSlice(args[]); + } return match; } + /******************************** + * Re-order `args` based on named arguments it contains + * + * Params: + * args = array of function arguments. + * pMessage = address to store error message, or null + * Returns: true on success, false on error + */ + private extern(D) bool resolveNamedArgs(ref Expression[] args, const(char)** pMessage) + { + auto newArgs = new Expression[parameterList.length]; + size_t ci = 0; + bool hasNamedArgs = false; + foreach (arg; args) + { + if (!arg) + { + ci++; + continue; + } + if (auto ne = arg.isNamedArgExp()) + { + hasNamedArgs = true; + const pi = parameterIndex(ne.ident); + if (pi == -1) + { + if (pMessage) + *pMessage = getMatchError("no parameter named `%s`", ne.ident.toChars()); + return false; + } + ci = pi; + arg = cast(Expression) ne.arg; + } + if (ci >= newArgs.length) + { + newArgs.length = ci + 1; + if (!parameterList.varargs) + { + // Without named args, let the caller diagnose argument overflow + if (hasNamedArgs && pMessage) + *pMessage = getMatchError("argument `%s` goes past end of parameter list", arg.toChars()); + return false; + } + } + + if (newArgs[ci]) + { + if (pMessage) + *pMessage = getMatchError("parameter `%s` assigned twice", parameterList[ci].toChars()); + return false; + } + newArgs[ci++] = arg; + } + foreach (i, arg; newArgs) + { + if (!arg) + { + if (parameterList[i].defaultArg) + continue; + + if (parameterList.varargs != VarArg.none && i + 1 == newArgs.length) + continue; + + if (pMessage) + *pMessage = getMatchError("missing argument for parameter #%d: `%s`", + i + 1, parameterToChars(parameterList[i], this, false)); + return false; + } + } + // strip trailing nulls from default arguments + size_t e = newArgs.length; + while (e > 0 && newArgs[e - 1] is null) { + --e; + } + + args = newArgs[0..e]; + return true; + } + /+ + Checks whether this function type is convertible to ` to` + when used in a function pointer / delegate. @@ -4893,6 +4990,17 @@ extern (C++) final class TypeFunction : TypeNext { v.visit(this); } + + /// Returns: index of parameter with name `ident` or -1 if not found + private extern(D) ptrdiff_t parameterIndex(Identifier ident) + { + foreach (i, p; this.parameterList) + { + if (p.ident == ident) + return i; + } + return -1; + } } /*********************************************************** diff --git a/tests/dmd/compilable/named_arguments.d b/tests/dmd/compilable/named_arguments.d new file mode 100644 index 00000000000..beed32a20f3 --- /dev/null +++ b/tests/dmd/compilable/named_arguments.d @@ -0,0 +1,12 @@ + +string fun(string x, string y, string z = "Z", string w = "W") +{ + return x ~ y ~ z ~ w; +} + +static assert(fun( "x", "y") == "xyZW"); +static assert(fun( "x", "y", "z", "w") == "xyzw"); +static assert(fun(x: "x", y: "y", z: "z", w: "w") == "xyzw"); +static assert(fun(w: "w", z: "z", y: "y", x: "x") == "xyzw"); +static assert(fun(y: "y", "z", x: "x") == "xyzW"); +static assert(fun( "x", "y", w: "w") == "xyZw"); diff --git a/tests/dmd/fail_compilation/named_arguments_error.d b/tests/dmd/fail_compilation/named_arguments_error.d new file mode 100644 index 00000000000..bc633a1da20 --- /dev/null +++ b/tests/dmd/fail_compilation/named_arguments_error.d @@ -0,0 +1,25 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/named_arguments_error.d(21): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)` +fail_compilation/named_arguments_error.d(21): parameter `x` assigned twice +fail_compilation/named_arguments_error.d(22): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)` +fail_compilation/named_arguments_error.d(22): argument `4` goes past end of parameter list +fail_compilation/named_arguments_error.d(23): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)` +fail_compilation/named_arguments_error.d(23): parameter `y` assigned twice +fail_compilation/named_arguments_error.d(24): Error: function `named_arguments_error.g(int x, int y, int z = 3)` is not callable using argument types `(int, int)` +fail_compilation/named_arguments_error.d(24): missing argument for parameter #1: `int x` +--- +*/ + +void f(int x, int y, int z); + +void g(int x, int y, int z = 3); + +void main() +{ + f(x: 3, x: 3, 5); + f(z: 3, 4, 5); + f(y: 3, x: 4, 5); + g(y: 4, z: 3); +} diff --git a/tests/dmd/fail_compilation/named_arguments_overload.d b/tests/dmd/fail_compilation/named_arguments_overload.d new file mode 100644 index 00000000000..725d7b0dd13 --- /dev/null +++ b/tests/dmd/fail_compilation/named_arguments_overload.d @@ -0,0 +1,31 @@ +/** +TEST_OUTPUT: +--- +fail_compilation/named_arguments_overload.d(29): Error: none of the overloads of `snoopy` are callable using argument types `(immutable(S), immutable(T))` +fail_compilation/named_arguments_overload.d(13): Candidates are: `named_arguments_overload.snoopy(S s, int i = 0, T t = T())` +fail_compilation/named_arguments_overload.d(14): `named_arguments_overload.snoopy(T t, int i, S s)` +fail_compilation/named_arguments_overload.d(30): Error: none of the overloads of `snoopy` are callable using argument types `(immutable(T), immutable(S))` +fail_compilation/named_arguments_overload.d(13): Candidates are: `named_arguments_overload.snoopy(S s, int i = 0, T t = T())` +fail_compilation/named_arguments_overload.d(14): `named_arguments_overload.snoopy(T t, int i, S s)` +--- +*/ + +char snoopy(S s, int i = 0, T t = T.init) { return 'B'; } +char snoopy(T t, int i, S s) { return 'A'; } + +struct S { } +struct T { } +immutable S s = S.init; +immutable T t = T.init; +immutable int i = 0; + +static assert(snoopy(t, i, s ) == 'A'); +static assert(snoopy(s, i, t ) == 'B'); +static assert(snoopy(s:s, t:t ) == 'B'); +static assert(snoopy(t:t, s:s ) == 'B'); +static assert(snoopy(t:t, i, s:s) == 'A'); +static assert(snoopy(s:s, t:t, i ) == 'A'); + +immutable err0 = snoopy(s, t); // error, neither A nor B match +immutable err1 = snoopy(t, s); // error, neither A nor B match +immutable err2 = snoopy(s:s, t:t, i:i); // error, ambiguous diff --git a/tests/dmd/fail_compilation/named_arguments_pragma.d b/tests/dmd/fail_compilation/named_arguments_pragma.d new file mode 100644 index 00000000000..f4a56ed4f83 --- /dev/null +++ b/tests/dmd/fail_compilation/named_arguments_pragma.d @@ -0,0 +1,14 @@ +/** +TEST_OUTPUT: +--- +fail_compilation/named_arguments_pragma.d(12): Error: cannot use named argument `thecode: "{}"` in `mixin` or `pragma` +fail_compilation/named_arguments_pragma.d(13): Error: cannot use named argument `themsg: "hello"` in `mixin` or `pragma` +fail_compilation/named_arguments_pragma.d(13): while evaluating `pragma(msg, themsg: "hello")` +--- +*/ + +void main() +{ + mixin(thecode: "{}"); + pragma(msg, themsg: "hello"); +} diff --git a/tests/dmd/fail_compilation/named_arguments_template.d b/tests/dmd/fail_compilation/named_arguments_template.d new file mode 100644 index 00000000000..018c146be80 --- /dev/null +++ b/tests/dmd/fail_compilation/named_arguments_template.d @@ -0,0 +1,10 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/named_arguments_template.d(10): Error: named template arguments (`X: int`) are not supported yet +fail_compilation/named_arguments_template.d(10): Error: template instance `T!(X: int)` does not match template declaration `T(X)` +--- +*/ + +template T(X) {} +alias I = T!(X: int); From 398b71fedf7631cdb827641d63b17be44acd3625 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Thu, 19 Jan 2023 10:34:17 +0100 Subject: [PATCH 080/177] Pass names along with arguments --- dmd/arrayop.d | 2 +- dmd/clone.d | 6 +- dmd/declaration.h | 2 +- dmd/dsymbolsem.d | 6 +- dmd/dtemplate.d | 27 ++++---- dmd/expression.d | 1 + dmd/expressionsem.d | 65 ++++++------------- dmd/frontend.h | 3 +- dmd/func.d | 18 ++--- dmd/mtype.d | 26 ++++---- dmd/opover.d | 14 ++-- dmd/semantic3.d | 2 +- dmd/statementsem.d | 2 +- .../fail_compilation/named_arguments_pragma.d | 14 ---- .../named_arguments_template.d | 10 --- 15 files changed, 79 insertions(+), 119 deletions(-) delete mode 100644 tests/dmd/fail_compilation/named_arguments_pragma.d delete mode 100644 tests/dmd/fail_compilation/named_arguments_template.d diff --git a/dmd/arrayop.d b/dmd/arrayop.d index d60e584deeb..bc24d15bf08 100644 --- a/dmd/arrayop.d +++ b/dmd/arrayop.d @@ -149,7 +149,7 @@ Expression arrayOp(BinExp e, Scope* sc) ObjectNotFound(idArrayOp); // fatal error } - auto fd = resolveFuncCall(e.loc, sc, arrayOp, tiargs, null, args, FuncResolveFlag.standard); + auto fd = resolveFuncCall(e.loc, sc, arrayOp, tiargs, null, args, null, FuncResolveFlag.standard); if (!fd || fd.errors) return ErrorExp.get(); return new CallExp(e.loc, new VarExp(e.loc, fd, false), args).expressionSemantic(sc); diff --git a/dmd/clone.d b/dmd/clone.d index 7f6ae21b971..543805d0a29 100644 --- a/dmd/clone.d +++ b/dmd/clone.d @@ -113,11 +113,11 @@ FuncDeclaration hasIdentityOpAssign(AggregateDeclaration ad, Scope* sc) sc.minst = null; a[0] = er; - auto f = resolveFuncCall(ad.loc, sc, assign, null, ad.type, &a, FuncResolveFlag.quiet); + auto f = resolveFuncCall(ad.loc, sc, assign, null, ad.type, &a, null, FuncResolveFlag.quiet); if (!f) { a[0] = el; - f = resolveFuncCall(ad.loc, sc, assign, null, ad.type, &a, FuncResolveFlag.quiet); + f = resolveFuncCall(ad.loc, sc, assign, null, ad.type, &a, null, FuncResolveFlag.quiet); } sc = sc.pop(); @@ -478,7 +478,7 @@ private FuncDeclaration hasIdentityOpEquals(AggregateDeclaration ad, Scope* sc) { a[0] = e; a[0].type = tthis; - return resolveFuncCall(ad.loc, sc, eq, null, tthis, &a, FuncResolveFlag.quiet); + return resolveFuncCall(ad.loc, sc, eq, null, tthis, &a, null, FuncResolveFlag.quiet); } f = rfc(er); diff --git a/dmd/declaration.h b/dmd/declaration.h index 233e2848530..429b3ccee04 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -682,7 +682,7 @@ class FuncDeclaration : public Declaration BaseClass *overrideInterface(); bool overloadInsert(Dsymbol *s) override; bool inUnittest(); - MATCH leastAsSpecialized(FuncDeclaration *g); + MATCH leastAsSpecialized(FuncDeclaration *g, Identifiers *names = nullptr); LabelDsymbol *searchLabel(Identifier *ident, const Loc &loc); int getLevel(FuncDeclaration *fd, int intypeof); // lexical nesting level difference int getLevelAndCheck(const Loc &loc, Scope *sc, FuncDeclaration *fd); diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index c9fb5692c7a..84bcfa6bec9 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -4745,7 +4745,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor sc = sc.push(); sc.tinst = null; sc.minst = null; - auto fcall = resolveFuncCall(sd.loc, sc, scall, null, null, null, FuncResolveFlag.quiet); + auto fcall = resolveFuncCall(sd.loc, sc, scall, null, null, null, null, FuncResolveFlag.quiet); sc = sc.pop(); global.endGagging(xerrors); @@ -5345,9 +5345,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor // this() { } if (!cldec.ctor && cldec.baseClass && cldec.baseClass.ctor) { - auto fd = resolveFuncCall(cldec.loc, sc2, cldec.baseClass.ctor, null, cldec.type, null, FuncResolveFlag.quiet); + auto fd = resolveFuncCall(cldec.loc, sc2, cldec.baseClass.ctor, null, cldec.type, null, null, FuncResolveFlag.quiet); if (!fd) // try shared base ctor instead - fd = resolveFuncCall(cldec.loc, sc2, cldec.baseClass.ctor, null, cldec.type.sharedOf, null, FuncResolveFlag.quiet); + fd = resolveFuncCall(cldec.loc, sc2, cldec.baseClass.ctor, null, cldec.type.sharedOf, null, null, FuncResolveFlag.quiet); if (fd && !fd.errors) { //printf("Creating default this(){} for class %s\n", toChars()); diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 11f71529dca..8b866183312 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -1335,7 +1335,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol for (size_t i = 0; i < (fargs ? fargs.length : 0); i++) { Expression e = (*fargs)[i]; - printf("\tfarg[%d] is %s, type is %s\n", i, e.toChars(), e.type.toChars()); + printf("\tfarg[%d] is %s, type is %s\n", cast(int) i, e.toChars(), e.type.toChars()); } printf("fd = %s\n", fd.toChars()); printf("fd.type = %s\n", fd.type.toChars()); @@ -2598,7 +2598,7 @@ extern (C++) final class TypeDeduced : Type * pMessage = address to store error message, or null */ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, Objects* tiargs, - Type tthis, Expressions* fargs, const(char)** pMessage = null) + Type tthis, Expressions* fargs, Identifiers* fnames, const(char)** pMessage = null) { alias fargs_ = fargs; version (none) @@ -2620,6 +2620,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, printf("\t%s %s\n", arg.type.toChars(), arg.toChars()); //printf("\tty = %d\n", arg.type.ty); } + printf(" fnames: %s\n", fnames ? fnames.toChars() : "null"); //printf("stc = %llx\n", dstart._scope.stc); //printf("match:t/f = %d/%d\n", ta_last, m.last); } @@ -2705,7 +2706,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, else if (shared_this && !shared_dtor && tthis_fd !is null) tf.mod = tthis_fd.mod; } - MATCH mfa = tf.callMatch(tthis_fd, fargs_, 0, pMessage, sc); + MATCH mfa = tf.callMatch(tthis_fd, fargs_, fnames, 0, pMessage, sc); //printf("test1: mfa = %d\n", mfa); if (mfa == MATCH.nomatch) return 0; @@ -2738,8 +2739,8 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, * This is because f() is "more specialized." */ { - MATCH c1 = fd.leastAsSpecialized(m.lastf); - MATCH c2 = m.lastf.leastAsSpecialized(fd); + MATCH c1 = fd.leastAsSpecialized(m.lastf, fnames); + MATCH c2 = m.lastf.leastAsSpecialized(fd, fnames); //printf("c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) return firstIsBetter(); if (c1 < c2) return 0; @@ -2883,13 +2884,13 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, pr.dedargs = &dedtypesX; tdx.previous = ≺ // add this to threaded list - fd = resolveFuncCall(loc, sc, s, null, tthis, fargs, FuncResolveFlag.quiet); + fd = resolveFuncCall(loc, sc, s, null, tthis, fargs, fnames, FuncResolveFlag.quiet); tdx.previous = pr.prev; // unlink from threaded list } else if (s.isFuncDeclaration()) { - fd = resolveFuncCall(loc, sc, s, null, tthis, fargs, FuncResolveFlag.quiet); + fd = resolveFuncCall(loc, sc, s, null, tthis, fargs, fnames, FuncResolveFlag.quiet); } else goto Lerror; @@ -2908,7 +2909,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, Type tthis_fd = fd.needThis() && !fd.isCtorDeclaration() ? tthis : null; auto tf = cast(TypeFunction)fd.type; - MATCH mfa = tf.callMatch(tthis_fd, fargs_, 0, null, sc); + MATCH mfa = tf.callMatch(tthis_fd, fargs_, fnames, 0, null, sc); if (mfa < m.last) return 0; @@ -3010,16 +3011,16 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, // Disambiguate by tf.callMatch auto tf1 = fd.type.isTypeFunction(); auto tf2 = m.lastf.type.isTypeFunction(); - MATCH c1 = tf1.callMatch(tthis_fd, fargs_, 0, null, sc); - MATCH c2 = tf2.callMatch(tthis_best, fargs_, 0, null, sc); + MATCH c1 = tf1.callMatch(tthis_fd, fargs_, fnames, 0, null, sc); + MATCH c2 = tf2.callMatch(tthis_best, fargs_, fnames, 0, null, sc); //printf("2: c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) goto Ltd; if (c1 < c2) goto Ltd_best; } { // Disambiguate by picking the most specialized FunctionDeclaration - MATCH c1 = fd.leastAsSpecialized(m.lastf); - MATCH c2 = m.lastf.leastAsSpecialized(fd); + MATCH c1 = fd.leastAsSpecialized(m.lastf, fnames); + MATCH c2 = m.lastf.leastAsSpecialized(fd, fnames); //printf("3: c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) goto Ltd; if (c1 < c2) goto Ltd_best; @@ -3114,7 +3115,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, if (m.lastf.type.ty == Terror) goto Lerror; auto tf = m.lastf.type.isTypeFunction(); - if (!tf.callMatch(tthis_best, fargs_, 0, null, sc)) + if (!tf.callMatch(tthis_best, fargs_, fnames, 0, null, sc)) goto Lnomatch; /* As https://issues.dlang.org/show_bug.cgi?id=3682 shows, diff --git a/dmd/expression.d b/dmd/expression.d index 25ea379b7ce..1a3b9c1216d 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -3645,6 +3645,7 @@ extern (C++) final class NewExp : Expression Expression thisexp; // if !=null, 'this' for class being allocated Type newtype; Expressions* arguments; // Array of Expression's + Identifiers* names; // Array of names corresponding to expressions Expression argprefix; // expression to be evaluated just before arguments[] CtorDeclaration member; // constructor function diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index c7c07944566..d87f85e8422 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -262,7 +262,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0) uint xerrors = global.startGagging(); sc = sc.push(); - FuncDeclaration fslice = resolveFuncCall(ae.loc, sc, slice, tiargs, ae.e1.type, fargs, FuncResolveFlag.quiet); + FuncDeclaration fslice = resolveFuncCall(ae.loc, sc, slice, tiargs, ae.e1.type, fargs, null, FuncResolveFlag.quiet); sc = sc.pop(); global.endGagging(xerrors); if (!fslice) @@ -1197,7 +1197,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = for (size_t i = 0; i < os.a.length; i++) { - if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, &a, FuncResolveFlag.quiet)) + if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, &a, null, FuncResolveFlag.quiet)) { if (f.errors) return ErrorExp.get(); @@ -1214,7 +1214,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = { for (size_t i = 0; i < os.a.length; i++) { - if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, null, FuncResolveFlag.quiet)) + if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, null, null, FuncResolveFlag.quiet)) { if (f.errors) return ErrorExp.get(); @@ -1312,7 +1312,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = Expressions a; a.push(e2); - FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, FuncResolveFlag.quiet); + FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, null, FuncResolveFlag.quiet); if (fd && fd.type) { if (fd.errors) @@ -1332,7 +1332,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = } } { - FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, null, FuncResolveFlag.quiet); + FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, null, null, FuncResolveFlag.quiet); if (fd && fd.type) { if (fd.errors) @@ -1403,10 +1403,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = if (!e1.type) { - if (e1.isNamedArgExp()) - error(loc, "named argument `%s` not allowed here", e1.toChars()); - else - error(loc, "cannot resolve type for %s", e1.toChars()); + error(loc, "cannot resolve type for %s", e1.toChars()); e1 = ErrorExp.get(); } return e1; @@ -1677,15 +1674,7 @@ private bool preFunctionParameters(Scope* sc, Identifiers* names, Expressions* e err = true; } - if (ne) - { - ne.arg = arg; - (*exps)[i] = ne; - } - else - { - (*exps)[i] = arg; - } + (*exps)[i] = arg; } } return err; @@ -3728,7 +3717,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (cd.ctor) { - FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard); + FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.ctor, null, tb, exp.arguments, exp.names, FuncResolveFlag.standard); if (!f || f.errors) return setError(); @@ -3853,7 +3842,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // is the same type as the struct if (nargs && (sd.hasRegularCtor() || (sd.ctor && (*exp.arguments)[0].type.mutableOf() == sd.type.mutableOf()))) { - FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard); + FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.ctor, null, tb, exp.arguments, exp.names, FuncResolveFlag.standard); if (!f || f.errors) return setError(); @@ -4734,14 +4723,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } FuncDeclaration resolveOverloadSet(Loc loc, Scope* sc, - OverloadSet os, Objects* tiargs, Type tthis, Expressions* arguments) + OverloadSet os, Objects* tiargs, Type tthis, Expressions* arguments, Identifiers* names) { FuncDeclaration f = null; foreach (s; os.a) { if (tiargs && s.isFuncDeclaration()) continue; - if (auto f2 = resolveFuncCall(loc, sc, s, tiargs, tthis, arguments, FuncResolveFlag.quiet)) + if (auto f2 = resolveFuncCall(loc, sc, s, tiargs, tthis, arguments, names, FuncResolveFlag.quiet)) { if (f2.errors) return null; @@ -4801,7 +4790,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } // Do overload resolution - exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue.e1.type, exp.arguments, FuncResolveFlag.standard); + exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue.e1.type, exp.arguments, exp.names, FuncResolveFlag.standard); if (!exp.f || exp.f.errors || exp.f.type.ty == Terror) return setError(); @@ -4964,9 +4953,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor tthis = ad.type.addMod(sc.func.type.mod); auto ctor = isSuper ? cd.baseClass.ctor : ad.ctor; if (auto os = ctor.isOverloadSet()) - exp.f = resolveOverloadSet(exp.loc, sc, os, null, tthis, exp.arguments); + exp.f = resolveOverloadSet(exp.loc, sc, os, null, tthis, exp.arguments, exp.names); else - exp.f = resolveFuncCall(exp.loc, sc, ctor, null, tthis, exp.arguments, FuncResolveFlag.standard); + exp.f = resolveFuncCall(exp.loc, sc, ctor, null, tthis, exp.arguments, exp.names, FuncResolveFlag.standard); if (!exp.f || exp.f.errors) return setError(); @@ -4991,7 +4980,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else if (auto oe = exp.e1.isOverExp()) { - exp.f = resolveOverloadSet(exp.loc, sc, oe.vars, tiargs, tthis, exp.arguments); + exp.f = resolveOverloadSet(exp.loc, sc, oe.vars, tiargs, tthis, exp.arguments, exp.names); if (!exp.f) return setError(); if (ethis) @@ -5038,7 +5027,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor else if (exp.e1.op == EXP.dotVariable && (cast(DotVarExp)exp.e1).var.isOverDeclaration()) { DotVarExp dve = cast(DotVarExp)exp.e1; - exp.f = resolveFuncCall(exp.loc, sc, dve.var, tiargs, dve.e1.type, exp.arguments, FuncResolveFlag.overloadOnly); + exp.f = resolveFuncCall(exp.loc, sc, dve.var, tiargs, dve.e1.type, exp.arguments, exp.names, FuncResolveFlag.overloadOnly); if (!exp.f) return setError(); if (exp.f.needThis()) @@ -5062,7 +5051,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { s = (cast(TemplateExp)exp.e1).td; L2: - exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, null, exp.arguments, FuncResolveFlag.standard); + exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, null, exp.arguments, exp.names, FuncResolveFlag.standard); if (!exp.f || exp.f.errors) return setError(); if (exp.f.needThis()) @@ -5090,7 +5079,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } const(char)* failMessage; - if (!tf.callMatch(null, exp.arguments, 0, &failMessage, sc)) + if (!tf.callMatch(null, exp.arguments, exp.names, 0, &failMessage, sc)) { OutBuffer buf; buf.writeByte('('); @@ -5157,13 +5146,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor tiargs = null; if (exp.f.overnext) - exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, FuncResolveFlag.overloadOnly); + exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, exp.names, FuncResolveFlag.overloadOnly); else { exp.f = exp.f.toAliasFunc(); TypeFunction tf = cast(TypeFunction)exp.f.type; const(char)* failMessage; - if (!tf.callMatch(null, exp.arguments, 0, &failMessage, sc)) + if (!tf.callMatch(null, exp.arguments, exp.names, 0, &failMessage, sc)) { OutBuffer buf; buf.writeByte('('); @@ -5205,7 +5194,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // // https://issues.dlang.org/show_bug.cgi?id=22157 if (exp.f.overnext) - exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, FuncResolveFlag.standard); + exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, exp.names, FuncResolveFlag.standard); if (!exp.f || exp.f.errors) return setError(); @@ -12504,18 +12493,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor result = e; } - - override void visit(NamedArgExp e) - { - //printf("NamedArgExp::semantic('%s')\n", e.toChars()); - if (e.arg.dyncast() == DYNCAST.expression) - { - e.arg = expressionSemantic(cast(Expression) e.arg, sc); - e.type = (cast(Expression) e.arg).type; - } - - result = e; - } } /********************************** diff --git a/dmd/frontend.h b/dmd/frontend.h index b46c89b6ffc..9141cbbe64b 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -2541,7 +2541,7 @@ class FuncDeclaration : public Declaration BaseClass* overrideInterface(); bool overloadInsert(Dsymbol* s) override; bool inUnittest(); - MATCH leastAsSpecialized(FuncDeclaration* g); + MATCH leastAsSpecialized(FuncDeclaration* g, Array* names); LabelDsymbol* searchLabel(Identifier* ident, const Loc& loc = Loc::initial); int32_t getLevel(FuncDeclaration* fd, int32_t intypeof); int32_t getLevelAndCheck(const Loc& loc, Scope* sc, FuncDeclaration* fd, Declaration* decl); @@ -7188,6 +7188,7 @@ class NewExp final : public Expression Expression* thisexp; Type* newtype; Array* arguments; + Array* names; Expression* argprefix; CtorDeclaration* member; bool onstack; diff --git a/dmd/func.d b/dmd/func.d index 93903306769..b03e8207c4e 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -1039,12 +1039,13 @@ extern (C++) class FuncDeclaration : Declaration * match 'this' is at least as specialized as g * 0 g is more specialized than 'this' */ - final MATCH leastAsSpecialized(FuncDeclaration g) + final MATCH leastAsSpecialized(FuncDeclaration g, Identifiers* names) { enum LOG_LEASTAS = 0; static if (LOG_LEASTAS) { - printf("%s.leastAsSpecialized(%s)\n", toChars(), g.toChars()); + import core.stdc.stdio : printf; + printf("%s.leastAsSpecialized(%s, %s)\n", toChars(), g.toChars(), names ? names.toChars() : "null"); printf("%s, %s\n", type.toChars(), g.type.toChars()); } @@ -1089,7 +1090,7 @@ extern (C++) class FuncDeclaration : Declaration args.push(e); } - MATCH m = tg.callMatch(null, &args, 1); + MATCH m = tg.callMatch(null, &args, names, 1); if (m > MATCH.nomatch) { /* A variadic parameter list is less specialized than a @@ -3134,7 +3135,7 @@ enum FuncResolveFlag : ubyte * if match is found, then function symbol, else null */ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, - Objects* tiargs, Type tthis, Expressions* fargs, FuncResolveFlag flags) + Objects* tiargs, Type tthis, Expressions* fargs, Identifiers* fnames, FuncResolveFlag flags) { if (!s) return null; // no match @@ -3153,6 +3154,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, printf("\t%s: %s\n", arg.toChars(), arg.type.toChars()); } } + printf("\tfnames: %s\n", fnames ? fnames.toChars() : "null"); } if (tiargs && arrayObjectIsError(tiargs)) @@ -3163,7 +3165,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, return null; MatchAccumulator m; - functionResolve(m, s, loc, sc, tiargs, tthis, fargs, null); + functionResolve(m, s, loc, sc, tiargs, tthis, fargs, fnames); auto orig_s = s; if (m.last > MATCH.nomatch && m.lastf) @@ -3286,7 +3288,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, } const(char)* failMessage; - functionResolve(m, orig_s, loc, sc, tiargs, tthis, fargs, &failMessage); + functionResolve(m, orig_s, loc, sc, tiargs, tthis, fargs, fnames, &failMessage); if (failMessage) { .error(loc, "%s `%s%s%s` is not callable using argument types `%s`", @@ -3332,7 +3334,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, if (auto baseFunction = baseClass.search(baseClass.loc, fd.ident)) { MatchAccumulator mErr; - functionResolve(mErr, baseFunction, loc, sc, tiargs, baseClass.type, fargs, null); + functionResolve(mErr, baseFunction, loc, sc, tiargs, baseClass.type, fargs, fnames); if (mErr.last > MATCH.nomatch && mErr.lastf) { errorSupplemental(loc, "%s `%s` hides base class function `%s`", @@ -3346,7 +3348,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, } } const(char)* failMessage; - functionResolve(m, orig_s, loc, sc, tiargs, tthis, fargs, &failMessage); + functionResolve(m, orig_s, loc, sc, tiargs, tthis, fargs, fnames, &failMessage); if (failMessage) errorSupplemental(loc, failMessage); } diff --git a/dmd/mtype.d b/dmd/mtype.d index b5dd614e9b3..9aef6d3ff10 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -2046,7 +2046,7 @@ extern (C++) abstract class Type : ASTNode } if (auto fd = s.isFuncDeclaration()) { - fd = resolveFuncCall(Loc.initial, null, fd, null, this, null, FuncResolveFlag.quiet); + fd = resolveFuncCall(Loc.initial, null, fd, null, this, null, null, FuncResolveFlag.quiet); if (!fd || fd.errors || !fd.functionSemantic()) return Type.terror; @@ -2068,7 +2068,7 @@ extern (C++) abstract class Type : ASTNode if (auto td = s.isTemplateDeclaration()) { assert(td._scope); - auto fd = resolveFuncCall(Loc.initial, null, td, null, this, null, FuncResolveFlag.quiet); + auto fd = resolveFuncCall(Loc.initial, null, td, null, this, null, null, FuncResolveFlag.quiet); if (!fd || fd.errors || !fd.functionSemantic()) return Type.terror; @@ -4633,9 +4633,10 @@ extern (C++) final class TypeFunction : TypeNext * Returns: * MATCHxxxx */ - extern (D) MATCH callMatch(Type tthis, Expressions* inArgs, int flag = 0, const(char)** pMessage = null, Scope* sc = null) + extern (D) MATCH callMatch(Type tthis, Expressions* inArgs, Identifiers* names, int flag = 0, const(char)** pMessage = null, Scope* sc = null) { //printf("TypeFunction::callMatch() %s\n", toChars()); + //printf("inArgs: %s, names: %s\n", inArgs ? inArgs.toChars() : "null", names ? names.toChars() : "null"); MATCH match = MATCH.exact; // assume exact match ubyte wildmatch = 0; @@ -4670,6 +4671,7 @@ extern (C++) final class TypeFunction : TypeNext const nparams = parameterList.length; Expression[] args = inArgs ? (*inArgs)[] : null; + Identifier[] nnames = names ? (*names)[] : null; if (args.length > nparams) { @@ -4688,13 +4690,13 @@ extern (C++) final class TypeFunction : TypeNext if (parameterList.varargs == VarArg.none && nparams > args.length && !parameterList[args.length].defaultArg) { OutBuffer buf; - buf.printf("too few arguments, expected `%d`, got `%d`", cast(int)nparams, cast(int)args.length); + buf.printf("too few arguments, expected %d, got %d", cast(int)nparams, cast(int)args.length); if (pMessage) *pMessage = buf.extractChars(); return MATCH.nomatch; } - if (!resolveNamedArgs(args, pMessage)) + if (!resolveNamedArgs(args, nnames, pMessage)) { if (!pMessage || *pMessage) return MATCH.nomatch; @@ -4809,30 +4811,30 @@ extern (C++) final class TypeFunction : TypeNext * pMessage = address to store error message, or null * Returns: true on success, false on error */ - private extern(D) bool resolveNamedArgs(ref Expression[] args, const(char)** pMessage) + private extern(D) bool resolveNamedArgs(ref Expression[] args, ref Identifier[] names, const(char)** pMessage) { auto newArgs = new Expression[parameterList.length]; size_t ci = 0; bool hasNamedArgs = false; - foreach (arg; args) + foreach (i, arg; args) { if (!arg) { ci++; continue; } - if (auto ne = arg.isNamedArgExp()) + auto name = i < names.length ? names[i] : null; + if (name) { hasNamedArgs = true; - const pi = parameterIndex(ne.ident); + const pi = parameterIndex(name); if (pi == -1) { if (pMessage) - *pMessage = getMatchError("no parameter named `%s`", ne.ident.toChars()); + *pMessage = getMatchError("no parameter named `%s`", name.toChars()); return false; } ci = pi; - arg = cast(Expression) ne.arg; } if (ci >= newArgs.length) { @@ -7092,7 +7094,7 @@ bool isCopyable(Type t) el.type = cast() ts; Expressions args; args.push(el); - FuncDeclaration f = resolveFuncCall(Loc.initial, null, ctor, null, cast()ts, &args, FuncResolveFlag.quiet); + FuncDeclaration f = resolveFuncCall(Loc.initial, null, ctor, null, cast()ts, &args, null, FuncResolveFlag.quiet); if (!f || f.storage_class & STC.disable) return false; } diff --git a/dmd/opover.d b/dmd/opover.d index 3db111b8e61..96ba05daa54 100644 --- a/dmd/opover.d +++ b/dmd/opover.d @@ -711,7 +711,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) MatchAccumulator m; if (s) { - functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2); + functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2, null); if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) { return ErrorExp.get(); @@ -720,7 +720,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) FuncDeclaration lastf = m.lastf; if (s_r) { - functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, &args1); + functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, &args1, null); if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) { return ErrorExp.get(); @@ -793,7 +793,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) MatchAccumulator m; if (s_r) { - functionResolve(m, s_r, e.loc, sc, tiargs, e.e1.type, &args2); + functionResolve(m, s_r, e.loc, sc, tiargs, e.e1.type, &args2, null); if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) { return ErrorExp.get(); @@ -802,7 +802,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) FuncDeclaration lastf = m.lastf; if (s) { - functionResolve(m, s, e.loc, sc, tiargs, e.e2.type, &args1); + functionResolve(m, s, e.loc, sc, tiargs, e.e2.type, &args1, null); if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) { return ErrorExp.get(); @@ -1254,7 +1254,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) args2[0] = e.e2; expandTuples(&args2); MatchAccumulator m; - functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2); + functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2, null); if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) { return ErrorExp.get(); @@ -1347,7 +1347,7 @@ private Expression compare_overload(BinExp e, Scope* sc, Identifier id, EXP* pop } if (s) { - functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2); + functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2, null); if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) return ErrorExp.get(); } @@ -1355,7 +1355,7 @@ private Expression compare_overload(BinExp e, Scope* sc, Identifier id, EXP* pop int count = m.count; if (s_r) { - functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, &args1); + functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, &args1, null); if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) return ErrorExp.get(); } diff --git a/dmd/semantic3.d b/dmd/semantic3.d index 981e2d16f12..8f95e0e3876 100644 --- a/dmd/semantic3.d +++ b/dmd/semantic3.d @@ -711,7 +711,7 @@ private extern(C++) final class Semantic3Visitor : Visitor // Insert implicit super() at start of fbody Type tthis = ad2.type.addMod(funcdecl.vthis.type.mod); - FuncDeclaration fd = resolveFuncCall(Loc.initial, sc2, cd.baseClass.ctor, null, tthis, null, FuncResolveFlag.quiet); + FuncDeclaration fd = resolveFuncCall(Loc.initial, sc2, cd.baseClass.ctor, null, tthis, null, null, FuncResolveFlag.quiet); if (!fd) { funcdecl.error("no match for implicit `super()` call in constructor"); diff --git a/dmd/statementsem.d b/dmd/statementsem.d index 20eb3c03fb5..768506ec5d7 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -1276,7 +1276,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor else if (auto td = sfront.isTemplateDeclaration()) { Expressions a; - if (auto f = resolveFuncCall(loc, sc, td, null, tab, &a, FuncResolveFlag.quiet)) + if (auto f = resolveFuncCall(loc, sc, td, null, tab, &a, null, FuncResolveFlag.quiet)) tfront = f.type; } else if (auto d = sfront.toAlias().isDeclaration()) diff --git a/tests/dmd/fail_compilation/named_arguments_pragma.d b/tests/dmd/fail_compilation/named_arguments_pragma.d deleted file mode 100644 index f4a56ed4f83..00000000000 --- a/tests/dmd/fail_compilation/named_arguments_pragma.d +++ /dev/null @@ -1,14 +0,0 @@ -/** -TEST_OUTPUT: ---- -fail_compilation/named_arguments_pragma.d(12): Error: cannot use named argument `thecode: "{}"` in `mixin` or `pragma` -fail_compilation/named_arguments_pragma.d(13): Error: cannot use named argument `themsg: "hello"` in `mixin` or `pragma` -fail_compilation/named_arguments_pragma.d(13): while evaluating `pragma(msg, themsg: "hello")` ---- -*/ - -void main() -{ - mixin(thecode: "{}"); - pragma(msg, themsg: "hello"); -} diff --git a/tests/dmd/fail_compilation/named_arguments_template.d b/tests/dmd/fail_compilation/named_arguments_template.d deleted file mode 100644 index 018c146be80..00000000000 --- a/tests/dmd/fail_compilation/named_arguments_template.d +++ /dev/null @@ -1,10 +0,0 @@ -/* -TEST_OUTPUT: ---- -fail_compilation/named_arguments_template.d(10): Error: named template arguments (`X: int`) are not supported yet -fail_compilation/named_arguments_template.d(10): Error: template instance `T!(X: int)` does not match template declaration `T(X)` ---- -*/ - -template T(X) {} -alias I = T!(X: int); From 230e99acc58b620f8b5871e132541817e631e17e Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Sat, 21 Jan 2023 11:51:28 +0100 Subject: [PATCH 081/177] Don't reorder arguments too soon --- dmd/dtemplate.d | 1 + dmd/expressionsem.d | 27 +++++++++++++++---- dmd/func.d | 1 + dmd/mtype.d | 10 +++---- tests/dmd/compilable/named_arguments.d | 3 +++ .../named_arguments_overload.d | 16 ++++++----- 6 files changed, 40 insertions(+), 18 deletions(-) diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 8b866183312..41c501fdc13 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -2595,6 +2595,7 @@ extern (C++) final class TypeDeduced : Type * tiargs = initial list of template arguments * tthis = if !NULL, the 'this' pointer argument * fargs = arguments to function + * fnames = names corresponding to fargs * pMessage = address to store error message, or null */ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, Objects* tiargs, diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index d87f85e8422..c4ab8577761 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -1722,13 +1722,12 @@ private bool checkDefCtor(Loc loc, Type t) * true errors happened */ private bool functionParameters(const ref Loc loc, Scope* sc, - TypeFunction tf, Expression ethis, Type tthis, Expressions* arguments, FuncDeclaration fd, + TypeFunction tf, Expression ethis, Type tthis, Expressions* arguments, Identifiers* names, FuncDeclaration fd, Type* prettype, Expression* peprefix) { //printf("functionParameters() %s\n", fd ? fd.toChars() : ""); assert(arguments); assert(fd || tf.next); - size_t nargs = arguments ? arguments.length : 0; const size_t nparams = tf.parameterList.length; const olderrors = global.errors; bool err = false; @@ -1736,6 +1735,24 @@ private bool functionParameters(const ref Loc loc, Scope* sc, Expression eprefix = null; *peprefix = null; + if (names) + { + Expression[] newArgs = arguments.peekSlice(); + const(char)* msg = null; + const result = tf.resolveNamedArgs(newArgs, names.peekSlice(), &msg); + if (!result) + { + // while errors are usually already caught by `tf.callMatch`, + // this can happen when calling `typeof(freefunc)` + if (msg) + error(loc, "%s", msg); + return true; + } + arguments.setDim(0); + arguments.pushSlice(newArgs); + } + size_t nargs = arguments ? arguments.length : 0; + if (nargs > nparams && tf.parameterList.varargs == VarArg.none) { error(loc, "expected %llu arguments, not %llu for non-variadic function type `%s`", cast(ulong)nparams, cast(ulong)nargs, tf.toChars()); @@ -3727,7 +3744,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor TypeFunction tf = f.type.isTypeFunction(); if (!exp.arguments) exp.arguments = new Expressions(); - if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix)) + if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, exp.names, f, &exp.type, &exp.argprefix)) return setError(); exp.member = f.isCtorDeclaration(); @@ -3852,7 +3869,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor TypeFunction tf = f.type.isTypeFunction(); if (!exp.arguments) exp.arguments = new Expressions(); - if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix)) + if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, exp.names, f, &exp.type, &exp.argprefix)) return setError(); exp.member = f.isCtorDeclaration(); @@ -5226,7 +5243,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor Expression argprefix; if (!exp.arguments) exp.arguments = new Expressions(); - if (functionParameters(exp.loc, sc, cast(TypeFunction)t1, ethis, tthis, exp.arguments, exp.f, &exp.type, &argprefix)) + if (functionParameters(exp.loc, sc, cast(TypeFunction)t1, ethis, tthis, exp.arguments, exp.names, exp.f, &exp.type, &argprefix)) return setError(); if (!exp.type) diff --git a/dmd/func.d b/dmd/func.d index b03e8207c4e..e7dc0862133 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -3130,6 +3130,7 @@ enum FuncResolveFlag : ubyte * tiargs = initial list of template arguments * tthis = if !NULL, the `this` argument type * fargs = arguments to function + * fnames = names corresponding to fargs for named arguments * flags = see $(LREF FuncResolveFlag). * Returns: * if match is found, then function symbol, else null diff --git a/dmd/mtype.d b/dmd/mtype.d index 9aef6d3ff10..a181a456ca7 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -4795,11 +4795,6 @@ extern (C++) final class TypeFunction : TypeNext return MATCH.nomatch; } //printf("match = %d\n", match); - if (inArgs) - { - inArgs.setDim(0); - inArgs.pushSlice(args[]); - } return match; } @@ -4811,7 +4806,7 @@ extern (C++) final class TypeFunction : TypeNext * pMessage = address to store error message, or null * Returns: true on success, false on error */ - private extern(D) bool resolveNamedArgs(ref Expression[] args, ref Identifier[] names, const(char)** pMessage) + extern(D) bool resolveNamedArgs(ref Expression[] args, Identifier[] names, const(char)** pMessage) { auto newArgs = new Expression[parameterList.length]; size_t ci = 0; @@ -4874,7 +4869,8 @@ extern (C++) final class TypeFunction : TypeNext } // strip trailing nulls from default arguments size_t e = newArgs.length; - while (e > 0 && newArgs[e - 1] is null) { + while (e > 0 && newArgs[e - 1] is null) + { --e; } diff --git a/tests/dmd/compilable/named_arguments.d b/tests/dmd/compilable/named_arguments.d index beed32a20f3..ff84f474201 100644 --- a/tests/dmd/compilable/named_arguments.d +++ b/tests/dmd/compilable/named_arguments.d @@ -10,3 +10,6 @@ static assert(fun(x: "x", y: "y", z: "z", w: "w") == "xyzw"); static assert(fun(w: "w", z: "z", y: "y", x: "x") == "xyzw"); static assert(fun(y: "y", "z", x: "x") == "xyzW"); static assert(fun( "x", "y", w: "w") == "xyZw"); + +// UFCS +static assert("x".fun("y", w: "w") == "xyZw"); diff --git a/tests/dmd/fail_compilation/named_arguments_overload.d b/tests/dmd/fail_compilation/named_arguments_overload.d index 725d7b0dd13..a9704464605 100644 --- a/tests/dmd/fail_compilation/named_arguments_overload.d +++ b/tests/dmd/fail_compilation/named_arguments_overload.d @@ -1,12 +1,16 @@ /** TEST_OUTPUT: --- -fail_compilation/named_arguments_overload.d(29): Error: none of the overloads of `snoopy` are callable using argument types `(immutable(S), immutable(T))` -fail_compilation/named_arguments_overload.d(13): Candidates are: `named_arguments_overload.snoopy(S s, int i = 0, T t = T())` -fail_compilation/named_arguments_overload.d(14): `named_arguments_overload.snoopy(T t, int i, S s)` -fail_compilation/named_arguments_overload.d(30): Error: none of the overloads of `snoopy` are callable using argument types `(immutable(T), immutable(S))` -fail_compilation/named_arguments_overload.d(13): Candidates are: `named_arguments_overload.snoopy(S s, int i = 0, T t = T())` -fail_compilation/named_arguments_overload.d(14): `named_arguments_overload.snoopy(T t, int i, S s)` +fail_compilation/named_arguments_overload.d(33): Error: none of the overloads of `snoopy` are callable using argument types `(immutable(S), immutable(T))` +fail_compilation/named_arguments_overload.d(17): Candidates are: `named_arguments_overload.snoopy(S s, int i = 0, T t = T())` +fail_compilation/named_arguments_overload.d(18): `named_arguments_overload.snoopy(T t, int i, S s)` +fail_compilation/named_arguments_overload.d(34): Error: none of the overloads of `snoopy` are callable using argument types `(immutable(T), immutable(S))` +fail_compilation/named_arguments_overload.d(17): Candidates are: `named_arguments_overload.snoopy(S s, int i = 0, T t = T())` +fail_compilation/named_arguments_overload.d(18): `named_arguments_overload.snoopy(T t, int i, S s)` +fail_compilation/named_arguments_overload.d(35): Error: `named_arguments_overload.snoopy` called with argument types `(immutable(S), immutable(T), immutable(int))` matches both: +fail_compilation/named_arguments_overload.d(17): `named_arguments_overload.snoopy(S s, int i = 0, T t = T())` +and: +fail_compilation/named_arguments_overload.d(18): `named_arguments_overload.snoopy(T t, int i, S s)` --- */ From 1a6c8ce0e64b728f9afe9ca9b2e13cd4352a19df Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Wed, 25 Jan 2023 23:55:24 +0100 Subject: [PATCH 082/177] Add named arguments to `new class` --- dmd/arrayop.d | 2 +- dmd/clone.d | 6 +-- dmd/dsymbolsem.d | 6 +-- dmd/dtemplate.d | 30 +++++------ dmd/expression.d | 25 ++++++++- dmd/expressionsem.d | 54 +++++++++---------- dmd/frontend.h | 16 ++++++ dmd/func.d | 16 +++--- dmd/mtype.d | 15 +++--- dmd/opover.d | 14 ++--- dmd/parse.d | 11 ++-- dmd/semantic3.d | 2 +- dmd/statementsem.d | 2 +- tests/dmd/compilable/named_arguments.d | 27 ++++++++++ .../dmd/fail_compilation/call_function_type.d | 2 +- 15 files changed, 147 insertions(+), 81 deletions(-) diff --git a/dmd/arrayop.d b/dmd/arrayop.d index bc24d15bf08..908855e271c 100644 --- a/dmd/arrayop.d +++ b/dmd/arrayop.d @@ -149,7 +149,7 @@ Expression arrayOp(BinExp e, Scope* sc) ObjectNotFound(idArrayOp); // fatal error } - auto fd = resolveFuncCall(e.loc, sc, arrayOp, tiargs, null, args, null, FuncResolveFlag.standard); + auto fd = resolveFuncCall(e.loc, sc, arrayOp, tiargs, null, ArgumentList(args), FuncResolveFlag.standard); if (!fd || fd.errors) return ErrorExp.get(); return new CallExp(e.loc, new VarExp(e.loc, fd, false), args).expressionSemantic(sc); diff --git a/dmd/clone.d b/dmd/clone.d index 543805d0a29..19bf83e4ec3 100644 --- a/dmd/clone.d +++ b/dmd/clone.d @@ -113,11 +113,11 @@ FuncDeclaration hasIdentityOpAssign(AggregateDeclaration ad, Scope* sc) sc.minst = null; a[0] = er; - auto f = resolveFuncCall(ad.loc, sc, assign, null, ad.type, &a, null, FuncResolveFlag.quiet); + auto f = resolveFuncCall(ad.loc, sc, assign, null, ad.type, ArgumentList(&a), FuncResolveFlag.quiet); if (!f) { a[0] = el; - f = resolveFuncCall(ad.loc, sc, assign, null, ad.type, &a, null, FuncResolveFlag.quiet); + f = resolveFuncCall(ad.loc, sc, assign, null, ad.type, ArgumentList(&a), FuncResolveFlag.quiet); } sc = sc.pop(); @@ -478,7 +478,7 @@ private FuncDeclaration hasIdentityOpEquals(AggregateDeclaration ad, Scope* sc) { a[0] = e; a[0].type = tthis; - return resolveFuncCall(ad.loc, sc, eq, null, tthis, &a, null, FuncResolveFlag.quiet); + return resolveFuncCall(ad.loc, sc, eq, null, tthis, ArgumentList(&a), FuncResolveFlag.quiet); } f = rfc(er); diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 84bcfa6bec9..404f3b6208e 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -4745,7 +4745,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor sc = sc.push(); sc.tinst = null; sc.minst = null; - auto fcall = resolveFuncCall(sd.loc, sc, scall, null, null, null, null, FuncResolveFlag.quiet); + auto fcall = resolveFuncCall(sd.loc, sc, scall, null, null, ArgumentList(), FuncResolveFlag.quiet); sc = sc.pop(); global.endGagging(xerrors); @@ -5345,9 +5345,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor // this() { } if (!cldec.ctor && cldec.baseClass && cldec.baseClass.ctor) { - auto fd = resolveFuncCall(cldec.loc, sc2, cldec.baseClass.ctor, null, cldec.type, null, null, FuncResolveFlag.quiet); + auto fd = resolveFuncCall(cldec.loc, sc2, cldec.baseClass.ctor, null, cldec.type, ArgumentList(), FuncResolveFlag.quiet); if (!fd) // try shared base ctor instead - fd = resolveFuncCall(cldec.loc, sc2, cldec.baseClass.ctor, null, cldec.type.sharedOf, null, null, FuncResolveFlag.quiet); + fd = resolveFuncCall(cldec.loc, sc2, cldec.baseClass.ctor, null, cldec.type.sharedOf, ArgumentList(), FuncResolveFlag.quiet); if (fd && !fd.errors) { //printf("Creating default this(){} for class %s\n", toChars()); diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 41c501fdc13..8b5db9c5475 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -2594,14 +2594,13 @@ extern (C++) final class TypeDeduced : Type * sc = instantiation scope * tiargs = initial list of template arguments * tthis = if !NULL, the 'this' pointer argument - * fargs = arguments to function - * fnames = names corresponding to fargs + * argumentList= arguments to function * pMessage = address to store error message, or null */ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, Objects* tiargs, - Type tthis, Expressions* fargs, Identifiers* fnames, const(char)** pMessage = null) + Type tthis, ArgumentList argumentList, const(char)** pMessage = null) { - alias fargs_ = fargs; + Expressions* fargs = argumentList.arguments; version (none) { printf("functionResolve() dstart = %s\n", dstart.toChars()); @@ -2621,7 +2620,6 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, printf("\t%s %s\n", arg.type.toChars(), arg.toChars()); //printf("\tty = %d\n", arg.type.ty); } - printf(" fnames: %s\n", fnames ? fnames.toChars() : "null"); //printf("stc = %llx\n", dstart._scope.stc); //printf("match:t/f = %d/%d\n", ta_last, m.last); } @@ -2707,7 +2705,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, else if (shared_this && !shared_dtor && tthis_fd !is null) tf.mod = tthis_fd.mod; } - MATCH mfa = tf.callMatch(tthis_fd, fargs_, fnames, 0, pMessage, sc); + MATCH mfa = tf.callMatch(tthis_fd, argumentList, 0, pMessage, sc); //printf("test1: mfa = %d\n", mfa); if (mfa == MATCH.nomatch) return 0; @@ -2740,8 +2738,8 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, * This is because f() is "more specialized." */ { - MATCH c1 = fd.leastAsSpecialized(m.lastf, fnames); - MATCH c2 = m.lastf.leastAsSpecialized(fd, fnames); + MATCH c1 = fd.leastAsSpecialized(m.lastf, argumentList.names); + MATCH c2 = m.lastf.leastAsSpecialized(fd, argumentList.names); //printf("c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) return firstIsBetter(); if (c1 < c2) return 0; @@ -2885,13 +2883,13 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, pr.dedargs = &dedtypesX; tdx.previous = ≺ // add this to threaded list - fd = resolveFuncCall(loc, sc, s, null, tthis, fargs, fnames, FuncResolveFlag.quiet); + fd = resolveFuncCall(loc, sc, s, null, tthis, argumentList, FuncResolveFlag.quiet); tdx.previous = pr.prev; // unlink from threaded list } else if (s.isFuncDeclaration()) { - fd = resolveFuncCall(loc, sc, s, null, tthis, fargs, fnames, FuncResolveFlag.quiet); + fd = resolveFuncCall(loc, sc, s, null, tthis, argumentList, FuncResolveFlag.quiet); } else goto Lerror; @@ -2910,7 +2908,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, Type tthis_fd = fd.needThis() && !fd.isCtorDeclaration() ? tthis : null; auto tf = cast(TypeFunction)fd.type; - MATCH mfa = tf.callMatch(tthis_fd, fargs_, fnames, 0, null, sc); + MATCH mfa = tf.callMatch(tthis_fd, argumentList, 0, null, sc); if (mfa < m.last) return 0; @@ -3012,16 +3010,16 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, // Disambiguate by tf.callMatch auto tf1 = fd.type.isTypeFunction(); auto tf2 = m.lastf.type.isTypeFunction(); - MATCH c1 = tf1.callMatch(tthis_fd, fargs_, fnames, 0, null, sc); - MATCH c2 = tf2.callMatch(tthis_best, fargs_, fnames, 0, null, sc); + MATCH c1 = tf1.callMatch(tthis_fd, argumentList, 0, null, sc); + MATCH c2 = tf2.callMatch(tthis_best, argumentList, 0, null, sc); //printf("2: c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) goto Ltd; if (c1 < c2) goto Ltd_best; } { // Disambiguate by picking the most specialized FunctionDeclaration - MATCH c1 = fd.leastAsSpecialized(m.lastf, fnames); - MATCH c2 = m.lastf.leastAsSpecialized(fd, fnames); + MATCH c1 = fd.leastAsSpecialized(m.lastf, argumentList.names); + MATCH c2 = m.lastf.leastAsSpecialized(fd, argumentList.names); //printf("3: c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) goto Ltd; if (c1 < c2) goto Ltd_best; @@ -3116,7 +3114,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, if (m.lastf.type.ty == Terror) goto Lerror; auto tf = m.lastf.type.isTypeFunction(); - if (!tf.callMatch(tthis_best, fargs_, fnames, 0, null, sc)) + if (!tf.callMatch(tthis_best, argumentList, 0, null, sc)) goto Lnomatch; /* As https://issues.dlang.org/show_bug.cgi?id=3682 shows, diff --git a/dmd/expression.d b/dmd/expression.d index 1a3b9c1216d..181437ae6ff 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -3654,12 +3654,17 @@ extern (C++) final class NewExp : Expression Expression lowering; // lowered druntime hook: `_d_newclass` - extern (D) this(const ref Loc loc, Expression thisexp, Type newtype, Expressions* arguments) + /// Puts the `arguments` and `names` into an `ArgumentList` for easily passing them around. + /// The fields are still separate for backwards compatibility + extern (D) ArgumentList argumentList() { return ArgumentList(arguments, names); } + + extern (D) this(const ref Loc loc, Expression thisexp, Type newtype, Expressions* arguments, Identifiers* names = null) { super(loc, EXP.new_, __traits(classInstanceSize, NewExp)); this.thisexp = thisexp; this.newtype = newtype; this.arguments = arguments; + this.names = names; } static NewExp create(const ref Loc loc, Expression thisexp, Type newtype, Expressions* arguments) @@ -5126,18 +5131,34 @@ extern (C++) final class DotTypeExp : UnaExp } } +/** + * The arguments of a function call + * + * Contains a list of expressions. If it is a named argument, the `names` + * list has a non-null entry at the same index. + */ +struct ArgumentList +{ + Expressions* arguments; // function arguments + Identifiers* names; // named argument identifiers +} + /*********************************************************** */ extern (C++) final class CallExp : UnaExp { Expressions* arguments; // function arguments - Identifiers* names; // named argument identifiers + Identifiers* names; // named argument identifiers FuncDeclaration f; // symbol to call bool directcall; // true if a virtual call is devirtualized bool inDebugStatement; /// true if this was in a debug statement bool ignoreAttributes; /// don't enforce attributes (e.g. call @gc function in @nogc code) VarDeclaration vthis2; // container for multi-context + /// Puts the `arguments` and `names` into an `ArgumentList` for easily passing them around. + /// The fields are still separate for backwards compatibility + extern (D) ArgumentList argumentList() { return ArgumentList(arguments, names); } + extern (D) this(const ref Loc loc, Expression e, Expressions* exps, Identifiers* names = null) { super(loc, EXP.call, __traits(classInstanceSize, CallExp), e); diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index c4ab8577761..6e99ff42976 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -262,7 +262,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0) uint xerrors = global.startGagging(); sc = sc.push(); - FuncDeclaration fslice = resolveFuncCall(ae.loc, sc, slice, tiargs, ae.e1.type, fargs, null, FuncResolveFlag.quiet); + FuncDeclaration fslice = resolveFuncCall(ae.loc, sc, slice, tiargs, ae.e1.type, ArgumentList(fargs), FuncResolveFlag.quiet); sc = sc.pop(); global.endGagging(xerrors); if (!fslice) @@ -1197,7 +1197,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = for (size_t i = 0; i < os.a.length; i++) { - if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, &a, null, FuncResolveFlag.quiet)) + if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, ArgumentList(&a), FuncResolveFlag.quiet)) { if (f.errors) return ErrorExp.get(); @@ -1214,7 +1214,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = { for (size_t i = 0; i < os.a.length; i++) { - if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, null, null, FuncResolveFlag.quiet)) + if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, ArgumentList(), FuncResolveFlag.quiet)) { if (f.errors) return ErrorExp.get(); @@ -1312,7 +1312,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = Expressions a; a.push(e2); - FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, null, FuncResolveFlag.quiet); + FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, ArgumentList(&a), FuncResolveFlag.quiet); if (fd && fd.type) { if (fd.errors) @@ -1332,7 +1332,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = } } { - FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, null, null, FuncResolveFlag.quiet); + FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, ArgumentList(), FuncResolveFlag.quiet); if (fd && fd.type) { if (fd.errors) @@ -1673,7 +1673,6 @@ private bool preFunctionParameters(Scope* sc, Identifiers* names, Expressions* e arg = ErrorExp.get(); err = true; } - (*exps)[i] = arg; } } @@ -1714,7 +1713,7 @@ private bool checkDefCtor(Loc loc, Type t) * tf = type of the function * ethis = `this` argument, `null` if none or not known * tthis = type of `this` argument, `null` if no `this` argument - * arguments = array of actual arguments to function call + * argumentsList = array of actual arguments to function call * fd = the function being called, `null` if called indirectly * prettype = set to return type of function * peprefix = set to expression to execute before `arguments[]` are evaluated, `null` if none @@ -1722,9 +1721,10 @@ private bool checkDefCtor(Loc loc, Type t) * true errors happened */ private bool functionParameters(const ref Loc loc, Scope* sc, - TypeFunction tf, Expression ethis, Type tthis, Expressions* arguments, Identifiers* names, FuncDeclaration fd, + TypeFunction tf, Expression ethis, Type tthis, ArgumentList argumentList, FuncDeclaration fd, Type* prettype, Expression* peprefix) { + Expressions* arguments = argumentList.arguments; //printf("functionParameters() %s\n", fd ? fd.toChars() : ""); assert(arguments); assert(fd || tf.next); @@ -1735,11 +1735,11 @@ private bool functionParameters(const ref Loc loc, Scope* sc, Expression eprefix = null; *peprefix = null; - if (names) + if (argumentList.names) { Expression[] newArgs = arguments.peekSlice(); const(char)* msg = null; - const result = tf.resolveNamedArgs(newArgs, names.peekSlice(), &msg); + const result = tf.resolveNamedArgs(newArgs, argumentList.names.peekSlice(), &msg); if (!result) { // while errors are usually already caught by `tf.callMatch`, @@ -3734,7 +3734,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (cd.ctor) { - FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.ctor, null, tb, exp.arguments, exp.names, FuncResolveFlag.standard); + FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.ctor, null, tb, exp.argumentList, FuncResolveFlag.standard); if (!f || f.errors) return setError(); @@ -3744,7 +3744,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor TypeFunction tf = f.type.isTypeFunction(); if (!exp.arguments) exp.arguments = new Expressions(); - if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, exp.names, f, &exp.type, &exp.argprefix)) + if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.argumentList, f, &exp.type, &exp.argprefix)) return setError(); exp.member = f.isCtorDeclaration(); @@ -3859,7 +3859,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // is the same type as the struct if (nargs && (sd.hasRegularCtor() || (sd.ctor && (*exp.arguments)[0].type.mutableOf() == sd.type.mutableOf()))) { - FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.ctor, null, tb, exp.arguments, exp.names, FuncResolveFlag.standard); + FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.ctor, null, tb, exp.argumentList, FuncResolveFlag.standard); if (!f || f.errors) return setError(); @@ -3869,7 +3869,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor TypeFunction tf = f.type.isTypeFunction(); if (!exp.arguments) exp.arguments = new Expressions(); - if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, exp.names, f, &exp.type, &exp.argprefix)) + if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.argumentList, f, &exp.type, &exp.argprefix)) return setError(); exp.member = f.isCtorDeclaration(); @@ -4740,14 +4740,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } FuncDeclaration resolveOverloadSet(Loc loc, Scope* sc, - OverloadSet os, Objects* tiargs, Type tthis, Expressions* arguments, Identifiers* names) + OverloadSet os, Objects* tiargs, Type tthis, ArgumentList argumentList) { FuncDeclaration f = null; foreach (s; os.a) { if (tiargs && s.isFuncDeclaration()) continue; - if (auto f2 = resolveFuncCall(loc, sc, s, tiargs, tthis, arguments, names, FuncResolveFlag.quiet)) + if (auto f2 = resolveFuncCall(loc, sc, s, tiargs, tthis, argumentList, FuncResolveFlag.quiet)) { if (f2.errors) return null; @@ -4807,7 +4807,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } // Do overload resolution - exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue.e1.type, exp.arguments, exp.names, FuncResolveFlag.standard); + exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue.e1.type, exp.argumentList, FuncResolveFlag.standard); if (!exp.f || exp.f.errors || exp.f.type.ty == Terror) return setError(); @@ -4970,9 +4970,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor tthis = ad.type.addMod(sc.func.type.mod); auto ctor = isSuper ? cd.baseClass.ctor : ad.ctor; if (auto os = ctor.isOverloadSet()) - exp.f = resolveOverloadSet(exp.loc, sc, os, null, tthis, exp.arguments, exp.names); + exp.f = resolveOverloadSet(exp.loc, sc, os, null, tthis, exp.argumentList); else - exp.f = resolveFuncCall(exp.loc, sc, ctor, null, tthis, exp.arguments, exp.names, FuncResolveFlag.standard); + exp.f = resolveFuncCall(exp.loc, sc, ctor, null, tthis, exp.argumentList, FuncResolveFlag.standard); if (!exp.f || exp.f.errors) return setError(); @@ -4997,7 +4997,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else if (auto oe = exp.e1.isOverExp()) { - exp.f = resolveOverloadSet(exp.loc, sc, oe.vars, tiargs, tthis, exp.arguments, exp.names); + exp.f = resolveOverloadSet(exp.loc, sc, oe.vars, tiargs, tthis, exp.argumentList); if (!exp.f) return setError(); if (ethis) @@ -5044,7 +5044,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor else if (exp.e1.op == EXP.dotVariable && (cast(DotVarExp)exp.e1).var.isOverDeclaration()) { DotVarExp dve = cast(DotVarExp)exp.e1; - exp.f = resolveFuncCall(exp.loc, sc, dve.var, tiargs, dve.e1.type, exp.arguments, exp.names, FuncResolveFlag.overloadOnly); + exp.f = resolveFuncCall(exp.loc, sc, dve.var, tiargs, dve.e1.type, exp.argumentList, FuncResolveFlag.overloadOnly); if (!exp.f) return setError(); if (exp.f.needThis()) @@ -5068,7 +5068,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { s = (cast(TemplateExp)exp.e1).td; L2: - exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, null, exp.arguments, exp.names, FuncResolveFlag.standard); + exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, null, exp.argumentList, FuncResolveFlag.standard); if (!exp.f || exp.f.errors) return setError(); if (exp.f.needThis()) @@ -5096,7 +5096,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } const(char)* failMessage; - if (!tf.callMatch(null, exp.arguments, exp.names, 0, &failMessage, sc)) + if (!tf.callMatch(null, exp.argumentList, 0, &failMessage, sc)) { OutBuffer buf; buf.writeByte('('); @@ -5163,13 +5163,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor tiargs = null; if (exp.f.overnext) - exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, exp.names, FuncResolveFlag.overloadOnly); + exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.argumentList, FuncResolveFlag.overloadOnly); else { exp.f = exp.f.toAliasFunc(); TypeFunction tf = cast(TypeFunction)exp.f.type; const(char)* failMessage; - if (!tf.callMatch(null, exp.arguments, exp.names, 0, &failMessage, sc)) + if (!tf.callMatch(null, exp.argumentList, 0, &failMessage, sc)) { OutBuffer buf; buf.writeByte('('); @@ -5211,7 +5211,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // // https://issues.dlang.org/show_bug.cgi?id=22157 if (exp.f.overnext) - exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, exp.names, FuncResolveFlag.standard); + exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.argumentList, FuncResolveFlag.standard); if (!exp.f || exp.f.errors) return setError(); @@ -5243,7 +5243,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor Expression argprefix; if (!exp.arguments) exp.arguments = new Expressions(); - if (functionParameters(exp.loc, sc, cast(TypeFunction)t1, ethis, tthis, exp.arguments, exp.names, exp.f, &exp.type, &argprefix)) + if (functionParameters(exp.loc, sc, cast(TypeFunction)t1, ethis, tthis, exp.argumentList, exp.f, &exp.type, &argprefix)) return setError(); if (!exp.type) diff --git a/dmd/frontend.h b/dmd/frontend.h index 9141cbbe64b..4ed21edb321 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -2308,6 +2308,21 @@ struct TemplateStats final {} }; +struct ArgumentList final +{ + Array* arguments; + Array* names; + ArgumentList() : + arguments(), + names() + { + } + ArgumentList(Array* arguments, Array* names = nullptr) : + arguments(arguments), + names(names) + {} +}; + enum : bool { LOGSEMANTIC = false }; enum class Modifiable @@ -4842,6 +4857,7 @@ struct ASTCodegen final using AddrExp = ::AddrExp; using AndAssignExp = ::AndAssignExp; using AndExp = ::AndExp; + using ArgumentList = ::ArgumentList; using ArrayExp = ::ArrayExp; using ArrayLengthExp = ::ArrayLengthExp; using ArrayLiteralExp = ::ArrayLiteralExp; diff --git a/dmd/func.d b/dmd/func.d index e7dc0862133..cf3e1154525 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -1090,7 +1090,7 @@ extern (C++) class FuncDeclaration : Declaration args.push(e); } - MATCH m = tg.callMatch(null, &args, names, 1); + MATCH m = tg.callMatch(null, ArgumentList(&args, names), 1); if (m > MATCH.nomatch) { /* A variadic parameter list is less specialized than a @@ -3129,15 +3129,15 @@ enum FuncResolveFlag : ubyte * s = instantiation symbol * tiargs = initial list of template arguments * tthis = if !NULL, the `this` argument type - * fargs = arguments to function - * fnames = names corresponding to fargs for named arguments + * argumentList = arguments to function * flags = see $(LREF FuncResolveFlag). * Returns: * if match is found, then function symbol, else null */ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, - Objects* tiargs, Type tthis, Expressions* fargs, Identifiers* fnames, FuncResolveFlag flags) + Objects* tiargs, Type tthis, ArgumentList argumentList, FuncResolveFlag flags) { + auto fargs = argumentList.arguments; if (!s) return null; // no match @@ -3166,7 +3166,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, return null; MatchAccumulator m; - functionResolve(m, s, loc, sc, tiargs, tthis, fargs, fnames); + functionResolve(m, s, loc, sc, tiargs, tthis, argumentList); auto orig_s = s; if (m.last > MATCH.nomatch && m.lastf) @@ -3289,7 +3289,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, } const(char)* failMessage; - functionResolve(m, orig_s, loc, sc, tiargs, tthis, fargs, fnames, &failMessage); + functionResolve(m, orig_s, loc, sc, tiargs, tthis, argumentList, &failMessage); if (failMessage) { .error(loc, "%s `%s%s%s` is not callable using argument types `%s`", @@ -3335,7 +3335,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, if (auto baseFunction = baseClass.search(baseClass.loc, fd.ident)) { MatchAccumulator mErr; - functionResolve(mErr, baseFunction, loc, sc, tiargs, baseClass.type, fargs, fnames); + functionResolve(mErr, baseFunction, loc, sc, tiargs, baseClass.type, argumentList); if (mErr.last > MATCH.nomatch && mErr.lastf) { errorSupplemental(loc, "%s `%s` hides base class function `%s`", @@ -3349,7 +3349,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, } } const(char)* failMessage; - functionResolve(m, orig_s, loc, sc, tiargs, tthis, fargs, fnames, &failMessage); + functionResolve(m, orig_s, loc, sc, tiargs, tthis, argumentList, &failMessage); if (failMessage) errorSupplemental(loc, failMessage); } diff --git a/dmd/mtype.d b/dmd/mtype.d index a181a456ca7..3d55708b7bb 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -2046,7 +2046,7 @@ extern (C++) abstract class Type : ASTNode } if (auto fd = s.isFuncDeclaration()) { - fd = resolveFuncCall(Loc.initial, null, fd, null, this, null, null, FuncResolveFlag.quiet); + fd = resolveFuncCall(Loc.initial, null, fd, null, this, ArgumentList(), FuncResolveFlag.quiet); if (!fd || fd.errors || !fd.functionSemantic()) return Type.terror; @@ -2068,7 +2068,7 @@ extern (C++) abstract class Type : ASTNode if (auto td = s.isTemplateDeclaration()) { assert(td._scope); - auto fd = resolveFuncCall(Loc.initial, null, td, null, this, null, null, FuncResolveFlag.quiet); + auto fd = resolveFuncCall(Loc.initial, null, td, null, this, ArgumentList(), FuncResolveFlag.quiet); if (!fd || fd.errors || !fd.functionSemantic()) return Type.terror; @@ -4626,17 +4626,16 @@ extern (C++) final class TypeFunction : TypeNext * Determine match level. * Params: * tthis = type of `this` pointer, null if not member function - * inArgs = array of function arguments. In case of a match, gets reordered based on named arguments. + * arguments = arguments to function call * flag = 1: performing a partial ordering match * pMessage = address to store error message, or null * sc = context * Returns: * MATCHxxxx */ - extern (D) MATCH callMatch(Type tthis, Expressions* inArgs, Identifiers* names, int flag = 0, const(char)** pMessage = null, Scope* sc = null) + extern (D) MATCH callMatch(Type tthis, ArgumentList argumentList, int flag = 0, const(char)** pMessage = null, Scope* sc = null) { //printf("TypeFunction::callMatch() %s\n", toChars()); - //printf("inArgs: %s, names: %s\n", inArgs ? inArgs.toChars() : "null", names ? names.toChars() : "null"); MATCH match = MATCH.exact; // assume exact match ubyte wildmatch = 0; @@ -4670,8 +4669,8 @@ extern (C++) final class TypeFunction : TypeNext } const nparams = parameterList.length; - Expression[] args = inArgs ? (*inArgs)[] : null; - Identifier[] nnames = names ? (*names)[] : null; + Expression[] args = argumentList.arguments ? (*argumentList.arguments)[] : null; + Identifier[] nnames = argumentList.names ? (*argumentList.names)[] : null; if (args.length > nparams) { @@ -7090,7 +7089,7 @@ bool isCopyable(Type t) el.type = cast() ts; Expressions args; args.push(el); - FuncDeclaration f = resolveFuncCall(Loc.initial, null, ctor, null, cast()ts, &args, null, FuncResolveFlag.quiet); + FuncDeclaration f = resolveFuncCall(Loc.initial, null, ctor, null, cast()ts, ArgumentList(&args), FuncResolveFlag.quiet); if (!f || f.storage_class & STC.disable) return false; } diff --git a/dmd/opover.d b/dmd/opover.d index 96ba05daa54..3c80e5e1d0e 100644 --- a/dmd/opover.d +++ b/dmd/opover.d @@ -711,7 +711,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) MatchAccumulator m; if (s) { - functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2, null); + functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(&args2)); if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) { return ErrorExp.get(); @@ -720,7 +720,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) FuncDeclaration lastf = m.lastf; if (s_r) { - functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, &args1, null); + functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, ArgumentList(&args1)); if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) { return ErrorExp.get(); @@ -793,7 +793,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) MatchAccumulator m; if (s_r) { - functionResolve(m, s_r, e.loc, sc, tiargs, e.e1.type, &args2, null); + functionResolve(m, s_r, e.loc, sc, tiargs, e.e1.type, ArgumentList(&args2)); if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) { return ErrorExp.get(); @@ -802,7 +802,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) FuncDeclaration lastf = m.lastf; if (s) { - functionResolve(m, s, e.loc, sc, tiargs, e.e2.type, &args1, null); + functionResolve(m, s, e.loc, sc, tiargs, e.e2.type, ArgumentList(&args1)); if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) { return ErrorExp.get(); @@ -1254,7 +1254,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null) args2[0] = e.e2; expandTuples(&args2); MatchAccumulator m; - functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2, null); + functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(&args2)); if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) { return ErrorExp.get(); @@ -1347,7 +1347,7 @@ private Expression compare_overload(BinExp e, Scope* sc, Identifier id, EXP* pop } if (s) { - functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2, null); + functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, ArgumentList(&args2)); if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) return ErrorExp.get(); } @@ -1355,7 +1355,7 @@ private Expression compare_overload(BinExp e, Scope* sc, Identifier id, EXP* pop int count = m.count; if (s_r) { - functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, &args1, null); + functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, ArgumentList(&args1)); if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors())) return ErrorExp.get(); } diff --git a/dmd/parse.d b/dmd/parse.d index c233016d220..85ba32e62d6 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -9415,13 +9415,17 @@ LagainStc: nextToken(); AST.Expressions* arguments = null; + AST.Identifiers* names = new AST.Identifiers(); // An anonymous nested class starts with "class" if (token.value == TOK.class_) { nextToken(); if (token.value == TOK.leftParenthesis) - arguments = parseArguments(); + { + arguments = new AST.Expressions(); + parseNamedArguments(arguments, names); + } AST.BaseClasses* baseclasses = null; if (token.value != TOK.leftCurly) @@ -9463,10 +9467,11 @@ LagainStc: } else if (token.value == TOK.leftParenthesis && t.ty != Tsarray) { - arguments = parseArguments(); + arguments = new AST.Expressions(); + parseNamedArguments(arguments, names); } - auto e = new AST.NewExp(loc, thisexp, t, arguments); + auto e = new AST.NewExp(loc, thisexp, t, arguments, names); return e; } diff --git a/dmd/semantic3.d b/dmd/semantic3.d index 8f95e0e3876..33a43187fa8 100644 --- a/dmd/semantic3.d +++ b/dmd/semantic3.d @@ -711,7 +711,7 @@ private extern(C++) final class Semantic3Visitor : Visitor // Insert implicit super() at start of fbody Type tthis = ad2.type.addMod(funcdecl.vthis.type.mod); - FuncDeclaration fd = resolveFuncCall(Loc.initial, sc2, cd.baseClass.ctor, null, tthis, null, null, FuncResolveFlag.quiet); + FuncDeclaration fd = resolveFuncCall(Loc.initial, sc2, cd.baseClass.ctor, null, tthis, ArgumentList(), FuncResolveFlag.quiet); if (!fd) { funcdecl.error("no match for implicit `super()` call in constructor"); diff --git a/dmd/statementsem.d b/dmd/statementsem.d index 768506ec5d7..ebf7bd1484f 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -1276,7 +1276,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor else if (auto td = sfront.isTemplateDeclaration()) { Expressions a; - if (auto f = resolveFuncCall(loc, sc, td, null, tab, &a, null, FuncResolveFlag.quiet)) + if (auto f = resolveFuncCall(loc, sc, td, null, tab, ArgumentList(&a), FuncResolveFlag.quiet)) tfront = f.type; } else if (auto d = sfront.toAlias().isDeclaration()) diff --git a/tests/dmd/compilable/named_arguments.d b/tests/dmd/compilable/named_arguments.d index ff84f474201..55cf36e23a8 100644 --- a/tests/dmd/compilable/named_arguments.d +++ b/tests/dmd/compilable/named_arguments.d @@ -13,3 +13,30 @@ static assert(fun( "x", "y", w: "w") == "xyZw"); // UFCS static assert("x".fun("y", w: "w") == "xyZw"); + +// tuples +alias AliasSeq(T...) = T; + +static assert("x".fun(x: AliasSeq!(), "y", w: "w") == "xyZw"); +static assert(AliasSeq!("x", "y").fun(w: "w", z: AliasSeq!()) == "xyZw"); +static assert(fun(y: AliasSeq!("y", "z", "w"), x: "x") == "xyzw"); + +// `new` expressions +class C +{ + int x, y; + + this(int x, int y) + { + this.x = x; + this.y = y; + } +} + +struct S +{ + int x, y; +} + +static assert(new C(y: 3, x: 2).x == 2); +// static assert(new S(y: 3, x: 2).x == 2); TODO diff --git a/tests/dmd/fail_compilation/call_function_type.d b/tests/dmd/fail_compilation/call_function_type.d index e60df95d76c..da60092c849 100644 --- a/tests/dmd/fail_compilation/call_function_type.d +++ b/tests/dmd/fail_compilation/call_function_type.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/call_function_type.d(18): Error: expected 1 function arguments, not 0 +fail_compilation/call_function_type.d(18): Error: missing argument for parameter #1: `int` fail_compilation/call_function_type.d(19): Error: cannot call `int(int)(3)` at compile time --- */ From d84aaeef535abc81abe4ce90cd6ff97848729510 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Thu, 26 Jan 2023 13:08:23 +0100 Subject: [PATCH 083/177] Improve `resolveNamedArgs` signature --- dmd/expression.d | 2 ++ dmd/expressionsem.d | 9 +++--- dmd/mtype.d | 77 +++++++++++++++++++++++---------------------- 3 files changed, 47 insertions(+), 41 deletions(-) diff --git a/dmd/expression.d b/dmd/expression.d index 181437ae6ff..71ebd3f2a33 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -5141,6 +5141,8 @@ struct ArgumentList { Expressions* arguments; // function arguments Identifiers* names; // named argument identifiers + + size_t length() const @nogc nothrow pure @safe { return arguments ? arguments.length : 0; } } /*********************************************************** diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 6e99ff42976..3d6ef59e037 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -1737,10 +1737,9 @@ private bool functionParameters(const ref Loc loc, Scope* sc, if (argumentList.names) { - Expression[] newArgs = arguments.peekSlice(); const(char)* msg = null; - const result = tf.resolveNamedArgs(newArgs, argumentList.names.peekSlice(), &msg); - if (!result) + auto resolvedArgs = tf.resolveNamedArgs(argumentList, &msg); + if (!resolvedArgs) { // while errors are usually already caught by `tf.callMatch`, // this can happen when calling `typeof(freefunc)` @@ -1748,8 +1747,10 @@ private bool functionParameters(const ref Loc loc, Scope* sc, error(loc, "%s", msg); return true; } + // note: the argument list should be mutated with named arguments / default arguments, + // so we can't simply change the pointer like `arguments = resolvedArgs;` arguments.setDim(0); - arguments.pushSlice(newArgs); + arguments.pushSlice((*resolvedArgs)[]); } size_t nargs = arguments ? arguments.length : 0; diff --git a/dmd/mtype.d b/dmd/mtype.d index 3d55708b7bb..35ea68364f3 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -4626,7 +4626,7 @@ extern (C++) final class TypeFunction : TypeNext * Determine match level. * Params: * tthis = type of `this` pointer, null if not member function - * arguments = arguments to function call + * argumentList = arguments to function call * flag = 1: performing a partial ordering match * pMessage = address to store error message, or null * sc = context @@ -4669,10 +4669,7 @@ extern (C++) final class TypeFunction : TypeNext } const nparams = parameterList.length; - Expression[] args = argumentList.arguments ? (*argumentList.arguments)[] : null; - Identifier[] nnames = argumentList.names ? (*argumentList.names)[] : null; - - if (args.length > nparams) + if (argumentList.length > nparams) { if (parameterList.varargs == VarArg.none) { @@ -4686,22 +4683,28 @@ extern (C++) final class TypeFunction : TypeNext } // https://issues.dlang.org/show_bug.cgi?id=22997 - if (parameterList.varargs == VarArg.none && nparams > args.length && !parameterList[args.length].defaultArg) + if (parameterList.varargs == VarArg.none && nparams > argumentList.length && !parameterList[argumentList.length].defaultArg) { OutBuffer buf; - buf.printf("too few arguments, expected %d, got %d", cast(int)nparams, cast(int)args.length); + buf.printf("too few arguments, expected %d, got %d", cast(int)nparams, cast(int)argumentList.length); if (pMessage) *pMessage = buf.extractChars(); return MATCH.nomatch; } - - if (!resolveNamedArgs(args, nnames, pMessage)) + auto resolvedArgs = resolveNamedArgs(argumentList, pMessage); + Expression[] args; + if (!resolvedArgs) { if (!pMessage || *pMessage) return MATCH.nomatch; // if no message was provided, it was because of overflow which will be diagnosed below match = MATCH.nomatch; + args = argumentList.arguments ? (*argumentList.arguments)[] : null; + } + else + { + args = (*resolvedArgs)[]; } foreach (u, p; parameterList) @@ -4798,16 +4801,19 @@ extern (C++) final class TypeFunction : TypeNext } /******************************** - * Re-order `args` based on named arguments it contains + * Re-order `argumentList` based on named arguments it contains * * Params: - * args = array of function arguments. - * pMessage = address to store error message, or null - * Returns: true on success, false on error + * argumentList = array of function arguments + * pMessage = address to store error message, or `null` + * Returns: re-ordered argument list, or `null` on error */ - extern(D) bool resolveNamedArgs(ref Expression[] args, Identifier[] names, const(char)** pMessage) + extern(D) Expressions* resolveNamedArgs(ArgumentList argumentList, const(char)** pMessage) { - auto newArgs = new Expression[parameterList.length]; + Expression[] args = argumentList.arguments ? (*argumentList.arguments)[] : null; + Identifier[] names = argumentList.names ? (*argumentList.names)[] : null; + auto newArgs = new Expressions(parameterList.length); + newArgs.zero(); size_t ci = 0; bool hasNamedArgs = false; foreach (i, arg; args) @@ -4826,55 +4832,52 @@ extern (C++) final class TypeFunction : TypeNext { if (pMessage) *pMessage = getMatchError("no parameter named `%s`", name.toChars()); - return false; + return null; } ci = pi; } if (ci >= newArgs.length) { - newArgs.length = ci + 1; if (!parameterList.varargs) { // Without named args, let the caller diagnose argument overflow if (hasNamedArgs && pMessage) *pMessage = getMatchError("argument `%s` goes past end of parameter list", arg.toChars()); - return false; + return null; } + while (ci >= newArgs.length) + newArgs.push(null); } - if (newArgs[ci]) + if ((*newArgs)[ci]) { if (pMessage) *pMessage = getMatchError("parameter `%s` assigned twice", parameterList[ci].toChars()); - return false; + return null; } - newArgs[ci++] = arg; + (*newArgs)[ci++] = arg; } - foreach (i, arg; newArgs) + foreach (i, arg; (*newArgs)[]) { - if (!arg) - { - if (parameterList[i].defaultArg) - continue; + if (arg || parameterList[i].defaultArg) + continue; - if (parameterList.varargs != VarArg.none && i + 1 == newArgs.length) - continue; + if (parameterList.varargs != VarArg.none && i + 1 == newArgs.length) + continue; - if (pMessage) - *pMessage = getMatchError("missing argument for parameter #%d: `%s`", - i + 1, parameterToChars(parameterList[i], this, false)); - return false; - } + if (pMessage) + *pMessage = getMatchError("missing argument for parameter #%d: `%s`", + i + 1, parameterToChars(parameterList[i], this, false)); + return null; } // strip trailing nulls from default arguments size_t e = newArgs.length; - while (e > 0 && newArgs[e - 1] is null) + while (e > 0 && (*newArgs)[e - 1] is null) { --e; } - - args = newArgs[0..e]; - return true; + newArgs.setDim(e); + return newArgs; } /+ From c1858a04f91214be2bbdb9bd305d82b210701685 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Thu, 26 Jan 2023 17:10:50 +0100 Subject: [PATCH 084/177] Implement named arguments for `new` expressions --- dmd/expressionsem.d | 49 ++++++++++++++----- tests/dmd/compilable/named_arguments.d | 2 +- .../fail_compilation/named_arguments_error.d | 24 ++++++--- 3 files changed, 55 insertions(+), 20 deletions(-) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 3d6ef59e037..e82cdb7ae09 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -1624,20 +1624,24 @@ private Expression rewriteOpAssign(BinExp exp) /**************************************** * Preprocess arguments to function. - * Input: - * reportErrors whether or not to report errors here. Some callers are not + * + * Tuples in argumentList get expanded, properties resolved, rewritten in place + * + * Params: + * sc = scope + * argumentList = arguments to function + * reportErrors = whether or not to report errors here. Some callers are not * checking actual function params, so they'll do their own error reporting - * Output: - * exps[] tuples expanded, properties resolved, rewritten in place * Returns: - * true a semantic error occurred + * `true` when a semantic error occurred */ -private bool preFunctionParameters(Scope* sc, Identifiers* names, Expressions* exps, const bool reportErrors = true) +private bool preFunctionParameters(Scope* sc, ArgumentList argumentList, const bool reportErrors = true) { + Expressions* exps = argumentList.arguments; bool err = false; if (exps) { - expandTuples(exps, names); + expandTuples(exps, argumentList.names); for (size_t i = 0; i < exps.length; i++) { @@ -3576,7 +3580,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { return setError(); } - if (preFunctionParameters(sc, /*names*/ null, exp.arguments)) + if (preFunctionParameters(sc, exp.argumentList)) { return setError(); } @@ -3881,8 +3885,20 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else { - if (!exp.arguments) + if (exp.names) + { + exp.arguments = resolveStructLiteralNamedArgs(sd, exp.type, sc, exp.loc, + exp.names ? (*exp.names)[] : null, + (size_t i, Type t) => (*exp.arguments)[i], + i => (*exp.arguments)[i].loc + ); + if (!exp.arguments) + return setError(); + } + else if (!exp.arguments) + { exp.arguments = new Expressions(); + } if (!sd.fit(exp.loc, sc, exp.arguments, tb)) return setError(); @@ -3931,6 +3947,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } Expression arg = (*exp.arguments)[i]; + if (exp.names && (*exp.names)[i]) + { + exp.error("no named argument `%s` allowed for array dimension", (*exp.names)[i].toChars()); + return setError(); + } + arg = resolveProperties(sc, arg); arg = arg.implicitCastTo(sc, Type.tsize_t); if (arg.op == EXP.error) @@ -3952,6 +3974,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else if (nargs == 1) { + if (exp.names && (*exp.names)[0]) + { + exp.error("no named argument `%s` allowed for scalar", (*exp.names)[0].toChars()); + return setError(); + } Expression e = (*exp.arguments)[0]; e = e.implicitCastTo(sc, tb); (*exp.arguments)[0] = e; @@ -4340,7 +4367,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (FuncExp fe = exp.e1.isFuncExp()) { if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc) || - preFunctionParameters(sc, exp.names, exp.arguments)) + preFunctionParameters(sc, exp.argumentList)) return setError(); // Run e1 semantic even if arguments have any errors @@ -4579,7 +4606,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc) || - preFunctionParameters(sc, exp.names, exp.arguments)) + preFunctionParameters(sc, exp.argumentList)) return setError(); // Check for call operator overload diff --git a/tests/dmd/compilable/named_arguments.d b/tests/dmd/compilable/named_arguments.d index 55cf36e23a8..5ad2a8a9dc4 100644 --- a/tests/dmd/compilable/named_arguments.d +++ b/tests/dmd/compilable/named_arguments.d @@ -39,4 +39,4 @@ struct S } static assert(new C(y: 3, x: 2).x == 2); -// static assert(new S(y: 3, x: 2).x == 2); TODO +static assert(new S(y: 3, x: 2).x == 2); diff --git a/tests/dmd/fail_compilation/named_arguments_error.d b/tests/dmd/fail_compilation/named_arguments_error.d index bc633a1da20..815c5fd1a71 100644 --- a/tests/dmd/fail_compilation/named_arguments_error.d +++ b/tests/dmd/fail_compilation/named_arguments_error.d @@ -1,17 +1,22 @@ /* TEST_OUTPUT: --- -fail_compilation/named_arguments_error.d(21): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)` -fail_compilation/named_arguments_error.d(21): parameter `x` assigned twice -fail_compilation/named_arguments_error.d(22): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)` -fail_compilation/named_arguments_error.d(22): argument `4` goes past end of parameter list -fail_compilation/named_arguments_error.d(23): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)` -fail_compilation/named_arguments_error.d(23): parameter `y` assigned twice -fail_compilation/named_arguments_error.d(24): Error: function `named_arguments_error.g(int x, int y, int z = 3)` is not callable using argument types `(int, int)` -fail_compilation/named_arguments_error.d(24): missing argument for parameter #1: `int x` +fail_compilation/named_arguments_error.d(26): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)` +fail_compilation/named_arguments_error.d(26): parameter `x` assigned twice +fail_compilation/named_arguments_error.d(27): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)` +fail_compilation/named_arguments_error.d(27): argument `4` goes past end of parameter list +fail_compilation/named_arguments_error.d(28): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)` +fail_compilation/named_arguments_error.d(28): parameter `y` assigned twice +fail_compilation/named_arguments_error.d(29): Error: function `named_arguments_error.g(int x, int y, int z = 3)` is not callable using argument types `(int, int)` +fail_compilation/named_arguments_error.d(29): missing argument for parameter #1: `int x` +fail_compilation/named_arguments_error.d(31): Error: no named argument `element` allowed for array dimension +fail_compilation/named_arguments_error.d(32): Error: no named argument `number` allowed for scalar --- */ + + + void f(int x, int y, int z); void g(int x, int y, int z = 3); @@ -22,4 +27,7 @@ void main() f(z: 3, 4, 5); f(y: 3, x: 4, 5); g(y: 4, z: 3); + + auto g0 = new int[](element: 3); + auto g1 = new int(number: 3); } From a0aa968149c621019173efe46041c673f93a555e Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Fri, 3 Feb 2023 17:41:45 +0100 Subject: [PATCH 085/177] Fix named arguments with `opCall` --- dmd/expressionsem.d | 2 +- tests/dmd/compilable/named_arguments.d | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index e82cdb7ae09..d2df7a6378f 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -4729,7 +4729,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor L1: // Rewrite as e1.call(arguments) Expression e = new DotIdExp(exp.loc, exp.e1, Id.call); - e = new CallExp(exp.loc, e, exp.arguments); + e = new CallExp(exp.loc, e, exp.arguments, exp.names); e = e.expressionSemantic(sc); result = e; return; diff --git a/tests/dmd/compilable/named_arguments.d b/tests/dmd/compilable/named_arguments.d index 5ad2a8a9dc4..02d9c934e61 100644 --- a/tests/dmd/compilable/named_arguments.d +++ b/tests/dmd/compilable/named_arguments.d @@ -31,6 +31,8 @@ class C this.x = x; this.y = y; } + + static C opCall(int x, int y) { return new C(x, y); } } struct S @@ -39,4 +41,21 @@ struct S } static assert(new C(y: 3, x: 2).x == 2); +static assert( C(y: 3, x: 2).x == 2); static assert(new S(y: 3, x: 2).x == 2); +static assert( S(y: 3, x: 2).x == 2); + +// opCall +struct Div +{ + static int opCall(int numer, int denom) { return numer / denom; } +} +static assert(Div(denom: 3, numer: 6) == 2); + +struct Concat +{ + string s = "s"; + string opCall(string st0, string st1) { return s ~ st0 ~ st1; } +} + +static assert(Concat.init("t0", "t1") == "st0t1"); From 473bc100589ab98cc33319c5e5e242604d722486 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Fri, 3 Feb 2023 17:46:44 +0100 Subject: [PATCH 086/177] print named arguments in error messages --- dmd/hdrgen.d | 18 +++++++++++++++--- .../fail_compilation/named_arguments_error.d | 5 +++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index 05586fe9653..c7e5690bc0a 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -2165,7 +2165,7 @@ private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg if (e.arguments && e.arguments.length) { buf.writeByte('('); - argsToBuffer(e.arguments, buf, hgs); + argsToBuffer(e.arguments, buf, hgs, null, e.names); buf.writeByte(')'); } } @@ -2469,7 +2469,7 @@ private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg else expToBuffer(e.e1, precedence[e.op], buf, hgs); buf.writeByte('('); - argsToBuffer(e.arguments, buf, hgs); + argsToBuffer(e.arguments, buf, hgs, null, e.names); buf.writeByte(')'); } @@ -3310,8 +3310,14 @@ private void parameterToBuffer(Parameter p, OutBuffer* buf, HdrGenState* hgs) /************************************************** * Write out argument list to buf. + * Params: + * expressions = argument list + * buf = buffer to write to + * hgs = context + * basis = replace `null`s in argument list with this expression (for sparse array literals) + * names = if non-null, use these as the names for the arguments */ -private void argsToBuffer(Expressions* expressions, OutBuffer* buf, HdrGenState* hgs, Expression basis = null) +private void argsToBuffer(Expressions* expressions, OutBuffer* buf, HdrGenState* hgs, Expression basis = null, Identifiers* names = null) { if (!expressions || !expressions.length) return; @@ -3321,6 +3327,12 @@ private void argsToBuffer(Expressions* expressions, OutBuffer* buf, HdrGenState* { if (i) buf.writestring(", "); + + if (names && i < names.length && (*names)[i]) + { + buf.writestring((*names)[i].toString()); + buf.writestring(": "); + } if (!el) el = basis; if (el) diff --git a/tests/dmd/fail_compilation/named_arguments_error.d b/tests/dmd/fail_compilation/named_arguments_error.d index 815c5fd1a71..b29fd8305be 100644 --- a/tests/dmd/fail_compilation/named_arguments_error.d +++ b/tests/dmd/fail_compilation/named_arguments_error.d @@ -11,15 +11,15 @@ fail_compilation/named_arguments_error.d(29): Error: function `named_arguments_e fail_compilation/named_arguments_error.d(29): missing argument for parameter #1: `int x` fail_compilation/named_arguments_error.d(31): Error: no named argument `element` allowed for array dimension fail_compilation/named_arguments_error.d(32): Error: no named argument `number` allowed for scalar +fail_compilation/named_arguments_error.d(33): Error: cannot implicitly convert expression `g(x: 3, y: 4, z: 5)` of type `int` to `string` --- */ - void f(int x, int y, int z); -void g(int x, int y, int z = 3); +int g(int x, int y, int z = 3); void main() { @@ -30,4 +30,5 @@ void main() auto g0 = new int[](element: 3); auto g1 = new int(number: 3); + string s = g(x: 3, y: 4, z: 5); } From 55b3c9507859f033a15e45968fad45e33a288ea5 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Fri, 3 Feb 2023 20:44:08 +0100 Subject: [PATCH 087/177] Handle named arguments in template deduction --- dmd/dsymbolsem.d | 10 ++-- dmd/dtemplate.d | 53 ++++++++++++------- dmd/expression.d | 12 +++++ dmd/frontend.h | 32 +++++------ dmd/template.h | 17 +++++- .../fail_compilation/named_arguments_error.d | 13 +++-- 6 files changed, 93 insertions(+), 44 deletions(-) diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 404f3b6208e..b0272c510f9 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -2714,7 +2714,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor override void visit(TemplateInstance ti) { - templateInstanceSemantic(ti, sc, null); + templateInstanceSemantic(ti, sc, ArgumentList()); } override void visit(TemplateMixin tm) @@ -2752,7 +2752,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor /* Run semantic on each argument, place results in tiargs[], * then find best match template with tiargs */ - if (!tm.findTempDecl(sc) || !tm.semanticTiargs(sc) || !tm.findBestMatch(sc, null)) + if (!tm.findTempDecl(sc) || !tm.semanticTiargs(sc) || !tm.findBestMatch(sc, ArgumentList())) { if (tm.semanticRun == PASS.initial) // forward reference had occurred { @@ -5824,7 +5824,7 @@ void addEnumMembers(EnumDeclaration ed, Scope* sc, ScopeDsymbol sds) }); } -void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, Expressions* fargs) +void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList argumentList) { //printf("[%s] TemplateInstance.dsymbolSemantic('%s', this=%p, gag = %d, sc = %p)\n", tempinst.loc.toChars(), tempinst.toChars(), tempinst, global.gag, sc); version (none) @@ -5896,7 +5896,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, Expressions* * then run semantic on each argument (place results in tiargs[]), * last find most specialized template from overload list/set. */ - if (!tempinst.findTempDecl(sc, null) || !tempinst.semanticTiargs(sc) || !tempinst.findBestMatch(sc, fargs)) + if (!tempinst.findTempDecl(sc, null) || !tempinst.semanticTiargs(sc) || !tempinst.findBestMatch(sc, argumentList)) { Lerror: if (tempinst.gagged) @@ -5949,6 +5949,8 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, Expressions* return aliasInstanceSemantic(tempinst, sc, tempdecl); } + Expressions* fargs = argumentList.arguments; // TODO: resolve named args + /* See if there is an existing TemplateInstantiation that already * implements the typeargs. If so, just refer to that one instead. */ diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 8b5db9c5475..df76d28a0b2 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -1051,7 +1051,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol * dedtypes deduced arguments * Return match level. */ - extern (D) MATCH matchWithInstance(Scope* sc, TemplateInstance ti, Objects* dedtypes, Expressions* fargs, int flag) + extern (D) MATCH matchWithInstance(Scope* sc, TemplateInstance ti, Objects* dedtypes, ArgumentList argumentList, int flag) { enum LOGM = 0; static if (LOGM) @@ -1169,6 +1169,12 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol if (fd) { TypeFunction tf = fd.type.isTypeFunction().syntaxCopy(); + if (argumentList.hasNames) + return nomatch(); + Expressions* fargs = argumentList.arguments; + // TODO: Expressions* fargs = tf.resolveNamedArgs(argumentList, null); + // if (!fargs) + // return nomatch(); fd = new FuncDeclaration(fd.loc, fd.endloc, fd.ident, fd.storage_class, tf); fd.parent = ti; @@ -1238,7 +1244,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol * match this is at least as specialized as td2 * 0 td2 is more specialized than this */ - MATCH leastAsSpecialized(Scope* sc, TemplateDeclaration td2, Expressions* fargs) + MATCH leastAsSpecialized(Scope* sc, TemplateDeclaration td2, ArgumentList argumentList) { enum LOG_LEASTAS = 0; static if (LOG_LEASTAS) @@ -1273,7 +1279,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol Objects dedtypes = Objects(td2.parameters.length); // Attempt a type deduction - MATCH m = td2.matchWithInstance(sc, ti, &dedtypes, fargs, 1); + MATCH m = td2.matchWithInstance(sc, ti, &dedtypes, argumentList, 1); if (m > MATCH.nomatch) { /* A non-variadic template is more specialized than a @@ -1304,14 +1310,14 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol * sc instantiation scope * fd * tthis 'this' argument if !NULL - * fargs arguments to function + * argumentList arguments to function * Output: * fd Partially instantiated function declaration * ti.tdtypes Expression/Type deduced template arguments * Returns: * match pair of initial and inferred template arguments */ - extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateInstance ti, Scope* sc, ref FuncDeclaration fd, Type tthis, Expressions* fargs) + extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateInstance ti, Scope* sc, ref FuncDeclaration fd, Type tthis, ArgumentList argumentList) { size_t nfparams; size_t nfargs; @@ -1459,7 +1465,10 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol fparameters = fd.getParameterList(); nfparams = fparameters.length; // number of function parameters - nfargs = fargs ? fargs.length : 0; // number of function arguments + nfargs = argumentList.length; // number of function arguments + if (argumentList.hasNames) + return matcherror(); // TODO: resolve named args + Expressions* fargs = argumentList.arguments; // TODO: resolve named args /* Check for match of function arguments with variadic template * parameter, such as: @@ -2600,7 +2609,6 @@ extern (C++) final class TypeDeduced : Type void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, Objects* tiargs, Type tthis, ArgumentList argumentList, const(char)** pMessage = null) { - Expressions* fargs = argumentList.arguments; version (none) { printf("functionResolve() dstart = %s\n", dstart.toChars()); @@ -2831,6 +2839,11 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, } //printf("td = %s\n", td.toChars()); + if (argumentList.hasNames) + { + .error(loc, "named arguments with Implicit Function Template Instantiation are not supported yet"); + goto Lerror; + } auto f = td.onemember ? td.onemember.isFuncDeclaration() : null; if (!f) { @@ -2839,12 +2852,12 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, auto ti = new TemplateInstance(loc, td, tiargs); Objects dedtypes = Objects(td.parameters.length); assert(td.semanticRun != PASS.initial); - MATCH mta = td.matchWithInstance(sc, ti, &dedtypes, fargs, 0); + MATCH mta = td.matchWithInstance(sc, ti, &dedtypes, argumentList, 0); //printf("matchWithInstance = %d\n", mta); if (mta == MATCH.nomatch || mta < ta_last) // no match or less match return 0; - ti.templateInstanceSemantic(sc, fargs); + ti.templateInstanceSemantic(sc, argumentList); if (!ti.inst) // if template failed to expand return 0; @@ -2955,7 +2968,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, ti.parent = td.parent; // Maybe calculating valid 'enclosing' is unnecessary. auto fd = f; - MATCHpair x = td.deduceFunctionTemplateMatch(ti, sc, fd, tthis, fargs); + MATCHpair x = td.deduceFunctionTemplateMatch(ti, sc, fd, tthis, argumentList); MATCH mta = x.mta; MATCH mfa = x.mfa; //printf("match:t/f = %d/%d\n", mta, mfa); @@ -2999,8 +3012,8 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, if (td_best) { // Disambiguate by picking the most specialized TemplateDeclaration - MATCH c1 = td.leastAsSpecialized(sc, td_best, fargs); - MATCH c2 = td_best.leastAsSpecialized(sc, td, fargs); + MATCH c1 = td.leastAsSpecialized(sc, td_best, argumentList); + MATCH c2 = td_best.leastAsSpecialized(sc, td, argumentList); //printf("1: c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) goto Ltd; if (c1 < c2) goto Ltd_best; @@ -3086,7 +3099,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc, sc = td_best._scope; // workaround for Type.aliasthisOf auto ti = new TemplateInstance(loc, td_best, ti_best.tiargs); - ti.templateInstanceSemantic(sc, fargs); + ti.templateInstanceSemantic(sc, argumentList); m.lastf = ti.toAlias().isFuncDeclaration(); if (!m.lastf) @@ -6932,12 +6945,12 @@ extern (C++) class TemplateInstance : ScopeDsymbol * * Params: * sc = the scope this TemplateInstance resides in - * fargs = function arguments in case of a template function, null otherwise + * argumentList = function arguments in case of a template function * * Returns: * `true` if a match was found, `false` otherwise */ - extern (D) final bool findBestMatch(Scope* sc, Expressions* fargs) + extern (D) final bool findBestMatch(Scope* sc, ArgumentList argumentList) { if (havetempdecl) { @@ -6946,7 +6959,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol assert(tempdecl._scope); // Deduce tdtypes tdtypes.setDim(tempdecl.parameters.length); - if (!tempdecl.matchWithInstance(sc, this, &tdtypes, fargs, 2)) + if (!tempdecl.matchWithInstance(sc, this, &tdtypes, argumentList, 2)) { error("incompatible arguments for template instantiation"); return false; @@ -6996,7 +7009,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol dedtypes.zero(); assert(td.semanticRun != PASS.initial); - MATCH m = td.matchWithInstance(sc, this, &dedtypes, fargs, 0); + MATCH m = td.matchWithInstance(sc, this, &dedtypes, argumentList, 0); //printf("matchWithInstance = %d\n", m); if (m == MATCH.nomatch) // no match at all return 0; @@ -7005,8 +7018,8 @@ extern (C++) class TemplateInstance : ScopeDsymbol // Disambiguate by picking the most specialized TemplateDeclaration { - MATCH c1 = td.leastAsSpecialized(sc, td_best, fargs); - MATCH c2 = td_best.leastAsSpecialized(sc, td, fargs); + MATCH c1 = td.leastAsSpecialized(sc, td_best, argumentList); + MATCH c2 = td_best.leastAsSpecialized(sc, td, argumentList); //printf("c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) goto Ltd; if (c1 < c2) goto Ltd_best; @@ -7272,7 +7285,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol return 1; } } - MATCH m = td.matchWithInstance(sc, this, &dedtypes, null, 0); + MATCH m = td.matchWithInstance(sc, this, &dedtypes, ArgumentList(), 0); if (m == MATCH.nomatch) return 0; } diff --git a/dmd/expression.d b/dmd/expression.d index 71ebd3f2a33..571da4269d4 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -5143,6 +5143,18 @@ struct ArgumentList Identifiers* names; // named argument identifiers size_t length() const @nogc nothrow pure @safe { return arguments ? arguments.length : 0; } + + /// Returns: whether this argument list contains any named arguments + bool hasNames() const @nogc nothrow pure @safe + { + if (names is null) + return false; + foreach (name; *names) + if (name !is null) + return true; + + return false; + } } /*********************************************************** diff --git a/dmd/frontend.h b/dmd/frontend.h index 4ed21edb321..964154328cf 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -1300,6 +1300,21 @@ struct AssocArray final } }; +struct ArgumentList final +{ + Array* arguments; + Array* names; + ArgumentList() : + arguments(), + names() + { + } + ArgumentList(Array* arguments, Array* names = nullptr) : + arguments(arguments), + names(names) + {} +}; + enum class TY : uint8_t { Tarray = 0u, @@ -2308,21 +2323,6 @@ struct TemplateStats final {} }; -struct ArgumentList final -{ - Array* arguments; - Array* names; - ArgumentList() : - arguments(), - names() - { - } - ArgumentList(Array* arguments, Array* names = nullptr) : - arguments(arguments), - names(names) - {} -}; - enum : bool { LOGSEMANTIC = false }; enum class Modifiable @@ -6694,7 +6694,7 @@ class TemplateDeclaration final : public ScopeDsymbol Visibility visible() override; const char* getConstraintEvalError(const char*& tip); Scope* scopeForTemplateParameters(TemplateInstance* ti, Scope* sc); - MATCH leastAsSpecialized(Scope* sc, TemplateDeclaration* td2, Array* fargs); + MATCH leastAsSpecialized(Scope* sc, TemplateDeclaration* td2, ArgumentList argumentList); RootObject* declareParameter(Scope* sc, TemplateParameter* tp, RootObject* o); TemplateDeclaration* isTemplateDeclaration() override; TemplateTupleParameter* isVariadic(); diff --git a/dmd/template.h b/dmd/template.h index 8e8ba16c0ab..12b21207b8e 100644 --- a/dmd/template.h +++ b/dmd/template.h @@ -46,6 +46,21 @@ struct TemplatePrevious Objects *dedargs; }; +struct ArgumentList final +{ + Expressions* arguments; + Identifiers* names; + ArgumentList() : + arguments(), + names() + { + } + ArgumentList(Expressions* arguments, Identifiers* names = nullptr) : + arguments(arguments), + names(names) + {} +}; + class TemplateDeclaration final : public ScopeDsymbol { public: @@ -81,7 +96,7 @@ class TemplateDeclaration final : public ScopeDsymbol Visibility visible() override; - MATCH leastAsSpecialized(Scope *sc, TemplateDeclaration *td2, Expressions *fargs); + MATCH leastAsSpecialized(Scope* sc, TemplateDeclaration* td2, ArgumentList argumentList); RootObject *declareParameter(Scope *sc, TemplateParameter *tp, RootObject *o); TemplateDeclaration *isTemplateDeclaration() override { return this; } diff --git a/tests/dmd/fail_compilation/named_arguments_error.d b/tests/dmd/fail_compilation/named_arguments_error.d index b29fd8305be..0daaa5ffce0 100644 --- a/tests/dmd/fail_compilation/named_arguments_error.d +++ b/tests/dmd/fail_compilation/named_arguments_error.d @@ -12,13 +12,13 @@ fail_compilation/named_arguments_error.d(29): missing argument for parame fail_compilation/named_arguments_error.d(31): Error: no named argument `element` allowed for array dimension fail_compilation/named_arguments_error.d(32): Error: no named argument `number` allowed for scalar fail_compilation/named_arguments_error.d(33): Error: cannot implicitly convert expression `g(x: 3, y: 4, z: 5)` of type `int` to `string` +fail_compilation/named_arguments_error.d(34): Error: named arguments with Implicit Function Template Instantiation are not supported yet +fail_compilation/named_arguments_error.d(34): Error: none of the overloads of template `named_arguments_error.tempfun` are callable using argument types `!()(string, int)` +fail_compilation/named_arguments_error.d(38): Candidate is: `tempfun(T, U)(T t, U u)` --- */ - - void f(int x, int y, int z); - int g(int x, int y, int z = 3); void main() @@ -31,4 +31,11 @@ void main() auto g0 = new int[](element: 3); auto g1 = new int(number: 3); string s = g(x: 3, y: 4, z: 5); + enum x = tempfun(u: "u", t: 0); +} + +// template arguments +int tempfun(T, U)(T t, U u) +{ + return 3; } From bdd1af58392c9bc762e7b9d6a30cf1438670be4b Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Mon, 13 Feb 2023 12:50:23 +0100 Subject: [PATCH 088/177] Address Walter's review --- dmd/mtype.d | 15 +++++++++++---- tests/dmd/compilable/named_arguments.d | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/dmd/mtype.d b/dmd/mtype.d index 35ea68364f3..e0bf723e43c 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -4801,7 +4801,8 @@ extern (C++) final class TypeFunction : TypeNext } /******************************** - * Re-order `argumentList` based on named arguments it contains + * Convert an `argumentList`, which may contain named arguments, into + * a list of arguments in the order of the parameter list. * * Params: * argumentList = array of function arguments @@ -4827,7 +4828,7 @@ extern (C++) final class TypeFunction : TypeNext if (name) { hasNamedArgs = true; - const pi = parameterIndex(name); + const pi = findParameterIndex(name); if (pi == -1) { if (pMessage) @@ -4991,8 +4992,14 @@ extern (C++) final class TypeFunction : TypeNext v.visit(this); } - /// Returns: index of parameter with name `ident` or -1 if not found - private extern(D) ptrdiff_t parameterIndex(Identifier ident) + /** + * Look for the index of parameter `ident` in the parameter list + * + * Params: + * ident = identifier of parameter to search for + * Returns: index of parameter with name `ident` or -1 if not found + */ + private extern(D) ptrdiff_t findParameterIndex(Identifier ident) { foreach (i, p; this.parameterList) { diff --git a/tests/dmd/compilable/named_arguments.d b/tests/dmd/compilable/named_arguments.d index 02d9c934e61..240bfe1ea97 100644 --- a/tests/dmd/compilable/named_arguments.d +++ b/tests/dmd/compilable/named_arguments.d @@ -10,6 +10,7 @@ static assert(fun(x: "x", y: "y", z: "z", w: "w") == "xyzw"); static assert(fun(w: "w", z: "z", y: "y", x: "x") == "xyzw"); static assert(fun(y: "y", "z", x: "x") == "xyzW"); static assert(fun( "x", "y", w: "w") == "xyZw"); +static assert(fun(x: "x", "y", z: "z") == "xyzW"); // UFCS static assert("x".fun("y", w: "w") == "xyZw"); From e3871fee67aff5b7b81f14862f2c60bc9735f038 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Mon, 13 Feb 2023 13:14:36 +0100 Subject: [PATCH 089/177] Add test for unknown named argument --- .../fail_compilation/named_arguments_error.d | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/tests/dmd/fail_compilation/named_arguments_error.d b/tests/dmd/fail_compilation/named_arguments_error.d index 0daaa5ffce0..0900e6010d1 100644 --- a/tests/dmd/fail_compilation/named_arguments_error.d +++ b/tests/dmd/fail_compilation/named_arguments_error.d @@ -1,24 +1,30 @@ /* TEST_OUTPUT: --- -fail_compilation/named_arguments_error.d(26): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)` -fail_compilation/named_arguments_error.d(26): parameter `x` assigned twice -fail_compilation/named_arguments_error.d(27): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)` -fail_compilation/named_arguments_error.d(27): argument `4` goes past end of parameter list -fail_compilation/named_arguments_error.d(28): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)` -fail_compilation/named_arguments_error.d(28): parameter `y` assigned twice -fail_compilation/named_arguments_error.d(29): Error: function `named_arguments_error.g(int x, int y, int z = 3)` is not callable using argument types `(int, int)` -fail_compilation/named_arguments_error.d(29): missing argument for parameter #1: `int x` -fail_compilation/named_arguments_error.d(31): Error: no named argument `element` allowed for array dimension -fail_compilation/named_arguments_error.d(32): Error: no named argument `number` allowed for scalar -fail_compilation/named_arguments_error.d(33): Error: cannot implicitly convert expression `g(x: 3, y: 4, z: 5)` of type `int` to `string` -fail_compilation/named_arguments_error.d(34): Error: named arguments with Implicit Function Template Instantiation are not supported yet -fail_compilation/named_arguments_error.d(34): Error: none of the overloads of template `named_arguments_error.tempfun` are callable using argument types `!()(string, int)` -fail_compilation/named_arguments_error.d(38): Candidate is: `tempfun(T, U)(T t, U u)` +fail_compilation/named_arguments_error.d(32): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)` +fail_compilation/named_arguments_error.d(32): parameter `x` assigned twice +fail_compilation/named_arguments_error.d(33): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)` +fail_compilation/named_arguments_error.d(33): argument `4` goes past end of parameter list +fail_compilation/named_arguments_error.d(34): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)` +fail_compilation/named_arguments_error.d(34): parameter `y` assigned twice +fail_compilation/named_arguments_error.d(35): Error: function `named_arguments_error.f(int x, int y, int z)` is not callable using argument types `(int, int, int)` +fail_compilation/named_arguments_error.d(35): no parameter named `a` +fail_compilation/named_arguments_error.d(36): Error: function `named_arguments_error.g(int x, int y, int z = 3)` is not callable using argument types `(int, int)` +fail_compilation/named_arguments_error.d(36): missing argument for parameter #1: `int x` +fail_compilation/named_arguments_error.d(38): Error: no named argument `element` allowed for array dimension +fail_compilation/named_arguments_error.d(39): Error: no named argument `number` allowed for scalar +fail_compilation/named_arguments_error.d(40): Error: cannot implicitly convert expression `g(x: 3, y: 4, z: 5)` of type `int` to `string` +fail_compilation/named_arguments_error.d(41): Error: named arguments with Implicit Function Template Instantiation are not supported yet +fail_compilation/named_arguments_error.d(41): Error: none of the overloads of template `named_arguments_error.tempfun` are callable using argument types `!()(string, int)` +fail_compilation/named_arguments_error.d(45): Candidate is: `tempfun(T, U)(T t, U u)` --- */ + + + void f(int x, int y, int z); + int g(int x, int y, int z = 3); void main() @@ -26,6 +32,7 @@ void main() f(x: 3, x: 3, 5); f(z: 3, 4, 5); f(y: 3, x: 4, 5); + f(a: 3, b: 4, 5); g(y: 4, z: 3); auto g0 = new int[](element: 3); From efdbd89c94384dc2667eee3570a8f56d5bab3a11 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 13 Feb 2023 15:14:35 -0800 Subject: [PATCH 090/177] Revert "reapply fix Issue 23479 - ImportC recognizes .i and .c files, but not .h files" (dlang/dmd!14870) This reverts commit 38073d02b36a3b7c7278019126b117d2db203bf3. --- dmd/dmodule.d | 10 ++--- dmd/file_manager.d | 75 +++++++++++++++----------------- dmd/globals.d | 1 - dmd/mars.d | 2 - tests/dmd/compilable/test23479.h | 2 - 5 files changed, 39 insertions(+), 51 deletions(-) delete mode 100644 tests/dmd/compilable/test23479.h diff --git a/dmd/dmodule.d b/dmd/dmodule.d index c1a014da3d8..bb518fa081d 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -458,7 +458,6 @@ extern (C++) final class Module : Package } else if (!FileName.equalsExt(srcfilename, mars_ext) && !FileName.equalsExt(srcfilename, hdr_ext) && - !FileName.equalsExt(srcfilename, h_ext) && !FileName.equalsExt(srcfilename, c_ext) && !FileName.equalsExt(srcfilename, i_ext) && !FileName.equalsExt(srcfilename, dd_ext)) @@ -687,8 +686,7 @@ extern (C++) final class Module : Package } if (global.preprocess && - (FileName.equalsExt(srcfile.toString(), c_ext) || - FileName.equalsExt(srcfile.toString(), h_ext)) && + FileName.equalsExt(srcfile.toString(), c_ext) && FileName.exists(srcfile.toString())) { filename = global.preprocess(srcfile, loc, ifile, &defines); // run C preprocessor @@ -761,12 +759,10 @@ extern (C++) final class Module : Package DsymbolTable dst; Package ppack = null; - /* If it has the extension ".c" or ".h", it is a "C" file. + /* If it has the extension ".c", it is a "C" file. * If it has the extension ".i", it is a preprocessed "C" file. */ - if (FileName.equalsExt(arg, c_ext) || - FileName.equalsExt(arg, h_ext) || - FileName.equalsExt(arg, i_ext)) + if (FileName.equalsExt(arg, c_ext) || FileName.equalsExt(arg, i_ext)) { filetype = FileType.c; diff --git a/dmd/file_manager.d b/dmd/file_manager.d index ac1c6918540..a0e5d0519c8 100644 --- a/dmd/file_manager.d +++ b/dmd/file_manager.d @@ -141,15 +141,6 @@ nothrow: return sd; scope(exit) FileName.free(sd.ptr); - static const(char)[] check(const(char)[] p, const(char)[] sx) - { - auto fn = FileName.combine(p, sx); - if (FileName.exists(fn)) - return fn; - FileName.free(fn.ptr); - return null; - } - if (checkLocal) { auto cached = packageStatus.lookup(filename); @@ -161,10 +152,15 @@ nothrow: * Therefore, the result should be: filename/package.d * iff filename/package.d is a file */ - if (auto fn = check(filename, package_di)) - return fn; - if (auto fn = check(filename, package_d)) - return fn; + const ni = FileName.combine(filename, package_di); + if (FileName.exists(ni) == 1) + return ni; + FileName.free(ni.ptr); + + const n = FileName.combine(filename, package_d); + if (FileName.exists(n) == 1) + return n; + FileName.free(n.ptr); } } @@ -172,28 +168,29 @@ nothrow: return null; if (!path.length) return null; - foreach (entry; path) { const p = entry.toDString(); - { - const(char)[] n = FileName.combine(p, sdi); - if (!packageExists(n)) { - FileName.free(n.ptr); - continue; // no need to check for anything else. - } - if (FileName.exists(n) == 1) { - return n; - } + const(char)[] n = FileName.combine(p, sdi); + + if (!packageExists(n)) { FileName.free(n.ptr); + continue; // no need to check for anything else. } + if (FileName.exists(n) == 1) { + return n; + } + FileName.free(n.ptr); - if (auto fn = check(p, sd)) - return fn; + n = FileName.combine(p, sd); + if (FileName.exists(n) == 1) { + return n; + } + FileName.free(n.ptr); - const(char)[] b = FileName.removeExt(filename); - const(char)[] n = FileName.combine(p, b); + const b = FileName.removeExt(filename); + n = FileName.combine(p, b); FileName.free(b.ptr); scope(exit) FileName.free(n.ptr); @@ -218,18 +215,13 @@ nothrow: } } - /* ImportC: No D modules found, now search along path[] for .i file, then .h file, then .c file. + /* ImportC: No D modules found, now search along path[] for .i file, then .c file. */ const si = FileName.forceExt(filename, i_ext); if (FileName.exists(si) == 1) return si; scope(exit) FileName.free(si.ptr); - const sh = FileName.forceExt(filename, h_ext); - if (FileName.exists(sh) == 1) - return sh; - scope(exit) FileName.free(sh.ptr); - const sc = FileName.forceExt(filename, c_ext); if (FileName.exists(sc) == 1) return sc; @@ -238,12 +230,17 @@ nothrow: { const p = entry.toDString(); - if (auto fn = check(p, si)) - return fn; - if (auto fn = check(p, sh)) - return fn; - if (auto fn = check(p, sc)) - return fn; + const(char)[] n = FileName.combine(p, si); + if (FileName.exists(n) == 1) { + return n; + } + FileName.free(n.ptr); + + n = FileName.combine(p, sc); + if (FileName.exists(n) == 1) { + return n; + } + FileName.free(n.ptr); } return null; } diff --git a/dmd/globals.d b/dmd/globals.d index 2e2a8a2e5cc..e6b4e31690a 100644 --- a/dmd/globals.d +++ b/dmd/globals.d @@ -252,7 +252,6 @@ enum hdr_ext = "di"; // for D 'header' import files enum json_ext = "json"; // for JSON files enum map_ext = "map"; // for .map files enum c_ext = "c"; // for C source files -enum h_ext = "h"; // for C header source files enum i_ext = "i"; // for preprocessed C source file /** diff --git a/dmd/mars.d b/dmd/mars.d index 3c11b373d8e..ca0645bbf08 100644 --- a/dmd/mars.d +++ b/dmd/mars.d @@ -2532,7 +2532,6 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param FileName.equals(ext, mars_ext) == 0 && FileName.equals(ext, hdr_ext) == 0 && FileName.equals(ext, i_ext) == 0 && - FileName.equals(ext, h_ext) == 0 && FileName.equals(ext, c_ext) == 0) { error("-run must be followed by a source file, not '%s'", arguments[i + 1]); @@ -2877,7 +2876,6 @@ Module createModule(const(char)* file, ref Strings libmodules, const ref Target if (FileName.equals(ext, mars_ext) || FileName.equals(ext, hdr_ext ) || FileName.equals(ext, dd_ext ) || - FileName.equals(ext, h_ext ) || FileName.equals(ext, c_ext ) || FileName.equals(ext, i_ext )) { diff --git a/tests/dmd/compilable/test23479.h b/tests/dmd/compilable/test23479.h deleted file mode 100644 index 791e2dd399c..00000000000 --- a/tests/dmd/compilable/test23479.h +++ /dev/null @@ -1,2 +0,0 @@ - -int foo() { } From 7eb95d0143bff1a6c3508678cb01245f2bcba3d9 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 14 Feb 2023 02:36:11 -0800 Subject: [PATCH 091/177] reboot separate out mangleType() (dlang/dmd!14862) --- dmd/dmangle.d | 568 +++++++++++++++++++++++++++----------------------- 1 file changed, 309 insertions(+), 259 deletions(-) diff --git a/dmd/dmangle.d b/dmd/dmangle.d index 59bad02fe29..72a44765787 100644 --- a/dmd/dmangle.d +++ b/dmd/dmangle.d @@ -14,17 +14,18 @@ module dmd.dmangle; -import dmd.astenums; /****************************************************************************** * Returns exact mangled name of function. */ extern (C++) const(char)* mangleExact(FuncDeclaration fd) { + //printf("mangleExact()\n"); if (!fd.mangleString) { OutBuffer buf; - scope Mangler v = new Mangler(&buf); + auto backref = Backref(null); + scope Mangler v = new Mangler(&buf, &backref); v.mangleExact(fd); fd.mangleString = buf.extractChars(); } @@ -33,30 +34,38 @@ extern (C++) const(char)* mangleExact(FuncDeclaration fd) extern (C++) void mangleToBuffer(Type t, OutBuffer* buf) { + //printf("mangleToBuffer t()\n"); if (t.deco) buf.writestring(t.deco); else { - scope Mangler v = new Mangler(buf, t); - v.visitWithMask(t, 0); + auto backref = Backref(t); + mangleType(t, 0, buf, backref); + //printf("%s\n", buf.peekChars()); } } extern (C++) void mangleToBuffer(Expression e, OutBuffer* buf) { - scope Mangler v = new Mangler(buf); + //printf("mangleToBuffer e()\n"); + auto backref = Backref(null); + scope Mangler v = new Mangler(buf, &backref); e.accept(v); } extern (C++) void mangleToBuffer(Dsymbol s, OutBuffer* buf) { - scope Mangler v = new Mangler(buf); + //printf("mangleToBuffer s(%s)\n", s.toChars()); + auto backref = Backref(null); + scope Mangler v = new Mangler(buf, &backref); s.accept(v); } extern (C++) void mangleToBuffer(TemplateInstance ti, OutBuffer* buf) { - scope Mangler v = new Mangler(buf); + //printf("mangleToBuffer ti()\n"); + auto backref = Backref(null); + scope Mangler v = new Mangler(buf, &backref); v.mangleTemplateInstance(ti); } @@ -127,6 +136,7 @@ import core.stdc.string; import dmd.aggregate; import dmd.arraytypes; +import dmd.astenums; import dmd.dclass; import dmd.declaration; import dmd.dmodule; @@ -231,233 +241,344 @@ unittest } } -private extern (C++) final class Mangler : Visitor +/************************************************ + * Append the mangling of type `t` to `buf`. + * Params: + * t = type to mangle + * modMask = mod bits currently applying to t + * buf = buffer to append mangling to + * backref = state of back references (updated) + */ +void mangleType(Type t, ubyte modMask, OutBuffer* buf, ref Backref backref) { - alias visit = Visitor.visit; -public: - static assert(Key.sizeof == size_t.sizeof); - - OutBuffer* buf; - Backref backref; - - extern (D) this(OutBuffer* buf, Type rootType = null) scope - { - this.buf = buf; - this.backref = Backref(rootType); - } - - void mangleSymbol(Dsymbol s) - { - s.accept(this); - } - - void mangleType(Type t) + void visitWithMask(Type t, ubyte modMask) { - if (!backref.addRefToType(buf, t)) - t.accept(this); - } + void mangleSymbol(Dsymbol s) + { + scope Mangler v = new Mangler(buf, &backref); + v.mangleSymbol(s); + } - void mangleIdentifier(Identifier id, Dsymbol s) - { - if (!backref.addRefToIdentifier(buf, id)) - toBuffer(buf, id.toString(), s); - } + void visitType(Type t) + { + tyToDecoBuffer(buf, t.ty); + } - //////////////////////////////////////////////////////////////////////////// - /************************************************** - * Type mangling - */ - void visitWithMask(Type t, ubyte modMask) - { - if (modMask != t.mod) + void visitTypeNext(TypeNext t) { - MODtoDecoBuffer(buf, t.mod); + visitType(t); + visitWithMask(t.next, t.mod); } - mangleType(t); - } - override void visit(Type t) - { - tyToDecoBuffer(buf, t.ty); - } + void visitTypeVector(TypeVector t) + { + buf.writestring("Nh"); + visitWithMask(t.basetype, t.mod); + } - override void visit(TypeNext t) - { - visit(cast(Type)t); - visitWithMask(t.next, t.mod); - } + void visitTypeSArray(TypeSArray t) + { + visitType(t); + if (t.dim) + buf.print(t.dim.toInteger()); + if (t.next) + visitWithMask(t.next, t.mod); + } - override void visit(TypeVector t) - { - buf.writestring("Nh"); - visitWithMask(t.basetype, t.mod); - } + void visitTypeDArray(TypeDArray t) + { + visitType(t); + if (t.next) + visitWithMask(t.next, t.mod); + } - override void visit(TypeSArray t) - { - visit(cast(Type)t); - if (t.dim) - buf.print(t.dim.toInteger()); - if (t.next) + void visitTypeAArray(TypeAArray t) + { + visitType(t); + visitWithMask(t.index, 0); visitWithMask(t.next, t.mod); - } + } - override void visit(TypeDArray t) - { - visit(cast(Type)t); - if (t.next) - visitWithMask(t.next, t.mod); - } + void visitTypeFunction(TypeFunction t) + { + //printf("TypeFunction.toDecoBuffer() t = %p %s\n", t, t.toChars()); + //static int nest; if (++nest == 50) *(char*)0=0; + mangleFuncType(t, t, t.mod, t.next, buf, backref); + } - override void visit(TypeAArray t) - { - visit(cast(Type)t); - visitWithMask(t.index, 0); - visitWithMask(t.next, t.mod); - } + void visitTypeIdentifier(TypeIdentifier t) + { + visitType(t); + auto name = t.ident.toString(); + buf.print(cast(int)name.length); + buf.writestring(name); + } - override void visit(TypeFunction t) - { - //printf("TypeFunction.toDecoBuffer() t = %p %s\n", t, t.toChars()); - //static int nest; if (++nest == 50) *(char*)0=0; - mangleFuncType(t, t, t.mod, t.next); - } + void visitTypeEnum(TypeEnum t) + { + visitType(t); + mangleSymbol(t.sym); + } - void mangleFuncType(TypeFunction t, TypeFunction ta, ubyte modMask, Type tret) - { - //printf("mangleFuncType() %s\n", t.toChars()); - if (t.inuse && tret) + void visitTypeStruct(TypeStruct t) { - // printf("TypeFunction.mangleFuncType() t = %s inuse\n", t.toChars()); - t.inuse = 2; // flag error to caller - return; + //printf("TypeStruct.toDecoBuffer('%s') = '%s'\n", t.toChars(), name); + visitType(t); + mangleSymbol(t.sym); } - t.inuse++; - if (modMask != t.mod) - MODtoDecoBuffer(buf, t.mod); - char mc; - final switch (t.linkage) + void visitTypeClass(TypeClass t) { - case LINK.default_: - case LINK.d: - mc = 'F'; - break; - case LINK.c: - mc = 'U'; - break; - case LINK.windows: - mc = 'W'; - break; - case LINK.cpp: - mc = 'R'; - break; - case LINK.objc: - mc = 'Y'; - break; - case LINK.system: - assert(0); + //printf("TypeClass.toDecoBuffer('%s' mod=%x) = '%s'\n", t.toChars(), mod, name); + visitType(t); + mangleSymbol(t.sym); } - buf.writeByte(mc); - - if (ta.purity) - buf.writestring("Na"); - if (ta.isnothrow) - buf.writestring("Nb"); - if (ta.isref) - buf.writestring("Nc"); - if (ta.isproperty) - buf.writestring("Nd"); - if (ta.isnogc) - buf.writestring("Ni"); - - // `return scope` must be in that order - if (ta.isreturnscope && !ta.isreturninferred) + + void visitTypeTuple(TypeTuple t) { - buf.writestring("NjNl"); + //printf("TypeTuple.toDecoBuffer() t = %p, %s\n", t, t.toChars()); + visitType(t); + Parameter._foreach(t.arguments, (idx, param) { + mangleParameter(param, buf, backref); + return 0; + }); + buf.writeByte('Z'); } - else + + void visitTypeNull(TypeNull t) { - // when return ref, the order is `scope return` - if (ta.isScopeQual && !ta.isscopeinferred) - buf.writestring("Nl"); + visitType(t); + } - if (ta.isreturn && !ta.isreturninferred) - buf.writestring("Nj"); + void visitTypeNoreturn(TypeNoreturn t) + { + buf.writestring("Nn"); } - if (ta.islive) - buf.writestring("Nm"); + if (modMask != t.mod) + { + MODtoDecoBuffer(buf, t.mod); + } + if (backref.addRefToType(buf, t)) + return; - switch (ta.trust) + switch (t.ty) { - case TRUST.trusted: - buf.writestring("Ne"); - break; - case TRUST.safe: - buf.writestring("Nf"); - break; - default: - break; + case Tpointer: + case Treference: + case Tdelegate: + case Tslice: visitTypeNext (cast(TypeNext)t); break; + + case Tarray: visitTypeDArray (t.isTypeDArray()); break; + case Tsarray: visitTypeSArray (t.isTypeSArray()); break; + case Taarray: visitTypeAArray (t.isTypeAArray()); break; + case Tfunction: visitTypeFunction (t.isTypeFunction()); break; + case Tident: visitTypeIdentifier(t.isTypeIdentifier()); break; + case Tclass: visitTypeClass (t.isTypeClass()); break; + case Tstruct: visitTypeStruct (t.isTypeStruct()); break; + case Tenum: visitTypeEnum (t.isTypeEnum()); break; + case Ttuple: visitTypeTuple (t.isTypeTuple()); break; + case Tnull: visitTypeNull (t.isTypeNull()); break; + case Tvector: visitTypeVector (t.isTypeVector()); break; + case Tnoreturn: visitTypeNoreturn (t.isTypeNoreturn); break; + + case Terror: + break; // ignore errors + + default: visitType(t); break; } + } - // Write argument types - foreach (idx, param; t.parameterList) - mangleParameter(param); - //if (buf.data[buf.length - 1] == '@') assert(0); - buf.writeByte('Z' - t.parameterList.varargs); // mark end of arg list - if (tret !is null) - visitWithMask(tret, 0); - t.inuse--; + visitWithMask(t, modMask); +} + + +/************************************************************* + */ +void mangleFuncType(TypeFunction t, TypeFunction ta, ubyte modMask, Type tret, OutBuffer* buf, ref Backref backref) +{ + //printf("mangleFuncType() %s\n", t.toChars()); + if (t.inuse && tret) + { + // printf("TypeFunction.mangleFuncType() t = %s inuse\n", t.toChars()); + t.inuse = 2; // flag error to caller + return; } + t.inuse++; + if (modMask != t.mod) + MODtoDecoBuffer(buf, t.mod); - override void visit(TypeIdentifier t) + char mc; + final switch (t.linkage) + { + case LINK.default_: + case LINK.d: + mc = 'F'; + break; + case LINK.c: + mc = 'U'; + break; + case LINK.windows: + mc = 'W'; + break; + case LINK.cpp: + mc = 'R'; + break; + case LINK.objc: + mc = 'Y'; + break; + case LINK.system: + assert(0); + } + buf.writeByte(mc); + + if (ta.purity) + buf.writestring("Na"); + if (ta.isnothrow) + buf.writestring("Nb"); + if (ta.isref) + buf.writestring("Nc"); + if (ta.isproperty) + buf.writestring("Nd"); + if (ta.isnogc) + buf.writestring("Ni"); + + // `return scope` must be in that order + if (ta.isreturnscope && !ta.isreturninferred) + { + buf.writestring("NjNl"); + } + else { - visit(cast(Type)t); - auto name = t.ident.toString(); - buf.print(cast(int)name.length); - buf.writestring(name); + // when return ref, the order is `scope return` + if (ta.isScopeQual && !ta.isscopeinferred) + buf.writestring("Nl"); + + if (ta.isreturn && !ta.isreturninferred) + buf.writestring("Nj"); } - override void visit(TypeEnum t) + if (ta.islive) + buf.writestring("Nm"); + + switch (ta.trust) { - visit(cast(Type)t); - mangleSymbol(t.sym); + case TRUST.trusted: + buf.writestring("Ne"); + break; + case TRUST.safe: + buf.writestring("Nf"); + break; + default: + break; } - override void visit(TypeStruct t) + // Write argument types + foreach (idx, param; t.parameterList) + mangleParameter(param, buf, backref); + //if (buf.data[buf.length - 1] == '@') assert(0); + buf.writeByte('Z' - t.parameterList.varargs); // mark end of arg list + if (tret !is null) + mangleType(tret, 0, buf, backref); + t.inuse--; +} + +/************************************************************* + */ +void mangleParameter(Parameter p, OutBuffer* buf, ref Backref backref) +{ + // https://dlang.org/spec/abi.html#Parameter + + auto stc = p.storageClass; + + // Inferred storage classes don't get mangled in + if (stc & STC.scopeinferred) + stc &= ~(STC.scope_ | STC.scopeinferred); + if (stc & STC.returninferred) + stc &= ~(STC.return_ | STC.returninferred); + + // much like hdrgen.stcToBuffer() + string rrs; + const isout = (stc & STC.out_) != 0; + final switch (buildScopeRef(stc)) { - //printf("TypeStruct.toDecoBuffer('%s') = '%s'\n", t.toChars(), name); - visit(cast(Type)t); - mangleSymbol(t.sym); + case ScopeRef.None: + case ScopeRef.Scope: + case ScopeRef.Ref: + case ScopeRef.Return: + case ScopeRef.RefScope: + break; + + case ScopeRef.ReturnScope: rrs = "NkM"; goto L1; // return scope + case ScopeRef.ReturnRef: rrs = isout ? "NkJ" : "NkK"; goto L1; // return ref + case ScopeRef.ReturnRef_Scope: rrs = isout ? "MNkJ" : "MNkK"; goto L1; // scope return ref + case ScopeRef.Ref_ReturnScope: rrs = isout ? "NkMJ" : "NkMK"; goto L1; // return scope ref + L1: + buf.writestring(rrs); + stc &= ~(STC.out_ | STC.scope_ | STC.ref_ | STC.return_); + break; } - override void visit(TypeClass t) + if (stc & STC.scope_) + buf.writeByte('M'); // scope + + if (stc & STC.return_) + buf.writestring("Nk"); // return + + switch (stc & (STC.IOR | STC.lazy_)) { - //printf("TypeClass.toDecoBuffer('%s' mod=%x) = '%s'\n", t.toChars(), mod, name); - visit(cast(Type)t); - mangleSymbol(t.sym); + case 0: + break; + case STC.in_: + buf.writeByte('I'); + break; + case STC.in_ | STC.ref_: + buf.writestring("IK"); + break; + case STC.out_: + buf.writeByte('J'); + break; + case STC.ref_: + buf.writeByte('K'); + break; + case STC.lazy_: + buf.writeByte('L'); + break; + default: + debug + { + printf("storageClass = x%llx\n", stc & (STC.IOR | STC.lazy_)); + } + assert(0); } + mangleType(p.type, (stc & STC.in_) ? MODFlags.const_ : 0, buf, backref); +} + + +private extern (C++) final class Mangler : Visitor +{ + alias visit = Visitor.visit; +public: + static assert(Key.sizeof == size_t.sizeof); - override void visit(TypeTuple t) + OutBuffer* buf; + Backref* backref; + + extern (D) this(OutBuffer* buf, Backref* backref) { - //printf("TypeTuple.toDecoBuffer() t = %p, %s\n", t, t.toChars()); - visit(cast(Type)t); - Parameter._foreach(t.arguments, (idx, param) { - mangleParameter(param); - return 0; - }); - buf.writeByte('Z'); + this.buf = buf; + this.backref = backref; } - override void visit(TypeNull t) + void mangleSymbol(Dsymbol s) { - visit(cast(Type)t); + s.accept(this); } - override void visit(TypeNoreturn t) + void mangleIdentifier(Identifier id, Dsymbol s) { - buf.writestring("Nn"); + if (!backref.addRefToIdentifier(buf, id)) + toBuffer(buf, id.toString(), s); } //////////////////////////////////////////////////////////////////////////// @@ -472,7 +593,7 @@ public: } else if (sthis.type) { - visitWithMask(sthis.type, 0); + mangleType(sthis.type, 0, buf, *backref); } else assert(0); @@ -530,11 +651,11 @@ public: { TypeFunction tf = fd.type.isTypeFunction(); TypeFunction tfo = fd.originalType.isTypeFunction(); - mangleFuncType(tf, tfo, 0, null); + mangleFuncType(tf, tfo, 0, null, buf, *backref); } else { - visitWithMask(fd.type, 0); + mangleType(fd.type, 0, buf, *backref); } } @@ -735,7 +856,7 @@ public: if (ta) { buf.writeByte('T'); - visitWithMask(ta, 0); + mangleType(ta, 0, buf, *backref); } else if (ea) { @@ -778,7 +899,7 @@ public: /* Use type mangling that matches what it would be for a function parameter */ - visitWithMask(ea.type, 0); + mangleType(ea.type, 0, buf, *backref); ea.accept(this); } else if (sa) @@ -1004,77 +1125,6 @@ public: else mangleSymbol(e.fd); } - - //////////////////////////////////////////////////////////////////////////// - - void mangleParameter(Parameter p) - { - // https://dlang.org/spec/abi.html#Parameter - - auto stc = p.storageClass; - - // Inferred storage classes don't get mangled in - if (stc & STC.scopeinferred) - stc &= ~(STC.scope_ | STC.scopeinferred); - if (stc & STC.returninferred) - stc &= ~(STC.return_ | STC.returninferred); - - // much like hdrgen.stcToBuffer() - string rrs; - const isout = (stc & STC.out_) != 0; - final switch (buildScopeRef(stc)) - { - case ScopeRef.None: - case ScopeRef.Scope: - case ScopeRef.Ref: - case ScopeRef.Return: - case ScopeRef.RefScope: - break; - - case ScopeRef.ReturnScope: rrs = "NkM"; goto L1; // return scope - case ScopeRef.ReturnRef: rrs = isout ? "NkJ" : "NkK"; goto L1; // return ref - case ScopeRef.ReturnRef_Scope: rrs = isout ? "MNkJ" : "MNkK"; goto L1; // scope return ref - case ScopeRef.Ref_ReturnScope: rrs = isout ? "NkMJ" : "NkMK"; goto L1; // return scope ref - L1: - buf.writestring(rrs); - stc &= ~(STC.out_ | STC.scope_ | STC.ref_ | STC.return_); - break; - } - - if (stc & STC.scope_) - buf.writeByte('M'); // scope - - if (stc & STC.return_) - buf.writestring("Nk"); // return - - switch (stc & (STC.IOR | STC.lazy_)) - { - case 0: - break; - case STC.in_: - buf.writeByte('I'); - break; - case STC.in_ | STC.ref_: - buf.writestring("IK"); - break; - case STC.out_: - buf.writeByte('J'); - break; - case STC.ref_: - buf.writeByte('K'); - break; - case STC.lazy_: - buf.writeByte('L'); - break; - default: - debug - { - printf("storageClass = x%llx\n", stc & (STC.IOR | STC.lazy_)); - } - assert(0); - } - visitWithMask(p.type, (stc & STC.in_) ? MODFlags.const_ : 0); - } } /*************************************** From ef1cb2ee11fd9a23e1b62407aaef6c5ccbac5229 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Tue, 14 Feb 2023 12:24:52 +0100 Subject: [PATCH 092/177] Remove old dead code from parse.d --- dmd/parse.d | 63 ----------------------------------------------------- 1 file changed, 63 deletions(-) diff --git a/dmd/parse.d b/dmd/parse.d index 85ba32e62d6..18ada5a4303 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -2883,43 +2883,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer storageClass = appendStorageClass(storageClass, stc); continue; - version (none) - { - case TOK.static_: - stc = STC.static_; - goto L2; - - case TOK.auto_: - storageClass = STC.auto_; - goto L4; - - case TOK.alias_: - storageClass = STC.alias_; - goto L4; - L4: - nextToken(); - ai = null; - if (token.value == TOK.identifier) - { - ai = token.ident; - nextToken(); - } - - at = null; // no type - ae = null; // no default argument - if (token.value == TOK.assign) // = defaultArg - { - nextToken(); - ae = parseDefaultInitExp(); - hasdefault = 1; - } - else - { - if (hasdefault) - error("default argument expected for `alias %s`", ai ? ai.toChars() : ""); - } - goto L3; - } default: { stc = storageClass & (STC.IOR | STC.lazy_); @@ -7639,24 +7602,6 @@ LagainStc: } goto L1; - version (none) - { - case TOK.static_: - continue; - case TOK.auto_: - case TOK.alias_: - t = peek(t); - if (t.value == TOK.identifier) - t = peek(t); - if (t.value == TOK.assign) - { - t = peek(t); - if (!isExpression(&t)) - return false; - } - goto L3; - } - default: { if (!isBasicType(&t)) @@ -8772,14 +8717,6 @@ LagainStc: case TOK.wcharLiteral: case TOK.dcharLiteral: case TOK.string_: - version (none) - { - case TOK.tilde: - case TOK.and: - case TOK.mul: - case TOK.min: - case TOK.add: - } case TOK.function_: case TOK.delegate_: case TOK.typeof_: From 658b40f3ffb5bfced20897dfd6bca99a5face801 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Tue, 14 Feb 2023 18:53:33 +0100 Subject: [PATCH 093/177] [refactor] Expression: change parens type from ubyte to bool --- dmd/expression.d | 2 +- dmd/expression.h | 2 +- dmd/frontend.h | 2 +- dmd/parse.d | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dmd/expression.d b/dmd/expression.d index 571da4269d4..4fb71d09419 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -730,7 +730,7 @@ extern (C++) abstract class Expression : ASTNode { const EXP op; // to minimize use of dynamic_cast ubyte size; // # of bytes in Expression so we can copy() it - ubyte parens; // if this is a parenthesized expression + bool parens; // if this is a parenthesized expression Type type; // !=null means that semantic() has been run Loc loc; // file location diff --git a/dmd/expression.h b/dmd/expression.h index caddb079b61..c7f789dbc08 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -81,7 +81,7 @@ class Expression : public ASTNode public: EXP op; // to minimize use of dynamic_cast unsigned char size; // # of bytes in Expression so we can copy() it - unsigned char parens; // if this is a parenthesized expression + bool parens; // if this is a parenthesized expression Type *type; // !=NULL means that semantic() has been run Loc loc; // file location diff --git a/dmd/frontend.h b/dmd/frontend.h index 964154328cf..a6aef2a9d73 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -993,7 +993,7 @@ class Expression : public ASTNode public: const EXP op; uint8_t size; - uint8_t parens; + bool parens; Type* type; Loc loc; static void _init(); diff --git a/dmd/parse.d b/dmd/parse.d index 18ada5a4303..c98e41cc16c 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -7307,7 +7307,7 @@ LagainStc: { // This code parallels parseDeclarator() Token* t = *pt; - int parens; + bool parens; //printf("Parser::isDeclarator() %s\n", t.toChars()); if (t.value == TOK.assign) @@ -8447,7 +8447,7 @@ LagainStc: // ( expression ) nextToken(); e = parseExpression(); - e.parens = 1; + e.parens = true; check(loc, TOK.rightParenthesis); break; } From 0e28d598fae40a0665f553eb5a0c6ed53fcffa96 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Sun, 12 Feb 2023 21:53:33 +0100 Subject: [PATCH 094/177] Revert "deprecate Object.factory" This reverts commit ddc7c1d0344738477fb3fffad3757b5892a4cd29. --- runtime/druntime/src/object.d | 3 +-- tests/dmd/runnable/test34.d | 2 -- tests/dmd/runnable/xtest46.d | 2 +- tests/dmd/runnable/xtest46_gc.d | 2 +- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/runtime/druntime/src/object.d b/runtime/druntime/src/object.d index 25347020612..ad7c0e5bc3e 100644 --- a/runtime/druntime/src/object.d +++ b/runtime/druntime/src/object.d @@ -246,7 +246,6 @@ class Object * } * --- */ - deprecated("use __traits(getModuleClasses) instead") static Object factory(string classname) { auto ci = TypeInfo_Class.find(classname); @@ -257,7 +256,7 @@ class Object return null; } - deprecated @system unittest + @system unittest { Object valid_obj = Object.factory("object.Object"); Object invalid_obj = Object.factory("object.__this_class_doesnt_exist__"); diff --git a/tests/dmd/runnable/test34.d b/tests/dmd/runnable/test34.d index 11543f1ae85..df461370066 100644 --- a/tests/dmd/runnable/test34.d +++ b/tests/dmd/runnable/test34.d @@ -1,5 +1,3 @@ -// REQUIRED_ARGS: -d - module test34; import core.exception; diff --git a/tests/dmd/runnable/xtest46.d b/tests/dmd/runnable/xtest46.d index a0907f4b856..8ae08ad2e47 100644 --- a/tests/dmd/runnable/xtest46.d +++ b/tests/dmd/runnable/xtest46.d @@ -1,4 +1,4 @@ -// REQUIRED_ARGS: -d -preview=rvaluerefparam +// REQUIRED_ARGS: -preview=rvaluerefparam // /* TEST_OUTPUT: --- diff --git a/tests/dmd/runnable/xtest46_gc.d b/tests/dmd/runnable/xtest46_gc.d index b0288a25e08..348c05bd09d 100644 --- a/tests/dmd/runnable/xtest46_gc.d +++ b/tests/dmd/runnable/xtest46_gc.d @@ -1,5 +1,5 @@ /* -REQUIRED_ARGS: -d -lowmem -Jrunnable -preview=rvaluerefparam +REQUIRED_ARGS: -lowmem -Jrunnable -preview=rvaluerefparam EXTRA_FILES: xtest46.d TEST_OUTPUT: --- From dbbffcd1dd2dd2cb3f28ed38511c3b43e07406b1 Mon Sep 17 00:00:00 2001 From: Dennis Date: Wed, 15 Feb 2023 11:31:59 +0100 Subject: [PATCH 095/177] Allow default arguments in the middle (dlang/dmd!14879) --- dmd/dsymbolsem.d | 3 +-- dmd/mtype.d | 24 +++++++++++++++++++++++- dmd/typesem.d | 7 ------- tests/dmd/compilable/named_arguments.d | 12 ++++++++++++ tests/dmd/fail_compilation/diag3438.d | 6 ++---- 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index b0272c510f9..5ce3bf0a844 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -4146,9 +4146,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor else if (dim == 0 && tf.parameterList.varargs != VarArg.none) // allow varargs only ctor { } - else if (dim && tf.parameterList[0].defaultArg) + else if (dim && !tf.parameterList.hasArgsWithoutDefault) { - // if the first parameter has a default argument, then the rest does as well if (ctd.storage_class & STC.disable) { ctd.error("is marked `@disable`, so it cannot have default "~ diff --git a/dmd/mtype.d b/dmd/mtype.d index e0bf723e43c..5939db5ba85 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -4683,7 +4683,7 @@ extern (C++) final class TypeFunction : TypeNext } // https://issues.dlang.org/show_bug.cgi?id=22997 - if (parameterList.varargs == VarArg.none && nparams > argumentList.length && !parameterList[argumentList.length].defaultArg) + if (parameterList.varargs == VarArg.none && nparams > argumentList.length && !parameterList.hasDefaultArgs) { OutBuffer buf; buf.printf("too few arguments, expected %d, got %d", cast(int)nparams, cast(int)argumentList.length); @@ -6631,6 +6631,28 @@ extern (C++) struct ParameterList // Ensure no remaining parameters in `other` return !diff && other[idx] is null; } + + /// Returns: `true` if any parameter has a default argument + extern(D) bool hasDefaultArgs() + { + foreach (oidx, oparam, eidx, eparam; this) + { + if (eparam.defaultArg) + return true; + } + return false; + } + + // Returns: `true` if any parameter doesn't have a default argument + extern(D) bool hasArgsWithoutDefault() + { + foreach (oidx, oparam, eidx, eparam; this) + { + if (!eparam.defaultArg) + return true; + } + return false; + } } diff --git a/dmd/typesem.d b/dmd/typesem.d index 65ddbf525a6..ac60596506b 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -1333,7 +1333,6 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) // extended index), as we need to run semantic when `oidx` changes. size_t tupleOrigIdx = size_t.max; size_t tupleExtIdx = size_t.max; - bool hasDefault; foreach (oidx, oparam, eidx, eparam; tf.parameterList) { // oparam (original param) will always have the default arg @@ -1342,7 +1341,6 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) // position to get the offset in it later on. if (oparam.defaultArg) { - hasDefault = true; // Get the obvious case out of the way if (oparam is eparam) errors |= !defaultArgSemantic(eparam, argsc); @@ -1369,11 +1367,6 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) eparam.defaultArg = (*te.exps)[eidx - tupleExtIdx]; } } - else if (hasDefault) - { - .error(loc, "default argument expected for `%s`", oparam.toChars()); - errors = true; - } // We need to know the default argument to resolve `auto ref`, // hence why this has to take place as the very last step. diff --git a/tests/dmd/compilable/named_arguments.d b/tests/dmd/compilable/named_arguments.d index 240bfe1ea97..f287ccdea95 100644 --- a/tests/dmd/compilable/named_arguments.d +++ b/tests/dmd/compilable/named_arguments.d @@ -12,6 +12,18 @@ static assert(fun(y: "y", "z", x: "x") == "xyzW"); static assert(fun( "x", "y", w: "w") == "xyZw"); static assert(fun(x: "x", "y", z: "z") == "xyzW"); +// Default arguments need not all be at the end anymore +string fun2(string x = "x", string y, string z = "z") +{ + return x ~ y ~ z; +} + +static assert(fun2(y: "y") == "xyz"); + +// The assumption that first parameter having a default implies all parameters have a default is no longer valid, +// so this struct constructor shouldn't be mistaken for a default constructor. +struct SD { this(int x = 1, int y) { } } + // UFCS static assert("x".fun("y", w: "w") == "xyZw"); diff --git a/tests/dmd/fail_compilation/diag3438.d b/tests/dmd/fail_compilation/diag3438.d index c4cbc721d86..0e4fb8b076f 100644 --- a/tests/dmd/fail_compilation/diag3438.d +++ b/tests/dmd/fail_compilation/diag3438.d @@ -7,7 +7,7 @@ fail_compilation/diag3438.d(20): Error: constructor `diag3438.F5.this` is marked fail_compilation/diag3438.d(20): Use `@disable this();` if you want to disable default initialization. fail_compilation/diag3438.d(21): Error: constructor `diag3438.F6.this` is marked `@disable`, so it cannot have default arguments for all parameters. fail_compilation/diag3438.d(21): Use `@disable this();` if you want to disable default initialization. -fail_compilation/diag3438.d(24): Error: default argument expected for `y` +fail_compilation/diag3438.d(22): Error: constructor `diag3438.F7.this` all parameters have default arguments, but structs cannot have default constructors. --- */ @@ -19,6 +19,4 @@ struct F3 { this(...) { } } // ok struct F4 { this(int[] x...) { } } // ok struct F5 { @disable this(int x = 1); } struct F6 { @disable this(int x = 1) { } } - -// Make sure the deprecation doesn't interfere w/ the check for default arguments -struct S { this(int x = 1, int y) { } } +struct F7 { this(int x = 1, int y = 2) { } } From 03b39c5d35d929255cfc645b96f5616bb68c4fec Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Wed, 15 Feb 2023 19:28:28 +0800 Subject: [PATCH 096/177] Deprecate alias this for classes v2 (dlang/dmd!14812) --- dmd/dsymbolsem.d | 5 + dmd/dtoh.d | 16 ++- runtime/druntime/src/object.d | 94 --------------- tests/dmd/compilable/test21073.d | 16 --- tests/dmd/compilable/test21543.d | 116 ------------------- tests/dmd/compilable/test5973.d | 41 ------- tests/dmd/compilable/test6777.d | 11 -- tests/dmd/fail_compilation/fail5851.d | 16 --- tests/dmd/runnable/aliasthis.d | 10 ++ tests/dmd/runnable/interpret.d | 1 + tests/dmd/runnable/test17684.d | 10 ++ tests/dmd/runnable/test19782.d | 8 ++ tests/dmd/runnable/test21039.d | 7 ++ tests/dmd/runnable/test23234.d | 7 ++ tests/dmd/runnable/testaliascast.d | 8 ++ tests/dmd/runnable/testassign.d | 2 + tests/dmd/runnable/traits_getPointerBitmap.d | 29 ----- tests/dmd/runnable/xtest46.d | 4 + tests/dmd/runnable/xtest46_gc.d | 4 + 19 files changed, 81 insertions(+), 324 deletions(-) delete mode 100644 tests/dmd/compilable/test21073.d delete mode 100644 tests/dmd/compilable/test21543.d delete mode 100644 tests/dmd/compilable/test5973.d delete mode 100644 tests/dmd/compilable/test6777.d delete mode 100644 tests/dmd/fail_compilation/fail5851.d diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 5ce3bf0a844..eb60cc67004 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -317,6 +317,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor return; } + // @@@DEPRECATED_2.121@@@ + // Deprecated in 2.101 - Can be removed in 2.121 + if (ad.isClassDeclaration() || ad.isInterfaceDeclaration()) + deprecation(dsym.loc, "alias this for classes/interfaces is deprecated"); + assert(ad.members); Dsymbol s = ad.search(dsym.loc, dsym.ident); if (!s) diff --git a/dmd/dtoh.d b/dmd/dtoh.d index 5386787f628..7c3ff4bccc2 100644 --- a/dmd/dtoh.d +++ b/dmd/dtoh.d @@ -291,7 +291,21 @@ public: /// Informations about the current context in the AST Context context; - alias context this; + + // Generates getter-setter methods to replace the use of alias this + // This should be replaced by a `static foreach` once the gdc tester + // gets upgraded to version 10 (to support `static foreach`). + private extern(D) static string generateMembers() + { + string result = ""; + foreach(member; __traits(allMembers, Context)) + { + result ~= "ref auto " ~ member ~ "() { return context." ~ member ~ "; }\n"; + } + return result; + } + + mixin(generateMembers()); this(OutBuffer* fwdbuf, OutBuffer* donebuf, OutBuffer* buf) scope { diff --git a/runtime/druntime/src/object.d b/runtime/druntime/src/object.d index ad7c0e5bc3e..bbf87328951 100644 --- a/runtime/druntime/src/object.d +++ b/runtime/druntime/src/object.d @@ -2927,25 +2927,6 @@ void clear(Value, Key)(Value[Key]* aa) assert("k1" !in aa); } -// Issue 20559 -@system unittest -{ - static class Foo - { - int[string] aa; - alias aa this; - } - - auto v = new Foo(); - v["Hello World"] = 42; - v.clear; - assert("Hello World" !in v); - - // Test for T* - static assert(!__traits(compiles, (&v).clear)); - static assert( __traits(compiles, (*(&v)).clear)); -} - /*********************************** * Reorganizes the associative array in place so that lookups are more * efficient. @@ -4278,44 +4259,6 @@ void destroy(bool initialize = true, T)(T obj) if (is(T == interface)) destroy!true(new C()); } -@system unittest -{ - // class with an `alias this` - class A - { - static int dtorCount; - ~this() - { - dtorCount++; - } - } - - class B - { - A a; - alias a this; - this() - { - a = new A; - } - static int dtorCount; - ~this() - { - dtorCount++; - } - } - auto b = new B; - assert(A.dtorCount == 0); - assert(B.dtorCount == 0); - destroy(b); - assert(A.dtorCount == 0); - assert(B.dtorCount == 1); - - auto a = new A; - destroy(a); - assert(A.dtorCount == 1); -} - @system unittest { interface I { } @@ -4529,43 +4472,6 @@ if (__traits(isStaticArray, T)) } } -// https://issues.dlang.org/show_bug.cgi?id=19218 -@system unittest -{ - static struct S - { - static dtorCount = 0; - ~this() { ++dtorCount; } - } - - static interface I - { - ref S[3] getArray(); - alias getArray this; - } - - static class C : I - { - static dtorCount = 0; - ~this() { ++dtorCount; } - - S[3] a; - alias a this; - - ref S[3] getArray() { return a; } - } - - C c = new C(); - destroy(c); - assert(S.dtorCount == 3); - assert(C.dtorCount == 1); - - I i = new C(); - destroy(i); - assert(S.dtorCount == 6); - assert(C.dtorCount == 2); -} - /// ditto void destroy(bool initialize = true, T)(ref T obj) if (!is(T == struct) && !is(T == interface) && !is(T == class) && !__traits(isStaticArray, T)) diff --git a/tests/dmd/compilable/test21073.d b/tests/dmd/compilable/test21073.d deleted file mode 100644 index 47d788128b3..00000000000 --- a/tests/dmd/compilable/test21073.d +++ /dev/null @@ -1,16 +0,0 @@ -// https://issues.dlang.org/show_bug.cgi?id=21073 - -class C -{ - auto internal() const - { - return 5; - } - alias internal this; -} - -void main() pure -{ - const c = new C; - auto r = cast(C)c; -} diff --git a/tests/dmd/compilable/test21543.d b/tests/dmd/compilable/test21543.d deleted file mode 100644 index 4914264aaf9..00000000000 --- a/tests/dmd/compilable/test21543.d +++ /dev/null @@ -1,116 +0,0 @@ -// https://issues.dlang.org/show_bug.cgi?id=21543 - -class B -{ - Nullable!B data; - alias data this; -} - -void test1() -{ - B b; - Nullable!B n; -} - -struct Nullable(T) -{ - T payload; - - void opAssign()(T) - { - move(payload); - } - - inout(T) get_() inout - { - return payload; - } - - alias get_ this; -} - -// another version with chain of 3 alias this - -struct C -{ - Nullable2 data; - alias data this; -} - -void test2() -{ - C c; - Nullable2 n2 = &c; - Nullable3 n3 = &c; - - // these are to check a sane -vcg-ast output - fn1(c); - fn1(n2); - fn1(n3); - fn2(c); - fn2(n2); - fn2(n3); - fn3(c); - fn3(n2); - fn3(n3); -} - -void fn1(C x) {} - -void fn2(Nullable2 x) {} - -void fn3(Nullable3 x) {} - -struct Nullable2 -{ - Nullable3 payload; - - this(C* c) - { - payload = Nullable3(c); - } - - void opAssign()(Nullable3) - { - move(payload); - } - - inout(Nullable3) get_() inout - { - return payload; - } - - alias get_ this; -} - -struct Nullable3 -{ - C* payload; - - this(C* c) - { - payload = c; - } - - void opAssign()(C) - { - move(payload); - } - - inout(C) get_() inout - { - return *payload; - } - - alias get_ this; -} - -T move(T)(ref T source) -{ - return source; -} - -T move(T)(T source) -{ - return source; -} diff --git a/tests/dmd/compilable/test5973.d b/tests/dmd/compilable/test5973.d deleted file mode 100644 index a54b0ae173a..00000000000 --- a/tests/dmd/compilable/test5973.d +++ /dev/null @@ -1,41 +0,0 @@ -// https://issues.dlang.org/show_bug.cgi?id=5973 - -class A { int a = 1; } -class B { int b = 2; } -class C : A -{ - B obj; - alias obj this; - this(){ obj = new B(); } -} -class X : C {} - -class D -{ - int i; -} - -class E -{ - D x; - alias x this; -} - -class F : E -{ - void test() - { - i = 5; - } -} - -void main() -{ - auto c = new C(); - assert(c.a == 1); // lookup C -> A, OK - assert(c.b == 2); // lookup C => B, OK - - auto x = new X(); - assert(x.a == 1); // lookup X -> C -> A, OK - assert(x.b == 2); // lookup X -> C => B, NG (Line 17) -} diff --git a/tests/dmd/compilable/test6777.d b/tests/dmd/compilable/test6777.d deleted file mode 100644 index 161a94a179d..00000000000 --- a/tests/dmd/compilable/test6777.d +++ /dev/null @@ -1,11 +0,0 @@ -struct S {} - -class C { - S s; - alias s this; -} - -void main() { - auto c = new C; - auto p = cast(void*) c; -} diff --git a/tests/dmd/fail_compilation/fail5851.d b/tests/dmd/fail_compilation/fail5851.d deleted file mode 100644 index 236a956de92..00000000000 --- a/tests/dmd/fail_compilation/fail5851.d +++ /dev/null @@ -1,16 +0,0 @@ -/* -TEST_OUTPUT: ---- -fail_compilation/fail5851.d(11): Error: alias this is not reachable as `Foo` already converts to `object.Object` ---- -*/ - -class Foo -{ - Object o; - alias o this; -} - -void main() -{ -} diff --git a/tests/dmd/runnable/aliasthis.d b/tests/dmd/runnable/aliasthis.d index db5913c8389..50e5c4db64b 100644 --- a/tests/dmd/runnable/aliasthis.d +++ b/tests/dmd/runnable/aliasthis.d @@ -1,7 +1,16 @@ /* TEST_OUTPUT: --- +runnable/aliasthis.d(103): Deprecation: alias this for classes/interfaces is deprecated +runnable/aliasthis.d(291): Deprecation: alias this for classes/interfaces is deprecated +runnable/aliasthis.d(292): Deprecation: alias this for classes/interfaces is deprecated +runnable/aliasthis.d(294): Deprecation: alias this for classes/interfaces is deprecated +runnable/aliasthis.d(465): Deprecation: alias this for classes/interfaces is deprecated +runnable/aliasthis.d(466): Deprecation: alias this for classes/interfaces is deprecated +runnable/aliasthis.d(477): Deprecation: alias this for classes/interfaces is deprecated +runnable/aliasthis.d(1013): Deprecation: alias this for classes/interfaces is deprecated false +runnable/aliasthis.d(2100): Deprecation: alias this for classes/interfaces is deprecated [] = int [] = string [0] = int @@ -10,6 +19,7 @@ false [] = int [1] = string [0] = int +runnable/aliasthis.d(741): Deprecation: alias this for classes/interfaces is deprecated --- RUN_OUTPUT: diff --git a/tests/dmd/runnable/interpret.d b/tests/dmd/runnable/interpret.d index 16d4c5570a4..f9972f235e2 100644 --- a/tests/dmd/runnable/interpret.d +++ b/tests/dmd/runnable/interpret.d @@ -4,6 +4,7 @@ TEST_OUTPUT: true g &Test109S(&Test109S()) +runnable/interpret.d(3742): Deprecation: alias this for classes/interfaces is deprecated tfoo tfoo Crash! diff --git a/tests/dmd/runnable/test17684.d b/tests/dmd/runnable/test17684.d index efdce0847ba..e10265558e8 100644 --- a/tests/dmd/runnable/test17684.d +++ b/tests/dmd/runnable/test17684.d @@ -1,3 +1,13 @@ +/* +TEST_OUTPUT: +--- +runnable/test17684.d(37): Deprecation: alias this for classes/interfaces is deprecated +runnable/test17684.d(54): Deprecation: alias this for classes/interfaces is deprecated +runnable/test17684.d(54): Deprecation: alias this for classes/interfaces is deprecated +runnable/test17684.d(37): Deprecation: alias this for classes/interfaces is deprecated +--- +*/ + struct StructField(T) { static T Field; diff --git a/tests/dmd/runnable/test19782.d b/tests/dmd/runnable/test19782.d index a24d84173ec..61a168bf918 100644 --- a/tests/dmd/runnable/test19782.d +++ b/tests/dmd/runnable/test19782.d @@ -1,4 +1,12 @@ // https://issues.dlang.org/show_bug.cgi?id=19782 + +/* +TEST_OUTPUT: +--- +runnable/test19782.d(17): Deprecation: alias this for classes/interfaces is deprecated +--- +*/ + class Inner { int a; diff --git a/tests/dmd/runnable/test21039.d b/tests/dmd/runnable/test21039.d index c58600f8da0..f32267ab59e 100644 --- a/tests/dmd/runnable/test21039.d +++ b/tests/dmd/runnable/test21039.d @@ -1,5 +1,12 @@ // https://issues.dlang.org/show_bug.cgi?id=21039 +/* +TEST_OUTPUT: +--- +runnable/test21039.d(14): Deprecation: alias this for classes/interfaces is deprecated +--- +*/ + class Inner {} class Outer { diff --git a/tests/dmd/runnable/test23234.d b/tests/dmd/runnable/test23234.d index 7872aa76dfe..f97486404b3 100644 --- a/tests/dmd/runnable/test23234.d +++ b/tests/dmd/runnable/test23234.d @@ -1,5 +1,12 @@ // https://issues.dlang.org/show_bug.cgi?id=23234 +/* +TEST_OUTPUT: +--- +runnable/test23234.d(17): Deprecation: alias this for classes/interfaces is deprecated +--- +*/ + class Bar { } diff --git a/tests/dmd/runnable/testaliascast.d b/tests/dmd/runnable/testaliascast.d index c55f8203499..ed5091dff01 100644 --- a/tests/dmd/runnable/testaliascast.d +++ b/tests/dmd/runnable/testaliascast.d @@ -1,5 +1,13 @@ // https://issues.dlang.org/show_bug.cgi?id=11294 +/* +TEST_OUTPUT: +--- +runnable/testaliascast.d(29): Deprecation: alias this for classes/interfaces is deprecated +runnable/testaliascast.d(58): Deprecation: alias this for classes/interfaces is deprecated +--- +*/ + string result; extern(C) void rt_finalize(void *ptr, bool det=true); diff --git a/tests/dmd/runnable/testassign.d b/tests/dmd/runnable/testassign.d index 586aea80cce..79a4c57cf3b 100644 --- a/tests/dmd/runnable/testassign.d +++ b/tests/dmd/runnable/testassign.d @@ -2,6 +2,8 @@ REQUIRED_ARGS: -preview=rvaluerefparam TEST_OUTPUT: --- +runnable/testassign.d(802): Deprecation: alias this for classes/interfaces is deprecated +runnable/testassign.d(808): Deprecation: alias this for classes/interfaces is deprecated \ S1 S2a S2b S3a S3b S4a S4b - true true true true true true true Xa true true true true true true true diff --git a/tests/dmd/runnable/traits_getPointerBitmap.d b/tests/dmd/runnable/traits_getPointerBitmap.d index 8996c9ebb8f..ffa0b803ade 100644 --- a/tests/dmd/runnable/traits_getPointerBitmap.d +++ b/tests/dmd/runnable/traits_getPointerBitmap.d @@ -1,4 +1,3 @@ - module traits_getPointerBitmap; import core.stdc.stdio; @@ -76,19 +75,6 @@ template pOff(T) enum pOff = T.p.offsetof / bytesPerPtr; } -class C(T, aliasTo = void) -{ - static if(!is(aliasTo == void)) - { - aliasTo a; - alias a this; - } - - size_t x; - T t = void; - void* p; -} - /////////////////////////////////////// void _testType(T)(size_t[] expected) @@ -118,21 +104,6 @@ void testType(T)(size_t[] expected) // prepend string sexp[0] = (expected[0] << tOff!(S!(T, string))) | (1 << pOff!(S!(T, string))) | 2; // arr ptr _testType!(S!(T, string))(sexp); - - // generate bit pattern for C!T - C!T ct = null; - size_t mutexBit = (RTInfoMark__Monitor ? 2 : 0); - size_t ctpOff = ct.p.offsetof / bytesPerPtr; - size_t cttOff = ct.t.offsetof / bytesPerPtr; - sexp[0] = (expected[0] << cttOff) | (1 << ctpOff) | mutexBit; - _testType!(C!(T))(sexp); - - C!(T, string) cts = null; - size_t ctspOff = cts.p.offsetof / bytesPerPtr; - size_t ctstOff = cts.t.offsetof / bytesPerPtr; - // generate bit pattern for C!T - sexp[0] = (expected[0] << ctstOff) | (1 << ctspOff) | mutexBit | 0b1000; // arr ptr - _testType!(C!(T, string))(sexp); } /////////////////////////////////////// diff --git a/tests/dmd/runnable/xtest46.d b/tests/dmd/runnable/xtest46.d index 8ae08ad2e47..e57f52f6578 100644 --- a/tests/dmd/runnable/xtest46.d +++ b/tests/dmd/runnable/xtest46.d @@ -2,11 +2,14 @@ // /* TEST_OUTPUT: --- +runnable/xtest46.d(165): Deprecation: alias this for classes/interfaces is deprecated Boo!double Boo!int true int !! immutable(int)[] +runnable/xtest46.d(2932): Deprecation: alias this for classes/interfaces is deprecated +runnable/xtest46.d(2964): Deprecation: alias this for classes/interfaces is deprecated int(int i, long j = 7L) long C10390(C10390(C10390())) @@ -19,6 +22,7 @@ string[] double[] double[] {} +runnable/xtest46.d(4670): Deprecation: alias this for classes/interfaces is deprecated tuple("m") true TFunction1: extern (C) void function() diff --git a/tests/dmd/runnable/xtest46_gc.d b/tests/dmd/runnable/xtest46_gc.d index 348c05bd09d..224625c65ec 100644 --- a/tests/dmd/runnable/xtest46_gc.d +++ b/tests/dmd/runnable/xtest46_gc.d @@ -3,11 +3,14 @@ REQUIRED_ARGS: -lowmem -Jrunnable -preview=rvaluerefparam EXTRA_FILES: xtest46.d TEST_OUTPUT: --- +runnable/xtest46_gc.d-mixin-33(197): Deprecation: alias this for classes/interfaces is deprecated Boo!double Boo!int true int !! immutable(int)[] +runnable/xtest46_gc.d-mixin-33(2964): Deprecation: alias this for classes/interfaces is deprecated +runnable/xtest46_gc.d-mixin-33(2996): Deprecation: alias this for classes/interfaces is deprecated int(int i, long j = 7L) long C10390(C10390()) @@ -20,6 +23,7 @@ string[] double[] double[] {} +runnable/xtest46_gc.d-mixin-33(4702): Deprecation: alias this for classes/interfaces is deprecated tuple("m") true TFunction1: extern (C) void function() From 9aae44572c7999308d1c1f2bc8f62d4cdf688c2f Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Tue, 14 Feb 2023 13:51:27 +0100 Subject: [PATCH 097/177] Fix inconsistent names and arguments arrays --- dmd/expression.d | 13 +++---------- dmd/parse.d | 4 +++- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/dmd/expression.d b/dmd/expression.d index 4fb71d09419..3319029a7c6 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -271,14 +271,6 @@ extern (C++) void expandTuples(Expressions* exps, Identifiers* names = null) if (names) { - if (exps.length != names.length) - { - // Fixme: this branch should be removed when CallExp rewrites - // (UFCS/operator overloading) are fixed to take named arguments into account - names.setDim(exps.length); - foreach (i; 0..exps.length) - (*names)[i] = null; - } if (exps.length != names.length) { printf("exps.length = %d, names.length = %d\n", cast(int) exps.length, cast(int) names.length); @@ -3677,7 +3669,8 @@ extern (C++) final class NewExp : Expression return new NewExp(loc, thisexp ? thisexp.syntaxCopy() : null, newtype.syntaxCopy(), - arraySyntaxCopy(arguments)); + arraySyntaxCopy(arguments), + names ? names.copy() : null); } override void accept(Visitor v) @@ -5244,7 +5237,7 @@ extern (C++) final class CallExp : UnaExp override CallExp syntaxCopy() { - return new CallExp(loc, e1.syntaxCopy(), arraySyntaxCopy(arguments), names); + return new CallExp(loc, e1.syntaxCopy(), arraySyntaxCopy(arguments), names ? names.copy() : null); } override bool isLvalue() diff --git a/dmd/parse.d b/dmd/parse.d index c98e41cc16c..723bb24d449 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -9352,7 +9352,7 @@ LagainStc: nextToken(); AST.Expressions* arguments = null; - AST.Identifiers* names = new AST.Identifiers(); + AST.Identifiers* names = null; // An anonymous nested class starts with "class" if (token.value == TOK.class_) @@ -9361,6 +9361,7 @@ LagainStc: if (token.value == TOK.leftParenthesis) { arguments = new AST.Expressions(); + names = new AST.Identifiers(); parseNamedArguments(arguments, names); } @@ -9405,6 +9406,7 @@ LagainStc: else if (token.value == TOK.leftParenthesis && t.ty != Tsarray) { arguments = new AST.Expressions(); + names = new AST.Identifiers(); parseNamedArguments(arguments, names); } From 29e7ad7610abb6c484ca99ad13617c23d2bdc8ce Mon Sep 17 00:00:00 2001 From: Dennis Date: Fri, 17 Feb 2023 10:59:19 +0100 Subject: [PATCH 098/177] Deduplicate return parameter destination logic (dlang/dmd!14885) --- dmd/escape.d | 73 ++++++++++++++++++++++++++++++++------------- dmd/expressionsem.d | 30 ++++++++----------- 2 files changed, 65 insertions(+), 38 deletions(-) diff --git a/dmd/escape.d b/dmd/escape.d index 2516a09500d..35c780a5447 100644 --- a/dmd/escape.d +++ b/dmd/escape.d @@ -558,6 +558,46 @@ bool checkConstructorEscape(Scope* sc, CallExp ce, bool gag) return false; } +/// How a `return` parameter escapes its pointer value +enum ReturnParamDest +{ + returnVal, /// through return statement: `return x` + this_, /// assigned to a struct instance: `this.x = x` + firstArg, /// assigned to first argument: `firstArg = x` +} + +/**************************************** + * Find out if instead of returning a `return` parameter via a return statement, + * it is returned via assignment to either `this` or the first parameter. + * + * This works the same as returning the value via a return statement. + * Although the first argument must be `ref`, it is not regarded as returning by `ref`. + * + * See_Also: https://dlang.org.spec/function.html#return-ref-parameters + * + * Params: + * tf = function type + * tthis = type of `this` parameter, or `null` if none + * Returns: What a `return` parameter should transfer the lifetime of the argument to + */ +ReturnParamDest returnParamDest(TypeFunction tf, Type tthis) +{ + assert(tf); + if (tf.isctor) + return ReturnParamDest.this_; + + if (!tf.nextOf() || (tf.nextOf().ty != Tvoid)) + return ReturnParamDest.returnVal; + + if (tthis && tthis.toBasetype().ty == Tstruct) // class `this` is passed by value + return ReturnParamDest.this_; + + if (tf.parameterList.length > 0 && tf.parameterList[0].isReference) + return ReturnParamDest.firstArg; + + return ReturnParamDest.returnVal; +} + /**************************************** * Given an `AssignExp`, determine if the lvalue will cause * the contents of the rvalue to escape. @@ -653,30 +693,23 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) const bool vaIsRef = va && va.isParameter() && va.isReference(); if (log && vaIsRef) printf("va is ref `%s`\n", va.toChars()); - /* Determine if va is the first parameter, through which other 'return' parameters - * can be assigned. - * This works the same as returning the value via a return statement. - * Although va is marked as `ref`, it is not regarded as returning by `ref`. - * https://dlang.org.spec/function.html#return-ref-parameters - */ - bool isFirstRef() + // Determine if va is the first parameter, through which other 'return' parameters + // can be assigned. + bool vaIsFirstRef = false; + if (fd && fd.type) { - if (!vaIsRef) - return false; - Dsymbol p = va.toParent2(); - if (p == fd && fd.type && fd.type.isTypeFunction()) + final switch (returnParamDest(fd.type.isTypeFunction(), fd.vthis ? fd.vthis.type : null)) { - TypeFunction tf = fd.type.isTypeFunction(); - if (!tf.nextOf() || (tf.nextOf().ty != Tvoid && !fd.isCtorDeclaration())) - return false; - if (va == fd.vthis) // `this` of a non-static member function is considered to be the first parameter - return true; - if (!fd.vthis && fd.parameters && fd.parameters.length && (*fd.parameters)[0] == va) // va is first parameter - return true; + case ReturnParamDest.this_: + vaIsFirstRef = va == fd.vthis; + break; + case ReturnParamDest.firstArg: + vaIsFirstRef = (*fd.parameters)[0] == va; + break; + case ReturnParamDest.returnVal: + break; } - return false; } - const bool vaIsFirstRef = isFirstRef(); if (log && vaIsFirstRef) printf("va is first ref `%s`\n", va.toChars()); bool result = false; diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index d2df7a6378f..51bc908c7fb 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -2011,11 +2011,18 @@ private bool functionParameters(const ref Loc loc, Scope* sc, return errorInout(wildmatch); } - Expression firstArg = ((tf.next && tf.next.ty == Tvoid || isCtorCall) && - tthis && - tthis.isMutable() && tthis.toBasetype().ty == Tstruct && - tthis.hasPointers()) - ? ethis : null; + Expression firstArg = null; + final switch (returnParamDest(tf, tthis)) + { + case ReturnParamDest.returnVal: + break; + case ReturnParamDest.firstArg: + firstArg = nargs > 0 ? (*arguments)[0] : null; + break; + case ReturnParamDest.this_: + firstArg = ethis; + break; + } assert(nargs >= nparams); foreach (const i, arg; (*arguments)[0 .. nargs]) @@ -2178,19 +2185,6 @@ private bool functionParameters(const ref Loc loc, Scope* sc, err |= arg.checkSharedAccess(sc); arg = arg.optimize(WANTvalue, p.isReference()); - - /* Determine if this parameter is the "first reference" parameter through which - * later "return" arguments can be stored. - */ - if (i == 0 && !tthis && p.isReference() && p.type && - (tf.next && tf.next.ty == Tvoid || isCtorCall)) - { - Type tb = p.type.baseElemOf(); - if (tb.isMutable() && tb.hasPointers()) - { - firstArg = arg; - } - } } else { From 34faf88ca1136c902f5bf6b5d6b4f66a39a6e9cc Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Fri, 17 Feb 2023 16:27:54 +0000 Subject: [PATCH 099/177] =?UTF-8?q?Fix=20Issue=2023669=20-=20[DIP1000]=20C?= =?UTF-8?q?ompound=20assignment=20to=20length=20of=20slice=20me=E2=80=A6?= =?UTF-8?q?=20(dlang/dmd!14865)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix Issue 23669 - [DIP1000] Compound assignment to length of slice me… Signed-off-by: Dennis Merged-on-behalf-of: Dennis --- dmd/expressionsem.d | 15 ++++----------- tests/dmd/compilable/scope.d | 9 +++++++++ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 51bc908c7fb..14ba676b8a1 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -1591,29 +1591,22 @@ private Expression opAssignToOp(const ref Loc loc, EXP op, Expression e1, Expres /********************* * Rewrite: * array.length op= e2 - * as: - * array.length = array.length op e2 - * or: - * auto tmp = &array; - * (*tmp).length = (*tmp).length op e2 */ private Expression rewriteOpAssign(BinExp exp) { ArrayLengthExp ale = exp.e1.isArrayLengthExp(); if (ale.e1.isVarExp()) { + // array.length = array.length op e2 Expression e = opAssignToOp(exp.loc, exp.op, ale, exp.e2); e = new AssignExp(exp.loc, ale.syntaxCopy(), e); return e; } else { - /* auto tmp = &array; - * (*tmp).length = (*tmp).length op e2 - */ - auto tmp = copyToTemp(0, "__arraylength", new AddrExp(ale.loc, ale.e1)); - - Expression e1 = new ArrayLengthExp(ale.loc, new PtrExp(ale.loc, new VarExp(ale.loc, tmp))); + // (ref tmp = array;), tmp.length = tmp.length op e2 + auto tmp = copyToTemp(STC.ref_, "__arraylength", ale.e1); + Expression e1 = new ArrayLengthExp(ale.loc, new VarExp(ale.loc, tmp)); Expression elvalue = e1.syntaxCopy(); Expression e = opAssignToOp(exp.loc, exp.op, e1, exp.e2); e = new AssignExp(exp.loc, elvalue, e); diff --git a/tests/dmd/compilable/scope.d b/tests/dmd/compilable/scope.d index 95c784627fa..44f54f7468a 100644 --- a/tests/dmd/compilable/scope.d +++ b/tests/dmd/compilable/scope.d @@ -253,3 +253,12 @@ void main21209() testForeach(cs); testForeach(fs); } + +struct S23669 +{ + string[] a; + @safe void reserve() scope + { + a.length += 1; + } +} From 82d86a49154b2c48cdf1f78ad8662b7960991f3a Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Fri, 17 Feb 2023 16:47:59 +0100 Subject: [PATCH 100/177] Move incorrectly places runnable tests --- {test => tests/dmd}/runnable/test21821.d | 0 {test => tests/dmd}/runnable/testcheck.c | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {test => tests/dmd}/runnable/test21821.d (100%) rename {test => tests/dmd}/runnable/testcheck.c (100%) diff --git a/test/runnable/test21821.d b/tests/dmd/runnable/test21821.d similarity index 100% rename from test/runnable/test21821.d rename to tests/dmd/runnable/test21821.d diff --git a/test/runnable/testcheck.c b/tests/dmd/runnable/testcheck.c similarity index 100% rename from test/runnable/testcheck.c rename to tests/dmd/runnable/testcheck.c From 91af4953f322f69c03ab72f6fee6b06521a5aa1b Mon Sep 17 00:00:00 2001 From: Dennis Date: Mon, 20 Feb 2023 11:55:36 +0100 Subject: [PATCH 101/177] Fix 22916 - copy of ref return still treated as scope variable (dlang/dmd!14871) --- dmd/escape.d | 11 ++++--- tests/dmd/compilable/test22916.d | 42 ++++++++++++++++++++++++++ tests/dmd/fail_compilation/retscope6.d | 28 ----------------- 3 files changed, 48 insertions(+), 33 deletions(-) create mode 100644 tests/dmd/compilable/test22916.d diff --git a/dmd/escape.d b/dmd/escape.d index 35c780a5447..420fa7f80bb 100644 --- a/dmd/escape.d +++ b/dmd/escape.d @@ -648,6 +648,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) if (e1.isStructLiteralExp()) return false; + VarDeclaration va = expToVariable(e1); EscapeByResults er; if (byRef) @@ -658,7 +659,6 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef) if (!er.byref.length && !er.byvalue.length && !er.byfunc.length && !er.byexp.length) return false; - VarDeclaration va = expToVariable(e1); if (va && e.op == EXP.concatenateElemAssign) { @@ -1777,7 +1777,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re Parameter p = tf.parameterList[i - j]; const stc = tf.parameterStorageClass(null, p); ScopeRef psr = buildScopeRef(stc); - if (psr == ScopeRef.ReturnScope) + if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope) { if (tf.isref) { @@ -1797,8 +1797,6 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re else escapeByValue(arg, er, live, retRefTransition); } - else if (psr == ScopeRef.Ref_ReturnScope) - escapeByValue(arg, er, live, retRefTransition); else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope) { if (tf.isref) @@ -1851,7 +1849,10 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re const psr = buildScopeRef(getThisStorageClass(fd)); if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope) - escapeByValue(dve.e1, er, live, retRefTransition); + { + if (!tf.isref || tf.isctor) + escapeByValue(dve.e1, er, live, retRefTransition); + } else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope) { if (tf.isref) diff --git a/tests/dmd/compilable/test22916.d b/tests/dmd/compilable/test22916.d new file mode 100644 index 00000000000..9f779fd07da --- /dev/null +++ b/tests/dmd/compilable/test22916.d @@ -0,0 +1,42 @@ +// REQUIRED_ARGS: -preview=dip1000 + +// https://issues.dlang.org/show_bug.cgi?id=22916 +// Issue 22916 - [dip1000] copy of ref return still treated as scope variable (edit) + +@safe: +struct Arr +{ + int** ptr; + ref int* index() return scope { return *ptr; } + void assign(int* p) scope { *ptr = p; } +} + +void main0() +{ + scope Arr a; + a.assign(a.index()); +} + +// https://issues.dlang.org/show_bug.cgi?id=23682 +ref char* front_p(ref return scope char** p) { return *p; } +ref char* front_r( return scope char** p) { return *p; } + +char* g; + +void test23862() +{ + scope char** _errors; + g = front_p(_errors); // should pass + g = front_r(_errors); // should pass +} + +// Test case reduced from druntime +ref int* monitor(return scope Object h) pure nothrow @nogc @trusted +{ + return *cast(int**)&h.__monitor; +} + +int* getMonitor(Object h) pure @nogc +{ + return monitor(h); // should pass +} diff --git a/tests/dmd/fail_compilation/retscope6.d b/tests/dmd/fail_compilation/retscope6.d index b43fc26f346..5c581d1db71 100644 --- a/tests/dmd/fail_compilation/retscope6.d +++ b/tests/dmd/fail_compilation/retscope6.d @@ -293,31 +293,3 @@ ref int escape23021() @safe } /******************************/ - -// https://issues.dlang.org/show_bug.cgi?id=23682 - -alias VErr = char*; - -@safe ref char* front_p(return scope char** p) { return *p; } - -char* g; - -@safe void test23862() -{ - char* _errors; - g = front_p(&_errors); // should pass -} - -/*******************************************/ - -ref int* monitor(return scope Object h) pure nothrow @nogc -{ - return *cast(int**)&h.__monitor; -} - -int* getMonitor(Object h) pure @nogc -{ - return monitor(h); // should pass -} - -/*******************************************/ From cb64bc5fcf49224dca275cee41b890df3f5ef7d8 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sun, 19 Feb 2023 23:25:56 -0800 Subject: [PATCH 102/177] fix Issue 23717 - runnable/bitfields.c:192:5: error: unknown type name S; use struct keyword to refer to the typ --- tests/dmd/runnable/bitfields.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dmd/runnable/bitfields.c b/tests/dmd/runnable/bitfields.c index 7e986b5f5f7..8946c832571 100644 --- a/tests/dmd/runnable/bitfields.c +++ b/tests/dmd/runnable/bitfields.c @@ -189,7 +189,7 @@ struct S6 int boo6() { - S s; + struct S6 s; s.a = 3; s.b = 1; s.a += 2; From 6e2bc336a67d824fe43135757b04e0a16b9253b5 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 20 Feb 2023 21:52:02 -0800 Subject: [PATCH 103/177] ImportC: smoke test all C Standard .h files (dlang/dmd!14810) --- runtime/druntime/src/importc.h | 19 +++++- tests/dmd/compilable/stdcheaders.c | 103 +++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 tests/dmd/compilable/stdcheaders.c diff --git a/runtime/druntime/src/importc.h b/runtime/druntime/src/importc.h index 7bb6c01332f..5d50e541969 100644 --- a/runtime/druntime/src/importc.h +++ b/runtime/druntime/src/importc.h @@ -43,6 +43,13 @@ */ #define __fastcall +#define __forceinline +#undef _Check_return_ +//#define _Check_return_ +#define __pragma(x) + +#undef _GLIBCXX_USE_FLOAT128 + /* Microsoft builtin types */ #define __int8 char #define __int16 short @@ -95,6 +102,11 @@ #if __FreeBSD__ #endif +#if _MSC_VER +//#undef _Post_writable_size +//#define _Post_writable_size(x) // consider #include +#endif + /**************************** * Define it to do what other C compilers do. */ @@ -107,11 +119,12 @@ */ #define __STDC_NO_VLA__ 1 -/************************* - * Ubuntu's assert.h uses this - */ #if linux // Microsoft won't allow the following macro +// Ubuntu's assert.h uses this #define __PRETTY_FUNCTION__ __func__ + +#define _Float128 long double +#define __float128 long double #endif #if __APPLE__ diff --git a/tests/dmd/compilable/stdcheaders.c b/tests/dmd/compilable/stdcheaders.c new file mode 100644 index 00000000000..90c0339a841 --- /dev/null +++ b/tests/dmd/compilable/stdcheaders.c @@ -0,0 +1,103 @@ +/* Do a smoke test of the C Standard headers. + * Many platforms do not support all the C Standard headers. + */ + +#include + +#ifndef __DMC__ // D:\a\1\s\tools\dm\include\complex.h(105): Deprecation: use of complex type `cdouble` is deprecated, use `std.complex.Complex!(double)` instead +#ifndef __FreeBSD__ // defines _COMPLEX_I with use of `i` postfix +#include +#endif +#endif + +#include +#include + +#ifndef _MSC_VER // C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt\fenv.h(68): Error: variable `stdcheaders._Fenv1` extern symbols cannot have initializers +#ifndef __FreeBSD__ // cannot turn off __GNUCLIKE_ASM in machine/ieeefp.h +#include +#endif +#endif + +#include +#include +#include +#include +#include + +#ifndef __APPLE__ // /Applications/Xcode-14.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/tgmath.h(39): Error: named parameter required before `...` +#include +#endif + +#ifndef _MSC_VER // setjmp.h(51): Error: missing tag `identifier` after `struct +#include +#endif + +#include + +#ifndef __DMC__ // no stdalign.h +#include +#endif + +#include + +#ifndef __DMC__ // no stdatomic.h +#ifndef __linux__ +#ifndef _MSC_VER +#ifndef __APPLE__ // /Applications/Xcode-14.2.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/14.0.0/include/stdatomic.h(80): Error: type-specifier is missing +#ifndef __FreeBSD__ // /stdatomic.h(162): Error: found `volatile` when expecting `{` +#include +#endif +#endif +#endif +#endif +#endif + +#include +#include +#include +#include + +#ifndef _MSC_VER // ucrt\corecrt_malloc.h(58): Error: extended-decl-modifier expected +#include +#endif + +#ifndef __DMC__ // no stdnoreturn.h +#include +#endif + +#include + +#ifndef __DMC__ // no tgmath.h +#ifndef _MSC_VER // C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt\tgmath.h(33): Error: no type for declarator before `)` +#ifndef __APPLE__ // /Applications/Xcode-14.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/tgmath.h(39): Error: named parameter required before `...` +#ifndef __FreeBSD__ // #includes complex.h +#include +#endif +#endif +#endif +#endif + +#ifndef __DMC__ +#ifndef __linux__ +#ifndef __APPLE__ +#ifndef _MSC_VER +#include +#endif +#endif +#endif +#endif + +#include + +#ifndef __DMC__ // no uchar.h +#ifndef __APPLE__ // no uchar.h +#include +#endif +#endif + +#include + +#ifndef __DMC__ // wctype.h(102): Error: unterminated string constant starting at #defines(780) +#include +#endif From 725f264bcd2e43557d5c24a793f5607e2b305e76 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sun, 19 Feb 2023 23:11:33 -0800 Subject: [PATCH 104/177] fix Issue 23711 - compilable/testcstuff1.c:63:1: error: invalid use of restrict --- tests/dmd/compilable/testcstuff1.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/dmd/compilable/testcstuff1.c b/tests/dmd/compilable/testcstuff1.c index af5682578fa..19db4f29174 100644 --- a/tests/dmd/compilable/testcstuff1.c +++ b/tests/dmd/compilable/testcstuff1.c @@ -60,7 +60,7 @@ _Static_assert(sizeof(float) == 4, "ok"); _Static_assert(sizeof(double) == 8, "ok"); //_Static_assert(sizeof(long double) == 8 || sizeof(long double) == 10 || sizeof(long double) == 16, "ok"); -_Static_assert(sizeof(const restrict volatile char volatile restrict const) == 1, "ok"); +_Static_assert(sizeof(const volatile char volatile const) == 1, "ok"); _Static_assert(sizeof(int*) == 8 || 4 == sizeof(char*), "ok"); @@ -257,7 +257,7 @@ void test2() int; int (*xi); int (*fp)(void); - int (* const volatile restrict fp2)(void); + int (* const volatile fp2)(void); void* pv; char c, d; short sh; @@ -275,7 +275,7 @@ void test2() register int reg; const int ci; volatile int vi; - restrict int ri; + int* restrict ri; // _Atomic(int) ai; // _Alignas(c) ac; From 283deba782e94c34982366e5f3109c66c44508d1 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 22 Feb 2023 01:13:32 -0800 Subject: [PATCH 105/177] add core.factory (dlang/dmd!14888) --- runtime/druntime/src/core/factory.d | 68 +++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 runtime/druntime/src/core/factory.d diff --git a/runtime/druntime/src/core/factory.d b/runtime/druntime/src/core/factory.d new file mode 100644 index 00000000000..f45a04ea91f --- /dev/null +++ b/runtime/druntime/src/core/factory.d @@ -0,0 +1,68 @@ +/* Create classes from their modules and names. + * + * Copyright: Copyright (C) D Language Foundation 2023 + * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) + * Authors: Walter Bright, Steven Schveighoffer + * Source: $(DRUNTIMESRC core/_factory.d) + */ + +module core.factory; + +/** + * Create instance of class specified by the module symbol and a string + * representing the name of the class. + * The class must either have no constructors or have + * a default constructor. + * Params: + * mod = symbol representing the module that the class is in + * classname = string representing the name of the class + * Returns: + * null if failed + * Example: + * --- + * module foo.bar; + * + * class C + * { + * this() { x = 10; } + * int x; + * } + * + * void main() + * { + * auto c = cast(C)factory!(foo.bar)("C"); + * assert(c !is null && c.x == 10); + * } + * --- + */ +Object factory(alias mod)(string classname) +{ + foreach(cl; _getModuleClasses!mod) + { + if (cl.stringof == classname) + return cl.classinfo.create(); + } + return null; +} + +@system unittest +{ + Object valid_obj = factory!object("Object"); + Object invalid_obj = factory!object("__this_class_doesnt_exist__"); + + assert(valid_obj !is null); + assert(invalid_obj is null); +} + +/************************************** + * Retrieve as a tuple all the types of the top level classes in the module mod. + */ +private template _getModuleClasses(alias mod) { + alias result = _AliasSeq!(); + static foreach(m; __traits(allMembers, mod)) + static if(is(__traits(getMember, mod, m) == class)) + result = _AliasSeq!(result, __traits(getMember, mod, m)); + alias _getModuleClasses = result; +} + +private template _AliasSeq(TList...) { alias _AliasSeq = TList; } From fc51f611a73d5d11a4fef51e1ef2ff023df91f40 Mon Sep 17 00:00:00 2001 From: Dennis Date: Wed, 22 Feb 2023 10:14:34 +0100 Subject: [PATCH 106/177] Revert "fix Issue 23558 - add __traits(getModuleClasses [, module name]) (dlang/dmd!14699)" (dlang/dmd!14892) This reverts commit 4e15f10dba6b2cd6b97f6562e461c6657c4c86fd. --- dmd/frontend.h | 1 - dmd/id.d | 1 - dmd/traits.d | 55 +------------------------- tests/dmd/compilable/test23558.d | 17 -------- tests/dmd/fail_compilation/test23558.d | 16 -------- 5 files changed, 1 insertion(+), 89 deletions(-) delete mode 100644 tests/dmd/compilable/test23558.d delete mode 100644 tests/dmd/fail_compilation/test23558.d diff --git a/dmd/frontend.h b/dmd/frontend.h index a6aef2a9d73..ef13151e5b1 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -8726,7 +8726,6 @@ struct Id final static Identifier* getVisibility; static Identifier* parent; static Identifier* child; - static Identifier* getModuleClasses; static Identifier* getMember; static Identifier* getOverloads; static Identifier* getVirtualFunctions; diff --git a/dmd/id.d b/dmd/id.d index 2eed152a8a6..ec5cb25ef28 100644 --- a/dmd/id.d +++ b/dmd/id.d @@ -462,7 +462,6 @@ immutable Msgtable[] msgtable = { "getVisibility" }, { "parent" }, { "child" }, - { "getModuleClasses" }, { "getMember" }, { "getOverloads" }, { "getVirtualFunctions" }, diff --git a/dmd/traits.d b/dmd/traits.d index 3e5ff159645..de0129b5b33 100644 --- a/dmd/traits.d +++ b/dmd/traits.d @@ -14,7 +14,6 @@ module dmd.traits; import core.stdc.stdio; -import core.stdc.string; import dmd.aggregate; import dmd.arraytypes; @@ -744,7 +743,6 @@ Expression semanticTraits(TraitsExp e, Scope* sc) auto se = new StringExp(e.loc, id.toString()); return se.expressionSemantic(sc); } - if (e.ident == Id.fullyQualifiedName) // https://dlang.org/spec/traits.html#fullyQualifiedName { if (dim != 1) @@ -781,56 +779,6 @@ Expression semanticTraits(TraitsExp e, Scope* sc) return se.expressionSemantic(sc); } - - if (e.ident == Id.getModuleClasses) - { - /* https://dlang.org/spec/traits.html#getModuleClasses - */ - Module m; - if (dim == 0) - { - m = sc._module; // default to current module - if (!m) - return False(); - } - else if (dim == 1) - { - auto o = (*e.args)[0]; - auto s = getDsymbol(o); - if (s) - { - if (auto imp = s.isImport()) - m = imp.mod; - else - m = s.isModule(); - } - if (!m) - { - e.error("in expression `%s` `%s` must be a module", e.toChars(), o.toChars()); - return ErrorExp.get(); - } - } - else - return dimError(0); - - ClassDeclarations aclasses; - getLocalClasses(m, aclasses); - - auto exps = new Expressions(aclasses.length); - foreach (i, cd; aclasses) - { - const p = cd.toPrettyChars(); - //printf("class %s\n", p); - const s = p[0 .. strlen(p)]; - auto se = new StringExp(e.loc, s); - (*exps)[i] = se; - } - - Expression ex = new TupleExp(e.loc, exps); - ex = ex.expressionSemantic(sc); - return ex; - } - if (e.ident == Id.getProtection || e.ident == Id.getVisibility) { if (dim != 1) @@ -2296,7 +2244,7 @@ private void traitNotFound(TraitsExp e) initialized = true; // lazy initialization // All possible traits - __gshared Identifier*[60] idents = + __gshared Identifier*[59] idents = [ &Id.isAbstractClass, &Id.isArithmetic, @@ -2333,7 +2281,6 @@ private void traitNotFound(TraitsExp e) &Id.child, &Id.getLinkage, &Id.getMember, - &Id.getModuleClasses, &Id.getOverloads, &Id.getVirtualFunctions, &Id.getVirtualMethods, diff --git a/tests/dmd/compilable/test23558.d b/tests/dmd/compilable/test23558.d deleted file mode 100644 index c5942fae246..00000000000 --- a/tests/dmd/compilable/test23558.d +++ /dev/null @@ -1,17 +0,0 @@ -/* TEST_OUTPUT: ---- -getModuleClasses: tuple("test23558.C") -getModuleClasses: tuple("std.stdio.StdioException") ---- -*/ - -// https://issues.dlang.org/show_bug.cgi?id=23558 - -import std.stdio; - -class C { } - -pragma(msg, "getModuleClasses: ", __traits(getModuleClasses)); -pragma(msg, "getModuleClasses: ", __traits(getModuleClasses, std.stdio)); - -//pragma(msg, "getClassInfos: ", __traits(getModuleClasses, 3)); diff --git a/tests/dmd/fail_compilation/test23558.d b/tests/dmd/fail_compilation/test23558.d deleted file mode 100644 index 2c6048f698d..00000000000 --- a/tests/dmd/fail_compilation/test23558.d +++ /dev/null @@ -1,16 +0,0 @@ -/* TEST_OUTPUT: ---- -fail_compilation/test23558.d(103): Error: in expression `__traits(getModuleClasses, S)` `S` must be a module -fail_compilation/test23558.d(105): Error: expected 0 arguments for `getModuleClasses` but had 2 ---- - */ - -// https://issues.dlang.org/show_bug.cgi?id=23558 - -#line 100 - -struct S { } - -auto x = __traits(getModuleClasses, S); - -auto y = __traits(getModuleClasses, 1, 2); From 57f4df20549b9869540c1b8887d93a6e89035925 Mon Sep 17 00:00:00 2001 From: Dennis Date: Wed, 22 Feb 2023 10:24:39 +0100 Subject: [PATCH 107/177] Deprecate `-preview=dip25` switch (dlang/dmd!14891) --- dmd/cli.d | 4 ++-- dmd/frontend.h | 3 ++- dmd/globals.d | 2 +- dmd/mars.d | 4 ++++ tests/dmd/compilable/previewhelp.d | 2 +- tests/dmd/compilable/reverthelp.d | 2 +- tests/dmd/fail_compilation/dip25.d | 6 +++--- tests/dmd/fail_compilation/dip25flag.d | 7 +++++++ tests/dmd/fail_compilation/fail_scope.d | 2 +- tests/dmd/fail_compilation/test20809.d | 4 ++-- 10 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 tests/dmd/fail_compilation/dip25flag.d diff --git a/dmd/cli.d b/dmd/cli.d index 9fbb44d3e94..f1afb0c8ee4 100644 --- a/dmd/cli.d +++ b/dmd/cli.d @@ -851,7 +851,7 @@ dmd -cov -unittest myprog.d /// Returns all available reverts static immutable reverts = [ - Feature("dip25", "useDIP25", "revert DIP25 changes https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP25.md"), + Feature("dip25", "useDIP25", "revert DIP25 changes https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP25.md", true, true), Feature("dip1000", "useDIP1000", "revert DIP1000 changes https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md (Scoped Pointers)"), Feature("intpromote", "fix16997", "revert integral promotions for unary + - ~ operators"), @@ -861,7 +861,7 @@ dmd -cov -unittest myprog.d /// Returns all available previews static immutable previews = [ Feature("dip25", "useDIP25", - "implement https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP25.md (Sealed references)"), + "implement https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP25.md (Sealed references)", true, true), Feature("dip1000", "useDIP1000", "implement https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md (Scoped Pointers)"), Feature("dip1008", "ehnogc", diff --git a/dmd/frontend.h b/dmd/frontend.h index ef13151e5b1..fad6b9cb483 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -3196,6 +3196,7 @@ struct Param final externStdUsage(), hcUsage(), logo(), + useDIP25((FeatureState)1), ehnogc(), useDIP1021(), fieldwise(), @@ -3248,7 +3249,7 @@ struct Param final mapfile() { } - Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool verbose = false, bool vcg_ast = false, bool showColumns = false, bool vtls = false, bool vtemplates = false, bool vtemplatesListInstances = false, bool vgc = false, bool vfield = false, bool vcomplex = true, bool vin = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting warnings = (DiagnosticReporting)2u, bool color = false, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = false, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, bool showGaggedErrors = false, bool printErrorContext = false, bool manual = false, bool usage = false, bool mcpuUsage = false, bool transitionUsage = false, bool checkUsage = false, bool checkActionUsage = false, bool revertUsage = false, bool previewUsage = false, bool externStdUsage = false, bool hcUsage = false, bool logo = false, FeatureState useDIP25 = (FeatureState)-1, FeatureState useDIP1000 = (FeatureState)-1, bool ehnogc = false, bool useDIP1021 = false, bool fieldwise = false, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)-1, FeatureState noSharedAccess = (FeatureState)-1, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)-1, FeatureState systemVariables = (FeatureState)-1, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, uint32_t errorLimit = 20u, uint32_t errorSupplementLimit = 6u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array* imppath = nullptr, Array* fileImppath = nullptr, _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), uint32_t debuglevel = 0u, Array* debugids = nullptr, uint32_t versionlevel = 0u, Array* versionids = nullptr, MessageStyle messageStyle = (MessageStyle)0u, bool run = false, Array runargs = Array(), Array cppswitches = Array(), Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}) : + Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool verbose = false, bool vcg_ast = false, bool showColumns = false, bool vtls = false, bool vtemplates = false, bool vtemplatesListInstances = false, bool vgc = false, bool vfield = false, bool vcomplex = true, bool vin = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting warnings = (DiagnosticReporting)2u, bool color = false, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = false, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, bool showGaggedErrors = false, bool printErrorContext = false, bool manual = false, bool usage = false, bool mcpuUsage = false, bool transitionUsage = false, bool checkUsage = false, bool checkActionUsage = false, bool revertUsage = false, bool previewUsage = false, bool externStdUsage = false, bool hcUsage = false, bool logo = false, FeatureState useDIP25 = (FeatureState)1, FeatureState useDIP1000 = (FeatureState)-1, bool ehnogc = false, bool useDIP1021 = false, bool fieldwise = false, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)-1, FeatureState noSharedAccess = (FeatureState)-1, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)-1, FeatureState systemVariables = (FeatureState)-1, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, uint32_t errorLimit = 20u, uint32_t errorSupplementLimit = 6u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array* imppath = nullptr, Array* fileImppath = nullptr, _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), uint32_t debuglevel = 0u, Array* debugids = nullptr, uint32_t versionlevel = 0u, Array* versionids = nullptr, MessageStyle messageStyle = (MessageStyle)0u, bool run = false, Array runargs = Array(), Array cppswitches = Array(), Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}) : obj(obj), multiobj(multiobj), trace(trace), diff --git a/dmd/globals.d b/dmd/globals.d index e6b4e31690a..407c68423c5 100644 --- a/dmd/globals.d +++ b/dmd/globals.d @@ -143,7 +143,7 @@ extern (C++) struct Param bool logo; // print compiler logo // Options for `-preview=/-revert=` - FeatureState useDIP25; // implement https://wiki.dlang.org/DIP25 + FeatureState useDIP25 = FeatureState.enabled; // implement https://wiki.dlang.org/DIP25 FeatureState useDIP1000; // implement https://dlang.org/spec/memory-safe-d.html#scope-return-params bool ehnogc; // use @nogc exception handling bool useDIP1021; // implement https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md diff --git a/dmd/mars.d b/dmd/mars.d index ca0645bbf08..7027735109f 100644 --- a/dmd/mars.d +++ b/dmd/mars.d @@ -2293,7 +2293,11 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param } } else if (arg == "-dip25") // https://dlang.org/dmd.html#switch-dip25 + { + // @@@ DEPRECATION 2.112 @@@ + deprecation(Loc.initial, "`-dip25` no longer has any effect"); params.useDIP25 = FeatureState.enabled; + } else if (arg == "-dip1000") { params.useDIP25 = FeatureState.enabled; diff --git a/tests/dmd/compilable/previewhelp.d b/tests/dmd/compilable/previewhelp.d index f4753eeeb2a..f71a3dd72ec 100644 --- a/tests/dmd/compilable/previewhelp.d +++ b/tests/dmd/compilable/previewhelp.d @@ -5,7 +5,7 @@ TEST_OUTPUT: ---- Upcoming language changes listed by -preview=name: =all Enables all available upcoming language changes - =dip25 implement https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP25.md (Sealed references) + =dip25 implement https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP25.md (Sealed references) [DEPRECATED] =dip1000 implement https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md (Scoped Pointers) =dip1008 implement https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1008.md (@nogc Throwable) =dip1021 implement https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md (Mutable function arguments) diff --git a/tests/dmd/compilable/reverthelp.d b/tests/dmd/compilable/reverthelp.d index 96ff760ba75..127baef5544 100644 --- a/tests/dmd/compilable/reverthelp.d +++ b/tests/dmd/compilable/reverthelp.d @@ -5,7 +5,7 @@ TEST_OUTPUT: ---- Revertable language changes listed by -revert=name: =all Enables all available revertable language changes - =dip25 revert DIP25 changes https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP25.md + =dip25 revert DIP25 changes https://github.com/dlang/DIPs/blob/master/DIPs/archive/DIP25.md [DEPRECATED] =dip1000 revert DIP1000 changes https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md (Scoped Pointers) =intpromote revert integral promotions for unary + - ~ operators =dtorfields don't destruct fields of partially constructed objects diff --git a/tests/dmd/fail_compilation/dip25.d b/tests/dmd/fail_compilation/dip25.d index 02f31407754..f43a6e9ef8d 100644 --- a/tests/dmd/fail_compilation/dip25.d +++ b/tests/dmd/fail_compilation/dip25.d @@ -1,11 +1,11 @@ /* -REQUIRED_ARGS: -de +REQUIRED_ARGS: TEST_OUTPUT: --- -fail_compilation/dip25.d(17): Deprecation: returning `this.buffer[]` escapes a reference to parameter `this` +fail_compilation/dip25.d(17): Error: returning `this.buffer[]` escapes a reference to parameter `this` fail_compilation/dip25.d(15): perhaps annotate the function with `return` fail_compilation/dip25.d(22): Error: returning `identity(x)` escapes a reference to parameter `x` -fail_compilation/dip25.d(23): Deprecation: returning `identity(x)` escapes a reference to parameter `x` +fail_compilation/dip25.d(23): Error: returning `identity(x)` escapes a reference to parameter `x` fail_compilation/dip25.d(23): perhaps annotate the parameter with `return` --- */ diff --git a/tests/dmd/fail_compilation/dip25flag.d b/tests/dmd/fail_compilation/dip25flag.d new file mode 100644 index 00000000000..d75ceace611 --- /dev/null +++ b/tests/dmd/fail_compilation/dip25flag.d @@ -0,0 +1,7 @@ +/* +REQUIRED_ARGS: -de -dip25 +TEST_OUTPUT: +--- +Deprecation: `-dip25` no longer has any effect +--- +*/ diff --git a/tests/dmd/fail_compilation/fail_scope.d b/tests/dmd/fail_compilation/fail_scope.d index 3fac1678e69..f2095921968 100644 --- a/tests/dmd/fail_compilation/fail_scope.d +++ b/tests/dmd/fail_compilation/fail_scope.d @@ -15,7 +15,7 @@ fail_compilation/fail_scope.d(69): `fail_scope.foo8(return ref int x)` fail_compilation/fail_scope.d(82): Error: returning `& string` escapes a reference to local variable `string` fail_compilation/fail_scope.d(92): Error: returning `cast(int[])a` escapes a reference to local variable `a` fail_compilation/fail_scope.d(100): Error: returning `cast(int[])a` escapes a reference to local variable `a` -fail_compilation/fail_scope.d(108): Deprecation: escaping reference to outer local variable `x` +fail_compilation/fail_scope.d(108): Error: escaping reference to outer local variable `x` 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` --- diff --git a/tests/dmd/fail_compilation/test20809.d b/tests/dmd/fail_compilation/test20809.d index 44728c5c2ff..0b452774245 100644 --- a/tests/dmd/fail_compilation/test20809.d +++ b/tests/dmd/fail_compilation/test20809.d @@ -1,8 +1,8 @@ /* -REQUIRED_ARGS: -de +REQUIRED_ARGS: TEST_OUTPUT: --- -fail_compilation/test20809.d(114): Deprecation: returning `this.a` escapes a reference to parameter `this` +fail_compilation/test20809.d(114): Error: returning `this.a` escapes a reference to parameter `this` fail_compilation/test20809.d(112): perhaps annotate the function with `return` --- */ From f787928880f500edcabad322d263ffb26730bb43 Mon Sep 17 00:00:00 2001 From: Dennis Date: Wed, 22 Feb 2023 10:26:09 +0100 Subject: [PATCH 108/177] Fix 23676 - Static foreach hangs compilation for some time (dlang/dmd!14886) --- dmd/frontend.h | 4 ++++ dmd/func.d | 13 ++++++++++--- tests/dmd/compilable/test23676.d | 16 ++++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 tests/dmd/compilable/test23676.d diff --git a/dmd/frontend.h b/dmd/frontend.h index fad6b9cb483..80caadb0091 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -2542,6 +2542,10 @@ class FuncDeclaration : public Declaration bool isCrtCtor(bool v); bool isCrtDtor() const; bool isCrtDtor(bool v); + bool hasEscapingSiblings() const; + bool hasEscapingSiblings(bool v); + bool computedEscapingSiblings() const; + bool computedEscapingSiblings(bool v); private: uint32_t bitFields; public: diff --git a/dmd/func.d b/dmd/func.d index cf3e1154525..3789d7a5440 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -217,6 +217,8 @@ private struct FUNCFLAG bool hasAlwaysInlines; /// Contains references to functions that must be inlined bool isCrtCtor; /// Has attribute pragma(crt_constructor) bool isCrtDtor; /// Has attribute pragma(crt_destructor) + bool hasEscapingSiblings;/// Has sibling functions that escape + bool computedEscapingSiblings; /// `hasEscapingSiblings` has been computed } /*********************************************************** @@ -1980,6 +1982,7 @@ extern (C++) class FuncDeclaration : Declaration if (!sc.intypeof && !(sc.flags & SCOPE.compile)) { siblingCallers.push(fdthis); + computedEscapingSiblings = false; } } } @@ -2029,8 +2032,7 @@ extern (C++) class FuncDeclaration : Declaration * is already set to `true` upon entering this function when the * struct/class refers to a local variable and a closure is needed. */ - - //printf("FuncDeclaration::needsClosure() %s\n", toChars()); + //printf("FuncDeclaration::needsClosure() %s\n", toPrettyChars()); if (requiresClosure) goto Lyes; @@ -2107,7 +2109,7 @@ extern (C++) class FuncDeclaration : Declaration */ extern (C++) final bool checkClosure() { - //printf("checkClosure() %s\n", toChars()); + //printf("checkClosure() %s\n", toPrettyChars()); if (!needsClosure()) return false; @@ -3625,6 +3627,9 @@ private bool checkEscapingSiblings(FuncDeclaration f, FuncDeclaration outerFunc, FuncDeclaration f; } + if (f.computedEscapingSiblings) + return f.hasEscapingSiblings; + PrevSibling ps; ps.p = cast(PrevSibling*)p; ps.f = f; @@ -3666,6 +3671,8 @@ private bool checkEscapingSiblings(FuncDeclaration f, FuncDeclaration outerFunc, prev = prev.p; } } + f.hasEscapingSiblings = bAnyClosures; + f.computedEscapingSiblings = true; //printf("\t%d\n", bAnyClosures); return bAnyClosures; } diff --git a/tests/dmd/compilable/test23676.d b/tests/dmd/compilable/test23676.d new file mode 100644 index 00000000000..91a73b9de82 --- /dev/null +++ b/tests/dmd/compilable/test23676.d @@ -0,0 +1,16 @@ +// Issue 23676 - Static foreach hangs compilation for some time +// https://issues.dlang.org/show_bug.cgi?id=23676 + +void f() +{ + int i; + void g(int I)() + { + static foreach(j; 0..11) + { + i++; + g!j(); + } + } + g!0; +} From 07ece66bef2a54b1c7124aa03c4ba8b12f30ab10 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sun, 19 Feb 2023 21:00:49 +0000 Subject: [PATCH 109/177] Tweak semicolon expected to close `alias` declaration error Show unexpected token. --- dmd/parse.d | 4 ++-- tests/dmd/fail_compilation/e15876_5.d | 2 +- tests/dmd/fail_compilation/fail21243.d | 2 +- tests/dmd/fail_compilation/issue16020.d | 2 +- tests/dmd/fail_compilation/udaparams.d | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dmd/parse.d b/dmd/parse.d index 723bb24d449..ec219af6cb4 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -4525,7 +4525,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer continue; default: - error("semicolon expected to close `alias` declaration"); + error("semicolon expected to close `alias` declaration, not `%s`", token.toChars()); break; } } @@ -4957,7 +4957,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer continue; default: - error("semicolon expected to close `alias` declaration"); + error("semicolon expected to close `alias` declaration, not `%s`", token.toChars()); break; } break; diff --git a/tests/dmd/fail_compilation/e15876_5.d b/tests/dmd/fail_compilation/e15876_5.d index 5b65b1b345a..96b23e278cd 100644 --- a/tests/dmd/fail_compilation/e15876_5.d +++ b/tests/dmd/fail_compilation/e15876_5.d @@ -2,7 +2,7 @@ TEST_OUTPUT: --- fail_compilation/e15876_5.d(16): Error: basic type expected, not `End of File` -fail_compilation/e15876_5.d(16): Error: semicolon expected to close `alias` declaration +fail_compilation/e15876_5.d(16): Error: semicolon expected to close `alias` declaration, not `End of File` fail_compilation/e15876_5.d(16): Error: found `End of File` when expecting `}` following compound statement fail_compilation/e15876_5.d(16): Error: found `End of File` when expecting `]` fail_compilation/e15876_5.d(16): Error: no identifier for declarator `p[() diff --git a/tests/dmd/fail_compilation/fail21243.d b/tests/dmd/fail_compilation/fail21243.d index 25df235e9cb..2e170d096c5 100644 --- a/tests/dmd/fail_compilation/fail21243.d +++ b/tests/dmd/fail_compilation/fail21243.d @@ -8,7 +8,7 @@ fail_compilation/fail21243.d(17): Error: `auto` can only be used as part of `aut fail_compilation/fail21243.d(18): Error: basic type expected, not `(` fail_compilation/fail21243.d(18): Error: function declaration without return type. (Note that constructors are always named `this`) fail_compilation/fail21243.d(18): Deprecation: storage class `auto` has no effect in type aliases -fail_compilation/fail21243.d(18): Error: semicolon expected to close `alias` declaration +fail_compilation/fail21243.d(18): Error: semicolon expected to close `alias` declaration, not `=>` fail_compilation/fail21243.d(18): Error: declaration expected, not `=>` fail_compilation/fail21243.d(19): Error: `auto` can only be used as part of `auto ref` for function literal return values --- diff --git a/tests/dmd/fail_compilation/issue16020.d b/tests/dmd/fail_compilation/issue16020.d index 75e3b9f0b81..fe4ad78f1ac 100644 --- a/tests/dmd/fail_compilation/issue16020.d +++ b/tests/dmd/fail_compilation/issue16020.d @@ -2,7 +2,7 @@ TEST_OUTPUT: --- fail_compilation/issue16020.d(12): Error: user-defined attributes not allowed for `alias` declarations -fail_compilation/issue16020.d(13): Error: semicolon expected to close `alias` declaration +fail_compilation/issue16020.d(13): Error: semicolon expected to close `alias` declaration, not `(` fail_compilation/issue16020.d(13): Error: declaration expected, not `(` --- */ diff --git a/tests/dmd/fail_compilation/udaparams.d b/tests/dmd/fail_compilation/udaparams.d index ec4796789ac..453ebba4e09 100644 --- a/tests/dmd/fail_compilation/udaparams.d +++ b/tests/dmd/fail_compilation/udaparams.d @@ -14,9 +14,9 @@ fail_compilation/udaparams.d(44): Error: `@trusted` attribute for function param 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(53): Error: semicolon expected to close `alias` declaration +fail_compilation/udaparams.d(53): Error: semicolon expected to close `alias` declaration, not `=>` fail_compilation/udaparams.d(53): Error: declaration expected, not `=>` -fail_compilation/udaparams.d(54): Error: semicolon expected to close `alias` declaration +fail_compilation/udaparams.d(54): Error: semicolon expected to close `alias` declaration, not `=>` fail_compilation/udaparams.d(54): Error: declaration expected, not `=>` fail_compilation/udaparams.d(57): Error: basic type expected, not `@` fail_compilation/udaparams.d(57): Error: identifier expected for template value parameter From 79de6ee59c6d7ca30212610ce4da9bcea9f6719c Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 24 Feb 2023 19:51:20 -0800 Subject: [PATCH 110/177] fix Issue 16098 - align(N) not respected for stack variables if N > platform stack alignment (dlang/dmd!14764) * fix 16098 * fix Issue 16098 - align(N) not respected for stack variables if N > platform stack alignment --- dmd/declaration.d | 5 +++ dmd/declaration.h | 6 ++++ dmd/dsymbolsem.d | 16 +++++++++ dmd/dtemplate.d | 2 +- dmd/frontend.h | 7 ++++ dmd/func.d | 12 +++++++ dmd/target.d | 9 +++++ dmd/target.h | 1 + tests/dmd/runnable/test16098.d | 63 ++++++++++++++++++++++++++++++++-- 9 files changed, 118 insertions(+), 3 deletions(-) diff --git a/dmd/declaration.d b/dmd/declaration.d index e8d8465a9fa..7cd8df19bdc 100644 --- a/dmd/declaration.d +++ b/dmd/declaration.d @@ -1149,6 +1149,11 @@ extern (C++) class VarDeclaration : Declaration bool isArgDtorVar; /// temporary created to handle scope destruction of a function argument bool isCmacro; /// it is a C macro turned into a C declaration + version (MARS) + { + bool inClosure; /// is inserted into a GC allocated closure + bool inAlignSection; /// is inserted into an aligned section on stack + } } import dmd.common.bitfields : generateBitFields; diff --git a/dmd/declaration.h b/dmd/declaration.h index 429b3ccee04..20accc82ec6 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -272,6 +272,12 @@ class VarDeclaration : public Declaration bool isArgDtorVar(bool v); bool isCmacro() const; // if a C macro turned into a C variable bool isCmacro(bool v); +#if MARS + bool inClosure() const; // is inserted into a GC allocated closure + bool inClosure(bool v); + bool inAlignSection() const; // is inserted into aligned section on stack + bool inAlignSection(bool v); +#endif static VarDeclaration *create(const Loc &loc, Type *t, Identifier *id, Initializer *init, StorageClass storage_class = STCundefined); VarDeclaration *syntaxCopy(Dsymbol *) override; void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override final; diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index eb60cc67004..8e491be37fe 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -855,6 +855,22 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } } + /* If the alignment of a stack local is greater than the stack alignment, + * note it in the enclosing function's alignSectionVars + */ + version (MARS) + { + if (!dsym.alignment.isDefault() && sc.func && + dsym.alignment.get() > target.stackAlign() && + sc.func && !dsym.isDataseg() && !dsym.isParameter() && !dsym.isField()) + { + auto fd = sc.func; + if (!fd.alignSectionVars) + fd.alignSectionVars = new VarDeclarations(); + fd.alignSectionVars.push(dsym); + } + } + if ((dsym.storage_class & (STC.ref_ | STC.parameter | STC.foreach_ | STC.temp | STC.result)) == STC.ref_ && dsym.ident != Id.This) { dsym.error("- only parameters, functions and `foreach` declarations can be `ref`"); diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index df76d28a0b2..ad3a6d4dd54 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -7561,7 +7561,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol //printf("\t staticIfDg on '%s %s' in '%s'\n", s.kind(), s.toChars(), this.toChars()); if (!s.isStaticIfDeclaration()) { - //s.dsymbolSemantic(sc2); + //s.dsymbolSemantic(sc2); done = true; return; } diff --git a/dmd/frontend.h b/dmd/frontend.h index 80caadb0091..3cf54a2d702 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -2488,6 +2488,8 @@ class FuncDeclaration : public Declaration Symbol* shidden; Array* returns; Array* gotos; + Array* alignSectionVars; + Symbol* salignSection; BUILTIN builtin; int32_t tookAddressOf; bool requiresClosure; @@ -5972,6 +5974,10 @@ class VarDeclaration : public Declaration bool isArgDtorVar(bool v); bool isCmacro() const; bool isCmacro(bool v); + bool inClosure() const; + bool inClosure(bool v); + bool inAlignSection() const; + bool inAlignSection(bool v); private: uint16_t bitFields; public: @@ -8124,6 +8130,7 @@ struct Target final bool isCalleeDestroyingArgs(TypeFunction* tf); bool libraryObjectMonitors(FuncDeclaration* fd, Statement* fbody); bool supportsLinkerDirective() const; + uint32_t stackAlign(); Target() : os((OS)1u), osMajor(0u), diff --git a/dmd/func.d b/dmd/func.d index 3789d7a5440..4b6b5b58233 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -324,6 +324,12 @@ extern (C++) class FuncDeclaration : Declaration GotoStatements* gotos; /// Gotos with forward references + version (MARS) + { + VarDeclarations* alignSectionVars; /// local variables with alignment needs larger than stackAlign + Symbol* salignSection; /// pointer to aligned section, if any + } + /// set if this is a known, builtin function we can evaluate at compile time BUILTIN builtin = BUILTIN.unknown; @@ -2831,6 +2837,12 @@ extern (C++) class FuncDeclaration : Declaration return false; if (v.nestedrefs.length && needsClosure()) return false; + // don't know if the return storage is aligned + version (MARS) + { + if (alignSectionVars && (*alignSectionVars).contains(v)) + return false; + } // The variable type needs to be equivalent to the return type. if (!v.type.equivalent(tf.next)) return false; diff --git a/dmd/target.d b/dmd/target.d index 944f09f2d2d..461e1e95ce4 100644 --- a/dmd/target.d +++ b/dmd/target.d @@ -1136,6 +1136,15 @@ extern (C++) struct Target { return (os & Target.OS.Posix) != 0; } + + /********************* + * Returns: + * alignment of the stack + */ + extern (C++) uint stackAlign() + { + return isXmmSupported() ? 16 : (is64bit ? 8 : 4); + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/dmd/target.h b/dmd/target.h index ef2c09d4147..5bd5162d8d4 100644 --- a/dmd/target.h +++ b/dmd/target.h @@ -208,6 +208,7 @@ struct Target bool isCalleeDestroyingArgs(TypeFunction* tf); bool libraryObjectMonitors(FuncDeclaration *fd, Statement *fbody); bool supportsLinkerDirective() const; + unsigned stackAlign(); void addPredefinedGlobalIdentifiers() const; }; diff --git a/tests/dmd/runnable/test16098.d b/tests/dmd/runnable/test16098.d index 16b34f1894c..a5af2d56448 100644 --- a/tests/dmd/runnable/test16098.d +++ b/tests/dmd/runnable/test16098.d @@ -1,14 +1,73 @@ // https://issues.dlang.org/show_bug.cgi?id=16098 -void main() { +/*********************************************/ + +void testDynamicClosure() +{ byte a; align(128) byte b; assert((cast(size_t) &b) % 128 == 0); + b = 37; byte foo() { return b; } dg = &foo; - assert(dg() == false); + assert(dg() == 37); } __gshared byte delegate() dg; + +/*********************************************/ + +void testStaticClosure() +{ + byte aa; + align(128) byte b; + assert((cast(size_t) &b) % 128 == 0); + b = 73; + + byte foo() { return b; } + assert(foo() == 73); +} + +/*********************************************/ + +void test3() +{ + struct S + { + align(32) int b; + } +} + +/*********************************************/ + +align(16) +struct Cent +{ + ulong lo; // low 64 bits + ulong hi; // high 64 bits +} + +enum Cent One = { 1 }; + +Cent inc(Cent c) { return add(c, One); } + +Cent add(Cent c1, Cent c2) { const Cent ret = { 3, 2 }; return ret; } + +void test4() +{ + const Cent C10_0 = { 0, 10 }; + const Cent Cm10_0 = inc(C10_0); +} + +/*********************************************/ + +int main() +{ + testDynamicClosure(); + testStaticClosure(); + test3(); + test4(); + return 0; +} From 5a3a341f06f8dd1687be5935f292c928f26d1d52 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Sat, 25 Feb 2023 19:32:13 +0100 Subject: [PATCH 111/177] Strip trailing whitespace in `Outbuffer.writenl` --- dmd/common/outbuffer.d | 20 ++++++++++++++++++- .../dmd/compilable/extra-files/header18365.d | 2 +- tests/dmd/compilable/extra-files/imp9057.d | 2 +- tests/dmd/compilable/extra-files/test23626a.d | 2 +- tests/dmd/compilable/extra-files/vcg-ast.d.cg | 2 +- tests/dmd/runnable/extra-files/test39.d | 2 +- 6 files changed, 24 insertions(+), 6 deletions(-) diff --git a/dmd/common/outbuffer.d b/dmd/common/outbuffer.d index 276928a6bd8..007d301359c 100644 --- a/dmd/common/outbuffer.d +++ b/dmd/common/outbuffer.d @@ -338,9 +338,12 @@ struct OutBuffer offset += len; } - /// write newline + /// strip trailing tabs or spaces, write newline extern (C++) void writenl() pure nothrow @safe { + while (offset > 0 && (data[offset - 1] == ' ' || data[offset - 1] == '\t')) + offset--; + version (Windows) { writeword(0x0A0D); // newline is CR,LF on Microsoft OS's @@ -919,3 +922,18 @@ unittest buf.setsize(4); assert(buf.length == 4); } + +unittest +{ + OutBuffer buf; + + buf.writenl(); + buf.writestring("abc \t "); + buf.writenl(); // strips trailing whitespace + buf.writenl(); // doesn't strip previous newline + + version(Windows) + assert(buf[] == "\r\nabc\r\n\r\n"); + else + assert(buf[] == "\nabc\n\n"); +} diff --git a/tests/dmd/compilable/extra-files/header18365.d b/tests/dmd/compilable/extra-files/header18365.d index 64d8ad073cf..a0fb8333d1b 100644 --- a/tests/dmd/compilable/extra-files/header18365.d +++ b/tests/dmd/compilable/extra-files/header18365.d @@ -1,5 +1,5 @@ module foo.bar.ba; -nothrow pure @nogc @safe package(foo) +nothrow pure @nogc @safe package(foo) { void foo(); nothrow pure @nogc @safe package(foo.bar) void foo2(); diff --git a/tests/dmd/compilable/extra-files/imp9057.d b/tests/dmd/compilable/extra-files/imp9057.d index 54598dd7769..74f035e40d3 100644 --- a/tests/dmd/compilable/extra-files/imp9057.d +++ b/tests/dmd/compilable/extra-files/imp9057.d @@ -1,5 +1,5 @@ struct BugInt { - uint[] data = ZEROX; + uint[] data = ZEROX; } enum uint [] ZEROX = [0]; diff --git a/tests/dmd/compilable/extra-files/test23626a.d b/tests/dmd/compilable/extra-files/test23626a.d index d3608f407fa..a1345929e14 100644 --- a/tests/dmd/compilable/extra-files/test23626a.d +++ b/tests/dmd/compilable/extra-files/test23626a.d @@ -1,5 +1,5 @@ template fullyQualifiedName(T...) -{ +{ enum fullyQualifiedName = !T[0]; } diff --git a/tests/dmd/compilable/extra-files/vcg-ast.d.cg b/tests/dmd/compilable/extra-files/vcg-ast.d.cg index 1bb0cd76655..688eb9f080d 100644 --- a/tests/dmd/compilable/extra-files/vcg-ast.d.cg +++ b/tests/dmd/compilable/extra-files/vcg-ast.d.cg @@ -109,7 +109,7 @@ R!int } mixin _d_cmain!(); { - extern (C) + extern (C) { extern (C) int _d_run_main(int argc, char** argv, void* mainFunc); extern (C) int _Dmain(char[][] args); diff --git a/tests/dmd/runnable/extra-files/test39.d b/tests/dmd/runnable/extra-files/test39.d index dd05b1b3529..a8f512d5a0b 100644 --- a/tests/dmd/runnable/extra-files/test39.d +++ b/tests/dmd/runnable/extra-files/test39.d @@ -7,4 +7,4 @@ void main() { auto t = new Test!(char); t.show ("hello"); -} +} From 53c8f9baf11003e9b26e2aef05dce57a491fe85b Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 25 Feb 2023 21:38:36 -0800 Subject: [PATCH 112/177] fix Issue 23710 - [REG master] Reachable code inside an 'if (false)' block no longer gets codegen --- tests/dmd/fail_compilation/test23710.d | 32 ++++++++++++++++++++++++++ tests/dmd/runnable/test23710.d | 30 ++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 tests/dmd/fail_compilation/test23710.d create mode 100644 tests/dmd/runnable/test23710.d diff --git a/tests/dmd/fail_compilation/test23710.d b/tests/dmd/fail_compilation/test23710.d new file mode 100644 index 00000000000..e834b78f7d5 --- /dev/null +++ b/tests/dmd/fail_compilation/test23710.d @@ -0,0 +1,32 @@ +/* REQUIRED_ARGS: -betterC +TEST_OUTPUT: +--- +fail_compilation/test23710.d(111): Error: array concatenation of expression `foo ~ [1, 2, 3]` requires the GC which is not available with -betterC +--- + */ +// https://issues.dlang.org/show_bug.cgi?id=23710 + +#line 100 + +int test(int i) +{ + int j; + int[] foo; + if (0) + { + for (;;) + { + import core.stdc.stdio; + printf("start body\n"); + foo = foo ~ [1,2,3]; +L1: + printf("foo.length = %zu\n", foo.length); + j += foo.length; + i += 2; + if (i > 5) + return j; + printf("end body\n"); + } + } + goto L1; +} diff --git a/tests/dmd/runnable/test23710.d b/tests/dmd/runnable/test23710.d new file mode 100644 index 00000000000..05ab1e43256 --- /dev/null +++ b/tests/dmd/runnable/test23710.d @@ -0,0 +1,30 @@ +// https://issues.dlang.org/show_bug.cgi?id=23710 + +int test(int i) +{ + int j; + int[] foo; + if (0) + { + for (;;) + { + import core.stdc.stdio; + printf("start body\n"); + foo = foo ~ [1,2,3]; +L1: + printf("foo.length = %zu\n", foo.length); + j += foo.length; + i += 2; + if (i > 5) + return j; + printf("end body\n"); + } + } + goto L1; +} + +int main() +{ + assert(test(1) == 0 + 3 + 6); + return 0; +} From e67d8148ee46f3b04ac52c24a52487e11293e460 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sun, 26 Feb 2023 15:08:59 -0800 Subject: [PATCH 113/177] add errorsink.d, an abstract interface to error messages (dlang/dmd!14906) --- dmd/README.md | 3 +- dmd/cparse.d | 16 +-- dmd/dmodule.d | 7 +- dmd/doc.d | 1 + dmd/dsymbolsem.d | 2 +- dmd/errors.d | 54 ++++++++- dmd/errorsink.d | 121 +++++++++++++++++++++ dmd/expressionsem.d | 2 +- dmd/frontend.h | 6 +- dmd/globals.d | 6 + dmd/globals.h | 2 + dmd/iasmgcc.d | 18 +-- dmd/lexer.d | 87 +++++++++------ dmd/parse.d | 66 +++++------ dmd/statementsem.d | 3 +- dmd/typesem.d | 3 +- tests/dmd/unit/frontend.d | 16 +-- tests/dmd/unit/lexer/diagnostic_reporter.d | 5 +- tests/dmd/unit/lexer/lexer_dmdlib.d | 22 ++-- tests/dmd/unit/lexer/location_offset.d | 37 ++++--- 20 files changed, 351 insertions(+), 126 deletions(-) create mode 100644 dmd/errorsink.d diff --git a/dmd/README.md b/dmd/README.md index 43eb187c735..cecd008e608 100644 --- a/dmd/README.md +++ b/dmd/README.md @@ -38,7 +38,8 @@ Note that these groups have no strict meaning, the category assignments are a bi | [dinifile.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dinifile.d) | Parse settings from .ini file (`sc.ini` / `dmd.conf`) | | [vsoptions.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/vsoptions.d) | Detect the Microsoft Visual Studio toolchain for linking | | [frontend.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/frontend.d) | An interface for using DMD as a library | -| [errors.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/errors.d) | Error reporting functionality | +| [errors.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/errors.d) | Error reporting implementation | +| [errorsink.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/errorsink.d) | Error reporting interface | | [target.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/target.d) | Manage target-specific parameters for cross-compiling (for LDC/GDC) | | [compiler.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/compiler.d) | Describe a back-end compiler and implements compiler-specific actions | diff --git a/dmd/cparse.d b/dmd/cparse.d index 57ca3550309..a18f810372d 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -16,6 +16,7 @@ module dmd.cparse; import core.stdc.stdio; import core.stdc.string; import dmd.astenums; +import dmd.errorsink; import dmd.globals; import dmd.id; import dmd.identifier; @@ -69,9 +70,10 @@ final class CParser(AST) : Parser!AST OutBuffer* defines; extern (D) this(TARGET)(AST.Module _module, const(char)[] input, bool doDocComment, + ErrorSink errorSink, const ref TARGET target, OutBuffer* defines) scope { - super(_module, input, doDocComment); + super(_module, input, doDocComment, errorSink); //printf("CParser.this()\n"); mod = _module; @@ -273,7 +275,7 @@ final class CParser(AST) : Parser!AST auto exp = cparseExpression(); if (token.value == TOK.identifier && exp.op == EXP.identifier) { - error("found `%s` when expecting `;` or `=`, did you mean `%s %s = %s`?", peek(&token).toChars(), exp.toChars(), token.toChars(), peek(peek(&token)).toChars()); + error(token.loc, "found `%s` when expecting `;` or `=`, did you mean `%s %s = %s`?", peek(&token).toChars(), exp.toChars(), token.toChars(), peek(peek(&token)).toChars()); nextToken(); } else @@ -754,7 +756,7 @@ final class CParser(AST) : Parser!AST if (token.postfix) { if (token.postfix != postfix) - error("mismatched string literal postfixes `'%c'` and `'%c'`", postfix, token.postfix); + error(token.loc, "mismatched string literal postfixes `'%c'` and `'%c'`", postfix, token.postfix); postfix = token.postfix; } @@ -1948,7 +1950,7 @@ final class CParser(AST) : Parser!AST case TOK.identifier: if (s) { - error("missing comma or semicolon after declaration of `%s`, found `%s` instead", s.toChars(), token.toChars()); + error(token.loc, "missing comma or semicolon after declaration of `%s`, found `%s` instead", s.toChars(), token.toChars()); goto Lend; } goto default; @@ -2014,7 +2016,7 @@ final class CParser(AST) : Parser!AST importBuiltins = true; // will need __va_list_tag auto plLength = pl.length; if (symbols.length != plLength) - error("%d identifiers does not match %d declarations", cast(int)plLength, cast(int)symbols.length); + error(token.loc, "%d identifiers does not match %d declarations", cast(int)plLength, cast(int)symbols.length); /* Transfer the types and storage classes from symbols[] to pl[] */ @@ -5154,9 +5156,9 @@ final class CParser(AST) : Parser!AST if (n.value == TOK.identifier && n.ident == Id.show) { if (packalign.isDefault()) - warning(startloc, "current pack attribute is default"); + eSink.warning(startloc, "current pack attribute is default"); else - warning(startloc, "current pack attribute is %d", packalign.get()); + eSink.warning(startloc, "current pack attribute is %d", packalign.get()); scan(&n); return closingParen(); } diff --git a/dmd/dmodule.d b/dmd/dmodule.d index bb518fa081d..a5f7cd321da 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -29,6 +29,7 @@ import dmd.dscope; import dmd.dsymbol; import dmd.dsymbolsem; import dmd.errors; +import dmd.errorsink; import dmd.expression; import dmd.expressionsem; import dmd.file_manager; @@ -766,7 +767,7 @@ extern (C++) final class Module : Package { filetype = FileType.c; - scope p = new CParser!AST(this, buf, cast(bool) docfile, target.c, &defines); + scope p = new CParser!AST(this, buf, cast(bool) docfile, global.errorSink, target.c, &defines); p.nextToken(); checkCompiledImport(); members = p.parseModule(); @@ -775,7 +776,7 @@ extern (C++) final class Module : Package } else { - scope p = new Parser!AST(this, buf, cast(bool) docfile); + scope p = new Parser!AST(this, buf, cast(bool) docfile, global.errorSink); p.nextToken(); p.parseModuleDeclaration(); md = p.md; @@ -1382,7 +1383,7 @@ extern (C++) struct ModuleDeclaration * for inclusion in ModuleInfo * Params: * mod = the Module - * aclasses = array to fill in + * aclasses = array to fill in * Returns: array of local classes */ extern (C++) void getLocalClasses(Module mod, ref ClassDeclarations aclasses) diff --git a/dmd/doc.d b/dmd/doc.d index 155406f9919..88e8996ae3a 100644 --- a/dmd/doc.d +++ b/dmd/doc.d @@ -5183,6 +5183,7 @@ private void highlightCode2(Scope* sc, Dsymbols* a, ref OutBuffer buf, size_t of uint errorsave = global.startGagging(); scope Lexer lex = new Lexer(null, cast(char*)buf[].ptr, 0, buf.length - 1, 0, 1, + global.errorSink, global.vendor, global.versionNumber()); OutBuffer res; const(char)* lastp = cast(char*)buf[].ptr; diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 8e491be37fe..6b41bf20d1c 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -1933,7 +1933,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor const len = buf.length; buf.writeByte(0); const str = buf.extractSlice()[0 .. len]; - scope p = new Parser!ASTCodegen(cd.loc, sc._module, str, false); + scope p = new Parser!ASTCodegen(cd.loc, sc._module, str, false, global.errorSink); p.nextToken(); auto d = p.parseDeclDefs(0); diff --git a/dmd/errors.d b/dmd/errors.d index b9a533565d8..05b884c280e 100644 --- a/dmd/errors.d +++ b/dmd/errors.d @@ -15,6 +15,7 @@ import core.stdc.stdarg; import core.stdc.stdio; import core.stdc.stdlib; import core.stdc.string; +import dmd.errorsink; import dmd.globals; import dmd.location; import dmd.common.outbuffer; @@ -24,6 +25,57 @@ import dmd.console; nothrow: +/*************************** + * Error message sink for D compiler. + */ +class ErrorSinkCompiler : ErrorSink +{ + nothrow: + extern (C++): + override: + + void error(const ref Loc loc, const(char)* format, ...) + { + va_list ap; + va_start(ap, format); + verror(loc, format, ap); + va_end(ap); + } + + void errorSupplemental(const ref Loc loc, const(char)* format, ...) + { + va_list ap; + va_start(ap, format); + verrorSupplemental(loc, format, ap); + va_end(ap); + } + + void warning(const ref Loc loc, const(char)* format, ...) + { + va_list ap; + va_start(ap, format); + vwarning(loc, format, ap); + va_end(ap); + } + + void deprecation(const ref Loc loc, const(char)* format, ...) + { + va_list ap; + va_start(ap, format); + vdeprecation(loc, format, ap); + va_end(ap); + } + + void deprecationSupplemental(const ref Loc loc, const(char)* format, ...) + { + va_list ap; + va_start(ap, format); + vdeprecationSupplemental(loc, format, ap); + va_end(ap); + } +} + + /** * Color highlighting to classify messages */ @@ -768,7 +820,7 @@ private void colorHighlightCode(ref OutBuffer buf) ++nested; auto gaggedErrorsSave = global.startGagging(); - scope Lexer lex = new Lexer(null, cast(char*)buf[].ptr, 0, buf.length - 1, 0, 1, global.vendor, global.versionNumber()); + scope Lexer lex = new Lexer(null, cast(char*)buf[].ptr, 0, buf.length - 1, 0, 1, global.errorSink, global.vendor, global.versionNumber()); OutBuffer res; const(char)* lastp = cast(char*)buf[].ptr; //printf("colorHighlightCode('%.*s')\n", cast(int)(buf.length - 1), buf[].ptr); diff --git a/dmd/errorsink.d b/dmd/errorsink.d new file mode 100644 index 00000000000..b519db7e9bc --- /dev/null +++ b/dmd/errorsink.d @@ -0,0 +1,121 @@ +/** + * Provides an abstraction for what to do with error messages. + * + * Copyright: Copyright (C) 2023 by The D Language Foundation, All Rights Reserved + * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) + * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/errorsink.d, _errorsink.d) + * Documentation: https://dlang.org/phobos/dmd_errorsink.html + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/errorsink.d + */ + +module dmd.errorsink; + +import dmd.location; + +/*************************************** + * Where error/warning/deprecation messages go. + */ +abstract class ErrorSink +{ + nothrow: + extern (C++): + + void error(const ref Loc loc, const(char)* format, ...); + + void errorSupplemental(const ref Loc loc, const(char)* format, ...); + + void warning(const ref Loc loc, const(char)* format, ...); + + void deprecation(const ref Loc loc, const(char)* format, ...); + + void deprecationSupplemental(const ref Loc loc, const(char)* format, ...); +} + +/***************************************** + * Just ignores the messages. + */ +class ErrorSinkNull : ErrorSink +{ + nothrow: + extern (C++): + override: + + void error(const ref Loc loc, const(char)* format, ...) { } + + void errorSupplemental(const ref Loc loc, const(char)* format, ...) { } + + void warning(const ref Loc loc, const(char)* format, ...) { } + + void deprecation(const ref Loc loc, const(char)* format, ...) { } + + void deprecationSupplemental(const ref Loc loc, const(char)* format, ...) { } +} + +/***************************************** + * Simplest implementation, just sends messages to stderr. + */ +class ErrorSinkStderr : ErrorSink +{ + import core.stdc.stdio; + import core.stdc.stdarg; + + nothrow: + extern (C++): + override: + + void error(const ref Loc loc, const(char)* format, ...) + { + fputs("Error: ", stderr); + const p = loc.toChars(); + if (*p) + { + fprintf(stderr, "%s: ", p); + //mem.xfree(cast(void*)p); // loc should provide the free() + } + + va_list ap; + va_start(ap, format); + vfprintf(stderr, format, ap); + fputc('\n', stderr); + va_end(ap); + } + + void errorSupplemental(const ref Loc loc, const(char)* format, ...) { } + + void warning(const ref Loc loc, const(char)* format, ...) + { + fputs("Warning: ", stderr); + const p = loc.toChars(); + if (*p) + { + fprintf(stderr, "%s: ", p); + //mem.xfree(cast(void*)p); // loc should provide the free() + } + + va_list ap; + va_start(ap, format); + vfprintf(stderr, format, ap); + fputc('\n', stderr); + va_end(ap); + } + + void deprecation(const ref Loc loc, const(char)* format, ...) + { + fputs("Deprecation: ", stderr); + const p = loc.toChars(); + if (*p) + { + fprintf(stderr, "%s: ", p); + //mem.xfree(cast(void*)p); // loc should provide the free() + } + + va_list ap; + va_start(ap, format); + vfprintf(stderr, format, ap); + fputc('\n', stderr); + va_end(ap); + } + + void deprecationSupplemental(const ref Loc loc, const(char)* format, ...) { } +} diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 14ba676b8a1..c805b06173a 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -6101,7 +6101,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor uint errors = global.errors; const len = buf.length; const str = buf.extractChars()[0 .. len]; - scope p = new Parser!ASTCodegen(exp.loc, sc._module, str, false); + scope p = new Parser!ASTCodegen(exp.loc, sc._module, str, false, global.errorSink); p.nextToken(); //printf("p.loc.linnum = %d\n", p.loc.linnum); diff --git a/dmd/frontend.h b/dmd/frontend.h index 3cf54a2d702..84089f525b6 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -307,6 +307,7 @@ class ArrayInitializer; class ExpInitializer; class CInitializer; class FileManager; +class ErrorSink; class ErrorStatement; class ExpStatement; class ConditionalStatement; @@ -3384,6 +3385,7 @@ struct Global final FileManager* fileManager; enum : int32_t { recursionLimit = 500 }; + ErrorSink* errorSink; FileName(*preprocess)(FileName , const Loc& , bool& , OutBuffer* ); uint32_t startGagging(); bool endGagging(uint32_t oldGagged); @@ -3410,10 +3412,11 @@ struct Global final hasMainFunction(), varSequenceNumber(1u), fileManager(), + errorSink(), preprocess() { } - Global(_d_dynamicArray< const char > inifilename, _d_dynamicArray< const char > copyright = { 73, "Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved" }, _d_dynamicArray< const char > written = { 24, "written by Walter Bright" }, Array* path = nullptr, Array* filePath = nullptr, _d_dynamicArray< const char > vendor = {}, Param params = Param(), uint32_t errors = 0u, uint32_t warnings = 0u, uint32_t gag = 0u, uint32_t gaggedErrors = 0u, uint32_t gaggedWarnings = 0u, void* console = nullptr, Array* versionids = nullptr, Array* debugids = nullptr, bool hasMainFunction = false, uint32_t varSequenceNumber = 1u, FileManager* fileManager = nullptr, FileName(*preprocess)(FileName , const Loc& , bool& , OutBuffer* ) = nullptr) : + Global(_d_dynamicArray< const char > inifilename, _d_dynamicArray< const char > copyright = { 73, "Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved" }, _d_dynamicArray< const char > written = { 24, "written by Walter Bright" }, Array* path = nullptr, Array* filePath = nullptr, _d_dynamicArray< const char > vendor = {}, Param params = Param(), uint32_t errors = 0u, uint32_t warnings = 0u, uint32_t gag = 0u, uint32_t gaggedErrors = 0u, uint32_t gaggedWarnings = 0u, void* console = nullptr, Array* versionids = nullptr, Array* debugids = nullptr, bool hasMainFunction = false, uint32_t varSequenceNumber = 1u, FileManager* fileManager = nullptr, ErrorSink* errorSink = nullptr, FileName(*preprocess)(FileName , const Loc& , bool& , OutBuffer* ) = nullptr) : inifilename(inifilename), copyright(copyright), written(written), @@ -3432,6 +3435,7 @@ struct Global final hasMainFunction(hasMainFunction), varSequenceNumber(varSequenceNumber), fileManager(fileManager), + errorSink(errorSink), preprocess(preprocess) {} }; diff --git a/dmd/globals.d b/dmd/globals.d index 407c68423c5..1919d9ae0ce 100644 --- a/dmd/globals.d +++ b/dmd/globals.d @@ -15,6 +15,8 @@ import core.stdc.stdint; import dmd.root.array; import dmd.root.filename; import dmd.common.outbuffer; +import dmd.errorsink; +import dmd.errors; import dmd.file_manager; import dmd.identifier; import dmd.location; @@ -292,6 +294,8 @@ extern (C++) struct Global enum recursionLimit = 500; /// number of recursive template expansions before abort + ErrorSink errorSink; /// where the error messages go + extern (C++) FileName function(FileName, ref const Loc, out bool, OutBuffer*) preprocess; nothrow: @@ -346,6 +350,8 @@ extern (C++) struct Global extern (C++) void _init() { + global.errorSink = new ErrorSinkCompiler; + this.fileManager = new FileManager(); version (MARS) { diff --git a/dmd/globals.h b/dmd/globals.h index dc637f86c3e..ec8fc32ed0f 100644 --- a/dmd/globals.h +++ b/dmd/globals.h @@ -19,6 +19,7 @@ // Can't include arraytypes.h here, need to declare these directly. template struct Array; +class ErrorSink; class FileManager; struct Loc; @@ -278,6 +279,7 @@ struct Global unsigned varSequenceNumber; FileManager* fileManager; + ErrorSink* errorSink; // where the error messages go FileName (*preprocess)(FileName, const Loc&, bool&, OutBuffer&); diff --git a/dmd/iasmgcc.d b/dmd/iasmgcc.d index baf6b14b97d..f8c88ab536e 100644 --- a/dmd/iasmgcc.d +++ b/dmd/iasmgcc.d @@ -17,6 +17,7 @@ import dmd.arraytypes; import dmd.astcodegen; import dmd.dscope; import dmd.errors; +import dmd.errorsink; import dmd.expression; import dmd.expressionsem; import dmd.identifier; @@ -72,7 +73,7 @@ int parseExtAsmOperands(Parser)(Parser p, GccAsmStatement s) } else { - p.error(s.loc, "expected identifier after `[`"); + p.eSink.error(s.loc, "expected identifier after `[`"); goto Lerror; } // Look for closing `]` @@ -116,7 +117,7 @@ int parseExtAsmOperands(Parser)(Parser p, GccAsmStatement s) break; default: - p.error("expected constant string constraint for operand, not `%s`", + p.eSink.error(p.token.loc, "expected constant string constraint for operand, not `%s`", p.token.toChars()); goto Lerror; } @@ -167,7 +168,7 @@ Expressions *parseExtAsmClobbers(Parser)(Parser p) break; default: - p.error("expected constant string constraint for clobber name, not `%s`", + p.eSink.error(p.token.loc, "expected constant string constraint for clobber name, not `%s`", p.token.toChars()); goto Lerror; } @@ -214,7 +215,7 @@ Identifiers *parseExtAsmGotoLabels(Parser)(Parser p) break; default: - p.error("expected identifier for goto label name, not `%s`", + p.eSink.error(p.token.loc, "expected identifier for goto label name, not `%s`", p.token.toChars()); goto Lerror; } @@ -301,7 +302,7 @@ Ldone: extern (C++) public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc) { //printf("GccAsmStatement.semantic()\n"); - scope p = new Parser!ASTCodegen(sc._module, ";", false); + scope p = new Parser!ASTCodegen(sc._module, ";", false, global.errorSink); // Make a safe copy of the token list before parsing. Token *toklist = null; @@ -384,6 +385,9 @@ unittest { import dmd.mtype : TypeBasic; + if (!global.errorSink) + global.errorSink = new ErrorSinkCompiler; + uint errors = global.startGagging(); scope(exit) global.endGagging(errors); @@ -406,7 +410,7 @@ unittest { const errors = global.errors; scope gas = new GccAsmStatement(Loc.initial, tokens); - scope p = new Parser!ASTCodegen(null, ";", false); + scope p = new Parser!ASTCodegen(null, ";", false, global.errorSink); p.token = *tokens; p.parseGccAsm(gas); return global.errors - errors; @@ -416,7 +420,7 @@ unittest static void parseAsm(string input, bool expectError) { // Generate tokens from input test. - scope p = new Parser!ASTCodegen(null, input, false); + scope p = new Parser!ASTCodegen(null, input, false, global.errorSink); p.nextToken(); Token* toklist = null; diff --git a/dmd/lexer.d b/dmd/lexer.d index 81830d7307b..4dc4a39929a 100644 --- a/dmd/lexer.d +++ b/dmd/lexer.d @@ -23,6 +23,7 @@ import core.stdc.time; import dmd.entity; import dmd.errors; +import dmd.errorsink; import dmd.globals; import dmd.id; import dmd.identifier; @@ -69,6 +70,8 @@ class Lexer ubyte long_doublesize; /// size of C long double, 8 or D real.sizeof ubyte wchar_tsize; /// size of C wchar_t, 2 or 4 + ErrorSink eSink; /// send error messages through this interface + private { const(char)* base; // pointer to start of buffer @@ -103,11 +106,13 @@ class Lexer * endoffset = the last offset to read into base[] * doDocComment = handle documentation comments * commentToken = comments become TOK.comment's + * errorSink = where error messages go, must not be null * vendor = name of the vendor * versionNumber = version of the caller */ this(const(char)* filename, const(char)* base, size_t begoffset, size_t endoffset, bool doDocComment, bool commentToken, + ErrorSink errorSink, const(char)[] vendor = "DLF", uint versionNumber = 1) pure scope { scanloc = Loc(filename, 1, 1); @@ -123,6 +128,8 @@ class Lexer this.tokenizeNewlines = false; this.inTokenStringConstant = 0; this.lastDocLine = 0; + this.eSink = errorSink; + assert(errorSink); this.versionNumber = versionNumber; this.vendor = vendor; //initKeywords(); @@ -163,16 +170,18 @@ class Lexer * Alternative entry point for DMDLIB, adds `whitespaceToken` */ this(const(char)* filename, const(char)* base, size_t begoffset, size_t endoffset, - bool doDocComment, bool commentToken, bool whitespaceToken) + bool doDocComment, bool commentToken, bool whitespaceToken, + ErrorSink errorSink + ) { - this(filename, base, begoffset, endoffset, doDocComment, commentToken); + this(filename, base, begoffset, endoffset, doDocComment, commentToken, errorSink); this.whitespaceToken = whitespaceToken; } /****************** * Used for unittests for a mock Lexer */ - this() scope { } + this(ErrorSink errorSink) scope { assert(errorSink); this.eSink = errorSink; } /************************************** * Reset lexer to lex #define's @@ -1616,7 +1625,7 @@ class Lexer else if (isspace(delimright)) error("delimited string must end in `\"`"); else - error("delimited string must end in `%c\"`", delimright); + error(token.loc, "delimited string must end in `%c\"`", delimright); result.setString(stringbuffer); stringPostfix(result); } @@ -1909,10 +1918,10 @@ class Lexer if (idx < n && !msg) msg = utf_decodeChar(str, idx, d2); if (msg) - error(loc, "%s", msg); + error(loc, "%.*s", cast(int)msg.length, msg.ptr); else if (idx < n) error(loc, "max number of chars in 16 bit character literal is 2, had %d", - (n + 1) >> 1); + cast(int)((n + 1) >> 1)); else if (d1 > 0x1_0000) error(loc, "%d does not fit in 16 bits", d1); else if (d2 > 0x1_0000) @@ -1927,10 +1936,10 @@ class Lexer size_t idx; auto msg = utf_decodeChar(str, idx, d); if (msg) - error(loc, "%s", msg); + error(loc, "%.*s", cast(int)msg.length, msg.ptr); else if (idx < n) error(loc, "max number of chars in 32 bit character literal is 1, had %d", - (n + 3) >> 2); + cast(int)((n + 3) >> 2)); u = d; break; @@ -2137,7 +2146,7 @@ class Lexer Ldone: if (errorDigit) { - error("%s digit expected, not `%c`", base == 2 ? "binary".ptr : + error(token.loc, "%s digit expected, not `%c`", base == 2 ? "binary".ptr : base == 8 ? "octal".ptr : "decimal".ptr, errorDigit); err = true; @@ -2149,7 +2158,7 @@ class Lexer } if ((base == 2 && !anyBinaryDigitsNoSingleUS) || (base == 16 && !anyHexDigitsNoSingleUS)) - error("`%.*s` isn't a valid integer literal, use `%.*s0` instead", cast(int)(p - start), start, 2, start); + error(token.loc, "`%.*s` isn't a valid integer literal, use `%.*s0` instead", cast(int)(p - start), start, 2, start); t.unsvalue = n; @@ -2202,7 +2211,7 @@ class Lexer // can't translate invalid octal value, just show a generic message error("octal literals larger than 7 are no longer supported"); else - error("octal literals `0%llo%.*s` are no longer supported, use `std.conv.octal!\"%llo%.*s\"` instead", + error(token.loc, "octal literals `0%llo%.*s` are no longer supported, use `std.conv.octal!\"%llo%.*s\"` instead", n, cast(int)(p - psuffix), psuffix, n, cast(int)(p - psuffix), psuffix); } TOK result; @@ -2619,7 +2628,7 @@ class Lexer TOK.float80Literal: "`real` for the current target".ptr][result]; error(scanloc, "number `%s%s` is not representable as a %s", sbufptr, suffix, type); const char* extra = result == TOK.float64Literal ? "`real` literals can be written using the `L` suffix. " : ""; - errorSupplemental(scanloc, "%shttps://dlang.org/spec/lex.html#floatliteral", extra); + eSink.errorSupplemental(scanloc, "%shttps://dlang.org/spec/lex.html#floatliteral", extra); } debug { @@ -2647,28 +2656,24 @@ class Lexer return scanloc; } - final void error(const(char)* format, ...) + void error(T...)(const(char)* format, T args) + { + eSink.error(token.loc, format, args); + } + + void error(T...)(const ref Loc loc, const(char)* format, T args) { - va_list args; - va_start(args, format); - .verror(token.loc, format, args); - va_end(args); + eSink.error(loc, format, args); } - final void error(const ref Loc loc, const(char)* format, ...) + final void deprecation(const(char)* format) { - va_list args; - va_start(args, format); - .verror(loc, format, args); - va_end(args); + eSink.deprecation(token.loc, format); } - final void deprecation(const(char)* format, ...) + final void deprecationSupplemental(const(char)* format) { - va_list args; - va_start(args, format); - .vdeprecation(token.loc, format, args); - va_end(args); + eSink.deprecationSupplemental(token.loc, format); } /*************************************** @@ -2692,7 +2697,7 @@ class Lexer else { const locx = loc(); - warning(locx, "C preprocessor directive `#%s` is not supported", n.ident.toChars()); + eSink.warning(locx, "C preprocessor directive `#%s` is not supported", n.ident.toChars()); } } else if (n.value == TOK.if_) @@ -2853,7 +2858,7 @@ class Lexer auto result = decodeUTFpure(msg); if (msg) - error("%.*s", cast(int)msg.length, msg.ptr); + error(token.loc, "%.*s", cast(int)msg.length, msg.ptr); return result; } @@ -3217,6 +3222,7 @@ private bool c_isalnum(const int c) pure @nogc @safe unittest { + fprintf(stderr, "Lexer.unittest %d\n", __LINE__); import dmd.console; nothrow bool assertDiagnosticHandler(const ref Loc loc, Color headerColor, const(char)* header, const(char)* format, va_list ap, const(char)* p1, const(char)* p2) @@ -3225,11 +3231,14 @@ unittest } diagnosticHandler = &assertDiagnosticHandler; + if (!global.errorSink) + global.errorSink = new ErrorSinkCompiler; + static void test(T)(string sequence, T expected, bool Ccompile = false) { auto p = cast(const(char)*)sequence.ptr; dchar c2; - Lexer lexer = new Lexer(); + Lexer lexer = new Lexer(global.errorSink); assert(expected == lexer.escapeSequence(Loc.initial, p, Ccompile, c2)); assert(p == sequence.ptr + sequence.length); } @@ -3272,6 +3281,7 @@ unittest unittest { + fprintf(stderr, "Lexer.unittest %d\n", __LINE__); import dmd.console; string expected; bool gotError; @@ -3290,13 +3300,16 @@ unittest diagnosticHandler = &expectDiagnosticHandler; + if (!global.errorSink) + global.errorSink = new ErrorSinkCompiler; + void test(string sequence, string expectedError, dchar expectedReturnValue, uint expectedScanLength, bool Ccompile = false) { uint errors = global.errors; gotError = false; expected = expectedError; auto p = cast(const(char)*)sequence.ptr; - Lexer lexer = new Lexer(); + Lexer lexer = new Lexer(global.errorSink); dchar c2; auto actualReturnValue = lexer.escapeSequence(Loc.initial, p, Ccompile, c2); assert(gotError); @@ -3344,11 +3357,13 @@ unittest unittest { - //printf("lexer.unittest\n"); + fprintf(stderr, "Lexer.unittest %d\n", __LINE__); /* Not much here, just trying things out. */ string text = "int"; // We rely on the implicit null-terminator - scope Lexer lex1 = new Lexer(null, text.ptr, 0, text.length, 0, 0); + if (!global.errorSink) + global.errorSink = new ErrorSinkCompiler; + scope Lexer lex1 = new Lexer(null, text.ptr, 0, text.length, false, false, global.errorSink); TOK tok; tok = lex1.nextToken(); //printf("tok == %s, %d, %d\n", Token::toChars(tok), tok, TOK.int32); @@ -3363,6 +3378,10 @@ unittest unittest { + fprintf(stderr, "Lexer.unittest %d\n", __LINE__); + if (!global.errorSink) + global.errorSink = new ErrorSinkCompiler; + // We don't want to see Lexer error output during these tests. uint errors = global.startGagging(); scope(exit) global.endGagging(errors); @@ -3383,7 +3402,7 @@ unittest foreach (testcase; testcases) { - scope Lexer lex2 = new Lexer(null, testcase.ptr, 0, testcase.length-1, 0, 0); + scope Lexer lex2 = new Lexer(null, testcase.ptr, 0, testcase.length-1, false, false, global.errorSink); TOK tok = lex2.nextToken(); size_t iterations = 1; while ((tok != TOK.endOfFile) && (iterations++ < testcase.length)) diff --git a/dmd/parse.d b/dmd/parse.d index ec219af6cb4..36a76f50da2 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -16,6 +16,7 @@ module dmd.parse; import core.stdc.stdio; import core.stdc.string; import dmd.astenums; +import dmd.errorsink; import dmd.globals; import dmd.id; import dmd.identifier; @@ -51,9 +52,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer * Input: * loc location in source file of mixin */ - extern (D) this(const ref Loc loc, AST.Module _module, const(char)[] input, bool doDocComment) scope + extern (D) this(const ref Loc loc, AST.Module _module, const(char)[] input, bool doDocComment, + ErrorSink errorSink) scope { super(_module ? _module.srcfile.toChars() : null, input.ptr, 0, input.length, doDocComment, false, + errorSink, global.vendor, global.versionNumber()); //printf("Parser::Parser()\n"); @@ -75,9 +78,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer //nextToken(); // start up the scanner } - extern (D) this(AST.Module _module, const(char)[] input, bool doDocComment) scope + extern (D) this(AST.Module _module, const(char)[] input, bool doDocComment, ErrorSink errorSink) scope { super(_module ? _module.srcfile.toChars() : null, input.ptr, 0, input.length, doDocComment, false, + errorSink, global.vendor, global.versionNumber()); //printf("Parser::Parser()\n"); @@ -168,13 +172,13 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (token.value == TOK.rightCurly) { - error(token.loc, "unmatched closing brace"); + error("unmatched closing brace"); return errorReturn(); } if (token.value != TOK.endOfFile) { - error(token.loc, "unrecognized declaration"); + error("unrecognized declaration"); return errorReturn(); } return decldefs; @@ -287,7 +291,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer check(TOK.rightParenthesis); if (msg) { - error("conflicting storage class `deprecated(%s)` and `deprecated(%s)`", msg.toChars(), e.toChars()); + error(token.loc, "conflicting storage class `deprecated(%s)` and `deprecated(%s)`", msg.toChars(), e.toChars()); } msg = e; return true; @@ -800,7 +804,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer { if (pAttrs.link != res.link) { - error("conflicting linkage `extern (%s)` and `extern (%s)`", AST.linkageToChars(pAttrs.link), AST.linkageToChars(res.link)); + error(token.loc, "conflicting linkage `extern (%s)` and `extern (%s)`", AST.linkageToChars(pAttrs.link), AST.linkageToChars(res.link)); } else if (res.idents || res.identExps || res.cppmangle != CPPMANGLE.def) { @@ -888,7 +892,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (pAttrs.visibility.kind != AST.Visibility.Kind.undefined) { if (pAttrs.visibility.kind != prot) - error("conflicting visibility attribute `%s` and `%s`", AST.visibilityToChars(pAttrs.visibility.kind), AST.visibilityToChars(prot)); + error(token.loc, "conflicting visibility attribute `%s` and `%s`", AST.visibilityToChars(pAttrs.visibility.kind), AST.visibilityToChars(prot)); else error("redundant visibility attribute `%s`", AST.visibilityToChars(prot)); } @@ -1241,7 +1245,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer { // Windows `printf` does not support `%1$s` const(char*) stc_str = (orig & STC.scope_) ? "scope".ptr : "ref".ptr; - error("attribute `in` cannot be added after `%s`: remove `%s`", + error(token.loc, "attribute `in` cannot be added after `%s`: remove `%s`", stc_str, stc_str); } else @@ -2174,7 +2178,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer nextToken(); if (token.value != TOK.identifier) { - error("`%s` expected as dot-separated identifiers, got `%s`", entity, token.toChars()); + error(token.loc, "`%s` expected as dot-separated identifiers, got `%s`", entity, token.toChars()); return qualified; } @@ -3237,7 +3241,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (token.value != TOK.rightCurly) { /* { */ - error("`}` expected following members in `%s` declaration at %s", + error(token.loc, "`}` expected following members in `%s` declaration at %s", Token.toChars(tok), loc.toChars()); } nextToken(); @@ -3250,7 +3254,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } else { - error("{ } expected following `%s` declaration", Token.toChars(tok)); + error(token.loc, "{ } expected following `%s` declaration", Token.toChars(tok)); } AST.AggregateDeclaration a; @@ -3637,7 +3641,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer loc = token.loc; nextToken(); if (token.value != TOK.leftParenthesis) - error("found `%s` when expecting `%s` following `mixin`", token.toChars(), Token.toChars(TOK.leftParenthesis)); + error(token.loc, "found `%s` when expecting `%s` following `mixin`", token.toChars(), Token.toChars(TOK.leftParenthesis)); auto exps = parseArguments(); t = new AST.TypeMixin(loc, exps); break; @@ -3701,7 +3705,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer default: error("basic type expected, not `%s`", token.toChars()); if (token.value == TOK.else_) - errorSupplemental(token.loc, "There's no `static else`, use `else` instead."); + eSink.errorSupplemental(token.loc, "There's no `static else`, use `else` instead."); t = AST.Type.terror; break; } @@ -4449,7 +4453,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (!tfirst) tfirst = t; else if (t != tfirst) - error("multiple declarations must have the same type, not `%s` and `%s`", tfirst.toChars(), t.toChars()); + error(token.loc, "multiple declarations must have the same type, not `%s` and `%s`", tfirst.toChars(), t.toChars()); if (token.value == TOK.colon && !ident && t.ty != Tfunction) { @@ -4486,7 +4490,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (_init) { if (isThis) - error("cannot use syntax `alias this = %s`, use `alias %s this` instead", _init.toChars(), _init.toChars()); + error(token.loc, "cannot use syntax `alias this = %s`, use `alias %s this` instead", _init.toChars(), _init.toChars()); else error("alias cannot have initializer"); } @@ -4664,12 +4668,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer default: if (loc.linnum != token.loc.linnum) { - error("semicolon needed to end declaration of `%s`, instead of `%s`", s.toChars(), token.toChars()); - errorSupplemental(loc, "`%s` declared here", s.toChars()); + error(token.loc, "semicolon needed to end declaration of `%s`, instead of `%s`", s.toChars(), token.toChars()); + eSink.errorSupplemental(loc, "`%s` declared here", s.toChars()); } else { - error("semicolon needed to end declaration of `%s` instead of `%s`", s.toChars(), token.toChars()); + error(token.loc, "semicolon needed to end declaration of `%s` instead of `%s`", s.toChars(), token.toChars()); } break; } @@ -4687,7 +4691,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer // A common mistake is to use a reserved keyword as an identifier, e.g. `in` or `out` if (token.isKeyword) { - errorSupplemental(token.loc, "`%s` is a keyword, perhaps append `_` to make it an identifier", token.toChars()); + eSink.errorSupplemental(token.loc, "`%s` is a keyword, perhaps append `_` to make it an identifier", token.toChars()); nextToken(); } } @@ -4907,7 +4911,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer AST.stcToBuffer(&buf, remStc); // @@@DEPRECATED_2.103@@@ // Deprecated in 2020-07, can be made an error in 2.103 - deprecation("storage class `%s` has no effect in type aliases", buf.peekChars()); + eSink.deprecation(token.loc, "storage class `%s` has no effect in type aliases", buf.peekChars()); } } @@ -5099,7 +5103,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (token.value == TOK.leftCurly) { deprecation("using `(args) => { ... }` to create a delegate that returns a delegate is error-prone."); - deprecationSupplemental(token.loc, "Use `(args) { ... }` for a multi-statement function literal or use `(args) => () { }` if you intended for the lambda to return a delegate."); + deprecationSupplemental("Use `(args) { ... }` for a multi-statement function literal or use `(args) => () { }` if you intended for the lambda to return a delegate."); } const returnloc = token.loc; AST.Expression ae = parseAssignExp(); @@ -5324,7 +5328,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer { if (token.value != TOK.else_ && token.value != TOK.catch_ && token.value != TOK.finally_ && lookingForElse.linnum != 0) { - warning(elseloc, "else is dangling, add { } after condition at %s", lookingForElse.toChars()); + eSink.warning(elseloc, "else is dangling, add { } after condition at %s", lookingForElse.toChars()); } } @@ -5367,7 +5371,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer nextToken(); } if (format) - error(format.ptr, start.ptr, param ? "declaration".ptr : condition.toChars()); + error(token.loc, format.ptr, start.ptr, param ? "declaration".ptr : condition.toChars()); } /***************************************** @@ -5502,7 +5506,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer nextToken(); if (lastai && parameters.length >= 2) { - errorSupplemental(loc, "perhaps the `;` goes before `%s`", lastai.toChars()); + eSink.errorSupplemental(loc, "perhaps the `;` goes before `%s`", lastai.toChars()); } return null; } @@ -5775,7 +5779,7 @@ LagainStc: */ if (token.value == TOK.identifier && exp.op == EXP.identifier) { - error("found `%s` when expecting `;` or `=`, did you mean `%s %s = %s`?", peek(&token).toChars(), exp.toChars(), token.toChars(), peek(peek(&token)).toChars()); + error(token.loc, "found `%s` when expecting `;` or `=`, did you mean `%s %s = %s`?", peek(&token).toChars(), exp.toChars(), token.toChars(), peek(peek(&token)).toChars()); nextToken(); } else @@ -6478,7 +6482,7 @@ LagainStc: if (token.value != TOK.leftParenthesis) { deprecation("`catch` statement without an exception specification is deprecated"); - deprecationSupplemental(token.loc, "use `catch(Throwable)` for old behavior"); + deprecationSupplemental("use `catch(Throwable)` for old behavior"); t = null; id = null; } @@ -7037,7 +7041,7 @@ LagainStc: void check(TOK value, const(char)* string) { if (token.value != value) - error("found `%s` when expecting `%s` following %s", token.toChars(), Token.toChars(value), string); + error(token.loc, "found `%s` when expecting `%s` following %s", token.toChars(), Token.toChars(value), string); nextToken(); } @@ -8103,12 +8107,12 @@ LagainStc: if (token.postfix) { if (token.postfix != postfix) - error("mismatched string literal postfixes `'%c'` and `'%c'`", postfix, token.postfix); + error(token.loc, "mismatched string literal postfixes `'%c'` and `'%c'`", postfix, token.postfix); postfix = token.postfix; } error("implicit string concatenation is error-prone and disallowed in D"); - errorSupplemental(token.loc, "Use the explicit syntax instead " ~ + eSink.errorSupplemental(token.loc, "Use the explicit syntax instead " ~ "(concatenating literals is `@nogc`): %s ~ %s", prev.toChars(), token.toChars()); @@ -8239,7 +8243,7 @@ LagainStc: check(TOK.dot); if (token.value != TOK.identifier) { - error("found `%s` when expecting identifier following `%s`.", token.toChars(), t.toChars()); + error(token.loc, "found `%s` when expecting identifier following `%s`.", token.toChars(), t.toChars()); goto Lerr; } e = new AST.DotIdExp(loc, new AST.TypeExp(loc, t), token.ident); @@ -8384,7 +8388,7 @@ LagainStc: // https://dlang.org/spec/expression.html#mixin_expressions nextToken(); if (token.value != TOK.leftParenthesis) - error("found `%s` when expecting `%s` following `mixin`", token.toChars(), Token.toChars(TOK.leftParenthesis)); + error(token.loc, "found `%s` when expecting `%s` following `mixin`", token.toChars(), Token.toChars(TOK.leftParenthesis)); auto exps = parseArguments(); e = new AST.MixinExp(loc, exps); break; diff --git a/dmd/statementsem.d b/dmd/statementsem.d index ebf7bd1484f..c80f08d4f21 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -39,6 +39,7 @@ import dmd.dsymbol; import dmd.dsymbolsem; import dmd.dtemplate; import dmd.errors; +import dmd.errorsink; import dmd.escape; import dmd.expression; import dmd.expressionsem; @@ -4732,7 +4733,7 @@ private Statements* flatten(Statement statement, Scope* sc) const len = buf.length; buf.writeByte(0); const str = buf.extractSlice()[0 .. len]; - scope p = new Parser!ASTCodegen(cs.loc, sc._module, str, false); + scope p = new Parser!ASTCodegen(cs.loc, sc._module, str, false, global.errorSink); p.nextToken(); auto a = new Statements(); diff --git a/dmd/typesem.d b/dmd/typesem.d index ac60596506b..84561ac467a 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -35,6 +35,7 @@ import dmd.dsymbol; import dmd.dsymbolsem; import dmd.dtemplate; import dmd.errors; +import dmd.errorsink; import dmd.expression; import dmd.expressionsem; import dmd.func; @@ -4917,7 +4918,7 @@ RootObject compileTypeMixin(TypeMixin tm, Loc loc, Scope* sc) const len = buf.length; buf.writeByte(0); const str = buf.extractSlice()[0 .. len]; - scope p = new Parser!ASTCodegen(loc, sc._module, str, false); + scope p = new Parser!ASTCodegen(loc, sc._module, str, false, global.errorSink); p.nextToken(); //printf("p.loc.linnum = %d\n", p.loc.linnum); diff --git a/tests/dmd/unit/frontend.d b/tests/dmd/unit/frontend.d index fd3556d6327..59275132709 100644 --- a/tests/dmd/unit/frontend.d +++ b/tests/dmd/unit/frontend.d @@ -56,7 +56,7 @@ unittest initDMD(); defaultImportPaths.each!addImport; - auto t = parseModule!AST("test.d", q{ + auto t = parseModule!AST("frontendcustomASTfamily.d", q{ interface Foo {} }); @@ -174,7 +174,7 @@ unittest initDMD(); defaultImportPaths.each!addImport; - auto t = parseModule("test.d", q{ + auto t = parseModule("frontendcontractchecking.d", q{ int foo(int a) in(a == 3) out(result; result == 0) @@ -219,7 +219,7 @@ unittest initDMD(null, null, ["Foo"]); defaultImportPaths.each!addImport; - auto t = parseModule("test.d", q{ + auto t = parseModule("frontendversionidentifiers.d", q{ version (Foo) enum a = 1; else @@ -263,7 +263,7 @@ unittest initDMD(&diagnosticHandler); defaultImportPaths.each!addImport; - parseModule("test.d", q{ + parseModule("frontendcustomdiagnostichandling.d", q{ void foo(){ auto temp == 7.8; foreach(i; 0..5){ @@ -287,7 +287,7 @@ unittest defaultImportPaths.each!addImport; addStringImport(__FILE_FULL_PATH__.dirName.buildPath("support", "data")); - auto t = parseModule("test.d", q{ + auto t = parseModule("frontendaddStringImport.d", q{ enum a = import("foo.txt"); }); @@ -310,7 +310,7 @@ unittest initDMD(); defaultImportPaths.each!addImport; - auto t = parseModule("test.d", q{ + auto t = parseModule("frontendfloatingpoint.d", q{ static assert((2.0i).re == 0); }); @@ -333,7 +333,7 @@ unittest initDMD(); defaultImportPaths.each!addImport; - auto t = parseModule("test.d", q{ + auto t = parseModule("frontendinlineassembly.d", q{ void foo() { asm @@ -380,7 +380,7 @@ unittest initDMD(&diagnosticHandler); defaultImportPaths.each!addImport; - auto t = parseModule("test.dd", q{Ddoc}); + auto t = parseModule("frontendddoc.dd", q{Ddoc}); assert(!t.diagnostics.hasErrors); assert(!t.diagnostics.hasWarnings); diff --git a/tests/dmd/unit/lexer/diagnostic_reporter.d b/tests/dmd/unit/lexer/diagnostic_reporter.d index 314c7a80f34..030ce6c6eca 100644 --- a/tests/dmd/unit/lexer/diagnostic_reporter.d +++ b/tests/dmd/unit/lexer/diagnostic_reporter.d @@ -6,6 +6,7 @@ import core.stdc.stdarg; import dmd.globals : global, DiagnosticReporting; import dmd.location; +import dmd.errors; import support : afterEach, NoopDiagnosticReporter; @@ -61,7 +62,9 @@ private void lexUntilEndOfFile(string code) import dmd.lexer : Lexer; import dmd.tokens : TOK; - scope lexer = new Lexer("test", code.ptr, 0, code.length, 0, 0); + if (!global.errorSink) + global.errorSink = new ErrorSinkCompiler; + scope lexer = new Lexer("test", code.ptr, 0, code.length, 0, 0, global.errorSink); lexer.nextToken; while (lexer.nextToken != TOK.endOfFile) {} diff --git a/tests/dmd/unit/lexer/lexer_dmdlib.d b/tests/dmd/unit/lexer/lexer_dmdlib.d index 589abce0e45..561fd1d1988 100644 --- a/tests/dmd/unit/lexer/lexer_dmdlib.d +++ b/tests/dmd/unit/lexer/lexer_dmdlib.d @@ -2,6 +2,7 @@ module lexer.lexer_dmdlib; import dmd.lexer : Lexer; import dmd.tokens : TOK; +import dmd.errorsink; unittest { @@ -16,7 +17,7 @@ unittest TOK.rightCurly, ]; - Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, false, false); + Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, false, false, new ErrorSinkStderr); TOK[] result; while (lexer.nextToken != TOK.endOfFile) @@ -39,7 +40,7 @@ unittest TOK.comment, ]; - Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true, false); + Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true, false, new ErrorSinkStderr); TOK[] result; while (lexer.nextToken != TOK.endOfFile) @@ -65,7 +66,7 @@ unittest TOK.comment, ]; - Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true, true); + Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true, true, new ErrorSinkStderr); TOK[] result; while (lexer.nextToken != TOK.endOfFile) @@ -92,7 +93,7 @@ unittest TOK.whitespace, ]; - Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true, true); + Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true, true, new ErrorSinkStderr); TOK[] result; while (lexer.nextToken != TOK.endOfFile) @@ -136,7 +137,7 @@ unittest TOK.whitespace, ]; - Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true, true); + Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true, true, new ErrorSinkStderr); TOK[] result; while (lexer.nextToken != TOK.endOfFile) @@ -171,7 +172,7 @@ unittest TOK.whitespace, ]; - Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true, true); + Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true, true, new ErrorSinkStderr); TOK[] result; while (lexer.nextToken != TOK.endOfFile) @@ -193,7 +194,7 @@ unittest TOK.rightCurly, ]; - Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, false); + Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, false, new ErrorSinkStderr); lexer.nextToken; TOK[] result; @@ -214,7 +215,7 @@ unittest TOK.comment, ]; - Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true); + Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true, new ErrorSinkStderr); lexer.nextToken; TOK[] result; @@ -240,7 +241,7 @@ unittest TOK.reserved, ]; - Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, false); + Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, false, new ErrorSinkStderr); TOK[] result; @@ -265,6 +266,7 @@ unittest import dmd.location; import dmd.common.outbuffer; import dmd.console : Color; + import dmd.errors; const(char)[][2][] diagnosticMessages; nothrow bool diagnosticHandler(const ref Loc loc, Color headerColor, const(char)* header, @@ -288,7 +290,7 @@ unittest foreach (codeNum, code; codes) { auto fileName = text("file", codeNum, '\0'); - Lexer lexer = new Lexer(fileName.ptr, code.ptr, 0, code.length, false, false); + Lexer lexer = new Lexer(fileName.ptr, code.ptr, 0, code.length, false, false, new ErrorSinkCompiler); // Generate the errors foreach(unused; lexer){} } diff --git a/tests/dmd/unit/lexer/location_offset.d b/tests/dmd/unit/lexer/location_offset.d index 9ba3c51752b..c52de839dbe 100644 --- a/tests/dmd/unit/lexer/location_offset.d +++ b/tests/dmd/unit/lexer/location_offset.d @@ -2,6 +2,7 @@ module lexer.location_offset; import dmd.lexer : Lexer; import dmd.tokens : TOK; +import dmd.errorsink; import support : afterEach; @@ -16,7 +17,7 @@ unittest { enum code = "token"; - scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0); + scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0, new ErrorSinkStderr); lexer.nextToken; @@ -28,7 +29,7 @@ unittest { enum code = "ignored_token token"; - scope lexer = new Lexer("test.d", code.ptr, 13, code.length - 14, 0, 0); + scope lexer = new Lexer("test.d", code.ptr, 13, code.length - 14, 0, 0, new ErrorSinkStderr); lexer.nextToken; @@ -40,7 +41,7 @@ unittest { enum code = "token1 token2 3"; - scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0); + scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0, new ErrorSinkStderr); lexer.nextToken; lexer.nextToken; @@ -54,7 +55,7 @@ unittest { enum code = "token"; - scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0); + scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0, new ErrorSinkStderr); lexer.nextToken; lexer.nextToken; @@ -67,7 +68,7 @@ unittest { enum code = "/* comment */"; - scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, true); + scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, true, new ErrorSinkStderr); lexer.nextToken; @@ -80,7 +81,7 @@ unittest { enum code = "// comment"; - scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, true); + scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, true, new ErrorSinkStderr); lexer.nextToken; @@ -93,7 +94,7 @@ unittest { enum code = "/+ comment +/"; - scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, true); + scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, true, new ErrorSinkStderr); lexer.nextToken; @@ -106,7 +107,7 @@ unittest { enum code = "/* comment */ token"; - scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0); + scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0, new ErrorSinkStderr); lexer.nextToken; @@ -118,7 +119,7 @@ unittest { enum code = "// comment\ntoken"; - scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0); + scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0, new ErrorSinkStderr); lexer.nextToken; @@ -130,7 +131,7 @@ unittest { enum code = "/+ comment +/ token"; - scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0); + scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0, new ErrorSinkStderr); lexer.nextToken; @@ -142,7 +143,7 @@ unittest { enum code = "line\ntoken"; - scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0); + scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0, new ErrorSinkStderr); lexer.nextToken; lexer.nextToken; @@ -155,7 +156,7 @@ unittest { enum code = "line\r\ntoken"; - scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0); + scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0, new ErrorSinkStderr); lexer.nextToken; lexer.nextToken; @@ -168,7 +169,7 @@ unittest { enum code = "line\rtoken"; - scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0); + scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0, new ErrorSinkStderr); lexer.nextToken; lexer.nextToken; @@ -181,7 +182,7 @@ unittest { enum code = "'🍺'"; - scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0); + scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0, new ErrorSinkStderr); lexer.nextToken; @@ -193,7 +194,7 @@ unittest { enum code = `"🍺🍺"`; - scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0); + scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0, new ErrorSinkStderr); lexer.nextToken; @@ -205,7 +206,7 @@ unittest { enum code = "'🍺' token"; - scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0); + scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0, new ErrorSinkStderr); lexer.nextToken; lexer.nextToken; @@ -218,7 +219,7 @@ unittest { enum code = `"🍺🍺" token`; - scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0); + scope lexer = new Lexer("test.d", code.ptr, 0, code.length, 0, 0, new ErrorSinkStderr); lexer.nextToken; lexer.nextToken; @@ -557,7 +558,7 @@ static foreach (tok; __traits(allMembers, TOK)) { const newCode = "first_token " ~ tests[tok].code; - scope lexer = new Lexer("test.d", newCode.ptr, 0, newCode.length, 0, 0); + scope lexer = new Lexer("test.d", newCode.ptr, 0, newCode.length, 0, 0, new ErrorSinkStderr); lexer.nextToken; lexer.nextToken; From ee13bcb9b8b9e8b3d179b31099ec7cfb0e1d2b53 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sun, 26 Feb 2023 23:33:42 -0800 Subject: [PATCH 114/177] recognize if(__ctfe) blocks (dlang/dmd!14913) --- dmd/dscope.d | 3 ++- dmd/frontend.h | 3 +++ dmd/nogc.d | 3 +++ dmd/statement.d | 18 ++++++++++++++ dmd/statement.h | 5 ++-- dmd/statementsem.d | 14 ++++++++++- tests/dmd/fail_compilation/ctfeblock.d | 33 +++++++++++++++++++++++++ tests/dmd/runnable/test21492.d | 34 -------------------------- 8 files changed, 75 insertions(+), 38 deletions(-) create mode 100644 tests/dmd/fail_compilation/ctfeblock.d delete mode 100644 tests/dmd/runnable/test21492.d diff --git a/dmd/dscope.d b/dmd/dscope.d index 73b09d270dc..ab422fd0cf6 100644 --- a/dmd/dscope.d +++ b/dmd/dscope.d @@ -64,13 +64,14 @@ enum SCOPE free = 0x8000, /// is on free list fullinst = 0x10000, /// fully instantiate templates + ctfeBlock = 0x20000, /// inside a `if (__ctfe)` block } /// Flags that are carried along with a scope push() private enum PersistentFlags = SCOPE.contract | SCOPE.debug_ | SCOPE.ctfe | SCOPE.compile | SCOPE.constraint | SCOPE.noaccesscheck | SCOPE.ignoresymbolvisibility | - SCOPE.Cfile; + SCOPE.Cfile | SCOPE.ctfeBlock; extern (C++) struct Scope { diff --git a/dmd/frontend.h b/dmd/frontend.h index 84089f525b6..5da2e4bade8 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -4410,6 +4410,7 @@ class GotoStatement final : public Statement TryFinallyStatement* tf; ScopeGuardStatement* os; VarDeclaration* lastVar; + bool inCtfeBlock; GotoStatement* syntaxCopy() override; void accept(Visitor* v) override; }; @@ -4425,6 +4426,7 @@ class IfStatement final : public Statement Loc endloc; IfStatement* syntaxCopy() override; void accept(Visitor* v) override; + bool isIfCtfeBlock(); }; class ImportStatement final : public Statement @@ -4470,6 +4472,7 @@ class LabelStatement final : public Statement Statement* gotoTarget; void* extra; bool breaks; + bool inCtfeBlock; LabelStatement* syntaxCopy() override; void accept(Visitor* v) override; }; diff --git a/dmd/nogc.d b/dmd/nogc.d index 197d659f4a4..201f168527c 100644 --- a/dmd/nogc.d +++ b/dmd/nogc.d @@ -212,6 +212,9 @@ public: Expression checkGC(Scope* sc, Expression e) { + if (sc.flags & SCOPE.ctfeBlock) // ignore GC in ctfe blocks + return e; + /* If betterC, allow GC to happen in non-CTFE code. * Just don't generate code for it. * Detect non-CTFE use of the GC in betterC code. diff --git a/dmd/statement.d b/dmd/statement.d index 96c59ba219c..90728fb6fec 100644 --- a/dmd/statement.d +++ b/dmd/statement.d @@ -1061,6 +1061,16 @@ extern (C++) final class IfStatement : Statement { v.visit(this); } + + /****** + * Returns: true if `if (__ctfe)` + */ + bool isIfCtfeBlock() + { + if (auto cv = condition.isVarExp()) + return cv.var.ident == Id.ctfe; + return false; + } } /*********************************************************** @@ -1762,6 +1772,7 @@ extern (C++) final class GotoStatement : Statement TryFinallyStatement tf; ScopeGuardStatement os; VarDeclaration lastVar; + bool inCtfeBlock; /// set if goto is inside an `if (__ctfe)` block extern (D) this(const ref Loc loc, Identifier ident) { @@ -1804,6 +1815,12 @@ extern (C++) final class GotoStatement : Statement return true; } + if (label.statement.inCtfeBlock && !inCtfeBlock) + { + error("cannot `goto` into `if (__ctfe)` block"); + return true; + } + Statement stbnext; for (auto stb = tryBody; stb != label.statement.tryBody; stb = stbnext) { @@ -1870,6 +1887,7 @@ extern (C++) final class LabelStatement : Statement Statement gotoTarget; // interpret void* extra; // used by Statement_toIR() bool breaks; // someone did a 'break ident' + bool inCtfeBlock; // inside a block dominated by `if (__ctfe)` extern (D) this(const ref Loc loc, Identifier ident, Statement statement) { diff --git a/dmd/statement.h b/dmd/statement.h index 76a39912718..46cc4dadf64 100644 --- a/dmd/statement.h +++ b/dmd/statement.h @@ -381,6 +381,7 @@ class IfStatement final : public Statement IfStatement *syntaxCopy() override; void accept(Visitor *v) override { v->visit(this); } + bool isIfCtfeBlock(); }; class ConditionalStatement final : public Statement @@ -667,7 +668,7 @@ class GotoStatement final : public Statement TryFinallyStatement *tf; ScopeGuardStatement *os; VarDeclaration *lastVar; - + bool inCtfeBlock; GotoStatement *syntaxCopy() override; void accept(Visitor *v) override { v->visit(this); } @@ -685,7 +686,7 @@ class LabelStatement final : public Statement Statement *gotoTarget; // interpret void* extra; // used by Statement_toIR() bool breaks; // someone did a 'break ident' - + bool inCtfeBlock; LabelStatement *syntaxCopy() override; void accept(Visitor *v) override { v->visit(this); } diff --git a/dmd/statementsem.d b/dmd/statementsem.d index c80f08d4f21..bbaee8e6152 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -1956,7 +1956,17 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor // Save 'root' of two branches (then and else) at the point where it forks CtorFlow ctorflow_root = scd.ctorflow.clone(); - ifs.ifbody = ifs.ifbody.semanticNoScope(scd); + /* Detect `if (__ctfe)` + */ + if (ifs.isIfCtfeBlock()) + { + Scope* scd2 = scd.push(); + scd2.flags |= SCOPE.ctfeBlock; + ifs.ifbody = ifs.ifbody.semanticNoScope(scd2); + scd2.pop(); + } + else + ifs.ifbody = ifs.ifbody.semanticNoScope(scd); scd.pop(); CtorFlow ctorflow_then = sc.ctorflow; // move flow results @@ -3801,6 +3811,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor gs.tf = sc.tf; gs.os = sc.os; gs.lastVar = sc.lastVar; + gs.inCtfeBlock = (sc.flags & SCOPE.ctfeBlock) != 0; if (!gs.label.statement && sc.fes) { @@ -3840,6 +3851,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor ls.tf = sc.tf; ls.os = sc.os; ls.lastVar = sc.lastVar; + ls.inCtfeBlock = (sc.flags & SCOPE.ctfeBlock) != 0; LabelDsymbol ls2 = fd.searchLabel(ls.ident, ls.loc); if (ls2.statement) diff --git a/tests/dmd/fail_compilation/ctfeblock.d b/tests/dmd/fail_compilation/ctfeblock.d new file mode 100644 index 00000000000..2d8bf7a0fef --- /dev/null +++ b/tests/dmd/fail_compilation/ctfeblock.d @@ -0,0 +1,33 @@ +/* TEST_OUTPUT: +--- +fail_compilation/ctfeblock.d(112): Error: cannot `goto` into `if (__ctfe)` block +--- +*/ + +/*******************************************/ +// https://issues.dlang.org/show_bug.cgi?id=18472 +// https://github.com/dlang/dmd/pull/14676 + +#line 100 + +struct T { } + +@nogc void test1() +{ + int a; + if (__ctfe) + { +L1: + new T(); + a = 3; + } + goto L1; +} + +@nogc void test2() +{ + if (__ctfe) + { + new T(); + } +} diff --git a/tests/dmd/runnable/test21492.d b/tests/dmd/runnable/test21492.d deleted file mode 100644 index b235fb4de1b..00000000000 --- a/tests/dmd/runnable/test21492.d +++ /dev/null @@ -1,34 +0,0 @@ -/* REQUIRED_ARGS: -betterC - */ - -// https://issues.dlang.org/show_bug.cgi?id=21492 - -int test(int i) -{ - switch (i) - { - case 0: - break; - case 1: - if (__ctfe) - { - { int[] foo = [1]; } - L3: - i += 2; - case 2: - ++i; - } - return i; - default: - break; - } - goto L3; -} - -extern (C) -int main() -{ - static assert(test(1) == 4); - assert(test(2) == 3); - return 0; -} From ece94a099282acc0441d09224011d823b97f276f Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 27 Feb 2023 00:07:49 -0800 Subject: [PATCH 115/177] lexer.d: revise unittests to use ErrorSinks --- dmd/lexer.d | 65 ++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/dmd/lexer.d b/dmd/lexer.d index 4dc4a39929a..4ffc761969e 100644 --- a/dmd/lexer.d +++ b/dmd/lexer.d @@ -3231,14 +3231,13 @@ unittest } diagnosticHandler = &assertDiagnosticHandler; - if (!global.errorSink) - global.errorSink = new ErrorSinkCompiler; + ErrorSink errorSink = new ErrorSinkStderr; - static void test(T)(string sequence, T expected, bool Ccompile = false) + void test(T)(string sequence, T expected, bool Ccompile = false) { auto p = cast(const(char)*)sequence.ptr; dchar c2; - Lexer lexer = new Lexer(global.errorSink); + Lexer lexer = new Lexer(errorSink); assert(expected == lexer.escapeSequence(Loc.initial, p, Ccompile, c2)); assert(p == sequence.ptr + sequence.length); } @@ -3282,42 +3281,46 @@ unittest unittest { fprintf(stderr, "Lexer.unittest %d\n", __LINE__); - import dmd.console; - string expected; - bool gotError; - nothrow bool expectDiagnosticHandler(const ref Loc loc, Color headerColor, const(char)* header, - const(char)* format, va_list ap, const(char)* p1, const(char)* p2) + static class ErrorSinkTest : ErrorSinkNull { - assert(cast(Classification)headerColor == Classification.error); + nothrow: + extern (C++): + override: - gotError = true; - char[100] buffer = void; - auto actual = buffer[0 .. vsnprintf(buffer.ptr, buffer.length, format, ap)]; - assert(expected == actual); - return true; - } + import core.stdc.stdio; + import core.stdc.stdarg; + + string expected; + bool gotError; - diagnosticHandler = &expectDiagnosticHandler; + void error(const ref Loc loc, const(char)* format, ...) + { + gotError = true; + char[100] buffer = void; + va_list ap; + va_start(ap, format); + auto actual = buffer[0 .. vsnprintf(buffer.ptr, buffer.length, format, ap)]; + va_end(ap); + assert(expected == actual); + } + } - if (!global.errorSink) - global.errorSink = new ErrorSinkCompiler; + ErrorSinkTest errorSink = new ErrorSinkTest; void test(string sequence, string expectedError, dchar expectedReturnValue, uint expectedScanLength, bool Ccompile = false) { - uint errors = global.errors; - gotError = false; - expected = expectedError; + errorSink.expected = expectedError; + errorSink.gotError = false; auto p = cast(const(char)*)sequence.ptr; - Lexer lexer = new Lexer(global.errorSink); + Lexer lexer = new Lexer(errorSink); dchar c2; auto actualReturnValue = lexer.escapeSequence(Loc.initial, p, Ccompile, c2); - assert(gotError); + assert(errorSink.gotError); assert(expectedReturnValue == actualReturnValue); auto actualScanLength = p - sequence.ptr; assert(expectedScanLength == actualScanLength); - global.errors = errors; } test("c", `undefined escape sequence \c`, 'c', 1); @@ -3361,9 +3364,8 @@ unittest /* Not much here, just trying things out. */ string text = "int"; // We rely on the implicit null-terminator - if (!global.errorSink) - global.errorSink = new ErrorSinkCompiler; - scope Lexer lex1 = new Lexer(null, text.ptr, 0, text.length, false, false, global.errorSink); + ErrorSink errorSink = new ErrorSinkStderr; + scope Lexer lex1 = new Lexer(null, text.ptr, 0, text.length, false, false, errorSink); TOK tok; tok = lex1.nextToken(); //printf("tok == %s, %d, %d\n", Token::toChars(tok), tok, TOK.int32); @@ -3379,12 +3381,9 @@ unittest unittest { fprintf(stderr, "Lexer.unittest %d\n", __LINE__); - if (!global.errorSink) - global.errorSink = new ErrorSinkCompiler; // We don't want to see Lexer error output during these tests. - uint errors = global.startGagging(); - scope(exit) global.endGagging(errors); + ErrorSink errorSink = new ErrorSinkNull; // Test malformed input: even malformed input should end in a TOK.endOfFile. static immutable char[][] testcases = @@ -3402,7 +3401,7 @@ unittest foreach (testcase; testcases) { - scope Lexer lex2 = new Lexer(null, testcase.ptr, 0, testcase.length-1, false, false, global.errorSink); + scope Lexer lex2 = new Lexer(null, testcase.ptr, 0, testcase.length-1, false, false, errorSink); TOK tok = lex2.nextToken(); size_t iterations = 1; while ((tok != TOK.endOfFile) && (iterations++ < testcase.length)) From aef37855acacbfa4d5ab089658f8e81cd2f50e68 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 27 Feb 2023 10:51:00 -0800 Subject: [PATCH 116/177] tokens.d: use buffer properly --- dmd/tokens.d | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dmd/tokens.d b/dmd/tokens.d index 1f4eb792fd3..aec3a77dee8 100644 --- a/dmd/tokens.d +++ b/dmd/tokens.d @@ -969,7 +969,7 @@ nothrow: OutBuffer buf; buf.writeSingleCharLiteral(cast(dchar) intvalue); buf.writeByte('\0'); - p = buf.extractSlice().ptr; + p = buf.extractChars(); } break; case TOK.int64Literal: @@ -1015,7 +1015,7 @@ nothrow: if (postfix) buf.writeByte(postfix); buf.writeByte(0); - p = buf.extractSlice().ptr; + p = buf.extractChars(); } break; case TOK.identifier: @@ -1125,7 +1125,7 @@ unittest { writeCharLiteral(buf, d); } - assert(buf.extractSlice() == `a\n\r\t\b\f\0\x11\u7233\U00017233`); + assert(buf[] == `a\n\r\t\b\f\0\x11\u7233\U00017233`); } /** @@ -1156,11 +1156,11 @@ unittest { OutBuffer buf; writeSingleCharLiteral(buf, '\''); - assert(buf.extractSlice() == `'\''`); + assert(buf[] == `'\''`); buf.reset(); writeSingleCharLiteral(buf, '"'); - assert(buf.extractSlice() == `'"'`); + assert(buf[] == `'"'`); buf.reset(); writeSingleCharLiteral(buf, '\n'); - assert(buf.extractSlice() == `'\n'`); + assert(buf[] == `'\n'`); } From dee70f22b857b19b8446859290031669ccb54df4 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 27 Feb 2023 12:47:05 -0800 Subject: [PATCH 117/177] parseModulePatternDepth: replace pointer with array --- dmd/compiler.d | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/dmd/compiler.d b/dmd/compiler.d index 84c2c6c9c6d..1c6f236ba42 100644 --- a/dmd/compiler.d +++ b/dmd/compiler.d @@ -11,6 +11,8 @@ module dmd.compiler; +import core.stdc.string; + import dmd.astcodegen; import dmd.astenums; import dmd.arraytypes; @@ -305,7 +307,7 @@ private void createMatchNodes() { foreach (modulePattern; includeModulePatterns) { - auto depth = parseModulePatternDepth(modulePattern); + auto depth = parseModulePatternDepth(modulePattern[0 .. strlen(modulePattern)]); auto entryIndex = findSortedIndexToAddForDepth(depth); matchNodes.split(entryIndex, depth + 1); parseModulePattern(modulePattern, &matchNodes[entryIndex], depth); @@ -342,24 +344,20 @@ private void createMatchNodes() * Returns: * The component depth of the given module pattern. */ -private ushort parseModulePatternDepth(const(char)* modulePattern) +pure @safe +private ushort parseModulePatternDepth(const char[] modulePattern) { - if (modulePattern[0] == '-') - modulePattern++; + const length = modulePattern.length; + size_t i = (length && modulePattern[0] == '-'); // skip past leading '-' // handle special case - if (modulePattern[0] == '.' && modulePattern[1] == '\0') + if (i + 1 == length && modulePattern[i] == '.') return 0; - ushort depth = 1; - for (;; modulePattern++) - { - auto c = *modulePattern; - if (c == '.') - depth++; - if (c == '\0') - return depth; - } + int depth = 1; + foreach (c; modulePattern[i .. length]) + depth += c == '.'; + return cast(ushort)depth; } unittest { From 6f14fd1495fba28784d7ff73b93a41eb000d50d3 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 27 Feb 2023 15:41:39 -0800 Subject: [PATCH 118/177] lexer.d: remove errors and globals imports --- dmd/lexer.d | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/dmd/lexer.d b/dmd/lexer.d index 4ffc761969e..c9ed35ffa6d 100644 --- a/dmd/lexer.d +++ b/dmd/lexer.d @@ -22,9 +22,7 @@ import core.stdc.string; import core.stdc.time; import dmd.entity; -import dmd.errors; import dmd.errorsink; -import dmd.globals; import dmd.id; import dmd.identifier; import dmd.location; @@ -574,7 +572,7 @@ class Lexer else if (*t.ptr == '_') // if special identifier token { // Lazy initialization - TimeStampInfo.initialize(t.loc); + TimeStampInfo.initialize(t.loc, eSink); if (id == Id.DATE) { @@ -3082,7 +3080,7 @@ private struct TimeStampInfo __gshared char[8 + 1] time; __gshared char[24 + 1] timestamp; - public static void initialize(const ref Loc loc) nothrow + public static void initialize(const ref Loc loc, ErrorSink eSink) nothrow { if (initdone) return; @@ -3093,7 +3091,7 @@ private struct TimeStampInfo if (auto p = getenv("SOURCE_DATE_EPOCH")) { if (!ct.parseDigits(p.toDString())) - error(loc, "value of environment variable `SOURCE_DATE_EPOCH` should be a valid UNIX timestamp, not: `%s`", p); + eSink.error(loc, "value of environment variable `SOURCE_DATE_EPOCH` should be a valid UNIX timestamp, not: `%s`", p); } else .time(&ct); @@ -3223,13 +3221,6 @@ private bool c_isalnum(const int c) pure @nogc @safe unittest { fprintf(stderr, "Lexer.unittest %d\n", __LINE__); - import dmd.console; - nothrow bool assertDiagnosticHandler(const ref Loc loc, Color headerColor, const(char)* header, - const(char)* format, va_list ap, const(char)* p1, const(char)* p2) - { - assert(0); - } - diagnosticHandler = &assertDiagnosticHandler; ErrorSink errorSink = new ErrorSinkStderr; @@ -3274,8 +3265,6 @@ unittest test(`"`, '"'); test(`<`, '<'); test(`>`, '>'); - - diagnosticHandler = null; } unittest @@ -3354,8 +3343,6 @@ unittest test(""", `unterminated named entity "`, '?', 5); test("400", `escape octal sequence \400 is larger than \377`, 0x100, 3); - - diagnosticHandler = null; } unittest From 8b3e196a71258e0f2168d09ef45ddafd8cdd208e Mon Sep 17 00:00:00 2001 From: Geod24 Date: Tue, 28 Feb 2023 00:32:03 +0100 Subject: [PATCH 119/177] Fix 11316: Infer storage class of parameters with function literals This will allow improving functional style code by seamlessly adding `ref` (or `in`) and having the compiler do the job. --- dmd/expression.d | 1 + tests/dmd/compilable/infer_stc.d | 51 ++++++++++++++++++++++++++++++++ tests/dmd/runnable/funclit.d | 1 - 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/compilable/infer_stc.d diff --git a/dmd/expression.d b/dmd/expression.d index 3319029a7c6..df5e9ddc98e 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -4045,6 +4045,7 @@ extern (C++) final class FuncExp : Expression Type t = pto.type; if (t.ty == Terror) return cannotInfer(this, to, flag); + tf.parameterList[u].storageClass = tof.parameterList[u].storageClass; tiargs.push(t); } diff --git a/tests/dmd/compilable/infer_stc.d b/tests/dmd/compilable/infer_stc.d new file mode 100644 index 00000000000..50140e73d2b --- /dev/null +++ b/tests/dmd/compilable/infer_stc.d @@ -0,0 +1,51 @@ +/// Test storage class inference on delegate parameters + +alias FPT = void function (in string, ref string, out string, scope string); +alias DGT = void delegate (in string, ref string, out string, scope string); + +void f1 (FPT func) +{ + string ro = "Hello World"; + string ref_ = ro, out_ = ro; + func(ro, ref_, out_, ro); +} + +void f2 (DGT func) +{ + string ro = "Hello World"; + string ref_ = ro, out_ = ro; + func(ro, ref_, out_, ro); +} + +void test () +{ + f1((in_, ref_, out_, scope_) { + assert(in_ == "Hello World"); + assert(in_ == scope_); + assert(in_ == ref_); + assert(out_ is null); + }); + + f2((in_, ref_, out_, scope_) { + assert(in_ == "Hello World"); + assert(in_ == scope_); + assert(in_ == ref_); + assert(out_ is null); + }); +} + +// https://issues.dlang.org/show_bug.cgi?id=11316 +void issue11316() { + void delegate(const int x) F0; + F0 = (const int x) {}; // OK + F0 = (x) {}; // OK + void delegate(in int x) F1; + F1 = (in int x) {}; // OK + F1 = (x) {}; // OK + void delegate(ref int x) F2; + F2 = (ref int x) {}; // OK + F2 = (x) {}; // Error + void delegate(out int x) F3; + F3 = (out int x) {}; // OK + F3 = (x) {}; // Error +} diff --git a/tests/dmd/runnable/funclit.d b/tests/dmd/runnable/funclit.d index 25b4e6e512c..e6e4fec1c54 100644 --- a/tests/dmd/runnable/funclit.d +++ b/tests/dmd/runnable/funclit.d @@ -520,7 +520,6 @@ void test7705() { void foo1(void delegate(ref int ) dg){ int x=10; dg(x); } foo1((ref x){ pragma(msg, typeof(x)); assert(x == 10); }); - static assert(!__traits(compiles, foo1((x){}) )); void foo2(void delegate(int, ...) dg){ dg(20, 3.14); } foo2((x,...){ pragma(msg, typeof(x)); assert(x == 20); }); From 483a5804fc2f5233c0f6ecf9ea7fc474ecbe94c6 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Mon, 27 Feb 2023 13:18:55 +0100 Subject: [PATCH 120/177] Deduplicate lexer unittest code --- tests/dmd/unit/lexer/lexer_dmdlib.d | 60 +++++++++-------------------- 1 file changed, 18 insertions(+), 42 deletions(-) diff --git a/tests/dmd/unit/lexer/lexer_dmdlib.d b/tests/dmd/unit/lexer/lexer_dmdlib.d index 561fd1d1988..4b53bafc9ac 100644 --- a/tests/dmd/unit/lexer/lexer_dmdlib.d +++ b/tests/dmd/unit/lexer/lexer_dmdlib.d @@ -4,6 +4,18 @@ import dmd.lexer : Lexer; import dmd.tokens : TOK; import dmd.errorsink; +/// Test that lexing `code` generates the `expected` tokens +private void test(string code, const TOK[] expected, bool keepComments = false, bool keepWhitespace = false) +{ + Lexer lexer = new Lexer(null, code.ptr, 0, code.length, /*doDocComment*/ false, keepComments, keepWhitespace, new ErrorSinkStderr); + TOK[] result; + + while (lexer.nextToken != TOK.endOfFile) + result ~= lexer.token.value; + + assert(result == expected); +} + unittest { immutable code = "void test() {} // foobar"; @@ -17,13 +29,7 @@ unittest TOK.rightCurly, ]; - Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, false, false, new ErrorSinkStderr); - TOK[] result; - - while (lexer.nextToken != TOK.endOfFile) - result ~= lexer.token.value; - - assert(result == expected); + test(code, expected, false, false); } unittest @@ -40,13 +46,7 @@ unittest TOK.comment, ]; - Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true, false, new ErrorSinkStderr); - TOK[] result; - - while (lexer.nextToken != TOK.endOfFile) - result ~= lexer.token.value; - - assert(result == expected); + test(code, expected, true, false); } unittest @@ -66,13 +66,7 @@ unittest TOK.comment, ]; - Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true, true, new ErrorSinkStderr); - TOK[] result; - - while (lexer.nextToken != TOK.endOfFile) - result ~= lexer.token.value; - - assert(result == expected); + test(code, expected, true, true); } unittest @@ -93,13 +87,7 @@ unittest TOK.whitespace, ]; - Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true, true, new ErrorSinkStderr); - TOK[] result; - - while (lexer.nextToken != TOK.endOfFile) - result ~= lexer.token.value; - - assert(result == expected); + test(code, expected, true, true); } unittest @@ -137,13 +125,7 @@ unittest TOK.whitespace, ]; - Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true, true, new ErrorSinkStderr); - TOK[] result; - - while (lexer.nextToken != TOK.endOfFile) - result ~= lexer.token.value; - - assert(result == expected); + test(code, expected, true, true); } unittest @@ -172,13 +154,7 @@ unittest TOK.whitespace, ]; - Lexer lexer = new Lexer(null, code.ptr, 0, code.length, false, true, true, new ErrorSinkStderr); - TOK[] result; - - while (lexer.nextToken != TOK.endOfFile) - result ~= lexer.token.value; - - assert(result == expected); + test(code, expected, true, true); } unittest From 7cf1dadfd9a4193887e1fc0017374f06338f1775 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 27 Feb 2023 20:42:53 -0800 Subject: [PATCH 121/177] fix Issue 18472: betterC cannot use format at compile time --- dmd/dstruct.d | 2 +- dmd/inlinecost.d | 7 +++++ tests/dmd/runnable/test18472.d | 53 ++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/runnable/test18472.d diff --git a/dmd/dstruct.d b/dmd/dstruct.d index 3d893266bcc..3268d5667de 100644 --- a/dmd/dstruct.d +++ b/dmd/dstruct.d @@ -75,7 +75,7 @@ extern (C++) void semanticTypeInfo(Scope* sc, Type t) { if (sc.intypeof) return; - if (sc.flags & (SCOPE.ctfe | SCOPE.compile)) + if (sc.flags & (SCOPE.ctfe | SCOPE.compile | SCOPE.ctfeBlock)) return; } diff --git a/dmd/inlinecost.d b/dmd/inlinecost.d index c6ac26bfdb0..2dd25e2c0f5 100644 --- a/dmd/inlinecost.d +++ b/dmd/inlinecost.d @@ -264,6 +264,13 @@ public: return; } expressionInlineCost(s.condition); + + if (s.isIfCtfeBlock()) + { + cost = COST_MAX; + return; + } + /* Specifically allow: * if (condition) * return exp1; diff --git a/tests/dmd/runnable/test18472.d b/tests/dmd/runnable/test18472.d new file mode 100644 index 00000000000..a571b08cfd2 --- /dev/null +++ b/tests/dmd/runnable/test18472.d @@ -0,0 +1,53 @@ +/* REQUIRED_ARGS: -betterC +*/ + +/*******************************************/ +// https://issues.dlang.org/show_bug.cgi?id=18472 +// https://github.com/dlang/dmd/pull/14676 + +@nogc nothrow pure: +immutable(Char)[] format(Char, Args...)(in Char[] fmt, Args args) +{ + + if (__ctfe) + { + auto data2 = new char[5]; + auto data = new Data2; + { + auto data3 = new Data2; + } + data2 = cast(char[]) "test2"; + return data2; + } + else + { + return "test"; + } +} + +extern(C) void main() +{ + static assert(getData() == "test"); + static assert("%s %s".format("test", "test") == "test2", "Not working"); + assert("%s %s".format("test", "test") == "test", "%s %s".format("test", "test")); + assert(getData() == "test2", getData()); +} + +string getData() +{ + if (__ctfe) + { + auto data2 = new ubyte[5]; + auto data = new Data2; + return "test"; + } + else + { + return "test2"; + } +} + +private struct Data2 +{ + size_t capacity; +} From ef079c0abe7c76fdb59c46499745ebf19683949f Mon Sep 17 00:00:00 2001 From: Geod24 Date: Sun, 4 Sep 2022 08:20:05 +0200 Subject: [PATCH 122/177] Add 'override' on functions overriding interface functions --- runtime/druntime/src/core/sys/windows/stacktrace.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/druntime/src/core/sys/windows/stacktrace.d b/runtime/druntime/src/core/sys/windows/stacktrace.d index 8df29729af3..cacfd27067f 100644 --- a/runtime/druntime/src/core/sys/windows/stacktrace.d +++ b/runtime/druntime/src/core/sys/windows/stacktrace.d @@ -67,7 +67,7 @@ public: m_trace = trace(tracebuf[], skip, context); } - int opApply( scope int delegate(ref const(char[])) dg ) const + override int opApply( scope int delegate(ref const(char[])) dg ) const { return opApply( (ref size_t, ref const(char[]) buf) { @@ -76,7 +76,7 @@ public: } - int opApply( scope int delegate(ref size_t, ref const(char[])) dg ) const + override int opApply( scope int delegate(ref size_t, ref const(char[])) dg ) const { int result; foreach ( i, e; resolve(m_trace) ) From 404b79d46a5ed6640551eeaebb68abc0f0aa748c Mon Sep 17 00:00:00 2001 From: Geod24 Date: Wed, 1 Mar 2023 12:20:38 +0100 Subject: [PATCH 123/177] Remove unused core.demangler : parseType name argument The function is private, so it is fine to remove it. There were no place where the non-default value wasn't given, directly or indirectly. --- runtime/druntime/src/core/demangle.d | 39 +++++++--------------------- 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/runtime/druntime/src/core/demangle.d b/runtime/druntime/src/core/demangle.d index a68e509c722..3fcb26657c8 100644 --- a/runtime/druntime/src/core/demangle.d +++ b/runtime/druntime/src/core/demangle.d @@ -801,7 +801,7 @@ pure @safe: TypeTuple: B Number Arguments */ - char[] parseType( char[] name = null ) return scope + char[] parseType() return scope { static immutable string[23] primitives = [ "char", // a @@ -830,7 +830,7 @@ pure @safe: ]; static if (__traits(hasMember, Hooks, "parseType")) - if (auto n = hooks.parseType(this, name)) + if (auto n = hooks.parseType(this, null)) return n; debug(trace) printf( "parseType+\n" ); @@ -861,27 +861,24 @@ pure @safe: switch ( t ) { case 'Q': // Type back reference - return parseBackrefType( () => parseType( name ) ); + return parseBackrefType(() => parseType()); case 'O': // Shared (O Type) popFront(); put( "shared(" ); parseType(); put( ')' ); - pad( name ); return dst[beg .. len]; case 'x': // Const (x Type) popFront(); put( "const(" ); parseType(); put( ')' ); - pad( name ); return dst[beg .. len]; case 'y': // Immutable (y Type) popFront(); put( "immutable(" ); parseType(); put( ')' ); - pad( name ); return dst[beg .. len]; case 'N': popFront(); @@ -912,7 +909,6 @@ pure @safe: popFront(); parseType(); put( "[]" ); - pad( name ); return dst[beg .. len]; case 'G': // TypeStaticArray (G Number Type) popFront(); @@ -921,7 +917,6 @@ pure @safe: put( '[' ); put( num ); put( ']' ); - pad( name ); return dst[beg .. len]; case 'H': // TypeAssocArray (H Type Type) popFront(); @@ -931,31 +926,28 @@ pure @safe: put( '[' ); put( tx ); put( ']' ); - pad( name ); return dst[beg .. len]; case 'P': // TypePointer (P Type) popFront(); parseType(); put( '*' ); - pad( name ); return dst[beg .. len]; case 'F': case 'U': case 'W': case 'V': case 'R': // TypeFunction - return parseTypeFunction( name ); + return parseTypeFunction(); case 'C': // TypeClass (C LName) case 'S': // TypeStruct (S LName) case 'E': // TypeEnum (E LName) case 'T': // TypeTypedef (T LName) popFront(); parseQualifiedName(); - pad( name ); return dst[beg .. len]; case 'D': // TypeDelegate (D TypeFunction) popFront(); auto modifiers = parseModifier(); if ( front == 'Q' ) - parseBackrefType( () => parseTypeFunction( name, IsDelegate.yes ) ); + parseBackrefType(() => parseTypeFunction(IsDelegate.yes)); else - parseTypeFunction( name, IsDelegate.yes ); + parseTypeFunction(IsDelegate.yes); if (modifiers) { // write modifiers behind the function arguments @@ -989,7 +981,6 @@ pure @safe: { popFront(); put( primitives[cast(size_t)(t - 'a')] ); - pad( name ); return dst[beg .. len]; } else if (t == 'z') @@ -1000,12 +991,10 @@ pure @safe: case 'i': popFront(); put( "cent" ); - pad( name ); return dst[beg .. len]; case 'k': popFront(); put( "ucent" ); - pad( name ); return dst[beg .. len]; default: error(); @@ -1358,7 +1347,7 @@ pure @safe: TypeFunction: CallConvention FuncAttrs Arguments ArgClose Type */ - char[] parseTypeFunction( char[] name = null, IsDelegate isdg = IsDelegate.no ) return scope + char[] parseTypeFunction(IsDelegate isdg = IsDelegate.no) return scope { debug(trace) printf( "parseTypeFunction+\n" ); debug(trace) scope(success) printf( "parseTypeFunction-\n" ); @@ -1383,18 +1372,8 @@ pure @safe: auto retbeg = len; parseType(); put( ' ' ); - // append name/delegate/function - if ( name.length ) - { - if ( !contains( dst[0 .. len], name ) ) - put( name ); - else if ( shift( name ).ptr != name.ptr ) - { - argbeg -= name.length; - retbeg -= name.length; - } - } - else if ( IsDelegate.yes == isdg ) + // append delegate/function + if (IsDelegate.yes == isdg) put( "delegate" ); else put( "function" ); From c796f431c85379c8ef9bfd8a51aed1f56fd4f1b0 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Wed, 1 Mar 2023 19:02:48 +0000 Subject: [PATCH 124/177] Fix tests broken by divergent changes in stable --- runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp | 2 +- runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp | 2 +- runtime/druntime/test/profile/myprofilegc.log.linux.32.exp | 2 +- runtime/druntime/test/profile/myprofilegc.log.linux.64.exp | 2 +- runtime/druntime/test/profile/myprofilegc.log.osx.32.exp | 2 +- runtime/druntime/test/profile/myprofilegc.log.osx.64.exp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp b/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp index bcf256b499c..15b5e41fd7c 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp @@ -16,5 +16,5 @@ bytes allocated, allocations, type, function, file:line 16 1 int[] D main src/profilegc.d:14 16 1 int[] D main src/profilegc.d:22 16 1 int[] D main src/profilegc.d:37 - 16 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2752 + 16 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2755 16 1 wchar[] D main src/profilegc.d:35 diff --git a/runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp b/runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp index 6a779303247..79c86edcfb3 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp @@ -6,7 +6,7 @@ bytes allocated, allocations, type, function, file:line 48 1 float[] D main src/profilegc.d:42 48 1 int[] D main src/profilegc.d:41 32 1 C D main src/profilegc.d:12 - 32 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2752 + 32 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2755 32 1 void[] profilegc.main src/profilegc.d:55 16 1 char[] D main src/profilegc.d:34 16 1 char[] D main src/profilegc.d:36 diff --git a/runtime/druntime/test/profile/myprofilegc.log.linux.32.exp b/runtime/druntime/test/profile/myprofilegc.log.linux.32.exp index bcf256b499c..15b5e41fd7c 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.linux.32.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.linux.32.exp @@ -16,5 +16,5 @@ bytes allocated, allocations, type, function, file:line 16 1 int[] D main src/profilegc.d:14 16 1 int[] D main src/profilegc.d:22 16 1 int[] D main src/profilegc.d:37 - 16 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2752 + 16 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2755 16 1 wchar[] D main src/profilegc.d:35 diff --git a/runtime/druntime/test/profile/myprofilegc.log.linux.64.exp b/runtime/druntime/test/profile/myprofilegc.log.linux.64.exp index 6a779303247..79c86edcfb3 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.linux.64.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.linux.64.exp @@ -6,7 +6,7 @@ bytes allocated, allocations, type, function, file:line 48 1 float[] D main src/profilegc.d:42 48 1 int[] D main src/profilegc.d:41 32 1 C D main src/profilegc.d:12 - 32 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2752 + 32 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2755 32 1 void[] profilegc.main src/profilegc.d:55 16 1 char[] D main src/profilegc.d:34 16 1 char[] D main src/profilegc.d:36 diff --git a/runtime/druntime/test/profile/myprofilegc.log.osx.32.exp b/runtime/druntime/test/profile/myprofilegc.log.osx.32.exp index b33b547aee1..4faa76ae777 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.osx.32.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.osx.32.exp @@ -16,5 +16,5 @@ bytes allocated, allocations, type, function, file:line 16 1 int[] D main src/profilegc.d:14 16 1 int[] D main src/profilegc.d:22 16 1 int[] D main src/profilegc.d:37 - 16 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2752 + 16 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2755 16 1 wchar[] D main src/profilegc.d:35 diff --git a/runtime/druntime/test/profile/myprofilegc.log.osx.64.exp b/runtime/druntime/test/profile/myprofilegc.log.osx.64.exp index 6a779303247..79c86edcfb3 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.osx.64.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.osx.64.exp @@ -6,7 +6,7 @@ bytes allocated, allocations, type, function, file:line 48 1 float[] D main src/profilegc.d:42 48 1 int[] D main src/profilegc.d:41 32 1 C D main src/profilegc.d:12 - 32 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2752 + 32 1 profilegc.main.C core.lifetime._d_newclassT!(C)._d_newclassT ../../src/core/lifetime.d:2755 32 1 void[] profilegc.main src/profilegc.d:55 16 1 char[] D main src/profilegc.d:34 16 1 char[] D main src/profilegc.d:36 From bf29655930a25e830b9b1eee42797da43e1d87c2 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Thu, 2 Mar 2023 18:57:45 +0800 Subject: [PATCH 125/177] Fix Issue 22039 - ICE on infinite recursion in default parameter (dlang/dmd!14934) --- dmd/expressionsem.d | 3 ++- tests/dmd/fail_compilation/fail22039.d | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/fail_compilation/fail22039.d diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 9b9fbb8ad77..d186abc0552 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -1728,7 +1728,6 @@ private bool functionParameters(const ref Loc loc, Scope* sc, const size_t nparams = tf.parameterList.length; const olderrors = global.errors; bool err = false; - *prettype = Type.terror; Expression eprefix = null; *peprefix = null; @@ -1817,6 +1816,8 @@ private bool functionParameters(const ref Loc loc, Scope* sc, return errorArgs(); } arg = p.defaultArg; + if (!arg.type) + arg = arg.expressionSemantic(sc); arg = inlineCopy(arg, sc); // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__ arg = arg.resolveLoc(loc, sc); diff --git a/tests/dmd/fail_compilation/fail22039.d b/tests/dmd/fail_compilation/fail22039.d new file mode 100644 index 00000000000..3df834f7ad0 --- /dev/null +++ b/tests/dmd/fail_compilation/fail22039.d @@ -0,0 +1,14 @@ +// https://issues.dlang.org/show_bug.cgi?id=22039 + +/* +TEST_OUTPUT: +--- +fail_compilation/fail22039.d(11): Error: recursive evaluation of `func()` +fail_compilation/fail22039.d(14): Error: recursive evaluation of `gun(func2())` +--- +*/ + +int func(int x = func()) { return x; } + +int gun() { return 2; } +int func2(int x = gun(func2())) { return x; } From a8a2d00243e5719c64f09be9a4cde5d7a47f71ee Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sat, 4 Mar 2023 01:20:44 +0100 Subject: [PATCH 126/177] Issue 23759 - [REG 2.103][FTBFS] Undefined symbols for architecture i386: "__ZN7CTFloat6sprintEPcjc10longdouble" --- dmd/root/ctfloat.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dmd/root/ctfloat.h b/dmd/root/ctfloat.h index a23fa506a9f..d2f795bf9e9 100644 --- a/dmd/root/ctfloat.h +++ b/dmd/root/ctfloat.h @@ -9,6 +9,7 @@ #pragma once +#include "dcompat.h" #include "longdouble.h" // Type used by the front-end for compile-time reals @@ -51,7 +52,7 @@ struct CTFloat static bool isInfinity(real_t r); static real_t parse(const char *literal, bool& isOutOfRange); - static int sprint(char *str, size_t size, char fmt, real_t x); + static int sprint(char *str, d_size_t size, char fmt, real_t x); static size_t hash(real_t a); From 544063b636610cf47fb8197167d3df4bf77a59f2 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Fri, 3 Mar 2023 22:40:33 +0100 Subject: [PATCH 127/177] fix Issue 23758 - [REG 2.103] Segfault accessing NewExp::argprefix from C++ --- dmd/expression.h | 1 + 1 file changed, 1 insertion(+) diff --git a/dmd/expression.h b/dmd/expression.h index c7f789dbc08..e4716c8dfcf 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -532,6 +532,7 @@ class NewExp final : public Expression Expression *thisexp; // if !NULL, 'this' for class being allocated Type *newtype; Expressions *arguments; // Array of Expression's + Identifiers *names; // Array of names corresponding to expressions Expression *argprefix; // expression to be evaluated just before arguments[] From d6995ebf8e88ec4633957df4fc0a68adb162f9b4 Mon Sep 17 00:00:00 2001 From: Geod24 Date: Wed, 8 Mar 2023 01:22:47 +0100 Subject: [PATCH 128/177] Fix 23763: Correctly handle struct constants with 0 initializer At the moment, in dsymbolsem.d:1026, there is the following comment: ``` /* If a struct is all zeros, as a special case * set its initializer to the integer 0. * In AssignExp::toElem(), we check for this and issue * a memset() to initialize the struct. * Must do same check in interpreter. */ ``` Turns out, the 'Must do same check in interpreter.' part was missing. --- dmd/dinterpret.d | 10 ++++++++++ tests/dmd/compilable/test17351.d | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/dmd/dinterpret.d b/dmd/dinterpret.d index 9073b0db2f8..7ad9908b3f0 100644 --- a/dmd/dinterpret.d +++ b/dmd/dinterpret.d @@ -2117,6 +2117,16 @@ public: return CTFEExp.cantexp; assert(e.type); + // There's a terrible hack in `dmd.dsymbolsem` that special case + // a struct with all zeros to an `ExpInitializer(BlitExp(IntegerExp(0)))` + // There's matching code for it in e2ir (toElem's visitAssignExp), + // so we need the same hack here. + // This does not trigger for global as they get a normal initializer. + if (auto ts = e.type.isTypeStruct()) + if (auto ae = e.isBlitExp()) + if (ae.e2.op == EXP.int64) + e = ts.defaultInitLiteral(loc); + if (e.op == EXP.construct || e.op == EXP.blit) { AssignExp ae = cast(AssignExp)e; diff --git a/tests/dmd/compilable/test17351.d b/tests/dmd/compilable/test17351.d index fffe92c4d58..a04ade12476 100644 --- a/tests/dmd/compilable/test17351.d +++ b/tests/dmd/compilable/test17351.d @@ -1,3 +1,4 @@ +// PERMUTE_ARGS: -preview=in bool fun(S)(ref S[3] a) { assert(a == [42, 84, 169]); return true; } bool fun2(S)(ref S a) { return true; } void main() @@ -14,4 +15,12 @@ void test2() { static immutable int[2] P = [ 0, 1 ]; static assert(f2(P) == 1); + immutable BigInt a, b; + static assert(glob1.twice == b.twice); + static assert(a.twice == b.twice); } + +struct BigInt { int[64] big; } +BigInt twice (in BigInt v) @safe pure nothrow @nogc { return v; } + +immutable BigInt glob1 = BigInt.init; From 32cf8f31dc8fe95f24e49e4be0fc06b16a115ce1 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Wed, 8 Mar 2023 22:03:08 +0800 Subject: [PATCH 129/177] Fix Issue 23760 - Unknown error for type used with traits(getOverloads) (dlang/dmd!14963) --- dmd/typesem.d | 1 + tests/dmd/fail_compilation/fail23760.d | 27 ++++++++++++++++++++++ tests/dmd/fail_compilation/fail_circular.d | 15 +++++++----- 3 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 tests/dmd/fail_compilation/fail23760.d diff --git a/dmd/typesem.d b/dmd/typesem.d index 84561ac467a..c668199e5f7 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -4176,6 +4176,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag) } if (v.type.ty == Terror) { + e.error("type of variable `%s` has errors", v.toPrettyChars); return ErrorExp.get(); } diff --git a/tests/dmd/fail_compilation/fail23760.d b/tests/dmd/fail_compilation/fail23760.d new file mode 100644 index 00000000000..fbca6ecd797 --- /dev/null +++ b/tests/dmd/fail_compilation/fail23760.d @@ -0,0 +1,27 @@ +// https://issues.dlang.org/show_bug.cgi?id=23760 + +/* +TEST_OUTPUT: +--- +fail_compilation/fail23760.d(16): Error: type of variable `fail23760.A.state` has errors +fail_compilation/fail23760.d(16): Error: `(A).state` cannot be resolved +fail_compilation/fail23760.d(21): Error: template instance `fail23760.JavaBridge!(A)` error instantiating +fail_compilation/fail23760.d(24): instantiated from here: `JavaClass!(A)` +--- +*/ + +class JavaBridge(Class) +{ + static if(is(typeof(__traits(getMember, Class, "state")))) {} + alias T = __traits(getOverloads, Class, "state"); +} + +class JavaClass(CRTP) +{ + JavaBridge!(CRTP) _javaDBridge; +} + +class A : JavaClass!A +{ + State* state; +} diff --git a/tests/dmd/fail_compilation/fail_circular.d b/tests/dmd/fail_compilation/fail_circular.d index 186444e459a..e67fabce91d 100644 --- a/tests/dmd/fail_compilation/fail_circular.d +++ b/tests/dmd/fail_compilation/fail_circular.d @@ -110,12 +110,15 @@ struct S6 /* TEST_OUTPUT: --- -fail_compilation/fail_circular.d(123): Error: circular reference to variable `fail_circular.C.a1` -fail_compilation/fail_circular.d(125): Error: circular reference to variable `fail_circular.C.b1` -fail_compilation/fail_circular.d(127): Error: circular reference to variable `fail_circular.C.c1` -fail_compilation/fail_circular.d(130): Error: circular reference to variable `fail_circular.C.a1a` -fail_compilation/fail_circular.d(133): Error: circular reference to variable `fail_circular.C.b1a` -fail_compilation/fail_circular.d(136): Error: circular reference to variable `fail_circular.C.c1a` +fail_compilation/fail_circular.d(126): Error: circular reference to variable `fail_circular.C.a1` +fail_compilation/fail_circular.d(128): Error: circular reference to variable `fail_circular.C.b1` +fail_compilation/fail_circular.d(130): Error: circular reference to variable `fail_circular.C.c1` +fail_compilation/fail_circular.d(133): Error: circular reference to variable `fail_circular.C.a1a` +fail_compilation/fail_circular.d(132): Error: type of variable `fail_circular.C.a1b` has errors +fail_compilation/fail_circular.d(136): Error: circular reference to variable `fail_circular.C.b1a` +fail_compilation/fail_circular.d(135): Error: type of variable `fail_circular.C.b1b` has errors +fail_compilation/fail_circular.d(139): Error: circular reference to variable `fail_circular.C.c1a` +fail_compilation/fail_circular.d(138): Error: type of variable `fail_circular.C.c1b` has errors --- */ class C From 7f7a6ac2330cdfc67de4267efb6308192f7a9e6e Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Fri, 10 Mar 2023 14:12:50 +0800 Subject: [PATCH 130/177] Fix Issue 16213 - CTFE internal error with static array $ as template argument (dlang/dmd!14964) --- dmd/dsymbol.d | 21 +++++++++++++++++---- tests/dmd/compilable/test16213.d | 8 ++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 tests/dmd/compilable/test16213.d diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index aa478f2fea2..e7ce93ee067 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -2162,10 +2162,23 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol * or a variable (in which case an expression is created in * toir.c). */ - auto e = new VoidInitializer(Loc.initial); - e.type = Type.tsize_t; - v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, e); - v.storage_class |= STC.temp | STC.ctfe; // it's never a true static variable + + // https://issues.dlang.org/show_bug.cgi?id=16213 + // For static arrays $ is known at compile time, + // so declare it as a manifest constant. + auto tsa = ce.type ? ce.type.isTypeSArray() : null; + if (tsa) + { + auto e = new ExpInitializer(loc, tsa.dim); + v = new VarDeclaration(loc, tsa.dim.type, Id.dollar, e, STC.manifest); + } + else + { + auto e = new VoidInitializer(Loc.initial); + e.type = Type.tsize_t; + v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, e); + v.storage_class |= STC.temp | STC.ctfe; // it's never a true static variable + } } *pvar = v; } diff --git a/tests/dmd/compilable/test16213.d b/tests/dmd/compilable/test16213.d new file mode 100644 index 00000000000..ccf77c6c948 --- /dev/null +++ b/tests/dmd/compilable/test16213.d @@ -0,0 +1,8 @@ +// https://issues.dlang.org/show_bug.cgi?id=16213 + +enum Id(size_t i) = i; +void main() +{ + int[5] y; + y[ Id!($) - 1 ] = 3; +} From 7c08ef482e398f27615fefe4016262628f7ad161 Mon Sep 17 00:00:00 2001 From: Dennis Date: Fri, 10 Mar 2023 13:59:12 +0100 Subject: [PATCH 131/177] Fix 23752 - ImportC: can't take address of dereferenced void pointer (dlang/dmd!14970) --- dmd/expressionsem.d | 8 ++++++++ tests/dmd/compilable/ctests2.c | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index d186abc0552..d191e9b5af2 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -7309,6 +7309,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor goto case Terror; } + if (sc.flags & SCOPE.Cfile && exp.type && exp.type.toBasetype().ty == Tvoid) + { + // https://issues.dlang.org/show_bug.cgi?id=23752 + // `&*((void*)(0))` is allowed in C + result = exp; + return; + } + if (exp.checkValue()) return setError(); diff --git a/tests/dmd/compilable/ctests2.c b/tests/dmd/compilable/ctests2.c index 8b8ca96285a..d01fa7df746 100644 --- a/tests/dmd/compilable/ctests2.c +++ b/tests/dmd/compilable/ctests2.c @@ -190,3 +190,8 @@ const typeof(testTypeofA) testTypeofB = 0; _Static_assert(sizeof(testTypeofB) == sizeof(short), "17"); /*************************************************/ + +// https://issues.dlang.org/show_bug.cgi?id=23752 +void *c23752 = &*((void*)(0)); + +/*************************************************/ From 935fa130b7cff3f5a90e8690124b53c40099cee5 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 12 Mar 2023 20:36:33 +0100 Subject: [PATCH 132/177] Bump LDC version / frontend version / Phobos submodule --- CMakeLists.txt | 6 +++--- runtime/phobos | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 64eca1722c1..74734444e7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,10 +111,10 @@ include(GetLinuxDistribution) # # Version information -set(LDC_VERSION "1.32.0") # May be overridden by git hash tag +set(LDC_VERSION "1.33.0") # May be overridden by git hash tag set(DMDFE_MAJOR_VERSION 2) -set(DMDFE_MINOR_VERSION 102) -set(DMDFE_PATCH_VERSION 2) +set(DMDFE_MINOR_VERSION 103) +set(DMDFE_PATCH_VERSION 0) set(DMD_VERSION ${DMDFE_MAJOR_VERSION}.${DMDFE_MINOR_VERSION}.${DMDFE_PATCH_VERSION}) diff --git a/runtime/phobos b/runtime/phobos index 507a0860922..422fece19ab 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit 507a0860922a3636128f2704af3953ef5a1e7e7b +Subproject commit 422fece19ab3224a14f5b737f2cda4b6d1185041 From e0bc077e69da68646f44a46e159c59c1ffe0d713 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 12 Mar 2023 20:45:31 +0100 Subject: [PATCH 133/177] Adapt to renamed VarDeclaration.aliasTuple (from aliassym) --- gen/declarations.cpp | 4 ++-- gen/dibuilder.cpp | 22 ++++++++++------------ gen/llvmhelpers.cpp | 16 ++++++++-------- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/gen/declarations.cpp b/gen/declarations.cpp index a5fe715c556..53620287e8e 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -250,8 +250,8 @@ class CodegenVisitor : public Visitor { decl->ir->setDefined(); // just forward aliases - if (decl->aliassym) { - Logger::println("alias sym"); + if (decl->aliasTuple) { + Logger::println("aliasTuple"); decl->toAlias()->accept(this); return; } diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp index e6cf0bcc9f3..1e817ee3f4a 100644 --- a/gen/dibuilder.cpp +++ b/gen/dibuilder.cpp @@ -515,19 +515,17 @@ void DIBuilder::AddStaticMembers(AggregateDeclaration *ad, DIFile file, visitMembers(tmixin->members); } else if (auto vd = s->isVarDeclaration()) { if (vd->isDataseg()) { - if (vd->aliassym) { // ugly kludge for tuples - if (auto td = vd->aliassym->isTupleDeclaration()) { - if (td->isexp && td->objects) { - Dsymbols tupleVars; - for (auto o : *td->objects) { - if (auto e = isExpression(o)) - if (auto ve = e->isVarExp()) - if (auto vd2 = ve->var->isVarDeclaration()) - if (vd2->isDataseg()) - tupleVars.push(vd2); - } - visitMembers(&tupleVars); + if (auto td = vd->aliasTuple) { // ugly kludge for tuples + if (td->isexp && td->objects) { + Dsymbols tupleVars; + for (auto o : *td->objects) { + if (auto e = isExpression(o)) + if (auto ve = e->isVarExp()) + if (auto vd2 = ve->var->isVarDeclaration()) + if (vd2->isDataseg()) + tupleVars.push(vd2); } + visitMembers(&tupleVars); } } else if (!vd->type->toBasetype()->isTypeNoreturn()) { llvm::MDNode *elem = diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 792f11cc5a7..13c9cd1d433 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -836,9 +836,9 @@ void DtoResolveVariable(VarDeclaration *vd) { // just forward aliases // TODO: Is this required here or is the check in VarDeclaration::codegen // sufficient? - if (vd->aliassym) { - Logger::println("alias sym"); - DtoResolveDsymbol(vd->aliassym); + if (vd->aliasTuple) { + Logger::println("aliasTuple"); + DtoResolveDsymbol(vd->aliasTuple); return; } @@ -872,7 +872,7 @@ void DtoResolveVariable(VarDeclaration *vd) { void DtoVarDeclaration(VarDeclaration *vd) { assert(!vd->isDataseg() && "Statics/globals are handled in DtoDeclarationExp."); - assert(!vd->aliassym && "Aliases are handled in DtoDeclarationExp."); + assert(!vd->aliasTuple && "Aliases are handled in DtoDeclarationExp."); IF_LOG Logger::println("DtoVarDeclaration(vdtype = %s)", vd->type->toChars()); LOG_SCOPE @@ -945,11 +945,11 @@ DValue *DtoDeclarationExp(Dsymbol *declaration) { if (VarDeclaration *vd = declaration->isVarDeclaration()) { Logger::println("VarDeclaration"); - // if aliassym is set, this VarDecl is redone as an alias to another symbol + // if aliasTuple is set, this VarDecl is redone as an alias to another symbol // this seems to be done to rewrite Tuple!(...) v; // as a TupleDecl that contains a bunch of individual VarDecls - if (vd->aliassym) { - return DtoDeclarationExp(vd->aliassym); + if (vd->aliasTuple) { + return DtoDeclarationExp(vd->aliasTuple); } if (vd->storage_class & STCmanifest) { @@ -1013,7 +1013,7 @@ LLValue *DtoRawVarDeclaration(VarDeclaration *var, LLValue *addr) { assert(!var->isDataseg()); // we don't handle aliases either - assert(!var->aliassym); + assert(!var->aliasTuple); IrLocal *irLocal = isIrLocalCreated(var) ? getIrLocal(var) : nullptr; From 0262ec4078f7018250e8db5529f946c259382e24 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 12 Mar 2023 20:53:01 +0100 Subject: [PATCH 134/177] Adapt to removed Dsymbol.addLocalClass() --- gen/moduleinfo.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/gen/moduleinfo.cpp b/gen/moduleinfo.cpp index 37400cde863..853f68b0760 100644 --- a/gen/moduleinfo.cpp +++ b/gen/moduleinfo.cpp @@ -162,9 +162,7 @@ llvm::Constant *buildLocalClasses(Module *m, size_t &count) { const auto classinfoTy = DtoType(getClassInfoType()); ClassDeclarations aclasses; - for (auto s : *m->members) { - s->addLocalClass(&aclasses); - } + getLocalClasses(m, aclasses); std::vector classInfoRefs; for (auto cd : aclasses) { From d5cb7584daea15d3138c0a0ca58f9fcbc0a8869b Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 12 Mar 2023 20:57:12 +0100 Subject: [PATCH 135/177] Fix up genTypeInfo() fwd declaration --- gen/typinf.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gen/typinf.cpp b/gen/typinf.cpp index ff1cb60052c..6abc0ea5f42 100644 --- a/gen/typinf.cpp +++ b/gen/typinf.cpp @@ -58,14 +58,15 @@ #include // in dmd/typinf.d: -void genTypeInfo(Expression *e, const Loc &loc, Type *torig, Scope *sc); +void genTypeInfo(Expression *e, const Loc &loc, Type *torig, Scope *sc, bool genObjCode = true); TypeInfoDeclaration *getOrCreateTypeInfoDeclaration(const Loc &loc, Type *forType) { IF_LOG Logger::println("getOrCreateTypeInfoDeclaration(): %s", forType->toChars()); LOG_SCOPE - genTypeInfo(nullptr, loc, forType, nullptr); + // the `genObjCode` parameter is unused by LDC + genTypeInfo(nullptr, loc, forType, nullptr, false); return forType->vtinfo; } From 8c69a49bba7f5349ae4139b36c69b372200b1742 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 12 Mar 2023 21:32:34 +0100 Subject: [PATCH 136/177] [tiny fix to make ldc2-unittest compile] --- dmd/root/ctfloat.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmd/root/ctfloat.d b/dmd/root/ctfloat.d index 7f081fe1f59..fa56200c81e 100644 --- a/dmd/root/ctfloat.d +++ b/dmd/root/ctfloat.d @@ -318,7 +318,7 @@ version (IN_LLVM) static void printAndCheck(char format, real_t x, string expected) nothrow { char[32] buffer = void; - const length = CTFloat.sprint(buffer.ptr, format, x); + const length = CTFloat.sprint(buffer.ptr, buffer.length, format, x); assert(length < buffer.length); printf("'%s', expected '%.*s'\n", buffer.ptr, cast(int) expected.length, expected.ptr); assert(buffer[0 .. length] == expected); From afa2afae48537937c795bd65107a92bf6d80f6b1 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 12 Mar 2023 22:10:45 +0100 Subject: [PATCH 137/177] [little important merge fix] --- dmd/globals.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dmd/globals.d b/dmd/globals.d index 15b967c0a9b..7c7a7d89d28 100644 --- a/dmd/globals.d +++ b/dmd/globals.d @@ -386,6 +386,8 @@ version (IN_LLVM) {} else /// Cache files read from disk FileManager fileManager; + ErrorSink errorSink; /// where the error messages go + version (IN_LLVM) { const(char)[] ldc_version; @@ -400,8 +402,6 @@ else enum recursionLimit = 500; /// number of recursive template expansions before abort } - ErrorSink errorSink; /// where the error messages go - extern (C++) FileName function(FileName, ref const Loc, out bool, OutBuffer*) preprocess; nothrow: From 28ac391a8742b68984283dc134b1319170595dd9 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 12 Mar 2023 22:17:07 +0100 Subject: [PATCH 138/177] Adopt new CLI option -verror-supplements= --- driver/cl_options.cpp | 6 ++++++ driver/ldmd.cpp | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/driver/cl_options.cpp b/driver/cl_options.cpp index 3c2c8817b3b..a380c2a8729 100644 --- a/driver/cl_options.cpp +++ b/driver/cl_options.cpp @@ -163,6 +163,12 @@ static cl::opt verrorStyle( "standard used by gcc and clang")), cl::init(MessageStyle::digitalmars)); +static cl::opt + verrorSupplements("verror-supplements", cl::ZeroOrMore, + cl::location(global.params.errorSupplementLimit), + cl::desc("Limit the number of supplemental messages for " + "each error (0 means unlimited)")); + static cl::opt warnings( cl::desc("Warnings:"), cl::ZeroOrMore, cl::location(global.params.warnings), cl::values( diff --git a/driver/ldmd.cpp b/driver/ldmd.cpp index 2b71e8a28d2..879fcfea33d 100644 --- a/driver/ldmd.cpp +++ b/driver/ldmd.cpp @@ -259,6 +259,8 @@ Where:\n\ -vdmd print the underlying LDC command line\n\ -verror-style=[digitalmars|gnu]\n\ set the style for file/line number annotations on compiler messages\n\ + -verror-supplements=\n\ + limit the number of supplemental messages for each error (0 means unlimited)\n\ -verrors= limit the number of error messages (0 means unlimited)\n\ -verrors=context show error messages with the context of the erroring source line\n\ -verrors=spec show errors from speculative compiles such as __traits(compiles,...)\n\ @@ -563,7 +565,8 @@ void translateArgs(const llvm::SmallVectorImpl &ldmdArgs, goto Lerror; } } - /* -verror-style + /* -verror-supplements + * -verror-style */ else if (startsWith(p + 1, "target=")) { ldcArgs.push_back(concat("-mtriple=", p + 8)); From 0466088ad2068172b22e96ecbc496056cb4bff7b Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Mon, 13 Mar 2023 17:17:41 +0800 Subject: [PATCH 139/177] Fix Issue 21288 & 10886 - incorrect this pointer (dlang/dmd!14969) --- dmd/expressionsem.d | 71 ++++++++++++++++++++++++-- tests/dmd/compilable/test19295.d | 10 ++++ tests/dmd/compilable/testcorrectthis.d | 37 ++++++++++++++ tests/dmd/fail_compilation/fail61.d | 2 +- tests/dmd/fail_compilation/ice19295.d | 18 ------- tests/dmd/fail_compilation/ice9439.d | 4 +- 6 files changed, 117 insertions(+), 25 deletions(-) create mode 100644 tests/dmd/compilable/test19295.d create mode 100644 tests/dmd/compilable/testcorrectthis.d delete mode 100644 tests/dmd/fail_compilation/ice19295.d diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index d191e9b5af2..c20038f82b5 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -1155,6 +1155,69 @@ L1: return e1; } +/* + * Check whether `outerFunc` and `calledFunc` have the same `this`. + * If `calledFunc` is the member of a base class of the class that contains + * `outerFunc` we consider that they have the same this. + * + * This function is used to test whether `this` needs to be prepended to + * a function call or function symbol. For example: + * + * struct X + * { + * void gun() {} + * } + * struct A + * { + * void fun() {} + * void sun() + * { + * fun(); + * X.gun(); // error + * } + * } + * + * When `fun` is called, `outerfunc` = `sun` and `calledFunc = `fun`. + * `sun` is a member of `A` and `fun` is also a member of `A`, therefore + * `this` can be prepended to `fun`. When `gun` is called (it will result + * in an error, but that is not relevant here), which is a member of `X`, + * no `this` is needed because the outer function does not have the same + * `this` as `gun`. + * + * Returns: + * `true` if outerFunc and calledFunc may use the same `this` pointer. + * `false` otherwise. + */ +private bool haveSameThis(FuncDeclaration outerFunc, FuncDeclaration calledFunc) +{ + auto thisAd = outerFunc.isMemberLocal(); + if (!thisAd) + return false; + + auto requiredAd = calledFunc.isMemberLocal(); + if (!requiredAd) + return false; + + if (thisAd == requiredAd) + return true; + + // outerfunc is the member of a base class that contains calledFunc, + // then we consider that they have the same this. + auto cd = requiredAd.isClassDeclaration(); + if (!cd) + return false; + + if (cd.isBaseOf2(thisAd.isClassDeclaration())) + return true; + + // if outerfunc is the member of a nested aggregate, then let + // getRightThis take care of this. + if (thisAd.isNested()) + return true; + + return false; +} + /*************************************** * Pull out any properties. */ @@ -5209,7 +5272,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (exp.f.checkNestedReference(sc, exp.loc)) return setError(); - if (hasThis(sc)) + auto memberFunc = hasThis(sc); + if (memberFunc && haveSameThis(memberFunc, exp.f)) { // Supply an implicit 'this', as in // this.ident @@ -6892,8 +6956,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor AggregateDeclaration ad = f.isMemberLocal(); if (f.needThis()) e.e1 = getRightThis(e.loc, sc, ad, e.e1, f); - if (e.e1.op == EXP.error) - return setError(); if (f.type.ty == Tfunction) { @@ -7207,7 +7269,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } if (f.needThis()) { - if (hasThis(sc)) + auto memberFunc = hasThis(sc); + if (memberFunc && haveSameThis(memberFunc, f)) { /* Should probably supply 'this' after overload resolution, * not before. diff --git a/tests/dmd/compilable/test19295.d b/tests/dmd/compilable/test19295.d new file mode 100644 index 00000000000..a32a317c08e --- /dev/null +++ b/tests/dmd/compilable/test19295.d @@ -0,0 +1,10 @@ +struct S1(T...) { + auto fun() { + static assert(__traits(compiles, &T[0])); + } +} + +struct S2 { + void gun() {} + S1!gun overloaded; +} diff --git a/tests/dmd/compilable/testcorrectthis.d b/tests/dmd/compilable/testcorrectthis.d new file mode 100644 index 00000000000..3adc0628236 --- /dev/null +++ b/tests/dmd/compilable/testcorrectthis.d @@ -0,0 +1,37 @@ +// https://issues.dlang.org/show_bug.cgi?id=10886 + +struct A +{ + @property int foo() { return 0; } + int bar() { return 0; } +} + +struct B +{ + void bar() + { + alias f = typeof(A.foo); // NG + alias b = typeof(A.bar); // ok + } +} + +// https://issues.dlang.org/show_bug.cgi?id=21288 + +struct XA +{ + int p; +} + +struct XB +{ + XA a() { return XA.init; } + alias a this; +} + +struct XC +{ + void foo() + { + static assert(XB.p.stringof == "p"); // Error: this for s needs to be type B not type C + } +} diff --git a/tests/dmd/fail_compilation/fail61.d b/tests/dmd/fail_compilation/fail61.d index 90c3b39977d..1386bd664a3 100644 --- a/tests/dmd/fail_compilation/fail61.d +++ b/tests/dmd/fail_compilation/fail61.d @@ -4,7 +4,7 @@ TEST_OUTPUT: fail_compilation/fail61.d(22): Error: no property `B` for type `fail61.A.B` fail_compilation/fail61.d(23): Error: no property `B` for type `fail61.A.B` fail_compilation/fail61.d(32): Error: no property `A2` for type `fail61.B2` -fail_compilation/fail61.d(41): Error: `this` for `foo` needs to be type `B3` not type `fail61.C3` +fail_compilation/fail61.d(41): Error: need `this` for `foo` of type `void()` --- */ diff --git a/tests/dmd/fail_compilation/ice19295.d b/tests/dmd/fail_compilation/ice19295.d deleted file mode 100644 index a92f5f8384c..00000000000 --- a/tests/dmd/fail_compilation/ice19295.d +++ /dev/null @@ -1,18 +0,0 @@ -/* -TEST_OUTPUT: ---- -fail_compilation/ice19295.d(11): Error: `this` for `gun` needs to be type `S2` not type `S1!(gun)` -fail_compilation/ice19295.d(11): while evaluating `pragma(msg, &gun)` -fail_compilation/ice19295.d(17): Error: template instance `ice19295.S1!(gun)` error instantiating ---- -*/ -struct S1(T...) { - auto fun() { - pragma(msg, &T[0]); - } -} - -struct S2 { - void gun() {} - S1!gun overloaded; -} diff --git a/tests/dmd/fail_compilation/ice9439.d b/tests/dmd/fail_compilation/ice9439.d index a9e70083802..5b2a8b12031 100644 --- a/tests/dmd/fail_compilation/ice9439.d +++ b/tests/dmd/fail_compilation/ice9439.d @@ -1,8 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/ice9439.d(12): Error: `this` for `foo` needs to be type `Derived` not type `ice9439.Base` -fail_compilation/ice9439.d(12): while evaluating: `static assert((__error).foo())` +fail_compilation/ice9439.d(12): Error: need `this` for `foo` of type `int()` +fail_compilation/ice9439.d(12): while evaluating: `static assert(foo())` fail_compilation/ice9439.d(19): Error: template instance `ice9439.Base.boo!(foo)` error instantiating --- */ From 33216304f534fa822f4ec356e53fa9773478747e Mon Sep 17 00:00:00 2001 From: Dennis Date: Mon, 13 Mar 2023 10:23:39 +0100 Subject: [PATCH 140/177] Fix 23767 - ImportC: ternary with null constant has wrong pointer type (dlang/dmd!14980) --- dmd/expressionsem.d | 23 +++++++++++++++++++++++ tests/dmd/compilable/ctests2.c | 11 +++++++++++ 2 files changed, 34 insertions(+) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index c20038f82b5..632ea11cdc0 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -12382,6 +12382,29 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor Type t1 = exp.e1.type; Type t2 = exp.e2.type; + + // https://issues.dlang.org/show_bug.cgi?id=23767 + // `cast(void*) 0` should be treated as `null` so the ternary expression + // gets the pointer type of the other branch + if (sc.flags & SCOPE.Cfile) + { + static void rewriteCNull(ref Expression e, ref Type t) + { + if (!t.isTypePointer()) + return; + if (auto ie = e.optimize(WANTvalue).isIntegerExp()) + { + if (ie.getInteger() == 0) + { + e = new NullExp(e.loc, Type.tnull); + t = Type.tnull; + } + } + } + rewriteCNull(exp.e1, t1); + rewriteCNull(exp.e2, t2); + } + if (t1.ty == Tnoreturn) { exp.type = t2; diff --git a/tests/dmd/compilable/ctests2.c b/tests/dmd/compilable/ctests2.c index d01fa7df746..16da88ba378 100644 --- a/tests/dmd/compilable/ctests2.c +++ b/tests/dmd/compilable/ctests2.c @@ -195,3 +195,14 @@ _Static_assert(sizeof(testTypeofB) == sizeof(short), "17"); void *c23752 = &*((void*)(0)); /*************************************************/ + +// https://issues.dlang.org/show_bug.cgi?id=23767 +const int arr23767[4]; +void f23767(void) +{ + int x = *(0 ? (void*)0 : arr23767); + int y = *(1 ? arr23767 : (void*)(3-3)); + int* p = (1 ? (void*)0 : (void*)0); +} + +/*************************************************/ From 2cb06287fd4658a4dc6ce2101e4a2dceec0c8b52 Mon Sep 17 00:00:00 2001 From: Geod24 Date: Wed, 15 Mar 2023 16:10:22 +0100 Subject: [PATCH 141/177] Fix 23781: Segmentation fault on taking the address of a ref return at CTFE --- dmd/dinterpret.d | 2 +- tests/dmd/fail_compilation/ice23781.d | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/fail_compilation/ice23781.d diff --git a/dmd/dinterpret.d b/dmd/dinterpret.d index 7ad9908b3f0..e6ef704be86 100644 --- a/dmd/dinterpret.d +++ b/dmd/dinterpret.d @@ -2036,7 +2036,7 @@ public: } auto er = interpret(e.e1, istate, CTFEGoal.LValue); if (auto ve = er.isVarExp()) - if (ve.var == istate.fd.vthis) + if (istate && ve.var == istate.fd.vthis) er = interpret(er, istate); if (exceptionOrCant(er)) diff --git a/tests/dmd/fail_compilation/ice23781.d b/tests/dmd/fail_compilation/ice23781.d new file mode 100644 index 00000000000..7adc11607db --- /dev/null +++ b/tests/dmd/fail_compilation/ice23781.d @@ -0,0 +1,10 @@ +/** +TEST_OUTPUT: +--- +fail_compilation/ice23781.d(10): Error: variable `b` cannot be read at compile time +--- +**/ +struct Bar { int i; } +ref const(Bar) func1 (const return ref Bar b) { return b; } +immutable E1 = Bar(); +enum E2 = &E1.func1(); From c70428ff71960c87c19819b661a159452d59bef2 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 14 Mar 2023 14:30:41 -0700 Subject: [PATCH 142/177] fix Issue 23778 - Code generator fails to handle __c_complex_real properly for Windows --- tests/dmd/runnable/complex3.d | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/dmd/runnable/complex3.d diff --git a/tests/dmd/runnable/complex3.d b/tests/dmd/runnable/complex3.d new file mode 100644 index 00000000000..7167b0b6ff8 --- /dev/null +++ b/tests/dmd/runnable/complex3.d @@ -0,0 +1,31 @@ +// https://issues.dlang.org/show_bug.cgi?id=23778 + + +enum __c_long_double : double; + +alias __c_long_double c_long_double; + +struct _Complex +{ + c_long_double re; + c_long_double im; +} + +version (all) // bug to test +{ + enum __c_complex_real : _Complex; + alias c_complex_real = __c_complex_real; +} +else // works + enum c_complex_real : _Complex; + +c_complex_real toNative2(real re, real im) +{ + return c_complex_real(re, im); +} + +void main() +{ + c_complex_real n = toNative2(123, 456); + assert(123 == n.re && 456 == n.im); +} From 3a5e778b4e2bc83742659aec7694ff6238871c1e Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Thu, 16 Mar 2023 18:20:08 +0100 Subject: [PATCH 143/177] Fix missing directives in testsuite --- tests/dmd/compilable/test22674.d | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/dmd/compilable/test22674.d b/tests/dmd/compilable/test22674.d index c9076fae14d..00750b0108f 100644 --- a/tests/dmd/compilable/test22674.d +++ b/tests/dmd/compilable/test22674.d @@ -1,4 +1,5 @@ // https://issues.dlang.org/show_bug.cgi?id=22674 +// EXTRA_FILES: imports/cimports2a.i imports/cimports2b.i import imports.cimports2a; import imports.cimports2b; From ce1ab852f62d328e267f84c5bcf7cd21b0617a6c Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Thu, 16 Mar 2023 18:23:04 +0100 Subject: [PATCH 144/177] dmd.gluelayer: Add toObjFile declaration for version IN_GCC --- dmd/gluelayer.d | 1 + 1 file changed, 1 insertion(+) diff --git a/dmd/gluelayer.d b/dmd/gluelayer.d index 4a022ec3d11..7b52eff663d 100644 --- a/dmd/gluelayer.d +++ b/dmd/gluelayer.d @@ -78,6 +78,7 @@ else version (IN_GCC) extern (C++) { Statement asmSemantic(AsmStatement s, Scope* sc); + void toObjFile(Dsymbol ds, bool multiobj); } // stubs From f95421de48e27efa16f0d2180459fea3351077e6 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Thu, 16 Mar 2023 18:07:18 +0100 Subject: [PATCH 145/177] dmd.target: Remove stackAlign from C++ headers --- dmd/frontend.h | 1 - dmd/target.d | 2 +- dmd/target.h | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/dmd/frontend.h b/dmd/frontend.h index 5da2e4bade8..480b91922c2 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -8137,7 +8137,6 @@ struct Target final bool isCalleeDestroyingArgs(TypeFunction* tf); bool libraryObjectMonitors(FuncDeclaration* fd, Statement* fbody); bool supportsLinkerDirective() const; - uint32_t stackAlign(); Target() : os((OS)1u), osMajor(0u), diff --git a/dmd/target.d b/dmd/target.d index 461e1e95ce4..6741147befa 100644 --- a/dmd/target.d +++ b/dmd/target.d @@ -1141,7 +1141,7 @@ extern (C++) struct Target * Returns: * alignment of the stack */ - extern (C++) uint stackAlign() + extern (D) uint stackAlign() { return isXmmSupported() ? 16 : (is64bit ? 8 : 4); } diff --git a/dmd/target.h b/dmd/target.h index 5bd5162d8d4..ef2c09d4147 100644 --- a/dmd/target.h +++ b/dmd/target.h @@ -208,7 +208,6 @@ struct Target bool isCalleeDestroyingArgs(TypeFunction* tf); bool libraryObjectMonitors(FuncDeclaration *fd, Statement *fbody); bool supportsLinkerDirective() const; - unsigned stackAlign(); void addPredefinedGlobalIdentifiers() const; }; From 127c2a628879758f4c65c5c155b6d8f9e77b5e6f Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Thu, 16 Mar 2023 18:15:50 +0100 Subject: [PATCH 146/177] dmd/declaration.h: Align header with D definition --- dmd/declaration.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmd/declaration.h b/dmd/declaration.h index 20accc82ec6..cd4155d0fbb 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -688,7 +688,7 @@ class FuncDeclaration : public Declaration BaseClass *overrideInterface(); bool overloadInsert(Dsymbol *s) override; bool inUnittest(); - MATCH leastAsSpecialized(FuncDeclaration *g, Identifiers *names = nullptr); + MATCH leastAsSpecialized(FuncDeclaration *g, Identifiers *names); LabelDsymbol *searchLabel(Identifier *ident, const Loc &loc); int getLevel(FuncDeclaration *fd, int intypeof); // lexical nesting level difference int getLevelAndCheck(const Loc &loc, Scope *sc, FuncDeclaration *fd); From 289b6a48376c59407a1b7877b005205ef1f3bcf7 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Fri, 17 Mar 2023 13:00:36 +0100 Subject: [PATCH 147/177] core.sys.freebsd.config: Update __FreeBSD_version with new values (dlang/dmd!14997) --- runtime/druntime/src/core/sys/freebsd/config.d | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/runtime/druntime/src/core/sys/freebsd/config.d b/runtime/druntime/src/core/sys/freebsd/config.d index 5e3129e2422..9d502e52e32 100644 --- a/runtime/druntime/src/core/sys/freebsd/config.d +++ b/runtime/druntime/src/core/sys/freebsd/config.d @@ -14,8 +14,9 @@ public import core.sys.posix.config; // NOTE: When adding newer versions of FreeBSD, verify all current versioned // bindings are still compatible with the release. - version (FreeBSD_13) enum __FreeBSD_version = 1300000; -else version (FreeBSD_12) enum __FreeBSD_version = 1202000; + version (FreeBSD_14) enum __FreeBSD_version = 1400000; +else version (FreeBSD_13) enum __FreeBSD_version = 1301000; +else version (FreeBSD_12) enum __FreeBSD_version = 1203000; else version (FreeBSD_11) enum __FreeBSD_version = 1104000; else version (FreeBSD_10) enum __FreeBSD_version = 1004000; else version (FreeBSD_9) enum __FreeBSD_version = 903000; From cfef5002da73631e7443ffdb3cf1bb96838bda7c Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Sat, 18 Mar 2023 11:42:00 +0100 Subject: [PATCH 148/177] Fix 23792 - lexer warns about preprocessor inside token strings --- dmd/lexer.d | 4 ++-- tests/dmd/fail_compilation/cerrors.d | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/dmd/lexer.d b/dmd/lexer.d index c9ed35ffa6d..7bf92c6b297 100644 --- a/dmd/lexer.d +++ b/dmd/lexer.d @@ -2692,13 +2692,13 @@ class Lexer poundLine(n, false); return true; } - else + else if (!inTokenStringConstant) { const locx = loc(); eSink.warning(locx, "C preprocessor directive `#%s` is not supported", n.ident.toChars()); } } - else if (n.value == TOK.if_) + else if (n.value == TOK.if_ && !inTokenStringConstant) { error("C preprocessor directive `#if` is not supported, use `version` or `static if`"); } diff --git a/tests/dmd/fail_compilation/cerrors.d b/tests/dmd/fail_compilation/cerrors.d index 3d69d415e2b..862e27aeb98 100644 --- a/tests/dmd/fail_compilation/cerrors.d +++ b/tests/dmd/fail_compilation/cerrors.d @@ -13,3 +13,9 @@ fail_compilation/cerrors.d(15): Error: declaration expected, not `#` void test(wchar_t u); #endif + +// https://issues.dlang.org/show_bug.cgi?id=23792 +enum s1 = q{ +#if 1 +#include +}; From 5fddf8072265c69998c79879b555692c2b4a0cc3 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Tue, 21 Mar 2023 16:49:26 +0200 Subject: [PATCH 149/177] Fix Issue 23783 - -preview=nosharedaccess does not detect comparison of shared data --- dmd/expressionsem.d | 3 +++ tests/dmd/fail_compilation/shared.d | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 632ea11cdc0..6948db57d42 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -12158,6 +12158,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (!needsArrayLowering) { + // https://issues.dlang.org/show_bug.cgi?id=23783 + if (exp.e1.checkSharedAccess(sc) || exp.e2.checkSharedAccess(sc)) + return setError(); if (auto e = typeCombine(exp, sc)) { result = e; diff --git a/tests/dmd/fail_compilation/shared.d b/tests/dmd/fail_compilation/shared.d index afdea64c744..8b94a7981a1 100644 --- a/tests/dmd/fail_compilation/shared.d +++ b/tests/dmd/fail_compilation/shared.d @@ -259,3 +259,22 @@ void test_casting_safe() @safe auto x1 = cast(int*)s; auto x2 = cast(const(shared(int*)))s; } + +#line 3100 + +// https://issues.dlang.org/show_bug.cgi?id=23783 + +/* +TEST_OUTPUT: +--- +fail_compilation/shared.d(3114): Error: direct access to shared `x` is not allowed, see `core.atomic` +fail_compilation/shared.d(3115): Error: direct access to shared `x` is not allowed, see `core.atomic` +--- +*/ + +void test23783() +{ + shared int x = 3; + assert(x == 3); + bool b = x == 3; +} From 4393c2ce765f40b246c0dd60c04c8a3e9f076d99 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Wed, 22 Mar 2023 16:47:31 +0800 Subject: [PATCH 150/177] Fix Issue 23790 - Cannot use cas on member variable with -preview=nosharedaccess (dlang/dmd!15016) --- dmd/expressionsem.d | 13 ++++++++++--- tests/dmd/compilable/shared.d | 12 ++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 6948db57d42..1f4f57b1f38 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -13412,9 +13412,16 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false) //printf("dotvarexp = %s\n", e.toChars()); if (e.type.isShared()) { - // / https://issues.dlang.org/show_bug.cgi?id=22626 - if (e.e1.isThisExp() && sc.func && sc.func.isSynchronized()) - return false; + if (e.e1.isThisExp()) + { + // https://issues.dlang.org/show_bug.cgi?id=22626 + if (sc.func && sc.func.isSynchronized()) + return false; + + // https://issues.dlang.org/show_bug.cgi?id=23790 + if (e.e1.type.isTypeStruct()) + return false; + } auto fd = e.var.isFuncDeclaration(); const sharedFunc = fd && fd.type.isShared; diff --git a/tests/dmd/compilable/shared.d b/tests/dmd/compilable/shared.d index 695083a5476..bd5c7ffe957 100644 --- a/tests/dmd/compilable/shared.d +++ b/tests/dmd/compilable/shared.d @@ -130,3 +130,15 @@ void main() { auto b = new shared Class(); } + +// https://issues.dlang.org/show_bug.cgi?id=23790 +bool cas(shared bool*, bool, bool) { return true; } + +struct Argh +{ + bool locked; + void lock() shared + { + while(!cas(&locked, false, true)) {} + } +} From c6bc923bc45da5968d00435fce5ef7f14f0db0f0 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Wed, 22 Mar 2023 23:37:15 +0800 Subject: [PATCH 151/177] Fix Issue 20908 - -preview=nosharedaccess requires zero-initializion for aggregates (dlang/dmd!15023) --- dmd/expressionsem.d | 6 ++++ tests/dmd/compilable/shared.d | 54 ++++++++++++++++++++++------------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 1f4f57b1f38..45dcb9739f2 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -13375,6 +13375,12 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false) bool visitVar(VarExp e) { + // https://issues.dlang.org/show_bug.cgi?id=20908 + // direct access to init symbols is ok as they + // cannot be modified. + if (e.var.isSymbolDeclaration()) + return false; + // https://issues.dlang.org/show_bug.cgi?id=22626 // Synchronized functions don't need to use core.atomic // when accessing `this`. diff --git a/tests/dmd/compilable/shared.d b/tests/dmd/compilable/shared.d index bd5c7ffe957..647910ecf16 100644 --- a/tests/dmd/compilable/shared.d +++ b/tests/dmd/compilable/shared.d @@ -11,34 +11,48 @@ ref shared(int) f(return shared ref int y) } // https://issues.dlang.org/show_bug.cgi?id=20908 +struct S +{ + int i = 2; +} + +union U +{ + int i = 1; + bool b; +} + void test20908() { - // shared locals (or struct members) should be able to be initialised: - shared int x; + // shared locals (or struct members) should be able to be initialised: + shared int x; - ref shared(int) fun() - { - static shared(int) val; + ref shared(int) fun() + { + static shared(int) val; - // return by reference - return val; - } + // return by reference + return val; + } + + ref shared(int) fun2() + { + static shared(int)* val; - ref shared(int) fun2() - { - static shared(int)* val; + // transfer pointer to reference + return *val; + } - // transfer pointer to reference - return *val; - } + ref shared(int) fun3() + { + static shared(int)*** val; - ref shared(int) fun3() - { - static shared(int)*** val; + // Multiple indirections + return ***val; + } - // Multiple indirections - return ***val; - } + shared S s; + shared U u; } // Simple tests for `DotVarExp` From 43af919222d70a28ce39058fced56490a1f81319 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Thu, 23 Mar 2023 20:04:23 +0800 Subject: [PATCH 152/177] Fix Issue 23799 - Link error with -betterC (dlang/dmd!15028) --- dmd/statementsem.d | 5 ++++- tests/dmd/compilable/test23799.d | 37 ++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/compilable/test23799.d diff --git a/dmd/statementsem.d b/dmd/statementsem.d index bbaee8e6152..65de6dcf105 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -1941,7 +1941,6 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor } if (checkNonAssignmentArrayOp(ifs.condition)) ifs.condition = ErrorExp.get(); - ifs.condition = checkGC(scd, ifs.condition); // Convert to boolean after declaring prm so this works: // if (S prm = S()) {} @@ -1953,6 +1952,10 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor // This feature allows a limited form of conditional compilation. ifs.condition = ifs.condition.optimize(WANTvalue); + // checkGC after optimizing the condition so that + // compile time constants are reduced. + ifs.condition = checkGC(scd, ifs.condition); + // Save 'root' of two branches (then and else) at the point where it forks CtorFlow ctorflow_root = scd.ctorflow.clone(); diff --git a/tests/dmd/compilable/test23799.d b/tests/dmd/compilable/test23799.d new file mode 100644 index 00000000000..007351602a3 --- /dev/null +++ b/tests/dmd/compilable/test23799.d @@ -0,0 +1,37 @@ +// https://issues.dlang.org/show_bug.cgi?id=23799 + +// REQUIRED_ARGS: -betterC + +struct Data +{ + Data[] range; + string test; +} + +Data[] foo() +{ + Data[] ret; + if (__ctfe) + { + Data tmp; + tmp.range ~= Data.init; + ret ~= tmp; + } + return ret; +} + +void func(Data dat)() +{ +} + +void bar(Data dat)() +{ + if (dat.test.length) + func!(dat.range[0])(); +} + +extern (C) void main() +{ + static immutable data = foo(); + bar!(data[0])(); +} From 14de74b2095fe878c80a7c2f332e0c9f34f88435 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 25 Mar 2023 17:30:23 +0100 Subject: [PATCH 153/177] Re-enable subtest in runnable/xtest46.d As this LLVM bug has apparently been fixed sometime. --- tests/dmd/runnable/xtest46.d | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/dmd/runnable/xtest46.d b/tests/dmd/runnable/xtest46.d index cbe5feb77e1..e57f52f6578 100644 --- a/tests/dmd/runnable/xtest46.d +++ b/tests/dmd/runnable/xtest46.d @@ -3120,14 +3120,12 @@ template map(fun...) void test139() { - /* LDC: FIXME - https://github.com/ldc-developers/ldc/issues/2361 double[] x; alias typeof(map!"a"(x)) T; T a = void; auto b = map!"a"(x); auto c = [map!"a"(x)]; T[3] d = void; - */ } From 5c90eba236b40060e3d754c20fc3f32f00c17574 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 25 Mar 2023 17:34:48 +0100 Subject: [PATCH 154/177] Fix lit-test codegen/const_struct_export.d Looks like `VarDeclaration.isImportedSymbol()` was fixed in this regard. --- tests/codegen/const_struct_export.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/codegen/const_struct_export.d b/tests/codegen/const_struct_export.d index 6cfb48620b8..d5c68f2847a 100644 --- a/tests/codegen/const_struct_export.d +++ b/tests/codegen/const_struct_export.d @@ -8,7 +8,7 @@ export void exportedFunction() {} export void importedFunction(); export immutable int exportedVariable = 1; -export immutable int importedVariable; +export extern immutable int importedVariable; void foo () { immutable auto exportedFuncs = [ &exportedFunction, &exportedFunction ]; From 145cf715c0bbce88b13ec70f1021edfd1ff3d07d Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 25 Mar 2023 17:48:51 +0100 Subject: [PATCH 155/177] ImportC: Lower AssertExp to C assert Fixes runnable/testcheck.c. --- gen/toir.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index 6a2c00052e0..265a12a35bf 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1754,7 +1754,8 @@ class ToElemVisitor : public Visitor { */ DValue *msg = e->msg ? toElemDtor(e->msg) : nullptr; Module *module = p->func()->decl->getModule(); - if (global.params.checkAction == CHECKACTION_C) { + if (global.params.checkAction == CHECKACTION_C || + module->filetype == FileType::c) { LLValue *cMsg = msg ? DtoArrayPtr( msg) // assuming `msg` is null-terminated, like DMD From 5dd0092dc664425e9f21ff7be4ebe8ea400c8132 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 25 Mar 2023 17:58:37 +0100 Subject: [PATCH 156/177] Deprecate -dip25 (following DMD) Fixes fail_compilation/dip25flag.d. --- driver/main.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/driver/main.cpp b/driver/main.cpp index bdcfd764e17..6d1c3441eb0 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -439,10 +439,8 @@ void parseCommandLine(Strings &sourceFiles) { if (global.params.useDIP1000 == FeatureState::enabled) // DIP1000 implies DIP25 global.params.useDIP25 = FeatureState::enabled; // legacy -dip25 option - if (global.params.useDIP25 == FeatureState::default_ && - opts::useDIP25.getNumOccurrences()) { - global.params.useDIP25 = - opts::useDIP25 ? FeatureState::enabled : FeatureState::disabled; + if (opts::useDIP25.getNumOccurrences()) { + deprecation(Loc(), "`-dip25` no longer has any effect"); } global.params.output_o = From b796588e08aa8c14c81dee945e8dc7a20bcd3e9f Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 25 Mar 2023 18:09:21 +0100 Subject: [PATCH 157/177] Use new FuncDeclaration::skipCodegen() Another betterC hack, hooray! - Fixes compilable/test23606.d. --- gen/declarations.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen/declarations.cpp b/gen/declarations.cpp index 53620287e8e..040bb862e58 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -284,7 +284,7 @@ class CodegenVisitor : public Visitor { void visit(FuncDeclaration *decl) override { // don't touch function aliases, they don't contribute any new symbols - if (!decl->isFuncAliasDeclaration()) { + if (!decl->skipCodegen() && !decl->isFuncAliasDeclaration()) { DtoDefineFunction(decl); } } From 6f549b7f27b29456be23375595b2f1cdae80ccb1 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 25 Mar 2023 18:23:18 +0100 Subject: [PATCH 158/177] Disable some new dmd-testsuite ImportC tests requiring a preprocessor Wrt. #3825. --- tests/dmd/compilable/stdcheaders.c | 1 + tests/dmd/compilable/test22809.c | 2 ++ tests/dmd/compilable/test23583.c | 2 +- tests/dmd/compilable/test23616.c | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/dmd/compilable/stdcheaders.c b/tests/dmd/compilable/stdcheaders.c index 90c0339a841..5fef0eeff78 100644 --- a/tests/dmd/compilable/stdcheaders.c +++ b/tests/dmd/compilable/stdcheaders.c @@ -1,5 +1,6 @@ /* Do a smoke test of the C Standard headers. * Many platforms do not support all the C Standard headers. + * DISABLED: LDC // FIXME: needs preprocessor */ #include diff --git a/tests/dmd/compilable/test22809.c b/tests/dmd/compilable/test22809.c index 68752d50a04..fcf3fbf4c4b 100644 --- a/tests/dmd/compilable/test22809.c +++ b/tests/dmd/compilable/test22809.c @@ -15,6 +15,7 @@ int y = ((size_t)((char *)&((struct Foo *)1)->x - (char *)1)); _Static_assert(((size_t)((char *)&((struct Foo *)0)->y - (char *)0))==4, ""); +/* LDC FIXME: needs preprocessor (for including importc.h) // https://issues.dlang.org/show_bug.cgi?id=23584 int foo(float bar) @@ -27,3 +28,4 @@ void test23584() int i = foo(3.5); _Static_assert(foo(3.5) == 0x40600000, "1"); } +*/ diff --git a/tests/dmd/compilable/test23583.c b/tests/dmd/compilable/test23583.c index 53581790108..60ca47cab94 100644 --- a/tests/dmd/compilable/test23583.c +++ b/tests/dmd/compilable/test23583.c @@ -1,4 +1,4 @@ - +// DISABLED: LDC // FIXME: needs preprocessor // https://issues.dlang.org/show_bug.cgi?id=23580 // https://issues.dlang.org/show_bug.cgi?id=23581 // https://issues.dlang.org/show_bug.cgi?id=23582 diff --git a/tests/dmd/compilable/test23616.c b/tests/dmd/compilable/test23616.c index 4b9ebca4fe8..019cea90afc 100644 --- a/tests/dmd/compilable/test23616.c +++ b/tests/dmd/compilable/test23616.c @@ -1,3 +1,4 @@ +// DISABLED: LDC // FIXME: needs preprocessor // https://issues.dlang.org/show_bug.cgi?id=23616 #if __has_extension(gnu_asm) From 5f942893d8bd389380e4f1b434d79e3885ddf954 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 26 Mar 2023 00:41:23 +0100 Subject: [PATCH 159/177] Phobos: Merge latest upstream stable --- runtime/phobos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/phobos b/runtime/phobos index aa8d7c11b89..c8f9cbc76b8 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit aa8d7c11b89e5f727a844a79f585f967b18492c5 +Subproject commit c8f9cbc76b8c538044a0d77356f91cd2d1aa0b18 From c2b947edeffcebd19b5e662fb2acd1c6df76f393 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 26 Mar 2023 01:43:54 +0100 Subject: [PATCH 160/177] Adapt to newly-non-optional parameter in C++ frontend header --- ir/irclass.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ir/irclass.cpp b/ir/irclass.cpp index 6eda5106614..88e54d089db 100644 --- a/ir/irclass.cpp +++ b/ir/irclass.cpp @@ -246,8 +246,8 @@ LLConstant *IrClass::getVtblInit() { if (fd2->isFuture()) { continue; } - if (fd->leastAsSpecialized(fd2) != MATCH::nomatch || - fd2->leastAsSpecialized(fd) != MATCH::nomatch) { + if (fd->leastAsSpecialized(fd2, nullptr) != MATCH::nomatch || + fd2->leastAsSpecialized(fd, nullptr) != MATCH::nomatch) { TypeFunction *tf = static_cast(fd->type); if (tf->ty == TY::Tfunction) { cd->error("use of `%s%s` is hidden by `%s`; use `alias %s = " From b6695cddda83d6df2892dcf58585e7aeddc8ebe5 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Tue, 4 Apr 2023 16:35:56 +0800 Subject: [PATCH 161/177] Fix Issue 23816 - Typing invalid mnemonic in asm{} block segfaults (dlang/dmd!15060) --- tests/dmd/fail_compilation/fail23816.d | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tests/dmd/fail_compilation/fail23816.d diff --git a/tests/dmd/fail_compilation/fail23816.d b/tests/dmd/fail_compilation/fail23816.d new file mode 100644 index 00000000000..574a7122eb9 --- /dev/null +++ b/tests/dmd/fail_compilation/fail23816.d @@ -0,0 +1,16 @@ +// https://issues.dlang.org/show_bug.cgi?id=23816 + +/* +TEST_OUTPUT: +--- +fail_compilation/fail23816.d(14): Error: opcode expected, not `NOP` +--- +*/ + +void main() +{ + asm + { + NOP; + } +} From c0107c662798f9cbcaf229533d095bd6d23089e5 Mon Sep 17 00:00:00 2001 From: Dennis Date: Thu, 6 Apr 2023 16:03:04 +0200 Subject: [PATCH 162/177] Deprecate invalid `#` tokens in `q{}` strings (dlang/dmd!15002) --- dmd/lexer.d | 30 ++++++++++++++++------ tests/dmd/fail_compilation/cerrors.d | 10 +++++--- tests/dmd/unit/lexer/diagnostic_reporter.d | 21 --------------- 3 files changed, 28 insertions(+), 33 deletions(-) diff --git a/dmd/lexer.d b/dmd/lexer.d index 7bf92c6b297..f0f7872c2b2 100644 --- a/dmd/lexer.d +++ b/dmd/lexer.d @@ -2664,14 +2664,19 @@ class Lexer eSink.error(loc, format, args); } - final void deprecation(const(char)* format) + void deprecation(T...)(const ref Loc loc, const(char)* format, T args) { - eSink.deprecation(token.loc, format); + eSink.deprecation(loc, format, args); } - final void deprecationSupplemental(const(char)* format) + void deprecation(T...)(const(char)* format, T args) { - eSink.deprecationSupplemental(token.loc, format); + eSink.deprecation(token.loc, format, args); + } + + void deprecationSupplemental(T...)(const(char)* format, T args) + { + eSink.deprecationSupplemental(token.loc, format, args); } /*************************************** @@ -2692,15 +2697,24 @@ class Lexer poundLine(n, false); return true; } - else if (!inTokenStringConstant) + else { const locx = loc(); - eSink.warning(locx, "C preprocessor directive `#%s` is not supported", n.ident.toChars()); + // @@@DEPRECATED_2.103@@@ + // Turn into an error in 2.113 + if (inTokenStringConstant) + deprecation(locx, "token string requires valid D tokens, not `#%s`", n.ident.toChars()); + else + error(locx, "C preprocessor directive `#%s` is not supported", n.ident.toChars()); } } - else if (n.value == TOK.if_ && !inTokenStringConstant) + else if (n.value == TOK.if_) { - error("C preprocessor directive `#if` is not supported, use `version` or `static if`"); + const locx = loc(); + if (inTokenStringConstant) + error(locx, "token string requires valid D tokens, not `#if`"); + else + error(locx, "C preprocessor directive `#if` is not supported, use `version` or `static if`"); } return false; } diff --git a/tests/dmd/fail_compilation/cerrors.d b/tests/dmd/fail_compilation/cerrors.d index 862e27aeb98..db306c1f213 100644 --- a/tests/dmd/fail_compilation/cerrors.d +++ b/tests/dmd/fail_compilation/cerrors.d @@ -1,10 +1,12 @@ /* REQUIRED_ARGS: -wi TEST_OUTPUT: --- -fail_compilation/cerrors.d(11): Error: C preprocessor directive `#if` is not supported, use `version` or `static if` -fail_compilation/cerrors.d(11): Error: declaration expected, not `#` -fail_compilation/cerrors.d(15): Warning: C preprocessor directive `#endif` is not supported -fail_compilation/cerrors.d(15): Error: declaration expected, not `#` +fail_compilation/cerrors.d(13): Error: C preprocessor directive `#if` is not supported, use `version` or `static if` +fail_compilation/cerrors.d(13): Error: declaration expected, not `#` +fail_compilation/cerrors.d(17): Error: C preprocessor directive `#endif` is not supported +fail_compilation/cerrors.d(17): Error: declaration expected, not `#` +fail_compilation/cerrors.d(21): Error: token string requires valid D tokens, not `#if` +fail_compilation/cerrors.d(22): Deprecation: token string requires valid D tokens, not `#include` --- */ diff --git a/tests/dmd/unit/lexer/diagnostic_reporter.d b/tests/dmd/unit/lexer/diagnostic_reporter.d index 030ce6c6eca..e707e99bb76 100644 --- a/tests/dmd/unit/lexer/diagnostic_reporter.d +++ b/tests/dmd/unit/lexer/diagnostic_reporter.d @@ -36,27 +36,6 @@ unittest assert(reporter.errorCount == 1); } -@("warnings: C preprocessor directive") -unittest -{ - static final class WarningCountingDiagnosticReporter : NoopDiagnosticReporter - { - int warningCount; - - override bool warning(const ref Loc, const(char)*, va_list, const(char)*, const(char)*) - { - warningCount++; - return true; - } - } - - global.params.warnings = DiagnosticReporting.inform; - scope reporter = new WarningCountingDiagnosticReporter; - lexUntilEndOfFile(`#foo`); - - assert(reporter.warningCount == 1); -} - private void lexUntilEndOfFile(string code) { import dmd.lexer : Lexer; From c9d596f89c5236005b167b63fd379ad130919b3d Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Thu, 13 Apr 2023 18:10:43 +0300 Subject: [PATCH 163/177] Fix Issue 22857 - Segfault for malformed static if in imported template (dlang/dmd!15097) --- dmd/cond.d | 3 --- dmd/dsymbolsem.d | 13 +++++++------ dmd/statementsem.d | 3 +-- tests/dmd/fail_compilation/fail17646.d | 2 +- tests/dmd/fail_compilation/fail22857.d | 18 ++++++++++++++++++ .../dmd/fail_compilation/imports/import22857.d | 4 ++++ tests/dmd/fail_compilation/test21164.d | 3 ++- 7 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 tests/dmd/fail_compilation/fail22857.d create mode 100644 tests/dmd/fail_compilation/imports/import22857.d diff --git a/dmd/cond.d b/dmd/cond.d index c0c4cf1ce82..c40936c78d1 100644 --- a/dmd/cond.d +++ b/dmd/cond.d @@ -935,9 +935,6 @@ extern (C++) final class StaticIfCondition : Condition import dmd.staticcond; bool errors; - if (!exp) - return errorReturn(); - bool result = evalStaticCondition(sc, exp, exp, errors); // Prevent repeated condition evaluation. diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 6697ad6d4d6..0f0ed2adec7 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -1383,10 +1383,14 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor imp.semanticRun = PASS.semantic; // Load if not already done so - bool loadErrored = false; if (!imp.mod) { - loadErrored = imp.load(sc); + // https://issues.dlang.org/show_bug.cgi?id=22857 + // if parser errors occur when loading a module + // we should just stop compilation + if (imp.load(sc)) + return; + if (imp.mod) { imp.mod.importAll(null); @@ -1427,10 +1431,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor imp.addPackageAccess(scopesym); } - if (!loadErrored) - { - imp.mod.dsymbolSemantic(null); - } + imp.mod.dsymbolSemantic(null); if (imp.mod.needmoduleinfo) { diff --git a/dmd/statementsem.d b/dmd/statementsem.d index 65de6dcf105..694db28b56c 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -4528,8 +4528,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState decls.append(Dsymbol.arraySyntaxCopy(dbody)); else { - if (fs._body) // https://issues.dlang.org/show_bug.cgi?id=17646 - stmts.push(fs._body.syntaxCopy()); + stmts.push(fs._body.syntaxCopy()); s = new CompoundStatement(loc, stmts); } diff --git a/tests/dmd/fail_compilation/fail17646.d b/tests/dmd/fail_compilation/fail17646.d index 39e7cb9eb73..2074b472a1e 100644 --- a/tests/dmd/fail_compilation/fail17646.d +++ b/tests/dmd/fail_compilation/fail17646.d @@ -4,7 +4,7 @@ EXTRA_FILES: imports/fail17646.d TEST_OUTPUT: --- fail_compilation/imports/fail17646.d(10): Error: found `}` instead of statement -fail_compilation/fail17646.d(11): Error: function `fail17646.runTests!"".runTests` has no `return` statement, but is expected to return a value of type `int` +fail_compilation/fail17646.d(15): Error: template instance `allTestData!Modules` template `allTestData` is not defined fail_compilation/fail17646.d(18): Error: template instance `fail17646.runTests!""` error instantiating --- */ diff --git a/tests/dmd/fail_compilation/fail22857.d b/tests/dmd/fail_compilation/fail22857.d new file mode 100644 index 00000000000..061eb62d49e --- /dev/null +++ b/tests/dmd/fail_compilation/fail22857.d @@ -0,0 +1,18 @@ +// https://issues.dlang.org/show_bug.cgi?id=22857 +// EXTRA_FILES: imports/import22857.d + +/* +TEST_OUTPUT: +--- +fail_compilation/imports/import22857.d(4): Error: (expression) expected following `static if` +fail_compilation/imports/import22857.d(4): Error: declaration expected, not `}` +fail_compilation/fail22857.d(17): Error: template instance `unaryFun!()` template `unaryFun` is not defined +--- +*/ + +void isPrettyPropertyName() +{ + import imports.import22857; + + unaryFun!(); +} diff --git a/tests/dmd/fail_compilation/imports/import22857.d b/tests/dmd/fail_compilation/imports/import22857.d new file mode 100644 index 00000000000..280c2eb10ff --- /dev/null +++ b/tests/dmd/fail_compilation/imports/import22857.d @@ -0,0 +1,4 @@ +template unaryFun() +{ + static if +} diff --git a/tests/dmd/fail_compilation/test21164.d b/tests/dmd/fail_compilation/test21164.d index f42c4bc9d15..a12002488ed 100644 --- a/tests/dmd/fail_compilation/test21164.d +++ b/tests/dmd/fail_compilation/test21164.d @@ -3,7 +3,8 @@ TEST_OUTPUT: --- fail_compilation/imports/test21164d.d(3): Error: (expression) expected following `static if` fail_compilation/imports/test21164d.d(3): Error: found `}` instead of statement -fail_compilation/test21164.d(11): Error: template instance `test21164a.D!(R!(O(), 1))` error instantiating +fail_compilation/imports/test21164a.d(5): Error: undefined identifier `I` +fail_compilation/test21164.d(12): Error: template instance `test21164a.D!(R!(O(), 1))` error instantiating --- */ import imports.test21164a; From 7d8e2996da0cc3d24dae8bd973957e7626b62e90 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Thu, 13 Apr 2023 18:11:04 +0300 Subject: [PATCH 164/177] Fix Issue 22739 - Segmentation fault in CppMangleVisitor.headOfType (dlang/dmd!15098) --- dmd/cppmangle.d | 5 +++++ tests/dmd/compilable/test22739.d | 10 ++++++++++ 2 files changed, 15 insertions(+) create mode 100644 tests/dmd/compilable/test22739.d diff --git a/dmd/cppmangle.d b/dmd/cppmangle.d index b015a642b90..2cee5961383 100644 --- a/dmd/cppmangle.d +++ b/dmd/cppmangle.d @@ -213,6 +213,11 @@ private final class CppMangleVisitor : Visitor { auto tf = cast(TypeFunction)this.context.res.asFuncDecl().type; Type rt = preSemantic.nextOf(); + // https://issues.dlang.org/show_bug.cgi?id=22739 + // auto return type means that rt is null. + // if so, just pick up the type from the instance + if (!rt) + rt = tf.nextOf(); if (tf.isref) rt = rt.referenceTo(); auto prev = this.context.push(tf.nextOf()); diff --git a/tests/dmd/compilable/test22739.d b/tests/dmd/compilable/test22739.d new file mode 100644 index 00000000000..6aeb5d60fd7 --- /dev/null +++ b/tests/dmd/compilable/test22739.d @@ -0,0 +1,10 @@ +// https://issues.dlang.org/show_bug.cgi?id=22739 + +extern(C++) auto f(T)() +{ + return T.init; +} +void main() +{ + f!int; +} From d40e279c1caacd649432ee1b1b384eb5c6e3b2b1 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Thu, 13 Apr 2023 18:11:22 +0300 Subject: [PATCH 165/177] Fix Issue 22765 - Assertion failure in CppMangleVisitor.template_args (dlang/dmd!15100) --- dmd/cppmangle.d | 6 +++++- tests/dmd/fail_compilation/test22765.d | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/fail_compilation/test22765.d diff --git a/dmd/cppmangle.d b/dmd/cppmangle.d index 2cee5961383..32b38518953 100644 --- a/dmd/cppmangle.d +++ b/dmd/cppmangle.d @@ -565,7 +565,11 @@ private final class CppMangleVisitor : Visitor foreach (j; i .. (*ti.tiargs).length) { Type t = isType((*ti.tiargs)[j]); - assert(t); + if (t is null) + { + ti.error("internal compiler error: C++ `%s` template value parameter is not supported", (*ti.tiargs)[j].toChars()); + fatal(); + } t.accept(this); } diff --git a/tests/dmd/fail_compilation/test22765.d b/tests/dmd/fail_compilation/test22765.d new file mode 100644 index 00000000000..0d1b582d517 --- /dev/null +++ b/tests/dmd/fail_compilation/test22765.d @@ -0,0 +1,14 @@ +// https://issues.dlang.org/show_bug.cgi?id=22765 + +/* +TEST_OUTPUT: +--- +fail_compilation/test22765.d(14): Error: template instance `test22765.Template!null` internal compiler error: C++ `null` template value parameter is not supported +--- +*/ + +template Template(T...) +{ + extern(C++) const __gshared int Template = 0; +} +auto x = Template!(null); From b5d67d0d99a37c1a8d9e64ed279a1b092578d331 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Wed, 19 Apr 2023 13:26:11 +0300 Subject: [PATCH 166/177] Fix Issue 20090 - Header generation wrongfully outputs constructor bodies (dlang/dmd!15115) --- dmd/hdrgen.d | 5 +++- tests/dmd/compilable/extra-files/header1.di | 28 ++++++--------------- tests/dmd/compilable/extra-files/header2.di | 10 ++------ 3 files changed, 13 insertions(+), 30 deletions(-) diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index c7e5690bc0a..e0684e6b365 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -1586,7 +1586,10 @@ public: if (hgs.hdrgen) { // if the return type is missing (e.g. ref functions or auto) - if (!tf.next || f.storage_class & STC.auto_) + // https://issues.dlang.org/show_bug.cgi?id=20090 + // constructors are an exception: they don't have an explicit return + // type but we still don't output the body. + if ((!f.isCtorDeclaration() && !tf.next) || f.storage_class & STC.auto_) { hgs.autoMember++; bodyToBuffer(f); diff --git a/tests/dmd/compilable/extra-files/header1.di b/tests/dmd/compilable/extra-files/header1.di index f99d1bcfaa9..ef298a3878a 100644 --- a/tests/dmd/compilable/extra-files/header1.di +++ b/tests/dmd/compilable/extra-files/header1.di @@ -215,12 +215,8 @@ class xFoo2 : iFoo, iFoo2 } class Foo3 { - this(int a, ...) - { - } - this(int* a) - { - } + this(int a, ...); + this(int* a); } alias myint = int; static extern typeof(1) notquit; @@ -368,12 +364,8 @@ struct S6360 } struct S12 { - nothrow this(int n) - { - } - nothrow this(string s) - { - } + nothrow this(int n); + nothrow this(string s); } struct T12 { @@ -482,11 +474,7 @@ class TestClass int aa; int b1; int b2; - this(int b1, int b2) - { - this.b1 = b1; - this.b2 = b2; - } + this(int b1, int b2); ref foo() { return aa; @@ -514,9 +502,7 @@ size_t magic(); class Foo2A { immutable(FooA) Dummy = new immutable(FooA); - private immutable pure nothrow @nogc @safe this() - { - } + private immutable pure nothrow @nogc @safe this(); } struct Foo3A(T) { @@ -573,4 +559,4 @@ interface I12344 assert(result > 0); } ; -} +} \ No newline at end of file diff --git a/tests/dmd/compilable/extra-files/header2.di b/tests/dmd/compilable/extra-files/header2.di index c8b66a51a85..7a2cff9de31 100644 --- a/tests/dmd/compilable/extra-files/header2.di +++ b/tests/dmd/compilable/extra-files/header2.di @@ -162,13 +162,7 @@ interface LeInterface } class LeClass { - this() - { - auto foo = new class LeInterface - { - } - ; - } + this(); } extern const typeof(new class LeClass, LeInterface { @@ -186,4 +180,4 @@ class CC } private struct Export { -} +} \ No newline at end of file From 5a76cb9b5a5905e4f6c141a47996b35222a6da0a Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Fri, 21 Apr 2023 14:39:16 +0200 Subject: [PATCH 167/177] Bump Phobos and frontend patch version --- CMakeLists.txt | 2 +- runtime/phobos | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 74734444e7f..e0ebfd8d9c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,7 +114,7 @@ include(GetLinuxDistribution) set(LDC_VERSION "1.33.0") # May be overridden by git hash tag set(DMDFE_MAJOR_VERSION 2) set(DMDFE_MINOR_VERSION 103) -set(DMDFE_PATCH_VERSION 0) +set(DMDFE_PATCH_VERSION 1) set(DMD_VERSION ${DMDFE_MAJOR_VERSION}.${DMDFE_MINOR_VERSION}.${DMDFE_PATCH_VERSION}) diff --git a/runtime/phobos b/runtime/phobos index c8f9cbc76b8..6c83b490f7d 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit c8f9cbc76b8c538044a0d77356f91cd2d1aa0b18 +Subproject commit 6c83b490f7d6c66bf430e5249dae608848d3ac2c From 9fc6ef0040c899ed44f0356249c48411216387a6 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Fri, 21 Apr 2023 15:24:56 +0200 Subject: [PATCH 168/177] Slightly adapt new fail_compilation/fail23816.d for LDC --- tests/dmd/fail_compilation/fail23816.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/dmd/fail_compilation/fail23816.d b/tests/dmd/fail_compilation/fail23816.d index 574a7122eb9..b8536219381 100644 --- a/tests/dmd/fail_compilation/fail23816.d +++ b/tests/dmd/fail_compilation/fail23816.d @@ -1,9 +1,9 @@ // https://issues.dlang.org/show_bug.cgi?id=23816 - +// DISABLED: LDC_not_x86 /* TEST_OUTPUT: --- -fail_compilation/fail23816.d(14): Error: opcode expected, not `NOP` +fail_compilation/fail23816.d(14): Error: unknown opcode `NOP` --- */ From 9bc3e0113b01e927e5b3944909bef0d1515740ab Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Tue, 25 Apr 2023 13:14:18 +0300 Subject: [PATCH 169/177] Fix Issue 22765 for windows (dlang/dmd!15118) --- dmd/cppmanglewin.d | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/dmd/cppmanglewin.d b/dmd/cppmanglewin.d index 1ae20bac368..bc54287f28f 100644 --- a/dmd/cppmanglewin.d +++ b/dmd/cppmanglewin.d @@ -997,9 +997,14 @@ extern(D): { tmp.mangleTemplateValue(o, tv, actualti, is_dmc_template); } - else - if (!tp || tp.isTemplateTypeParameter()) + else if (!tp || tp.isTemplateTypeParameter()) { + Type t = isType(o); + if (t is null) + { + actualti.error("internal compiler error: C++ `%s` template value parameter is not supported", o.toChars()); + fatal(); + } tmp.mangleTemplateType(o); } else if (tp.isTemplateAliasParameter()) From fe462114f0e44da405719676c31be4a874d71966 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Tue, 25 Apr 2023 21:32:16 +0200 Subject: [PATCH 170/177] fix issue 23859 - [REG 2.103] Throwing while in a deep callstack causes memory corruption (dlang/dmd!15127) avoid writing beyond the end of the trace buffer --- .../druntime/src/core/sys/windows/stacktrace.d | 2 ++ runtime/druntime/test/exceptions/src/winstack.d | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/runtime/druntime/src/core/sys/windows/stacktrace.d b/runtime/druntime/src/core/sys/windows/stacktrace.d index c10a9175b4d..a73fc9ce4d2 100644 --- a/runtime/druntime/src/core/sys/windows/stacktrace.d +++ b/runtime/druntime/src/core/sys/windows/stacktrace.d @@ -239,6 +239,8 @@ private: if (frameNum >= skip) { buffer[nframes++] = stackframe.AddrPC.Offset; + if (nframes >= buffer.length) + break; } frameNum++; } diff --git a/runtime/druntime/test/exceptions/src/winstack.d b/runtime/druntime/test/exceptions/src/winstack.d index fcade2893ca..0577a2d04a4 100644 --- a/runtime/druntime/test/exceptions/src/winstack.d +++ b/runtime/druntime/test/exceptions/src/winstack.d @@ -49,6 +49,15 @@ void main() assert(checkStack(ex), "Bad stack"); } } + + // see https://issues.dlang.org/show_bug.cgi?id=23859 + try + { + recurseThrow(200); + } + catch(Exception e) + { + } } void regular() @@ -66,3 +75,10 @@ void recursion(int i) f(); } } + +void* recurseThrow(int n) +{ + if (n > 0) + return recurseThrow(n - 1) + 1; // avoid tail call optimization + throw new Exception("cancel"); +} From 7b7eeb34d968570ce635cd3185146ff6238c6bf7 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Wed, 26 Apr 2023 16:18:45 +0300 Subject: [PATCH 171/177] CI: Disable tests so Azure OMG targets pass (stable) (dlang/dmd!15132) --- tests/dmd/fail_compilation/bug9631.d | 2 +- tests/dmd/fail_compilation/fail19948.d | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/dmd/fail_compilation/bug9631.d b/tests/dmd/fail_compilation/bug9631.d index f456454fe87..c980d76a73d 100644 --- a/tests/dmd/fail_compilation/bug9631.d +++ b/tests/dmd/fail_compilation/bug9631.d @@ -4,7 +4,7 @@ TEST_OUTPUT: fail_compilation/bug9631.d(20): Error: cannot implicitly convert expression `F()` of type `bug9631.T1!().F` to `bug9631.T2!().F` --- */ - +// DISABLED: win32 template T1() { struct F { } diff --git a/tests/dmd/fail_compilation/fail19948.d b/tests/dmd/fail_compilation/fail19948.d index 6122e418339..e8a9e777904 100644 --- a/tests/dmd/fail_compilation/fail19948.d +++ b/tests/dmd/fail_compilation/fail19948.d @@ -7,7 +7,7 @@ fail_compilation/fail19948.d(15): Error: function `fail19948.func(const(X))` is fail_compilation/fail19948.d(15): cannot pass argument `X()` of type `fail19948.main.X` to parameter `const(fail19948.X)` --- */ - +// DISABLED: win32 struct X {} void main() { From 8d98352cb103f4a78dcb167c94e3b836d4090ead Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Thu, 4 May 2023 15:34:47 +0200 Subject: [PATCH 172/177] Disable _d_newclassT lowering for LDC for now As we don't codegen it either yet. --- dmd/expressionsem.d | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index a3fd50fcaba..f662f49c93f 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -3865,7 +3865,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor result = id.expressionSemantic(sc); return; } - else if (!exp.onstack && !exp.type.isscope()) + // LDC: not using the `_d_newclassT` lowering yet + else if (!IN_LLVM && !exp.onstack && !exp.type.isscope()) { auto hook = global.params.tracegc ? Id._d_newclassTTrace : Id._d_newclassT; if (!verifyHookExist(exp.loc, *sc, hook, "new class")) From 210e1a0391c88d9292e8749811becfa14e7af469 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 6 May 2023 13:03:08 +0200 Subject: [PATCH 173/177] CMake: On Windows, resort to a response file for dc() to overcome max cmdline length limit The effective cmdline length limit seems to be around 8K, and we now exceed it for GH Actions when compiling druntime all-at-once - the length of all module paths (relative to runtime/druntime/src) is > 7,900. --- runtime/CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index c0978274756..d595144737b 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -452,6 +452,15 @@ macro(dc src_files src_basedir d_flags output_basedir emit_bc all_at_once single list(APPEND dc_flags -of=${new_o}) endif() + # Use a response file on Windows, in order not to exceed the max command-line length. + if(WIN32) + set(first_obj "") + list(GET new_o 0 first_obj) + string(REPLACE ";" " " relative_src_files "${relative_src_files}") + file(WRITE ${first_obj}.rsp ${relative_src_files}) + set(relative_src_files "@${first_obj}.rsp") + endif() + add_custom_command( OUTPUT ${new_o} ${new_bc} COMMAND ${LDC_EXE_FULL} ${dc_flags} ${relative_src_files} From 9539044b390457db61b5a89f46cb5a88c8a6ae6b Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 7 May 2023 13:06:21 +0200 Subject: [PATCH 174/177] ldmd: Remove unused variable --- driver/ldmd.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/driver/ldmd.cpp b/driver/ldmd.cpp index 879fcfea33d..4a9aaf63694 100644 --- a/driver/ldmd.cpp +++ b/driver/ldmd.cpp @@ -294,7 +294,6 @@ void appendEnvVar(const char *envVarName, std::vector &args) { char *env = strdup(envVar.c_str()); // create forever-living copy - size_t j = 1; // leave argv[0] alone while (1) { switch (*env) { case ' ': @@ -307,7 +306,6 @@ void appendEnvVar(const char *envVarName, std::vector &args) { default: args.push_back(env); // append - j++; char *p = env; int slash = 0; int instring = 0; From 80b215b34197c47e355057afdb2934941e10c4a6 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 7 May 2023 13:07:25 +0200 Subject: [PATCH 175/177] GH Actions Win32: Disable LTO for LDC itself --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c2e66d0a29c..1ede1951c39 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -62,11 +62,11 @@ jobs: os: windows-2022 arch: x86 bootstrap_cmake_flags: -DBUILD_LTO_LIBS=ON - # Undefined symbol errors with FullLTO; ThinLTO works. extra_cmake_flags: >- -DBUILD_LTO_LIBS=ON - "-DD_COMPILER_FLAGS=-O -flto=thin -defaultlib=phobos2-ldc-lto,druntime-ldc-lto" - -DEXTRA_CXXFLAGS=-flto=thin + # Undefined symbol errors with FullLTO; ThinLTO used to work, but apparently miscompiles a lexer.d:130 assertion since v1.33. + # "-DD_COMPILER_FLAGS=-O -flto=thin -defaultlib=phobos2-ldc-lto,druntime-ldc-lto" + # -DEXTRA_CXXFLAGS=-flto=thin with_pgo: true name: ${{ matrix.job_name }} From 1ca2e49299e6c499156b7913b2b28023164cff24 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 7 May 2023 15:14:07 +0200 Subject: [PATCH 176/177] [add changelog entry] --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c725ff70f9..1d2896019c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # LDC master #### Big news +- Frontend, druntime and Phobos are at version [2.103.1](https://dlang.org/changelog/2.103.0.html), incl. new command-line option `-verror-supplements`. (#4345) #### Platform support From a60ba69cdc289cdfe997b6ed8ab35dcd5d7b1e47 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 7 May 2023 15:16:43 +0200 Subject: [PATCH 177/177] Bump bundled dlang tools, dub & reggae reggae to latest master (using dub v1.32.1). --- packaging/dlang-tools_version | 2 +- packaging/dub_version | 2 +- packaging/reggae_version | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packaging/dlang-tools_version b/packaging/dlang-tools_version index b87e57a249c..4ac687073e6 100644 --- a/packaging/dlang-tools_version +++ b/packaging/dlang-tools_version @@ -1 +1 @@ -v2.102.2 \ No newline at end of file +v2.103.1 \ No newline at end of file diff --git a/packaging/dub_version b/packaging/dub_version index 6f986544fec..4beef39c0b7 100644 --- a/packaging/dub_version +++ b/packaging/dub_version @@ -1 +1 @@ -v1.31.1 \ No newline at end of file +v1.32.1 \ No newline at end of file diff --git a/packaging/reggae_version b/packaging/reggae_version index 3c41a9d487a..ceb52eaf4dd 100644 --- a/packaging/reggae_version +++ b/packaging/reggae_version @@ -1 +1 @@ -087b629e559d15d3372fefaceecb740ef5379316 \ No newline at end of file +fb18f3eb6cb0cd82ea401750f4e200fa82d91e39 \ No newline at end of file