]> git.ipfire.org Git - people/ms/gcc.git/commitdiff
d: Merge upstream dmd, druntime 4ca4140e58, phobos 454dff14d.
authorIain Buclaw <ibuclaw@gdcproject.org>
Sun, 5 Mar 2023 00:47:19 +0000 (01:47 +0100)
committerIain Buclaw <ibuclaw@gdcproject.org>
Thu, 16 Mar 2023 16:29:57 +0000 (17:29 +0100)
D front-end changes:

- Import dmd v2.103.0-beta.1.
- Using `alias this' for classes has been deprecated.
- The feature `-fpreview=dip25` is now enabled by default.
- The compile-time traits `isVirtualFunction' and
  `getVirtualFunctions' have been deprecated.

D runtime changes:

- Import druntime v2.103.0-beta.1.

Phobos changes:

- Import phobos v2.103.0-beta.1.
- Updated unicode grapheme walking updated to conform to Unicode
  version 15.
- Improved friendliness of error messages when instantiating
  `std.algorithm.iteration.joiner' and
  `std.algorithm.sorting.sort' with wrong inputs.

gcc/d/ChangeLog:

* dmd/MERGE: Merge upstream dmd 4ca4140e58.
* dmd/VERSION: Bump version to v2.103.0-beta.1.
* Make-lang.in (D_FRONTEND_OBJS): Add d/errorsink.o.
* d-ctfloat.cc (CTFloat::sprint): Update signature for new front-end
interface.
* d-frontend.cc (getTypeInfoType): Likewise.
* d-lang.cc (d_handle_option): Remove handling of -fpreview=dip25 and
-frevert=dip25.
(d_post_options): Remove enabling of sealed references language
feature when scoped pointers is enabled.
* d-tree.h (create_typeinfo): Update signature.
* decl.cc (DeclVisitor::finish_vtable): Update for new front-end
interface.
(DeclVisitor::visit (VarDeclaration *)): Likewise.
(DeclVisitor::visit (FuncDeclaration *)): Check skipCodegen to see if
front-end explicitly requested not to generate code.
* expr.cc (ExprVisitor::visit (NewExp *)): Update for new front-end
interface.
* lang.opt (fpreview=dip25): Remove.
(frevert=dip25): Remove.
* modules.cc (layout_moduleinfo_fields): Update for new front-end
interface.
(layout_moduleinfo): Likewise.
* runtime.def (NEWCLASS): Remove.
* toir.cc (IRVisitor::visit (IfStatement *)): Don't generate IR for if
statement list when condition is `__ctfe'.
* typeinfo.cc (create_typeinfo): Add generate parameter.
* types.cc (layout_aggregate_members): Update for new front-end
interface.

libphobos/ChangeLog:

* libdruntime/MERGE: Merge upstream druntime 4ca4140e58.
* libdruntime/Makefile.am (DRUNTIME_DSOURCES): Add core/factory.d.
* libdruntime/Makefile.in: Regenerate.
* src/MERGE: Merge upstream phobos 454dff14d.
* testsuite/libphobos.hash/test_hash.d: Update test.
* testsuite/libphobos.shared/finalize.d: Update test.
* libdruntime/core/factory.d: New file.

gcc/testsuite/ChangeLog:

* gdc.dg/torture/simd23084.d: New test.
* gdc.dg/torture/simd23085.d: New test.
* gdc.dg/torture/simd23218.d: New test.

313 files changed:
gcc/d/Make-lang.in
gcc/d/d-ctfloat.cc
gcc/d/d-frontend.cc
gcc/d/d-lang.cc
gcc/d/d-tree.h
gcc/d/decl.cc
gcc/d/dmd/MERGE
gcc/d/dmd/README.md
gcc/d/dmd/VERSION
gcc/d/dmd/aggregate.h
gcc/d/dmd/apply.d
gcc/d/dmd/arrayop.d
gcc/d/dmd/attrib.d
gcc/d/dmd/attrib.h
gcc/d/dmd/blockexit.d
gcc/d/dmd/canthrow.d
gcc/d/dmd/clone.d
gcc/d/dmd/common/outbuffer.d
gcc/d/dmd/constfold.d
gcc/d/dmd/cparse.d
gcc/d/dmd/cppmangle.d
gcc/d/dmd/ctfeexpr.d
gcc/d/dmd/dcast.d
gcc/d/dmd/dclass.d
gcc/d/dmd/declaration.d
gcc/d/dmd/declaration.h
gcc/d/dmd/delegatize.d
gcc/d/dmd/dinterpret.d
gcc/d/dmd/dmangle.d
gcc/d/dmd/dmodule.d
gcc/d/dmd/doc.d
gcc/d/dmd/dscope.d
gcc/d/dmd/dstruct.d
gcc/d/dmd/dsymbol.d
gcc/d/dmd/dsymbol.h
gcc/d/dmd/dsymbolsem.d
gcc/d/dmd/dtemplate.d
gcc/d/dmd/dtoh.d
gcc/d/dmd/errors.d
gcc/d/dmd/errorsink.d [new file with mode: 0644]
gcc/d/dmd/escape.d
gcc/d/dmd/expression.d
gcc/d/dmd/expression.h
gcc/d/dmd/expressionsem.d
gcc/d/dmd/foreachvar.d
gcc/d/dmd/func.d
gcc/d/dmd/globals.d
gcc/d/dmd/globals.h
gcc/d/dmd/hdrgen.d
gcc/d/dmd/iasmgcc.d
gcc/d/dmd/id.d
gcc/d/dmd/initsem.d
gcc/d/dmd/json.d
gcc/d/dmd/lambdacomp.d
gcc/d/dmd/lexer.d
gcc/d/dmd/module.h
gcc/d/dmd/mtype.d
gcc/d/dmd/nogc.d
gcc/d/dmd/ob.d
gcc/d/dmd/opover.d
gcc/d/dmd/parse.d
gcc/d/dmd/printast.d
gcc/d/dmd/root/aav.d
gcc/d/dmd/root/array.d
gcc/d/dmd/root/ctfloat.d
gcc/d/dmd/root/ctfloat.h
gcc/d/dmd/root/filename.d
gcc/d/dmd/root/filename.h
gcc/d/dmd/root/rootobject.d
gcc/d/dmd/sapply.d
gcc/d/dmd/semantic2.d
gcc/d/dmd/semantic3.d
gcc/d/dmd/sideeffect.d
gcc/d/dmd/statement.d
gcc/d/dmd/statement.h
gcc/d/dmd/statementsem.d
gcc/d/dmd/template.h
gcc/d/dmd/templateparamsem.d
gcc/d/dmd/tokens.d
gcc/d/dmd/tokens.h
gcc/d/dmd/traits.d
gcc/d/dmd/typesem.d
gcc/d/dmd/typinf.d
gcc/d/dmd/visitor.d
gcc/d/expr.cc
gcc/d/lang.opt
gcc/d/modules.cc
gcc/d/runtime.def
gcc/d/toir.cc
gcc/d/typeinfo.cc
gcc/d/types.cc
gcc/testsuite/gdc.dg/torture/simd23084.d [new file with mode: 0644]
gcc/testsuite/gdc.dg/torture/simd23085.d [new file with mode: 0644]
gcc/testsuite/gdc.dg/torture/simd23218.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/b23620.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/extra-files/header18365.d
gcc/testsuite/gdc.test/compilable/extra-files/imp9057.d
gcc/testsuite/gdc.test/compilable/extra-files/test23626a.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/extra-files/test23626b.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/ice13920.d
gcc/testsuite/gdc.test/compilable/imports/imp23662.c [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/infer_stc.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/named_argumens_struct.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/named_arguments.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/scope.d
gcc/testsuite/gdc.test/compilable/shared.d
gcc/testsuite/gdc.test/compilable/test16495.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test18026.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test19268.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test20201.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test21073.d [deleted file]
gcc/testsuite/gdc.test/compilable/test21543.d [deleted file]
gcc/testsuite/gdc.test/compilable/test22916.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test23145.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test23431_minimal.d
gcc/testsuite/gdc.test/compilable/test23433.d
gcc/testsuite/gdc.test/compilable/test23598.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test23606.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test23617.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test23626.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test23639.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test23651.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test23662.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test23676.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test23679.d [new file with mode: 0644]
gcc/testsuite/gdc.test/compilable/test5973.d [deleted file]
gcc/testsuite/gdc.test/compilable/test6777.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/biterrors2.d
gcc/testsuite/gdc.test/fail_compilation/call_function_type.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/ctfeblock.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/deprecate_getVirtualFunctions.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/diag10099.d
gcc/testsuite/gdc.test/fail_compilation/diag11132.d
gcc/testsuite/gdc.test/fail_compilation/diag12312.d
gcc/testsuite/gdc.test/fail_compilation/diag14235.d
gcc/testsuite/gdc.test/fail_compilation/diag3438.d
gcc/testsuite/gdc.test/fail_compilation/diag8101.d
gcc/testsuite/gdc.test/fail_compilation/diag9358.d
gcc/testsuite/gdc.test/fail_compilation/diag9679.d
gcc/testsuite/gdc.test/fail_compilation/dip25.d
gcc/testsuite/gdc.test/fail_compilation/dip25flag.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/e15876_5.d
gcc/testsuite/gdc.test/fail_compilation/enum9921.d
gcc/testsuite/gdc.test/fail_compilation/enum_init.d
gcc/testsuite/gdc.test/fail_compilation/fail10102.d
gcc/testsuite/gdc.test/fail_compilation/fail14406.d
gcc/testsuite/gdc.test/fail_compilation/fail155.d
gcc/testsuite/gdc.test/fail_compilation/fail156.d
gcc/testsuite/gdc.test/fail_compilation/fail15616a.d
gcc/testsuite/gdc.test/fail_compilation/fail15616c.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fail15616d.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fail158.d
gcc/testsuite/gdc.test/fail_compilation/fail17955.d
gcc/testsuite/gdc.test/fail_compilation/fail19076.d
gcc/testsuite/gdc.test/fail_compilation/fail21243.d
gcc/testsuite/gdc.test/fail_compilation/fail22039.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fail22570.d
gcc/testsuite/gdc.test/fail_compilation/fail233.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/fail23626a.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fail23626b.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fail23745.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fail253.d
gcc/testsuite/gdc.test/fail_compilation/fail299.d
gcc/testsuite/gdc.test/fail_compilation/fail308.d
gcc/testsuite/gdc.test/fail_compilation/fail346.d
gcc/testsuite/gdc.test/fail_compilation/fail4269a.d
gcc/testsuite/gdc.test/fail_compilation/fail5851.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/fail_scope.d
gcc/testsuite/gdc.test/fail_compilation/failinout2.d
gcc/testsuite/gdc.test/fail_compilation/failinout3748a.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/failinout3748b.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/failob1.d
gcc/testsuite/gdc.test/fail_compilation/failob2.d
gcc/testsuite/gdc.test/fail_compilation/fnconstraint.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/fob1.d
gcc/testsuite/gdc.test/fail_compilation/fob2.d
gcc/testsuite/gdc.test/fail_compilation/gag4269f.d
gcc/testsuite/gdc.test/fail_compilation/ice12727.d
gcc/testsuite/gdc.test/fail_compilation/ice12902.d
gcc/testsuite/gdc.test/fail_compilation/ice13788.d
gcc/testsuite/gdc.test/fail_compilation/ice13816.d
gcc/testsuite/gdc.test/fail_compilation/ice18753.d
gcc/testsuite/gdc.test/fail_compilation/ice23569.d
gcc/testsuite/gdc.test/fail_compilation/issue16020.d
gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/named_arguments_overload.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/named_arguments_parse.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/retscope6.d
gcc/testsuite/gdc.test/fail_compilation/shared.d
gcc/testsuite/gdc.test/fail_compilation/test15368.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test16495.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test17096.d
gcc/testsuite/gdc.test/fail_compilation/test17451.d
gcc/testsuite/gdc.test/fail_compilation/test20549.d
gcc/testsuite/gdc.test/fail_compilation/test20719.d
gcc/testsuite/gdc.test/fail_compilation/test20809.d
gcc/testsuite/gdc.test/fail_compilation/test20998.d
gcc/testsuite/gdc.test/fail_compilation/test22593.d [deleted file]
gcc/testsuite/gdc.test/fail_compilation/test23607.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test23674.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test23710.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/test_switch_error.d
gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d [new file with mode: 0644]
gcc/testsuite/gdc.test/fail_compilation/testscopestatic.d
gcc/testsuite/gdc.test/fail_compilation/udaparams.d
gcc/testsuite/gdc.test/runnable/aliasthis.d
gcc/testsuite/gdc.test/runnable/auto1.d
gcc/testsuite/gdc.test/runnable/cppdtor.d
gcc/testsuite/gdc.test/runnable/e7804.d
gcc/testsuite/gdc.test/runnable/extra-files/test11051.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/funclit.d
gcc/testsuite/gdc.test/runnable/imports/freer.i [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/imports/maker.i [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/interpret.d
gcc/testsuite/gdc.test/runnable/issue22854.d
gcc/testsuite/gdc.test/runnable/mars1.d
gcc/testsuite/gdc.test/runnable/mixin2.d
gcc/testsuite/gdc.test/runnable/test15985.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/test16098.d
gcc/testsuite/gdc.test/runnable/test17684.d
gcc/testsuite/gdc.test/runnable/test18472.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/test19782.d
gcc/testsuite/gdc.test/runnable/test19946.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/test20520.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/test20855.d
gcc/testsuite/gdc.test/runnable/test21039.d
gcc/testsuite/gdc.test/runnable/test21772.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/test21821.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/test23.d
gcc/testsuite/gdc.test/runnable/test23234.d
gcc/testsuite/gdc.test/runnable/test23387.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/test23514.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/test23618.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/test23650.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/test23710.d [new file with mode: 0644]
gcc/testsuite/gdc.test/runnable/test34.d
gcc/testsuite/gdc.test/runnable/test8.d
gcc/testsuite/gdc.test/runnable/testaliascast.d
gcc/testsuite/gdc.test/runnable/testassign.d
gcc/testsuite/gdc.test/runnable/testdstress.d
gcc/testsuite/gdc.test/runnable/traits.d
gcc/testsuite/gdc.test/runnable/traits_getPointerBitmap.d
gcc/testsuite/gdc.test/runnable/xtest46.d
gcc/testsuite/gdc.test/runnable/xtest46_gc.d
gcc/testsuite/gdc.test/runnable_cxx/cpp_abi_tests.d
gcc/testsuite/gdc.test/runnable_cxx/cppa.d
gcc/testsuite/gdc.test/runnable_cxx/extra-files/cpp_abi_tests.cpp
gcc/testsuite/gdc.test/runnable_cxx/test22898.d
libphobos/libdruntime/MERGE
libphobos/libdruntime/Makefile.am
libphobos/libdruntime/Makefile.in
libphobos/libdruntime/core/attribute.d
libphobos/libdruntime/core/cpuid.d
libphobos/libdruntime/core/demangle.d
libphobos/libdruntime/core/factory.d [new file with mode: 0644]
libphobos/libdruntime/core/int128.d
libphobos/libdruntime/core/internal/array/appending.d
libphobos/libdruntime/core/internal/array/capacity.d
libphobos/libdruntime/core/internal/array/concatenation.d
libphobos/libdruntime/core/internal/array/duplication.d
libphobos/libdruntime/core/internal/array/utils.d
libphobos/libdruntime/core/internal/traits.d
libphobos/libdruntime/core/lifetime.d
libphobos/libdruntime/core/memory.d
libphobos/libdruntime/core/stdc/config.d
libphobos/libdruntime/core/stdc/time.d
libphobos/libdruntime/core/sys/darwin/sys/event.d
libphobos/libdruntime/core/sys/posix/aio.d
libphobos/libdruntime/core/sys/posix/dlfcn.d
libphobos/libdruntime/core/sys/posix/mqueue.d
libphobos/libdruntime/core/sys/posix/netinet/in_.d
libphobos/libdruntime/core/sys/posix/sched.d
libphobos/libdruntime/core/sys/posix/semaphore.d
libphobos/libdruntime/core/sys/posix/signal.d
libphobos/libdruntime/core/sys/posix/sys/resource.d
libphobos/libdruntime/core/sys/posix/sys/select.d
libphobos/libdruntime/core/sys/posix/sys/stat.d
libphobos/libdruntime/core/sys/posix/sys/time.d
libphobos/libdruntime/core/sys/posix/time.d
libphobos/libdruntime/core/sys/posix/utime.d
libphobos/libdruntime/core/sys/windows/stacktrace.d
libphobos/libdruntime/core/sys/windows/winbase.d
libphobos/libdruntime/core/thread/fiber.d
libphobos/libdruntime/core/thread/osthread.d
libphobos/libdruntime/core/thread/types.d
libphobos/libdruntime/object.d
libphobos/src/MERGE
libphobos/src/std/algorithm/iteration.d
libphobos/src/std/algorithm/package.d
libphobos/src/std/algorithm/sorting.d
libphobos/src/std/array.d
libphobos/src/std/bitmanip.d
libphobos/src/std/concurrency.d
libphobos/src/std/container/binaryheap.d
libphobos/src/std/exception.d
libphobos/src/std/file.d
libphobos/src/std/format/internal/write.d
libphobos/src/std/format/read.d
libphobos/src/std/getopt.d
libphobos/src/std/internal/unicode_grapheme.d
libphobos/src/std/math/exponential.d
libphobos/src/std/net/curl.d
libphobos/src/std/process.d
libphobos/src/std/range/primitives.d
libphobos/src/std/regex/internal/parser.d
libphobos/src/std/socket.d
libphobos/src/std/stdio.d
libphobos/src/std/traits.d
libphobos/src/std/typecons.d
libphobos/src/std/uni/package.d
libphobos/src/std/utf.d
libphobos/testsuite/libphobos.hash/test_hash.d
libphobos/testsuite/libphobos.shared/finalize.d

index 4feebac982ba7b30e64a18cdbbe48024f280d0fc..1679fb81097985639199262abab81ab59d9d2bb8 100644 (file)
@@ -124,6 +124,7 @@ D_FRONTEND_OBJS = \
        d/dversion.o \
        d/entity.o \
        d/errors.o \
+       d/errorsink.o \
        d/escape.o \
        d/expression.o \
        d/expressionsem.o \
index a85a413d7bdd9f23db6ac07643127b230d8dec6a..15d02b6de7603695fd66bd084b659962d7acb951 100644 (file)
@@ -96,16 +96,16 @@ CTFloat::parse (const char *buffer, bool &overflow)
   return r;
 }
 
-/* Format the real_t value R to string BUFFER as a decimal or hexadecimal,
-   converting the result to uppercase if FMT requests it.  */
+/* Format the real_t value R to string BUFFER, bounded by BUF_SIZE, as a decimal
+   or hexadecimal, converting the result to uppercase if FMT requests it.  */
 
 int
-CTFloat::sprint (char *buffer, char fmt, real_t r)
+CTFloat::sprint (char *buffer, d_size_t buf_size, char fmt, real_t r)
 {
   if (fmt == 'a' || fmt == 'A')
     {
       /* Converting to a hexadecimal string.  */
-      real_to_hexadecimal (buffer, &r.rv (), 32, 0, 1);
+      real_to_hexadecimal (buffer, &r.rv (), buf_size, 0, 1);
       int buflen;
 
       switch (fmt)
index f5e049604893895a022af8f4db78bbecfa036a08..cf200959cf9dfc0793bb8dd1f16d01198fe0cfe2 100644 (file)
@@ -79,11 +79,11 @@ eval_builtin (const Loc &loc, FuncDeclaration *fd, Expressions *arguments)
 /* Build and return typeinfo type for TYPE.  */
 
 Type *
-getTypeInfoType (const Loc &loc, Type *type, Scope *sc)
+getTypeInfoType (const Loc &loc, Type *type, Scope *sc, bool genObjCode)
 {
   gcc_assert (type->ty != TY::Terror);
   check_typeinfo_type (loc, sc);
-  create_typeinfo (type, sc ? sc->_module->importedFrom : NULL);
+  create_typeinfo (type, sc ? sc->_module->importedFrom : NULL, genObjCode);
   return type->vtinfo->type;
 }
 
index 449c69296a770638fc9588a8abca717f0f656417..235e22a4b41e32a23741fe87ddd4981a3fdf5903 100644 (file)
@@ -558,7 +558,6 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
 
     case OPT_fpreview_all:
       global.params.ehnogc = value;
-      global.params.useDIP25 = FeatureState::enabled;
       global.params.useDIP1000 = FeatureState::enabled;
       global.params.useDIP1021 = value;
       global.params.bitfields = value;
@@ -590,10 +589,6 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       global.params.useDIP1021 = value;
       break;
 
-    case OPT_fpreview_dip25:
-      global.params.useDIP25 = FeatureState::enabled;
-      break;
-
     case OPT_fpreview_dtorfields:
       global.params.dtorFields = FeatureState::enabled;
       break;
@@ -636,7 +631,6 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
 
     case OPT_frevert_all:
       global.params.useDIP1000 = FeatureState::disabled;
-      global.params.useDIP25 = FeatureState::disabled;
       global.params.dtorFields = FeatureState::disabled;
       global.params.fix16997 = !value;
       break;
@@ -645,10 +639,6 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       global.params.useDIP1000 = FeatureState::disabled;
       break;
 
-    case OPT_frevert_dip25:
-      global.params.useDIP25 = FeatureState::disabled;
-      break;
-
     case OPT_frevert_dtorfields:
       global.params.dtorFields = FeatureState::disabled;
       break;
@@ -911,10 +901,6 @@ d_post_options (const char ** fn)
   if (global.params.useDIP1021)
     global.params.useDIP1000 = FeatureState::enabled;
 
-  /* Enabling DIP1000 implies DIP25.  */
-  if (global.params.useDIP1000 == FeatureState::enabled)
-    global.params.useDIP25 = FeatureState::enabled;
-
   /* Keep in sync with existing -fbounds-check flag.  */
   flag_bounds_check = (global.params.useArrayBounds == CHECKENABLEon);
 
index c9f5aaabd496eaf39082baa37f6b37826396f3b7..b64a6fb46f9c15da6e8f2a9b23b81d5d0af27df4 100644 (file)
@@ -689,7 +689,7 @@ extern tree get_classinfo_decl (ClassDeclaration *);
 extern void check_typeinfo_type (const Loc &, Scope *, Expression * = NULL);
 extern tree build_typeinfo (const Loc &, Type *, Expression * = NULL);
 extern tree build_typeinfo (Expression *, Type *);
-extern void create_typeinfo (Type *, Module *);
+extern void create_typeinfo (Type *, Module *, bool = true);
 extern void create_tinfo_types (Module *);
 extern void layout_cpp_typeinfo (ClassDeclaration *);
 extern tree get_cpp_typeinfo_decl (ClassDeclaration *);
index 4fbabd599983cef7be3e3b6c83a663a18a2b1ec9..78c4ab554dc8a7a04eb9aaab16237ce5107860df 100644 (file)
@@ -563,8 +563,8 @@ public:
            if (fd2->isFuture ())
              continue;
 
-           if (fd->leastAsSpecialized (fd2) != MATCH::nomatch
-               || fd2->leastAsSpecialized (fd) != MATCH::nomatch)
+           if (fd->leastAsSpecialized (fd2, NULL) != MATCH::nomatch
+               || fd2->leastAsSpecialized (fd, NULL) != MATCH::nomatch)
              {
                error_at (make_location_t (fd->loc), "use of %qs",
                          fd->toPrettyChars ());
@@ -772,7 +772,7 @@ public:
        return;
       }
 
-    if (d->aliassym)
+    if (d->aliasTuple)
       {
        this->build_dsymbol (d->toAlias ());
        return;
@@ -821,7 +821,7 @@ public:
                DECL_INITIAL (decl) = build_expr (e, true);
              }
          }
-       else
+       else if (!d->type->isZeroInit ())
          {
            /* Use default initializer for the type.  */
            if (TypeStruct *ts = d->type->isTypeStruct ())
@@ -903,6 +903,10 @@ public:
     if (gcc_attribute_p (d))
       return;
 
+    /* Front-end decided this function doesn't require code generation.  */
+    if (d->skipCodegen ())
+      return;
+
     /* Not emitting unittest functions.  */
     if (!global.params.useUnitTests && d->isUnitTestDeclaration ())
       return;
index ac3dd1292685979e3dd29bba401c8eb7a6628118..269eebfc483ffc2d35cff980269cfcf3bcefe443 100644 (file)
@@ -1,4 +1,4 @@
-09faa4eacd4fb147107e94eeebf56b3a73fdcc05
+4ca4140e584c055a8a9bc727e56a97ebcecd61e0
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
index 43eb187c735b71af08d347081e509a317526683e..cecd008e608b519e765df8bf614930aa1aeb2b43 100644 (file)
@@ -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 |
 
index 177c41dd63bad254e35fe3350a24315155304eb2..8b24f92dab7872fb50c21c92e219d87e162e37c2 100644 (file)
@@ -1 +1 @@
-v2.102.0-beta.1
+v2.103.0-beta.1
index 9f9098f7f2b006e6015fc93b655e9341ccbd958a..04e5eb2f0d9b1acf399ccf33808816dab4571a33 100644 (file)
@@ -304,7 +304,6 @@ public:
     virtual int vtblOffset() const;
     const char *kind() const override;
 
-    void addLocalClass(ClassDeclarations *) override final;
     void addObjcSymbols(ClassDeclarations *classes, ClassDeclarations *categories) override final;
 
     // Back end
index f5855c4758aa67852556403b0641cb9e1ff34cfd..59ba9f5ecd65fb815c8bde7b5d2f0bc401d8b720 100644 (file)
@@ -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;
     }
index da2f8000fc1c3a55cf55bfcdee10adcc9f8614a2..908855e271c644796658208cb66d9bc3a4d04463 100644 (file)
@@ -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, 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);
@@ -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;
index 712099ed333a339f45afb66e10a76411ab8ebb5d..dbe78ef74bc595bb61c3d5448dbbb2b859bbcdee 100644 (file)
@@ -197,17 +197,12 @@ 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);
     }
 
-    override final inout(AttribDeclaration) isAttribDeclaration() inout pure @safe
+    override inout(AttribDeclaration) isAttribDeclaration() inout pure @safe
     {
         return this;
     }
@@ -1080,6 +1075,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);
index 96c46e8f7184d18da4b4ff0656975b09a313b3da..44ceb12e0d06b892cf49c007e0315d10d38a3e3d 100644 (file)
@@ -36,8 +36,7 @@ public:
     bool hasPointers() override final;
     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 +183,7 @@ public:
     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); }
 };
index 6369b5ab04b479f97611356de0f4878cda1192ea..bd5b78e92dc557817f647589e56a60c8b4fd53a3 100644 (file)
@@ -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;
index 7c18040eb02790b3fcc040bea556d8eaa8929a2c..0c237e6da567015bc5ac14b68a8337daafbac2fb 100644 (file)
@@ -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;
index ef5464d75e0e0474c8faf7f9a3d21e1ff428fdb1..19bf83e4ec353144df64fc98b580e39950a4f102 100644 (file)
@@ -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, ArgumentList(&a), 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, 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, FuncResolveFlag.quiet);
+                return resolveFuncCall(ad.loc, sc, eq, null, tthis, ArgumentList(&a), FuncResolveFlag.quiet);
             }
 
             f = rfc(er);
@@ -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.
index 276928a6bd875d065ca441ff828372b8773b5209..007d301359c78a9c2c5283f43689497488241d33 100644 (file)
@@ -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");
+}
index 79bbd5dead5cfa81a36a7adcbc72ecb42eddd78e..e4be63cda3e5261122c2f24644e72174eefd9061 100644 (file)
@@ -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);
index a6bc42b1014023b561520973597f069c1e43c5a0..a18f810372df477fb0ecc2d89d6e116b9f9446f0 100644 (file)
@@ -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,
-                            const ref TARGET target, OutBuffer* defines)
+                            ErrorSink errorSink,
+                            const ref TARGET target, OutBuffer* defines) scope
     {
-        super(_module, input, doDocComment);
+        super(_module, input, doDocComment, errorSink);
 
         //printf("CParser.this()\n");
         mod = _module;
@@ -268,11 +270,12 @@ 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)
             {
-                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
@@ -286,6 +289,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:
@@ -752,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;
                     }
 
@@ -781,6 +785,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
@@ -1640,6 +1652,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)
@@ -1664,22 +1693,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;
         }
@@ -1823,17 +1842,10 @@ 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);
+                        if (!tt.id && id)
+                            tt.id = id;
+                        Specifier spec;
+                        auto stag = declareTag(tt, spec);
                         if (tt.tok == TOK.enum_)
                         {
                             isalias = false;
@@ -1847,6 +1859,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
 
@@ -1929,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;
@@ -1995,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[]
              */
@@ -2183,6 +2204,7 @@ final class CParser(AST) : Parser!AST
             ximaginary = 0x8000,
             xcomplex   = 0x10000,
             x_Atomic   = 0x20000,
+            xint128    = 0x40000,
         }
 
         AST.Type t;
@@ -2227,6 +2249,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 +2528,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;
 
@@ -2991,11 +3019,11 @@ final class CParser(AST) : Parser!AST
             auto param = new AST.Parameter(specifiersToSTC(LVL.parameter, specifier),
                                            t, id, null, null);
             parameters.push(param);
-            if (token.value == TOK.rightParenthesis)
+            if (token.value == TOK.rightParenthesis || token.value == TOK.endOfFile)
                 break;
             check(TOK.comma);
         }
-        nextToken();
+        check(TOK.rightParenthesis);
         return finish();
     }
 
@@ -3270,6 +3298,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 +3969,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 +4334,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 +4733,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 +4759,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;
     }
@@ -5115,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();
         }
@@ -5278,6 +5319,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
              */
index d3effa99ddd78aa0420534a504d198fd338bf861..b015a642b909159f753e93311574c1f9d7b87a92 100644 (file)
@@ -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;
index c902149e2b52acec68aaac50f7bb15d14df6bfb9..8109e12d43d34daab0506e6422329a73f1a0e674 100644 (file)
@@ -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);
index b305360a3abc0afc7c9ea48ec159ce5999161161..2830b25d651210af1cb5cd09eb3f0fb3ed8d21a9 100644 (file)
@@ -1520,6 +1520,8 @@ Type toStaticArrayType(SliceExp e)
  */
 Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
 {
+    //printf("castTo(e: %s from: %s to: %s\n", e.toChars(), e.type.toChars(), t.toChars());
+
     Expression visit(Expression e)
     {
         //printf("Expression::castTo(this=%s, t=%s)\n", e.toChars(), t.toChars());
index 1fdd0730fcf335623e1c06065275543da72532c6..e4585934089f3255f52ec2d6c9839bbd499e6bb5 100644 (file)
@@ -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);
index 51737cef2c6f55a3f4b30103e9b9e28cd99d5d43..7cd8df19bdcb0fab5dcd39c06a6efe611f4fa077 100644 (file)
@@ -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
@@ -1148,6 +1148,12 @@ 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
+        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;
@@ -1199,12 +1205,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;
         }
 
@@ -1315,9 +1319,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
@@ -1659,8 +1671,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);
@@ -1697,8 +1708,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;
     }
 
index 5d5c4234b7456c38d22c59bf11fa89bb36bf6c76..cd4155d0fbb0d659d49dc53c4bcf9a4e6c40d4cd 100644 (file)
@@ -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
@@ -270,6 +270,14 @@ public:
     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);
+#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;
@@ -634,8 +642,8 @@ public:
     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;
     bool printf(bool v);
     bool scanf() const;
@@ -680,7 +688,7 @@ public:
     BaseClass *overrideInterface();
     bool overloadInsert(Dsymbol *s) override;
     bool inUnittest();
-    MATCH leastAsSpecialized(FuncDeclaration *g);
+    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);
index 3f982b3faf770514e5590e2bca19c3de12aedb8f..fd9569105b59c56ce18cc418e22958e9a5b86aaf 100644 (file)
@@ -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;
         }
index 7920df799910e7bf8c1cc246ab8d31a591907e27..9073b0db2f843e35f39edee4647652ed268670e3 100644 (file)
@@ -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;
index 867d3cacb2f2531ca7dbc6a3f437868511f52f57..72a447657878f7d71b79292c7e8c2b92fc7edbfe 100644 (file)
 
 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)
-    {
-        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);
-    }
 }
 
 /***************************************
@@ -1322,7 +1372,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])
     {
index e1234e5bde95e6f3efbc10af551df0bfc5001b75..a5f7cd321da53c521e712c13788e91d806e28a58 100644 (file)
@@ -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;
@@ -1377,6 +1378,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
  *
index 732a7370a77e34394b805279ee4ff36df29d9185..88e8996ae3aafda278e3a2bf2692da70c8d99f7a 100644 (file)
@@ -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;
@@ -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;
index 8f196266c79cd5a0e1c10df6ce9e19c113f71c17..ab422fd0cf6024d71c02b58ba92478459139075a 100644 (file)
@@ -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
 {
@@ -272,6 +273,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.
index 6ab93d4c39c67e87ad2013378367c5ced7a20417..3268d5667de88675c4df6f5dd9eddadc6c5b358a 100644 (file)
@@ -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;
     }
 
@@ -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;
index 3611e09c2867701ebaf27d1d88002456ab4a3c48..aa478f2fea22564bd5ea1062971d3cf50cfddb42 100644 (file)
@@ -999,10 +999,7 @@ extern (C++) class Dsymbol : ASTNode
                 sm = sm.toAlias();
                 TemplateDeclaration td = sm.isTemplateDeclaration();
                 if (!td)
-                {
-                    .error(loc, "`%s.%s` is not a template, it is a %s", s.toPrettyChars(), ti.name.toChars(), sm.kind());
-                    return null;
-                }
+                    return null; // error but handled later
                 ti.tempdecl = td;
                 if (!ti.semanticRun)
                     ti.dsymbolSemantic(sc);
@@ -1242,10 +1239,6 @@ extern (C++) class Dsymbol : ASTNode
         return false;
     }
 
-    void addLocalClass(ClassDeclarations*)
-    {
-    }
-
     void addObjcSymbols(ClassDeclarations* classes, ClassDeclarations* categories)
     {
     }
@@ -1416,6 +1409,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; }
 }
 
 /***********************************************************
@@ -2620,6 +2614,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
index 88110e1f5d2f4d6834491dacc36eb0d5b7c164f7..1cee456aa10b6cdd653003774c1d5509cafa3a43 100644 (file)
@@ -72,6 +72,7 @@ class ExpressionDsymbol;
 class AliasAssign;
 class OverloadSet;
 class StaticAssert;
+class StaticIfDeclaration;
 struct AA;
 #ifdef IN_GCC
 typedef union tree_node Symbol;
@@ -257,7 +258,6 @@ public:
     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() { }
 
@@ -323,6 +323,7 @@ public:
     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); }
 };
 
index 49e1c5978798118ec24ea48c9edb207ad5f9e276..6697ad6d4d66506da429df95ab2cc0ee61313704 100644 (file)
@@ -230,12 +230,48 @@ package bool allowsContractWithoutBody(FuncDeclaration funcdecl)
     return true;
 }
 
+/*
+Tests whether the `ctor` that is part of `ti` is an rvalue constructor
+(i.e. a constructor that receives a single parameter of the same type as
+`Unqual!typeof(this)`). If that is the case and `sd` contains a copy
+constructor, than an error is issued.
+
+Params:
+    sd = struct declaration that may contin both an rvalue and copy constructor
+    ctor = constructor that will be checked if it is an evalue constructor
+    ti = template instance the ctor is part of
+
+Return:
+    `false` if ctor is not an rvalue constructor or if `sd` does not contain a
+    copy constructor. `true` otherwise
+*/
+bool checkHasBothRvalueAndCpCtor(StructDeclaration sd, CtorDeclaration ctor, TemplateInstance ti)
+{
+    auto loc = ctor.loc;
+    auto tf = cast(TypeFunction)ctor.type;
+    auto dim = tf.parameterList.length;
+    if (sd && sd.hasCopyCtor && (dim == 1 || (dim > 1 && tf.parameterList[1].defaultArg)))
+    {
+        auto param = tf.parameterList[0];
+        if (!(param.storageClass & STC.ref_) && param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf())
+        {
+            .error(loc, "cannot define both an rvalue constructor and a copy constructor for `struct %s`", sd.toChars());
+            .errorSupplemental(ti.loc, "Template instance `%s` creates an rvalue constructor for `struct %s`",
+                    ti.toPrettyChars(), sd.toChars());
+
+            return true;
+        }
+    }
+
+    return false;
+}
+
 private extern(C++) final class DsymbolSemanticVisitor : Visitor
 {
     alias visit = Visitor.visit;
 
     Scope* sc;
-    this(Scope* sc)
+    this(Scope* sc) scope
     {
         this.sc = sc;
     }
@@ -281,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)
@@ -338,6 +379,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
             return;
         assert(dsym.semanticRun <= PASS.semantic);
 
+        if (!sc)
+            return;
+
+        dsym.semanticRun = PASS.semantic;
+
         dsym.storage_class |= sc.stc & STC.deprecated_;
         dsym.visibility = sc.visibility;
         dsym.userAttribDecl = sc.userAttribDecl;
@@ -509,10 +555,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 +574,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())
@@ -544,7 +590,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())
         {
@@ -689,7 +735,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;
         }
@@ -742,7 +788,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 +826,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,21 +850,37 @@ 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());
                 }
             }
         }
 
+        /* 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 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 +898,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");
                 }
             }
         }
@@ -856,7 +918,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 +973,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 +1001,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
@@ -974,7 +1036,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 +1057,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();
@@ -1049,9 +1111,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;
                             }
@@ -1244,7 +1323,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 +1613,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 +1821,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
@@ -1854,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);
@@ -2656,7 +2735,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)
@@ -2694,7 +2773,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
             {
@@ -3054,7 +3133,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())
@@ -3844,11 +3923,25 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
 
                         if (fd.ident == funcdecl.ident)
                             hgs.fullQual = true;
-                        functionToBufferFull(cast(TypeFunction)(fd.type), &buf1,
-                            new Identifier(fd.toPrettyChars()), &hgs, null);
 
-                        error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?",
-                            funcdeclToChars, buf1.peekChars());
+                        // https://issues.dlang.org/show_bug.cgi?id=23745
+                        // If the potentially overriden function contains errors,
+                        // inform the user to fix that one first
+                        if (fd.errors)
+                        {
+                            error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?",
+                                funcdecl.toChars(), fd.toPrettyChars());
+                            errorSupplemental(fd.loc, "Function `%s` contains errors in its declaration, therefore it cannot be correctly overriden",
+                                fd.toPrettyChars());
+                        }
+                        else
+                        {
+                            functionToBufferFull(cast(TypeFunction)(fd.type), &buf1,
+                                new Identifier(fd.toPrettyChars()), &hgs, null);
+
+                            error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?",
+                                funcdeclToChars, buf1.peekChars());
+                       }
                     }
                     else
                     {
@@ -4088,9 +4181,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 "~
@@ -4115,20 +4207,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
         // https://issues.dlang.org/show_bug.cgi?id=22593
         else if (auto ti = ctd.parent.isTemplateInstance())
         {
-            if (!sd || !sd.hasCopyCtor || !(dim == 1 || (dim > 1 && tf.parameterList[1].defaultArg)))
-                return;
-
-            auto param = tf.parameterList[0];
-
-            // if the template instance introduces an rvalue constructor
-            // between the members of a struct declaration, we should check if a
-            // copy constructor exists and issue an error in that case.
-            if (!(param.storageClass & STC.ref_) && param.type.mutableOf().unSharedOf() == sd.type.mutableOf().unSharedOf())
-            {
-                .error(ctd.loc, "cannot define both an rvalue constructor and a copy constructor for `struct %s`", sd.toChars);
-                .errorSupplemental(ti.loc, "Template instance `%s` creates a rvalue constructor for `struct %s`",
-                        ti.toChars(), sd.toChars());
-            }
+            checkHasBothRvalueAndCpCtor(sd, ctd, ti);
         }
     }
 
@@ -4171,8 +4250,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)
@@ -4534,7 +4613,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);
 
@@ -4604,6 +4684,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;
         }
@@ -4655,7 +4736,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);
         }
 
@@ -4685,7 +4766,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();
 
@@ -4698,7 +4779,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, ArgumentList(), FuncResolveFlag.quiet);
                 sc = sc.pop();
                 global.endGagging(xerrors);
 
@@ -4752,6 +4833,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)
@@ -5297,9 +5379,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, ArgumentList(), 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, ArgumentList(), FuncResolveFlag.quiet);
             if (fd && !fd.errors)
             {
                 //printf("Creating default this(){} for class %s\n", toChars());
@@ -5311,7 +5393,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());
 
@@ -5776,7 +5858,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)
@@ -5848,7 +5930,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)
@@ -5901,6 +5983,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.
      */
@@ -5986,7 +6070,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;
                 }
@@ -6142,7 +6226,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;
         }
@@ -6189,7 +6273,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;
             }
@@ -7022,12 +7106,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))
index 32799aa04e3251712ffc3757e7c44292eaa563ba..ad3a6d4dd54f9e9af4904691d87ad341e5f438a7 100644 (file)
@@ -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;
@@ -1050,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)
@@ -1168,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;
@@ -1226,7 +1233,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;
     }
@@ -1237,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)
@@ -1272,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
@@ -1303,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;
@@ -1334,7 +1341,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());
@@ -1458,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:
@@ -2593,13 +2603,12 @@ 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
+ *      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, const(char)** pMessage = null)
+    Type tthis, ArgumentList argumentList, const(char)** pMessage = null)
 {
-    Expression[] fargs_ = fargs.peekSlice();
     version (none)
     {
         printf("functionResolve() dstart = %s\n", dstart.toChars());
@@ -2704,7 +2713,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, argumentList, 0, pMessage, sc);
         //printf("test1: mfa = %d\n", mfa);
         if (mfa == MATCH.nomatch)
             return 0;
@@ -2737,8 +2746,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, 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;
@@ -2806,7 +2815,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
 
     int applyTemplate(TemplateDeclaration td)
     {
-        //printf("applyTemplate()\n");
+        //printf("applyTemplate(): td = %s\n", td.toChars());
         if (td == td_best)   // skip duplicates
             return 0;
 
@@ -2830,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)
         {
@@ -2838,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;
 
@@ -2882,13 +2896,13 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
                 pr.dedargs = &dedtypesX;
                 tdx.previous = &pr;             // add this to threaded list
 
-                fd = resolveFuncCall(loc, sc, s, null, tthis, fargs, 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, FuncResolveFlag.quiet);
+                fd = resolveFuncCall(loc, sc, s, null, tthis, argumentList, FuncResolveFlag.quiet);
             }
             else
                 goto Lerror;
@@ -2907,7 +2921,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, argumentList, 0, null, sc);
             if (mfa < m.last)
                 return 0;
 
@@ -2954,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);
@@ -2967,7 +2981,6 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
             if (isCtorCall)
             {
                 // Constructor call requires additional check.
-
                 auto tf = cast(TypeFunction)fd.type;
                 assert(tf.next);
                 if (MODimplicitConv(tf.mod, tthis_fd.mod) ||
@@ -2978,6 +2991,16 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
                 }
                 else
                     continue;   // MATCH.nomatch
+
+                // need to check here whether the constructor is the member of a struct
+                // declaration that defines a copy constructor. This is already checked
+                // in the semantic of CtorDeclaration, however, when matching functions,
+                // the template instance is not expanded.
+                // https://issues.dlang.org/show_bug.cgi?id=21613
+                auto ad = fd.isThis();
+                auto sd = ad.isStructDeclaration();
+                if (checkHasBothRvalueAndCpCtor(sd, fd.isCtorDeclaration(), ti))
+                    continue;
             }
 
             if (mta < ta_last) goto Ltd_best;
@@ -2989,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;
@@ -3000,16 +3023,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, 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);
-                MATCH c2 = m.lastf.leastAsSpecialized(fd);
+                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;
@@ -3076,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)
@@ -3104,7 +3127,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, argumentList, 0, null, sc))
             goto Lnomatch;
 
         /* As https://issues.dlang.org/show_bug.cgi?id=3682 shows,
@@ -5887,7 +5910,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)
@@ -5902,7 +5925,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)
@@ -6010,7 +6033,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
@@ -6247,41 +6273,55 @@ 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
+        // 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;
 
-        if (errors || (inst && inst.isDiscardable()))
+        // Don't do codegen if the instance has errors,
+        // is a dummy instance (see evaluateConstraint),
+        // or is determined to be discardable.
+        if (errors || inst is null || inst.isDiscardable())
         {
             minst = null; // mark as speculative
             return false;
         }
 
+        // This should only be called on the primary instantiation.
+        assert(this is inst);
+
         if (global.params.allInst)
         {
             // Do codegen if there is an instantiation from a root module, to maximize link-ability.
-
-            // Do codegen if `this` is instantiated from a root module.
-            if (minst && minst.isRoot())
-                return true;
-
-            // Do codegen if the ancestor needs it.
-            if (tinst && tinst.needsCodegen())
+            static ThreeState needsCodegenAllInst(TemplateInstance tithis, TemplateInstance tinst)
             {
-                minst = tinst.minst; // cache result
-                assert(minst);
-                assert(minst.isRoot());
-                return true;
+                // Do codegen if `this` is instantiated from a root module.
+                if (tithis.minst && tithis.minst.isRoot())
+                    return ThreeState.yes;
+
+                // Do codegen if the ancestor needs it.
+                if (tinst && tinst.inst && tinst.inst.needsCodegen())
+                {
+                    tithis.minst = tinst.inst.minst; // cache result
+                    assert(tithis.minst);
+                    assert(tithis.minst.isRoot());
+                    return ThreeState.yes;
+                }
+                return ThreeState.none;
             }
 
+            if (const needsCodegen = needsCodegenAllInst(this, tinst))
+                return needsCodegen == ThreeState.yes ? true : false;
+
             // Do codegen if a sibling needs it.
-            if (tnext)
+            for (; tnext; tnext = tnext.tnext)
             {
-                if (tnext.needsCodegen())
+                const needsCodegen = needsCodegenAllInst(tnext, tnext.tinst);
+                if (needsCodegen == ThreeState.yes)
                 {
                     minst = tnext.minst; // cache result
                     assert(minst);
@@ -6291,8 +6331,10 @@ extern (C++) class TemplateInstance : ScopeDsymbol
                 else if (!minst && tnext.minst)
                 {
                     minst = tnext.minst; // cache result from non-speculative sibling
-                    return false;
+                    // continue searching
                 }
+                else if (needsCodegen != ThreeState.none)
+                    break;
             }
 
             // Elide codegen because there's no instantiation from any root modules.
@@ -6317,31 +6359,39 @@ extern (C++) class TemplateInstance : ScopeDsymbol
              * => Elide codegen if there is at least one instantiation from a non-root module
              *    which doesn't import any root modules.
              */
-
-            // If the ancestor isn't speculative,
-            // 1. do codegen if the ancestor needs it
-            // 2. elide codegen if the ancestor doesn't need it (non-root instantiation of ancestor incl. subtree)
-            if (tinst)
+            static ThreeState needsCodegenRootOnly(TemplateInstance tithis, TemplateInstance tinst)
             {
-                const needsCodegen = tinst.needsCodegen(); // sets tinst.minst
-                if (tinst.minst) // not speculative
+                // If the ancestor isn't speculative,
+                // 1. do codegen if the ancestor needs it
+                // 2. elide codegen if the ancestor doesn't need it (non-root instantiation of ancestor incl. subtree)
+                if (tinst && tinst.inst)
                 {
-                    minst = tinst.minst; // cache result
-                    return needsCodegen;
+                    tinst = tinst.inst;
+                    const needsCodegen = tinst.needsCodegen(); // sets tinst.minst
+                    if (tinst.minst) // not speculative
+                    {
+                        tithis.minst = tinst.minst; // cache result
+                        return needsCodegen ? ThreeState.yes : ThreeState.no;
+                    }
                 }
+
+                // Elide codegen if `this` doesn't need it.
+                if (tithis.minst && !tithis.minst.isRoot() && !tithis.minst.rootImports())
+                    return ThreeState.no;
+
+                return ThreeState.none;
             }
 
-            // Elide codegen if `this` doesn't need it.
-            if (minst && !minst.isRoot() && !minst.rootImports())
-                return false;
+            if (const needsCodegen = needsCodegenRootOnly(this, tinst))
+                return needsCodegen == ThreeState.yes ? true : false;
 
             // Elide codegen if a (non-speculative) sibling doesn't need it.
-            if (tnext)
+            for (; tnext; tnext = tnext.tnext)
             {
-                const needsCodegen = tnext.needsCodegen(); // sets tnext.minst
+                const needsCodegen = needsCodegenRootOnly(tnext, tnext.tinst); // sets tnext.minst
                 if (tnext.minst) // not speculative
                 {
-                    if (!needsCodegen)
+                    if (needsCodegen == ThreeState.no)
                     {
                         minst = tnext.minst; // cache result
                         assert(!minst.isRoot() && !minst.rootImports());
@@ -6350,8 +6400,10 @@ extern (C++) class TemplateInstance : ScopeDsymbol
                     else if (!minst)
                     {
                         minst = tnext.minst; // cache result from non-speculative sibling
-                        return true;
+                        // continue searching
                     }
+                    else if (needsCodegen != ThreeState.none)
+                        break;
                 }
             }
 
@@ -6564,7 +6616,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
@@ -6883,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)
         {
@@ -6897,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;
@@ -6947,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;
@@ -6956,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;
@@ -7223,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;
                 }
@@ -7480,6 +7542,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());
index 30ca3d1f8c6fd1c7ceb3b1ee225b53e3d05a3a1c..7c3ff4bccc2ca87842ac8164f82e3d26f6cd207f 100644 (file)
@@ -291,9 +291,23 @@ public:
 
     /// Informations about the current context in the AST
     Context context;
-    alias context this;
 
-    this(OutBuffer* fwdbuf, OutBuffer* donebuf, OutBuffer* buf)
+    // 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
     {
         this.fwdbuf = fwdbuf;
         this.donebuf = donebuf;
@@ -875,7 +889,7 @@ public:
         // (we'll visit them later)
         if (vd.type && vd.type.isTypeTuple())
         {
-            assert(vd.aliassym);
+            assert(vd.aliasTuple);
             vd.toAlias().accept(this);
             return;
         }
index 03c78a5acdce226f816ed488967440d6a36f7cb3..f107f7b09b3a24f197ef7a546f2e2d373b1da0db 100644 (file)
 module dmd.errors;
 
 import core.stdc.stdarg;
+import dmd.errorsink;
 import dmd.globals;
 import dmd.location;
 
 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
  */
diff --git a/gcc/d/dmd/errorsink.d b/gcc/d/dmd/errorsink.d
new file mode 100644 (file)
index 0000000..b519db7
--- /dev/null
@@ -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, ...) { }
+}
index 7bc018e1e32b338b9fb43cdec1cf10d8cae70d31..420fa7f80bbb816dc87c0efed8cd46c1158d513d 100644 (file)
@@ -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)
@@ -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.
@@ -608,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)
@@ -618,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)
     {
@@ -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;
@@ -1745,7 +1778,25 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
                     const stc = tf.parameterStorageClass(null, p);
                     ScopeRef psr = buildScopeRef(stc);
                     if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
-                        escapeByValue(arg, er, live, retRefTransition);
+                    {
+                        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.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
                     {
                         if (tf.isref)
@@ -1768,68 +1819,55 @@ 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)
                 {
-                    /* 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;
-                    }
+                    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;
+                }
 
-                    const psr = buildScopeRef(getThisStorageClass(fd));
-                    if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
+                const psr = buildScopeRef(getThisStorageClass(fd));
+                if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
+                {
+                    if (!tf.isref || tf.isctor)
                         escapeByValue(dve.e1, er, live, retRefTransition);
-                    else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
+                }
+                else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
+                {
+                    if (tf.isref)
                     {
-                        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);
+                        /* 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);
                 }
             }
-            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);
-                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 it's also a nested function that is 'return scope'
             if (fd && fd.isNested())
index e0f258c5a577d614881a06d81c78badf42079fbb..df5e9ddc98ef33810312e0d2c2c796aa22e76001 100644 (file)
@@ -249,18 +249,55 @@ 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)
+        {
+            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 +312,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 +323,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 +336,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]);
@@ -682,11 +722,11 @@ 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
 
-    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;
@@ -1393,7 +1433,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());
     }
@@ -1435,7 +1475,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;
@@ -1488,7 +1528,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;
@@ -1496,7 +1536,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());
 
@@ -1647,6 +1688,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 +2187,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 +2270,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();
@@ -2261,7 +2328,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;
@@ -2416,7 +2483,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;
@@ -2475,7 +2542,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
@@ -2483,7 +2550,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
@@ -3570,18 +3637,26 @@ 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
     bool onstack;               // allocate on stack
     bool thrownew;              // this NewExp is the expression of a ThrowStatement
 
-    extern (D) this(const ref Loc loc, Expression thisexp, Type newtype, Expressions* arguments)
+    Expression lowering;        // lowered druntime hook: `_d_newclass`
+
+    /// 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)
@@ -3594,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)
@@ -3969,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);
             }
 
@@ -4217,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;
@@ -4257,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;
@@ -4330,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;
@@ -4621,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);
     }
@@ -5048,21 +5125,53 @@ 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
+
+    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;
+    }
+}
+
 /***********************************************************
  */
 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)
+    /// 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);
         this.arguments = exps;
+        this.names = names;
     }
 
     extern (D) this(const ref Loc loc, Expression e)
@@ -5129,7 +5238,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 ? names.copy() : null);
     }
 
     override bool isLvalue()
@@ -5325,7 +5434,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);
     }
@@ -6387,7 +6496,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);
     }
@@ -6717,7 +6826,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;
index 7202960af63a140661dfb9d022491fe80d0fd4c7..e4716c8dfcf51008bfbdbd97e6a28910c54a8711 100644 (file)
@@ -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);
 
@@ -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
 
@@ -123,6 +123,7 @@ public:
     // 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<bool> toBool();
     virtual bool hasCode()
     {
@@ -281,6 +282,7 @@ public:
     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 @@ public:
     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;
@@ -529,6 +532,7 @@ public:
     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[]
 
@@ -536,6 +540,8 @@ public:
     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;
 
@@ -823,6 +829,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
index 63236cdb8826f861d7243723010168e276c51b01..d186abc05524d5fb4767c11b998ef1342052dcce 100644 (file)
@@ -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();
@@ -260,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, ArgumentList(fargs), FuncResolveFlag.quiet);
             sc = sc.pop();
             global.endGagging(xerrors);
             if (!fslice)
@@ -649,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;
 }
@@ -1192,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, ArgumentList(&a), FuncResolveFlag.quiet))
                 {
                     if (f.errors)
                         return ErrorExp.get();
@@ -1209,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, ArgumentList(), FuncResolveFlag.quiet))
                 {
                     if (f.errors)
                         return ErrorExp.get();
@@ -1307,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, ArgumentList(&a), FuncResolveFlag.quiet);
             if (fd && fd.type)
             {
                 if (fd.errors)
@@ -1327,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, ArgumentList(), FuncResolveFlag.quiet);
             if (fd && fd.type)
             {
                 if (fd.errors)
@@ -1586,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);
@@ -1619,20 +1617,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, 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);
+        expandTuples(exps, argumentList.names);
 
         for (size_t i = 0; i < exps.length; i++)
         {
@@ -1708,7 +1710,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
@@ -1716,20 +1718,38 @@ 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, 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);
-    size_t nargs = arguments ? arguments.length : 0;
     const size_t nparams = tf.parameterList.length;
     const olderrors = global.errors;
     bool err = false;
-    *prettype = Type.terror;
     Expression eprefix = null;
     *peprefix = null;
 
+    if (argumentList.names)
+    {
+        const(char)* msg = null;
+        auto resolvedArgs = tf.resolveNamedArgs(argumentList, &msg);
+        if (!resolvedArgs)
+        {
+            // while errors are usually already caught by `tf.callMatch`,
+            // this can happen when calling `typeof(freefunc)`
+            if (msg)
+                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((*resolvedArgs)[]);
+    }
+    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());
@@ -1796,11 +1816,18 @@ 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);
-                arguments.push(arg);
-                nargs++;
+                if (i >= nargs)
+                {
+                    arguments.push(arg);
+                    nargs++;
+                }
+                else
+                    (*arguments)[i] = arg;
             }
             else
             {
@@ -1978,11 +2005,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])
@@ -2145,19 +2179,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
         {
@@ -2443,10 +2464,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
@@ -2545,7 +2566,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
     Scope* sc;
     Expression result;
 
-    this(Scope* sc)
+    this(Scope* sc) scope
     {
         this.sc = sc;
     }
@@ -3547,7 +3568,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
         {
             return setError();
         }
-        if (preFunctionParameters(sc, exp.arguments))
+        if (preFunctionParameters(sc, exp.argumentList))
         {
             return setError();
         }
@@ -3706,7 +3727,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.argumentList, FuncResolveFlag.standard);
                 if (!f || f.errors)
                     return setError();
 
@@ -3716,7 +3737,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.argumentList, f, &exp.type, &exp.argprefix))
                     return setError();
 
                 exp.member = f.isCtorDeclaration();
@@ -3776,6 +3797,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())
         {
@@ -3805,7 +3852,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.argumentList, FuncResolveFlag.standard);
                 if (!f || f.errors)
                     return setError();
 
@@ -3815,7 +3862,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.argumentList, f, &exp.type, &exp.argprefix))
                     return setError();
 
                 exp.member = f.isCtorDeclaration();
@@ -3826,8 +3873,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();
@@ -3876,6 +3935,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)
@@ -3897,6 +3962,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;
@@ -4285,7 +4355,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.argumentList))
                 return setError();
 
             // Run e1 semantic even if arguments have any errors
@@ -4524,7 +4594,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             return;
         }
         if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc) ||
-            preFunctionParameters(sc, exp.arguments))
+            preFunctionParameters(sc, exp.argumentList))
             return setError();
 
         // Check for call operator overload
@@ -4622,7 +4692,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;
@@ -4632,7 +4717,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;
@@ -4671,14 +4756,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, ArgumentList argumentList)
         {
             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, argumentList, FuncResolveFlag.quiet))
                 {
                     if (f2.errors)
                         return null;
@@ -4738,7 +4823,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.argumentList, FuncResolveFlag.standard);
             if (!exp.f || exp.f.errors || exp.f.type.ty == Terror)
                 return setError();
 
@@ -4901,9 +4986,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.argumentList);
             else
-                exp.f = resolveFuncCall(exp.loc, sc, ctor, null, tthis, exp.arguments, FuncResolveFlag.standard);
+                exp.f = resolveFuncCall(exp.loc, sc, ctor, null, tthis, exp.argumentList, FuncResolveFlag.standard);
 
             if (!exp.f || exp.f.errors)
                 return setError();
@@ -4928,7 +5013,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.argumentList);
             if (!exp.f)
                 return setError();
             if (ethis)
@@ -4975,7 +5060,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.argumentList, FuncResolveFlag.overloadOnly);
                 if (!exp.f)
                     return setError();
                 if (exp.f.needThis())
@@ -4999,7 +5084,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.argumentList, FuncResolveFlag.standard);
                 if (!exp.f || exp.f.errors)
                     return setError();
                 if (exp.f.needThis())
@@ -5027,8 +5112,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.argumentList, 0, &failMessage, sc))
             {
                 OutBuffer buf;
                 buf.writeByte('(');
@@ -5095,14 +5179,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.argumentList, FuncResolveFlag.overloadOnly);
             else
             {
                 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.argumentList, 0, &failMessage, sc))
                 {
                     OutBuffer buf;
                     buf.writeByte('(');
@@ -5144,7 +5227,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.argumentList, FuncResolveFlag.standard);
 
                     if (!exp.f || exp.f.errors)
                         return setError();
@@ -5176,7 +5259,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.argumentList, exp.f, &exp.type, &argprefix))
             return setError();
 
         if (!exp.type)
@@ -5499,8 +5582,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)
@@ -6009,7 +6102,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);
 
@@ -8342,13 +8435,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
 
         Type t1b = exp.e1.type.toBasetype();
 
-        if (t1b.ty == Tvector)
+        if (TypeVector tv1 = t1b.isTypeVector())
         {
             // Convert e1 to corresponding static array
-            TypeVector tv1 = cast(TypeVector)t1b;
             t1b = tv1.basetype;
             t1b = t1b.castMod(tv1.mod);
-            exp.e1.type = t1b;
+            exp.e1 = exp.e1.castTo(sc, t1b);
         }
         if (t1b.ty == Tsarray || t1b.ty == Tarray)
         {
@@ -12043,6 +12135,15 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
             __equals = new DotIdExp(exp.loc, __equals, Id.object);
             __equals = new DotIdExp(exp.loc, __equals, id);
 
+            /* https://issues.dlang.org/show_bug.cgi?id=23674
+             *
+             * Optimize before creating the call expression to the
+             * druntime hook as the optimizer may output errors
+             * that will get swallowed otherwise.
+             */
+            exp.e1 = exp.e1.optimize(WANTvalue);
+            exp.e2 = exp.e2.optimize(WANTvalue);
+
             auto arguments = new Expressions(2);
             (*arguments)[0] = exp.e1;
             (*arguments)[1] = exp.e2;
@@ -13149,11 +13250,6 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
 
     //printf("checkSharedAccess() `%s` returnRef: %d\n", e.toChars(), returnRef);
 
-    /* In case we don't know which expression triggered it,
-     * e.g. for `visit(Type)` overload
-     */
-    Expression original = e;
-
     bool check(Expression e, bool allowRef)
     {
         bool sharedError(Expression e)
@@ -13166,7 +13262,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;
         }
@@ -13175,10 +13273,6 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
         {
             if (e.thisexp)
                 check(e.thisexp, false);
-            // Note: This handles things like `new shared(Throwable).msg`,
-            // where accessing `msg` would violate `shared`.
-            if (e.newtype.isShared())
-                return sharedError(original);
             return false;
         }
 
@@ -13216,33 +13310,32 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
             return check(e.e1, false);
         }
 
-        bool visitThis(ThisExp e)
+        bool visitDotVar(DotVarExp e)
         {
-            if (sc.func && sc.func.isSynchronized())
-                return 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 (!allowRef && e.type.isShared())
-                return sharedError(e);
+                auto fd = e.var.isFuncDeclaration();
+                const sharedFunc = fd && fd.type.isShared;
+                if (!allowRef && !sharedFunc)
+                    return sharedError(e);
 
-            return false;
-        }
+                // Allow using `DotVarExp` within value types
+                if (e.e1.type.isTypeSArray() || e.e1.type.isTypeStruct())
+                    return check(e.e1, allowRef);
 
-        bool visitDotVar(DotVarExp e)
-        {
-            //printf("dotvarexp = %s\n", e.toChars());
-            auto fd = e.var.isFuncDeclaration();
-            const sharedFunc = fd && fd.type.isShared;
-            // Allow using `DotVarExp` within value types
-            if (!allowRef && e.type.isShared() && !sharedFunc && !(sc.func && sc.func.isSynchronized()))
-                return sharedError(e);
-            if (e.e1.type.isTypeSArray() || e.e1.type.isTypeStruct())
-                return check(e.e1, allowRef);
+                // If we end up with a single `VarExp`, it might be a `ref` param
+                // `shared ref T` param == `shared(T)*`.
+                if (auto ve = e.e1.isVarExp())
+                {
+                    return check(e.e1, allowRef && (ve.var.storage_class & STC.ref_));
+                }
 
-            // If we end up with a single `VarExp`, it might be a `ref` param
-            // `shared ref T` param == `shared(T)*`.
-            if (auto ve = e.e1.isVarExp())
-            {
-                return check(e.e1, allowRef && (ve.var.storage_class & STC.ref_));
+                return sharedError(e);
             }
 
             return check(e.e1, false);
@@ -13283,7 +13376,6 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
             case EXP.star:        return visitPtr(e.isPtrExp());
             case EXP.dotVariable: return visitDotVar(e.isDotVarExp());
             case EXP.index:       return visitIndex(e.isIndexExp());
-            case EXP.this_:       return visitThis(e.isThisExp());
         }
     }
 
index 7c4df0deca8eede1bedd094b2790f8837283e094..ba2825a3098dfa80d71eb560c4529bde32bae965 100644 (file)
@@ -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;
         }
index 3a85679626c15768099737f19fd125e03186c6c4..4b6b5b58233942cff73b4866afb87a46136dfbb6 100644 (file)
@@ -202,7 +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.
     bool printf;             /// is a printf-like function
     bool scanf;              /// is a scanf-like function
     bool noreturn;           /// the function does not return
@@ -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
 }
 
 /***********************************************************
@@ -322,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;
 
@@ -1039,12 +1047,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 +1098,7 @@ extern (C++) class FuncDeclaration : Declaration
             args.push(e);
         }
 
-        MATCH m = tg.callMatch(null, args[], 1);
+        MATCH m = tg.callMatch(null, ArgumentList(&args, names), 1);
         if (m > MATCH.nomatch)
         {
             /* A variadic parameter list is less specialized than a
@@ -1979,6 +1988,7 @@ extern (C++) class FuncDeclaration : Declaration
                         if (!sc.intypeof && !(sc.flags & SCOPE.compile))
                         {
                             siblingCallers.push(fdthis);
+                            computedEscapingSiblings = false;
                         }
                     }
                 }
@@ -2028,8 +2038,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;
@@ -2106,7 +2115,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;
 
@@ -2320,6 +2329,7 @@ extern (C++) class FuncDeclaration : Declaration
          *    base.in();
          *    assert(false, "Logic error: " ~ thr.msg);
          *  }
+         * }
          */
 
         foreach (fdv; foverrides)
@@ -2827,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;
@@ -3127,14 +3143,15 @@ enum FuncResolveFlag : ubyte
  *      s =             instantiation symbol
  *      tiargs =        initial list of template arguments
  *      tthis =         if !NULL, the `this` argument type
- *      fargs =         arguments to function
+ *      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, FuncResolveFlag flags)
+    Objects* tiargs, Type tthis, ArgumentList argumentList, FuncResolveFlag flags)
 {
+    auto fargs = argumentList.arguments;
     if (!s)
         return null; // no match
 
@@ -3152,6 +3169,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))
@@ -3162,7 +3180,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, argumentList);
     auto orig_s = s;
 
     if (m.last > MATCH.nomatch && m.lastf)
@@ -3285,7 +3303,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, argumentList, &failMessage);
         if (failMessage)
         {
             .error(loc, "%s `%s%s%s` is not callable using argument types `%s`",
@@ -3331,7 +3349,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, argumentList);
                         if (mErr.last > MATCH.nomatch && mErr.lastf)
                         {
                             errorSupplemental(loc, "%s `%s` hides base class function `%s`",
@@ -3345,7 +3363,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, argumentList, &failMessage);
         if (failMessage)
             errorSupplemental(loc, failMessage);
     }
@@ -3362,8 +3380,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;
@@ -3619,6 +3639,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;
@@ -3660,6 +3683,8 @@ private bool checkEscapingSiblings(FuncDeclaration f, FuncDeclaration outerFunc,
             prev = prev.p;
         }
     }
+    f.hasEscapingSiblings = bAnyClosures;
+    f.computedEscapingSiblings = true;
     //printf("\t%d\n", bAnyClosures);
     return bAnyClosures;
 }
@@ -3859,7 +3884,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)
@@ -4350,6 +4375,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`
@@ -4392,7 +4437,7 @@ bool setUnsafe(Scope* sc,
     }
 
 
-    if (sc.flags & SCOPE.compile) // __traits(compiles, x)
+    if (isRootTraitsCompilesScope(sc)) // __traits(compiles, x)
     {
         if (sc.func.isSafeBypassingInference())
         {
index 80c183e5a7727e5e9b36ccc922a1269cb564a33d..1919d9ae0ce1e0a53907a77443d1384100c1ed6d 100644 (file)
@@ -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;
@@ -143,7 +145,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
@@ -176,6 +178,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
@@ -291,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:
@@ -345,6 +350,8 @@ extern (C++) struct Global
 
     extern (C++) void _init()
     {
+        global.errorSink = new ErrorSinkCompiler;
+
         this.fileManager = new FileManager();
         version (MARS)
         {
index 45c5624b19c124aac822a98ee63f9091451b147b..ec8fc32ed0f52871737bb85afdc8f2ed2bbbe97c 100644 (file)
@@ -19,6 +19,7 @@
 // Can't include arraytypes.h here, need to declare these directly.
 template <typename TYPE> struct Array;
 
+class ErrorSink;
 class FileManager;
 struct Loc;
 
@@ -179,6 +180,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<const char *> modFileAliasStrings; // array of char*'s of -I module filename alias strings
@@ -277,6 +279,7 @@ struct Global
     unsigned varSequenceNumber;
 
     FileManager* fileManager;
+    ErrorSink* errorSink;       // where the error messages go
 
     FileName (*preprocess)(FileName, const Loc&, bool&, OutBuffer&);
 
index 68670d929e50019db77407be1b51d47a4f6d8af2..c7e5690bc0a7e9d9486e48ee83776ad1d72ce90f 100644 (file)
@@ -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;
@@ -144,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;
@@ -805,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;
@@ -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);
         }
     }
 
@@ -2136,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(')');
         }
     }
@@ -2440,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(')');
     }
 
@@ -2683,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)
     {
@@ -2691,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] == '.')
@@ -2733,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;
@@ -2814,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;
@@ -3281,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;
@@ -3292,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)
index baf6b14b97d84a948e591ba0b8c6555e5f0b96c2..f8c88ab536e9cccd5cfa2d2829244f07bdc4d652 100644 (file)
@@ -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;
index 40a5c6e47f680dd6ff0aefd84c8c3d0b48c45276..ec5cb25ef28abf5ee25ff96481bb186f580fc8e8 100644 (file)
@@ -313,6 +313,8 @@ immutable Msgtable[] msgtable =
     { "__ArrayDtor" },
     { "_d_delThrowable" },
     { "_d_newThrowable" },
+    { "_d_newclassT" },
+    { "_d_newclassTTrace" },
     { "_d_assert_fail" },
     { "dup" },
     { "_aaApply" },
@@ -455,6 +457,7 @@ immutable Msgtable[] msgtable =
     { "isLazy" },
     { "hasMember" },
     { "identifier" },
+    { "fullyQualifiedName" },
     { "getProtection" },
     { "getVisibility" },
     { "parent" },
index 572753b2dd868cf55841a66ea38b79e3525dca3f..18b10b41a2d3e19acacca01bd7ccc080acaef681 100644 (file)
@@ -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;
+}
index 38e03e7d20dcc08810bb814615e28960578bfc2e..2af7faec354d6c74eedb6896a887cc174ff3548f 100644 (file)
@@ -54,7 +54,7 @@ public:
     int indentLevel;
     const(char)[] filename;
 
-    extern (D) this(OutBuffer* buf)
+    extern (D) this(OutBuffer* buf) scope
     {
         this.buf = buf;
     }
index c800273e2d41e93c5ec050dbdd134d558c0e9cf0..885a27af9059588647bed7a88b7c8b9a119a2ca4 100644 (file)
@@ -120,7 +120,7 @@ public:
     OutBuffer buf;
     alias visit = SemanticTimeTransitiveVisitor.visit;
 
-    this(Scope* sc)
+    this(Scope* sc) scope
     {
         this.sc = sc;
     }
index bd53433d6c832c5fd26a2adc287265f4563448aa..c9ed35ffa6d5015876e8248496f866a8122b4a80 100644 (file)
@@ -22,8 +22,7 @@ import core.stdc.string;
 import core.stdc.time;
 
 import dmd.entity;
-import dmd.errors;
-import dmd.globals;
+import dmd.errorsink;
 import dmd.id;
 import dmd.identifier;
 import dmd.location;
@@ -69,6 +68,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,12 +104,14 @@ 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,
-        const(char)[] vendor = "DLF", uint versionNumber = 1) pure
+        ErrorSink errorSink,
+        const(char)[] vendor = "DLF", uint versionNumber = 1) pure scope
     {
         scanloc = Loc(filename, 1, 1);
         // debug printf("Lexer::Lexer(%p)\n", base);
@@ -123,6 +126,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 +168,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() { }
+    this(ErrorSink errorSink) scope { assert(errorSink); this.eSink = errorSink; }
 
     /**************************************
      * Reset lexer to lex #define's
@@ -565,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)
                         {
@@ -1616,7 +1623,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 +1916,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 +1934,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 +2144,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 +2156,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 +2209,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 +2626,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 +2654,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 +2695,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 +2856,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;
     }
 
@@ -3077,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;
@@ -3088,15 +3091,15 @@ 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);
         const p = ctime(&ct);
         assert(p);
-        sprintf(&date[0], "%.6s %.4s", p + 4, p + 20);
-        sprintf(&time[0], "%.8s", p + 11);
-        sprintf(&timestamp[0], "%.24s", p);
+        snprintf(&date[0], date.length, "%.6s %.4s", p + 4, p + 20);
+        snprintf(&time[0], time.length, "%.8s", p + 11);
+        snprintf(&timestamp[0], timestamp.length, "%.24s", p);
     }
 }
 
@@ -3217,19 +3220,15 @@ private bool c_isalnum(const int c) pure @nogc @safe
 
 unittest
 {
-    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;
+    fprintf(stderr, "Lexer.unittest %d\n", __LINE__);
+
+    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();
+        Lexer lexer = new Lexer(errorSink);
         assert(expected == lexer.escapeSequence(Loc.initial, p, Ccompile, c2));
         assert(p == sequence.ptr + sequence.length);
     }
@@ -3266,45 +3265,51 @@ unittest
     test(`&quot;`, '"');
     test(`&lt;`, '<');
     test(`&gt;`, '>');
-
-    diagnosticHandler = null;
 }
 
 unittest
 {
-    import dmd.console;
-    string expected;
-    bool gotError;
+    fprintf(stderr, "Lexer.unittest %d\n", __LINE__);
 
-    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:
+
+        import core.stdc.stdio;
+        import core.stdc.stdarg;
 
-        gotError = true;
-        char[100] buffer = void;
-        auto actual = buffer[0 .. vsprintf(buffer.ptr, format, ap)];
-        assert(expected == actual);
-        return true;
+        string expected;
+        bool gotError;
+
+        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);
+        }
     }
 
-    diagnosticHandler = &expectDiagnosticHandler;
+    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();
+        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);
@@ -3338,17 +3343,16 @@ unittest
     test("&quot", `unterminated named entity &quot;`, '?', 5);
 
     test("400", `escape octal sequence \400 is larger than \377`, 0x100, 3);
-
-    diagnosticHandler = null;
 }
 
 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);
+    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);
@@ -3363,9 +3367,10 @@ unittest
 
 unittest
 {
+    fprintf(stderr, "Lexer.unittest %d\n", __LINE__);
+
     // 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 =
@@ -3383,7 +3388,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, errorSink);
         TOK tok = lex2.nextToken();
         size_t iterations = 1;
         while ((tok != TOK.endOfFile) && (iterations++ < testcase.length))
index bc89ac4677eeb3826c3e30ccd056da9e773bf26c..002bb1a875b8d2f4e8e85d4059f03d4ddbea1408 100644 (file)
@@ -170,3 +170,5 @@ struct ModuleDeclaration
 
     const char *toChars() const;
 };
+
+extern void getLocalClasses(Module* mod, Array<ClassDeclaration* >& aclasses);
index 232042d9f4fab74425f3e47606f30a4c95d64390..5939db5ba854e4c9d60e8dcac189b894e3a31674 100644 (file)
@@ -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;
     }
@@ -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, 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, FuncResolveFlag.quiet);
+            auto fd = resolveFuncCall(Loc.initial, null, td, null, this, ArgumentList(), FuncResolveFlag.quiet);
             if (!fd || fd.errors || !fd.functionSemantic())
                 return Type.terror;
 
@@ -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
@@ -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;
@@ -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
+     *      argumentList = 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, Expression[] args, 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());
         MATCH match = MATCH.exact; // assume exact match
@@ -4669,8 +4669,7 @@ extern (C++) final class TypeFunction : TypeNext
         }
 
         const nparams = parameterList.length;
-        const nargs = args.length;
-        if (nargs > nparams)
+        if (argumentList.length > nparams)
         {
             if (parameterList.varargs == VarArg.none)
             {
@@ -4684,22 +4683,39 @@ 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 > argumentList.length && !parameterList.hasDefaultArgs)
         {
             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)argumentList.length);
             if (pMessage)
                 *pMessage = buf.extractChars();
             return MATCH.nomatch;
         }
+        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)
         {
-            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 +4749,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 +4762,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 +4777,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 +4790,97 @@ 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);
         return match;
     }
 
+    /********************************
+     * 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
+     *      pMessage = address to store error message, or `null`
+     * Returns: re-ordered argument list, or `null` on error
+     */
+    extern(D) Expressions* resolveNamedArgs(ArgumentList argumentList, const(char)** pMessage)
+    {
+        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)
+        {
+            if (!arg)
+            {
+                ci++;
+                continue;
+            }
+            auto name = i < names.length ? names[i] : null;
+            if (name)
+            {
+                hasNamedArgs = true;
+                const pi = findParameterIndex(name);
+                if (pi == -1)
+                {
+                    if (pMessage)
+                        *pMessage = getMatchError("no parameter named `%s`", name.toChars());
+                    return null;
+                }
+                ci = pi;
+            }
+            if (ci >= newArgs.length)
+            {
+                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 null;
+                }
+                while (ci >= newArgs.length)
+                    newArgs.push(null);
+            }
+
+            if ((*newArgs)[ci])
+            {
+                if (pMessage)
+                    *pMessage = getMatchError("parameter `%s` assigned twice", parameterList[ci].toChars());
+                return null;
+            }
+            (*newArgs)[ci++] = arg;
+        }
+        foreach (i, arg; (*newArgs)[])
+        {
+            if (arg || 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 null;
+        }
+        // strip trailing nulls from default arguments
+        size_t e = newArgs.length;
+        while (e > 0 && (*newArgs)[e - 1] is null)
+        {
+            --e;
+        }
+        newArgs.setDim(e);
+        return newArgs;
+    }
+
     /+
      + Checks whether this function type is convertible to ` to`
      + when used in a function pointer / delegate.
@@ -4871,9 +4969,18 @@ extern (C++) final class TypeFunction : TypeNext
     }
 
     /// Returns: whether `this` function type has the same attributes (`@safe`,...) as `other`
-    bool attributesEqual(const scope TypeFunction other) const pure nothrow @safe @nogc
-    {
-        return this.trust == other.trust &&
+    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):
+        // Two overloads that are identical except for one having an explicit `@system`
+        // attribute is currently in deprecation, and will become an error in 2.104 for
+        // `extern(C)`, and 2.112 for `extern(D)` code respectively. Once the deprecation
+        // period has passed, the trustSystemEqualsDefault=true behaviour should be made
+        // the default, then we can remove the `cannot overload extern(...) function`
+        // errors as they will become dead code as a result.
+        return (this.trust == other.trust ||
+                (trustSystemEqualsDefault && this.trust <= TRUST.system && other.trust <= TRUST.system)) &&
                 this.purity == other.purity &&
                 this.isnothrow == other.isnothrow &&
                 this.isnogc == other.isnogc &&
@@ -4884,6 +4991,23 @@ extern (C++) final class TypeFunction : TypeNext
     {
         v.visit(this);
     }
+
+    /**
+     * 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)
+        {
+            if (p.ident == ident)
+                return i;
+        }
+        return -1;
+    }
 }
 
 /***********************************************************
@@ -6507,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;
+    }
 }
 
 
@@ -6975,7 +7121,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, ArgumentList(&args), FuncResolveFlag.quiet);
             if (!f || f.storage_class & STC.disable)
                 return false;
         }
index 370e3b81d20fb246cc0591335276dc7459524938..201f168527cb71c92c9a2686e91c9a7c934abc97 100644 (file)
 
 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;
@@ -34,9 +37,10 @@ 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)
+    extern (D) this(FuncDeclaration f) scope
     {
         this.f = f;
     }
@@ -64,6 +68,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;
@@ -75,24 +103,14 @@ public:
         auto fd = stripHookTraceImpl(e.f);
         if (fd.ident == Id._d_arraysetlengthT)
         {
-            if (f.setGC())
-            {
-                e.error("setting `length` in `@nogc` %s `%s` may cause a GC allocation",
-                    f.kind(), f.toPrettyChars());
-                err = true;
+            if (setGC(e, "setting `length` in `@nogc` %s `%s` may cause a GC allocation"))
                 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 (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");
         }
     }
@@ -101,13 +119,8 @@ public:
     {
         if (e.type.ty != Tarray || !e.elements || !e.elements.length || e.onstack)
             return;
-        if (f.setGC())
-        {
-            e.error("array literal in `@nogc` %s `%s` may cause a GC allocation",
-                f.kind(), f.toPrettyChars());
-            err = true;
+        if (setGC(e, "array literal in `@nogc` %s `%s` may cause a GC allocation"))
             return;
-        }
         f.printGCUsage(e.loc, "array literal may cause a GC allocation");
     }
 
@@ -115,13 +128,8 @@ public:
     {
         if (!e.keys.length)
             return;
-        if (f.setGC())
-        {
-            e.error("associative array literal in `@nogc` %s `%s` may cause a GC allocation",
-                f.kind(), f.toPrettyChars());
-            err = true;
+        if (setGC(e, "associative array literal in `@nogc` %s `%s` may cause a GC allocation"))
             return;
-        }
         f.printGCUsage(e.loc, "associative array literal may cause a GC allocation");
     }
 
@@ -136,13 +144,9 @@ public:
             return;
         if (global.params.ehnogc && e.thrownew)
             return;                     // separate allocator is called for this, not the GC
-        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");
     }
 
@@ -164,13 +168,8 @@ public:
         Type t1b = e.e1.type.toBasetype();
         if (e.modifiable && t1b.ty == Taarray)
         {
-            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");
         }
     }
@@ -179,13 +178,8 @@ public:
     {
         if (e.e1.op == EXP.arrayLength)
         {
-            if (f.setGC())
-            {
-                e.error("setting `length` in `@nogc` %s `%s` may cause a GC allocation",
-                    f.kind(), f.toPrettyChars());
-                err = true;
+            if (setGC(e, "setting `length` in `@nogc` %s `%s` may cause a GC allocation"))
                 return;
-            }
             f.printGCUsage(e.loc, "setting `length` may cause a GC allocation");
         }
     }
@@ -196,6 +190,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,29 +204,43 @@ public:
 
     override void visit(CatExp e)
     {
-        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");
     }
 }
 
 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.
+     */
+    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;
 }
index 31e93a7637f15a4d8a43ff1d0f55cdf368acaaa8..9cff76b84aa2fe8930af04ebd20cf165b4dff7a9 100644 (file)
@@ -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;
@@ -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");
                 }
             }
         }
index 4d7fe9fcea362b1741f25ff2cc950fede69036c6..3c80e5e1d0e749375d6f7333b23e289a36cd7b60 100644 (file)
@@ -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, 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);
+                    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);
+                            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);
+                            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);
+                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);
+            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);
+            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();
         }
@@ -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
index 6eb3021dd82e9a90bc9434f1b3b103a6ba71e96a..36a76f50da20590abc9560533b1901b1258ad00b 100644 (file)
@@ -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)
+    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");
@@ -64,8 +67,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;
         }
 
@@ -74,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)
+    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");
@@ -167,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;
@@ -286,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;
@@ -799,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)
                         {
@@ -887,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));
                     }
@@ -1240,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
@@ -1285,7 +1290,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)
@@ -2170,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;
             }
 
@@ -2420,7 +2428,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
         tf = tf.addSTC(stc);
 
         auto f = new AST.CtorDeclaration(loc, Loc.initial, stc, tf);
-        AST.Dsymbol s = parseContracts(f);
+        AST.Dsymbol s = parseContracts(f, !!tpl);
         if (udas)
         {
             auto a = new AST.Dsymbols();
@@ -2879,43 +2887,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_);
@@ -3270,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();
@@ -3283,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;
@@ -3670,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;
@@ -3734,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;
         }
@@ -4482,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)
             {
@@ -4519,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");
                 }
@@ -4558,7 +4529,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;
                 }
             }
@@ -4571,7 +4542,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                     pAttrs.storageClass = STC.undefined_;
                 if (tpl)
                     constraint = parseConstraint();
-                AST.Dsymbol s = parseContracts(f);
+                AST.Dsymbol s = parseContracts(f, !!tpl);
                 auto tplIdent = s.ident;
 
                 if (link != linkage)
@@ -4697,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;
                 }
@@ -4720,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();
         }
     }
@@ -4940,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());
                         }
                     }
 
@@ -4990,7 +4961,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;
@@ -5132,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();
@@ -5157,7 +5128,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
     /*****************************************
      * Parse contracts following function declaration.
      */
-    private AST.FuncDeclaration parseContracts(AST.FuncDeclaration f)
+    private AST.FuncDeclaration parseContracts(AST.FuncDeclaration f, bool isTemplateFunction = false)
     {
         LINK linksave = linkage;
 
@@ -5329,7 +5300,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                 else if (t == TOK.at)
                     error("attributes cannot be placed after a template constraint");
                 else if (t == TOK.if_)
-                    error("cannot use function constraints for non-template functions. Use `static if` instead");
+                {
+                    if (isTemplateFunction)
+                        error("template constraint must follow parameter lists and attributes");
+                    else
+                        error("cannot use function constraints for non-template functions. Use `static if` instead");
+                }
                 else
                     error("semicolon expected following function declaration");
             }
@@ -5352,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());
         }
     }
 
@@ -5395,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());
     }
 
     /*****************************************
@@ -5450,6 +5426,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
                     stc = STC.out_;
                     goto Lagain;
 
+                case TOK.auto_:
+                    error("cannot declare `auto` loop variable, omit `auto` to still get type inference");
+                    stc = STC.auto_;
+                    goto Lagain;
+
                 case TOK.enum_:
                     stc = STC.manifest;
                     goto Lagain;
@@ -5525,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;
         }
@@ -5798,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
@@ -6501,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;
                     }
@@ -7060,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();
     }
 
@@ -7330,7 +7311,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)
@@ -7625,24 +7606,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))
@@ -8144,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());
 
@@ -8280,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);
@@ -8425,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;
@@ -8488,7 +8451,7 @@ LagainStc:
                 // ( expression )
                 nextToken();
                 e = parseExpression();
-                e.parens = 1;
+                e.parens = true;
                 check(loc, TOK.rightParenthesis);
                 break;
             }
@@ -8758,14 +8721,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_:
@@ -8907,7 +8862,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:
@@ -9342,26 +9300,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;
     }
 
     /*******************************************
@@ -9372,13 +9356,18 @@ LagainStc:
 
         nextToken();
         AST.Expressions* arguments = null;
+        AST.Identifiers* names = null;
 
         // An anonymous nested class starts with "class"
         if (token.value == TOK.class_)
         {
             nextToken();
             if (token.value == TOK.leftParenthesis)
-                arguments = parseArguments();
+            {
+                arguments = new AST.Expressions();
+                names = new AST.Identifiers();
+                parseNamedArguments(arguments, names);
+            }
 
             AST.BaseClasses* baseclasses = null;
             if (token.value != TOK.leftCurly)
@@ -9420,10 +9409,12 @@ LagainStc:
         }
         else if (token.value == TOK.leftParenthesis && t.ty != Tsarray)
         {
-            arguments = parseArguments();
+            arguments = new AST.Expressions();
+            names = new AST.Identifiers();
+            parseNamedArguments(arguments, names);
         }
 
-        auto e = new AST.NewExp(loc, thisexp, t, arguments);
+        auto e = new AST.NewExp(loc, thisexp, t, arguments, names);
         return e;
     }
 
index 9975c9c1f1ea441c2487e650eb1232e171e4ea2a..d85105d6f202a155e2039a72dcfb1d53f4f58a2d 100644 (file)
@@ -14,6 +14,7 @@ module dmd.printast;
 import core.stdc.stdio;
 
 import dmd.expression;
+import dmd.ctfeexpr;
 import dmd.tokens;
 import dmd.visitor;
 import dmd.hdrgen;
@@ -38,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;
     }
@@ -210,6 +211,14 @@ extern (C++) final class PrintASTVisitor : Visitor
         printf(".init: %s\n", e.initializer ? e.initializer.toChars() : "");
     }
 
+    override void visit(ClassReferenceExp e)
+    {
+        visit(cast(Expression)e);
+        printIndent(indent + 2);
+        printf(".value: %s\n", e.value ? e.value.toChars() : "");
+        printAST(e.value, indent + 2);
+    }
+
     static void printIndent(int indent)
     {
         foreach (i; 0 .. indent)
index 42d13994126ed7e861cdbaf10a51d903122e3295..1d450505a4dad694ac3f8a0a3f47923fb60a092a 100644 (file)
@@ -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)
         {
index e352c61ce6bf456999d1212e971026d63abf9e21..541a12d9e1db3fa5c8394395b1b6db30cf2a2171 100644 (file)
@@ -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;
@@ -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
index cd336e63f722d7043fb146c67bd31673986c5b4d..aae56fac02b24260b71744f6967d7d05f8097ca4 100644 (file)
@@ -50,7 +50,7 @@ extern (C++) struct CTFloat
     static real_t parse(const(char)* literal, out bool isOutOfRange);
 
     @system
-    static int sprint(char* str, char fmt, real_t x);
+    static int sprint(char* str, size_t size, char fmt, real_t x);
 
     // Constant real values 0, 1, -1 and 0.5.
     __gshared real_t zero;
index 44bd959edd9ff51d1ce6c0b08f526c3fe061a471..d2f795bf9e912c442ec4e6c571081e20525fc229 100644 (file)
@@ -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, 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);
 
index 33f4a7aa4b155017af4a9eb52f69989318706174..387361568e07576bb57510ef7caa8cb6e6cfe88c 100644 (file)
@@ -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
     {
index 89774119d4d6600e2061c3ac6f71bf7107ff06a4..62142331013a04755228762c901c6c730772562d 100644 (file)
@@ -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);
index 4437d1622e4a156230d89283f102f0202f6bce93..7138841caa02ae3d95a2fb97521649573d60f306 100644 (file)
@@ -38,7 +38,7 @@ enum DYNCAST : int
 
 extern (C++) class RootObject
 {
-    this() nothrow pure @nogc @safe
+    this() nothrow pure @nogc @safe scope
     {
     }
 
index 848602897b987bd8fd7efbff969eed579a6de756..ef0151656b1dd68ebea3071adbe0fdd3abe66dd8 100644 (file)
@@ -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;
     }
index c103f60689b8953b7718a281781ded0744e06f4b..440e4cbc8e7a2d2a915e6c3c38f70bfe2121b010 100644 (file)
@@ -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;
     }
@@ -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;
         }
@@ -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
@@ -462,7 +466,19 @@ private extern(C++) final class Semantic2Visitor : Visitor
 
                 // Different attributes don't conflict in extern(D)
                 if (!sameAttr && linkage1 == LINK.d)
+                {
+                    // @@@DEPRECATED_2.112@@@
+                    // 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))
+                    {
+                        f2.deprecation("cannot overload `extern(%s)` function at %s",
+                                linkageToChars(f1._linkage),
+                                f1.loc.toChars());
+                    }
                     return 0;
+                }
 
                 error(f2.loc, "%s `%s%s` conflicts with previous declaration at %s",
                         f2.kind(),
index 78da4a15a42e9244a2450d05bc221af463425dbd..33a43187fa8af1eba32976cc97f20630f37eb635 100644 (file)
@@ -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;
     }
@@ -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;
@@ -712,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, ArgumentList(), FuncResolveFlag.quiet);
                         if (!fd)
                         {
                             funcdecl.error("no match for implicit `super()` call in constructor");
@@ -1600,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;
index ed938762babc30969576051820b26b999caf53a6..60a74cc2812b7ae9e5b0c07b2f89d7da415f6ee5 100644 (file)
@@ -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
         {
         }
 
index 96c59ba219c27af8a32daafc7b95b88c354a943d..90728fb6fec5a4695e4ec7fc76d57ee19a4c0c54 100644 (file)
@@ -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)
     {
index 76a39912718ccd9c3defcb93aaccfb2aefd082a5..46cc4dadf6461751e36a6a42bcbd870d87f304ad 100644 (file)
@@ -381,6 +381,7 @@ public:
     IfStatement *syntaxCopy() override;
 
     void accept(Visitor *v) override { v->visit(this); }
+    bool isIfCtfeBlock();
 };
 
 class ConditionalStatement final : public Statement
@@ -667,7 +668,7 @@ public:
     TryFinallyStatement *tf;
     ScopeGuardStatement *os;
     VarDeclaration *lastVar;
-
+    bool inCtfeBlock;
     GotoStatement *syntaxCopy() override;
 
     void accept(Visitor *v) override { v->visit(this); }
@@ -685,7 +686,7 @@ public:
     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); }
index 5764efd60fd8331f53a5bb056def92bfbafbbf59..bbaee8e61523862036ac4a0f21cba67a82180b93 100644 (file)
@@ -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;
@@ -160,7 +161,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
     Statement result;
     Scope* sc;
 
-    this(Scope* sc)
+    this(Scope* sc) scope
     {
         this.sc = sc;
     }
@@ -1276,7 +1277,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, ArgumentList(&a), FuncResolveFlag.quiet))
                         tfront = f.type;
                 }
                 else if (auto d = sfront.toAlias().isDeclaration())
@@ -1491,7 +1492,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;
@@ -1955,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
@@ -2222,7 +2233,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)
                 {
@@ -2256,7 +2269,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;
 
@@ -2485,7 +2498,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;
             }
 
@@ -3798,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)
         {
@@ -3837,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)
@@ -4730,7 +4745,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();
index 8e8ba16c0ab58844b45a99d1faa7e50325d7f68e..12b21207b8e660ed4f65ddcd840cfb1881ab78a6 100644 (file)
@@ -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 @@ public:
 
     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; }
index 432daeea5c78cdcfb03526487137987e2d2e5044..1a9d2520c84ec597e8bba9c8cb0c0828ab04b3ee 100644 (file)
@@ -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;
index b3cd2d3c4036a59bb3013553a94be4d0734d6e73..aec3a77dee8cdf0a6c6952742aa733d15a872277 100644 (file)
@@ -269,11 +269,13 @@ enum TOK : ubyte
     _Thread_local,
 
     // C only extended keywords
+    _assert,
     _import,
     __cdecl,
     __declspec,
     __stdcall,
     __pragma,
+    __int128,
     __attribute__,
 }
 
@@ -579,11 +581,13 @@ private immutable TOK[] keywords =
     TOK._Thread_local,
 
     // C only extended keywords
+    TOK._assert,
     TOK._import,
     TOK.__cdecl,
     TOK.__declspec,
     TOK.__stdcall,
     TOK.__pragma,
+    TOK.__int128,
     TOK.__attribute__,
 ];
 
@@ -612,7 +616,9 @@ 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__,
+                       _assert ];
 
         foreach (kw; Ckwds)
             tab[kw] = cast(TOK) kw;
@@ -878,11 +884,13 @@ 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",
         TOK.__stdcall      : "__stdcall",
         TOK.__pragma       : "__pragma",
+        TOK.__int128       : "__int128",
         TOK.__attribute__  : "__attribute__",
     ];
 
@@ -942,16 +950,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:
@@ -960,36 +969,36 @@ nothrow:
                 OutBuffer buf;
                 buf.writeSingleCharLiteral(cast(dchar) intvalue);
                 buf.writeByte('\0');
-                p = buf.extractSlice().ptr;
+                p = buf.extractChars();
             }
             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_:
@@ -1006,7 +1015,7 @@ nothrow:
                 if (postfix)
                     buf.writeByte(postfix);
                 buf.writeByte(0);
-                p = buf.extractSlice().ptr;
+                p = buf.extractChars();
             }
             break;
         case TOK.identifier:
@@ -1116,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`);
 }
 
 /**
@@ -1147,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'`);
 }
index 32ae5f437c40e2278121ac2bd04de92bd3f77d36..87361f327a4f87cac2a7bedd1cc26c4d9f8f4e09 100644 (file)
@@ -278,11 +278,13 @@ enum class TOK : unsigned char
     _Thread_local_,
 
     // C only extended keywords
+    _assert,
     _import,
     cdecl_,
     declspec,
     stdcall,
     pragma,
+    int128_,
     attribute__,
 
     MAX,
index 048c24f7b22c8af483cd5c0fd09402caf53121d3..de0129b5b332adba5f3882bfb8bb41fccb84e3b5 100644 (file)
@@ -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;
@@ -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);
 
@@ -739,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)
@@ -995,6 +1035,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();
@@ -1676,7 +1723,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;
@@ -2197,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,
@@ -2227,6 +2274,7 @@ private void traitNotFound(TraitsExp e)
             &Id.isReturnOnStack,
             &Id.hasMember,
             &Id.identifier,
+            &Id.fullyQualifiedName,
             &Id.getProtection,
             &Id.getVisibility,
             &Id.parent,
index 0d64ba46a503c528dc55fe220288d0fb8d3b5d77..84561ac467aa4d14aecebd5ace0bca6fbaca6620 100644 (file)
@@ -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;
@@ -285,54 +286,10 @@ private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymb
                     return helper3();
             }
         }
+
         if (!sm)
-        {
-            if (!t)
-            {
-                if (s.isDeclaration()) // var, func, or tuple declaration?
-                {
-                    t = s.isDeclaration().type;
-                    if (!t && s.isTupleDeclaration()) // expression tuple?
-                        return helper3();
-                }
-                else if (s.isTemplateInstance() ||
-                         s.isImport() || s.isPackage() || s.isModule())
-                {
-                    return helper3();
-                }
-            }
-            if (t)
-            {
-                sm = t.toDsymbol(sc);
-                if (sm && id.dyncast() == DYNCAST.identifier)
-                {
-                    sm = sm.search(loc, cast(Identifier)id, IgnorePrivateImports);
-                    if (!sm)
-                        return helper3();
-                }
-                else
-                    return helper3();
-            }
-            else
-            {
-                if (id.dyncast() == DYNCAST.dsymbol)
-                {
-                    // searchX already handles errors for template instances
-                    assert(global.errors);
-                }
-                else
-                {
-                    assert(id.dyncast() == DYNCAST.identifier);
-                    sm = s.search_correct(cast(Identifier)id);
-                    if (sm)
-                        error(loc, "identifier `%s` of `%s` is not defined, did you mean %s `%s`?", id.toChars(), mt.toChars(), sm.kind(), sm.toChars());
-                    else
-                        error(loc, "identifier `%s` of `%s` is not defined", id.toChars(), mt.toChars());
-                }
-                pe = ErrorExp.get();
-                return;
-            }
-        }
+            return helper3();
+
         s = sm.toAlias();
     }
 
@@ -580,6 +537,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
         {
             auto errors = global.errors;
             mtype.dim = semanticLength(sc, tbn, mtype.dim);
+            mtype.dim = mtype.dim.implicitCastTo(sc, Type.tsize_t);
             if (errors != global.errors)
                 return error();
 
@@ -636,7 +594,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
                  * run on them for the size, since they may be forward referenced.
                  */
                 bool overflow = false;
-                if (mulu(tbn.size(loc), d2, overflow) >= target.maxStaticDataSize || overflow)
+                if (mulu(tbn.size(loc), d2, overflow) > target.maxStaticDataSize || overflow)
                     return overflowError();
             }
         }
@@ -1285,20 +1243,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'
@@ -1389,7 +1334,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
@@ -1398,7 +1342,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);
@@ -1425,11 +1368,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.
@@ -3912,8 +3850,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);
@@ -4973,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);
 
index b35e03de91f9f420c8e2cd65c5a9db820e60a49a..2ca71437d14a9a4383e6c63d7214b833d6bdc77e 100644 (file)
@@ -105,10 +105,11 @@ 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);
 
 private TypeInfoDeclaration getTypeInfoDeclaration(Type t)
 {
index e4c2a91e7f7adf377e58cd9777a69e62f0f758aa..8990ce49a2a9dd7aedae0bdc280221709d165645 100644 (file)
@@ -248,7 +248,7 @@ extern (C++) class StoppableVisitor : Visitor
 public:
     bool stop;
 
-    final extern (D) this()
+    final extern (D) this() scope
     {
     }
 }
index 4311edcc2d6039d0d7684913bc81b43ea2852328..c6245ff5fc19f4b89eeb8ce4bae4862c3526f6ef 100644 (file)
@@ -2277,8 +2277,7 @@ public:
        else
          {
            /* Generate: _d_newclass()  */
-           tree arg = build_address (get_classinfo_decl (cd));
-           new_call = build_libcall (LIBCALL_NEWCLASS, tb, 1, arg);
+           new_call = build_expr (e->lowering);
          }
 
        /* Set the context pointer for nested classes.  */
index 25a6bcebfffe14e243a0080df6ad33e4d32e2aa0..bb0a3dcc911bb2e24f9250853d275095415334ef 100644 (file)
@@ -360,10 +360,6 @@ fpreview=dip1021
 D RejectNegative
 Implement DIP1021: Mutable function arguments.
 
-fpreview=dip25
-D RejectNegative
-Implement DIP25: Sealed references.
-
 fpreview=dtorfields
 D RejectNegative
 Destruct fields of partially constructed objects.
@@ -412,10 +408,6 @@ frevert=dip1000
 D RejectNegative
 Revert DIP1000: Scoped pointers.
 
-frevert=dip25
-D RejectNegative
-Revert DIP25: Sealed references.
-
 frevert=dtorfields
 D RejectNegative
 Don't destruct fields of partially constructed objects.
index 84deadacf9daac778c47d133580b57e0675e0228..f2180d30546ea5b0c975aa06815c3705a831b612 100644 (file)
@@ -530,11 +530,7 @@ layout_moduleinfo_fields (Module *decl, tree type)
 
   /* Array of local ClassInfo decls are laid out in the same way.  */
   ClassDeclarations aclasses;
-  for (size_t i = 0; i < decl->members->length; i++)
-    {
-      Dsymbol *member = (*decl->members)[i];
-      member->addLocalClass (&aclasses);
-    }
+  getLocalClasses (decl, aclasses);
 
   if (aclasses.length)
     {
@@ -564,11 +560,7 @@ layout_moduleinfo (Module *decl)
   ClassDeclarations aclasses;
   FuncDeclaration *sgetmembers;
 
-  for (size_t i = 0; i < decl->members->length; i++)
-    {
-      Dsymbol *member = (*decl->members)[i];
-      member->addLocalClass (&aclasses);
-    }
+  getLocalClasses (decl, aclasses);
 
   size_t aimports_dim = decl->aimports.length;
   for (size_t i = 0; i < decl->aimports.length; i++)
index a9b2453d2bdacf4e3fff9991347d43515dae5be2..23f8b64324efb4546c07eac4fbfbfe444eaf4de8 100644 (file)
@@ -59,9 +59,6 @@ DEF_D_RUNTIME (ARRAYBOUNDS_SLICEP, "_d_arraybounds_slicep", RT(VOID),
 DEF_D_RUNTIME (ARRAYBOUNDS_INDEXP, "_d_arraybounds_indexp", RT(VOID),
               P4(IMMUTABLE_CHARPTR, UINT, SIZE_T, SIZE_T), ECF_NORETURN)
 
-/* Used when calling new on a class.  */
-DEF_D_RUNTIME (NEWCLASS, "_d_newclass", RT(OBJECT), P1(CONST_CLASSINFO), 0)
-
 /* Used when calling delete on a stack-allocated class or interface.  */
 DEF_D_RUNTIME (CALLFINALIZER, "_d_callfinalizer", RT(VOID), P1(VOIDPTR), 0)
 DEF_D_RUNTIME (CALLINTERFACEFINALIZER, "_d_callinterfacefinalizer", RT(VOID),
index e3fa0eed4cb43a69d795d70851b5912b75923994..8bd6eb63d51e343d8aa5b78c8b8d94aa0f700270 100644 (file)
@@ -582,8 +582,9 @@ public:
     tree ifbody = void_node;
     tree elsebody = void_node;
 
-    /* Build the `then' branch.  */
-    if (s->ifbody)
+    /* Build the `then' branch, don't do code generation when the condition
+       is `if (__ctfe)', as that is always false at run-time.  */
+    if (s->ifbody && !s->isIfCtfeBlock ())
       {
        push_stmt_list ();
        this->build_stmt (s->ifbody);
index 08bb1bb2f47d5c381871b5c4619a6a010a27a495..1c5e50c03c0962ca36225bb928c21478615a25f5 100644 (file)
@@ -1524,10 +1524,12 @@ get_cpp_typeinfo_decl (ClassDeclaration *decl)
   return decl->cpp_type_info_ptr_sym;
 }
 
-/* Get the exact TypeInfo for TYPE, if it doesn't exist, create it.  */
+/* Get the exact TypeInfo for TYPE, if it doesn't exist, create it.
+   When GENERATE is true, push the TypeInfo as a member of MOD so that it will
+   get code generation. */
 
 void
-create_typeinfo (Type *type, Module *mod)
+create_typeinfo (Type *type, Module *mod, bool generate)
 {
   if (!Type::dtypeinfo)
     create_frontend_tinfo_types ();
@@ -1685,7 +1687,7 @@ create_typeinfo (Type *type, Module *mod)
 
       /* If this has a custom implementation in rt/typeinfo, then
         do not generate a COMDAT for it.  */
-      if (!builtin_typeinfo_p (t))
+      if (generate && !builtin_typeinfo_p (t))
        {
          /* Find module that will go all the way to an object file.  */
          if (mod)
index 483173d01fca3d2e5a22b3d798561cdcc989a531..beaf2a61af999d833be0f67a01e87b6873122ebd 100644 (file)
@@ -381,9 +381,9 @@ layout_aggregate_members (Dsymbols *members, tree context, bool inherited_p)
            continue;
 
          /* If this variable was really a tuple, add all tuple fields.  */
-         if (var->aliassym)
+         if (var->aliasTuple)
            {
-             TupleDeclaration *td = var->aliassym->isTupleDeclaration ();
+             TupleDeclaration *td = var->aliasTuple;
              Dsymbols tmembers;
              /* No other way to coerce the underlying type out of the tuple.
                 Frontend should have already validated this.  */
diff --git a/gcc/testsuite/gdc.dg/torture/simd23084.d b/gcc/testsuite/gdc.dg/torture/simd23084.d
new file mode 100644 (file)
index 0000000..ad18813
--- /dev/null
@@ -0,0 +1,16 @@
+// https://issues.dlang.org/show_bug.cgi?id=23084
+// { dg-additional-options "-mavx" { target avx_runtime } }
+// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } }
+// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
+
+__vector(int[4]) test23084a(__vector(int[4]) a)
+{
+    __vector(short[8]) r = cast(short)(a.array[0]);
+    return cast(__vector(int[4]))r;
+}
+
+__vector(int[4]) test23084b(__vector(int[4]) a)
+{
+    __vector(byte[16]) r = cast(byte)(a.array[0]);
+    return cast(__vector(int[4]))r;
+}
diff --git a/gcc/testsuite/gdc.dg/torture/simd23085.d b/gcc/testsuite/gdc.dg/torture/simd23085.d
new file mode 100644 (file)
index 0000000..66444ad
--- /dev/null
@@ -0,0 +1,11 @@
+// https://issues.dlang.org/show_bug.cgi?id=23085
+// { dg-additional-options "-mavx" { target avx_runtime } }
+// { dg-do compile }
+// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
+
+float test23085(float x)
+{
+    byte i = *cast(byte*)&x;
+    ++i;
+    return *cast(float*)&i; // this cast is not allowed in @safe code
+}
diff --git a/gcc/testsuite/gdc.dg/torture/simd23218.d b/gcc/testsuite/gdc.dg/torture/simd23218.d
new file mode 100644 (file)
index 0000000..865fc82
--- /dev/null
@@ -0,0 +1,15 @@
+// https://issues.dlang.org/show_bug.cgi?id=23218
+// { dg-additional-options "-mavx" { target avx_runtime } }
+// { dg-do run { target { avx_runtime || vect_sizes_16B_8B } } }
+// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
+
+__vector(int[4]) convtest(int[4] a)
+{
+    return cast(__vector(int[4]))a;
+}
+
+void main()
+{
+    static assert(convtest([1,2,3,4])[0] == 1);
+    assert(convtest([1,2,3,4])[0] == 1);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/b23620.d b/gcc/testsuite/gdc.test/compilable/b23620.d
new file mode 100644 (file)
index 0000000..1eb1dcd
--- /dev/null
@@ -0,0 +1,10 @@
+// https://issues.dlang.org/show_bug.cgi?id=23620
+struct Index
+{
+    uint value;
+    alias value this;
+}
+
+enum i = Index();
+int[i] a;
+static assert(a.length == 0);
index 64d8ad073cf54f4a0db93848faf0056e4c20b831..a0fb8333d1b37004f5fb69f35549e32e7ad4ca54 100644 (file)
@@ -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();
index 54598dd77695fb12d07075fdd1aaeedb453da915..74f035e40d3de15e195e35f43a3ffaf9fc80d753 100644 (file)
@@ -1,5 +1,5 @@
 struct BugInt
 {
-    uint[] data = ZEROX;  
+    uint[] data = ZEROX;
 }
 enum uint [] ZEROX = [0];
diff --git a/gcc/testsuite/gdc.test/compilable/extra-files/test23626a.d b/gcc/testsuite/gdc.test/compilable/extra-files/test23626a.d
new file mode 100644 (file)
index 0000000..a134592
--- /dev/null
@@ -0,0 +1,49 @@
+template fullyQualifiedName(T...)
+{
+    enum fullyQualifiedName = !T[0];
+}
+
+void __trace_maybeDumpTupleToFile(Args...)(auto ref const Args args) nothrow @nogc { }
+
+int getStructInfoEx(T)() {
+   enum Ctx = fullyQualifiedName!T;
+   return 0;
+}
+
+auto as(Func)(Func) {}
+
+@nogc void foo() { }
+
+void assertOp(string OPERATION, LHS, RHS)(LHS lhs, RHS) {
+  as({
+    try {
+      try as(lhs);
+      catch(Throwable) foo();
+    } catch(Throwable) assert(false);
+  });
+}
+
+struct FixedArray(T, size_t capacity_) {
+  int a = getStructInfoEx!FixedArray;
+
+  T* some_function() {
+    assertOp !""(1, 1);
+    return null;
+  }
+  alias some_function this;
+}
+
+struct ReclamationBatch {
+
+  FixedArray !(uint,1) dummy;
+
+  @nogc nothrow void some_inout_func() inout { }
+
+  void func_2(Dlg)(Dlg dlg) {
+    __trace_maybeDumpTupleToFile(dlg);
+  }
+
+  void _reclaimBatch() {
+    func_2({ some_inout_func; });
+  }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/extra-files/test23626b.d b/gcc/testsuite/gdc.test/compilable/extra-files/test23626b.d
new file mode 100644 (file)
index 0000000..8bb2af5
--- /dev/null
@@ -0,0 +1,14 @@
+interface Timeline {
+}
+
+struct Policy {
+  alias OldTagCallback = void delegate() @nogc nothrow;
+  Timeline timeline;
+  OldTagCallback oldTagCB;
+}
+
+import test23626;
+
+struct Tiering {
+    StaticHashTable!(Policy) policies;
+}
index 466b2e0449f4daeba7a34818c6102959b89ece8b..a4540d1eac87d5bd1be2898117eedbdc491949a1 100644 (file)
@@ -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/gcc/testsuite/gdc.test/compilable/imports/imp23662.c b/gcc/testsuite/gdc.test/compilable/imports/imp23662.c
new file mode 100644 (file)
index 0000000..1556bc9
--- /dev/null
@@ -0,0 +1,6 @@
+// https://issues.dlang.org/show_bug.cgi?id=23662
+typedef enum {A} E;
+
+E func(E v) {
+    return v;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/infer_stc.d b/gcc/testsuite/gdc.test/compilable/infer_stc.d
new file mode 100644 (file)
index 0000000..50140e7
--- /dev/null
@@ -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/gcc/testsuite/gdc.test/compilable/named_argumens_struct.d b/gcc/testsuite/gdc.test/compilable/named_argumens_struct.d
new file mode 100644 (file)
index 0000000..0c60509
--- /dev/null
@@ -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/gcc/testsuite/gdc.test/compilable/named_arguments.d b/gcc/testsuite/gdc.test/compilable/named_arguments.d
new file mode 100644 (file)
index 0000000..f287ccd
--- /dev/null
@@ -0,0 +1,74 @@
+
+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");
+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");
+
+// 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;
+       }
+
+       static C opCall(int x, int y) { return new C(x, y); }
+}
+
+struct S
+{
+       int x, y;
+}
+
+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");
index 95c784627fa5ec657c9a70b78ce6213c2e48687f..44f54f7468ab394a511120e846051fb1a4eb54d6 100644 (file)
@@ -253,3 +253,12 @@ void main21209()
     testForeach(cs);
     testForeach(fs);
 }
+
+struct S23669
+{
+    string[] a;
+    @safe void reserve() scope
+    {
+        a.length += 1;
+    }
+}
index bfa84224d792f8d164c1d97a86c202fea2aa92f7..695083a5476e90a515e2735cc706a3dcee718a28 100644 (file)
@@ -123,3 +123,10 @@ struct Parent
         ch = shared Child(i);
     }
 }
+
+// https://issues.dlang.org/show_bug.cgi?id=23732
+class Class {}
+void main()
+{
+    auto b = new shared Class();
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test16495.d b/gcc/testsuite/gdc.test/compilable/test16495.d
new file mode 100644 (file)
index 0000000..70f11be
--- /dev/null
@@ -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/gcc/testsuite/gdc.test/compilable/test18026.d b/gcc/testsuite/gdc.test/compilable/test18026.d
new file mode 100644 (file)
index 0000000..97d83b4
--- /dev/null
@@ -0,0 +1,12 @@
+// https://issues.dlang.org/show_bug.cgi?id=18026
+bool f(T)(T x)
+{
+    return false;
+}
+
+static foreach(i; 0..60000)
+{
+    static if(f(i))
+    {
+    }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test19268.d b/gcc/testsuite/gdc.test/compilable/test19268.d
new file mode 100644 (file)
index 0000000..ff22403
--- /dev/null
@@ -0,0 +1,6 @@
+/* REQUIRED_ARGS: -betterC
+ */
+
+// https://issues.dlang.org/show_bug.cgi?id=19268
+
+mixin(`void foo(){}`.idup);
diff --git a/gcc/testsuite/gdc.test/compilable/test20201.d b/gcc/testsuite/gdc.test/compilable/test20201.d
new file mode 100644 (file)
index 0000000..b0419d6
--- /dev/null
@@ -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);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test21073.d b/gcc/testsuite/gdc.test/compilable/test21073.d
deleted file mode 100644 (file)
index 47d7881..0000000
+++ /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/gcc/testsuite/gdc.test/compilable/test21543.d b/gcc/testsuite/gdc.test/compilable/test21543.d
deleted file mode 100644 (file)
index 4914264..0000000
+++ /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/gcc/testsuite/gdc.test/compilable/test22916.d b/gcc/testsuite/gdc.test/compilable/test22916.d
new file mode 100644 (file)
index 0000000..9f779fd
--- /dev/null
@@ -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/gcc/testsuite/gdc.test/compilable/test23145.d b/gcc/testsuite/gdc.test/compilable/test23145.d
new file mode 100644 (file)
index 0000000..45235dc
--- /dev/null
@@ -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;
+}
index 0293f1272865573b8f944f520266550f30862e8e..c3ae19a21eb998b68d10fda8840ea0da9fc5983a 100644 (file)
@@ -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;
index 713267c0ecbc09e9897516f90f70a7f85bd8e5fd..dfffa456c8a141107e7341a6ef1be6adab8538fc 100644 (file)
@@ -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/gcc/testsuite/gdc.test/compilable/test23598.d b/gcc/testsuite/gdc.test/compilable/test23598.d
new file mode 100644 (file)
index 0000000..cdcb5a8
--- /dev/null
@@ -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/gcc/testsuite/gdc.test/compilable/test23606.d b/gcc/testsuite/gdc.test/compilable/test23606.d
new file mode 100644 (file)
index 0000000..4d8ab24
--- /dev/null
@@ -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();
diff --git a/gcc/testsuite/gdc.test/compilable/test23617.d b/gcc/testsuite/gdc.test/compilable/test23617.d
new file mode 100644 (file)
index 0000000..2d03ee7
--- /dev/null
@@ -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"();
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23626.d b/gcc/testsuite/gdc.test/compilable/test23626.d
new file mode 100644 (file)
index 0000000..ac19943
--- /dev/null
@@ -0,0 +1,8 @@
+// https://issues.dlang.org/show_bug.cgi?id=23626
+// EXTRA_SOURCES: extra-files/test23626a.d extra-files/test23626b.d
+module test23626;
+
+struct StaticHashTable(V)
+{
+    V v;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23639.d b/gcc/testsuite/gdc.test/compilable/test23639.d
new file mode 100644 (file)
index 0000000..e2ec002
--- /dev/null
@@ -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/gcc/testsuite/gdc.test/compilable/test23651.d b/gcc/testsuite/gdc.test/compilable/test23651.d
new file mode 100644 (file)
index 0000000..8c477b0
--- /dev/null
@@ -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!());
diff --git a/gcc/testsuite/gdc.test/compilable/test23662.d b/gcc/testsuite/gdc.test/compilable/test23662.d
new file mode 100644 (file)
index 0000000..884c399
--- /dev/null
@@ -0,0 +1,8 @@
+// https://issues.dlang.org/show_bug.cgi?id=23662
+// EXTRA_FILES: imports/imp23662.c
+import imports.imp23662;
+
+void main(string[] args) {
+    auto r = func(A);
+    assert(r == A);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23676.d b/gcc/testsuite/gdc.test/compilable/test23676.d
new file mode 100644 (file)
index 0000000..91a73b9
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test23679.d b/gcc/testsuite/gdc.test/compilable/test23679.d
new file mode 100644 (file)
index 0000000..9264d01
--- /dev/null
@@ -0,0 +1,3 @@
+// DISABLED: win32
+// https://issues.dlang.org/show_bug.cgi?id=23679
+ubyte [0x7fff_ffffU] arr;
diff --git a/gcc/testsuite/gdc.test/compilable/test5973.d b/gcc/testsuite/gdc.test/compilable/test5973.d
deleted file mode 100644 (file)
index a54b0ae..0000000
+++ /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/gcc/testsuite/gdc.test/compilable/test6777.d b/gcc/testsuite/gdc.test/compilable/test6777.d
deleted file mode 100644 (file)
index 161a94a..0000000
+++ /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;
-}
index c8390ba7dc30d09ffe44fa2e27c361ffa3a46967..77671eb853ff90f1a0d9e1c797c5315f24e52e49 100644 (file)
@@ -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/gcc/testsuite/gdc.test/fail_compilation/call_function_type.d b/gcc/testsuite/gdc.test/fail_compilation/call_function_type.d
new file mode 100644 (file)
index 0000000..da60092
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+TEST_OUTPUT:
+---
+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
+---
+*/
+
+// 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);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ctfeblock.d b/gcc/testsuite/gdc.test/fail_compilation/ctfeblock.d
new file mode 100644 (file)
index 0000000..2d8bf7a
--- /dev/null
@@ -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/gcc/testsuite/gdc.test/fail_compilation/deprecate_getVirtualFunctions.d b/gcc/testsuite/gdc.test/fail_compilation/deprecate_getVirtualFunctions.d
new file mode 100644 (file)
index 0000000..137482f
--- /dev/null
@@ -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")) {}
+}
index cf1b6459436b3830c84f57a9c355c53e751772de..46109247fb6a964ab7b5bfd1ada1d39981f1d303 100644 (file)
@@ -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`
 ---
 */
 
index 64db64d1e97964835241f3ce9ee10775fbd73a76..0bdfe50ca748920516251eb44c0b10223febaf17 100644 (file)
@@ -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
 ---
 */
 
index e015cfea7ac2fc5b37c7582a0f2b83b225943b62..307c6be1d09cd22306a8759b304b0ddd5ef736fd 100644 (file)
@@ -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;
+}
index 29261b4ea1c266f4a3fae67a5c5f971bfda52607..8c563ba44c9f9c519e2beebbe48589963782640e 100644 (file)
@@ -4,7 +4,7 @@ TEST_OUTPUT:
 ---
 fail_compilation/diag14235.d(12): Error: undefined identifier `Undefined` in module `imports.a14235`
 fail_compilation/diag14235.d(13): Error: undefined identifier `Something` in module `imports.a14235`, did you mean struct `SomeThing(T...)`?
-fail_compilation/diag14235.d(14): Error: `imports.a14235.SomeClass` is not a template, it is a class
+fail_compilation/diag14235.d(14): Error: `SomeClass` isn't a template
 ---
 */
 
index c4cbc721d860f7f199bf85fcc22660f8b7ee215f..0e4fb8b076f7f270a354b03e46016e035b9c4818 100644 (file)
@@ -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) { } }
index 9644fdd224209c5bcdc15fa06d53a19f780e673d..ddc74e28131f7212bc29f933d4cdc04e96fa2142 100644 (file)
@@ -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()
 {
index 5aea6b5f9c1a4dc77ab377795b1a8e1f6f948c83..58dd495ab8eb9299b32459a78e0068d07971fa5e 100644 (file)
@@ -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:
+    }
+}
index 4496f0c8920a943209a30da314a6279dcface85f..85923b7189e11db6e053f95dcd34f407de8eddb2 100644 (file)
@@ -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`?
 ---
 */
 
index 02f314077545b5c8958b99cc53756886b2a00c39..f43a6e9ef8d1d4af8fed8ab5c6a22b6fd2adc411 100644 (file)
@@ -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/gcc/testsuite/gdc.test/fail_compilation/dip25flag.d b/gcc/testsuite/gdc.test/fail_compilation/dip25flag.d
new file mode 100644 (file)
index 0000000..d75ceac
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+REQUIRED_ARGS: -de -dip25
+TEST_OUTPUT:
+---
+Deprecation: `-dip25` no longer has any effect
+---
+*/
index 5b65b1b345a97f21f0efa2571df0afed8d8cefa5..96b23e278cd905c813977da0bd37beeb1ef9f0ab 100644 (file)
@@ -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[()
index 90d8802d6d838b2e4768f639c15c2f53ac0fb149..51c8b1a66538ceb8c5a071c2ef76eae9049ec04e 100644 (file)
@@ -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;
index ab6ba3085502971222e405d4c8ac41a1f62deb94..8344a4701c778470fec483d52f6873a5e16ce0fa 100644 (file)
@@ -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`
 ---
 */
index 4847413ffea30d089fd2dad2f297859748b72f17..17577ec84f4ee974e9266e73b56cc52ea2d4dee9 100644 (file)
@@ -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
 ---
index 3725a913c5b6236ec2bdf9c7bdc1eb4da29413f1..f6c8fbb6804bad64ddc984f0dd5f834f1ac5fb18 100644 (file)
@@ -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
 ---
 */
 
index 6d8f184c9ea12ad78480d1da444f3fae3ad42c29..5f73f9a0ea5e4ec9e2232d9c99b17412ba147963 100644 (file)
@@ -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
 ---
 */
index bfc2383b590b5550b1c358bf1d280f883cf4d35c..ccb325415b2a2c708af5a2dbfe934fce30ccdd22 100644 (file)
@@ -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
 ---
 */
index e047365fbe3bac6350d57ab4c85eba9477389546..042eee12299aa820f2c1a6f0251ef8bba9b5050d 100644 (file)
@@ -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/gcc/testsuite/gdc.test/fail_compilation/fail15616c.d b/gcc/testsuite/gdc.test/fail_compilation/fail15616c.d
new file mode 100644 (file)
index 0000000..092590e
--- /dev/null
@@ -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/gcc/testsuite/gdc.test/fail_compilation/fail15616d.d b/gcc/testsuite/gdc.test/fail_compilation/fail15616d.d
new file mode 100644 (file)
index 0000000..a0f85a1
--- /dev/null
@@ -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);
+}
index 6f09f658487e7f5c80f006d7e4ab7764ab28b8cd..3253d1671626a66ba7435d837a1ff9f582cee30a 100644 (file)
@@ -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
 ---
 */
 
index f33149ea94d7e7fbfc945763cc079ece5068582e..95eb5cc8c1f92639456752d5e91b8f7835a5ae5d 100644 (file)
@@ -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`
 ---
 */
index 9bfc0a564eb94410e4684e1208cc595d56c58af2..2441d6f3caeeb2b9f7a7673725cc0c03cdbb286a 100644 (file)
@@ -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");
index 25df235e9cb6ca29fabcc48cf111dc0030dce76a..2e170d096c598891c6659267abf9bd60ab363cfd 100644 (file)
@@ -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/gcc/testsuite/gdc.test/fail_compilation/fail22039.d b/gcc/testsuite/gdc.test/fail_compilation/fail22039.d
new file mode 100644 (file)
index 0000000..3df834f
--- /dev/null
@@ -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; }
index cb8c286650d08abb8daa4aa3d71b5a51fcdcae2a..e937a480b45c1de4c96a892d7dd40850a0d33e98 100644 (file)
@@ -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/gcc/testsuite/gdc.test/fail_compilation/fail233.d b/gcc/testsuite/gdc.test/fail_compilation/fail233.d
deleted file mode 100644 (file)
index 7d4d978..0000000
+++ /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/gcc/testsuite/gdc.test/fail_compilation/fail23626a.d b/gcc/testsuite/gdc.test/fail_compilation/fail23626a.d
new file mode 100644 (file)
index 0000000..2943f1a
--- /dev/null
@@ -0,0 +1,16 @@
+/* TEST_OUTPUT:
+---
+fail_compilation/fail23626a.d(10): Deprecation: function `fail23626a.ambig` cannot overload `extern(D)` function at fail_compilation/fail23626a.d(9)
+fail_compilation/fail23626a.d(13): Deprecation: function `fail23626a.ambigC` cannot overload `extern(C)` function at fail_compilation/fail23626a.d(12)
+fail_compilation/fail23626a.d(16): Error: function `fail23626a.ambigCxx(int a)` conflicts with previous declaration at fail_compilation/fail23626a.d(15)
+---
+*/
+
+extern(D) int ambig(int a) { return 0; }
+extern(D) int ambig(int a) @system { return 1; }
+
+extern(C) int ambigC(int a) { return 2; }
+extern(C) int ambigC(int a) @system { return 3; }
+
+extern(C++) int ambigCxx(int a) { return 4; }
+extern(C++) int ambigCxx(int a) @system { return 5; }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23626b.d b/gcc/testsuite/gdc.test/fail_compilation/fail23626b.d
new file mode 100644 (file)
index 0000000..758a28b
--- /dev/null
@@ -0,0 +1,27 @@
+/* TEST_OUTPUT:
+---
+fail_compilation/fail23626b.d(26): Error: `fail23626b.AmbigOpApply.opApply` called with argument types `(int delegate(int i) pure nothrow @nogc @system)` matches both:
+fail_compilation/fail23626b.d(12):     `fail23626b.AmbigOpApply.opApply(int delegate(int) dg)`
+and:
+fail_compilation/fail23626b.d(17):     `fail23626b.AmbigOpApply.opApply(int delegate(int) dg)`
+---
+*/
+
+struct AmbigOpApply
+{
+    int opApply(int delegate(int) dg)
+    {
+        return 0;
+    }
+
+    int opApply(int delegate(int) dg) @system
+    {
+        return 0;
+    }
+}
+
+void ambigOpApply() @system
+{
+    AmbigOpApply sa;
+    foreach (int i; sa) { }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23745.d b/gcc/testsuite/gdc.test/fail_compilation/fail23745.d
new file mode 100644 (file)
index 0000000..eda9e1e
--- /dev/null
@@ -0,0 +1,22 @@
+// https://issues.dlang.org/show_bug.cgi?id=2374
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail23745.d(21): Error: undefined identifier `UndefinedType`
+fail_compilation/fail23745.d(14): Error: function `fun` does not override any function, did you mean to override `fail23745.A.fun`?
+fail_compilation/fail23745.d(21):        Function `fail23745.A.fun` contains errors in its declaration, therefore it cannot be correctly overriden
+---
+*/
+
+class B : A
+{
+    override void fun()
+    {
+    }
+}
+
+class A
+{
+    void fun(UndefinedType);
+}
index bee7e31eb3dd0e203719cd6ff5db5967eb97eb36..e6bfbedc7a33c25d25ed2c80a6e6077414cfb260 100644 (file)
@@ -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;
 }
index ffe506792829a105c5c305b03e8c5b5d49781fe5..832a9a8d193cdb0ce26e55f20d98377f7afd756e 100644 (file)
@@ -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
 ---
 */
 
index d885b3ef3ee7d21b70ddee2ca0be28a4c228d16e..603fe51db7b050cdb5edfa88cbcc00a95eb5379d 100644 (file)
@@ -16,6 +16,6 @@ class MinHeap(NodeType)
     unittest
     {
         struct TestType {}
-        MinHeap!(TestType) foo = new MinHeap!(TestType)();
+        MinHeap!(TestType) foo;
     }
 }
index 77042cc111bec33a4c3e687fa89b639e747a9968..5b51f54498f90c38395685f991892588ee7f3bce 100644 (file)
@@ -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)`
 ---
index be59e1f72b00272f86c950b14499bc586b3390bf..1ce98065882f1d979e4830c31f3b356f9ace84a1 100644 (file)
@@ -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/gcc/testsuite/gdc.test/fail_compilation/fail5851.d b/gcc/testsuite/gdc.test/fail_compilation/fail5851.d
deleted file mode 100644 (file)
index 236a956..0000000
+++ /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()
-{
-}
index 3fac1678e69ea457b0baf4d00bdf944b36729fa8..f209592196882a92b8414038713cbf9730944a5c 100644 (file)
@@ -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`
 ---
index e1553636ab7cc2ce829ec031d65e19f250c4f152..6fe86434e29f750363bd1809aca994045fa0fde2 100644 (file)
@@ -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/gcc/testsuite/gdc.test/fail_compilation/failinout3748a.d b/gcc/testsuite/gdc.test/fail_compilation/failinout3748a.d
deleted file mode 100644 (file)
index 77edb7e..0000000
+++ /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/gcc/testsuite/gdc.test/fail_compilation/failinout3748b.d b/gcc/testsuite/gdc.test/fail_compilation/failinout3748b.d
deleted file mode 100644 (file)
index b6dddd8..0000000
+++ /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;
-}
index 7fe73d3d179c274357d9b51e4fc8600e99d6e728..377125d569b5721ad595c415b615339d3d0f3050 100644 (file)
@@ -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
 ---
 */
 
index bd5264854092c4c31642e25092ee9f456180d32b..c8a4c4d93d4cb342aab42cd02d0317ca21347b21 100644 (file)
@@ -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/gcc/testsuite/gdc.test/fail_compilation/fnconstraint.d b/gcc/testsuite/gdc.test/fail_compilation/fnconstraint.d
new file mode 100644 (file)
index 0000000..5862f7a
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fnconstraint.d(13): Error: template constraint must follow parameter lists and attributes
+fail_compilation/fnconstraint.d(13): Error: declaration expected, not `if`
+fail_compilation/fnconstraint.d(22): Error: template constraint must follow parameter lists and attributes
+fail_compilation/fnconstraint.d(22): Error: declaration expected, not `if`
+fail_compilation/fnconstraint.d(26): Error: `}` expected following members in `struct` declaration at fail_compilation/fnconstraint.d(18)
+---
+*/
+void foo()()
+in(true)
+if (true)
+{}
+
+alias f = foo!();
+
+struct S
+{
+    this()()
+    if (true)
+    if (true) {}
+}
+
+S s;
index 9dfcc4da7dfa681399de66622707873b61cf5130..d11a7a69916ee4d22de6e3edfca3b607062c1c70 100644 (file)
@@ -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
 ---
 */
 
@@ -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);
index 6f100ee5124dc0191712eda7cfb5cff15e2e2862..e9179da74057c0ecbf3ce1d605d80efa092bc927 100644 (file)
@@ -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
 ---
 */
 
@@ -28,11 +28,13 @@ 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(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() {
@@ -44,7 +46,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 +142,8 @@ 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
+fail_compilation/fob2.d(612): Error: more than one mutable reference of `p` in arguments to `fob2.foo6b()`
 ---
 */
 
index 84d39ebae50d50ea4f3351ffb49b6b1d88e45623..b571059eb453ceca131a098e5773dd5dcaa41a17 100644 (file)
@@ -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
 ---
 */
 
index bf6af7b404f1ec04b256ef25157fb54270682617..13eb8e09ed86cba4d95c59dd3fa680d7afe33061 100644 (file)
@@ -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)
index ac430120d4979f53740981d821418cc40eb1cca6..03763f7c18a535857b0619ea8f88744bbfa9c70e 100644 (file)
@@ -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
 ---
 */
index 99f3c4a6c35ecb7148d6ac08005306b964de3b2c..3e3989bc290a902312950f7601d2d1e124bd05c4 100644 (file)
@@ -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`
 ---
 */
 
index e683e339e6125095a18ca97fc3413fb7bd99837e..aefe273da0c1ba2b1761055f4f8f257128f4cf05 100644 (file)
@@ -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()
index 253025cdc7a3be754899d4705ac81a3105dd7639..f41ab3e754f962c9c0f01d69fb811b04eceefa96 100644 (file)
@@ -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))`
index 277814f76cfabaa3eb5dc79783931b19805ade19..6fdb71a39763969e146d0829c841e62bf48afb17 100644 (file)
@@ -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
index 75e3b9f0b81029b51d8e397f7ef17532511ed094..fe4ad78f1accafe810de97e649c4eca253dde580 100644 (file)
@@ -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/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d
new file mode 100644 (file)
index 0000000..0900e60
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+TEST_OUTPUT:
+---
+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()
+{
+       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);
+       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;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/named_arguments_overload.d b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_overload.d
new file mode 100644 (file)
index 0000000..a970446
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+TEST_OUTPUT:
+---
+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)`
+---
+*/
+
+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/gcc/testsuite/gdc.test/fail_compilation/named_arguments_parse.d b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_parse.d
new file mode 100644 (file)
index 0000000..19e230e
--- /dev/null
@@ -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");
+}
index 9736d37e94920980470cb492b1d25c5eb3176eb7..5c581d1db71c2f1dcbc800cf061e1c362236cbbe 100644 (file)
@@ -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,5 @@ ref int escape23021() @safe
     // ensure we do not infer return ref
     return infer23021(nonScopePtr); // no error
 }
+
+/******************************/
index 7d15b16bdc1f787b00068d653a8d140a2884b07b..afdea64c744720dea5e3243b2e70486d594b5ce2 100644 (file)
@@ -86,7 +86,7 @@ fail_compilation/shared.d(2148): Error: direct access to shared `*c` is not allo
 fail_compilation/shared.d(2154): Error: direct access to shared `*c.c1` is not allowed, see `core.atomic`
 fail_compilation/shared.d(2160): Error: direct access to shared `*c.c1.c1` is not allowed, see `core.atomic`
 fail_compilation/shared.d(2181): Error: direct access to shared `k` is not allowed, see `core.atomic`
-fail_compilation/shared.d(2187): Error: direct access to shared `k.k2.k1` is not allowed, see `core.atomic`
+fail_compilation/shared.d(2187): Error: direct access to shared `k.k2.k1.value` is not allowed, see `core.atomic`
 fail_compilation/shared.d(2194): Error: direct access to shared `(new shared(K2)).k1` is not allowed, see `core.atomic`
 fail_compilation/shared.d(2202): Error: direct access to shared `c` is not allowed, see `core.atomic`
 fail_compilation/shared.d(2206): Error: function `shared.test_inference_2` function returns `shared` but cannot be inferred `ref`
@@ -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;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15368.d b/gcc/testsuite/gdc.test/fail_compilation/test15368.d
new file mode 100644 (file)
index 0000000..ab12e86
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test15368.d(13): Error: cannot declare `auto` loop variable, omit `auto` to still get type inference
+---
+*/
+
+// Issue 15368 - Improve error message for "auto" keyword inside "foreach"
+// https://issues.dlang.org/show_bug.cgi?id=15368
+
+void main()
+{
+    foreach (auto e; foo) { }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16495.d b/gcc/testsuite/gdc.test/fail_compilation/test16495.d
new file mode 100644 (file)
index 0000000..667d4c2
--- /dev/null
@@ -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);
+}
index e421419ae2d03a1dfecc761f0f372b523eef4eac..2c431a3849b33b498c8fc2d6db497fa3e29889c3 100644 (file)
@@ -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);
index a7ef88a0dba3326a624a979a683ccba10e57b390..b0cda2105a22aeff6230696b8dc365db60d8d9a7 100644 (file)
@@ -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
 ---
 */
index 2cafc1be9e23167b3f98a968917bedb14d887604..dc95da10eb534c1fe80de4da290c48103509502c 100644 (file)
@@ -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`
 ----
 */
 
index 44d3d5a36a3e180633c03a06f8d43e5813dd24b8..b9305f20f80fac4ff7311e1d0c33053cf0249a8b 100644 (file)
@@ -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
 ---
 */
index 44728c5c2ff83aa38d2718fd7a06c4ade5ab2623..0b452774245f7315b10e3677086c673477536a3c 100644 (file)
@@ -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`
 ---
  */
index 16eb02622d8dc3433f04707dc83689b978c3b833..2e137ab76316bb3f181cf696f02a9483b213123b 100644 (file)
@@ -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()`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22593.d b/gcc/testsuite/gdc.test/fail_compilation/test22593.d
deleted file mode 100644 (file)
index a47c0fe..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// https://issues.dlang.org/show_bug.cgi?id=22593
-
-/*
-TEST_OUTPUT:
----
-fail_compilation/test22593.d(14): Error: cannot define both an rvalue constructor and a copy constructor for `struct Foo`
-fail_compilation/test22593.d(22):        Template instance `__ctor!(immutable(Foo!int), immutable(Foo!int))` creates a rvalue constructor for `struct Foo`
-fail_compilation/test22593.d(22): Error: template instance `test22593.Foo!int.Foo.__ctor!(immutable(Foo!int), immutable(Foo!int))` error instantiating
----
-*/
-
-struct Foo(T)
-{
-    this(Rhs, this This)(scope Rhs rhs){}
-
-    this(ref scope typeof(this) rhs){}
-}
-
-void main()
-{
-    immutable Foo!int a;
-    a.__ctor(a);
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23607.d b/gcc/testsuite/gdc.test/fail_compilation/test23607.d
new file mode 100644 (file)
index 0000000..69b6f39
--- /dev/null
@@ -0,0 +1,16 @@
+//https://issues.dlang.org/show_bug.cgi?id=23607
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test23607.d(15): Error: template `to(T)()` does not have property `bad`
+fail_compilation/test23607.d(16): Error: template `to(T)()` does not have property `bad`
+---
+*/
+
+template to(T)
+{
+    void to(T)(){}
+}
+
+alias comb = to!int.bad!0;
+auto combe = to!int.bad!0;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23674.d b/gcc/testsuite/gdc.test/fail_compilation/test23674.d
new file mode 100644 (file)
index 0000000..0f11de9
--- /dev/null
@@ -0,0 +1,15 @@
+// https://issues.dlang.org/show_bug.cgi?id=23674
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test23674.d(14): Error: array index 2 is out of bounds `arr[0 .. 2]`
+fail_compilation/test23674.d(14): Error: array index 3 is out of bounds `arr[0 .. 2]`
+---
+*/
+
+void main()
+{
+    string[2] arr;
+    assert(arr[2] == arr[3]);
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test23710.d b/gcc/testsuite/gdc.test/fail_compilation/test23710.d
new file mode 100644 (file)
index 0000000..e834b78
--- /dev/null
@@ -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;
+}
index bfd8803d2f2a247aa5b9e6ffa8146423f3260088..41b6e52545e09aa552b140d4fede23ce21bc0fb8 100644 (file)
@@ -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
diff --git a/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d b/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d
new file mode 100644 (file)
index 0000000..96511f5
--- /dev/null
@@ -0,0 +1,47 @@
+// https://issues.dlang.org/show_bug.cgi?id=22593
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/testrvaluecpctor.d(16): Error: cannot define both an rvalue constructor and a copy constructor for `struct Foo`
+fail_compilation/testrvaluecpctor.d(24):        Template instance `testrvaluecpctor.Foo!int.Foo.__ctor!(immutable(Foo!int), immutable(Foo!int))` creates an rvalue constructor for `struct Foo`
+fail_compilation/testrvaluecpctor.d(24): Error: none of the overloads of `__ctor` are callable using a `immutable` object
+fail_compilation/testrvaluecpctor.d(18):        Candidates are: `testrvaluecpctor.Foo!int.Foo.this(ref Foo!int rhs)`
+fail_compilation/testrvaluecpctor.d(16):                        `__ctor(Rhs, this This)(scope Rhs rhs)`
+---
+*/
+
+struct Foo(T)
+{
+    this(Rhs, this This)(scope Rhs rhs){}
+
+    this(ref scope typeof(this) rhs){}
+}
+
+void fail22593()
+{
+    immutable Foo!int a;
+    a.__ctor(a);
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=21613
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/testrvaluecpctor.d(40): Error: cannot define both an rvalue constructor and a copy constructor for `struct Test`
+fail_compilation/testrvaluecpctor.d(46):        Template instance `testrvaluecpctor.Test.__ctor!()` creates an rvalue constructor for `struct Test`
+---
+*/
+
+struct Test
+{
+    this(ref const typeof(this) rhs){}
+    this()(const typeof(this) rhs){}    // rvalue ctor
+}
+
+void fail21613()
+{
+    const Test cb;
+    Test b = cb;
+}
index 86c6328e9e48115b0682c429c8a466fe7b7df39f..cc7b0125953f1a1607d353963755d9c7ee8e5f0a 100644 (file)
@@ -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`
 ---
 */
 
index ec4796789ac754823ac1e097beb626688aff8119..453ebba4e09c5946d053dbd94f2b3da83e7d21a0 100644 (file)
@@ -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
index db5913c83899897719a5e124ae2925ae06abb428..50e5c4db64bf60c49ecd727c2a0e7c248ae34c5c 100644 (file)
@@ -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:
index 6ee075089d14adafed52cdf39fb62b79e132ea6e..af95545ccc9b3c5554f3824608086fb522ad81ca 100644 (file)
@@ -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;
         }
index 0592d448b1f8adf9fc982decd6bab19b8889da54..711f309b7a2c3eac69f47a73520e64c1ecbf9f74 100644 (file)
@@ -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;
        }
index d32531055f540e5f75ceaa666451922675fe0292..ff66310ff2b4ae226436cd9eb040a8b4fe1e45a9 100644 (file)
@@ -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/gcc/testsuite/gdc.test/runnable/extra-files/test11051.d b/gcc/testsuite/gdc.test/runnable/extra-files/test11051.d
new file mode 100644 (file)
index 0000000..c8bfdc2
--- /dev/null
@@ -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;
+        }
+    }
+}
index 25b4e6e512ce13449596c17b92b3a8e52a606405..e6e4fec1c54d5552980949b88b479636616af87e 100644 (file)
@@ -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); });
diff --git a/gcc/testsuite/gdc.test/runnable/imports/freer.i b/gcc/testsuite/gdc.test/runnable/imports/freer.i
new file mode 100644 (file)
index 0000000..57e8792
--- /dev/null
@@ -0,0 +1,5 @@
+typedef struct Foo *FooRef;
+struct Foo {
+    int x;
+};
+void free_foo(FooRef foo) { }
diff --git a/gcc/testsuite/gdc.test/runnable/imports/maker.i b/gcc/testsuite/gdc.test/runnable/imports/maker.i
new file mode 100644 (file)
index 0000000..d3a7d94
--- /dev/null
@@ -0,0 +1,5 @@
+typedef struct Foo *FooRef;
+struct Foo {
+    int x;
+};
+FooRef make_foo(void) { return 0; }
index 16d4c5570a416b750482c45fa770d5820c4f8471..f9972f235e214e6070a7f83817b242f657890096 100644 (file)
@@ -4,6 +4,7 @@ TEST_OUTPUT:
 true
 g
 &Test109S(&Test109S(<recursion>))
+runnable/interpret.d(3742): Deprecation: alias this for classes/interfaces is deprecated
 tfoo
 tfoo
 Crash!
index c4cae17f95b2c676f94938d5bd4560f7e8c24443..155144b5bcb82ffbaf75734272c81b4a3412eb05 100644 (file)
@@ -2,12 +2,12 @@
 void main()
 {
     uint loops = 0;
-    static foreach (i; 0 .. 50)
+    static foreach (i; 0 .. 5)
     {
         static foreach (ch; SomeContainer().range)
             loops++;
     }
-    assert(loops == 50 * 50);
+    assert(loops == 5 * 5);
 }
 
 struct SomeContainer
@@ -20,7 +20,7 @@ struct TypeWithDestructor { ~this() { } }
 
 struct SomeRange
 {
-    int count = 50;
+    int count = 5;
     int front() { return count; }
     bool empty() { return count <= 0; }
     void popFront() { count--; }
index c981334a5b1017114b0e58a5f6c797f39688a5cb..b24eced9f7f4d014c2b5d1cb7d76e31bf7b847f2 100644 (file)
@@ -617,6 +617,17 @@ void test11565()
     assert(cond11565(true) == size_t.max);
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=23743
+void test23743()
+{
+    ubyte[] a = [1];
+    foreach (x; a)
+    {
+        ubyte v = x >= 1 ? 255 : 0;
+        assert(v == 255);
+    }
+}
+
 ///////////////////////
 
 int[3] array1 = [1:1,2,0:3];
@@ -2498,6 +2509,7 @@ int main()
     testdocond();
     testnegcom();
     test11565();
+    test23743();
     testoror();
     testbt();
     test12095(0);
index 7679bbe5b34e27925a845b293656e75a5c0f23fb..70bf051a46f986123e28ecd63b7793699b40b8ae 100644 (file)
@@ -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/gcc/testsuite/gdc.test/runnable/test15985.d b/gcc/testsuite/gdc.test/runnable/test15985.d
new file mode 100644 (file)
index 0000000..dbf4f4b
--- /dev/null
@@ -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; }
index 16b34f1894cb63117e17ba22bb32eb494a1f7b99..a5af2d564485fa0b112c9fcf53dbb034c2612ace 100644 (file)
@@ -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;
+}
index efdce0847ba06cfdb102ed09c10780fb1744bbd1..e10265558e8498afce19511b5f1c3376609678ed 100644 (file)
@@ -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/gcc/testsuite/gdc.test/runnable/test18472.d b/gcc/testsuite/gdc.test/runnable/test18472.d
new file mode 100644 (file)
index 0000000..a571b08
--- /dev/null
@@ -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;
+}
index a24d84173ec865180d4c79b2746769670c28691f..61a168bf918aa22a9c486e8e4846d6c8e9ab9292 100644 (file)
@@ -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/gcc/testsuite/gdc.test/runnable/test19946.d b/gcc/testsuite/gdc.test/runnable/test19946.d
new file mode 100644 (file)
index 0000000..9f9d3bc
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test20520.d b/gcc/testsuite/gdc.test/runnable/test20520.d
new file mode 100644 (file)
index 0000000..dd45266
--- /dev/null
@@ -0,0 +1,13 @@
+// https://issues.dlang.org/show_bug.cgi?id=20520
+
+class C {}
+
+enum Foo {
+    Bar = new C()
+}
+
+void main()
+{
+    //pragma(msg, typeid(Foo.Bar)); // Works fine: typeid(C())
+    auto t = typeid(Foo.Bar);     // Segfault here
+}
index 30152fe3914eca32f10a35d1c9c09cc3a21532fd..1d2ae50919a6a2d683adaac73c57dcce83daaa1b 100644 (file)
@@ -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;
 }
index c58600f8da094ec2126c113802dc74259d2f26ab..f32267ab59e006d26a4dff54157a9cb4b23129fc 100644 (file)
@@ -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/gcc/testsuite/gdc.test/runnable/test21772.d b/gcc/testsuite/gdc.test/runnable/test21772.d
new file mode 100644 (file)
index 0000000..dcb7b80
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test21821.d b/gcc/testsuite/gdc.test/runnable/test21821.d
new file mode 100644 (file)
index 0000000..d16331d
--- /dev/null
@@ -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();
+}
index f1fd4a6c2bc7f6548b96d3cc38d41a5a86bd9ba4..cb951c17faaf0e09c5d0768ea179532922cd790e 100644 (file)
@@ -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()
index 7872aa76dfe2571767dbea51022a33e2da609c7f..f97486404b3bef05b6deb345034bbd1d5baea2bf 100644 (file)
@@ -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/gcc/testsuite/gdc.test/runnable/test23387.d b/gcc/testsuite/gdc.test/runnable/test23387.d
new file mode 100644 (file)
index 0000000..4419cf1
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test23514.d b/gcc/testsuite/gdc.test/runnable/test23514.d
new file mode 100644 (file)
index 0000000..1ba7e21
--- /dev/null
@@ -0,0 +1,13 @@
+// DISABLED: win64
+// https://issues.dlang.org/show_bug.cgi?id=23514
+
+// Note: this test is disabled on Win64 because of an issue with the Windows
+// MS-COFF backend causing it to fail.
+
+enum ulong offset = 0xFFFF_FFFF_0000_0000UL;
+
+void main()
+{
+    ulong voffset = offset;
+    assert((cast(ulong)&main + voffset) == (cast(ulong)&main + offset));
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test23618.d b/gcc/testsuite/gdc.test/runnable/test23618.d
new file mode 100644 (file)
index 0000000..7cde3ff
--- /dev/null
@@ -0,0 +1,30 @@
+
+// https://issues.dlang.org/show_bug.cgi?id=23618
+
+import core.stdc.stdio;
+
+uint test1()
+{
+    ushort ee = 1028;
+    ee <<= 5U;
+    ee >>= 5U;
+    assert(ee == 1028);
+    //printf("%x, %d\n", ee, ee);
+    return ee;
+}
+
+uint test2()
+{
+    ubyte ee = 4;
+    ee <<= 5U;
+    ee >>= 5U;
+    //printf("%x, %d\n", ee, ee);
+    assert(ee == 4);
+    return ee;
+}
+
+void main()
+{
+    test1();
+    test2();
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test23650.d b/gcc/testsuite/gdc.test/runnable/test23650.d
new file mode 100644 (file)
index 0000000..3ce8f5f
--- /dev/null
@@ -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);
+    }));
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test23710.d b/gcc/testsuite/gdc.test/runnable/test23710.d
new file mode 100644 (file)
index 0000000..05ab1e4
--- /dev/null
@@ -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;
+}
index 11543f1ae85661452d492534e061684e5cefaced..df461370066404881674a20ac717ba5691061cc2 100644 (file)
@@ -1,5 +1,3 @@
-// REQUIRED_ARGS: -d
-
 module test34;
 
 import core.exception;
index d65ba0eb7ad3109d9272c0be09d559077cbfb5b9..f10076223d59b6e2b39ddbaeb03fb48116d087b5 100644 (file)
@@ -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 { }
 
index c55f82034994eb4a8b561103501acf3edb4b8f0c..ed5091dff018a040ef7bebd14440a8db2c8331c0 100644 (file)
@@ -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);
index 586aea80ccef258b2891116bfc0c6a5da9f8095d..79a4c57cf3b3c5b90b56e7c342ac7ac2b12980f3 100644 (file)
@@ -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
index 03af20710f2eebad51da1afe4fa7491578165dd5..269949fb0c0276f03b925d22397724d86dc70bd7 100644 (file)
@@ -494,7 +494,7 @@ void test23()
 int status24;
 
 class C24{
-        this(){
+        this() scope {
                 assert(status24==0);
                 status24+=2;
         }
index ddd505919d252e0f288473eeaa925607e2a9129b..5186987deaea57354da92d5bae515532deeef318 100644 (file)
@@ -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();
index 8996c9ebb8fd3930f97bd78faf1402fb8c896780..ffa0b803ade635f04d40e00ec910dca3717f0332 100644 (file)
@@ -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);
 }
 
 ///////////////////////////////////////
index a0907f4b856ca654966e85a0d5a14c305359c98d..e57f52f6578364f9a3b19fdea5b8e5a17289d3b7 100644 (file)
@@ -1,12 +1,15 @@
-// REQUIRED_ARGS: -d -preview=rvaluerefparam
+// REQUIRED_ARGS: -preview=rvaluerefparam
 //
 /* 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(<recursion>)))
@@ -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()
index b0288a25e0817909719b141ab56c6e3ef9205a33..224625c65ecb5b5bcbe64513799530ea2b0ea2d0 100644 (file)
@@ -1,13 +1,16 @@
 /*
-REQUIRED_ARGS: -d -lowmem -Jrunnable -preview=rvaluerefparam
+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(<recursion>))
@@ -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()
index c677d6e0be87bbbbaa2c8031758b8f84d664f820..c0f4e6dd78060bea2469c8ed920de53ceb4ed36a 100644 (file)
@@ -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();
 }
index cd91dd558340eefa22fa9c747c55815fb8fd575f..cb268af062230fd16e6464c77cb316183a67621e 100644 (file)
@@ -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
 
@@ -444,57 +442,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 +537,6 @@ void test14()
 
 version (linux)
 {
-    void test14a(std.allocator!int * pa)
-    {
-    pa.deallocate(null, 0);
-    }
-
     void gun(std.vector!int pa)
     {
     int x = 42;
@@ -1115,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");
 }
 
 /****************************************/
@@ -1362,7 +1324,7 @@ extern(C++)
     class Cpp15589Derived : Cpp15589Base
     {
     public:
-        this();
+        this() scope;
         final ~this();
         int b;
     }
@@ -1372,7 +1334,7 @@ extern(C++)
     public:
         void beforeDtor();
 
-        this();
+        this() scope;
         ~this();
 
         void afterDtor();
@@ -1382,7 +1344,7 @@ extern(C++)
     class Cpp15589DerivedVirtual : Cpp15589BaseVirtual
     {
     public:
-        this();
+        this() scope;
         ~this();
 
         override void afterDtor();
@@ -1393,7 +1355,7 @@ extern(C++)
     class Cpp15589IntroducingVirtual : Cpp15589Base
     {
     public:
-        this();
+        this() scope;
         void beforeIntroducedVirtual();
         ~this();
         void afterIntroducedVirtual(int);
@@ -1699,7 +1661,7 @@ void main()
     testeh2();
     testeh3();
     test15576();
-    test15579();
+    version (TEST15579) test15579();
     test15610();
     test15455();
     test15372();
index 8ba613920a4bb8305d08b8823a9a20340177506d..e1dcc28b8b1d7c7d9ed99d33de68e1a5595ce3fe 100644 (file)
@@ -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;
+}
index 32506238785abaa987c03e62e88a7f38dc3883cc..f6890e0cbd41993d5c641a34f23adfedb80b3a1d 100644 (file)
@@ -4,14 +4,26 @@ import core.stdc.config;
 
 extern(C++):
 
-version (AArch64) version = UnsignedChar;
-version (ARM)     version = UnsignedChar;
-version (RISCV32) version = UnsignedChar;
-version (RISCV64) version = UnsignedChar;
-version (PPC)     version = UnsignedChar;
-version (PPC64)   version = UnsignedChar;
-version (S390)    version = UnsignedChar;
-version (SystemZ) version = UnsignedChar;
+version (OSX)
+    version = Darwin;
+else version (iOS)
+    version = Darwin;
+else version (TVOS)
+    version = Darwin;
+else version (WatchOS)
+    version = Darwin;
+
+version (Darwin) { /* signed on ARM too */ } else
+{
+    version (AArch64) version = UnsignedChar;
+    version (ARM)     version = UnsignedChar;
+    version (RISCV32) version = UnsignedChar;
+    version (RISCV64) version = UnsignedChar;
+    version (PPC)     version = UnsignedChar;
+    version (PPC64)   version = UnsignedChar;
+    version (S390)    version = UnsignedChar;
+    version (SystemZ) version = UnsignedChar;
+}
 
 version (UnsignedChar)
     enum __c_char : ubyte;
index ac3dd1292685979e3dd29bba401c8eb7a6628118..269eebfc483ffc2d35cff980269cfcf3bcefe443 100644 (file)
@@ -1,4 +1,4 @@
-09faa4eacd4fb147107e94eeebf56b3a73fdcc05
+4ca4140e584c055a8a9bc727e56a97ebcecd61e0
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
index 18154dedd9b9486f6e199ed28664e12f0d12251e..8225ba4a0288ee8fb3391fd9573eceae37d8355d 100644 (file)
@@ -169,7 +169,7 @@ DRUNTIME_CSOURCES = core/stdc/errno_.c
 
 DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
        core/builtins.d core/checkedint.d core/cpuid.d core/demangle.d \
-       core/exception.d core/gc/config.d core/gc/gcinterface.d \
+       core/exception.d core/factory.d core/gc/config.d core/gc/gcinterface.d \
        core/gc/registry.d core/int128.d core/internal/abort.d \
        core/internal/array/appending.d core/internal/array/arrayassign.d \
        core/internal/array/capacity.d core/internal/array/casting.d \
index 3f04496bd7b48194e60b73c51445bfbb57b76f27..797d6435a7ce28d0519a021840e86a904edbdfea 100644 (file)
@@ -189,9 +189,10 @@ am__DEPENDENCIES_1 =
 am__dirstamp = $(am__leading_dot)dirstamp
 am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
        core/builtins.lo core/checkedint.lo core/cpuid.lo \
-       core/demangle.lo core/exception.lo core/gc/config.lo \
-       core/gc/gcinterface.lo core/gc/registry.lo core/int128.lo \
-       core/internal/abort.lo core/internal/array/appending.lo \
+       core/demangle.lo core/exception.lo core/factory.lo \
+       core/gc/config.lo core/gc/gcinterface.lo core/gc/registry.lo \
+       core/int128.lo core/internal/abort.lo \
+       core/internal/array/appending.lo \
        core/internal/array/arrayassign.lo \
        core/internal/array/capacity.lo core/internal/array/casting.lo \
        core/internal/array/comparison.lo \
@@ -838,7 +839,7 @@ libgdruntime_convenience_la_LINK = $(libgdruntime_la_LINK)
 DRUNTIME_CSOURCES = core/stdc/errno_.c
 DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
        core/builtins.d core/checkedint.d core/cpuid.d core/demangle.d \
-       core/exception.d core/gc/config.d core/gc/gcinterface.d \
+       core/exception.d core/factory.d core/gc/config.d core/gc/gcinterface.d \
        core/gc/registry.d core/int128.d core/internal/abort.d \
        core/internal/array/appending.d core/internal/array/arrayassign.d \
        core/internal/array/capacity.d core/internal/array/casting.d \
@@ -1188,6 +1189,7 @@ core/checkedint.lo: core/$(am__dirstamp)
 core/cpuid.lo: core/$(am__dirstamp)
 core/demangle.lo: core/$(am__dirstamp)
 core/exception.lo: core/$(am__dirstamp)
+core/factory.lo: core/$(am__dirstamp)
 core/gc/$(am__dirstamp):
        @$(MKDIR_P) core/gc
        @: > core/gc/$(am__dirstamp)
index 8a1dc8add894023873ace68264d1ed5d2e7129ec..c2a7c334eb77a0e8397b5ae9f47bb47b2401c7d1 100644 (file)
@@ -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;
     }
 }
 
index 1c2ac0677046fc7b76450c7f06cce14a214492ef..b79bd1df9c48971ce8139aa77c57b0b9c3d6f971 100644 (file)
@@ -1080,7 +1080,7 @@ void cpuidSparc()
 }
 */
 
-shared static this()
+pragma(crt_constructor) void cpuid_initialization()
 {
     auto cf = getCpuFeatures();
 
index fe273319f21320004978c5eff9d2b6847772e25b..3fcb26657c84074e4a446edac1ebed45a4ae176a 100644 (file)
@@ -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" );
@@ -2933,7 +2912,7 @@ CXX_DEMANGLER getCXXDemangler() nothrow @trusted
         version (linux) import core.sys.linux.dlfcn : RTLD_DEFAULT;
         version (NetBSD) import core.sys.netbsd.dlfcn : RTLD_DEFAULT;
         version (OpenBSD) import core.sys.openbsd.dlfcn : RTLD_DEFAULT;
-        version (OSX) import core.sys.darwin.dlfcn : RTLD_DEFAULT;
+        version (Darwin) import core.sys.darwin.dlfcn : RTLD_DEFAULT;
         version (Solaris) import core.sys.solaris.dlfcn : RTLD_DEFAULT;
 
         if (auto found = cast(CXX_DEMANGLER) dlsym(RTLD_DEFAULT, "__cxa_demangle"))
diff --git a/libphobos/libdruntime/core/factory.d b/libphobos/libdruntime/core/factory.d
new file mode 100644 (file)
index 0000000..f45a04e
--- /dev/null
@@ -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; }
index 46eb9b2755613d863c1a25a35e783758259b7127..20fa7dea1705a7864d7a5e3fc95e4edc97074c15 100644 (file)
@@ -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
 {
index 616d27cfe8327aff2986bc9234b44b91cd90b6e4..b609167eefe2f02122daef1a2c08f888fd7272de 100644 (file)
@@ -17,8 +17,6 @@ private enum isCopyingNothrow(T) = __traits(compiles, (ref T rhs) nothrow { T lh
 /// Implementation of `_d_arrayappendcTX` and `_d_arrayappendcTXTrace`
 template _d_arrayappendcTXImpl(Tarr : T[], T)
 {
-    import core.internal.array.utils : _d_HookTraceImpl;
-
     private enum errorMessage = "Cannot append to array if compiling without support for runtime type information!";
 
     /**
@@ -51,17 +49,22 @@ template _d_arrayappendcTXImpl(Tarr : T[], T)
             return px;
         }
         else
-            assert(0, "Cannot append arrays if compiling without support for runtime type information!");
+            assert(0, errorMessage);
     }
 
-    /**
-     * TraceGC wrapper around $(REF _d_arrayappendcTX, rt,array,appending,_d_arrayappendcTXImpl).
-     * Bugs:
-     *  This function template was ported from a much older runtime hook that bypassed safety,
-     *  purity, and throwabilty checks. To prevent breaking existing code, this function template
-     *  is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations.
-     */
-    alias _d_arrayappendcTXTrace = _d_HookTraceImpl!(Tarr, _d_arrayappendcTX, errorMessage);
+    version (D_ProfileGC)
+    {
+        import core.internal.array.utils : _d_HookTraceImpl;
+
+        /**
+         * TraceGC wrapper around $(REF _d_arrayappendcTX, rt,array,appending,_d_arrayappendcTXImpl).
+         * Bugs:
+         *  This function template was ported from a much older runtime hook that bypassed safety,
+         *  purity, and throwabilty checks. To prevent breaking existing code, this function template
+         *  is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations.
+         */
+        alias _d_arrayappendcTXTrace = _d_HookTraceImpl!(Tarr, _d_arrayappendcTX, errorMessage);
+    }
 }
 
 /// Implementation of `_d_arrayappendT`
@@ -71,7 +74,6 @@ ref Tarr _d_arrayappendT(Tarr : T[], T)(return ref scope Tarr x, scope Tarr y) @
 
     import core.stdc.string : memcpy;
     import core.internal.traits : hasElaborateCopyConstructor, Unqual;
-    import core.lifetime : copyEmplace;
 
     enum hasPostblit = __traits(hasPostblit, T);
     auto length = x.length;
@@ -81,6 +83,8 @@ ref Tarr _d_arrayappendT(Tarr : T[], T)(return ref scope Tarr x, scope Tarr y) @
     // Only call `copyEmplace` if `T` has a copy ctor and no postblit.
     static if (hasElaborateCopyConstructor!T && !hasPostblit)
     {
+        import core.lifetime : copyEmplace;
+
         foreach (i, ref elem; y)
             copyEmplace(elem, x[length + i]);
     }
@@ -107,20 +111,23 @@ ref Tarr _d_arrayappendT(Tarr : T[], T)(return ref scope Tarr x, scope Tarr y) @
     return x;
 }
 
-/**
- * TraceGC wrapper around $(REF _d_arrayappendT, core,internal,array,appending).
- */
-ref Tarr _d_arrayappendTTrace(Tarr : T[], T)(string file, int line, string funcname, return ref scope Tarr x, scope Tarr y) @trusted
+version (D_ProfileGC)
 {
-    version (D_TypeInfo)
+    /**
+     * TraceGC wrapper around $(REF _d_arrayappendT, core,internal,array,appending).
+     */
+    ref Tarr _d_arrayappendTTrace(Tarr : T[], T)(string file, int line, string funcname, return ref scope Tarr x, scope Tarr y) @trusted
     {
-        import core.internal.array.utils: TraceHook, gcStatsPure, accumulatePure;
-        mixin(TraceHook!(Tarr.stringof, "_d_arrayappendT"));
+        version (D_TypeInfo)
+        {
+            import core.internal.array.utils: TraceHook, gcStatsPure, accumulatePure;
+            mixin(TraceHook!(Tarr.stringof, "_d_arrayappendT"));
 
-        return _d_arrayappendT(x, y);
+            return _d_arrayappendT(x, y);
+        }
+        else
+            assert(0, "Cannot append to array if compiling without support for runtime type information!");
     }
-    else
-        assert(0, "Cannot append to array if compiling without support for runtime type information!");
 }
 
 @safe unittest
index 9440428ebd733074ec6e9bef70097e579bc40555..254e9501f632c4905b40086d380f325678bb50e9 100644 (file)
@@ -22,8 +22,6 @@ private extern (C) void[] _d_arraysetlengthiT(const TypeInfo ti, size_t newlengt
 /// Implementation of `_d_arraysetlengthT` and `_d_arraysetlengthTTrace`
 template _d_arraysetlengthTImpl(Tarr : T[], T)
 {
-    import core.internal.array.utils : _d_HookTraceImpl;
-
     private enum errorMessage = "Cannot resize arrays if compiling without support for runtime type information!";
 
     /**
@@ -54,14 +52,19 @@ template _d_arraysetlengthTImpl(Tarr : T[], T)
             assert(0, errorMessage);
     }
 
-    /**
-    * TraceGC wrapper around $(REF _d_arraysetlengthT, core,internal,array,core.internal.array.capacity).
-    * Bugs:
-    *  This function template was ported from a much older runtime hook that bypassed safety,
-    *  purity, and throwabilty checks. To prevent breaking existing code, this function template
-    *  is temporarily declared `@trusted pure nothrow` until the implementation can be brought up to modern D expectations.
-    */
-    alias _d_arraysetlengthTTrace = _d_HookTraceImpl!(Tarr, _d_arraysetlengthT, errorMessage);
+    version (D_ProfileGC)
+    {
+        import core.internal.array.utils : _d_HookTraceImpl;
+
+        /**
+         * TraceGC wrapper around $(REF _d_arraysetlengthT, core,internal,array,core.internal.array.capacity).
+         * Bugs:
+         *  This function template was ported from a much older runtime hook that bypassed safety,
+         *  purity, and throwabilty checks. To prevent breaking existing code, this function template
+         *  is temporarily declared `@trusted pure nothrow` until the implementation can be brought up to modern D expectations.
+         */
+        alias _d_arraysetlengthTTrace = _d_HookTraceImpl!(Tarr, _d_arraysetlengthT, errorMessage);
+    }
 }
 
 @safe unittest
index 955e3814769af24dead557bd282b5096f7938c3d..99f33da7683dc2abab463ac5e9960e10f262a430 100644 (file)
@@ -14,8 +14,6 @@ private extern (C) void[] _d_arraycatnTX(const TypeInfo ti, scope byte[][] arrs)
 /// Implementation of `_d_arraycatnTX` and `_d_arraycatnTXTrace`
 template _d_arraycatnTXImpl(Tarr : ResultArrT[], ResultArrT : T[], T)
 {
-    import core.internal.array.utils : _d_HookTraceImpl;
-
     private enum errorMessage = "Cannot concatenate arrays if compiling without support for runtime type information!";
 
     /**
@@ -45,14 +43,19 @@ template _d_arraycatnTXImpl(Tarr : ResultArrT[], ResultArrT : T[], T)
             assert(0, errorMessage);
     }
 
-    /**
-    * TraceGC wrapper around $(REF _d_arraycatnTX, core,internal,array,concat).
-    * Bugs:
-    *  This function template was ported from a much older runtime hook that bypassed safety,
-    *  purity, and throwabilty checks. To prevent breaking existing code, this function template
-    *  is temporarily declared `@trusted pure nothrow` until the implementation can be brought up to modern D expectations.
-    */
-    alias _d_arraycatnTXTrace = _d_HookTraceImpl!(ResultArrT, _d_arraycatnTX, errorMessage);
+    version (D_ProfileGC)
+    {
+        import core.internal.array.utils : _d_HookTraceImpl;
+
+        /**
+         * TraceGC wrapper around $(REF _d_arraycatnTX, core,internal,array,concat).
+         * Bugs:
+         *  This function template was ported from a much older runtime hook that bypassed safety,
+         *  purity, and throwabilty checks. To prevent breaking existing code, this function template
+         *  is temporarily declared `@trusted pure nothrow` until the implementation can be brought up to modern D expectations.
+         */
+        alias _d_arraycatnTXTrace = _d_HookTraceImpl!(ResultArrT, _d_arraycatnTX, errorMessage);
+    }
 }
 
 @safe unittest
index 41dfab6f349c56778c1b23d47a47baf5253ffed7..21894c29d38585a3361803d18310afb47662f951 100644 (file)
@@ -15,10 +15,17 @@ U[] _dup(T, U)(scope T[] a) pure nothrow @trusted if (__traits(isPOD, T))
     if (__ctfe)
         return _dupCtfe!(T, U)(a);
 
-    import core.stdc.string : memcpy;
-    auto arr = _d_newarrayU(typeid(T[]), a.length);
-    memcpy(arr.ptr, cast(const(void)*) a.ptr, T.sizeof * a.length);
-    return *cast(U[]*) &arr;
+    version (D_BetterC)
+    {
+        return _dupCtfe!(T, U)(a);
+    }
+    else
+    {
+        import core.stdc.string : memcpy;
+        auto arr = _d_newarrayU(typeid(T[]), a.length);
+        memcpy(arr.ptr, cast(const(void)*) a.ptr, T.sizeof * a.length);
+        return *cast(U[]*) &arr;
+    }
 }
 
 U[] _dupCtfe(T, U)(scope T[] a)
@@ -41,25 +48,32 @@ U[] _dup(T, U)(T[] a) if (!__traits(isPOD, T))
     if (__ctfe)
         return _dupCtfe!(T, U)(a);
 
-    import core.lifetime: copyEmplace;
-    U[] res = () @trusted {
-        auto arr = cast(U*) _d_newarrayU(typeid(T[]), a.length);
-        size_t i;
-        scope (failure)
-        {
-            import core.internal.lifetime: emplaceInitializer;
-            // Initialize all remaining elements to not destruct garbage
-            foreach (j; i .. a.length)
-                emplaceInitializer(cast() arr[j]);
-        }
-        for (; i < a.length; i++)
-        {
-            copyEmplace(a.ptr[i], arr[i]);
-        }
-        return cast(U[])(arr[0..a.length]);
-    } ();
+    version (D_BetterC)
+    {
+        return _dupCtfe!(T, U)(a);
+    }
+    else
+    {
+        import core.lifetime: copyEmplace;
+        U[] res = () @trusted {
+            auto arr = cast(U*) _d_newarrayU(typeid(T[]), a.length);
+            size_t i;
+            scope (failure)
+            {
+                import core.internal.lifetime: emplaceInitializer;
+                // Initialize all remaining elements to not destruct garbage
+                foreach (j; i .. a.length)
+                    emplaceInitializer(cast() arr[j]);
+            }
+            for (; i < a.length; i++)
+            {
+                copyEmplace(a.ptr[i], arr[i]);
+            }
+            return cast(U[])(arr[0..a.length]);
+        } ();
 
-    return res;
+        return res;
+    }
 }
 
 // https://issues.dlang.org/show_bug.cgi?id=22107
index 41aa57faf0ce6fd1bfa6a69dec3187daeec54d47..a16005e714de98916c331d756cd74a41d56230b6 100644 (file)
@@ -34,76 +34,79 @@ ulong accumulatePure(string file, int line, string funcname, string name, ulong
     return func(file, line, funcname, name, size);
 }
 
-/**
- * TraceGC wrapper generator around the runtime hook `Hook`.
- * Params:
- *   Type = The type of hook to report to accumulate
- *   Hook = The name hook to wrap
- */
-template TraceHook(string Type, string Hook)
+version (D_ProfileGC)
 {
-    const char[] TraceHook = q{
-        import core.internal.array.utils : gcStatsPure, accumulatePure;
-
-        pragma(inline, false);
-        string name = } ~ "`" ~ Type ~ "`;" ~ q{
-
-        // FIXME: use rt.tracegc.accumulator when it is accessable in the future.
-        version (tracegc)
-    } ~ "{\n" ~ q{
-            import core.stdc.stdio;
-
-            printf("%sTrace file = '%.*s' line = %d function = '%.*s' type = %.*s\n",
-            } ~ "\"" ~ Hook ~ "\".ptr," ~ q{
-                file.length, file.ptr,
-                line,
-                funcname.length, funcname.ptr,
-                name.length, name.ptr
-            );
-        } ~ "}\n" ~ q{
-        ulong currentlyAllocated = gcStatsPure().allocatedInCurrentThread;
-
-        scope(exit)
-        {
-            ulong size = gcStatsPure().allocatedInCurrentThread - currentlyAllocated;
-            if (size > 0)
-                if (!accumulatePure(file, line, funcname, name, size)) {
-                    // This 'if' and 'assert' is needed to force the compiler to not remove the call to
-                    // `accumulatePure`. It really want to do that while optimizing as the function is
-                    // `pure` and it does not influence the result of this hook.
-
-                    // `accumulatePure` returns the value of `size`, which can never be zero due to the
-                    // previous 'if'. So this assert will never be triggered.
-                    assert(0);
-                }
-        }
-    };
-}
+    /**
+     * TraceGC wrapper generator around the runtime hook `Hook`.
+     * Params:
+     *   Type = The type of hook to report to accumulate
+     *   Hook = The name hook to wrap
+     */
+    template TraceHook(string Type, string Hook)
+    {
+        const char[] TraceHook = q{
+            import core.internal.array.utils : gcStatsPure, accumulatePure;
+
+            pragma(inline, false);
+            string name = } ~ "`" ~ Type ~ "`;" ~ q{
+
+            // FIXME: use rt.tracegc.accumulator when it is accessable in the future.
+            version (tracegc)
+        } ~ "{\n" ~ q{
+                import core.stdc.stdio;
+
+                printf("%sTrace file = '%.*s' line = %d function = '%.*s' type = %.*s\n",
+                } ~ "\"" ~ Hook ~ "\".ptr," ~ q{
+                    file.length, file.ptr,
+                    line,
+                    funcname.length, funcname.ptr,
+                    name.length, name.ptr
+                );
+            } ~ "}\n" ~ q{
+            ulong currentlyAllocated = gcStatsPure().allocatedInCurrentThread;
+
+            scope(exit)
+            {
+                ulong size = gcStatsPure().allocatedInCurrentThread - currentlyAllocated;
+                if (size > 0)
+                    if (!accumulatePure(file, line, funcname, name, size)) {
+                        // This 'if' and 'assert' is needed to force the compiler to not remove the call to
+                        // `accumulatePure`. It really want to do that while optimizing as the function is
+                        // `pure` and it does not influence the result of this hook.
+
+                        // `accumulatePure` returns the value of `size`, which can never be zero due to the
+                        // previous 'if'. So this assert will never be triggered.
+                        assert(0);
+                    }
+            }
+        };
+    }
 
-/**
- * TraceGC wrapper around runtime hook `Hook`.
- * Params:
- *  T = Type of hook to report to accumulate
- *  Hook = The hook to wrap
- *  errorMessage = The error message incase `version != D_TypeInfo`
- *  file = File that called `_d_HookTraceImpl`
- *  line = Line inside of `file` that called `_d_HookTraceImpl`
- *  funcname = Function that called `_d_HookTraceImpl`
- *  parameters = Parameters that will be used to call `Hook`
- * Bugs:
- *  This function template needs be between the compiler and a much older runtime hook that bypassed safety,
- *  purity, and throwabilty checks. To prevent breaking existing code, this function template
- *  is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations.
-*/
-auto _d_HookTraceImpl(T, alias Hook, string errorMessage)(string file, int line, string funcname, Parameters!Hook parameters) @trusted pure
-{
-    version (D_TypeInfo)
+    /**
+     * TraceGC wrapper around runtime hook `Hook`.
+     * Params:
+     *  T = Type of hook to report to accumulate
+     *  Hook = The hook to wrap
+     *  errorMessage = The error message incase `version != D_TypeInfo`
+     *  file = File that called `_d_HookTraceImpl`
+     *  line = Line inside of `file` that called `_d_HookTraceImpl`
+     *  funcname = Function that called `_d_HookTraceImpl`
+     *  parameters = Parameters that will be used to call `Hook`
+     * Bugs:
+     *  This function template needs be between the compiler and a much older runtime hook that bypassed safety,
+     *  purity, and throwabilty checks. To prevent breaking existing code, this function template
+     *  is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations.
+    */
+    auto _d_HookTraceImpl(T, alias Hook, string errorMessage)(string file, int line, string funcname, Parameters!Hook parameters) @trusted pure
     {
-        mixin(TraceHook!(T.stringof, __traits(identifier, Hook)));
-        return Hook(parameters);
+        version (D_TypeInfo)
+        {
+            mixin(TraceHook!(T.stringof, __traits(identifier, Hook)));
+            return Hook(parameters);
+        }
+        else
+            assert(0, errorMessage);
     }
-    else
-        assert(0, errorMessage);
 }
 
 /**
index 0b4890cbfa9cc780253b0925ea7477dd969b8650..966839f176ac6dae9168da2d1bbfc36d88c9c5ad 100644 (file)
@@ -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]);
index 371308def7974b3ed49bd3a07d4bf392d6fc9821..5e339c041d12e69f5f1192ad9bc227d0bd9d1e0d 100644 (file)
@@ -2385,21 +2385,24 @@ template _d_delstructImpl(T)
         }
     }
 
-    import core.internal.array.utils : _d_HookTraceImpl;
+    version (D_ProfileGC)
+    {
+        import core.internal.array.utils : _d_HookTraceImpl;
 
-    private enum errorMessage = "Cannot delete struct if compiling without support for runtime type information!";
+        private enum errorMessage = "Cannot delete struct if compiling without support for runtime type information!";
 
-    /**
-     * TraceGC wrapper around $(REF _d_delstruct, core,lifetime,_d_delstructImpl).
-     *
-     * Bugs:
-     *   This function template was ported from a much older runtime hook that
-     *   bypassed safety, purity, and throwabilty checks. To prevent breaking
-     *   existing code, this function template is temporarily declared
-     *   `@trusted` until the implementation can be brought up to modern D
-     *   expectations.
-     */
-    alias _d_delstructTrace = _d_HookTraceImpl!(T, _d_delstruct, errorMessage);
+        /**
+         * TraceGC wrapper around $(REF _d_delstruct, core,lifetime,_d_delstructImpl).
+         *
+         * Bugs:
+         *   This function template was ported from a much older runtime hook that
+         *   bypassed safety, purity, and throwabilty checks. To prevent breaking
+         *   existing code, this function template is temporarily declared
+         *   `@trusted` until the implementation can be brought up to modern D
+         *   expectations.
+         */
+        alias _d_delstructTrace = _d_HookTraceImpl!(T, _d_delstruct, errorMessage);
+    }
 }
 
 @system pure nothrow unittest
@@ -2709,3 +2712,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!");
+}
index 7d1356af0be1a6dc6d73b06704d62de1507fdd8a..96c2af478d39e0923129ef4aacf47d445fc8a49b 100644 (file)
@@ -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)
     {
index 16bc47501e34813a73eb172dca2bf8a9dd349034..c85682ec0a6b8651b33b47542337198500f71ad2 100644 (file)
@@ -312,3 +312,28 @@ alias c_complex_float = __c_complex_float;
 alias c_complex_double = __c_complex_double;
 alias c_complex_real = __c_complex_real;
 }
+
+
+// Returns the mangled name for the 64-bit time_t versions of
+// functions affected by musl's transition to 64-bit time_t.
+// https://musl.libc.org/time64.html
+version (CRuntime_Musl)
+{
+    version (CRuntime_Musl_Pre_Time64)
+        enum muslRedirTime64 = false;
+    else
+    {
+        // time_t was defined as a C long in older Musl versions.
+        enum muslRedirTime64 = (c_long.sizeof == 4);
+    }
+}
+else
+    enum muslRedirTime64 = false;
+
+package(core) template muslRedirTime64Mangle(string name, string redirectedName)
+{
+    static if (muslRedirTime64)
+        enum muslRedirTime64Mangle = redirectedName;
+    else
+        enum muslRedirTime64Mangle = name;
+}
index b19c3c7a899f83b5819b1399308b8ff2bb8d30b0..d7a57655fabe63dd41702b91ecc57b2497dd87c3 100644 (file)
@@ -30,19 +30,25 @@ nothrow:
 @nogc:
 
 ///
+pragma(mangle, muslRedirTime64Mangle!("difftime", "__difftime64"))
 pure double  difftime(time_t time1, time_t time0); // MT-Safe
 ///
+pragma(mangle, muslRedirTime64Mangle!("mktime", "__mktime64"))
 @system time_t  mktime(scope tm* timeptr); // @system: MT-Safe env locale
 ///
+pragma(mangle, muslRedirTime64Mangle!("time", "__time64"))
 time_t  time(scope time_t* timer);
 
 ///
 @system char*   asctime(const scope tm* timeptr); // @system: MT-Unsafe race:asctime locale
 ///
+pragma(mangle, muslRedirTime64Mangle!("ctime", "__ctime64"))
 @system char*   ctime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf race:asctime env locale
 ///
+pragma(mangle, muslRedirTime64Mangle!("gmtime", "__gmtime64"))
 @system tm*     gmtime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf env locale
 ///
+pragma(mangle, muslRedirTime64Mangle!("localtime", "__localtime64"))
 @system tm*     localtime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf env locale
 ///
 @system size_t  strftime(scope char* s, size_t maxsize, const scope char* format, const scope tm* timeptr); // @system: MT-Safe env locale
index 24f1cbe6528ab5e64df3000d7eb00552fb10958d..53504db449e7005857fb024577de958d5b5dde3f 100644 (file)
@@ -46,12 +46,12 @@ enum : short
     EVFILT_EXCEPT   = -15,
 }
 
-extern(D) void EV_SET(kevent_t* kevp, typeof(kevent_t.tupleof) args)
+extern(D) void EV_SET()(kevent_t* kevp, typeof(kevent_t.tupleof) args)
 {
     *kevp = kevent_t(args);
 }
 
-extern(D) void EV_SET64(kevent64_s* kevp, typeof(kevent64_s.tupleof) args)
+extern(D) void EV_SET64()(kevent64_s* kevp, typeof(kevent64_s.tupleof) args)
 {
     *kevp = kevent64_s(args);
 }
index 3ea7f6a19adfd13c086e6d55a9345e5482fd3bc0..3a537a4a575b398dab49e85ba7ce515b751eb0c9 100644 (file)
@@ -8,6 +8,7 @@
  */
 module core.sys.posix.aio;
 
+import core.stdc.config;
 import core.sys.posix.signal;
 import core.sys.posix.sys.types;
 
@@ -392,6 +393,7 @@ else
     int aio_fsync(int op, aiocb* aiocbp);
     int aio_error(const(aiocb)* aiocbp);
     ssize_t aio_return(aiocb* aiocbp);
+    pragma(mangle, muslRedirTime64Mangle!("aio_suspend", "__aio_suspend_time64"))
     int aio_suspend(const(aiocb*)* aiocb_list, int nitems, const(timespec)* timeout);
     int aio_cancel(int fd, aiocb* aiocbp);
     int lio_listio(int mode, const(aiocb*)* aiocb_list, int nitems, sigevent* sevp);
index 5797b8fd35d8506bee671663440af09ec36af3d5..f4bd2d8ba92fd47a50c922ebf334dfbdbf63495d 100644 (file)
@@ -177,6 +177,38 @@ version (CRuntime_Glibc)
         void* dli_saddr;
     }
 }
+else
+version (CRuntime_Musl)
+{
+    enum RTLD_LAZY   = 1;
+    enum RTLD_NOW    = 2;
+    enum RTLD_NOLOAD = 4;
+    enum RTLD_NODELETE = 4096;
+    enum RTLD_GLOBAL = 256;
+    enum RTLD_LOCAL  = 0;
+
+    enum RTLD_NEXT    = cast(void *)-1;
+    enum RTLD_DEFAULT = cast(void *)0;
+
+    enum RTLD_DI_LINKMAP = 2;
+
+    int    dlclose(void *);
+    char  *dlerror();
+    void  *dlopen(const(char) *, int);
+
+    pragma(mangle, muslRedirTime64Mangle!("dlsym", "__dlsym_time64"))
+    void  *dlsym(void *__restrict, const(char) *__restrict);
+
+    struct Dl_info
+    {
+        const(char)* dli_fname;
+        void* dli_fbase;
+        const(char)* dli_sname;
+        void* dli_saddr;
+    }
+    int dladdr(const(void) *, Dl_info *);
+    int dlinfo(void *, int, void *);
+}
 else version (Darwin)
 {
     enum RTLD_LAZY      = 0x00001;
index ac697bf8b9beb9224a6bffe846446b1025dd5e52..eae50d27d835070f8eb76d3e0c3097d3a1225d15 100644 (file)
@@ -178,6 +178,7 @@ ssize_t mq_receive (mqd_t mqdes, char* msg_ptr, size_t msg_len, uint* msg_prio);
  *   On success, mq_receive() returns the number of bytes in the received
  *   message; on error, -1 is returned, with errno set to indicate the error
  */
+pragma(mangle, muslRedirTime64Mangle!("mq_timedreceive", "__mq_timedreceive_time64"))
 ssize_t mq_timedreceive (mqd_t mqdes, char* msg_ptr, size_t msg_len,
                          uint* msg_prio, const(timespec)* abs_timeout);
 
@@ -216,5 +217,6 @@ int mq_send (mqd_t mqdes, const(char)* msg_ptr, size_t msg_len, uint msg_prio);
  *   with errno set to indicate the error.
  *
  */
+pragma(mangle, muslRedirTime64Mangle!("mq_timedsend", "__mq_timedsend_time64"))
 int mq_timedsend (mqd_t mqdes, const(char)* msg_ptr, size_t msg_len,
                    uint msg_prio, const(timespec)* abs_timeout);
index a58fa850d5db50dfd62b457504523de4716a3d60..5818ee6e22b6ae10a61ba6208aeab6bcb6756046 100644 (file)
@@ -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;
index f6f0a58e3592e0ed2804a5dd4225f675c3a7de43..ba7ab8984a9c2a6a01d640594b9dbda89f3db1a0 100644 (file)
@@ -65,7 +65,10 @@ version (linux)
         {
             int sched_priority;
             int __reserved1;
-            timespec[2] __reserved2;
+            static if (muslRedirTime64)
+                c_long[2] __reserved2;
+            else
+                timespec[2] __reserved2;
             int __reserved3;
         }
     }
@@ -282,6 +285,7 @@ else version (CRuntime_Musl)
 {
     int sched_get_priority_max(int);
     int sched_get_priority_min(int);
+    pragma(mangle, muslRedirTime64Mangle!("sched_rr_get_interval", "__sched_rr_get_interval_time64"))
     int sched_rr_get_interval(pid_t, timespec*);
 }
 else version (CRuntime_UClibc)
index d755f86c9cc86e1b36a6be9d56a4b35fb6febb34..4f3b6e951c3393f8a419858af3f2bdf2b23d3eb8 100644 (file)
@@ -216,6 +216,7 @@ else version (CRuntime_Bionic)
 }
 else version (CRuntime_Musl)
 {
+    pragma(mangle, muslRedirTime64Mangle!("sem_timedwait", "__sem_timedwait_time64"))
     int sem_timedwait(sem_t*, const scope timespec*);
 }
 else version (CRuntime_UClibc)
index 542e83a1679d267cd525f89ed7b08e1c5fffc0e6..f722bc4df628f4efa2ad8e12c6c2fef8a6064f80 100644 (file)
@@ -2990,6 +2990,7 @@ else version (CRuntime_Bionic)
 else version (CRuntime_Musl)
 {
     int sigqueue(pid_t, int, const sigval);
+    pragma(mangle, muslRedirTime64Mangle!("sigtimedwait", "__sigtimedwait_time64"))
     int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
     int sigwaitinfo(const scope sigset_t*, siginfo_t*);
 }
index 1f46f03e14d97c1e88709ed9a14806bb1bf6bb8b..b997f112e4d03d39727b2e9fe24662b4ff06cba5 100644 (file)
@@ -547,6 +547,7 @@ else version (CRuntime_Musl)
     int setrlimit(int, const scope rlimit*);
     alias getrlimit getrlimit64;
     alias setrlimit setrlimit64;
+    pragma(mangle, muslRedirTime64Mangle!("getrusage", "__getrusage_time64"))
     int getrusage(int, rusage*);
 }
 else version (Solaris)
index 06b094093ed56e3a16303a822d9dd8a9aa3e8cd6..dd05d08dde6b5d24ed9354602b017cb503f83dfe 100644 (file)
@@ -501,7 +501,9 @@ else version (CRuntime_Musl)
     {
         fdset.fds_bits[0 .. $] = 0;
     }
+    pragma(mangle, muslRedirTime64Mangle!("pselect", "__pselect_time64"))
     int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
+    pragma(mangle, muslRedirTime64Mangle!("select", "__select_time64"))
     int select(int, fd_set*, fd_set*, fd_set*, timeval*);
 }
 else version (CRuntime_UClibc)
index ecc98ccf0ed86c6ee81f6852e5d7e7e0e69fb6c8..ee9e5da2feb51fb13820b12a2e5b988a30a43aec 100644 (file)
@@ -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
@@ -1890,8 +1889,11 @@ else version (CRuntime_Bionic)
 }
 else version (CRuntime_Musl)
 {
+    pragma(mangle, muslRedirTime64Mangle!("stat", "__stat_time64"))
     int stat(const scope char*, stat_t*);
+    pragma(mangle, muslRedirTime64Mangle!("fstat", "__fstat_time64"))
     int fstat(int, stat_t*);
+    pragma(mangle, muslRedirTime64Mangle!("lstat", "__lstat_time64"))
     int lstat(const scope char*, stat_t*);
 
     alias fstat fstat64;
index b536eedc14fe87b607c1a4fb2f4c57f42dafd56e..dda4caf0bf36aa779f121e52283ab546d820388b 100644 (file)
@@ -89,7 +89,9 @@ else version (CRuntime_Musl)
         time_t      tv_sec;
         suseconds_t tv_usec;
     }
+    pragma(mangle, muslRedirTime64Mangle!("gettimeofday", "__gettimeofday_time64"))
     int gettimeofday(timeval*, void*);
+    pragma(mangle, muslRedirTime64Mangle!("utimes", "__utimes_time64"))
     int utimes(const scope char*, ref const(timeval)[2]);
 }
 else version (Darwin)
index af52002b1aafe5e6adb399b5f8d15f70fedfe637..f49764d1964a089d904c67336a826474200e1916 100644 (file)
@@ -83,6 +83,7 @@ else version (CRuntime_Bionic)
 }
 else version (CRuntime_Musl)
 {
+    pragma(mangle, muslRedirTime64Mangle!("timegm", "__timegm_time64"))
     time_t timegm(tm*);
 }
 else version (CRuntime_UClibc)
@@ -483,15 +484,21 @@ else version (CRuntime_Musl)
 
     int nanosleep(const scope timespec*, timespec*);
 
+    pragma(mangle, muslRedirTime64Mangle!("clock_getres", "__clock_getres_time64"))
     int clock_getres(clockid_t, timespec*);
+    pragma(mangle, muslRedirTime64Mangle!("clock_gettime", "__clock_gettime64"))
     int clock_gettime(clockid_t, timespec*);
+    pragma(mangle, muslRedirTime64Mangle!("clock_settime", "__clock_settime64"))
     int clock_settime(clockid_t, const scope timespec*);
+    pragma(mangle, muslRedirTime64Mangle!("clock_nanosleep", "__clock_nanosleep_time64"))
     int clock_nanosleep(clockid_t, int, const scope timespec*, timespec*);
     int clock_getcpuclockid(pid_t, clockid_t *);
 
     int timer_create(clockid_t, sigevent*, timer_t*);
     int timer_delete(timer_t);
+    pragma(mangle, muslRedirTime64Mangle!("timer_gettime", "__timer_gettime64"))
     int timer_gettime(timer_t, itimerspec*);
+    pragma(mangle, muslRedirTime64Mangle!("timer_settime", "__timer_settime64"))
     int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*);
     int timer_getoverrun(timer_t);
 }
@@ -596,8 +603,11 @@ else version (CRuntime_Bionic)
 else version (CRuntime_Musl)
 {
     char* asctime_r(const scope tm*, char*);
+    pragma(mangle, muslRedirTime64Mangle!("ctime_r", "__ctime64_r"))
     char* ctime_r(const scope time_t*, char*);
+    pragma(mangle, muslRedirTime64Mangle!("gmtime_r", "__gmtime64_r"))
     tm*   gmtime_r(const scope time_t*, tm*);
+    pragma(mangle, muslRedirTime64Mangle!("localtime_r", "__localtime64_r"))
     tm*   localtime_r(const scope time_t*, tm*);
 }
 else version (CRuntime_UClibc)
index fcec7af3fde0ea3dc440123d517f404223fdb402..e7059d7128387a5d6d6b0ad232a2e23aa5fa08bf 100644 (file)
@@ -62,6 +62,7 @@ else version (CRuntime_Musl)
         time_t  modtime;
     }
 
+    pragma(mangle, muslRedirTime64Mangle!("utime", "__utime64"))
     int utime(const scope char*, const scope utimbuf*);
 }
 else version (Darwin)
index 8df29729af3987655b7ee44762e75df60ce1d2d5..c10a9175b4d1c78481577870c83f8ac41294bc12 100644 (file)
@@ -30,6 +30,7 @@ extern(Windows) DWORD GetEnvironmentVariableA(LPCSTR lpName, LPSTR pBuffer, DWOR
 extern(Windows) alias USHORT function(ULONG FramesToSkip, ULONG FramesToCapture, PVOID *BackTrace, PULONG BackTraceHash) @nogc RtlCaptureStackBackTraceFunc;
 
 private __gshared RtlCaptureStackBackTraceFunc RtlCaptureStackBackTrace;
+private __gshared CRITICAL_SECTION mutex; // cannot use core.sync.mutex.Mutex unfortunately (cyclic dependency...)
 private __gshared immutable bool initialized;
 
 
@@ -63,11 +64,11 @@ public:
 
             skip += INTERNALFRAMES;
         }
-        if ( initialized )
+        if (initialized)
             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 +77,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) )
@@ -118,10 +119,10 @@ public:
     /// ditto
     static ulong[] trace(ulong[] buffer, size_t skip = 0, CONTEXT* context = null) @nogc
     {
-        synchronized( typeid(StackTrace) )
-        {
-            return traceNoSync(buffer, skip, context);
-        }
+        EnterCriticalSection(&mutex);
+        scope(exit) LeaveCriticalSection(&mutex);
+
+        return traceNoSync(buffer, skip, context);
     }
 
     /**
@@ -133,10 +134,15 @@ public:
      */
     @trusted static char[][] resolve(const(ulong)[] addresses)
     {
-        synchronized( typeid(StackTrace) )
-        {
-            return resolveNoSync(addresses);
-        }
+        // FIXME: make @nogc to avoid having to disable resolution within finalizers
+        import core.memory : GC;
+        if (GC.inFinalizer)
+            return null;
+
+        EnterCriticalSection(&mutex);
+        scope(exit) LeaveCriticalSection(&mutex);
+
+        return resolveNoSync(addresses);
     }
 
 private:
@@ -421,5 +427,6 @@ shared static this()
 
     dbghelp.SymRegisterCallback64(hProcess, &FixupDebugHeader, 0);
 
+    InitializeCriticalSection(&mutex);
     initialized = true;
 }
index 3b571ad57dac1e56ef07ffe545f8def3d64090c3..bbb6e9a7b41eb5981fd9170a8a10ce5dd8956950 100644 (file)
@@ -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);
index efbad7d6b74741563706332612af164d1edbd160..4590ff1c0525811c2b52ec4406217dca6510629f 100644 (file)
@@ -19,6 +19,8 @@ import core.thread.threadgroup;
 import core.thread.types;
 import core.thread.context;
 
+import core.memory : pageSize;
+
 ///////////////////////////////////////////////////////////////////////////////
 // Fiber Platform Detection
 ///////////////////////////////////////////////////////////////////////////////
@@ -600,7 +602,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;
@@ -623,8 +625,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 );
@@ -651,8 +653,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 );
@@ -962,9 +964,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
index 7316373195a5050fb25f85f1796d26d3b5db0da1..066f39e39c77e9462cc9f45307bf8c7f140c7dd1 100644 (file)
@@ -19,7 +19,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;
@@ -1115,7 +1115,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();
 }
@@ -2889,8 +2889,8 @@ private size_t adjustStackSize(size_t sz) nothrow @nogc
         }
     }
 
-    // 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;
 }
index e50399a59d9009498e5ad4b9478f416172a6e9fb..eb84ad74b48142c2f2c95458d62f2001e1c7c7ac 100644 (file)
@@ -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");
-    }
 }
index 0385b51d60e45b94d507c0acbac02cbc3e7525f8..a77788bec20deb1b141fca2108879fdd07b0a914 100644 (file)
@@ -246,7 +246,7 @@ class Object
      * }
      * ---
      */
-    deprecated static Object factory(string classname)
+    static Object factory(string classname)
     {
         auto ci = TypeInfo_Class.find(classname);
         if (ci)
@@ -256,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__");
@@ -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])));
@@ -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))
@@ -4622,7 +4528,8 @@ they are only intended to be instantiated by the compiler, not the user.
 public import core.internal.entrypoint : _d_cmain;
 
 public import core.internal.array.appending : _d_arrayappendT;
-public import core.internal.array.appending : _d_arrayappendTTrace;
+version (D_ProfileGC)
+    public import core.internal.array.appending : _d_arrayappendTTrace;
 public import core.internal.array.appending : _d_arrayappendcTXImpl;
 public import core.internal.array.comparison : __cmp;
 public import core.internal.array.equality : __equals;
@@ -4648,6 +4555,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);
 
index 0b4fe4586450d6a9921f6bc41d5d266601a0c8fe..a21913975993004450bd82bf6f4ddfa16809a1fd 100644 (file)
@@ -1,4 +1,4 @@
-e5a521ab2bddfa0a42ecf371910ffe6a2fe0a03a
+454dff14dcbd005f9550302c5836ef8e06ab663a
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/phobos repository.
index 967d2a6f50c43fa2b78e922942a61ac57783f46b..82360763adc3d969291abd7aef9f581668261c70 100644 (file)
@@ -2969,10 +2969,24 @@ iterated from the back to the front, the separator will still be consumed from
 front to back, even if it is a bidirectional range too.
  */
 auto joiner(RoR, Separator)(RoR r, Separator sep)
-if (isInputRange!RoR && isInputRange!(ElementType!RoR)
-        && isForwardRange!Separator
-        && is(ElementType!Separator : ElementType!(ElementType!RoR)))
 {
+    static assert(isInputRange!RoR, "The type of RoR '", RoR.stringof
+            , " must be an InputRange (isInputRange!", RoR.stringof, ").");
+    static assert(isInputRange!(ElementType!RoR), "The ElementyType of RoR '"
+            , ElementType!(RoR).stringof, "' must be an InputRange "
+            , "(isInputRange!(ElementType!(", RoR.stringof , "))).");
+    static assert(isForwardRange!Separator, "The type of the Seperator '"
+            , Seperator.stringof, "' must be a ForwardRange (isForwardRange!("
+            , Seperator.stringof, ")).");
+    static assert(is(ElementType!Separator : ElementType!(ElementType!RoR))
+            , "The type of the elements of the separator range does not match "
+            , "the type of the elements that are joined. Separator type '"
+            , ElementType!(Separator).stringof, "' is not implicitly"
+            , "convertible to range element type '"
+            , ElementType!(ElementType!RoR).stringof, "' (is(ElementType!"
+            , Separator.stringof, " : ElementType!(ElementType!", RoR.stringof
+            , "))).");
+
     static struct Result
     {
         private RoR _items;
index 6aacd513fc53de392e41f94eaf5b5cb74dc13008..71bd1d90ceb49345f2e18fcb0818ce389e54c37c 100644 (file)
@@ -103,6 +103,7 @@ $(TR
         $(SUBREF sorting, multiSort)
         $(SUBREF sorting, nextEvenPermutation)
         $(SUBREF sorting, nextPermutation)
+        $(SUBREF sorting, nthPermutation)
         $(SUBREF sorting, partialSort)
         $(SUBREF sorting, partition)
         $(SUBREF sorting, partition3)
index ddb80b8fc68d08f1a06e2b7d9d6678e31e38e971..c5b085d1037f232375dcc5abaf7060dbd0a5f26b 100644 (file)
@@ -1922,14 +1922,8 @@ See_Also:
     $(REF binaryFun, std,functional)
 */
 SortedRange!(Range, less)
-sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable,
-        Range)(Range r)
-if (((ss == SwapStrategy.unstable && (hasSwappableElements!Range ||
-    hasAssignableElements!Range)) ||
-    (ss != SwapStrategy.unstable && hasAssignableElements!Range)) &&
-    isRandomAccessRange!Range &&
-    hasSlicing!Range &&
-    hasLength!Range)
+sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)
+(Range r)
     /+ Unstable sorting uses the quicksort algorithm, which uses swapAt,
        which either uses swap(...), requiring swappable elements, or just
        swaps using assignment.
@@ -1937,21 +1931,46 @@ if (((ss == SwapStrategy.unstable && (hasSwappableElements!Range ||
        requiring assignable elements. +/
 {
     import std.range : assumeSorted;
-    alias lessFun = binaryFun!(less);
-    alias LessRet = typeof(lessFun(r.front, r.front));    // instantiate lessFun
-    static if (is(LessRet == bool))
+    static if (ss == SwapStrategy.unstable)
     {
-        static if (ss == SwapStrategy.unstable)
-            quickSortImpl!(lessFun)(r, r.length);
-        else //use Tim Sort for semistable & stable
-            TimSortImpl!(lessFun, Range).sort(r, null);
-
-        assert(isSorted!lessFun(r), "Failed to sort range of type " ~ Range.stringof);
+        static assert(hasSwappableElements!Range || hasAssignableElements!Range,
+                  "When using SwapStrategy.unstable, the passed Range '"
+                ~ Range.stringof ~ "' must"
+                ~ " either fulfill hasSwappableElements, or"
+                ~ " hasAssignableElements, both were not the case");
     }
     else
     {
-        static assert(false, "Invalid predicate passed to sort: " ~ less.stringof);
+        static assert(hasAssignableElements!Range, "When using a SwapStrategy"
+                ~ " != unstable, the"
+                ~ " passed Range '" ~ Range.stringof ~ "' must fulfill"
+                ~ " hasAssignableElements, which it did not");
     }
+
+    static assert(isRandomAccessRange!Range, "The passed Range '"
+            ~ Range.stringof ~ "' must be a Random AccessRange "
+            ~ "(isRandomAccessRange)");
+
+    static assert(hasSlicing!Range, "The passed Range '"
+            ~ Range.stringof ~ "' must allow Slicing (hasSlicing)");
+
+    static assert(hasLength!Range, "The passed Range '"
+            ~ Range.stringof ~ "' must have a length (hasLength)");
+
+    alias lessFun = binaryFun!(less);
+    alias LessRet = typeof(lessFun(r.front, r.front));    // instantiate lessFun
+
+    static assert(is(LessRet == bool), "The return type of the template"
+            ~ " argument 'less' when used with the binaryFun!less template"
+            ~ " must be a bool. This is not the case, the returned type is '"
+            ~ LessRet.stringof ~ "'");
+
+    static if (ss == SwapStrategy.unstable)
+        quickSortImpl!(lessFun)(r, r.length);
+    else //use Tim Sort for semistable & stable
+        TimSortImpl!(lessFun, Range).sort(r, null);
+
+    assert(isSorted!lessFun(r), "Failed to sort range of type " ~ Range.stringof);
     return assumeSorted!less(r);
 }
 
@@ -2599,8 +2618,16 @@ private template TimSortImpl(alias pred, R)
             //Test for overflow
             if (newSize < minCapacity) newSize = minCapacity;
 
-            if (__ctfe) temp.length = newSize;
-            else temp = () @trusted { return uninitializedArray!(T[])(newSize); }();
+            // can't use `temp.length` if there's no default constructor
+            static if (__traits(compiles, { T defaultConstructed; cast(void) defaultConstructed; }))
+            {
+                if (__ctfe) temp.length = newSize;
+                else temp = () @trusted { return uninitializedArray!(T[])(newSize); }();
+            }
+            else
+            {
+                temp = () @trusted { return uninitializedArray!(T[])(newSize); }();
+            }
         }
         return temp;
     }
@@ -3037,6 +3064,18 @@ private template TimSortImpl(alias pred, R)
     sort!(cmp, SwapStrategy.stable)(makeArray(minMerge + 5));
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=23668
+@safe unittest
+{
+    static struct S
+    {
+        int opCmp(const S) const { return 1; }
+        @disable this();
+    }
+    S[] array;
+    array.sort!("a < b", SwapStrategy.stable);
+}
+
 // schwartzSort
 /**
 Alternative sorting method that should be used when comparing keys involves an
index daa103a9a420afc38283081f13c6e114d4aad6ab..4584dcc92ddb24b721808475a071fe28c03f89f2 100644 (file)
@@ -170,7 +170,7 @@ if (isIterable!Range && !isAutodecodableString!Range && !isInfinite!Range)
 
 /// ditto
 ForeachType!(typeof((*Range).init))[] array(Range)(Range r)
-if (is(Range : U*, U) && isIterable!U && !isAutodecodableString!Range && !isInfinite!Range)
+if (is(Range == U*, U) && isIterable!U && !isAutodecodableString!Range && !isInfinite!Range)
 {
     return array(*r);
 }
@@ -2294,22 +2294,6 @@ if (isInputRange!RoR &&
     }
 }
 
-// https://issues.dlang.org/show_bug.cgi?id=10895
-@safe unittest
-{
-    static class A
-    {
-        string name;
-        alias name this;
-        this(string name) { this.name = name; }
-    }
-    auto a = [new A(`foo`)];
-    assert(a[0].length == 3);
-    auto temp = join(a, " ");
-    assert(a[0].length == 3);
-    assert(temp.length == 3);
-}
-
 // https://issues.dlang.org/show_bug.cgi?id=14230
 @safe unittest
 {
index 559f8da5f3fc4d02a7fb644a48121eddead92da9..b84a6762d195468cef8e8093941dd85d179f3669 100644 (file)
@@ -89,22 +89,21 @@ private template createAccessors(
     }
     else
     {
-        enum ulong
-            maskAllElse = ((~0uL) >> (64 - len)) << offset,
-            signBitCheck = 1uL << (len - 1);
+        enum ulong maskAllElse = ((~0uL) >> (64 - len)) << offset;
+        enum TSize = 8 * T.sizeof;
+        enum SignShift = TSize - len;
 
         static if (T.min < 0)
         {
             enum long minVal = -(1uL << (len - 1));
             enum ulong maxVal = (1uL << (len - 1)) - 1;
-            alias UT = Unsigned!(T);
-            enum UT extendSign = cast(UT)~((~0uL) >> (64 - len));
+            enum RightShiftOp = ">>=";
         }
         else
         {
             enum ulong minVal = 0;
             enum ulong maxVal = (~0uL) >> (64 - len);
-            enum extendSign = 0;
+            enum RightShiftOp = ">>>=";
         }
 
         static if (is(T == bool))
@@ -121,15 +120,11 @@ private template createAccessors(
         else
         {
             // getter
-            enum createAccessors = "@property "~T.stringof~" "~name~"() @safe pure nothrow @nogc const { auto result = "
-                ~"("~store~" & "
-                ~ myToString(maskAllElse) ~ ") >>"
-                ~ myToString(offset) ~ ";"
-                ~ (T.min < 0
-                   ? "if (result >= " ~ myToString(signBitCheck)
-                   ~ ") result |= " ~ myToString(extendSign) ~ ";"
-                   : "")
-                ~ " return cast("~T.stringof~") result;}\n"
+            enum createAccessors = "@property "~T.stringof~" "~name~"() @safe pure nothrow @nogc const {"
+                ~ "auto result = cast("~T.stringof~") (" ~ store ~ " >>" ~ myToString(offset) ~ ");"
+                ~ "result <<= " ~ myToString(SignShift) ~ ";"
+                ~ "result " ~ RightShiftOp ~ myToString(SignShift) ~ ";"
+                ~ " return result;}\n"
             // setter
                 ~"@property void "~name~"("~T.stringof~" v) @safe pure nothrow @nogc { "
                 ~"assert(v >= "~name~`_min, "Value is smaller than the minimum value of bitfield '`~name~`'"); `
index 323926a6aaed9eb797fa726b9e477836f076eff3..7fe52ba55ec7b8b676cd55511d36f834724967e4 100644 (file)
@@ -46,7 +46,7 @@
  *
  * This is a low-level messaging API upon which more structured or restrictive
  * APIs may be built.  The general idea is that every messageable entity is
- * represented by a common handle type called a Tid, which allows messages to
+ * represented by a common handle type called a `Tid`, which allows messages to
  * be sent to logical threads that are executing in both the current process
  * and in external processes using the same interface.  This is an important
  * aspect of scalability because it allows the components of a program to be
  *
  * A logical thread is an execution context that has its own stack and which
  * runs asynchronously to other logical threads.  These may be preemptively
- * scheduled kernel threads, fibers (cooperative user-space threads), or some
- * other concept with similar behavior.
+ * scheduled kernel threads, $(MREF_ALTTEXT fibers, core, thread, fiber)
+ * (cooperative user-space threads), or some other concept with similar behavior.
  *
  * The type of concurrency used when logical threads are created is determined
- * by the Scheduler selected at initialization time.  The default behavior is
+ * by the $(LREF Scheduler) selected at initialization time.  The default behavior is
  * currently to create a new kernel thread per call to spawn, but other
  * schedulers are available that multiplex fibers across the main thread or
  * use some combination of the two approaches.
@@ -274,7 +274,7 @@ static ~this()
 // Exceptions
 
 /**
- * Thrown on calls to `receiveOnly` if a message other than the type
+ * Thrown on calls to $(LREF receiveOnly) if a message other than the type
  * the receiving thread expected is sent.
  */
 class MessageMismatch : Exception
@@ -287,7 +287,7 @@ class MessageMismatch : Exception
 }
 
 /**
- * Thrown on calls to `receive` if the thread that spawned the receiving
+ * Thrown on calls to $(LREF receive) if the thread that spawned the receiving
  * thread has terminated and no more messages exist.
  */
 class OwnerTerminated : Exception
@@ -354,7 +354,7 @@ class MailboxFull : Exception
 }
 
 /**
- * Thrown when a Tid is missing, e.g. when `ownerTid` doesn't
+ * Thrown when a `Tid` is missing, e.g. when $(LREF ownerTid) doesn't
  * find an owner thread.
  */
 class TidMissingException : Exception
@@ -384,11 +384,11 @@ private:
 public:
 
     /**
-     * Generate a convenient string for identifying this Tid.  This is only
-     * useful to see if Tid's that are currently executing are the same or
+     * Generate a convenient string for identifying this `Tid`.  This is only
+     * useful to see if `Tid`'s that are currently executing are the same or
      * different, e.g. for logging and debugging.  It is potentially possible
-     * that a Tid executed in the future will have the same toString() output
-     * as another Tid that has already terminated.
+     * that a `Tid` executed in the future will have the same `toString()` output
+     * as another `Tid` that has already terminated.
      */
     void toString(W)(ref W w) const
     {
@@ -420,7 +420,7 @@ public:
 }
 
 /**
- * Returns: The $(LREF Tid) of the caller's thread.
+ * Returns: The `Tid` of the caller's thread.
  */
 @property Tid thisTid() @safe
 {
@@ -437,7 +437,7 @@ public:
 }
 
 /**
- * Return the Tid of the thread which spawned the caller's thread.
+ * Return the `Tid` of the thread which spawned the caller's thread.
  *
  * Throws: A `TidMissingException` exception if
  * there is no owner thread.
@@ -493,7 +493,7 @@ private template isSpawnable(F, T...)
 }
 
 /**
- * Starts fn(args) in a new logical thread.
+ * Starts `fn(args)` in a new logical thread.
  *
  * Executes the supplied function in a new logical thread represented by
  * `Tid`.  The calling thread is designated as the owner of the new thread.
@@ -506,7 +506,7 @@ private template isSpawnable(F, T...)
  *  args = Arguments to the function.
  *
  * Returns:
- *  A Tid representing the new logical thread.
+ *  A `Tid` representing the new logical thread.
  *
  * Notes:
  *  `args` must not have unshared aliasing.  In other words, all arguments
@@ -573,16 +573,16 @@ if (isSpawnable!(F, T))
 }
 
 /**
- * Starts fn(args) in a logical thread and will receive a LinkTerminated
+ * Starts `fn(args)` in a logical thread and will receive a `LinkTerminated`
  * message when the operation terminates.
  *
  * Executes the supplied function in a new logical thread represented by
- * Tid.  This new thread is linked to the calling thread so that if either
- * it or the calling thread terminates a LinkTerminated message will be sent
- * to the other, causing a LinkTerminated exception to be thrown on receive().
- * The owner relationship from spawn() is preserved as well, so if the link
+ * `Tid`.  This new thread is linked to the calling thread so that if either
+ * it or the calling thread terminates a `LinkTerminated` message will be sent
+ * to the other, causing a `LinkTerminated` exception to be thrown on `receive()`.
+ * The owner relationship from `spawn()` is preserved as well, so if the link
  * between threads is broken, owner termination will still result in an
- * OwnerTerminated exception to be thrown on receive().
+ * `OwnerTerminated` exception to be thrown on `receive()`.
  *
  * Params:
  *  fn   = The function to execute.
@@ -1021,7 +1021,7 @@ do
 enum OnCrowding
 {
     block, /// Wait until room is available.
-    throwException, /// Throw a MailboxFull exception.
+    throwException, /// Throw a $(LREF MailboxFull) exception.
     ignore /// Abort the send and return.
 }
 
@@ -1178,13 +1178,13 @@ bool unregister(string name)
 }
 
 /**
- * Gets the Tid associated with name.
+ * Gets the `Tid` associated with name.
  *
  * Params:
  *  name = The name to locate within the registry.
  *
  * Returns:
- *  The associated Tid or Tid.init if name is not registered.
+ *  The associated `Tid` or `Tid.init` if name is not registered.
  */
 Tid locate(string name)
 {
@@ -1199,7 +1199,7 @@ Tid locate(string name)
 /**
  * Encapsulates all implementation-level data needed for scheduling.
  *
- * When defining a Scheduler, an instance of this struct must be associated
+ * When defining a $(LREF Scheduler), an instance of this struct must be associated
  * with each logical thread.  It contains all implementation-level information
  * needed by the internal API.
  */
@@ -1210,11 +1210,11 @@ struct ThreadInfo
     Tid owner;
 
     /**
-     * Gets a thread-local instance of ThreadInfo.
+     * Gets a thread-local instance of `ThreadInfo`.
      *
-     * Gets a thread-local instance of ThreadInfo, which should be used as the
+     * Gets a thread-local instance of `ThreadInfo`, which should be used as the
      * default instance when info is requested for a thread not created by the
-     * Scheduler.
+     * `Scheduler`.
      */
     static @property ref thisInfo() nothrow
     {
@@ -1253,15 +1253,15 @@ struct ThreadInfo
 }
 
 /**
- * A Scheduler controls how threading is performed by spawn.
+ * A `Scheduler` controls how threading is performed by spawn.
  *
- * Implementing a Scheduler allows the concurrency mechanism used by this
+ * Implementing a `Scheduler` allows the concurrency mechanism used by this
  * module to be customized according to different needs.  By default, a call
  * to spawn will create a new kernel thread that executes the supplied routine
- * and terminates when finished.  But it is possible to create Schedulers that
- * reuse threads, that multiplex Fibers (coroutines) across a single thread,
- * or any number of other approaches.  By making the choice of Scheduler a
- * user-level option, std.concurrency may be used for far more types of
+ * and terminates when finished.  But it is possible to create `Scheduler`s that
+ * reuse threads, that multiplex `Fiber`s (coroutines) across a single thread,
+ * or any number of other approaches.  By making the choice of `Scheduler` a
+ * user-level option, `std.concurrency` may be used for far more types of
  * application than if this behavior were predefined.
  *
  * Example:
@@ -1280,25 +1280,25 @@ struct ThreadInfo
  * ---
  *
  * Some schedulers have a dispatching loop that must run if they are to work
- * properly, so for the sake of consistency, when using a scheduler, start()
- * must be called within main().  This yields control to the scheduler and
+ * properly, so for the sake of consistency, when using a scheduler, `start()`
+ * must be called within `main()`.  This yields control to the scheduler and
  * will ensure that any spawned threads are executed in an expected manner.
  */
 interface Scheduler
 {
     /**
-     * Spawns the supplied op and starts the Scheduler.
+     * Spawns the supplied op and starts the `Scheduler`.
      *
      * This is intended to be called at the start of the program to yield all
-     * scheduling to the active Scheduler instance.  This is necessary for
+     * scheduling to the active `Scheduler` instance.  This is necessary for
      * schedulers that explicitly dispatch threads rather than simply relying
      * on the operating system to do so, and so start should always be called
-     * within main() to begin normal program execution.
+     * within `main()` to begin normal program execution.
      *
      * Params:
      *  op = A wrapper for whatever the main thread would have done in the
      *       absence of a custom scheduler.  It will be automatically executed
-     *       via a call to spawn by the Scheduler.
+     *       via a call to spawn by the `Scheduler`.
      */
     void start(void delegate() op);
 
@@ -1307,8 +1307,8 @@ interface Scheduler
      *
      * This routine is called by spawn.  It is expected to instantiate a new
      * logical thread and run the supplied operation.  This thread must call
-     * thisInfo.cleanup() when the thread terminates if the scheduled thread
-     * is not a kernel thread--all kernel threads will have their ThreadInfo
+     * `thisInfo.cleanup()` when the thread terminates if the scheduled thread
+     * is not a kernel thread--all kernel threads will have their `ThreadInfo`
      * cleaned up automatically by a thread-local destructor.
      *
      * Params:
@@ -1329,36 +1329,36 @@ interface Scheduler
     void yield() nothrow;
 
     /**
-     * Returns an appropriate ThreadInfo instance.
+     * Returns an appropriate `ThreadInfo` instance.
      *
-     * Returns an instance of ThreadInfo specific to the logical thread that
+     * Returns an instance of `ThreadInfo` specific to the logical thread that
      * is calling this routine or, if the calling thread was not create by
-     * this scheduler, returns ThreadInfo.thisInfo instead.
+     * this scheduler, returns `ThreadInfo.thisInfo` instead.
      */
     @property ref ThreadInfo thisInfo() nothrow;
 
     /**
-     * Creates a Condition variable analog for signaling.
+     * Creates a `Condition` variable analog for signaling.
      *
-     * Creates a new Condition variable analog which is used to check for and
+     * Creates a new `Condition` variable analog which is used to check for and
      * to signal the addition of messages to a thread's message queue.  Like
      * yield, some schedulers may need to define custom behavior so that calls
-     * to Condition.wait() yield to another thread when no new messages are
+     * to `Condition.wait()` yield to another thread when no new messages are
      * available instead of blocking.
      *
      * Params:
-     *  m = The Mutex that will be associated with this condition.  It will be
+     *  m = The `Mutex` that will be associated with this condition.  It will be
      *      locked prior to any operation on the condition, and so in some
-     *      cases a Scheduler may need to hold this reference and unlock the
+     *      cases a `Scheduler` may need to hold this reference and unlock the
      *      mutex before yielding execution to another logical thread.
      */
     Condition newCondition(Mutex m) nothrow;
 }
 
 /**
- * An example Scheduler using kernel threads.
+ * An example `Scheduler` using kernel threads.
  *
- * This is an example Scheduler that mirrors the default scheduling behavior
+ * This is an example `Scheduler` that mirrors the default scheduling behavior
  * of creating one kernel thread per call to spawn.  It is fully functional
  * and may be instantiated and used, but is not a necessary part of the
  * default functioning of this module.
@@ -1392,8 +1392,8 @@ class ThreadScheduler : Scheduler
     }
 
     /**
-     * Returns ThreadInfo.thisInfo, since it is a thread-local instance of
-     * ThreadInfo, which is the correct behavior for this scheduler.
+     * Returns `ThreadInfo.thisInfo`, since it is a thread-local instance of
+     * `ThreadInfo`, which is the correct behavior for this scheduler.
      */
     @property ref ThreadInfo thisInfo() nothrow
     {
@@ -1401,7 +1401,7 @@ class ThreadScheduler : Scheduler
     }
 
     /**
-     * Creates a new Condition variable.  No custom behavior is needed here.
+     * Creates a new `Condition` variable.  No custom behavior is needed here.
      */
     Condition newCondition(Mutex m) nothrow
     {
@@ -1410,15 +1410,15 @@ class ThreadScheduler : Scheduler
 }
 
 /**
- * An example Scheduler using Fibers.
+ * An example `Scheduler` using $(MREF_ALTTEXT `Fiber`s, core, thread, fiber).
  *
- * This is an example scheduler that creates a new Fiber per call to spawn
+ * This is an example scheduler that creates a new `Fiber` per call to spawn
  * and multiplexes the execution of all fibers within the main thread.
  */
 class FiberScheduler : Scheduler
 {
     /**
-     * This creates a new Fiber for the supplied op and then starts the
+     * This creates a new `Fiber` for the supplied op and then starts the
      * dispatcher.
      */
     void start(void delegate() op)
@@ -1428,7 +1428,7 @@ class FiberScheduler : Scheduler
     }
 
     /**
-     * This created a new Fiber for the supplied op and adds it to the
+     * This created a new `Fiber` for the supplied op and adds it to the
      * dispatch list.
      */
     void spawn(void delegate() op) nothrow
@@ -1438,8 +1438,8 @@ class FiberScheduler : Scheduler
     }
 
     /**
-     * If the caller is a scheduled Fiber, this yields execution to another
-     * scheduled Fiber.
+     * If the caller is a scheduled `Fiber`, this yields execution to another
+     * scheduled `Fiber`.
      */
     void yield() nothrow
     {
@@ -1451,11 +1451,11 @@ class FiberScheduler : Scheduler
     }
 
     /**
-     * Returns an appropriate ThreadInfo instance.
+     * Returns an appropriate `ThreadInfo` instance.
      *
-     * Returns a ThreadInfo instance specific to the calling Fiber if the
-     * Fiber was created by this dispatcher, otherwise it returns
-     * ThreadInfo.thisInfo.
+     * Returns a `ThreadInfo` instance specific to the calling `Fiber` if the
+     * `Fiber` was created by this dispatcher, otherwise it returns
+     * `ThreadInfo.thisInfo`.
      */
     @property ref ThreadInfo thisInfo() nothrow
     {
@@ -1467,10 +1467,10 @@ class FiberScheduler : Scheduler
     }
 
     /**
-     * Returns a Condition analog that yields when wait or notify is called.
+     * Returns a `Condition` analog that yields when wait or notify is called.
      *
      * Bug:
-     * For the default implementation, `notifyAll`will behave like `notify`.
+     * For the default implementation, `notifyAll` will behave like `notify`.
      *
      * Params:
      *   m = A `Mutex` to use for locking if the condition needs to be waited on
@@ -1485,7 +1485,7 @@ class FiberScheduler : Scheduler
 
 protected:
     /**
-     * Creates a new Fiber which calls the given delegate.
+     * Creates a new `Fiber` which calls the given delegate.
      *
      * Params:
      *   op = The delegate the fiber should call
@@ -1505,7 +1505,7 @@ protected:
     }
 
     /**
-     * Fiber which embeds a ThreadInfo
+     * `Fiber` which embeds a `ThreadInfo`
      */
     static class InfoFiber : Fiber
     {
@@ -1650,10 +1650,10 @@ private:
 }
 
 /**
- * Sets the Scheduler behavior within the program.
+ * Sets the `Scheduler` behavior within the program.
  *
- * This variable sets the Scheduler behavior within this program.  Typically,
- * when setting a Scheduler, scheduler.start() should be called in main.  This
+ * This variable sets the `Scheduler` behavior within this program.  Typically,
+ * when setting a `Scheduler`, `scheduler.start()` should be called in `main`.  This
  * routine will not return until program execution is complete.
  */
 __gshared Scheduler scheduler;
@@ -1661,8 +1661,8 @@ __gshared Scheduler scheduler;
 // Generator
 
 /**
- * If the caller is a Fiber and is not a Generator, this function will call
- * scheduler.yield() or Fiber.yield(), as appropriate.
+ * If the caller is a `Fiber` and is not a $(LREF Generator), this function will call
+ * `scheduler.yield()` or `Fiber.yield()`, as appropriate.
  */
 void yield() nothrow
 {
@@ -1684,8 +1684,9 @@ private interface IsGenerator {}
 
 
 /**
- * A Generator is a Fiber that periodically returns values of type T to the
- * caller via yield.  This is represented as an InputRange.
+ * A Generator is a $(MREF_ALTTEXT Fiber, core, thread, fiber)
+ * that periodically returns values of type `T` to the
+ * caller via `yield`.  This is represented as an InputRange.
  */
 class Generator(T) :
     Fiber, IsGenerator, InputRange!T
@@ -1829,7 +1830,7 @@ class Generator(T) :
     /**
      * Returns the most recently generated value without executing a
      * copy contructor. Will not compile for element types defining a
-     * postblit, because Generator does not return by reference.
+     * postblit, because `Generator` does not return by reference.
      */
     final T moveFront()
     {
index 7ff14fc3bad49cdc522bbafd3610587311715cf7..0fd34526ea72babd494e468a3626fa1df94609e4 100644 (file)
@@ -597,3 +597,43 @@ BinaryHeap!(Store, less) heapify(alias less = "a < b", Store)(Store s,
     heap.insert(6);
     assert(equal(heap, [6, 5]));
 }
+
+/**
+Example for unintuitive behaviour
+It is important not to use the Store after a Heap has been instantiated from
+it, at least in the cases of Dynamic Arrays. For example, inserting a new element
+in a Heap, which is using a Dyamic Array as a Store, will cause a reallocation of
+the Store, if the Store is already full. The Heap will not point anymore to the
+original Dyamic Array, but point to a new Dynamic Array.
+ */
+
+// https://issues.dlang.org/show_bug.cgi?id=18333
+@system unittest
+{
+    import std.stdio;
+    import std.algorithm.comparison : equal;
+    import std.container.binaryheap;
+
+    int[] a = [ 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 ];
+    auto h = heapify(a);
+
+    // Internal representation of Binary Heap tree
+    assert(a.equal([16, 14, 10, 8, 7, 9, 3, 2, 4, 1]));
+
+    h.replaceFront(30);
+    // Value 16 was replaced by 30
+    assert(a.equal([30, 14, 10, 8, 7, 9, 3, 2, 4, 1]));
+
+    // Making changes to the Store will be seen in the Heap
+    a[0] = 40;
+    assert(h.front() == 40);
+
+    // Inserting a new element will reallocate the Store, leaving
+    // the original Store unchanged.
+    h.insert(20);
+    assert(a.equal([40, 14, 10, 8, 7, 9, 3, 2, 4, 1]));
+
+    // Making changes to the original Store will not affect the Heap anymore
+    a[0] = 60;
+    assert(h.front() == 40);
+}
index b699a8edea36a272bc197ff825ecde141846fbdc..6ffc0f7750a8a8a4dd157caa0e1039fcb73990e4 100644 (file)
@@ -1069,9 +1069,9 @@ as the language is free to assume objects don't have internal pointers
 */
 bool doesPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @nogc @trusted pure nothrow
 if (__traits(isRef, source) || isDynamicArray!S ||
-    is(S : U*, U) || is(S == class))
+    is(S == U*, U) || is(S == class))
 {
-    static if (is(S : U*, U) || is(S == class) || is(S == interface))
+    static if (is(S == U*, U) || is(S == class) || is(S == interface))
     {
         const m = *cast(void**) &source;
         const b = cast(void*) &target;
@@ -1115,9 +1115,9 @@ bool doesPointTo(S, T)(auto ref const shared S source, ref const shared T target
 /// ditto
 bool mayPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @trusted pure nothrow
 if (__traits(isRef, source) || isDynamicArray!S ||
-    is(S : U*, U) || is(S == class))
+    is(S == U*, U) || is(S == class))
 {
-    static if (is(S : U*, U) || is(S == class) || is(S == interface))
+    static if (is(S == U*, U) || is(S == class) || is(S == interface))
     {
         const m = *cast(void**) &source;
         const b = cast(void*) &target;
@@ -1533,21 +1533,6 @@ version (StdUnittest)
     assert( doesPointTo(cast(int*) s, i));
     assert(!doesPointTo(cast(int*) s, j));
 }
-@safe unittest //more alias this opCast
-{
-    void* p;
-    class A
-    {
-        void* opCast(T)() if (is(T == void*))
-        {
-            return p;
-        }
-        alias foo = opCast!(void*);
-        alias foo this;
-    }
-    assert(!doesPointTo(A.init, p));
-    assert(!mayPointTo(A.init, p));
-}
 
 /+
 Returns true if the field at index `i` in ($D T) shares its address with another field.
index d031096678694baed435eec1029df9a56354e058..b7bd3fc91cf971f761048a8b913dbbf7ae76dff2 100644 (file)
@@ -1575,7 +1575,7 @@ private void setTimesImpl(scope const(char)[] names, scope const(FSChar)* namez,
         const ta = SysTimeToFILETIME(accessTime);
         const tm = SysTimeToFILETIME(modificationTime);
         alias defaults =
-            AliasSeq!(GENERIC_WRITE,
+            AliasSeq!(FILE_WRITE_ATTRIBUTES,
                       0,
                       null,
                       OPEN_EXISTING,
@@ -1664,6 +1664,16 @@ private void setTimesImpl(scope const(char)[] names, scope const(FSChar)* namez,
     rmdirRecurse(newdir);
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=23683
+@safe unittest
+{
+    scope(exit) deleteme.remove;
+    import std.stdio : File;
+    auto f = File(deleteme, "wb");
+    SysTime time = SysTime(DateTime(2018, 10, 4, 0, 0, 30));
+    setTimes(deleteme, time, time);
+}
+
 /++
     Returns the time that the given file was last modified.
 
@@ -4930,7 +4940,10 @@ alias DirIterator = _DirIterator!dip1000Enabled;
         $(LREF DirEntry).
 
     Throws:
-        $(LREF FileException) if the directory does not exist.
+        $(UL
+        $(LI $(LREF FileException) if the $(B path) directory does not exist or read permission is denied.)
+        $(LI $(LREF FileException) if $(B mode) is not `shallow` and a subdirectory cannot be read.)
+        )
 
 Example:
 --------------------
@@ -4971,7 +4984,25 @@ auto dFiles = dirEntries("","*.{d,di}",SpanMode.depth);
 foreach (d; dFiles)
     writeln(d.name);
 --------------------
- +/
+To handle subdirectories with denied read permission, use `SpanMode.shallow`:
+---
+void scan(string path)
+{
+    foreach (DirEntry entry; dirEntries(path, SpanMode.shallow))
+    {
+        try
+        {
+            writeln(entry.name);
+            if (entry.isDir)
+                scan(entry.name);
+        }
+        catch (FileException fe) { continue; } // ignore
+    }
+}
+
+scan("");
+---
++/
 
 // For some reason, doing the same alias-to-a-template trick as with DirIterator
 // does not work here.
index 32c82995feeec682f7df84f6872a09628fd1c952..7f127c098478c867812352b09d40a578fb67f7ba 100644 (file)
@@ -50,27 +50,6 @@ if (is(BooleanTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 
 @safe unittest
 {
-    class C1
-    {
-        bool val;
-        alias val this;
-        this(bool v){ val = v; }
-    }
-
-    class C2 {
-        bool val;
-        alias val this;
-        this(bool v){ val = v; }
-        override string toString() const { return "C"; }
-    }
-
-    () @trusted {
-        formatTest(new C1(false), "false");
-        formatTest(new C1(true),  "true");
-        formatTest(new C2(false), "C");
-        formatTest(new C2(true),  "C");
-    } ();
-
     struct S1
     {
         bool val;
@@ -411,26 +390,6 @@ private uint baseOfSpec(in char spec) @safe pure
 
 @safe unittest
 {
-    class C1
-    {
-        long val;
-        alias val this;
-        this(long v){ val = v; }
-    }
-
-    class C2
-    {
-        long val;
-        alias val this;
-        this(long v){ val = v; }
-        override string toString() const { return "C"; }
-    }
-
-    () @trusted {
-        formatTest(new C1(10), "10");
-        formatTest(new C2(10), "C");
-    } ();
-
     struct S1
     {
         long val;
@@ -709,26 +668,6 @@ if (is(FloatingPointTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 {
     formatTest(2.25, "2.25");
 
-    class C1
-    {
-        double val;
-        alias val this;
-        this(double v){ val = v; }
-    }
-
-    class C2
-    {
-        double val;
-        alias val this;
-        this(double v){ val = v; }
-        override string toString() const { return "C"; }
-    }
-
-    () @trusted {
-        formatTest(new C1(2.25), "2.25");
-        formatTest(new C2(2.25), "C");
-    } ();
-
     struct S1
     {
         double val;
@@ -1078,26 +1017,6 @@ if (is(CharTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 
 @safe unittest
 {
-    class C1
-    {
-        char val;
-        alias val this;
-        this(char v){ val = v; }
-    }
-
-    class C2
-    {
-        char val;
-        alias val this;
-        this(char v){ val = v; }
-        override string toString() const { return "C"; }
-    }
-
-    () @trusted {
-        formatTest(new C1('c'), "c");
-        formatTest(new C2('c'), "C");
-    } ();
-
     struct S1
     {
         char val;
@@ -1165,26 +1084,6 @@ if (is(StringTypeOf!T) && !is(StaticArrayTypeOf!T) && !is(T == enum) && !hasToSt
 
 @safe unittest
 {
-    // Test for bug 5371 for classes
-    class C1
-    {
-        const string var;
-        alias var this;
-        this(string s){ var = s; }
-    }
-
-    class C2
-    {
-        string var;
-        alias var this;
-        this(string s){ var = s; }
-    }
-
-    () @trusted {
-        formatTest(new C1("c1"), "c1");
-        formatTest(new C2("c2"), "c2");
-    } ();
-
     // Test for bug 5371 for structs
     struct S1
     {
@@ -1204,16 +1103,6 @@ if (is(StringTypeOf!T) && !is(StaticArrayTypeOf!T) && !is(T == enum) && !hasToSt
 
 @safe unittest
 {
-    class C3
-    {
-        string val;
-        alias val this;
-        this(string s){ val = s; }
-        override string toString() const { return "C"; }
-    }
-
-    () @trusted { formatTest(new C3("c3"), "C"); } ();
-
     struct S3
     {
         string val; alias val this;
@@ -1436,36 +1325,6 @@ if (is(DynamicArrayTypeOf!T) && !is(StringTypeOf!T) && !is(T == enum) && !hasToS
     formatTest(S!0b101([0, 1, 2]), "S");                // Test for bug 7628
     formatTest(S!0b110([0, 1, 2]), "S");
     formatTest(S!0b111([0, 1, 2]), "S");
-
-    class C(uint flags)
-    {
-        int[] arr;
-        static if (flags & 1)
-            alias arr this;
-
-        this(int[] a) { arr = a; }
-
-        static if (flags & 2)
-        {
-            @property bool empty() const { return arr.length == 0; }
-            @property int front() const { return arr[0] * 2; }
-            void popFront() { arr = arr[1 .. $]; }
-        }
-
-        static if (flags & 4)
-            override string toString() const { return "C"; }
-    }
-
-    () @trusted {
-        formatTest(new C!0b000([0, 1, 2]), (new C!0b000([])).toString());
-        formatTest(new C!0b001([0, 1, 2]), "[0, 1, 2]");    // Test for bug 7628
-        formatTest(new C!0b010([0, 1, 2]), "[0, 2, 4]");
-        formatTest(new C!0b011([0, 1, 2]), "[0, 2, 4]");
-        formatTest(new C!0b100([0, 1, 2]), "C");
-        formatTest(new C!0b101([0, 1, 2]), "C");            // Test for bug 7628
-        formatTest(new C!0b110([0, 1, 2]), "C");
-        formatTest(new C!0b111([0, 1, 2]), "C");
-    } ();
 }
 
 @safe unittest
@@ -1901,26 +1760,6 @@ if (is(AssocArrayTypeOf!T) && !is(T == enum) && !hasToString!(T, Char))
 
 @safe unittest
 {
-    class C1
-    {
-        int[char] val;
-        alias val this;
-        this(int[char] v){ val = v; }
-    }
-
-    class C2
-    {
-        int[char] val;
-        alias val this;
-        this(int[char] v){ val = v; }
-        override string toString() const { return "C"; }
-    }
-
-    () @trusted {
-        formatTest(new C1(['c':1, 'd':2]), [`['c':1, 'd':2]`, `['d':2, 'c':1]`]);
-        formatTest(new C2(['c':1, 'd':2]), "C");
-    } ();
-
     struct S1
     {
         int[char] val;
@@ -1990,7 +1829,8 @@ enum HasToStringResult
     customPutWriterFormatSpec,
 }
 
-private enum hasPreviewIn = !is(typeof(mixin(q{(in ref int a) => a})));
+private alias DScannerBug895 = int[256];
+private immutable bool hasPreviewIn = ((in DScannerBug895 a) { return __traits(isRef, a); })(DScannerBug895.init);
 
 template hasToString(T, Char)
 {
@@ -3167,18 +3007,6 @@ if (isPointer!T && !is(T == enum) && !hasToString!(T, Char))
     formatTest(q, "FFEECCAA");
 }
 
-// https://issues.dlang.org/show_bug.cgi?id=8186
-@system unittest
-{
-    class B
-    {
-        int* a;
-        this() { a = new int; }
-        alias a this;
-    }
-    formatTest(B.init, "null");
-}
-
 // https://issues.dlang.org/show_bug.cgi?id=9336
 @system pure unittest
 {
index 144fa8c0d6573a1affae67488a1e557c046a4630..da9d0dc14db4337eb77c4d5cf31460098ff6b3ce 100644 (file)
@@ -303,8 +303,23 @@ uint formattedRead(alias fmt, Range, Args...)(auto ref Range r, auto ref Args ar
 if (isSomeString!(typeof(fmt)))
 {
     import std.format : checkFormatException;
+    import std.meta : staticMap;
+    import std.typecons : Tuple;
+
 
-    alias e = checkFormatException!(fmt, Args);
+    // formattedRead supports std.typecons.Tuple
+    // however, checkFormatException does not
+    // this means that all std.typecons.Tuple's types in Args must be unwrapped
+    // and passed to checkFormatException
+    template Flatten(T)
+    {
+        static if (is(T : Tuple!Args, Args...))
+            alias Flatten = Args;
+        else
+            alias Flatten = T;
+    }
+
+    alias e = checkFormatException!(fmt, staticMap!(Flatten, Args));
     static assert(!e, e);
     return .formattedRead(r, fmt, args);
 }
@@ -361,6 +376,20 @@ if (isSomeString!(typeof(fmt)))
     assert(t[0] == 1 && t[1] == 2.125);
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=23600
+@safe pure unittest
+{
+    import std.typecons : Tuple, tuple;
+
+    string h, w;
+    Tuple!(int, float) t;
+
+    assert("hello 1 2.34 world".formattedRead!"%s %d %f %s"(h, t, w) == 3);
+    assert(h == "hello");
+    assert(t == tuple(1, 2.34f));
+    assert(w == "world");
+}
+
 @safe unittest
 {
     import std.math.operations : isClose;
index c85247f924ede10af4270c3e6f79bbe7a3f869f9..42aeb4099e704aab9a6ffd882a8442d5ca1c2949 100644 (file)
@@ -558,7 +558,7 @@ private template optionValidator(A...)
     import std.format : format;
 
     enum fmt = "getopt validator: %s (at position %d)";
-    enum isReceiver(T) = is(T : U*, U) || (is(T == function)) || (is(T == delegate));
+    enum isReceiver(T) = is(T == U*, U) || (is(T == function)) || (is(T == delegate));
     enum isOptionStr(T) = isSomeString!T || isSomeChar!T;
 
     auto validator()
index d7b2c29119ec91946e3d5cf1281343e76cc204fe..093ebd1c19fbeaefee13c1e6662ac8e808284efa 100644 (file)
@@ -22,10 +22,16 @@ static if (size_t.sizeof == 4)
 enum hangulLVTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0x80], [ 0x100,  0x80,  0xa00], [ 0x0,  0x20100,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20001,  0x40003,  0x60005,  0x10007,  0x30002,  0x50004,  0x70006,  0x20001,  0x40003,  0x60005,  0x10007,  0x30002,  0x50004,  0x70006,  0x20001,  0x40003,  0x60005,  0x10007,  0x30002,  0x50004,  0x70006,  0x80001,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000001,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x10,  0x10000001,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x10,  0x10000001,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x10,  0x10000001,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x10,  0x10000001,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x10,  0x10000001,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x10,  0x10000001,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x10,  0x10000001,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x10,  0x1000000,  0x100000,  0x10000,  0x1000,  0x100,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
 //832 bytes
 enum hangulLVTTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0x80], [ 0x100,  0x80,  0xa00], [ 0x0,  0x20100,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20001,  0x40003,  0x60005,  0x10007,  0x30002,  0x50004,  0x70006,  0x20001,  0x40003,  0x60005,  0x10007,  0x30002,  0x50004,  0x70006,  0x20001,  0x40003,  0x60005,  0x10007,  0x30002,  0x50004,  0x70006,  0x80001,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xeffffffe,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xffffffef,  0xeffffffe,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xffffffef,  0xeffffffe,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xffffffef,  0xeffffffe,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xffffffef,  0xeffffffe,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xffffffef,  0xeffffffe,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xffffffef,  0xeffffffe,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xffffffef,  0xeffffffe,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xffffffef,  0xfeffffff,  0xffefffff,  0xfffeffff,  0xffffefff,  0xfffffeff,  0xf,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
-//1920 bytes
-enum mcTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0xc0], [ 0x100,  0x100,  0x2400], [ 0x2020100,  0x2020302,  0x5020204,  0x2060202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x30002,  0x50004,  0x60000,  0x7,  0x0,  0x0,  0x80000,  0x90000,  0xb000a,  0xc,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xd,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf000e,  0x110010,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x130012,  0x150014,  0x170016,  0x190018,  0x1b001a,  0x1c,  0x1e001d,  0x20001f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x210000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x220000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x8,  0xc8000000,  0xde01,  0x0,  0xc,  0xc0000000,  0x801981,  0x0,  0x8,  0xc0000000,  0x1,  0x0,  0x8,  0xc0000000,  0x1a01,  0x0,  0xc,  0x40000000,  0x801981,  0x0,  0x0,  0xc0000000,  0x801dc6,  0x0,  0xe,  0x0,  0x1e,  0x0,  0xc,  0x40000000,  0x600d9f,  0x80000,  0xc,  0xc0000000,  0x801dc1,  0x0,  0xc,  0x0,  0xff038000,  0xc0000,  0x0,  0xc0000000,  0x0,  0x80000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x19021800,  0xc00000,  0x3f9c,  0x1c009f98,  0x0,  0x0,  0x0,  0x200000,  0x100000,  0x0,  0x0,  0x0,  0xc0400000,  0x1bf,  0x0,  0x0,  0x1fb0e78,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x6000000,  0x0,  0xa00000,  0x7e01a,  0x0,  0x0,  0x0,  0x0,  0x10,  0xe8200000,  0x1b,  0x0,  0x4,  0x4c2,  0x0,  0xc5c80,  0x0,  0x300ff0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x800002,  0x0,  0xc000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x98,  0x0,  0x0,  0x3,  0xfff00000,  0xf,  0x0,  0x0,  0x0,  0xc0000,  0x0,  0x8,  0xcc300000,  0x1,  0x0,  0x0,  0x198000,  0x2000,  0x28000000,  0x0,  0x0,  0x0,  0x20c800,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x16d8,  0x5,  0x0,  0x0,  0x0,  0x4,  0x1870000,  0x0,  0x0,  0x0,  0x1000,  0x60,  0x0,  0x4,  0x80380000,  0x4001,  0x0,  0x0,  0x2c7000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7,  0xc,  0xc0000000,  0x80399e,  0xc,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe00000,  0x23,  0x0,  0x0,  0x7a070000,  0x2,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4f038000,  0x0,  0x0,  0x0,  0x58070000,  0x0,  0x0,  0x0,  0x40d000,  0x0,  0x0,  0x0,  0x43,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1007000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x21bf0000,  0x5,  0x0,  0x0,  0x0,  0xf00e0000,  0x10,  0x0,  0x2000000,  0x1800000,  0x0,  0x800000,  0x0,  0x0,  0x0,  0x0,  0x40008000,  0x0,  0x0,  0x0,  0x120200,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x587c00,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x600000,  0x8,  0xc0300000,  0x2,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfffe0000,  0xffffffff,  0xff,  0x0,  0x0,  0x30000,  0x0,  0x0,  0x0,  0x7e060,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
-//3456 bytes
-enum graphemeExtendTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0x110], [ 0x100,  0x1a0,  0x4a00], [ 0x2020100,  0x4020302,  0x7020605,  0xa090802,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x202020b,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x30002,  0x50004,  0x70006,  0x90008,  0xb000a,  0xd000c,  0xe,  0xf0000,  0x0,  0x100000,  0x120011,  0x140013,  0x160015,  0x0,  0x17,  0x0,  0x0,  0x0,  0x0,  0x0,  0x190018,  0x0,  0x1a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b,  0x1d001c,  0x1f001e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x200000,  0x0,  0x220021,  0x230000,  0x250024,  0x0,  0x0,  0x0,  0x26,  0x270000,  0x290028,  0x2b002a,  0x2d002c,  0x2f002e,  0x310030,  0x330032,  0x34,  0x360035,  0x380037,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x39,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3b003a,  0x0,  0x3c0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3e0000,  0x3f0000,  0x40,  0x0,  0x0,  0x0,  0x41,  0x0,  0x0,  0x3b0042,  0x43,  0x44,  0x0,  0x460045,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x480047,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3f8,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfffe0000,  0xbfffffff,  0xb6,  0x0,  0x7ff0000,  0x0,  0xfffff800,  0x10000,  0x0,  0x0,  0x9fc00000,  0x3d9f,  0x20000,  0xffff0000,  0x7ff,  0x0,  0x0,  0x1ffc0,  0x0,  0x200ff800,  0xfbc00000,  0x3eef,  0xe000000,  0x0,  0xff000000,  0x0,  0xfffffc00,  0xfffffffb,  0x7,  0x14000000,  0xfe21fe,  0xc,  0x2,  0x50000000,  0x80201e,  0x4000000c,  0x6,  0x10000000,  0x23986,  0x230000,  0x6,  0x10000000,  0x21be,  0xfc00000c,  0x2,  0xd0000000,  0xe0201e,  0xc,  0x4,  0x40000000,  0x802001,  0x0,  0x11,  0xd0000000,  0x603dc1,  0xc,  0x2,  0x90000000,  0x603044,  0xc,  0x3,  0x58000000,  0x80201e,  0xc,  0x2,  0x0,  0x805c8400,  0x0,  0x0,  0x7f20000,  0x7f80,  0x0,  0x0,  0x1ff20000,  0x7f00,  0x0,  0x3000000,  0x2a00000,  0x0,  0x7ffe0000,  0xfeffe0df,  0x1fffffff,  0x40,  0x0,  0x0,  0x66fde000,  0xc3000000,  0x1e0001,  0x20002064,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe0000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1c0000,  0xc0000,  0xc0000,  0xc0000,  0x0,  0x3fb00000,  0x200ffe40,  0x0,  0xb800,  0x0,  0x0,  0x0,  0x60,  0x200,  0x0,  0x0,  0x0,  0xe040187,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9800000,  0x0,  0x7f400000,  0x9ff81fe5,  0x0,  0xffff0000,  0x7fff,  0x0,  0xf,  0x17f00000,  0x4,  0xff800,  0x3,  0x3b3c,  0x0,  0x3a340,  0x0,  0xcff000,  0x0,  0x0,  0x0,  0x0,  0xfff70000,  0x31021fd,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0x1000,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffff0000,  0x1ffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x38000,  0x0,  0x0,  0x0,  0x80000000,  0x0,  0x0,  0x0,  0xffffffff,  0x0,  0xfc00,  0x0,  0x0,  0x6000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3ff78000,  0xc0000000,  0x0,  0x0,  0x30000,  0x844,  0x1060,  0x0,  0x0,  0x0,  0x0,  0x30,  0x8003ffff,  0x0,  0x3fc0,  0x3ff80,  0x0,  0x7,  0x33c80000,  0x0,  0x20,  0x0,  0x667e00,  0x1008,  0x10000000,  0x0,  0xc19d0000,  0x2,  0x403000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2120,  0x40000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffff,  0xffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc0000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1,  0x0,  0x0,  0x0,  0x7c00000,  0x0,  0x0,  0x0,  0x0,  0xf06e,  0x87000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x60,  0x0,  0xf0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1800,  0x0,  0xe0000000,  0x0,  0x0,  0x1ffc0,  0x0,  0x3c,  0x0,  0x0,  0x0,  0x2,  0xff000000,  0x7f,  0x80190000,  0x3,  0x6780000,  0x4,  0x0,  0x7,  0x1fef80,  0x0,  0x80000,  0x3,  0x7fc00000,  0x9e00,  0x0,  0x0,  0x40d38000,  0x2,  0x0,  0x0,  0x0,  0x80000000,  0x7f8,  0x3,  0x58000000,  0x800001,  0x1f1fc0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xff000000,  0x4000005c,  0x0,  0x0,  0xa5f90000,  0xd,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb03c8000,  0x30000001,  0x0,  0x0,  0xa7f80000,  0x1,  0x0,  0x0,  0xbf2800,  0x0,  0x0,  0xe0000000,  0xfbc,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x6ff8000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x58010000,  0x8,  0x0,  0x0,  0x0,  0xcf00000,  0x1,  0x7fe,  0x79f80000,  0xe7e0080,  0x0,  0x37ffc00,  0x0,  0x0,  0x0,  0x0,  0xbf7f0000,  0x0,  0x0,  0xfffc0000,  0x6dfcff,  0x0,  0x0,  0x0,  0xb47e0000,  0xbf,  0x0,  0xa30000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x180000,  0x3,  0x7c00000,  0x5,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3fff81,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1f0000,  0x0,  0x7f0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x8000,  0x0,  0x78000,  0x0,  0x0,  0x10,  0x0,  0x0,  0x0,  0x0,  0x60000000,  0x0,  0x0,  0x0,  0xffffffff,  0xffff3fff,  0x7f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf807c3a0,  0xfe7,  0x3c00,  0x0,  0x0,  0x0,  0x0,  0x1c,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xf87fffff,  0xffffffff,  0x201fff,  0xf8000010,  0xfffe,  0x0,  0x0,  0xf9ffff7f,  0x7db,  0x0,  0x0,  0x8000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4000,  0x0,  0xf000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7f0000,  0x0,  0x0,  0x0,  0x7f0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//896 bytes
+enum prependTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0x80], [ 0x100,  0x80,  0xc00], [ 0x1010100,  0x1010101,  0x1010102,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20001,  0x3,  0x0,  0x40000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x60005,  0x0,  0x0,  0x0,  0x70000,  0x8,  0x90000,  0xa0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20000000,  0x0,  0x8000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x30000,  0x0,  0x0,  0x4,  0x0,  0x0,  0x4000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20000000,  0x2000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc,  0x0,  0x0,  0x80000000,  0x2,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4000000,  0x0,  0x0,  0x3f0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x40,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//1280 bytes
+enum controlTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0xd0], [ 0x100,  0x120,  0xe00], [ 0x2020100,  0x3020202,  0x2020402,  0x2060502,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020207,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x10001,  0x10001,  0x10002,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10003,  0x10001,  0x10001,  0x10001,  0x10004,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x60005,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10007,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10008,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x90001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0xb000a,  0xc000c,  0xc000c,  0xc000c,  0xc000c,  0xc000c,  0xc000c,  0xc000c,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0xffffdbff,  0x0,  0x0,  0x80000000,  0xffffffff,  0x2000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc800,  0x7f00,  0x0,  0xffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x80000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfff0000,  0x0,  0xffff0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7f80000,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffff0000,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//1856 bytes
+enum spacingMarkTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0xb0], [ 0x100,  0xe0,  0x2400], [ 0x1010100,  0x1010201,  0x4010103,  0x1050101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x1010101,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x30002,  0x50004,  0x70006,  0x8,  0x0,  0x0,  0x90000,  0xa0000,  0xc000b,  0xd,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf000e,  0x110010,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x130012,  0x150014,  0x170016,  0x190018,  0x1b001a,  0x1c,  0x1e001d,  0x20001f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x210000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x220000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x8,  0xc8000000,  0xde01,  0x0,  0xc,  0x80000000,  0x1981,  0x0,  0x8,  0xc0000000,  0x1,  0x0,  0x8,  0xc0000000,  0x1a01,  0x0,  0xc,  0x0,  0x1981,  0x0,  0x0,  0x80000000,  0x1dc6,  0x0,  0xe,  0x0,  0x1e,  0x0,  0xc,  0x40000000,  0xd9b,  0x80000,  0xc,  0x80000000,  0x1dc1,  0x0,  0xc,  0x0,  0x7f030000,  0xc0000,  0x0,  0x80000,  0x0,  0x0,  0x0,  0x80000,  0x0,  0x0,  0x0,  0xc0000000,  0x0,  0x80000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x18020000,  0xc00000,  0x0,  0x10,  0x0,  0x0,  0x0,  0x200000,  0x100000,  0x0,  0x0,  0x0,  0xc0400000,  0x1bf,  0x0,  0x0,  0x1fb0e78,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x6000000,  0x0,  0xa00000,  0x7e000,  0x0,  0x0,  0x0,  0x0,  0x10,  0xe8000000,  0x1b,  0x0,  0x4,  0x4c2,  0x0,  0xc5c80,  0x0,  0x300ff0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x800002,  0x0,  0x98,  0x0,  0x0,  0x3,  0xfff00000,  0xf,  0x0,  0x0,  0x0,  0xc0000,  0x0,  0x8,  0xcc300000,  0x1,  0x0,  0x0,  0x198000,  0x2000,  0x0,  0x0,  0x0,  0x0,  0x20c800,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x16d8,  0x5,  0x0,  0x0,  0x0,  0x4,  0x1870000,  0x0,  0x0,  0x0,  0x1000,  0x60,  0x0,  0x4,  0x80380000,  0x4001,  0x0,  0x0,  0x2c7000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7,  0xc,  0x80000000,  0x399e,  0xc,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe00000,  0x23,  0x0,  0x0,  0x5a060000,  0x2,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4f030000,  0x0,  0x0,  0x0,  0x58070000,  0x0,  0x0,  0x0,  0x40d000,  0x0,  0x0,  0x0,  0x40,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1007000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x21be0000,  0x5,  0x0,  0x0,  0x0,  0xf00e0000,  0x10,  0x0,  0x2000000,  0x1800000,  0x0,  0x800000,  0x0,  0x0,  0x0,  0x0,  0x40008000,  0x0,  0x0,  0x0,  0x120200,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x587c00,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x600000,  0x8,  0xc0300000,  0x2,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfffe0000,  0xffffffff,  0xff,  0x0,  0x0,  0x30000,  0x0,  0x0,  0x0,  0x2040,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//3488 bytes
+enum graphemeExtendTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0x110], [ 0x100,  0x1a0,  0x4b00], [ 0x2020100,  0x4020302,  0x7020605,  0xa090802,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x202020b,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x30002,  0x50004,  0x70006,  0x90008,  0xb000a,  0xd000c,  0xe,  0xf0000,  0x0,  0x100000,  0x120011,  0x140013,  0x160015,  0x0,  0x17,  0x0,  0x0,  0x0,  0x0,  0x0,  0x190018,  0x0,  0x1a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b,  0x1d001c,  0x1f001e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x200000,  0x0,  0x220021,  0x230000,  0x250024,  0x0,  0x0,  0x0,  0x26,  0x270000,  0x290028,  0x2b002a,  0x2d002c,  0x2f002e,  0x310030,  0x330032,  0x34,  0x360035,  0x380037,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x39,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3b003a,  0x0,  0x3c0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3d,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3e0000,  0x3f0000,  0x40,  0x0,  0x0,  0x0,  0x41,  0x0,  0x0,  0x3b0042,  0x43,  0x44,  0x0,  0x460045,  0x0,  0x0,  0x0,  0x0,  0x470000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x490048,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3f8,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfffe0000,  0xbfffffff,  0xb6,  0x0,  0x7ff0000,  0x0,  0xfffff800,  0x10000,  0x0,  0x0,  0x9fc00000,  0x3d9f,  0x20000,  0xffff0000,  0x7ff,  0x0,  0x0,  0x1ffc0,  0x0,  0x200ff800,  0xfbc00000,  0x3eef,  0xe000000,  0x0,  0xff000000,  0x0,  0xfffffc00,  0xfffffffb,  0x7,  0x14000000,  0xfe21fe,  0xc,  0x2,  0x50000000,  0x80201e,  0x4000000c,  0x6,  0x10000000,  0x23986,  0x230000,  0x6,  0x10000000,  0x21be,  0xfc00000c,  0x2,  0xd0000000,  0xe0201e,  0xc,  0x4,  0x40000000,  0x802001,  0x0,  0x11,  0xd0000000,  0x603dc1,  0xc,  0x2,  0x90000000,  0x603044,  0xc,  0x3,  0x58000000,  0x80201e,  0xc,  0x2,  0x0,  0x805c8400,  0x0,  0x0,  0x7f20000,  0x7f80,  0x0,  0x0,  0x1ff20000,  0x7f00,  0x0,  0x3000000,  0x2a00000,  0x0,  0x7ffe0000,  0xfeffe0df,  0x1fffffff,  0x40,  0x0,  0x0,  0x66fde000,  0xc3000000,  0x1e0001,  0x20002064,  0x0,  0x0,  0x0,  0x0,  0x0,  0xe0000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1c0000,  0xc0000,  0xc0000,  0xc0000,  0x0,  0x3fb00000,  0x200ffe40,  0x0,  0xb800,  0x0,  0x0,  0x0,  0x60,  0x200,  0x0,  0x0,  0x0,  0xe040187,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x9800000,  0x0,  0x7f400000,  0x9ff81fe5,  0x0,  0xffff0000,  0x7fff,  0x0,  0xf,  0x17f00000,  0x4,  0xff800,  0x3,  0x3b3c,  0x0,  0x3a340,  0x0,  0xcff000,  0x0,  0x0,  0x0,  0x0,  0xfff70000,  0x31021fd,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0x1000,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffff0000,  0x1ffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x38000,  0x0,  0x0,  0x0,  0x80000000,  0x0,  0x0,  0x0,  0xffffffff,  0x0,  0xfc00,  0x0,  0x0,  0x6000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3ff78000,  0xc0000000,  0x0,  0x0,  0x30000,  0x844,  0x1060,  0x0,  0x0,  0x0,  0x0,  0x30,  0x8003ffff,  0x0,  0x3fc0,  0x3ff80,  0x0,  0x7,  0x33c80000,  0x0,  0x20,  0x0,  0x667e00,  0x1008,  0x10000000,  0x0,  0xc19d0000,  0x2,  0x403000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2120,  0x40000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffff,  0xffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc0000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1,  0x0,  0x0,  0x0,  0x7c00000,  0x0,  0x0,  0x0,  0x0,  0xf06e,  0x87000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x60,  0x0,  0xf0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1800,  0x0,  0xe0000000,  0x0,  0x0,  0x1ffc0,  0x0,  0x3c,  0x0,  0x0,  0x0,  0x2,  0xff000000,  0x7f,  0x80190000,  0x3,  0x6780000,  0x4,  0x0,  0x7,  0x1fef80,  0x0,  0x80000,  0x3,  0x7fc00000,  0x9e00,  0x0,  0x0,  0x40d38000,  0x2,  0x0,  0x0,  0x0,  0x80000000,  0x7f8,  0x3,  0x58000000,  0x800001,  0x1f1fc0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xff000000,  0x4000005c,  0x0,  0x0,  0xa5f90000,  0xd,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xb03c8000,  0x30000001,  0x0,  0x0,  0xa7f80000,  0x1,  0x0,  0x0,  0xbf2800,  0x0,  0x0,  0xe0000000,  0xfbc,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x6ff8000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x58010000,  0x8,  0x0,  0x0,  0x0,  0xcf00000,  0x1,  0x7fe,  0x79f80000,  0xe7e0080,  0x0,  0x37ffc00,  0x0,  0x0,  0x0,  0x0,  0xbf7f0000,  0x0,  0x0,  0xfffc0000,  0x6dfcff,  0x0,  0x0,  0x0,  0xb47e0000,  0xbf,  0x0,  0xa30000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x180000,  0x3,  0x7c00000,  0x5,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3fff81,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1f0000,  0x0,  0x7f0000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x8000,  0x0,  0x78000,  0x0,  0x0,  0x10,  0x0,  0x0,  0x0,  0x0,  0x60000000,  0x0,  0x0,  0x0,  0xffffffff,  0xffff3fff,  0x7f,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf807c3a0,  0xfe7,  0x3c00,  0x0,  0x0,  0x0,  0x0,  0x1c,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xf87fffff,  0xffffffff,  0x201fff,  0xf8000010,  0xfffe,  0x0,  0x0,  0xf9ffff7f,  0x7db,  0x0,  0x0,  0x8000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4000,  0x0,  0xf000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x7f0000,  0x0,  0x0,  0x0,  0x7f0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf8000000,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0x0,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//1344 bytes
+enum Extended_PictographicTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x40,  0x90], [ 0x100,  0xa0,  0x1800], [ 0x2020100,  0x2020202,  0x2020202,  0x3020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x2020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x30002,  0x40001,  0x60005,  0x80007,  0x90001,  0xa0001,  0x10001,  0x10001,  0x1000b,  0x1000c,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0xe000d,  0x10000f,  0x11000d,  0x130012,  0x150014,  0x1000d,  0xd000d,  0x16000d,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x10001,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4200,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000000,  0x200,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2000004,  0x0,  0x0,  0x3f00000,  0x600,  0x0,  0x0,  0xc000000,  0x100,  0x0,  0x0,  0x100,  0x0,  0x8000,  0x70ffe00,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x400c00,  0x1,  0x78000000,  0xfff7ffbf,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff003f,  0xffffffff,  0xffffffff,  0xffffffff,  0x2057ff3f,  0x180102,  0xb85090,  0xf8,  0xe00000,  0x80010002,  0x0,  0x0,  0x0,  0x300000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x180000e0,  0x0,  0x210000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20010000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2800000,  0x0,  0x0,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xe000,  0x8000,  0x0,  0xc003f000,  0x7fe4000,  0xffffe000,  0xffffffff,  0x3f,  0x400fffe,  0xf7fc8000,  0xfffffe00,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x7ffffff,  0xffffffff,  0x3fffffff,  0xffffffc0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffff,  0x0,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x0,  0x0,  0x0,  0xfff00000,  0x0,  0x0,  0xffe00000,  0xffffffff,  0xf000,  0x0,  0xfc00ff00,  0x0,  0xff00,  0xffffc000,  0xffffffff,  0xffffffff,  0xfffff000,  0xf7ffffff,  0xffffffbf,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0xffffffff,  0x3fffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
 
 }
 
@@ -36,10 +42,16 @@ static if (size_t.sizeof == 8)
 enum hangulLVTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x40], [ 0x100,  0x80,  0xa00], [ 0x2010000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4000300020001,  0x1000700060005,  0x5000400030002,  0x2000100070006,  0x6000500040003,  0x3000200010007,  0x7000600050004,  0x4000300020001,  0x1000700060005,  0x5000400030002,  0x8000100070006,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x100000010000001,  0x1000000100000,  0x10000001000,  0x1000000100000010,  0x10000001000000,  0x100000010000,  0x1000000100,  0x100000010000001,  0x1000000100000,  0x10000001000,  0x1000000100000010,  0x10000001000000,  0x100000010000,  0x1000000100,  0x100000010000001,  0x1000000100000,  0x10000001000,  0x1000000100000010,  0x10000001000000,  0x100000010000,  0x1000000100,  0x100000010000001,  0x1000000100000,  0x10000001000,  0x1000000100000010,  0x10000001000000,  0x100000010000,  0x1000000100,  0x10000001000000,  0x100000010000,  0x100,  0x0,  0x0,  0x0,  0x0,  0x0]);
 //832 bytes
 enum hangulLVTTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x40], [ 0x100,  0x80,  0xa00], [ 0x2010000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x4000300020001,  0x1000700060005,  0x5000400030002,  0x2000100070006,  0x6000500040003,  0x3000200010007,  0x7000600050004,  0x4000300020001,  0x1000700060005,  0x5000400030002,  0x8000100070006,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xfeffffffeffffffe,  0xfffeffffffefffff,  0xfffffeffffffefff,  0xeffffffeffffffef,  0xffeffffffeffffff,  0xffffeffffffeffff,  0xffffffeffffffeff,  0xfeffffffeffffffe,  0xfffeffffffefffff,  0xfffffeffffffefff,  0xeffffffeffffffef,  0xffeffffffeffffff,  0xffffeffffffeffff,  0xffffffeffffffeff,  0xfeffffffeffffffe,  0xfffeffffffefffff,  0xfffffeffffffefff,  0xeffffffeffffffef,  0xffeffffffeffffff,  0xffffeffffffeffff,  0xffffffeffffffeff,  0xfeffffffeffffffe,  0xfffeffffffefffff,  0xfffffeffffffefff,  0xeffffffeffffffef,  0xffeffffffeffffff,  0xffffeffffffeffff,  0xffffffeffffffeff,  0xffeffffffeffffff,  0xffffeffffffeffff,  0xffffffeff,  0x0,  0x0,  0x0,  0x0,  0x0]);
-//1920 bytes
-enum mcTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x60], [ 0x100,  0x100,  0x2400], [ 0x202030202020100,  0x206020205020204,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3000200010000,  0x6000000050004,  0x7,  0x8000000000000,  0xb000a00090000,  0xc,  0x0,  0x0,  0x0,  0x0,  0xd,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x110010000f000e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x15001400130012,  0x19001800170016,  0x1c001b001a,  0x20001f001e001d,  0x0,  0x0,  0x0,  0x21000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x220000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc800000000000008,  0xde01,  0xc00000000000000c,  0x801981,  0xc000000000000008,  0x1,  0xc000000000000008,  0x1a01,  0x400000000000000c,  0x801981,  0xc000000000000000,  0x801dc6,  0xe,  0x1e,  0x400000000000000c,  0x8000000600d9f,  0xc00000000000000c,  0x801dc1,  0xc,  0xc0000ff038000,  0xc000000000000000,  0x8000000000000000,  0x0,  0x0,  0x1902180000000000,  0x3f9c00c00000,  0x1c009f98,  0x0,  0x10000000200000,  0x0,  0xc040000000000000,  0x1bf,  0x1fb0e7800000000,  0x0,  0x0,  0x0,  0x6000000,  0x7e01a00a00000,  0x0,  0x0,  0xe820000000000010,  0x1b,  0x4c200000004,  0xc5c8000000000,  0x300ff000000000,  0x0,  0x0,  0x80000200000000,  0xc00000000000,  0x0,  0x0,  0x0,  0x9800000000,  0x0,  0xfff0000000000003,  0xf,  0x0,  0xc0000,  0xcc30000000000008,  0x1,  0x19800000000000,  0x2800000000002000,  0x0,  0x20c80000000000,  0x0,  0x0,  0x0,  0x16d800000000,  0x5,  0x0,  0x187000000000004,  0x0,  0x100000000000,  0x60,  0x8038000000000004,  0x4001,  0x2c700000000000,  0x0,  0x0,  0x700000000,  0xc00000000000000c,  0xc0080399e,  0x0,  0x0,  0xe0000000000000,  0x23,  0x7a07000000000000,  0x2,  0x0,  0x0,  0x4f03800000000000,  0x0,  0x5807000000000000,  0x0,  0x40d00000000000,  0x0,  0x4300000000,  0x0,  0x0,  0x0,  0x100700000000000,  0x0,  0x0,  0x0,  0x21bf000000000000,  0x5,  0x0,  0x10f00e0000,  0x200000000000000,  0x1800000,  0x800000,  0x0,  0x4000800000000000,  0x0,  0x12020000000000,  0x0,  0x0,  0x0,  0x587c00,  0x0,  0x0,  0x0,  0x0,  0x60000000000000,  0xc030000000000008,  0x2,  0x0,  0x0,  0x0,  0xfffffffffffe0000,  0xff,  0x3000000000000,  0x0,  0x7e06000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
-//3456 bytes
-enum graphemeExtendTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x88], [ 0x100,  0x1a0,  0x4a00], [ 0x402030202020100,  0xa09080207020605,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x20202020202020b,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1000000000000,  0x5000400030002,  0x9000800070006,  0xd000c000b000a,  0xf00000000000e,  0x10000000000000,  0x14001300120011,  0x160015,  0x17,  0x0,  0x0,  0x190018,  0x1a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b00000000,  0x1f001e001d001c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20000000000000,  0x22002100000000,  0x25002400230000,  0x0,  0x2600000000,  0x29002800270000,  0x2d002c002b002a,  0x310030002f002e,  0x3400330032,  0x38003700360035,  0x0,  0x0,  0x0,  0x0,  0x0,  0x39,  0x0,  0x0,  0x0,  0x0,  0x3b003a00000000,  0x3c000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3d,  0x0,  0x0,  0x0,  0x3e000000000000,  0x40003f0000,  0x0,  0x4100000000,  0x0,  0x43003b0042,  0x44,  0x460045,  0x0,  0x0,  0x0,  0x0,  0x0,  0x480047,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffff,  0x0,  0x0,  0x0,  0x0,  0x3f8,  0x0,  0x0,  0x0,  0xbffffffffffe0000,  0xb6,  0x7ff0000,  0x10000fffff800,  0x0,  0x3d9f9fc00000,  0xffff000000020000,  0x7ff,  0x1ffc000000000,  0x200ff80000000000,  0x3eeffbc00000,  0xe000000,  0xff000000,  0xfffffffbfffffc00,  0x1400000000000007,  0xc00fe21fe,  0x5000000000000002,  0x4000000c0080201e,  0x1000000000000006,  0x23000000023986,  0x1000000000000006,  0xfc00000c000021be,  0xd000000000000002,  0xc00e0201e,  0x4000000000000004,  0x802001,  0xd000000000000011,  0xc00603dc1,  0x9000000000000002,  0xc00603044,  0x5800000000000003,  0xc0080201e,  0x2,  0x805c8400,  0x7f2000000000000,  0x7f80,  0x1ff2000000000000,  0x7f00,  0x2a0000003000000,  0x7ffe000000000000,  0x1ffffffffeffe0df,  0x40,  0x66fde00000000000,  0x1e0001c3000000,  0x20002064,  0x0,  0x0,  0xe0000000,  0x0,  0x0,  0xc0000001c0000,  0xc0000000c0000,  0x3fb0000000000000,  0x200ffe40,  0xb800,  0x0,  0x20000000060,  0x0,  0xe04018700000000,  0x0,  0x0,  0x0,  0x9800000,  0x9ff81fe57f400000,  0xffff000000000000,  0x7fff,  0x17f000000000000f,  0xff80000000004,  0x3b3c00000003,  0x3a34000000000,  0xcff00000000000,  0x0,  0x0,  0x31021fdfff70000,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0x1000,  0x0,  0x0,  0x1ffffffff0000,  0x0,  0x0,  0x0,  0x3800000000000,  0x0,  0x8000000000000000,  0x0,  0xffffffff00000000,  0xfc0000000000,  0x0,  0x6000000,  0x0,  0x0,  0x3ff7800000000000,  0xc0000000,  0x3000000000000,  0x106000000844,  0x0,  0x0,  0x8003ffff00000030,  0x3fc000000000,  0x3ff80,  0x33c8000000000007,  0x2000000000,  0x667e0000000000,  0x1000000000001008,  0xc19d000000000000,  0x40300000000002,  0x0,  0x0,  0x0,  0x212000000000,  0x40000000,  0x0,  0x0,  0x0,  0xffff0000ffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc0000000,  0x0,  0x0,  0x0,  0x0,  0x2000000000000000,  0x0,  0x0,  0x0,  0x100000000,  0x0,  0x7c0000000000000,  0x0,  0x0,  0x870000000000f06e,  0x0,  0x0,  0x6000000000,  0xf000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x180000000000,  0xe000000000000000,  0x0,  0x1ffc0,  0x3c,  0x0,  0xff00000000000002,  0x801900000000007f,  0x678000000000003,  0x4,  0x1fef8000000007,  0x8000000000000,  0x7fc0000000000003,  0x9e00,  0x40d3800000000000,  0x2,  0x0,  0x7f880000000,  0x5800000000000003,  0x1f1fc000800001,  0x0,  0x0,  0xff00000000000000,  0x4000005c,  0xa5f9000000000000,  0xd,  0x0,  0x0,  0xb03c800000000000,  0x30000001,  0xa7f8000000000000,  0x1,  0xbf280000000000,  0x0,  0xfbce0000000,  0x0,  0x0,  0x0,  0x6ff800000000000,  0x0,  0x0,  0x0,  0x5801000000000000,  0x8,  0x0,  0x10cf00000,  0x79f80000000007fe,  0xe7e0080,  0x37ffc00,  0x0,  0xbf7f000000000000,  0x0,  0x6dfcfffffc0000,  0x0,  0xb47e000000000000,  0xbf,  0xa30000,  0x0,  0x0,  0x0,  0x0,  0x18000000000000,  0x7c0000000000003,  0x5,  0x0,  0x0,  0x0,  0x3fff81,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1f000000000000,  0x7f000000000000,  0x0,  0x0,  0x0,  0x0,  0x8000,  0x78000,  0x1000000000,  0x0,  0x0,  0x60000000,  0x0,  0xffff3fffffffffff,  0x7f,  0x0,  0x0,  0x0,  0xf807c3a000000000,  0x3c0000000fe7,  0x0,  0x0,  0x1c,  0x0,  0x0,  0xf87fffffffffffff,  0x201fffffffffff,  0xfffef8000010,  0x0,  0x7dbf9ffff7f,  0x0,  0x8000,  0x0,  0x0,  0x0,  0x400000000000,  0xf00000000000,  0x0,  0x0,  0x0,  0xf00000000000,  0x0,  0x0,  0x0,  0x7f0000,  0x0,  0x7f0,  0x0,  0x0,  0xffffffff00000000,  0xffffffffffffffff,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffff,  0x0,  0x0,  0x0,  0x0]);
+//896 bytes
+enum prependTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x40], [ 0x100,  0x80,  0xc00], [ 0x101010101010100,  0x101010101010102,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2000100000000,  0x3,  0x40000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x60005,  0x0,  0x800070000,  0xa000000090000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3f,  0x0,  0x0,  0x20000000,  0x8000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x30000,  0x400000000,  0x0,  0x4000,  0x0,  0x0,  0x0,  0x0,  0x2000000000000000,  0x2000,  0x0,  0x0,  0x0,  0xc,  0x8000000000000000,  0x2,  0x0,  0x0,  0x400000000000000,  0x0,  0x3f0,  0x0,  0x0,  0x40,  0x0,  0x0,  0x4,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//1280 bytes
+enum controlTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x68], [ 0x100,  0x120,  0xe00], [ 0x302020202020100,  0x206050202020402,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020207,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1000100010000,  0x1000200010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010003,  0x1000100010001,  0x1000100010004,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x6000500010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010007,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010008,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100090001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0xc000c000b000a,  0xc000c000c000c,  0xc000c000c000c,  0xc000c000c000c,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0xffffdbff,  0x8000000000000000,  0x2000ffffffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0x10000000,  0x0,  0x0,  0x0,  0x4000,  0x0,  0x0,  0x0,  0x7f000000c800,  0xffff00000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x8000000000000000,  0x0,  0x0,  0x0,  0xfff000000000000,  0xffff000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf00000000,  0x0,  0x0,  0x7f8000000000000,  0x0,  0x0,  0xffffffff,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0x0,  0x0,  0x0,  0xffff000000000000,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x0,  0x0,  0x0,  0x0]);
+//1856 bytes
+enum spacingMarkTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x58], [ 0x100,  0xe0,  0x2400], [ 0x101020101010100,  0x105010104010103,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x101010101010101,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3000200010000,  0x7000600050004,  0x8,  0x9000000000000,  0xc000b000a0000,  0xd,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x110010000f000e,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x15001400130012,  0x19001800170016,  0x1c001b001a,  0x20001f001e001d,  0x0,  0x0,  0x0,  0x21000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x220000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc800000000000008,  0xde01,  0x800000000000000c,  0x1981,  0xc000000000000008,  0x1,  0xc000000000000008,  0x1a01,  0xc,  0x1981,  0x8000000000000000,  0x1dc6,  0xe,  0x1e,  0x400000000000000c,  0x8000000000d9b,  0x800000000000000c,  0x1dc1,  0xc,  0xc00007f030000,  0x8000000000000,  0x0,  0x8000000000000,  0x0,  0xc000000000000000,  0x8000000000000000,  0x0,  0x0,  0x1802000000000000,  0xc00000,  0x10,  0x0,  0x10000000200000,  0x0,  0xc040000000000000,  0x1bf,  0x1fb0e7800000000,  0x0,  0x0,  0x0,  0x6000000,  0x7e00000a00000,  0x0,  0x0,  0xe800000000000010,  0x1b,  0x4c200000004,  0xc5c8000000000,  0x300ff000000000,  0x0,  0x0,  0x80000200000000,  0x9800000000,  0x0,  0xfff0000000000003,  0xf,  0x0,  0xc0000,  0xcc30000000000008,  0x1,  0x19800000000000,  0x2000,  0x0,  0x20c80000000000,  0x0,  0x0,  0x0,  0x16d800000000,  0x5,  0x0,  0x187000000000004,  0x0,  0x100000000000,  0x60,  0x8038000000000004,  0x4001,  0x2c700000000000,  0x0,  0x0,  0x700000000,  0x800000000000000c,  0xc0000399e,  0x0,  0x0,  0xe0000000000000,  0x23,  0x5a06000000000000,  0x2,  0x0,  0x0,  0x4f03000000000000,  0x0,  0x5807000000000000,  0x0,  0x40d00000000000,  0x0,  0x4000000000,  0x0,  0x0,  0x0,  0x100700000000000,  0x0,  0x0,  0x0,  0x21be000000000000,  0x5,  0x0,  0x10f00e0000,  0x200000000000000,  0x1800000,  0x800000,  0x0,  0x4000800000000000,  0x0,  0x12020000000000,  0x0,  0x0,  0x0,  0x587c00,  0x0,  0x0,  0x0,  0x0,  0x60000000000000,  0xc030000000000008,  0x2,  0x0,  0x0,  0x0,  0xfffffffffffe0000,  0xff,  0x3000000000000,  0x0,  0x204000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0]);
+//3488 bytes
+enum graphemeExtendTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x88], [ 0x100,  0x1a0,  0x4b00], [ 0x402030202020100,  0xa09080207020605,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x20202020202020b,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1000000000000,  0x5000400030002,  0x9000800070006,  0xd000c000b000a,  0xf00000000000e,  0x10000000000000,  0x14001300120011,  0x160015,  0x17,  0x0,  0x0,  0x190018,  0x1a,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1b00000000,  0x1f001e001d001c,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x20000000000000,  0x22002100000000,  0x25002400230000,  0x0,  0x2600000000,  0x29002800270000,  0x2d002c002b002a,  0x310030002f002e,  0x3400330032,  0x38003700360035,  0x0,  0x0,  0x0,  0x0,  0x0,  0x39,  0x0,  0x0,  0x0,  0x0,  0x3b003a00000000,  0x3c000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x3d,  0x0,  0x0,  0x0,  0x3e000000000000,  0x40003f0000,  0x0,  0x4100000000,  0x0,  0x43003b0042,  0x44,  0x460045,  0x0,  0x47000000000000,  0x0,  0x0,  0x0,  0x490048,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffff,  0x0,  0x0,  0x0,  0x0,  0x3f8,  0x0,  0x0,  0x0,  0xbffffffffffe0000,  0xb6,  0x7ff0000,  0x10000fffff800,  0x0,  0x3d9f9fc00000,  0xffff000000020000,  0x7ff,  0x1ffc000000000,  0x200ff80000000000,  0x3eeffbc00000,  0xe000000,  0xff000000,  0xfffffffbfffffc00,  0x1400000000000007,  0xc00fe21fe,  0x5000000000000002,  0x4000000c0080201e,  0x1000000000000006,  0x23000000023986,  0x1000000000000006,  0xfc00000c000021be,  0xd000000000000002,  0xc00e0201e,  0x4000000000000004,  0x802001,  0xd000000000000011,  0xc00603dc1,  0x9000000000000002,  0xc00603044,  0x5800000000000003,  0xc0080201e,  0x2,  0x805c8400,  0x7f2000000000000,  0x7f80,  0x1ff2000000000000,  0x7f00,  0x2a0000003000000,  0x7ffe000000000000,  0x1ffffffffeffe0df,  0x40,  0x66fde00000000000,  0x1e0001c3000000,  0x20002064,  0x0,  0x0,  0xe0000000,  0x0,  0x0,  0xc0000001c0000,  0xc0000000c0000,  0x3fb0000000000000,  0x200ffe40,  0xb800,  0x0,  0x20000000060,  0x0,  0xe04018700000000,  0x0,  0x0,  0x0,  0x9800000,  0x9ff81fe57f400000,  0xffff000000000000,  0x7fff,  0x17f000000000000f,  0xff80000000004,  0x3b3c00000003,  0x3a34000000000,  0xcff00000000000,  0x0,  0x0,  0x31021fdfff70000,  0x0,  0x0,  0x0,  0xffffffffffffffff,  0x1000,  0x0,  0x0,  0x1ffffffff0000,  0x0,  0x0,  0x0,  0x3800000000000,  0x0,  0x8000000000000000,  0x0,  0xffffffff00000000,  0xfc0000000000,  0x0,  0x6000000,  0x0,  0x0,  0x3ff7800000000000,  0xc0000000,  0x3000000000000,  0x106000000844,  0x0,  0x0,  0x8003ffff00000030,  0x3fc000000000,  0x3ff80,  0x33c8000000000007,  0x2000000000,  0x667e0000000000,  0x1000000000001008,  0xc19d000000000000,  0x40300000000002,  0x0,  0x0,  0x0,  0x212000000000,  0x40000000,  0x0,  0x0,  0x0,  0xffff0000ffff,  0x0,  0x0,  0x0,  0x0,  0x0,  0xc0000000,  0x0,  0x0,  0x0,  0x0,  0x2000000000000000,  0x0,  0x0,  0x0,  0x100000000,  0x0,  0x7c0000000000000,  0x0,  0x0,  0x870000000000f06e,  0x0,  0x0,  0x6000000000,  0xf000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x180000000000,  0xe000000000000000,  0x0,  0x1ffc0,  0x3c,  0x0,  0xff00000000000002,  0x801900000000007f,  0x678000000000003,  0x4,  0x1fef8000000007,  0x8000000000000,  0x7fc0000000000003,  0x9e00,  0x40d3800000000000,  0x2,  0x0,  0x7f880000000,  0x5800000000000003,  0x1f1fc000800001,  0x0,  0x0,  0xff00000000000000,  0x4000005c,  0xa5f9000000000000,  0xd,  0x0,  0x0,  0xb03c800000000000,  0x30000001,  0xa7f8000000000000,  0x1,  0xbf280000000000,  0x0,  0xfbce0000000,  0x0,  0x0,  0x0,  0x6ff800000000000,  0x0,  0x0,  0x0,  0x5801000000000000,  0x8,  0x0,  0x10cf00000,  0x79f80000000007fe,  0xe7e0080,  0x37ffc00,  0x0,  0xbf7f000000000000,  0x0,  0x6dfcfffffc0000,  0x0,  0xb47e000000000000,  0xbf,  0xa30000,  0x0,  0x0,  0x0,  0x0,  0x18000000000000,  0x7c0000000000003,  0x5,  0x0,  0x0,  0x0,  0x3fff81,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1f000000000000,  0x7f000000000000,  0x0,  0x0,  0x0,  0x0,  0x8000,  0x78000,  0x1000000000,  0x0,  0x0,  0x60000000,  0x0,  0xffff3fffffffffff,  0x7f,  0x0,  0x0,  0x0,  0xf807c3a000000000,  0x3c0000000fe7,  0x0,  0x0,  0x1c,  0x0,  0x0,  0xf87fffffffffffff,  0x201fffffffffff,  0xfffef8000010,  0x0,  0x7dbf9ffff7f,  0x0,  0x8000,  0x0,  0x0,  0x0,  0x400000000000,  0xf00000000000,  0x0,  0x0,  0x0,  0xf00000000000,  0x0,  0x0,  0x0,  0x7f0000,  0x0,  0x7f0,  0x0,  0x0,  0x0,  0x0,  0x0,  0xf800000000000000,  0xffffffff00000000,  0xffffffffffffffff,  0x0,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffff,  0x0,  0x0,  0x0,  0x0]);
+//1344 bytes
+enum Extended_PictographicTrieEntries = TrieEntry!(bool, 8, 5, 8)([ 0x0,  0x20,  0x48], [ 0x100,  0xa0,  0x1800], [ 0x202020202020100,  0x302020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x202020202020202,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1000100010000,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x4000100030002,  0x8000700060005,  0xa000100090001,  0x1000100010001,  0x1000c0001000b,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x10000f000e000d,  0x1300120011000d,  0x1000d00150014,  0x16000d000d000d,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x1000100010001,  0x0,  0x0,  0x420000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x1000000000000000,  0x200,  0x0,  0x0,  0x200000400000000,  0x0,  0x60003f00000,  0x0,  0x1000c000000,  0x0,  0x100,  0x70ffe0000008000,  0x0,  0x0,  0x0,  0x4,  0x0,  0x0,  0x400c0000000000,  0x7800000000000001,  0xfffffffffff7ffbf,  0xffffffffffffffff,  0xffffffffffff003f,  0xffffffffffffffff,  0x1801022057ff3f,  0xf800b85090,  0x8001000200e00000,  0x0,  0x30000000000000,  0x0,  0x0,  0x0,  0x180000e0,  0x210000,  0x0,  0x0,  0x2001000000000000,  0x0,  0x0,  0x0,  0x0,  0x0,  0x2800000,  0x0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x80000000e000,  0xc003f00000000000,  0xffffe00007fe4000,  0x3fffffffff,  0xf7fc80000400fffe,  0xfffffffffffffe00,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x7ffffffffffffff,  0x3fffffffffffffff,  0xffffffffffffffc0,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x0,  0xfff0000000000000,  0x0,  0xffffffffffe00000,  0xf000,  0xfc00ff00,  0xffffc0000000ff00,  0xffffffffffffffff,  0xf7fffffffffff000,  0xffffffffffffffbf,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0xffffffffffffffff,  0x3fffffffffffffff,  0x0,  0x0,  0x0,  0x0]);
 
 }
 
index 66f4b8a05928b5108f523116733fd1f626397995..fd1ff244b626a1a2f95a43740f9ccaacd97e858a 100644 (file)
@@ -39,7 +39,8 @@ static import core.stdc.math;
 
 version (DigitalMars)
 {
-    version = INLINE_YL2X;        // x87 has opcodes for these
+    version (OSX) { }             // macOS 13 (M1) has issues emulating instruction
+    else version = INLINE_YL2X;   // x87 has opcodes for these
 }
 
 version (D_InlineAsm_X86)    version = InlineAsm_X86_Any;
@@ -2862,7 +2863,7 @@ float ldexp(float n, int exp)   @safe pure nothrow @nogc { return core.math.ldex
 
 private
 {
-    // Coefficients shared across log(), log2(), log10().
+    // Coefficients shared across log(), log2(), log10(), log1p().
     template LogCoeffs(T)
     {
         import std.math : floatTraits, RealFormat;
@@ -3022,6 +3023,25 @@ private
             alias log2Q = logQ;
 
             // Coefficients for log(1 + x) = x - x^^2/2 + x^^3 P(x)/Q(x)
+            static immutable double[7] logp1P = [
+                2.0039553499201281259648E1,
+                5.7112963590585538103336E1,
+                6.0949667980987787057556E1,
+                2.9911919328553073277375E1,
+                6.5787325942061044846969E0,
+                4.9854102823193375972212E-1,
+                4.5270000862445199635215E-5,
+            ];
+            static immutable double[7] logp1Q = [
+                1.0000000000000000000000E0,
+                6.0118660497603843919306E1,
+                2.1642788614495947685003E2,
+                3.0909872225312059774938E2,
+                2.2176239823732856465394E2,
+                8.3047565967967209469434E1,
+                1.5062909083469192043167E1,
+            ];
+
             static immutable double[7] log10P = [
                 1.98892446572874072159E1,
                 5.67349287391754285487E1,
@@ -3070,6 +3090,26 @@ private
                  7.0376836292E-2,
             ];
 
+            // Coefficients for log(1 + x) = x - x^^2/2 + x^^3 P(x)/Q(x)
+            static immutable float[7] logp1P = [
+                 2.0039553499E1,
+                 5.7112963590E1,
+                 6.0949667980E1,
+                 2.9911919328E1,
+                 6.5787325942E0,
+                 4.9854102823E-1,
+                 4.5270000862E-5,
+            ];
+            static immutable float[7] logp1Q = [
+                1.00000000000E0,
+                6.01186604976E1,
+                2.16427886144E2,
+                3.09098722253E2,
+                2.21762398237E2,
+                8.30475659679E1,
+                1.50629090834E1,
+            ];
+
             // log2 and log10 uses the same coefficients as log.
             alias log2P = logP;
             alias log10P = logP;
@@ -3135,7 +3175,7 @@ real log(ulong x) @safe pure nothrow @nogc { return log(cast(real) x); }
     assert(feqrel(log(E), 1) >= real.mant_dig - 1);
 }
 
-private T logImpl(T)(T x) @safe pure nothrow @nogc
+private T logImpl(T, bool LOG1P = false)(T x) @safe pure nothrow @nogc
 {
     import std.math.constants : SQRT1_2;
     import std.math.algebraic : poly;
@@ -3145,6 +3185,12 @@ private T logImpl(T)(T x) @safe pure nothrow @nogc
     alias coeffs = LogCoeffs!T;
     alias F = floatTraits!T;
 
+    static if (LOG1P)
+    {
+        const T xm1 = x;
+        x = x + 1.0;
+    }
+
     static if (F.realFormat == RealFormat.ieeeExtended ||
                F.realFormat == RealFormat.ieeeExtended53 ||
                F.realFormat == RealFormat.ieeeQuadruple)
@@ -3219,11 +3265,28 @@ private T logImpl(T)(T x) @safe pure nothrow @nogc
     if (x < SQRT1_2)
     {
         exp -= 1;
-        x = 2.0 * x - 1.0;
+        static if (LOG1P)
+        {
+            if (exp != 0)
+                x = 2.0 * x - 1.0;
+            else
+                x = xm1;
+        }
+        else
+            x = 2.0 * x - 1.0;
+
     }
     else
     {
-        x = x - 1.0;
+        static if (LOG1P)
+        {
+            if (exp != 0)
+                x = x - 1.0;
+            else
+                x = xm1;
+        }
+        else
+            x = x - 1.0;
     }
     z = x * x;
     static if (F.realFormat == RealFormat.ieeeSingle)
@@ -3241,6 +3304,84 @@ private T logImpl(T)(T x) @safe pure nothrow @nogc
     return z;
 }
 
+@safe @nogc nothrow unittest
+{
+    import std.math : floatTraits, RealFormat;
+    import std.meta : AliasSeq;
+
+    static void testLog(T)(T[2][] vals)
+    {
+        import std.math.operations : isClose;
+        import std.math.traits : isNaN;
+        foreach (ref pair; vals)
+        {
+            if (isNaN(pair[1]))
+                assert(isNaN(log(pair[0])));
+            else
+                assert(isClose(log(pair[0]), pair[1]));
+        }
+    }
+    static foreach (F; AliasSeq!(float, double, real))
+    {{
+        F[2][24] vals = [
+            [F(1), F(0x0p+0)], [F(2), F(0x1.62e42fefa39ef358p-1)],
+            [F(4), F(0x1.62e42fefa39ef358p+0)], [F(8), F(0x1.0a2b23f3bab73682p+1)],
+            [F(16), F(0x1.62e42fefa39ef358p+1)], [F(32), F(0x1.bb9d3beb8c86b02ep+1)],
+            [F(64), F(0x1.0a2b23f3bab73682p+2)], [F(128), F(0x1.3687a9f1af2b14ecp+2)],
+            [F(256), F(0x1.62e42fefa39ef358p+2)], [F(512), F(0x1.8f40b5ed9812d1c2p+2)],
+            [F(1024), F(0x1.bb9d3beb8c86b02ep+2)], [F(2048), F(0x1.e7f9c1e980fa8e98p+2)],
+            [F(3), F(0x1.193ea7aad030a976p+0)], [F(5), F(0x1.9c041f7ed8d336bp+0)],
+            [F(7), F(0x1.f2272ae325a57546p+0)], [F(15), F(0x1.5aa16394d481f014p+1)],
+            [F(17), F(0x1.6aa6bc1fa7f79cfp+1)], [F(31), F(0x1.b78ce48912b59f12p+1)],
+            [F(33), F(0x1.bf8d8f4d5b8d1038p+1)], [F(63), F(0x1.09291e8e3181b20ep+2)],
+            [F(65), F(0x1.0b292939429755ap+2)], [F(-0), -F.infinity], [F(0), -F.infinity],
+            [F(10000), F(0x1.26bb1bbb5551582ep+3)],
+        ];
+        testLog(vals);
+    }}
+    {
+        float[2][16] vals = [
+            [float.nan, float.nan],[-float.nan, float.nan],
+            [float.infinity, float.infinity], [-float.infinity, float.nan],
+            [float.min_normal, -0x1.5d58ap+6f], [-float.min_normal, float.nan],
+            [float.max, 0x1.62e43p+6f], [-float.max, float.nan],
+            [float.min_normal / 2, -0x1.601e68p+6f], [-float.min_normal / 2, float.nan],
+            [float.max / 2, 0x1.601e68p+6f], [-float.max / 2, float.nan],
+            [float.min_normal / 3, -0x1.61bd9ap+6f], [-float.min_normal / 3, float.nan],
+            [float.max / 3, 0x1.5e7f36p+6f], [-float.max / 3, float.nan],
+        ];
+        testLog(vals);
+    }
+    {
+        double[2][16] vals = [
+            [double.nan, double.nan],[-double.nan, double.nan],
+            [double.infinity, double.infinity], [-double.infinity, double.nan],
+            [double.min_normal, -0x1.6232bdd7abcd2p+9], [-double.min_normal, double.nan],
+            [double.max, 0x1.62e42fefa39efp+9], [-double.max, double.nan],
+            [double.min_normal / 2, -0x1.628b76e3a7b61p+9], [-double.min_normal / 2, double.nan],
+            [double.max / 2, 0x1.628b76e3a7b61p+9], [-double.max / 2, double.nan],
+            [double.min_normal / 3, -0x1.62bf5d2b81354p+9], [-double.min_normal / 3, double.nan],
+            [double.max / 3, 0x1.6257909bce36ep+9], [-double.max / 3, double.nan],
+        ];
+        testLog(vals);
+    }
+    alias F = floatTraits!real;
+    static if (F.realFormat == RealFormat.ieeeExtended || F.realFormat == RealFormat.ieeeQuadruple)
+    {{
+        real[2][16] vals = [
+            [real.nan, real.nan],[-real.nan, real.nan],
+            [real.infinity, real.infinity], [-real.infinity, real.nan],
+            [real.min_normal, -0x1.62d918ce2421d66p+13L], [-real.min_normal, real.nan],
+            [real.max, 0x1.62e42fefa39ef358p+13L], [-real.max, real.nan],
+            [real.min_normal / 2, -0x1.62dea45ee3e064dcp+13L], [-real.min_normal / 2, real.nan],
+            [real.max / 2, 0x1.62dea45ee3e064dcp+13L], [-real.max / 2, real.nan],
+            [real.min_normal / 3, -0x1.62e1e2c3617857e6p+13L], [-real.min_normal / 3, real.nan],
+            [real.max / 3, 0x1.62db65fa664871d2p+13L], [-real.max / 3, real.nan],
+        ];
+        testLog(vals);
+    }}
+}
+
 /**************************************
  * Calculate the base-10 logarithm of x.
  *
@@ -3296,6 +3437,14 @@ real log10(ulong x) @safe pure nothrow @nogc { return log10(cast(real) x); }
     assert(fabs(log10(1000.0L) - 3) < .000001);
 }
 
+@safe pure nothrow @nogc unittest
+{
+    import std.math.algebraic : fabs;
+
+    assert(fabs(log10(1000.0) - 3) < .000001);
+    assert(fabs(log10(1000.0f) - 3) < .000001);
+}
+
 private T log10Impl(T)(T x) @safe pure nothrow @nogc
 {
     import std.math.constants : SQRT1_2;
@@ -3404,6 +3553,84 @@ Ldone:
     return z;
 }
 
+@safe @nogc nothrow unittest
+{
+    import std.math : floatTraits, RealFormat;
+    import std.meta : AliasSeq;
+
+    static void testLog10(T)(T[2][] vals)
+    {
+        import std.math.operations : isClose;
+        import std.math.traits : isNaN;
+        foreach (ref pair; vals)
+        {
+            if (isNaN(pair[1]))
+                assert(isNaN(log10(pair[0])));
+            else
+                assert(isClose(log10(pair[0]), pair[1]));
+        }
+    }
+    static foreach (F; AliasSeq!(float, double, real))
+    {{
+        F[2][24] vals = [
+            [F(1), F(0x0p+0)], [F(2), F(0x1.34413509f79fef32p-2)],
+            [F(4), F(0x1.34413509f79fef32p-1)], [F(8), F(0x1.ce61cf8ef36fe6cap-1)],
+            [F(16), F(0x1.34413509f79fef32p+0)], [F(32), F(0x1.8151824c7587eafep+0)],
+            [F(64), F(0x1.ce61cf8ef36fe6cap+0)], [F(128), F(0x1.0db90e68b8abf14cp+1)],
+            [F(256), F(0x1.34413509f79fef32p+1)], [F(512), F(0x1.5ac95bab3693ed18p+1)],
+            [F(1024), F(0x1.8151824c7587eafep+1)], [F(2048), F(0x1.a7d9a8edb47be8e4p+1)],
+            [F(3), F(0x1.e8927964fd5fd08cp-2)], [F(5), F(0x1.65df657b04300868p-1)],
+            [F(7), F(0x1.b0b0b0b78cc3f296p-1)], [F(15), F(0x1.2d145116c16ff856p+0)],
+            [F(17), F(0x1.3afeb354b7d9731ap+0)], [F(31), F(0x1.7dc9e145867e62eap+0)],
+            [F(33), F(0x1.84bd545e4baeddp+0)], [F(63), F(0x1.cca1950e4511e192p+0)],
+            [F(65), F(0x1.d01b16f9433cf7b8p+0)], [F(-0), -F.infinity], [F(0), -F.infinity],
+            [F(10000), F(0x1p+2)],
+        ];
+        testLog10(vals);
+    }}
+    {
+        float[2][16] vals = [
+            [float.nan, float.nan],[-float.nan, float.nan],
+            [float.infinity, float.infinity], [-float.infinity, float.nan],
+            [float.min_normal, -0x1.2f703p+5f], [-float.min_normal, float.nan],
+            [float.max, 0x1.344136p+5f], [-float.max, float.nan],
+            [float.min_normal / 2, -0x1.31d8b2p+5f], [-float.min_normal / 2, float.nan],
+            [float.max / 2, 0x1.31d8b2p+5f], [-float.max / 2, float.nan],
+            [float.min_normal / 3, -0x1.334156p+5f], [-float.min_normal / 3, float.nan],
+            [float.max / 3, 0x1.30701p+5f], [-float.max / 3, float.nan],
+        ];
+        testLog10(vals);
+    }
+    {
+        double[2][16] vals = [
+            [double.nan, double.nan],[-double.nan, double.nan],
+            [double.infinity, double.infinity], [-double.infinity, double.nan],
+            [double.min_normal, -0x1.33a7146f72a42p+8], [-double.min_normal, double.nan],
+            [double.max, 0x1.34413509f79ffp+8], [-double.max, double.nan],
+            [double.min_normal / 2, -0x1.33f424bcb522p+8], [-double.min_normal / 2, double.nan],
+            [double.max / 2, 0x1.33f424bcb522p+8], [-double.max / 2, double.nan],
+            [double.min_normal / 3, -0x1.3421390dcbe37p+8], [-double.min_normal / 3, double.nan],
+            [double.max / 3, 0x1.33c7106b9e609p+8], [-double.max / 3, double.nan],
+        ];
+        testLog10(vals);
+    }
+    alias F = floatTraits!real;
+    static if (F.realFormat == RealFormat.ieeeExtended || F.realFormat == RealFormat.ieeeQuadruple)
+    {{
+        real[2][16] vals = [
+            [real.nan, real.nan],[-real.nan, real.nan],
+            [real.infinity, real.infinity], [-real.infinity, real.nan],
+            [real.min_normal, -0x1.343793004f503232p+12L], [-real.min_normal, real.nan],
+            [real.max, 0x1.34413509f79fef32p+12L], [-real.max, real.nan],
+            [real.min_normal / 2, -0x1.343c6405237810b2p+12L], [-real.min_normal / 2, real.nan],
+            [real.max / 2, 0x1.343c6405237810b2p+12L], [-real.max / 2, real.nan],
+            [real.min_normal / 3, -0x1.343f354a34e427bp+12L], [-real.min_normal / 3, real.nan],
+            [real.max / 3, 0x1.343992c0120bf9b2p+12L], [-real.max / 3, real.nan],
+        ];
+        testLog10(vals);
+    }}
+}
+
 /**
  * Calculates the natural logarithm of 1 + x.
  *
@@ -3476,6 +3703,9 @@ real log1p(ulong x) @safe pure nothrow @nogc { return log1p(cast(real) x); }
 private T log1pImpl(T)(T x) @safe pure nothrow @nogc
 {
     import std.math.traits : isNaN, isInfinity, signbit;
+    import std.math.algebraic : poly;
+    import std.math.constants : SQRT1_2, SQRT2;
+    import std.math : floatTraits, RealFormat;
 
     // Special cases.
     if (isNaN(x) || x == 0.0)
@@ -3487,7 +3717,104 @@ private T log1pImpl(T)(T x) @safe pure nothrow @nogc
     if (x < -1.0)
         return T.nan;
 
-    return logImpl(x + 1.0);
+    alias F = floatTraits!T;
+    static if (F.realFormat == RealFormat.ieeeSingle ||
+               F.realFormat == RealFormat.ieeeDouble)
+    {
+        // When the input is within the range 1/sqrt(2) <= x+1 <= sqrt(2), compute
+        // log1p inline. Forwarding to log() would otherwise result in inaccuracies.
+        const T xp1 = x + 1.0;
+        if (xp1 >= SQRT1_2 && xp1 <= SQRT2)
+        {
+            alias coeffs = LogCoeffs!T;
+
+            T px = poly(x, coeffs.logp1P);
+            T qx = poly(x, coeffs.logp1Q);
+            const T xx = x * x;
+            qx = x + ((cast(T) -0.5) * xx + x * (xx * px / qx));
+            return qx;
+        }
+    }
+
+    return logImpl!(T, true)(x);
+}
+
+@safe @nogc nothrow unittest
+{
+    import std.math : floatTraits, RealFormat;
+    import std.meta : AliasSeq;
+
+    static void testLog1p(T)(T[2][] vals)
+    {
+        import std.math.operations : isClose;
+        import std.math.traits : isNaN;
+        foreach (ref pair; vals)
+        {
+            if (isNaN(pair[1]))
+                assert(isNaN(log1p(pair[0])));
+            else
+                assert(isClose(log1p(pair[0]), pair[1]));
+        }
+    }
+    static foreach (F; AliasSeq!(float, double, real))
+    {{
+        F[2][24] vals = [
+            [F(1), F(0x1.62e42fefa39ef358p-1)], [F(2), F(0x1.193ea7aad030a976p+0)],
+            [F(4), F(0x1.9c041f7ed8d336bp+0)], [F(8), F(0x1.193ea7aad030a976p+1)],
+            [F(16), F(0x1.6aa6bc1fa7f79cfp+1)], [F(32), F(0x1.bf8d8f4d5b8d1038p+1)],
+            [F(64), F(0x1.0b292939429755ap+2)], [F(128), F(0x1.37072a9b5b6cb31p+2)],
+            [F(256), F(0x1.63241004e9010ad8p+2)], [F(512), F(0x1.8f60adf041bde2a8p+2)],
+            [F(1024), F(0x1.bbad39ebe1cc08b6p+2)], [F(2048), F(0x1.e801c1698ba4395cp+2)],
+            [F(3), F(0x1.62e42fefa39ef358p+0)], [F(5), F(0x1.cab0bfa2a2002322p+0)],
+            [F(7), F(0x1.0a2b23f3bab73682p+1)], [F(15), F(0x1.62e42fefa39ef358p+1)],
+            [F(17), F(0x1.71f7b3a6b918664cp+1)], [F(31), F(0x1.bb9d3beb8c86b02ep+1)],
+            [F(33), F(0x1.c35fc81b90df59c6p+1)], [F(63), F(0x1.0a2b23f3bab73682p+2)],
+            [F(65), F(0x1.0c234da4a23a6686p+2)], [F(-0), F(-0x0p+0)], [F(0), F(0x0p+0)],
+            [F(10000), F(0x1.26bbed6fbd84182ep+3)],
+        ];
+        testLog1p(vals);
+    }}
+    {
+        float[2][16] vals = [
+            [float.nan, float.nan],[-float.nan, float.nan],
+            [float.infinity, float.infinity], [-float.infinity, float.nan],
+            [float.min_normal, 0x1p-126f], [-float.min_normal, -0x1p-126f],
+            [float.max, 0x1.62e43p+6f], [-float.max, float.nan],
+            [float.min_normal / 2, 0x0.8p-126f], [-float.min_normal / 2, -0x0.8p-126f],
+            [float.max / 2, 0x1.601e68p+6f], [-float.max / 2, float.nan],
+            [float.min_normal / 3, 0x0.555556p-126f], [-float.min_normal / 3, -0x0.555556p-126f],
+            [float.max / 3, 0x1.5e7f36p+6f], [-float.max / 3, float.nan],
+        ];
+        testLog1p(vals);
+    }
+    {
+        double[2][16] vals = [
+            [double.nan, double.nan],[-double.nan, double.nan],
+            [double.infinity, double.infinity], [-double.infinity, double.nan],
+            [double.min_normal, 0x1p-1022], [-double.min_normal, -0x1p-1022],
+            [double.max, 0x1.62e42fefa39efp+9], [-double.max, double.nan],
+            [double.min_normal / 2, 0x0.8p-1022], [-double.min_normal / 2, -0x0.8p-1022],
+            [double.max / 2, 0x1.628b76e3a7b61p+9], [-double.max / 2, double.nan],
+            [double.min_normal / 3, 0x0.5555555555555p-1022], [-double.min_normal / 3, -0x0.5555555555555p-1022],
+            [double.max / 3, 0x1.6257909bce36ep+9], [-double.max / 3, double.nan],
+        ];
+        testLog1p(vals);
+    }
+    alias F = floatTraits!real;
+    static if (F.realFormat == RealFormat.ieeeExtended || F.realFormat == RealFormat.ieeeQuadruple)
+    {{
+        real[2][16] vals = [
+            [real.nan, real.nan],[-real.nan, real.nan],
+            [real.infinity, real.infinity], [-real.infinity, real.nan],
+            [real.min_normal, 0x1p-16382L], [-real.min_normal, -0x1p-16382L],
+            [real.max, 0x1.62e42fefa39ef358p+13L], [-real.max, real.nan],
+            [real.min_normal / 2, 0x0.8p-16382L], [-real.min_normal / 2, -0x0.8p-16382L],
+            [real.max / 2, 0x1.62dea45ee3e064dcp+13L], [-real.max / 2, real.nan],
+            [real.min_normal / 3, 0x0.5555555555555556p-16382L], [-real.min_normal / 3, -0x0.5555555555555556p-16382L],
+            [real.max / 3, 0x1.62db65fa664871d2p+13L], [-real.max / 3, real.nan],
+        ];
+        testLog1p(vals);
+    }}
 }
 
 /***************************************
@@ -3635,6 +3962,84 @@ Ldone:
     return z;
 }
 
+@safe @nogc nothrow unittest
+{
+    import std.math : floatTraits, RealFormat;
+    import std.meta : AliasSeq;
+
+    static void testLog2(T)(T[2][] vals)
+    {
+        import std.math.operations : isClose;
+        import std.math.traits : isNaN;
+        foreach (ref pair; vals)
+        {
+            if (isNaN(pair[1]))
+                assert(isNaN(log2(pair[0])));
+            else
+                assert(isClose(log2(pair[0]), pair[1]));
+        }
+    }
+    static foreach (F; AliasSeq!(float, double, real))
+    {{
+        F[2][24] vals = [
+            [F(1), F(0x0p+0)], [F(2), F(0x1p+0)],
+            [F(4), F(0x1p+1)], [F(8), F(0x1.8p+1)],
+            [F(16), F(0x1p+2)], [F(32), F(0x1.4p+2)],
+            [F(64), F(0x1.8p+2)], [F(128), F(0x1.cp+2)],
+            [F(256), F(0x1p+3)], [F(512), F(0x1.2p+3)],
+            [F(1024), F(0x1.4p+3)], [F(2048), F(0x1.6p+3)],
+            [F(3), F(0x1.95c01a39fbd687ap+0)], [F(5), F(0x1.2934f0979a3715fcp+1)],
+            [F(7), F(0x1.675767f54042cd9ap+1)], [F(15), F(0x1.f414fdb4982259ccp+1)],
+            [F(17), F(0x1.0598fdbeb244c5ap+2)], [F(31), F(0x1.3d118d66c4d4e554p+2)],
+            [F(33), F(0x1.42d75a6eb1dfb0e6p+2)], [F(63), F(0x1.7e8bc1179e0caa9cp+2)],
+            [F(65), F(0x1.816e79685c2d2298p+2)], [F(-0), -F.infinity], [F(0), -F.infinity],
+            [F(10000), F(0x1.a934f0979a3715fcp+3)],
+        ];
+        testLog2(vals);
+    }}
+    {
+        float[2][16] vals = [
+            [float.nan, float.nan],[-float.nan, float.nan],
+            [float.infinity, float.infinity], [-float.infinity, float.nan],
+            [float.min_normal, -0x1.f8p+6f], [-float.min_normal, float.nan],
+            [float.max, 0x1p+7f], [-float.max, float.nan],
+            [float.min_normal / 2, -0x1.fcp+6f], [-float.min_normal / 2, float.nan],
+            [float.max / 2, 0x1.fcp+6f], [-float.max / 2, float.nan],
+            [float.min_normal / 3, -0x1.fe57p+6f], [-float.min_normal / 3, float.nan],
+            [float.max / 3, 0x1.f9a9p+6f], [-float.max / 3, float.nan],
+        ];
+        testLog2(vals);
+    }
+    {
+        double[2][16] vals = [
+            [double.nan, double.nan],[-double.nan, double.nan],
+            [double.infinity, double.infinity], [-double.infinity, double.nan],
+            [double.min_normal, -0x1.ffp+9], [-double.min_normal, double.nan],
+            [double.max, 0x1p+10], [-double.max, double.nan],
+            [double.min_normal / 2, -0x1.ff8p+9], [-double.min_normal / 2, double.nan],
+            [double.max / 2, 0x1.ff8p+9], [-double.max / 2, double.nan],
+            [double.min_normal / 3, -0x1.ffcae00d1cfdfp+9], [-double.min_normal / 3, double.nan],
+            [double.max / 3, 0x1.ff351ff2e3021p+9], [-double.max / 3, double.nan],
+        ];
+        testLog2(vals);
+    }
+    alias F = floatTraits!real;
+    static if (F.realFormat == RealFormat.ieeeExtended || F.realFormat == RealFormat.ieeeQuadruple)
+    {{
+        real[2][16] vals = [
+            [real.nan, real.nan],[-real.nan, real.nan],
+            [real.infinity, real.infinity], [-real.infinity, real.nan],
+            [real.min_normal, -0x1.fffp+13L], [-real.min_normal, real.nan],
+            [real.max, 0x1p+14L], [-real.max, real.nan],
+            [real.min_normal / 2, -0x1.fff8p+13L], [-real.min_normal / 2, real.nan],
+            [real.max / 2, 0x1.fff8p+13L], [-real.max / 2, real.nan],
+            [real.min_normal / 3, -0x1.fffcae00d1cfdeb4p+13L], [-real.min_normal / 3, real.nan],
+            [real.max / 3, 0x1.fff351ff2e30214cp+13L], [-real.max / 3, real.nan],
+        ];
+        testLog2(vals);
+    }}
+}
+
 /*****************************************
  * Extracts the exponent of x as a signed integral value.
  *
@@ -3754,6 +4159,84 @@ private T logbImpl(T)(T x) @trusted pure nothrow @nogc
     return ilogb(x);
 }
 
+@safe @nogc nothrow unittest
+{
+    import std.math : floatTraits, RealFormat;
+    import std.meta : AliasSeq;
+
+    static void testLogb(T)(T[2][] vals)
+    {
+        import std.math.operations : isClose;
+        import std.math.traits : isNaN;
+        foreach (ref pair; vals)
+        {
+            if (isNaN(pair[1]))
+                assert(isNaN(logb(pair[0])));
+            else
+                assert(isClose(logb(pair[0]), pair[1]));
+        }
+    }
+    static foreach (F; AliasSeq!(float, double, real))
+    {{
+        F[2][24] vals = [
+            [F(1), F(0x0p+0)], [F(2), F(0x1p+0)],
+            [F(4), F(0x1p+1)], [F(8), F(0x1.8p+1)],
+            [F(16), F(0x1p+2)], [F(32), F(0x1.4p+2)],
+            [F(64), F(0x1.8p+2)], [F(128), F(0x1.cp+2)],
+            [F(256), F(0x1p+3)], [F(512), F(0x1.2p+3)],
+            [F(1024), F(0x1.4p+3)], [F(2048), F(0x1.6p+3)],
+            [F(3), F(0x1p+0)], [F(5), F(0x1p+1)],
+            [F(7), F(0x1p+1)], [F(15), F(0x1.8p+1)],
+            [F(17), F(0x1p+2)], [F(31), F(0x1p+2)],
+            [F(33), F(0x1.4p+2)], [F(63), F(0x1.4p+2)],
+            [F(65), F(0x1.8p+2)], [F(-0), -F.infinity], [F(0), -F.infinity],
+            [F(10000), F(0x1.ap+3)],
+        ];
+        testLogb(vals);
+    }}
+    {
+        float[2][16] vals = [
+            [float.nan, float.nan],[-float.nan, float.nan],
+            [float.infinity, float.infinity], [-float.infinity, float.infinity],
+            [float.min_normal, -0x1.f8p+6f], [-float.min_normal, -0x1.f8p+6f],
+            [float.max, 0x1.fcp+6f], [-float.max, 0x1.fcp+6f],
+            [float.min_normal / 2, -0x1.fcp+6f], [-float.min_normal / 2, -0x1.fcp+6f],
+            [float.max / 2, 0x1.f8p+6f], [-float.max / 2, 0x1.f8p+6f],
+            [float.min_normal / 3, -0x1p+7f], [-float.min_normal / 3, -0x1p+7f],
+            [float.max / 3, 0x1.f8p+6f], [-float.max / 3, 0x1.f8p+6f],
+        ];
+        testLogb(vals);
+    }
+    {
+        double[2][16] vals = [
+            [double.nan, double.nan],[-double.nan, double.nan],
+            [double.infinity, double.infinity], [-double.infinity, double.infinity],
+            [double.min_normal, -0x1.ffp+9], [-double.min_normal, -0x1.ffp+9],
+            [double.max, 0x1.ff8p+9], [-double.max, 0x1.ff8p+9],
+            [double.min_normal / 2, -0x1.ff8p+9], [-double.min_normal / 2, -0x1.ff8p+9],
+            [double.max / 2, 0x1.ffp+9], [-double.max / 2, 0x1.ffp+9],
+            [double.min_normal / 3, -0x1p+10], [-double.min_normal / 3, -0x1p+10],
+            [double.max / 3, 0x1.ffp+9], [-double.max / 3, 0x1.ffp+9],
+        ];
+        testLogb(vals);
+    }
+    alias F = floatTraits!real;
+    static if (F.realFormat == RealFormat.ieeeExtended || F.realFormat == RealFormat.ieeeQuadruple)
+    {{
+        real[2][16] vals = [
+            [real.nan, real.nan],[-real.nan, real.nan],
+            [real.infinity, real.infinity], [-real.infinity, real.infinity],
+            [real.min_normal, -0x1.fffp+13L], [-real.min_normal, -0x1.fffp+13L],
+            [real.max, 0x1.fff8p+13L], [-real.max, 0x1.fff8p+13L],
+            [real.min_normal / 2, -0x1.fff8p+13L], [-real.min_normal / 2, -0x1.fff8p+13L],
+            [real.max / 2, 0x1.fffp+13L], [-real.max / 2, 0x1.fffp+13L],
+            [real.min_normal / 3, -0x1p+14L], [-real.min_normal / 3, -0x1p+14L],
+            [real.max / 3, 0x1.fffp+13L], [-real.max / 3, 0x1.fffp+13L],
+        ];
+        testLogb(vals);
+    }}
+}
+
 /*************************************
  * Efficiently calculates x * 2$(SUPERSCRIPT n).
  *
index 8745bbd7a0772f17c2be9b0274300e6f95f67a1a..42a34b9bd559791c87f05d30f7eaa48128368953 100644 (file)
@@ -2171,7 +2171,7 @@ private mixin template Protocol()
       *
       * Example:
       * ----
-      * import std.net.curl, std.stdio;
+      * import std.net.curl, std.stdio, std.conv;
       * auto client = HTTP("dlang.org");
       * client.onReceive = (ubyte[] data)
       * {
@@ -2817,7 +2817,7 @@ struct HTTP
          *
          * Example:
          * ----
-         * import std.net.curl, std.stdio;
+         * import std.net.curl, std.stdio, std.conv;
          * auto client = HTTP("dlang.org");
          * client.onReceive = (ubyte[] data)
          * {
@@ -3054,7 +3054,7 @@ struct HTTP
       *
       * Example:
       * ----
-      * import std.net.curl, std.stdio;
+      * import std.net.curl, std.stdio, std.conv;
       * auto http = HTTP("http://www.mydomain.com");
       * http.onReceive = (ubyte[] data) { writeln(to!(const(char)[])(data)); return data.length; };
       * http.postData = [1,2,3,4,5];
@@ -3073,7 +3073,7 @@ struct HTTP
       *
       * Example:
       * ----
-      * import std.net.curl, std.stdio;
+      * import std.net.curl, std.stdio, std.conv;
       * auto http = HTTP("http://www.mydomain.com");
       * http.onReceive = (ubyte[] data) { writeln(to!(const(char)[])(data)); return data.length; };
       * http.postData = "The quick....";
@@ -3145,7 +3145,7 @@ struct HTTP
       *
       * Example:
       * ----
-      * import std.net.curl, std.stdio;
+      * import std.net.curl, std.stdio, std.conv;
       * auto http = HTTP("dlang.org");
       * http.onReceive = (ubyte[] data) { writeln(to!(const(char)[])(data)); return data.length; };
       * http.onReceiveHeader = (in char[] key, in char[] value) { writeln(key, " = ", value); };
@@ -4551,7 +4551,7 @@ struct Curl
       *
       * Example:
       * ----
-      * import std.net.curl, std.stdio;
+      * import std.net.curl, std.stdio, std.conv;
       * Curl curl;
       * curl.initialize();
       * curl.set(CurlOption.url, "http://dlang.org");
index 3eaa2835249f38b8a4195807f8487d5db8dda82c..494910f35350927a561c98c78f6b19fe20a579a9 100644 (file)
@@ -2505,7 +2505,7 @@ version (Windows)
     import std.exception : collectException;
     import std.typecons : tuple;
 
-    TestScript prog = ":Loop\ngoto Loop;";
+    TestScript prog = ":Loop\r\n" ~ "goto Loop";
     auto pid = spawnProcess(prog.path);
 
     // Doesn't block longer than one second
@@ -3658,7 +3658,7 @@ string escapeShellCommand(scope const(char[])[] args...) @safe pure
         {
             args    : ["foo bar", "hello"],
             windows : `"foo bar" hello`,
-            posix   : `'foo bar' 'hello'`
+            posix   : `'foo bar' hello`
         },
         {
             args    : ["foo bar", "hello world"],
@@ -3668,20 +3668,34 @@ string escapeShellCommand(scope const(char[])[] args...) @safe pure
         {
             args    : ["foo bar", "hello", "world"],
             windows : `"foo bar" hello world`,
-            posix   : `'foo bar' 'hello' 'world'`
+            posix   : `'foo bar' hello world`
         },
         {
             args    : ["foo bar", `'"^\`],
             windows : `"foo bar" ^"'\^"^^\\^"`,
             posix   : `'foo bar' ''\''"^\'`
         },
+        {
+            args    : ["foo bar", ""],
+            windows : `"foo bar" ^"^"`,
+            posix   : `'foo bar' ''`
+        },
+        {
+            args    : ["foo bar", "2"],
+            windows : `"foo bar" ^"2^"`,
+            posix   : `'foo bar' '2'`
+        },
     ];
 
     foreach (test; tests)
+    {
+        auto actual = escapeShellCommand(test.args);
         version (Windows)
-            assert(escapeShellCommand(test.args) == test.windows);
+            string expected = test.windows;
         else
-            assert(escapeShellCommand(test.args) == test.posix  );
+            string expected = test.posix;
+        assert(actual == expected, "\nExpected: " ~ expected ~ "\nGot: " ~ actual);
+    }
 }
 
 private string escapeShellCommandString(return scope string command) @safe pure
@@ -3922,6 +3936,37 @@ private char[] escapePosixArgumentImpl(alias allocator)(scope const(char)[] arg)
     @safe nothrow
 if (is(typeof(allocator(size_t.init)[0] = char.init)))
 {
+    bool needQuoting = {
+        import std.ascii : isAlphaNum, isDigit;
+        import std.algorithm.comparison : among;
+
+        // Empty arguments need to be specified as ''
+        if (arg.length == 0)
+            return true;
+        // Arguments ending with digits need to be escaped,
+        // to disambiguate with 1>file redirection syntax
+        if (isDigit(arg[$-1]))
+            return true;
+
+        // Obtained using:
+        // for n in $(seq 1 255) ; do
+        //     c=$(printf \\$(printf "%o" $n))
+        //     q=$(/bin/printf '%q' "$c")
+        //     if [[ "$q" == "$c" ]] ; then printf "%s, " "'$c'" ; fi
+        // done
+        // printf '\n'
+        foreach (char c; arg)
+            if (!isAlphaNum(c) && !c.among('%', '+', ',', '-', '.', '/', ':', '@', ']', '_'))
+                return true;
+        return false;
+    }();
+    if (!needQuoting)
+    {
+        auto buf = allocator(arg.length);
+        buf[] = arg;
+        return buf;
+    }
+
     // '\'' means: close quoted part of argument, append an escaped
     // single quote, and reopen quotes
 
@@ -3995,6 +4040,11 @@ version (unittest_burnin)
     // Then, test this module with:
     // rdmd --main -unittest -version=unittest_burnin process.d
 
+    import std.file : readText, remove;
+    import std.format : format;
+    import std.path : absolutePath;
+    import std.random : uniform;
+
     auto helper = absolutePath("std_process_unittest_helper");
     assert(executeShell(helper ~ " hello").output.split("\0")[1..$] == ["hello"], "Helper malfunction");
 
index cdab401a1f28447fe8a4fc840802373f44e66412..748fde38ed3b21657e4c83ea2e26ea7e7f71b23e 100644 (file)
@@ -171,9 +171,9 @@ Returns:
  */
 enum bool isInputRange(R) =
     is(typeof(R.init) == R)
-    && is(ReturnType!((R r) => r.empty) == bool)
+    && is(typeof((R r) { return r.empty; } (R.init)) == bool)
     && (is(typeof((return ref R r) => r.front)) || is(typeof(ref (return ref R r) => r.front)))
-    && !is(ReturnType!((R r) => r.front) == void)
+    && !is(typeof((R r) { return r.front; } (R.init)) == void)
     && is(typeof((R r) => r.popFront));
 
 ///
@@ -998,7 +998,7 @@ See_Also:
     The header of $(MREF std,range) for tutorials on ranges.
  */
 enum bool isForwardRange(R) = isInputRange!R
-    && is(ReturnType!((R r) => r.save) == R);
+    && is(typeof((R r) { return r.save; } (R.init)) == R);
 
 ///
 @safe unittest
@@ -1041,7 +1041,7 @@ See_Also:
  */
 enum bool isBidirectionalRange(R) = isForwardRange!R
     && is(typeof((R r) => r.popBack))
-    && is(ReturnType!((R r) => r.back) == ElementType!R);
+    && is(typeof((R r) { return r.back; } (R.init)) == ElementType!R);
 
 ///
 @safe unittest
@@ -1674,8 +1674,8 @@ The following expression must be true for `hasSlicing` to be `true`:
 
 ----
     isForwardRange!R
-    && !isNarrowString!R
-    && is(ReturnType!((R r) => r[1 .. 1].length) == size_t)
+    && !(isAutodecodableString!R && !isAggregateType!R)
+    && is(typeof((R r) { return r[1 .. 1].length; } (R.init)) == size_t)
     && (is(typeof(lvalueOf!R[1 .. 1]) == R) || isInfinite!R)
     && (!is(typeof(lvalueOf!R[0 .. $])) || is(typeof(lvalueOf!R[0 .. $]) == R))
     && (!is(typeof(lvalueOf!R[0 .. $])) || isInfinite!R
@@ -1688,7 +1688,7 @@ The following expression must be true for `hasSlicing` to be `true`:
  */
 enum bool hasSlicing(R) = isForwardRange!R
     && !(isAutodecodableString!R && !isAggregateType!R)
-    && is(ReturnType!((R r) => r[1 .. 1].length) == size_t)
+    && is(typeof((R r) { return r[1 .. 1].length; } (R.init)) == size_t)
     && (is(typeof(lvalueOf!R[1 .. 1]) == R) || isInfinite!R)
     && (!is(typeof(lvalueOf!R[0 .. $])) || is(typeof(lvalueOf!R[0 .. $]) == R))
     && (!is(typeof(lvalueOf!R[0 .. $])) || isInfinite!R
index 448bb99a9a132fd2a7c37cae59abec446b316a40..ab2b297fb884d8088f00eb8c425d057d8ddf7aba 100644 (file)
@@ -1010,12 +1010,14 @@ if (isForwardRange!R && is(ElementType!R : dchar))
     //
     @trusted void error(string msg)
     {
-        import std.array : appender;
-        import std.format.write : formattedWrite;
-        auto app = appender!string();
-        formattedWrite(app, "%s\nPattern with error: `%s` <--HERE-- `%s`",
-                       msg, origin[0..$-pat.length], pat);
-        throw new RegexException(app.data);
+        import std.conv : text;
+        string app = msg;
+        app ~= "\nPattern with error: `";
+        app ~= origin[0..$-pat.length].text;
+        app ~= "` <--HERE-- `";
+        app ~= pat.text;
+        app ~= "`";
+        throw new RegexException(app);
     }
 
     alias Char = BasicElementOf!R;
index 593052e5a822f6501361db9617a28020bc40a862..3359c8ebf6217867b4e137b06099ae67f5e2d52f 100644 (file)
@@ -802,10 +802,14 @@ class InternetHost
     {
         string getHostNameFromInt = ih.name.dup;
 
-        assert(ih.getHostByAddr(ia.toAddrString()));
-        string getHostNameFromStr = ih.name.dup;
+        // This randomly fails in the compiler test suite
+        //assert(ih.getHostByAddr(ia.toAddrString()));
 
-        assert(getHostNameFromInt == getHostNameFromStr);
+        if (ih.getHostByAddr(ia.toAddrString()))
+        {
+            string getHostNameFromStr = ih.name.dup;
+            assert(getHostNameFromInt == getHostNameFromStr);
+        }
     }
 }
 
index 802aa128c6e47b2ca407d54f117e3a3649a2f5c9..92e4906b4f4a44a2b44e96bb05e46b5699c29276 100644 (file)
@@ -1374,8 +1374,9 @@ Throws: `Exception` if the file is not opened.
     }
 
 /**
-Calls $(HTTP cplusplus.com/reference/clibrary/cstdio/ftell.html, ftell) for the
-managed file handle.
+Calls $(HTTP cplusplus.com/reference/cstdio/ftell.html, ftell)
+for the managed file handle, which returns the current value of
+the position indicator of the file handle.
 
 Throws: `Exception` if the file is not opened.
         `ErrnoException` if the call to `ftell` fails.
index e5f305bf83c7d0eefe4a9a200bd597499f34892c..bbbca69b22bc618b1644b88db9018df29dc6f8a5 100644 (file)
@@ -10,6 +10,7 @@
  * $(TR $(TH Category) $(TH Templates))
  * $(TR $(TD Symbol Name traits) $(TD
  *           $(LREF fullyQualifiedName)
+ *           $(LREF mangledName)
  *           $(LREF moduleName)
  *           $(LREF packageName)
  * ))
@@ -67,9 +68,7 @@
  *           $(LREF isCovariantWith)
  *           $(LREF isImplicitlyConvertible)
  * ))
- * $(TR $(TD SomethingTypeOf) $(TD
- *           $(LREF rvalueOf)
- *           $(LREF lvalueOf)
+ * $(TR $(TD Type Constructors) $(TD
  *           $(LREF InoutOf)
  *           $(LREF ConstOf)
  *           $(LREF SharedOf)
  *           $(LREF Promoted)
  * ))
  * $(TR $(TD Misc) $(TD
- *           $(LREF mangledName)
+ *           $(LREF lvalueOf)
+ *           $(LREF rvalueOf)
  *           $(LREF Select)
  *           $(LREF select)
  * ))
@@ -889,7 +889,7 @@ private template fqnType(T,
             );
         }
     }
-    else static if (is(T : U*, U))
+    else static if (is(T == U*, U))
     {
         enum fqnType = chain!(
             fqnType!(U, qualifiers) ~ "*"
@@ -986,6 +986,10 @@ private template fqnType(T,
  * or a class with an `opCall`. Please note that $(D_KEYWORD ref)
  * is not part of a type, but the attribute of the function
  * (see template $(LREF functionAttributes)).
+ *
+ * $(NOTE To reduce template instantiations, consider instead using
+ * $(D typeof(() { return func(args); } ())) if the argument types are known or
+ * $(D static if (is(typeof(func) Ret == return))) if only that basic test is needed.)
  */
 template ReturnType(alias func)
 if (isCallable!func)
@@ -2302,7 +2306,7 @@ if (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]);
@@ -3925,7 +3929,7 @@ template hasStaticMember(T, string member)
 {
     static if (__traits(hasMember, T, member))
     {
-        static if (is(T : V*, V))
+        static if (is(T == V*, V))
             alias U = V;
         else
             alias U = T;
@@ -4529,7 +4533,7 @@ if (is(C == class) || is(C == interface))
             static if (__traits(hasMember, Node, name) && __traits(compiles, __traits(getMember, Node, name)))
             {
                 // Get all overloads in sight (not hidden).
-                alias inSight = __traits(getVirtualFunctions, Node, name);
+                alias inSight = __traits(getVirtualMethods, Node, name);
 
                 // And collect all overloads in ancestor classes to reveal hidden
                 // methods.  The result may contain duplicates.
@@ -5297,7 +5301,8 @@ enum isLvalueAssignable(Lhs, Rhs = Lhs) = __traits(compiles, { lvalueOf!Lhs = lv
     static assert(!isAssignable!S5);
 
     // `-preview=in` is enabled
-    static if (!is(typeof(mixin(q{(in ref int a) => a}))))
+    alias DScannerBug895 = int[256];
+    static if (((in DScannerBug895 a) { return __traits(isRef, a); })(DScannerBug895.init))
     {
         struct S6 { void opAssign(in S5); }
 
@@ -6066,7 +6071,7 @@ template StringTypeOf(T)
                 static assert(is(Q!T[] == StringTypeOf!( SubTypeOf!(Q!T[]) )));
 
                 alias Str = Q!T[];
-                class C(S) { S val;  alias val this; }
+                struct C(S) { S val;  alias val this; }
                 static assert(is(StringTypeOf!(C!Str) == Str));
             }}
         }
@@ -7481,24 +7486,10 @@ Params:
 Returns:
     A `bool`
  */
-template isSomeFunction(alias T)
-{
-    static if (is(typeof(& T) U : U*) && is(U == function) || is(typeof(& T) U == delegate))
-    {
-        // T is a (nested) function symbol.
-        enum bool isSomeFunction = true;
-    }
-    else static if (is(T W) || is(typeof(T) W))
-    {
-        // T is an expression or a type.  Take the type of it and examine.
-        static if (is(W F : F*) && is(F == function))
-            enum bool isSomeFunction = true; // function pointer
-        else
-            enum bool isSomeFunction = is(W == function) || is(W == delegate);
-    }
-    else
-        enum bool isSomeFunction = false;
-}
+enum bool isSomeFunction(alias T) =
+    is(T == return) ||
+    is(typeof(T) == return) ||
+    is(typeof(&T) == return); // @property
 
 ///
 @safe unittest
@@ -7513,17 +7504,16 @@ template isSomeFunction(alias T)
     auto c = new C;
     auto fp = &func;
     auto dg = &c.method;
-    real val;
 
     static assert( isSomeFunction!func);
     static assert( isSomeFunction!prop);
     static assert( isSomeFunction!(C.method));
     static assert( isSomeFunction!(C.prop));
     static assert( isSomeFunction!(c.prop));
-    static assert( isSomeFunction!(c.prop));
     static assert( isSomeFunction!fp);
     static assert( isSomeFunction!dg);
 
+    real val;
     static assert(!isSomeFunction!int);
     static assert(!isSomeFunction!val);
 }
@@ -7969,7 +7959,7 @@ has both opApply and a range interface.
 */
 template ForeachType(T)
 {
-    alias ForeachType = ReturnType!(typeof(
+    alias ForeachType = typeof(
     (inout int x = 0)
     {
         foreach (elem; T.init)
@@ -7977,7 +7967,7 @@ template ForeachType(T)
             return elem;
         }
         assert(0);
-    }));
+    }());
 }
 
 ///
index 25cf9e0084134f9824393067cd0bffbd5b588ec9..bde8439a5fca872bafc31dc0cc0efb456588c912 100644 (file)
@@ -3159,12 +3159,6 @@ struct Nullable(T)
         return this;
     }
 
-    /// ditto
-    inout(typeof(this)) opIndex() inout
-    {
-        return this;
-    }
-
     /// ditto
     inout(typeof(this)) opIndex(size_t[2] dim) inout
     in (dim[0] <= length && dim[1] <= length && dim[1] >= dim[0])
@@ -3192,6 +3186,74 @@ struct Nullable(T)
     {
         return get();
     }
+
+    /**
+     * Converts `Nullable` to a range. Works even when the contained type is `immutable`.
+     */
+    auto opSlice(this This)()
+    {
+        static struct NullableRange
+        {
+            private This value;
+
+            // starts out true if value is null
+            private bool empty_;
+
+            @property bool empty() const @safe pure nothrow
+            {
+                return empty_;
+            }
+
+            void popFront() @safe pure nothrow
+            {
+                empty_ = true;
+            }
+
+            alias popBack = popFront;
+
+            @property ref inout(typeof(value.get())) front() inout @safe pure nothrow
+            {
+                return value.get();
+            }
+
+            alias back = front;
+
+            @property inout(typeof(this)) save() inout
+            {
+                return this;
+            }
+
+            size_t[2] opSlice(size_t dim : 0)(size_t from, size_t to) const
+            {
+                return [from, to];
+            }
+
+            @property size_t length() const @safe pure nothrow
+            {
+                return !empty;
+            }
+
+            alias opDollar(size_t dim : 0) = length;
+
+            ref inout(typeof(value.get())) opIndex(size_t index) inout @safe pure nothrow
+            in (index < length)
+            {
+                return value.get();
+            }
+
+            inout(typeof(this)) opIndex(size_t[2] dim) inout
+            in (dim[0] <= length && dim[1] <= length && dim[1] >= dim[0])
+            {
+                return (dim[0] == 0 && dim[1] == 1) ? this : this.init;
+            }
+
+            auto opIndex() inout
+            {
+                return this;
+            }
+        }
+        return NullableRange(this, isNull);
+    }
 }
 
 /// ditto
@@ -3774,6 +3836,34 @@ auto nullable(T)(T t)
     assert(hasLvalueElements!(Nullable!int));
 }
 
+// https://issues.dlang.org/show_bug.cgi?id=23640
+@safe pure nothrow unittest
+{
+    import std.algorithm.comparison : equal;
+    import std.range : only;
+    import std.range.primitives : hasLength, hasSlicing,
+        isRandomAccessRange;
+    static immutable struct S { int[] array; }
+    auto value = S([42]);
+    alias ImmutableNullable = immutable Nullable!S;
+    auto a = ImmutableNullable(value)[];
+    alias Range = typeof(a);
+    assert(isRandomAccessRange!Range);
+    assert(hasLength!Range);
+    assert(hasSlicing!Range);
+    assert(!a.empty);
+    assert(a.front == value);
+    assert(a.back == value);
+    assert(a[0] == value);
+    assert(a.equal(only(value)));
+    assert(a[0 .. $].equal(only(value)));
+    Range b = a.save();
+    assert(!b.empty);
+    b.popFront();
+    assert(!a.empty);
+    assert(b.empty);
+}
+
 /**
 Just like `Nullable!T`, except that the null state is defined as a
 particular value. For example, $(D Nullable!(uint, uint.max)) is an
index 5c0659ec7c63ffcdbed107b11320c08abfb5ccdb..e2a0de7353557419750e0930a906decc9b286933 100644 (file)
@@ -712,6 +712,8 @@ import std.traits : isConvertibleToString, isIntegral, isSomeChar,
     isSomeString, Unqual, isDynamicArray;
 // debug = std_uni;
 
+import std.internal.unicode_tables; // generated file
+
 debug(std_uni) import std.stdio; // writefln, writeln
 
 private:
@@ -6962,23 +6964,192 @@ private:
 
 enum EMPTY_CASE_TRIE = ushort.max;// from what gen_uni uses internally
 
-// control - '\r'
-enum controlSwitch = `
-    case '\u0000':..case '\u0008':case '\u000E':..case '\u001F':case '\u007F':..
-    case '\u0084':case '\u0086':..case '\u009F': case '\u0009':..case '\u000C': case '\u0085':
-`;
 // TODO: redo the most of hangul stuff algorithmically in case of Graphemes too
-// kill unrolled switches
+// Use combined trie instead of checking for '\r' | '\n' | ccTrie,
+//   or extend | '\u200D' separately
 
 private static bool isRegionalIndicator(dchar ch) @safe pure @nogc nothrow
 {
     return ch >= '\U0001F1E6' && ch <= '\U0001F1FF';
 }
 
+// Our grapheme decoder is a state machine, this is list of all possible
+// states before each code point.
+private enum GraphemeState
+{
+    Start,
+    CR,
+    RI,
+    L,
+    V,
+    LVT,
+    Emoji,
+    EmojiZWJ,
+    Prepend,
+    End
+}
+
+// Message values whether end of grapheme is reached
+private enum TransformRes
+{
+    // No, unless the source range ends here
+    // (GB2 - break at end of text, unless text is empty)
+    goOn,
+    redo, // Run last character again with new state
+    retInclude, // Yes, after the just iterated character
+    retExclude // Yes, before the just iterated character
+}
+
+// The logic of the grapheme decoding is all here
+// GB# means Grapheme Breaking rule number # - see Unicode standard annex #29
+// Note, getting GB1 (break at start of text, unless text is empty) right
+// relies on the user starting grapheme walking from beginning of the text, and
+// not attempting to walk an empty text.
+private enum TransformRes
+    function(ref GraphemeState, dchar) @safe pure nothrow @nogc [] graphemeTransforms =
+[
+    GraphemeState.Start: (ref state, ch)
+    {
+        // GB4. Break after controls.
+        if (graphemeControlTrie[ch] || ch == '\n')
+            return TransformRes.retInclude;
+
+        with (GraphemeState) state =
+            ch == '\r' ? CR :
+            isRegionalIndicator(ch) ? RI :
+            isHangL(ch) ? L :
+            hangLV[ch] || isHangV(ch) ? V :
+            hangLVT[ch] || isHangT(ch) ? LVT :
+            prependTrie[ch] ? Prepend :
+            xpictoTrie[ch] ? Emoji :
+            End;
+
+        // No matter what we encountered, we always include the
+        // first code point in the grapheme.
+        return TransformRes.goOn;
+    },
+
+    // GB3, GB4. Do not break between a CR and LF.
+    // Otherwise, break after controls.
+    GraphemeState.CR: (ref state, ch) => ch == '\n' ?
+        TransformRes.retInclude :
+        TransformRes.retExclude,
+
+    // GB12 - GB13. Do not break within emoji flag sequences.
+    // That is, do not break between regional indicator (RI) symbols if
+    // there is an odd number of RI characters before the break point.
+    // This state applies if one and only one RI code point has been
+    // encountered.
+    GraphemeState.RI: (ref state, ch)
+    {
+        state = GraphemeState.End;
+
+        return isRegionalIndicator(ch) ?
+            TransformRes.goOn :
+            TransformRes.redo;
+    },
+
+    // GB6. Do not break Hangul syllable sequences.
+    GraphemeState.L: (ref state, ch)
+    {
+        if (isHangL(ch))
+            return TransformRes.goOn;
+        else if (isHangV(ch) || hangLV[ch])
+        {
+            state = GraphemeState.V;
+            return TransformRes.goOn;
+        }
+        else if (hangLVT[ch])
+        {
+            state = GraphemeState.LVT;
+            return TransformRes.goOn;
+        }
+
+        state = GraphemeState.End;
+        return TransformRes.redo;
+    },
+
+    // GB7. Do not break Hangul syllable sequences.
+    GraphemeState.V: (ref state, ch)
+    {
+        if (isHangV(ch))
+            return TransformRes.goOn;
+        else if (isHangT(ch))
+        {
+            state = GraphemeState.LVT;
+            return TransformRes.goOn;
+        }
+
+        state = GraphemeState.End;
+        return TransformRes.redo;
+    },
+
+    // GB8. Do not break Hangul syllable sequences.
+    GraphemeState.LVT: (ref state, ch)
+    {
+        if (isHangT(ch))
+            return TransformRes.goOn;
+
+        state = GraphemeState.End;
+        return TransformRes.redo;
+    },
+
+    // GB11. Do not break within emoji modifier sequences or emoji
+    // zwj sequences. This state applies when the last code point was
+    // NOT a ZWJ.
+    GraphemeState.Emoji: (ref state, ch)
+    {
+        if (graphemeExtendTrie[ch])
+            return TransformRes.goOn;
+
+        static assert(!graphemeExtendTrie['\u200D']);
+
+        if (ch == '\u200D')
+        {
+            state = GraphemeState.EmojiZWJ;
+            return TransformRes.goOn;
+        }
+
+        state = GraphemeState.End;
+        // There might still be spacing marks are
+        // at the end, which are not allowed in
+        // middle of emoji sequences
+        return TransformRes.redo;
+    },
+
+    // GB11. Do not break within emoji modifier sequences or emoji
+    // zwj sequences. This state applies when the last code point was
+    // a ZWJ.
+    GraphemeState.EmojiZWJ: (ref state, ch)
+    {
+        state = GraphemeState.Emoji;
+        if (xpictoTrie[ch])
+            return TransformRes.goOn;
+        return TransformRes.redo;
+    },
+
+    // GB9b. Do not break after Prepend characters.
+    GraphemeState.Prepend: (ref state, ch)
+    {
+        // GB5. Break before controls.
+        if (graphemeControlTrie[ch] || ch == '\r' || ch == '\n')
+            return TransformRes.retExclude;
+
+        state = GraphemeState.Start;
+        return TransformRes.redo;
+    },
+
+    // GB9, GB9a. Do not break before extending characters, ZWJ
+    // or SpacingMarks.
+    // GB999. Otherwise, break everywhere.
+    GraphemeState.End: (ref state, ch)
+        => !graphemeExtendTrie[ch] && !spacingMarkTrie[ch] && ch != '\u200D' ?
+            TransformRes.retExclude :
+            TransformRes.goOn
+];
+
 template genericDecodeGrapheme(bool getValue)
 {
-    alias graphemeExtend = graphemeExtendTrie;
-    alias spacingMark = mcTrie;
     static if (getValue)
         alias Value = Grapheme;
     else
@@ -6986,115 +7157,44 @@ template genericDecodeGrapheme(bool getValue)
 
     Value genericDecodeGrapheme(Input)(ref Input range)
     {
-        import std.internal.unicode_tables : isHangL, isHangT, isHangV; // generated file
-        enum GraphemeState {
-            Start,
-            CR,
-            RI,
-            L,
-            V,
-            LVT
-        }
         static if (getValue)
             Grapheme grapheme;
         auto state = GraphemeState.Start;
-        enum eat = q{
-            static if (getValue)
-                grapheme ~= ch;
-            range.popFront();
-        };
-
         dchar ch;
+
         assert(!range.empty, "Attempting to decode grapheme from an empty " ~ Input.stringof);
+    outer:
         while (!range.empty)
         {
             ch = range.front;
-            final switch (state) with(GraphemeState)
+
+        rerun:
+            final switch (graphemeTransforms[state](state, ch))
+                with(TransformRes)
             {
-            case Start:
-                mixin(eat);
-                if (ch == '\r')
-                    state = CR;
-                else if (isRegionalIndicator(ch))
-                    state = RI;
-                else if (isHangL(ch))
-                    state = L;
-                else if (hangLV[ch] || isHangV(ch))
-                    state = V;
-                else if (hangLVT[ch])
-                    state = LVT;
-                else if (isHangT(ch))
-                    state = LVT;
-                else
-                {
-                    switch (ch)
-                    {
-                    mixin(controlSwitch);
-                        goto L_End;
-                    default:
-                        goto L_End_Extend;
-                    }
-                }
-            break;
-            case CR:
-                if (ch == '\n')
-                    mixin(eat);
-                goto L_End_Extend;
-            case RI:
-                if (isRegionalIndicator(ch))
-                    mixin(eat);
-                goto L_End_Extend;
-            case L:
-                if (isHangL(ch))
-                    mixin(eat);
-                else if (isHangV(ch) || hangLV[ch])
-                {
-                    state = V;
-                    mixin(eat);
-                }
-                else if (hangLVT[ch])
-                {
-                    state = LVT;
-                    mixin(eat);
-                }
-                else
-                    goto L_End_Extend;
-            break;
-            case V:
-                if (isHangV(ch))
-                    mixin(eat);
-                else if (isHangT(ch))
-                {
-                    state = LVT;
-                    mixin(eat);
-                }
-                else
-                    goto L_End_Extend;
-            break;
-            case LVT:
-                if (isHangT(ch))
-                {
-                    mixin(eat);
-                }
-                else
-                    goto L_End_Extend;
-            break;
+            case goOn:
+                static if (getValue)
+                    grapheme ~= ch;
+                range.popFront();
+                continue;
+
+            case redo:
+                goto rerun;
+
+            case retInclude:
+                static if (getValue)
+                    grapheme ~= ch;
+                range.popFront();
+                break outer;
+
+            case retExclude:
+                break outer;
             }
         }
-    L_End_Extend:
-        while (!range.empty)
-        {
-            ch = range.front;
-            // extend & spacing marks
-            if (!graphemeExtend[ch] && !spacingMark[ch])
-                break;
-            mixin(eat);
-        }
-    L_End:
+
         static if (getValue)
             return grapheme;
     }
-
 }
 
 public: // Public API continues
@@ -7143,6 +7243,31 @@ if (is(C : dchar))
     static assert(c2 == 3); // \u0301 has 2 UTF-8 code units
 }
 
+// TODO: make this @nogc. Probably no big deal since the state machine is
+// already GC-free.
+@safe pure nothrow unittest
+{
+    // grinning face ~ emoji modifier fitzpatrick type-5 ~ grinning face
+    assert(graphemeStride("\U0001F600\U0001f3FE\U0001F600"d, 0) == 2);
+    // skier ~ female sign ~ '€'
+    assert(graphemeStride("\u26F7\u2640€"d, 0) == 1);
+    // skier ~ emoji modifier fitzpatrick type-5 ~ female sign ~ '€'
+    assert(graphemeStride("\u26F7\U0001f3FE\u2640€"d, 0) == 2);
+    // skier ~ zero-width joiner ~ female sign ~ '€'
+    assert(graphemeStride("\u26F7\u200D\u2640€"d, 0) == 3);
+    // skier ~ emoji modifier fitzpatrick type-5 ~ zero-width joiner
+    // ~ female sign ~ '€'
+    assert(graphemeStride("\u26F7\U0001f3FE\u200D\u2640€"d, 0) == 4);
+    // skier ~ zero-width joiner ~ '€'
+    assert(graphemeStride("\u26F7\u200D€"d, 0) == 2);
+    //'€' ~ zero-width joiner ~ skier
+    assert(graphemeStride("€\u200D\u26F7"d, 0) == 2);
+    // Kaithi number sign ~ Devanagari digit four ~ Devanagari digit two
+    assert(graphemeStride("\U000110BD\u096A\u0968"d, 0) == 2);
+    // Kaithi number sign ~ null
+    assert(graphemeStride("\U000110BD\0"d, 0) == 1);
+}
+
 /++
     Reads one full grapheme cluster from an
     $(REF_ALTTEXT input range, isInputRange, std,range,primitives) of dchar `inp`.
@@ -7285,6 +7410,13 @@ private static @safe struct InputRangeString
     assert(nonForwardRange.walkLength == 4);
 }
 
+// Issue 23474
+@safe pure unittest
+{
+    import std.range.primitives : walkLength;
+    assert(byGrapheme("\r\u0308").walkLength == 2);
+}
+
 /++
     $(P Lazily transform a range of $(LREF Grapheme)s to a range of code points.)
 
@@ -10530,8 +10662,6 @@ private:
 
 @safe pure nothrow @nogc @property
 {
-    import std.internal.unicode_tables; // generated file
-
     // It's important to use auto return here, so that the compiler
     // only runs semantic on the return type if the function gets
     // used. Also these are functions rather than templates to not
@@ -10578,10 +10708,10 @@ private:
     }
 
     //grapheme breaking algorithm tables
-    auto mcTrie()
+    auto spacingMarkTrie()
     {
-        import std.internal.unicode_grapheme : mcTrieEntries;
-        static immutable res = asTrie(mcTrieEntries);
+        import std.internal.unicode_grapheme : spacingMarkTrieEntries;
+        static immutable res = asTrie(spacingMarkTrieEntries);
         return res;
     }
 
@@ -10606,6 +10736,27 @@ private:
         return res;
     }
 
+    auto prependTrie()
+    {
+        import std.internal.unicode_grapheme : prependTrieEntries;
+        static immutable res = asTrie(prependTrieEntries);
+        return res;
+    }
+
+    auto graphemeControlTrie()
+    {
+        import std.internal.unicode_grapheme : controlTrieEntries;
+        static immutable res = asTrie(controlTrieEntries);
+        return res;
+    }
+
+    auto xpictoTrie()
+    {
+        import std.internal.unicode_grapheme : Extended_PictographicTrieEntries;
+        static immutable res = asTrie(Extended_PictographicTrieEntries);
+        return res;
+    }
+
     // tables below are used for composition/decomposition
     auto combiningClassTrie()
     {
index 7a0556de8227d3ee46f217f8b78a54eab27bcc34..3eef5cbcc03d50b8dac67e9634a298852d9a467d 100644 (file)
@@ -3136,7 +3136,7 @@ private T toUTFImpl(T, S)(scope S s)
     collection cycle and cause a nasty bug when the C code tries to use it.
   +/
 template toUTFz(P)
-if (is(P : C*, C) && isSomeChar!C)
+if (is(P == C*, C) && isSomeChar!C)
 {
     P toUTFz(S)(S str) @safe pure
     if (isSomeString!S)
index 0ad2443c826ea2cfebc9223c893bd9a9cfd7c246..a6d7e5a57884cb6380b948162b339aff6b104095 100644 (file)
@@ -290,14 +290,14 @@ void issue22076()
     extern(C++) static class C0
     {
         int foo() { return 0; } // Need at least one function in vtable.
-        S0 a; alias a this;
+        S0 a; alias a this; // { dg-warning "is deprecated" }
     }
 
     extern(C++) static class C1
     {
         S1 a;
         inout(S1)* b() inout nothrow { return &a; }
-        alias b this;
+        alias b this;       // { dg-warning "is deprecated" }
     }
 
     cast(void) hashOf(S0.init);
index fcec87b1aacc3854dfce2bfbd610a8512ed295c2..f31b818e261673ec31eec521b435fd756f4dbd67 100644 (file)
@@ -7,9 +7,9 @@ import core.sys.posix.dlfcn;
 void runTest()
 {
     Object obj;
-    obj = Object.factory("lib.MyFinalizer");    // { dg-warning "is deprecated" } 
+    obj = Object.factory("lib.MyFinalizer");
     assert(obj.toString() == "lib.MyFinalizer");
-    obj = Object.factory("lib.MyFinalizerBig"); // { dg-warning "is deprecated" }
+    obj = Object.factory("lib.MyFinalizerBig");
     assert(obj.toString() == "lib.MyFinalizerBig");
 }