aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2022-02-20 20:02:23 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2022-02-20 23:37:32 +0100
commit6384eff56dba1fac071c1b525f7e49cf03f2737f (patch)
tree7263a4a6ec603a81f6df660f4f6b19a4607513fc
parente49508ac6b36adb8a2056c5a1fb6e0178de2439d (diff)
downloadgcc-6384eff56dba1fac071c1b525f7e49cf03f2737f.zip
gcc-6384eff56dba1fac071c1b525f7e49cf03f2737f.tar.gz
gcc-6384eff56dba1fac071c1b525f7e49cf03f2737f.tar.bz2
d: Merge upstream dmd cb49e99f8, druntime 55528bd1, phobos 1a3e80ec2.
D front-end changes: - Import dmd v2.099.0-beta.1. - It's now an error to use `alias this' for partial assignment. - The `delete' keyword has been removed from the language. - Using `this' and `super' as types has been removed from the language, the parser no longer specially handles this wrong code with an informative error. D Runtime changes: - Import druntime v2.099.0-beta.1. Phobos changes: - Import phobos v2.099.0-beta.1. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd cb49e99f8. * dmd/VERSION: Update version to v2.099.0-beta.1. * decl.cc (layout_class_initializer): Update call to NewExp::create. * expr.cc (ExprVisitor::visit (DeleteExp *)): Remove handling of deleting arrays and pointers. (ExprVisitor::visit (DotVarExp *)): Convert complex types to the front-end library type representing them. (ExprVisitor::visit (StringExp *)): Use getCodeUnit instead of charAt to get the value of each index in a string expression. * runtime.def (DELMEMORY): Remove. (DELARRAYT): Remove. * types.cc (TypeVisitor::visit (TypeEnum *)): Handle anonymous enums. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 55528bd1. * src/MERGE: Merge upstream phobos 1a3e80ec2. * testsuite/libphobos.hash/test_hash.d: Update. * testsuite/libphobos.betterc/test19933.d: New test.
-rw-r--r--gcc/d/decl.cc2
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/VERSION2
-rw-r--r--gcc/d/dmd/apply.d4
-rw-r--r--gcc/d/dmd/canthrow.d12
-rw-r--r--gcc/d/dmd/clone.d37
-rw-r--r--gcc/d/dmd/constfold.d6
-rw-r--r--gcc/d/dmd/cparse.d27
-rw-r--r--gcc/d/dmd/ctfeexpr.d2
-rw-r--r--gcc/d/dmd/dcast.d4263
-rw-r--r--gcc/d/dmd/declaration.d5
-rw-r--r--gcc/d/dmd/declaration.h1
-rw-r--r--gcc/d/dmd/dinterpret.d106
-rw-r--r--gcc/d/dmd/dmangle.d3
-rw-r--r--gcc/d/dmd/dmodule.d78
-rw-r--r--gcc/d/dmd/dscope.d2
-rw-r--r--gcc/d/dmd/dsymbol.d11
-rw-r--r--gcc/d/dmd/dsymbol.h2
-rw-r--r--gcc/d/dmd/dsymbolsem.d184
-rw-r--r--gcc/d/dmd/dtemplate.d52
-rw-r--r--gcc/d/dmd/dtoh.d24
-rw-r--r--gcc/d/dmd/escape.d2
-rw-r--r--gcc/d/dmd/expression.d115
-rw-r--r--gcc/d/dmd/expression.h17
-rw-r--r--gcc/d/dmd/expressionsem.d304
-rw-r--r--gcc/d/dmd/func.d3
-rw-r--r--gcc/d/dmd/hdrgen.d70
-rw-r--r--gcc/d/dmd/iasmgcc.d2
-rw-r--r--gcc/d/dmd/id.d4
-rw-r--r--gcc/d/dmd/importc.d47
-rw-r--r--gcc/d/dmd/initsem.d4
-rw-r--r--gcc/d/dmd/lexer.d444
-rw-r--r--gcc/d/dmd/mtype.d45
-rw-r--r--gcc/d/dmd/nogc.d42
-rw-r--r--gcc/d/dmd/opover.d342
-rw-r--r--gcc/d/dmd/optimize.d7
-rw-r--r--gcc/d/dmd/parse.d794
-rw-r--r--gcc/d/dmd/printast.d10
-rw-r--r--gcc/d/dmd/semantic2.d2
-rw-r--r--gcc/d/dmd/semantic3.d22
-rw-r--r--gcc/d/dmd/statementsem.d206
-rw-r--r--gcc/d/dmd/staticassert.d5
-rw-r--r--gcc/d/dmd/staticassert.h1
-rw-r--r--gcc/d/dmd/tokens.d120
-rw-r--r--gcc/d/dmd/tokens.h13
-rw-r--r--gcc/d/dmd/transitivevisitor.d4
-rw-r--r--gcc/d/dmd/typesem.d80
-rw-r--r--gcc/d/expr.cc46
-rw-r--r--gcc/d/runtime.def7
-rw-r--r--gcc/d/types.cc14
-rw-r--r--gcc/testsuite/gdc.dg/special1.d12
-rw-r--r--gcc/testsuite/gdc.test/compilable/99bottles.d212
-rw-r--r--gcc/testsuite/gdc.test/compilable/b18242.d6
-rw-r--r--gcc/testsuite/gdc.test/compilable/b19294.d10
-rw-r--r--gcc/testsuite/gdc.test/compilable/b20938.d6
-rw-r--r--gcc/testsuite/gdc.test/compilable/b21285.d10
-rw-r--r--gcc/testsuite/gdc.test/compilable/commontype.d9
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddoc10.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddoc11.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddoc14.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddoc3.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddoc5.d4
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddoc5446.d22
-rw-r--r--gcc/testsuite/gdc.test/compilable/ddoc9155.d10
-rw-r--r--gcc/testsuite/gdc.test/compilable/debugInference.d6
-rw-r--r--gcc/testsuite/gdc.test/compilable/defa.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/dlangui_crash.d34
-rw-r--r--gcc/testsuite/gdc.test/compilable/enumbasearithmetic.d20
-rw-r--r--gcc/testsuite/gdc.test/compilable/header18364.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/b33a.d4
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/imp22734.c3
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/test22714a.d3
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/test22714b.d12
-rw-r--r--gcc/testsuite/gdc.test/compilable/issue16472.d42
-rw-r--r--gcc/testsuite/gdc.test/compilable/issue21340.d4
-rw-r--r--gcc/testsuite/gdc.test/compilable/issue21813b.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/minimal.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/test10993.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/test16107.d6
-rw-r--r--gcc/testsuite/gdc.test/compilable/test17545.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/test17906.d7
-rw-r--r--gcc/testsuite/gdc.test/compilable/test18030.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/test19014.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/test19315.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/test19557.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/test19609.d4
-rw-r--r--gcc/testsuite/gdc.test/compilable/test21177.d76
-rw-r--r--gcc/testsuite/gdc.test/compilable/test21196.d71
-rw-r--r--gcc/testsuite/gdc.test/compilable/test22224.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/test22632.d4
-rw-r--r--gcc/testsuite/gdc.test/compilable/test22714.d3
-rw-r--r--gcc/testsuite/gdc.test/compilable/test22734.d6
-rw-r--r--gcc/testsuite/gdc.test/compilable/test4375.d6
-rw-r--r--gcc/testsuite/gdc.test/compilable/test7172.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/test8296.d4
-rw-r--r--gcc/testsuite/gdc.test/compilable/test8513.d8
-rw-r--r--gcc/testsuite/gdc.test/compilable/testpostblit.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/testsctreturn.d16
-rw-r--r--gcc/testsuite/gdc.test/compilable/typeid_name.d2
-rw-r--r--gcc/testsuite/gdc.test/compilable/vgc1.d17
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/b20011.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/b3841.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/bug16165.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/bug8150a.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/bug8150b.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ccast.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ctfe14731.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag10319.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag10805.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag13281.d6
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag15713.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag16977.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail10964.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail11375.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail11542.d8
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail12809.d8
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail14277.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail14486.d45
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail14554.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail15089.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail160.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail17906.d12
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail17969.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail18228.d6
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19441.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail196.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19897.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19911b.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19911c.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19922.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19923.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail20.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail20800.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail22127.d11
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail22634.d12
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail22780.d12
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail2361.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail258.d12
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail332.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail349.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail354.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail4082.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail4269a.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail4269b.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail4269c.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail4375d.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail6968.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail7848.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail80_m32.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail80_m64.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail8724.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d6
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail_typeof.d82
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/faildeleteaa.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice10727a.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice10727b.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice11968.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/ice18753.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/lexer1.d4
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/no_Throwable.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/no_TypeInfo.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/nogc1.d9
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/noreturn2.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/scope_type.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test12228.d6
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test16195.d3
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test17307.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test20245.d53
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test22145.d28
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/test22686.d21
-rw-r--r--gcc/testsuite/gdc.test/runnable/b18034.d10
-rw-r--r--gcc/testsuite/gdc.test/runnable/imports/a15079.d2
-rw-r--r--gcc/testsuite/gdc.test/runnable/imports/a19a.d2
-rw-r--r--gcc/testsuite/gdc.test/runnable/imports/link12144a.d2
-rw-r--r--gcc/testsuite/gdc.test/runnable/imports/test11745b.d12
-rw-r--r--gcc/testsuite/gdc.test/runnable/imports/test46c.d2
-rw-r--r--gcc/testsuite/gdc.test/runnable/inline7625.d185
-rw-r--r--gcc/testsuite/gdc.test/runnable/interface.d12
-rw-r--r--gcc/testsuite/gdc.test/runnable/interface2.d11
-rw-r--r--gcc/testsuite/gdc.test/runnable/interpret.d91
-rw-r--r--gcc/testsuite/gdc.test/runnable/link12144.d6
-rw-r--r--gcc/testsuite/gdc.test/runnable/link15017.d8
-rw-r--r--gcc/testsuite/gdc.test/runnable/mixin1.d7
-rw-r--r--gcc/testsuite/gdc.test/runnable/newdel.d8
-rw-r--r--gcc/testsuite/gdc.test/runnable/sdtor.d26
-rw-r--r--gcc/testsuite/gdc.test/runnable/test11934.d2
-rw-r--r--gcc/testsuite/gdc.test/runnable/test17684.d20
-rw-r--r--gcc/testsuite/gdc.test/runnable/test17899.d2
-rw-r--r--gcc/testsuite/gdc.test/runnable/test20.d8
-rw-r--r--gcc/testsuite/gdc.test/runnable/test22136.d25
-rw-r--r--gcc/testsuite/gdc.test/runnable/test22163.d13
-rw-r--r--gcc/testsuite/gdc.test/runnable/test22717.d31
-rw-r--r--gcc/testsuite/gdc.test/runnable/test4.d8
-rw-r--r--gcc/testsuite/gdc.test/runnable/testappend.d16
-rw-r--r--gcc/testsuite/gdc.test/runnable/testconst.d4
-rw-r--r--gcc/testsuite/gdc.test/runnable/testdstress.d8
-rw-r--r--gcc/testsuite/gdc.test/runnable/testptrref.d10
-rw-r--r--gcc/testsuite/gdc.test/runnable/xpostblit.d2
-rw-r--r--gcc/testsuite/gdc.test/runnable_cxx/cppa.d2
-rw-r--r--libphobos/libdruntime/MERGE2
-rw-r--r--libphobos/libdruntime/__builtins.di65
-rw-r--r--libphobos/libdruntime/core/attribute.d49
-rw-r--r--libphobos/libdruntime/core/bitop.d13
-rw-r--r--libphobos/libdruntime/core/int128.d2
-rw-r--r--libphobos/libdruntime/core/internal/array/appending.d8
-rw-r--r--libphobos/libdruntime/core/internal/array/comparison.d33
-rw-r--r--libphobos/libdruntime/core/internal/convert.d22
-rw-r--r--libphobos/libdruntime/core/lifetime.d4
-rw-r--r--libphobos/libdruntime/core/math.d1
-rw-r--r--libphobos/libdruntime/core/runtime.d2
-rw-r--r--libphobos/libdruntime/core/stdc/stdio.d17
-rw-r--r--libphobos/libdruntime/core/sys/linux/config.d3
-rw-r--r--libphobos/libdruntime/core/sys/linux/dlfcn.d22
-rw-r--r--libphobos/libdruntime/core/sys/linux/errno.d2
-rw-r--r--libphobos/libdruntime/core/sys/linux/netinet/in_.d10
-rw-r--r--libphobos/libdruntime/core/sys/linux/string.d2
-rw-r--r--libphobos/libdruntime/core/sys/linux/sys/mman.d72
-rw-r--r--libphobos/libdruntime/core/sys/posix/aio.d132
-rw-r--r--libphobos/libdruntime/core/sys/posix/config.d58
-rw-r--r--libphobos/libdruntime/core/sys/posix/spawn.d12
-rw-r--r--libphobos/libdruntime/core/sys/posix/sys/ipc.d65
-rw-r--r--libphobos/libdruntime/core/sys/posix/sys/mman.d4
-rw-r--r--libphobos/libdruntime/core/sys/posix/sys/shm.d12
-rw-r--r--libphobos/libdruntime/core/sys/posix/sys/socket.d32
-rw-r--r--libphobos/libdruntime/core/sys/posix/sys/stat.d24
-rw-r--r--libphobos/libdruntime/core/sys/posix/sys/statvfs.d2
-rw-r--r--libphobos/libdruntime/core/sys/posix/sys/types.d2
-rw-r--r--libphobos/libdruntime/object.d4
-rw-r--r--libphobos/libdruntime/rt/util/typeinfo.d289
-rw-r--r--libphobos/src/MERGE2
-rw-r--r--libphobos/src/std/algorithm/internal.d2
-rw-r--r--libphobos/src/std/bigint.d16
-rw-r--r--libphobos/src/std/container/rbtree.d16
-rw-r--r--libphobos/src/std/conv.d2
-rw-r--r--libphobos/src/std/file.d27
-rw-r--r--libphobos/src/std/functional.d9
-rw-r--r--libphobos/src/std/internal/math/biguintcore.d6
-rw-r--r--libphobos/src/std/socket.d17
-rw-r--r--libphobos/src/std/sumtype.d20
-rw-r--r--libphobos/src/std/typecons.d42
-rw-r--r--libphobos/src/std/uni/package.d2
-rw-r--r--libphobos/src/std/zip.d35
-rw-r--r--libphobos/testsuite/libphobos.betterc/test19933.d11
-rw-r--r--libphobos/testsuite/libphobos.hash/test_hash.d2
245 files changed, 5539 insertions, 4937 deletions
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index b08d797..7ec0caf 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -2235,7 +2235,7 @@ aggregate_initializer_decl (AggregateDeclaration *decl)
tree
layout_class_initializer (ClassDeclaration *cd)
{
- NewExp *ne = NewExp::create (cd->loc, NULL, NULL, cd->type, NULL);
+ NewExp *ne = NewExp::create (cd->loc, NULL, cd->type, NULL);
ne->type = cd->type;
Expression *e = ne->ctfeInterpret ();
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 91cdc9f..b92f376 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-52844d4b1e9d6714bfd2e535f25a72074a046209
+cb49e99f80e8111c71035b88fe47fe7d855c300f
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION
index 0aa03f4..12042ff 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@
-v2.098.1
+v2.099.0-beta.1
diff --git a/gcc/d/dmd/apply.d b/gcc/d/dmd/apply.d
index 75b4af1..ac2c80e 100644
--- a/gcc/d/dmd/apply.d
+++ b/gcc/d/dmd/apply.d
@@ -110,13 +110,13 @@ public:
override void visit(NewExp e)
{
//printf("NewExp::apply(): %s\n", toChars());
- doCond(e.thisexp) || doCond(e.newargs) || doCond(e.arguments) || applyTo(e);
+ doCond(e.thisexp) || doCond(e.arguments) || applyTo(e);
}
override void visit(NewAnonClassExp e)
{
//printf("NewAnonClassExp::apply(): %s\n", toChars());
- doCond(e.thisexp) || doCond(e.newargs) || doCond(e.arguments) || applyTo(e);
+ doCond(e.thisexp) || doCond(e.arguments) || applyTo(e);
}
override void visit(TypeidExp e)
diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d
index faf427d..745e552 100644
--- a/gcc/d/dmd/canthrow.d
+++ b/gcc/d/dmd/canthrow.d
@@ -114,9 +114,7 @@ extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN
import dmd.id : Id;
auto sd = ts.sym;
- if (sd.dtor && ce.f.ident == Id._d_delstruct)
- checkFuncThrows(ce, sd.dtor);
- else if (sd.postblit &&
+ if (sd.postblit &&
(ce.f.ident == Id._d_arrayctor || ce.f.ident == Id._d_arraysetctor))
{
checkFuncThrows(ce, sd.postblit);
@@ -175,14 +173,6 @@ extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustN
ad = tb.isTypeClass().sym;
break;
- case Tpointer:
- case Tarray:
- auto ts = tb.nextOf().baseElemOf().isTypeStruct();
- if (!ts)
- return;
- ad = ts.sym;
- break;
-
default:
assert(0); // error should have been detected by semantic()
}
diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d
index 1a143cb..a6dbd8e 100644
--- a/gcc/d/dmd/clone.d
+++ b/gcc/d/dmd/clone.d
@@ -521,9 +521,9 @@ FuncDeclaration buildOpEquals(StructDeclaration sd, Scope* sc)
/******************************************
* Build __xopEquals for TypeInfo_Struct
- * static bool __xopEquals(ref const S p, ref const S q)
+ * bool __xopEquals(ref const S p) const
* {
- * return p == q;
+ * return this == p;
* }
*
* This is called by TypeInfo.equals(p1, p2). If the struct does not support
@@ -570,14 +570,15 @@ FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc)
Loc declLoc; // loc is unnecessary so __xopEquals is never called directly
Loc loc; // loc is unnecessary so errors are gagged
auto parameters = new Parameters();
- parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.p, null, null))
- .push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.q, null, null));
- auto tf = new TypeFunction(ParameterList(parameters), Type.tbool, LINK.d);
+ parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.p, null, null));
+ auto tf = new TypeFunction(ParameterList(parameters), Type.tbool, LINK.d, STC.const_);
+ tf = tf.addSTC(STC.const_).toTypeFunction();
Identifier id = Id.xopEquals;
- auto fop = new FuncDeclaration(declLoc, Loc.initial, id, STC.static_, tf);
+ auto fop = new FuncDeclaration(declLoc, Loc.initial, id, 0, tf);
fop.generated = true;
- Expression e1 = new IdentifierExp(loc, Id.p);
- Expression e2 = new IdentifierExp(loc, Id.q);
+ fop.parent = sd;
+ Expression e1 = new IdentifierExp(loc, Id.This);
+ Expression e2 = new IdentifierExp(loc, Id.p);
Expression e = new EqualExp(EXP.equal, loc, e1, e2);
fop.fbody = new ReturnStatement(loc, e);
uint errors = global.startGagging(); // Do not report errors
@@ -594,9 +595,9 @@ FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc)
/******************************************
* Build __xopCmp for TypeInfo_Struct
- * static bool __xopCmp(ref const S p, ref const S q)
+ * int __xopCmp(ref const S p) const
* {
- * return p.opCmp(q);
+ * return this.opCmp(p);
* }
*
* This is called by TypeInfo.compare(p1, p2). If the struct does not support
@@ -691,17 +692,15 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc)
Loc loc; // loc is unnecessary so errors are gagged
auto parameters = new Parameters();
parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.p, null, null));
- parameters.push(new Parameter(STC.ref_ | STC.const_, sd.type, Id.q, null, null));
- auto tf = new TypeFunction(ParameterList(parameters), Type.tint32, LINK.d);
+ auto tf = new TypeFunction(ParameterList(parameters), Type.tint32, LINK.d, STC.const_);
+ tf = tf.addSTC(STC.const_).toTypeFunction();
Identifier id = Id.xopCmp;
- auto fop = new FuncDeclaration(declLoc, Loc.initial, id, STC.static_, tf);
+ auto fop = new FuncDeclaration(declLoc, Loc.initial, id, 0, tf);
fop.generated = true;
- Expression e1 = new IdentifierExp(loc, Id.p);
- Expression e2 = new IdentifierExp(loc, Id.q);
- version (IN_GCC)
- Expression e = new CallExp(loc, new DotIdExp(loc, e1, Id.cmp), e2);
- else
- Expression e = new CallExp(loc, new DotIdExp(loc, e2, Id.cmp), e1);
+ fop.parent = sd;
+ Expression e1 = new IdentifierExp(loc, Id.This);
+ Expression e2 = new IdentifierExp(loc, Id.p);
+ Expression e = new CallExp(loc, new DotIdExp(loc, e1, Id.cmp), e2);
fop.fbody = new ReturnStatement(loc, e);
uint errors = global.startGagging(); // Do not report errors
Scope* sc2 = sc.push();
diff --git a/gcc/d/dmd/constfold.d b/gcc/d/dmd/constfold.d
index 16f7b2f..7bc890f 100644
--- a/gcc/d/dmd/constfold.d
+++ b/gcc/d/dmd/constfold.d
@@ -827,9 +827,9 @@ UnionExp Equal(EXP op, const ref Loc loc, Type type, Expression e1, Expression e
else
{
cmp = 1; // if dim1 winds up being 0
- for (size_t i = 0; i < dim1; i++)
+ foreach (i; 0 .. dim1)
{
- uinteger_t c = es1.charAt(i);
+ uinteger_t c = es1.getCodeUnit(i);
auto ee2 = es2[i];
if (ee2.isConst() != 1)
{
@@ -1247,7 +1247,7 @@ UnionExp Index(Type type, Expression e1, Expression e2)
}
else
{
- emplaceExp!(IntegerExp)(&ue, loc, es1.charAt(i), type);
+ emplaceExp!(IntegerExp)(&ue, loc, es1.getCodeUnit(cast(size_t) i), type);
}
}
else if (e1.type.toBasetype().ty == Tsarray && e2.op == EXP.int64)
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 38a78a0..0fe6459 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -197,6 +197,7 @@ final class CParser(AST) : Parser!AST
}
break;
+ case TOK.charLiteral:
case TOK.int32Literal:
case TOK.uns32Literal:
case TOK.int64Literal:
@@ -264,6 +265,7 @@ final class CParser(AST) : Parser!AST
case TOK.const_:
case TOK.volatile:
case TOK.restrict:
+ case TOK.__stdcall:
// alignment-specifier
case TOK._Alignas:
@@ -635,6 +637,7 @@ final class CParser(AST) : Parser!AST
nextToken();
break;
+ case TOK.charLiteral:
case TOK.int32Literal:
e = new AST.IntegerExp(loc, token.intvalue, AST.Type.tint32);
nextToken();
@@ -1585,7 +1588,7 @@ final class CParser(AST) : Parser!AST
if (tspec && specifier.mod & MOD.xconst)
{
tspec = toConst(tspec);
- specifier.mod = MOD.xnone; // 'used' it
+ specifier.mod &= ~MOD.xnone; // 'used' it
}
bool first = true;
@@ -1708,7 +1711,7 @@ final class CParser(AST) : Parser!AST
symbols.push(stag);
if (tt.tok == TOK.enum_)
{
- if (!tt.members)
+ if (!stag.members)
error(tt.loc, "`enum %s` has no members", stag.toChars());
isalias = false;
s = new AST.AliasDeclaration(token.loc, id, stag);
@@ -1842,8 +1845,8 @@ final class CParser(AST) : Parser!AST
/* Since there were declarations, the parameter-list must have been
* an identifier-list.
*/
+ ft.parameterList.hasIdentifierList = true; // semantic needs to know to adjust parameter types
auto pl = ft.parameterList;
- pl.hasIdentifierList = true; // semantic needs to know to adjust parameter types
if (pl.varargs != AST.VarArg.none && pl.length)
error("function identifier-list cannot end with `...`");
ft.parameterList.varargs = AST.VarArg.variadic; // but C11 allows extra arguments
@@ -2071,6 +2074,7 @@ final class CParser(AST) : Parser!AST
case TOK.const_: modx = MOD.xconst; break;
case TOK.volatile: modx = MOD.xvolatile; break;
case TOK.restrict: modx = MOD.xrestrict; break;
+ case TOK.__stdcall: modx = MOD.x__stdcall; break;
// Type specifiers
case TOK.char_: tkwx = TKW.xchar; break;
@@ -2409,6 +2413,13 @@ final class CParser(AST) : Parser!AST
* T ((*fp))();
*/
nextToken();
+
+ if (token.value == TOK.__stdcall) // T (__stdcall*fp)();
+ {
+ specifier.mod |= MOD.x__stdcall;
+ nextToken();
+ }
+
ts = parseDecl(t);
check(TOK.rightParenthesis);
break;
@@ -2544,7 +2555,8 @@ final class CParser(AST) : Parser!AST
this.symbols = null;
auto parameterList = cparseParameterList();
- AST.Type tf = new AST.TypeFunction(parameterList, t, linkage, 0);
+ const lkg = specifier.mod & MOD.x__stdcall ? LINK.windows : linkage;
+ AST.Type tf = new AST.TypeFunction(parameterList, t, lkg, 0);
// tf = tf.addSTC(storageClass); // TODO
insertTx(ts, tf, t); // ts -> ... -> tf -> t
@@ -2612,6 +2624,7 @@ final class CParser(AST) : Parser!AST
* restrict
* volatile
* _Atomic
+ * __stdcall
*/
MOD cparseTypeQualifierList()
{
@@ -2624,6 +2637,7 @@ final class CParser(AST) : Parser!AST
case TOK.volatile: mod |= MOD.xvolatile; break;
case TOK.restrict: mod |= MOD.xrestrict; break;
case TOK._Atomic: mod |= MOD.x_Atomic; break;
+ case TOK.__stdcall: mod |= MOD.x__stdcall; break;
default:
return mod;
@@ -3708,6 +3722,7 @@ final class CParser(AST) : Parser!AST
case TOK.const_:
case TOK.volatile:
case TOK.restrict:
+ case TOK.__stdcall:
t = peek(t);
any = true;
continue;
@@ -3948,6 +3963,7 @@ final class CParser(AST) : Parser!AST
case TOK.restrict:
case TOK.volatile:
case TOK._Atomic:
+ case TOK.__stdcall:
t = peek(t);
continue;
@@ -4000,6 +4016,7 @@ final class CParser(AST) : Parser!AST
case TOK.const_:
case TOK.restrict:
case TOK.volatile:
+ case TOK.__stdcall:
// Type Specifiers
case TOK.char_:
@@ -4202,6 +4219,7 @@ final class CParser(AST) : Parser!AST
switch (t.value)
{
case TOK.identifier:
+ case TOK.charLiteral:
case TOK.int32Literal:
case TOK.uns32Literal:
case TOK.int64Literal:
@@ -4283,6 +4301,7 @@ final class CParser(AST) : Parser!AST
xvolatile = 2,
xrestrict = 4,
x_Atomic = 8,
+ x__stdcall = 0x10, // Windows linkage extension
}
/**********************************
diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d
index 43dce4b..9bc453d 100644
--- a/gcc/d/dmd/ctfeexpr.d
+++ b/gcc/d/dmd/ctfeexpr.d
@@ -1565,7 +1565,7 @@ Expression ctfeIndex(UnionExp* pue, const ref Loc loc, Type type, Expression e1,
error(loc, "string index %llu is out of bounds `[0 .. %llu]`", indx, cast(ulong)es1.len);
return CTFEExp.cantexp;
}
- emplaceExp!IntegerExp(pue, loc, es1.charAt(indx), type);
+ emplaceExp!IntegerExp(pue, loc, es1.getCodeUnit(cast(size_t) indx), type);
return pue.exp();
}
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 91b3861..f1afa76 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -64,160 +64,151 @@ enum LOG = false;
*/
Expression implicitCastTo(Expression e, Scope* sc, Type t)
{
- extern (C++) final class ImplicitCastTo : Visitor
+ Expression visit(Expression e)
{
- alias visit = Visitor.visit;
- public:
- Type t;
- Scope* sc;
- Expression result;
+ //printf("Expression.implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars());
- extern (D) this(Scope* sc, Type t)
+ if (const match = (sc && sc.flags & SCOPE.Cfile) ? e.cimplicitConvTo(t) : e.implicitConvTo(t))
{
- this.sc = sc;
- this.t = t;
- }
-
- override void visit(Expression e)
- {
- //printf("Expression.implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars());
+ if (match == MATCH.constant && (e.type.constConv(t) || !e.isLvalue() && e.type.equivalent(t)))
+ {
+ /* Do not emit CastExp for const conversions and
+ * unique conversions on rvalue.
+ */
+ auto result = e.copy();
+ result.type = t;
+ return result;
+ }
- if (const match = (sc && sc.flags & SCOPE.Cfile) ? e.cimplicitConvTo(t) : e.implicitConvTo(t))
+ auto ad = isAggregate(e.type);
+ if (ad && ad.aliasthis)
{
- if (match == MATCH.constant && (e.type.constConv(t) || !e.isLvalue() && e.type.equivalent(t)))
- {
- /* Do not emit CastExp for const conversions and
- * unique conversions on rvalue.
- */
- result = e.copy();
- result.type = t;
- return;
- }
+ auto ts = ad.type.isTypeStruct();
+ const adMatch = ts
+ ? ts.implicitConvToWithoutAliasThis(t)
+ : ad.type.isTypeClass().implicitConvToWithoutAliasThis(t);
- auto ad = isAggregate(e.type);
- if (ad && ad.aliasthis)
+ if (!adMatch)
{
- auto ts = ad.type.isTypeStruct();
- const adMatch = ts
- ? ts.implicitConvToWithoutAliasThis(t)
- : ad.type.isTypeClass().implicitConvToWithoutAliasThis(t);
-
- if (!adMatch)
+ Type tob = t.toBasetype();
+ Type t1b = e.type.toBasetype();
+ if (ad != isAggregate(tob))
{
- Type tob = t.toBasetype();
- Type t1b = e.type.toBasetype();
- if (ad != isAggregate(tob))
+ if (t1b.ty == Tclass && tob.ty == Tclass)
{
- if (t1b.ty == Tclass && tob.ty == Tclass)
+ ClassDeclaration t1cd = t1b.isClassHandle();
+ ClassDeclaration tocd = tob.isClassHandle();
+ int offset;
+ if (tocd.isBaseOf(t1cd, &offset))
{
- ClassDeclaration t1cd = t1b.isClassHandle();
- ClassDeclaration tocd = tob.isClassHandle();
- int offset;
- if (tocd.isBaseOf(t1cd, &offset))
- {
- result = new CastExp(e.loc, e, t);
- result.type = t;
- return;
- }
+ auto result = new CastExp(e.loc, e, t);
+ result.type = t;
+ return result;
}
+ }
- /* Forward the cast to our alias this member, rewrite to:
- * cast(to)e1.aliasthis
- */
- result = resolveAliasThis(sc, e);
- result = result.castTo(sc, t);
- return;
- }
- }
+ /* Forward the cast to our alias this member, rewrite to:
+ * cast(to)e1.aliasthis
+ */
+ auto result = resolveAliasThis(sc, e);
+ return result.castTo(sc, t);
+ }
}
-
- result = e.castTo(sc, t);
- return;
}
- result = e.optimize(WANTvalue);
- if (result != e)
- {
- result.accept(this);
- return;
- }
+ return e.castTo(sc, t);
+ }
- if (t.ty != Terror && e.type.ty != Terror)
- {
- if (!t.deco)
- {
- e.error("forward reference to type `%s`", t.toChars());
- }
- else
- {
- //printf("type %p ty %d deco %p\n", type, type.ty, type.deco);
- //type = type.typeSemantic(loc, sc);
- //printf("type %s t %s\n", type.deco, t.deco);
- auto ts = toAutoQualChars(e.type, t);
- e.error("cannot implicitly convert expression `%s` of type `%s` to `%s`",
- e.toChars(), ts[0], ts[1]);
- }
- }
- result = ErrorExp.get();
+ auto result = e.optimize(WANTvalue);
+ if (result != e)
+ {
+ return implicitCastTo(result, sc, t);
}
- override void visit(StringExp e)
+ if (t.ty != Terror && e.type.ty != Terror)
{
- //printf("StringExp::implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars());
- visit(cast(Expression)e);
- if (auto se = result.isStringExp())
+ if (!t.deco)
+ {
+ e.error("forward reference to type `%s`", t.toChars());
+ }
+ else
{
- // Retain polysemous nature if it started out that way
- se.committed = e.committed;
+ //printf("type %p ty %d deco %p\n", type, type.ty, type.deco);
+ //type = type.typeSemantic(loc, sc);
+ //printf("type %s t %s\n", type.deco, t.deco);
+ auto ts = toAutoQualChars(e.type, t);
+ e.error("cannot implicitly convert expression `%s` of type `%s` to `%s`",
+ e.toChars(), ts[0], ts[1]);
}
}
+ return ErrorExp.get();
+ }
- override void visit(ErrorExp e)
+ Expression visitString(StringExp e)
+ {
+ //printf("StringExp::implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars());
+ auto result = visit(e);
+ if (auto se = result.isStringExp())
{
- result = e;
+ // Retain polysemous nature if it started out that way
+ se.committed = e.committed;
}
+ return result;
+ }
+
+ Expression visitError(ErrorExp e)
+ {
+ return e;
+ }
- override void visit(FuncExp e)
+ Expression visitFunc(FuncExp e)
+ {
+ //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", e.type, e.type ? e.type.toChars() : NULL, t.toChars());
+ FuncExp fe;
+ if (e.matchType(t, sc, &fe) > MATCH.nomatch)
{
- //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", e.type, e.type ? e.type.toChars() : NULL, t.toChars());
- FuncExp fe;
- if (e.matchType(t, sc, &fe) > MATCH.nomatch)
- {
- result = fe;
- return;
- }
- visit(cast(Expression)e);
+ return fe;
}
+ return visit(e);
+ }
- override void visit(ArrayLiteralExp e)
- {
- visit(cast(Expression)e);
+ Expression visitArrayLiteral(ArrayLiteralExp e)
+ {
+ auto result = visit(e);
- Type tb = result.type.toBasetype();
- if (auto ta = tb.isTypeDArray())
- if (global.params.useTypeInfo && Type.dtypeinfo)
- semanticTypeInfo(sc, ta.next);
- }
+ Type tb = result.type.toBasetype();
+ if (auto ta = tb.isTypeDArray())
+ if (global.params.useTypeInfo && Type.dtypeinfo)
+ semanticTypeInfo(sc, ta.next);
+ return result;
+ }
- override void visit(SliceExp e)
- {
- visit(cast(Expression)e);
+ Expression visitSlice(SliceExp e)
+ {
+ auto result = visit(e);
- if (auto se = result.isSliceExp())
- if (auto ale = se.e1.isArrayLiteralExp())
- {
- Type tb = t.toBasetype();
- Type tx = (tb.ty == Tsarray)
- ? tb.nextOf().sarrayOf(ale.elements ? ale.elements.dim : 0)
- : tb.nextOf().arrayOf();
- se.e1 = ale.implicitCastTo(sc, tx);
- }
- }
+ if (auto se = result.isSliceExp())
+ if (auto ale = se.e1.isArrayLiteralExp())
+ {
+ Type tb = t.toBasetype();
+ Type tx = (tb.ty == Tsarray)
+ ? tb.nextOf().sarrayOf(ale.elements ? ale.elements.dim : 0)
+ : tb.nextOf().arrayOf();
+ se.e1 = ale.implicitCastTo(sc, tx);
+ }
+
+ return result;
}
- scope ImplicitCastTo v = new ImplicitCastTo(sc, t);
- e.accept(v);
- return v.result;
+ switch (e.op)
+ {
+ default : return visit (e);
+ case EXP.string_ : return visitString (e.isStringExp());
+ case EXP.error : return visitError (e.isErrorExp());
+ case EXP.function_ : return visitFunc (e.isFuncExp());
+ case EXP.arrayLiteral: return visitArrayLiteral(e.isArrayLiteralExp());
+ case EXP.slice : return visitSlice (e.isSliceExp());
+ }
}
/**
@@ -236,1242 +227,1244 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t)
*/
MATCH implicitConvTo(Expression e, Type t)
{
- extern (C++) final class ImplicitConvTo : Visitor
+ MATCH visit(Expression e)
{
- alias visit = Visitor.visit;
- public:
- Type t;
- MATCH result;
+ version (none)
+ {
+ printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ }
+ //static int nest; if (++nest == 10) assert(0);
+ if (t == Type.terror)
+ return MATCH.nomatch;
+ if (!e.type)
+ {
+ e.error("`%s` is not an expression", e.toChars());
+ e.type = Type.terror;
+ }
- extern (D) this(Type t)
+ Expression ex = e.optimize(WANTvalue);
+ if (ex.type.equals(t))
+ {
+ return MATCH.exact;
+ }
+ if (ex != e)
{
- this.t = t;
- result = MATCH.nomatch;
+ //printf("\toptimized to %s of type %s\n", e.toChars(), e.type.toChars());
+ return ex.implicitConvTo(t);
}
- override void visit(Expression e)
+ MATCH match = e.type.implicitConvTo(t);
+ if (match != MATCH.nomatch)
{
- version (none)
- {
- printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
- }
- //static int nest; if (++nest == 10) assert(0);
- if (t == Type.terror)
- return;
- if (!e.type)
- {
- e.error("`%s` is not an expression", e.toChars());
- e.type = Type.terror;
- }
+ return match;
+ }
- Expression ex = e.optimize(WANTvalue);
- if (ex.type.equals(t))
- {
- result = MATCH.exact;
- return;
- }
- if (ex != e)
+ /* See if we can do integral narrowing conversions
+ */
+ if (e.type.isintegral() && t.isintegral() && e.type.isTypeBasic() && t.isTypeBasic())
+ {
+ IntRange src = getIntRange(e);
+ IntRange target = IntRange.fromType(t);
+ if (target.contains(src))
{
- //printf("\toptimized to %s of type %s\n", e.toChars(), e.type.toChars());
- result = ex.implicitConvTo(t);
- return;
+ return MATCH.convert;
}
+ }
+ return MATCH.nomatch;
+ }
- MATCH match = e.type.implicitConvTo(t);
- if (match != MATCH.nomatch)
- {
- result = match;
- return;
- }
+ /******
+ * Given expression e of type t, see if we can implicitly convert e
+ * to type tprime, where tprime is type t with mod bits added.
+ * Returns:
+ * match level
+ */
+ static MATCH implicitMod(Expression e, Type t, MOD mod)
+ {
+ Type tprime;
+ if (t.ty == Tpointer)
+ tprime = t.nextOf().castMod(mod).pointerTo();
+ else if (t.ty == Tarray)
+ tprime = t.nextOf().castMod(mod).arrayOf();
+ else if (t.ty == Tsarray)
+ tprime = t.nextOf().castMod(mod).sarrayOf(t.size() / t.nextOf().size());
+ else
+ tprime = t.castMod(mod);
- /* See if we can do integral narrowing conversions
- */
- if (e.type.isintegral() && t.isintegral() && e.type.isTypeBasic() && t.isTypeBasic())
- {
- IntRange src = getIntRange(e);
- IntRange target = IntRange.fromType(t);
- if (target.contains(src))
- {
- result = MATCH.convert;
- return;
- }
- }
- }
+ return e.implicitConvTo(tprime);
+ }
- /******
- * Given expression e of type t, see if we can implicitly convert e
- * to type tprime, where tprime is type t with mod bits added.
- * Returns:
- * match level
+ static MATCH implicitConvToAddMin(BinExp e, Type t)
+ {
+ /* Is this (ptr +- offset)? If so, then ask ptr
+ * if the conversion can be done.
+ * This is to support doing things like implicitly converting a mutable unique
+ * pointer to an immutable pointer.
*/
- static MATCH implicitMod(Expression e, Type t, MOD mod)
- {
- Type tprime;
- if (t.ty == Tpointer)
- tprime = t.nextOf().castMod(mod).pointerTo();
- else if (t.ty == Tarray)
- tprime = t.nextOf().castMod(mod).arrayOf();
- else if (t.ty == Tsarray)
- tprime = t.nextOf().castMod(mod).sarrayOf(t.size() / t.nextOf().size());
- else
- tprime = t.castMod(mod);
- return e.implicitConvTo(tprime);
+ Type tb = t.toBasetype();
+ Type typeb = e.type.toBasetype();
+
+ if (typeb.ty != Tpointer || tb.ty != Tpointer)
+ return MATCH.nomatch;
+
+ Type t1b = e.e1.type.toBasetype();
+ Type t2b = e.e2.type.toBasetype();
+ if (t1b.ty == Tpointer && t2b.isintegral() && t1b.equivalent(tb))
+ {
+ // ptr + offset
+ // ptr - offset
+ MATCH m = e.e1.implicitConvTo(t);
+ return (m > MATCH.constant) ? MATCH.constant : m;
+ }
+ if (t2b.ty == Tpointer && t1b.isintegral() && t2b.equivalent(tb))
+ {
+ // offset + ptr
+ MATCH m = e.e2.implicitConvTo(t);
+ return (m > MATCH.constant) ? MATCH.constant : m;
}
- static MATCH implicitConvToAddMin(BinExp e, Type t)
+ return MATCH.nomatch;
+ }
+
+ MATCH visitAdd(AddExp e)
+ {
+ version (none)
{
- /* Is this (ptr +- offset)? If so, then ask ptr
- * if the conversion can be done.
- * This is to support doing things like implicitly converting a mutable unique
- * pointer to an immutable pointer.
- */
+ printf("AddExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ }
+ auto result = visit(e);
+ if (result == MATCH.nomatch)
+ result = implicitConvToAddMin(e, t);
+ return result;
+ }
- Type tb = t.toBasetype();
- Type typeb = e.type.toBasetype();
+ MATCH visitMin(MinExp e)
+ {
+ version (none)
+ {
+ printf("MinExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ }
+ auto result = visit(e);
+ if (result == MATCH.nomatch)
+ result = implicitConvToAddMin(e, t);
+ return result;
+ }
- if (typeb.ty != Tpointer || tb.ty != Tpointer)
- return MATCH.nomatch;
+ MATCH visitInteger(IntegerExp e)
+ {
+ version (none)
+ {
+ printf("IntegerExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ }
+ MATCH m = e.type.implicitConvTo(t);
+ if (m >= MATCH.constant)
+ {
+ return m;
+ }
- Type t1b = e.e1.type.toBasetype();
- Type t2b = e.e2.type.toBasetype();
- if (t1b.ty == Tpointer && t2b.isintegral() && t1b.equivalent(tb))
- {
- // ptr + offset
- // ptr - offset
- MATCH m = e.e1.implicitConvTo(t);
- return (m > MATCH.constant) ? MATCH.constant : m;
- }
- if (t2b.ty == Tpointer && t1b.isintegral() && t2b.equivalent(tb))
- {
- // offset + ptr
- MATCH m = e.e2.implicitConvTo(t);
- return (m > MATCH.constant) ? MATCH.constant : m;
- }
+ TY ty = e.type.toBasetype().ty;
+ TY toty = t.toBasetype().ty;
+ TY oldty = ty;
+ if (m == MATCH.nomatch && t.ty == Tenum)
return MATCH.nomatch;
- }
- override void visit(AddExp e)
+ if (auto tv = t.isTypeVector())
{
- version (none)
- {
- printf("AddExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
- }
- visit(cast(Expression)e);
- if (result == MATCH.nomatch)
- result = implicitConvToAddMin(e, t);
+ TypeBasic tb = tv.elementType();
+ if (tb.ty == Tvoid)
+ return MATCH.nomatch;
+ toty = tb.ty;
}
- override void visit(MinExp e)
+ switch (ty)
{
- version (none)
- {
- printf("MinExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
- }
- visit(cast(Expression)e);
- if (result == MATCH.nomatch)
- result = implicitConvToAddMin(e, t);
+ case Tbool:
+ case Tint8:
+ case Tchar:
+ case Tuns8:
+ case Tint16:
+ case Tuns16:
+ case Twchar:
+ ty = Tint32;
+ break;
+
+ case Tdchar:
+ ty = Tuns32;
+ break;
+
+ default:
+ break;
}
- override void visit(IntegerExp e)
+ // Only allow conversion if no change in value
+ immutable dinteger_t value = e.toInteger();
+
+ bool isLosslesslyConvertibleToFP(T)()
{
- version (none)
+ if (e.type.isunsigned())
{
- printf("IntegerExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ const f = cast(T) value;
+ return cast(dinteger_t) f == value;
}
- MATCH m = e.type.implicitConvTo(t);
- if (m >= MATCH.constant)
- {
- result = m;
- return;
- }
-
- TY ty = e.type.toBasetype().ty;
- TY toty = t.toBasetype().ty;
- TY oldty = ty;
- if (m == MATCH.nomatch && t.ty == Tenum)
- return;
+ const f = cast(T) cast(sinteger_t) value;
+ return cast(sinteger_t) f == cast(sinteger_t) value;
+ }
- if (auto tv = t.isTypeVector())
- {
- TypeBasic tb = tv.elementType();
- if (tb.ty == Tvoid)
- return;
- toty = tb.ty;
- }
+ switch (toty)
+ {
+ case Tbool:
+ if ((value & 1) != value)
+ return MATCH.nomatch;
+ break;
- switch (ty)
- {
- case Tbool:
- case Tint8:
- case Tchar:
- case Tuns8:
- case Tint16:
- case Tuns16:
- case Twchar:
- ty = Tint32;
- break;
+ case Tint8:
+ if (ty == Tuns64 && value & ~0x7FU)
+ return MATCH.nomatch;
+ else if (cast(byte)value != value)
+ return MATCH.nomatch;
+ break;
- case Tdchar:
- ty = Tuns32;
- break;
+ case Tchar:
+ if ((oldty == Twchar || oldty == Tdchar) && value > 0x7F)
+ return MATCH.nomatch;
+ goto case Tuns8;
+ case Tuns8:
+ //printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value);
+ if (cast(ubyte)value != value)
+ return MATCH.nomatch;
+ break;
- default:
- break;
- }
+ case Tint16:
+ if (ty == Tuns64 && value & ~0x7FFFU)
+ return MATCH.nomatch;
+ else if (cast(short)value != value)
+ return MATCH.nomatch;
+ break;
- // Only allow conversion if no change in value
- immutable dinteger_t value = e.toInteger();
+ case Twchar:
+ if (oldty == Tdchar && value > 0xD7FF && value < 0xE000)
+ return MATCH.nomatch;
+ goto case Tuns16;
+ case Tuns16:
+ if (cast(ushort)value != value)
+ return MATCH.nomatch;
+ break;
- bool isLosslesslyConvertibleToFP(T)()
+ case Tint32:
+ if (ty == Tuns32)
{
- if (e.type.isunsigned())
- {
- const f = cast(T) value;
- return cast(dinteger_t) f == value;
- }
-
- const f = cast(T) cast(sinteger_t) value;
- return cast(sinteger_t) f == cast(sinteger_t) value;
}
+ else if (ty == Tuns64 && value & ~0x7FFFFFFFU)
+ return MATCH.nomatch;
+ else if (cast(int)value != value)
+ return MATCH.nomatch;
+ break;
- switch (toty)
+ case Tuns32:
+ if (ty == Tint32)
{
- case Tbool:
- if ((value & 1) != value)
- return;
- break;
-
- case Tint8:
- if (ty == Tuns64 && value & ~0x7FU)
- return;
- else if (cast(byte)value != value)
- return;
- break;
-
- case Tchar:
- if ((oldty == Twchar || oldty == Tdchar) && value > 0x7F)
- return;
- goto case Tuns8;
- case Tuns8:
- //printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value);
- if (cast(ubyte)value != value)
- return;
- break;
-
- case Tint16:
- if (ty == Tuns64 && value & ~0x7FFFU)
- return;
- else if (cast(short)value != value)
- return;
- break;
-
- case Twchar:
- if (oldty == Tdchar && value > 0xD7FF && value < 0xE000)
- return;
- goto case Tuns16;
- case Tuns16:
- if (cast(ushort)value != value)
- return;
- break;
+ }
+ else if (cast(uint)value != value)
+ return MATCH.nomatch;
+ break;
- case Tint32:
- if (ty == Tuns32)
- {
- }
- else if (ty == Tuns64 && value & ~0x7FFFFFFFU)
- return;
- else if (cast(int)value != value)
- return;
- break;
+ case Tdchar:
+ if (value > 0x10FFFFU)
+ return MATCH.nomatch;
+ break;
- case Tuns32:
- if (ty == Tint32)
- {
- }
- else if (cast(uint)value != value)
- return;
- break;
+ case Tfloat32:
+ if (!isLosslesslyConvertibleToFP!float)
+ return MATCH.nomatch;
+ break;
- case Tdchar:
- if (value > 0x10FFFFU)
- return;
- break;
+ case Tfloat64:
+ if (!isLosslesslyConvertibleToFP!double)
+ return MATCH.nomatch;
+ break;
- case Tfloat32:
- if (!isLosslesslyConvertibleToFP!float)
- return;
- break;
+ case Tfloat80:
+ if (!isLosslesslyConvertibleToFP!real_t)
+ return MATCH.nomatch;
+ break;
- case Tfloat64:
- if (!isLosslesslyConvertibleToFP!double)
- return;
+ case Tpointer:
+ //printf("type = %s\n", type.toBasetype()->toChars());
+ //printf("t = %s\n", t.toBasetype()->toChars());
+ if (ty == Tpointer && e.type.toBasetype().nextOf().ty == t.toBasetype().nextOf().ty)
+ {
+ /* Allow things like:
+ * const char* P = cast(char *)3;
+ * char* q = P;
+ */
break;
+ }
+ goto default;
- case Tfloat80:
- if (!isLosslesslyConvertibleToFP!real_t)
- return;
- break;
+ default:
+ return visit(e);
+ }
- case Tpointer:
- //printf("type = %s\n", type.toBasetype()->toChars());
- //printf("t = %s\n", t.toBasetype()->toChars());
- if (ty == Tpointer && e.type.toBasetype().nextOf().ty == t.toBasetype().nextOf().ty)
- {
- /* Allow things like:
- * const char* P = cast(char *)3;
- * char* q = P;
- */
- break;
- }
- goto default;
+ //printf("MATCH.convert\n");
+ return MATCH.convert;
+ }
- default:
- visit(cast(Expression)e);
- return;
- }
+ MATCH visitError(ErrorExp e)
+ {
+ return MATCH.nomatch;
+ }
- //printf("MATCH.convert\n");
- result = MATCH.convert;
+ MATCH visitNull(NullExp e)
+ {
+ version (none)
+ {
+ printf("NullExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
}
-
- override void visit(ErrorExp e)
+ if (e.type.equals(t))
{
- // no match
+ return MATCH.exact;
}
- override void visit(NullExp e)
+ /* Allow implicit conversions from immutable to mutable|const,
+ * and mutable to immutable. It works because, after all, a null
+ * doesn't actually point to anything.
+ */
+ if (t.equivalent(e.type))
{
- version (none)
- {
- printf("NullExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
- }
- if (e.type.equals(t))
- {
- result = MATCH.exact;
- return;
- }
+ return MATCH.constant;
+ }
- /* Allow implicit conversions from immutable to mutable|const,
- * and mutable to immutable. It works because, after all, a null
- * doesn't actually point to anything.
- */
- if (t.equivalent(e.type))
- {
- result = MATCH.constant;
- return;
- }
+ return visit(e);
+ }
- visit(cast(Expression)e);
+ MATCH visitStructLiteral(StructLiteralExp e)
+ {
+ version (none)
+ {
+ printf("StructLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
}
-
- override void visit(StructLiteralExp e)
+ auto result = visit(e);
+ if (result != MATCH.nomatch)
+ return result;
+ if (e.type.ty == t.ty && e.type.isTypeStruct() && e.type.isTypeStruct().sym == t.isTypeStruct().sym)
{
- version (none)
- {
- printf("StructLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
- }
- visit(cast(Expression)e);
- if (result != MATCH.nomatch)
- return;
- if (e.type.ty == t.ty && e.type.isTypeStruct() && e.type.isTypeStruct().sym == t.isTypeStruct().sym)
+ result = MATCH.constant;
+ foreach (i, el; (*e.elements)[])
{
- result = MATCH.constant;
- foreach (i, el; (*e.elements)[])
- {
- if (!el)
- continue;
- Type te = e.sd.fields[i].type.addMod(t.mod);
- MATCH m2 = el.implicitConvTo(te);
- //printf("\t%s => %s, match = %d\n", el.toChars(), te.toChars(), m2);
- if (m2 < result)
- result = m2;
- }
+ if (!el)
+ continue;
+ Type te = e.sd.fields[i].type.addMod(t.mod);
+ MATCH m2 = el.implicitConvTo(te);
+ //printf("\t%s => %s, match = %d\n", el.toChars(), te.toChars(), m2);
+ if (m2 < result)
+ result = m2;
}
}
+ return result;
+ }
- override void visit(StringExp e)
+ MATCH visitString(StringExp e)
+ {
+ version (none)
{
- version (none)
- {
- printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n", e.toChars(), e.committed, e.type.toChars(), t.toChars());
- }
- if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid)
- return;
+ printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n", e.toChars(), e.committed, e.type.toChars(), t.toChars());
+ }
+ if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid)
+ return MATCH.nomatch;
- if (!(e.type.ty == Tsarray || e.type.ty == Tarray || e.type.ty == Tpointer))
- return visit(cast(Expression)e);
+ if (!(e.type.ty == Tsarray || e.type.ty == Tarray || e.type.ty == Tpointer))
+ return visit(e);
- TY tyn = e.type.nextOf().ty;
+ TY tyn = e.type.nextOf().ty;
- if (!tyn.isSomeChar)
- return visit(cast(Expression)e);
+ if (!tyn.isSomeChar)
+ return visit(e);
- switch (t.ty)
+ switch (t.ty)
+ {
+ case Tsarray:
+ if (e.type.ty == Tsarray)
{
- case Tsarray:
- if (e.type.ty == Tsarray)
+ TY tynto = t.nextOf().ty;
+ if (tynto == tyn)
{
- TY tynto = t.nextOf().ty;
- if (tynto == tyn)
- {
- if (e.type.isTypeSArray().dim.toInteger() == t.isTypeSArray().dim.toInteger())
- {
- result = MATCH.exact;
- }
- return;
- }
- if (tynto.isSomeChar)
- {
- if (e.committed && tynto != tyn)
- return;
- size_t fromlen = e.numberOfCodeUnits(tynto);
- size_t tolen = cast(size_t)t.isTypeSArray().dim.toInteger();
- if (tolen < fromlen)
- return;
- if (tolen != fromlen)
- {
- // implicit length extending
- result = MATCH.convert;
- return;
- }
- }
- if (!e.committed && tynto.isSomeChar)
+ if (e.type.isTypeSArray().dim.toInteger() == t.isTypeSArray().dim.toInteger())
{
- result = MATCH.exact;
- return;
+ return MATCH.exact;
}
+ return MATCH.nomatch;
}
- else if (e.type.ty == Tarray)
+ if (tynto.isSomeChar)
{
- TY tynto = t.nextOf().ty;
- if (tynto.isSomeChar)
- {
- if (e.committed && tynto != tyn)
- return;
- size_t fromlen = e.numberOfCodeUnits(tynto);
- size_t tolen = cast(size_t)t.isTypeSArray().dim.toInteger();
- if (tolen < fromlen)
- return;
- if (tolen != fromlen)
- {
- // implicit length extending
- result = MATCH.convert;
- return;
- }
- }
- if (tynto == tyn)
+ if (e.committed && tynto != tyn)
+ return MATCH.nomatch;
+ size_t fromlen = e.numberOfCodeUnits(tynto);
+ size_t tolen = cast(size_t)t.isTypeSArray().dim.toInteger();
+ if (tolen < fromlen)
+ return MATCH.nomatch;
+ if (tolen != fromlen)
{
- result = MATCH.exact;
- return;
+ // implicit length extending
+ return MATCH.convert;
}
- if (!e.committed && tynto.isSomeChar)
+ }
+ if (!e.committed && tynto.isSomeChar)
+ {
+ return MATCH.exact;
+ }
+ }
+ else if (e.type.ty == Tarray)
+ {
+ TY tynto = t.nextOf().ty;
+ if (tynto.isSomeChar)
+ {
+ if (e.committed && tynto != tyn)
+ return MATCH.nomatch;
+ size_t fromlen = e.numberOfCodeUnits(tynto);
+ size_t tolen = cast(size_t)t.isTypeSArray().dim.toInteger();
+ if (tolen < fromlen)
+ return MATCH.nomatch;
+ if (tolen != fromlen)
{
- result = MATCH.exact;
- return;
+ // implicit length extending
+ return MATCH.convert;
}
}
- goto case; /+ fall through +/
- case Tarray:
- case Tpointer:
- Type tn = t.nextOf();
- MATCH m = MATCH.exact;
- if (e.type.nextOf().mod != tn.mod)
+ if (tynto == tyn)
{
- // https://issues.dlang.org/show_bug.cgi?id=16183
- if (!tn.isConst() && !tn.isImmutable())
- return;
- m = MATCH.constant;
+ return MATCH.exact;
}
- if (!e.committed)
+ if (!e.committed && tynto.isSomeChar)
{
- switch (tn.ty)
+ return MATCH.exact;
+ }
+ }
+ goto case; /+ fall through +/
+ case Tarray:
+ case Tpointer:
+ Type tn = t.nextOf();
+ MATCH m = MATCH.exact;
+ if (e.type.nextOf().mod != tn.mod)
+ {
+ // https://issues.dlang.org/show_bug.cgi?id=16183
+ if (!tn.isConst() && !tn.isImmutable())
+ return MATCH.nomatch;
+ m = MATCH.constant;
+ }
+ if (!e.committed)
+ {
+ switch (tn.ty)
+ {
+ case Tchar:
+ if (e.postfix == 'w' || e.postfix == 'd')
+ m = MATCH.convert;
+ return m;
+ case Twchar:
+ if (e.postfix != 'w')
+ m = MATCH.convert;
+ return m;
+ case Tdchar:
+ if (e.postfix != 'd')
+ m = MATCH.convert;
+ return m;
+ case Tenum:
+ if (tn.isTypeEnum().sym.isSpecial())
{
- case Tchar:
- if (e.postfix == 'w' || e.postfix == 'd')
- m = MATCH.convert;
- result = m;
- return;
- case Twchar:
- if (e.postfix != 'w')
- m = MATCH.convert;
- result = m;
- return;
- case Tdchar:
- if (e.postfix != 'd')
- m = MATCH.convert;
- result = m;
- return;
- case Tenum:
- if (tn.isTypeEnum().sym.isSpecial())
- {
- /* Allow string literal -> const(wchar_t)[]
- */
- if (TypeBasic tob = tn.toBasetype().isTypeBasic())
- result = tn.implicitConvTo(tob);
- return;
- }
- break;
- default:
- break;
+ /* Allow string literal -> const(wchar_t)[]
+ */
+ if (TypeBasic tob = tn.toBasetype().isTypeBasic())
+ return tn.implicitConvTo(tob);
}
+ break;
+ default:
+ break;
}
- break;
-
- default:
- break;
}
+ break;
- visit(cast(Expression)e);
+ default:
+ break;
+ }
+
+ return visit(e);
+ }
+
+ MATCH visitArrayLiteral(ArrayLiteralExp e)
+ {
+ version (none)
+ {
+ printf("ArrayLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
}
+ Type tb = t.toBasetype();
+ Type typeb = e.type.toBasetype();
- override void visit(ArrayLiteralExp e)
+ auto result = MATCH.nomatch;
+ if ((tb.ty == Tarray || tb.ty == Tsarray) &&
+ (typeb.ty == Tarray || typeb.ty == Tsarray))
{
- version (none)
+ result = MATCH.exact;
+ Type typen = typeb.nextOf().toBasetype();
+
+ if (auto tsa = tb.isTypeSArray())
{
- printf("ArrayLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ if (e.elements.dim != tsa.dim.toInteger())
+ result = MATCH.nomatch;
}
- Type tb = t.toBasetype();
- Type typeb = e.type.toBasetype();
- if ((tb.ty == Tarray || tb.ty == Tsarray) &&
- (typeb.ty == Tarray || typeb.ty == Tsarray))
+ Type telement = tb.nextOf();
+ if (!e.elements.dim)
{
- result = MATCH.exact;
- Type typen = typeb.nextOf().toBasetype();
-
- if (auto tsa = tb.isTypeSArray())
- {
- if (e.elements.dim != tsa.dim.toInteger())
- result = MATCH.nomatch;
- }
-
- Type telement = tb.nextOf();
- if (!e.elements.dim)
- {
- if (typen.ty != Tvoid)
- result = typen.implicitConvTo(telement);
- }
- else
- {
- if (e.basis)
- {
- MATCH m = e.basis.implicitConvTo(telement);
- if (m < result)
- result = m;
- }
- for (size_t i = 0; i < e.elements.dim; i++)
- {
- Expression el = (*e.elements)[i];
- if (result == MATCH.nomatch)
- break;
- if (!el)
- continue;
- MATCH m = el.implicitConvTo(telement);
- if (m < result)
- result = m; // remember worst match
- }
- }
-
- if (!result)
- result = e.type.implicitConvTo(t);
-
- return;
+ if (typen.ty != Tvoid)
+ result = typen.implicitConvTo(telement);
}
- else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray))
+ else
{
- result = MATCH.exact;
- // Convert array literal to vector type
- TypeVector tv = tb.isTypeVector();
- TypeSArray tbase = tv.basetype.isTypeSArray();
- assert(tbase);
- const edim = e.elements.dim;
- const tbasedim = tbase.dim.toInteger();
- if (edim > tbasedim)
- {
- result = MATCH.nomatch;
- return;
- }
-
- Type telement = tv.elementType();
- if (edim < tbasedim)
+ if (e.basis)
{
- Expression el = typeb.nextOf.defaultInitLiteral(e.loc);
- MATCH m = el.implicitConvTo(telement);
+ MATCH m = e.basis.implicitConvTo(telement);
if (m < result)
- result = m; // remember worst match
+ result = m;
}
- foreach (el; (*e.elements)[])
+ for (size_t i = 0; i < e.elements.dim; i++)
{
+ Expression el = (*e.elements)[i];
+ if (result == MATCH.nomatch)
+ break;
+ if (!el)
+ continue;
MATCH m = el.implicitConvTo(telement);
if (m < result)
result = m; // remember worst match
- if (result == MATCH.nomatch)
- break; // no need to check for worse
}
- return;
}
- visit(cast(Expression)e);
- }
+ if (!result)
+ result = e.type.implicitConvTo(t);
- override void visit(AssocArrayLiteralExp e)
+ return result;
+ }
+ else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray))
{
- auto taa = t.toBasetype().isTypeAArray();
- Type typeb = e.type.toBasetype();
-
- if (!(taa && typeb.ty == Taarray))
- return visit(cast(Expression)e);
-
result = MATCH.exact;
- foreach (i, el; (*e.keys)[])
+ // Convert array literal to vector type
+ TypeVector tv = tb.isTypeVector();
+ TypeSArray tbase = tv.basetype.isTypeSArray();
+ assert(tbase);
+ const edim = e.elements.dim;
+ const tbasedim = tbase.dim.toInteger();
+ if (edim > tbasedim)
{
- MATCH m = el.implicitConvTo(taa.index);
+ return MATCH.nomatch;
+ }
+
+ Type telement = tv.elementType();
+ if (edim < tbasedim)
+ {
+ Expression el = typeb.nextOf.defaultInitLiteral(e.loc);
+ MATCH m = el.implicitConvTo(telement);
if (m < result)
result = m; // remember worst match
- if (result == MATCH.nomatch)
- break; // no need to check for worse
- el = (*e.values)[i];
- m = el.implicitConvTo(taa.nextOf());
+ }
+ foreach (el; (*e.elements)[])
+ {
+ MATCH m = el.implicitConvTo(telement);
if (m < result)
result = m; // remember worst match
if (result == MATCH.nomatch)
break; // no need to check for worse
}
+ return result;
}
- override void visit(CallExp e)
+ return visit(e);
+ }
+
+ MATCH visitAssocArrayLiteral(AssocArrayLiteralExp e)
+ {
+ auto taa = t.toBasetype().isTypeAArray();
+ Type typeb = e.type.toBasetype();
+
+ if (!(taa && typeb.ty == Taarray))
+ return visit(e);
+
+ auto result = MATCH.exact;
+ foreach (i, el; (*e.keys)[])
{
- enum LOG = false;
- static if (LOG)
- {
- printf("CallExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
- }
+ MATCH m = el.implicitConvTo(taa.index);
+ if (m < result)
+ result = m; // remember worst match
+ if (result == MATCH.nomatch)
+ break; // no need to check for worse
+ el = (*e.values)[i];
+ m = el.implicitConvTo(taa.nextOf());
+ if (m < result)
+ result = m; // remember worst match
+ if (result == MATCH.nomatch)
+ break; // no need to check for worse
+ }
+ return result;
+ }
- visit(cast(Expression)e);
- if (result != MATCH.nomatch)
- return;
+ MATCH visitCall(CallExp e)
+ {
+ enum LOG = false;
+ static if (LOG)
+ {
+ printf("CallExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ }
- /* Allow the result of strongly pure functions to
- * convert to immutable
- */
- if (e.f &&
- // lots of legacy code breaks with the following purity check
- (global.params.useDIP1000 != FeatureState.enabled || e.f.isPure() >= PURE.const_) &&
- e.f.isReturnIsolated() // check isReturnIsolated last, because it is potentially expensive.
- )
- {
- result = e.type.immutableOf().implicitConvTo(t);
- if (result > MATCH.constant) // Match level is MATCH.constant at best.
- result = MATCH.constant;
- return;
- }
+ auto result = visit(e);
+ if (result != MATCH.nomatch)
+ return result;
- /* Conversion is 'const' conversion if:
- * 1. function is pure (weakly pure is ok)
- * 2. implicit conversion only fails because of mod bits
- * 3. each function parameter can be implicitly converted to the mod bits
- */
- auto tf = (e.f ? e.f.type : e.e1.type).toBasetype().isTypeFunction();
- if (!tf)
- return;
+ /* Allow the result of strongly pure functions to
+ * convert to immutable
+ */
+ if (e.f &&
+ // lots of legacy code breaks with the following purity check
+ (global.params.useDIP1000 != FeatureState.enabled || e.f.isPure() >= PURE.const_) &&
+ e.f.isReturnIsolated() // check isReturnIsolated last, because it is potentially expensive.
+ )
+ {
+ result = e.type.immutableOf().implicitConvTo(t);
+ if (result > MATCH.constant) // Match level is MATCH.constant at best.
+ result = MATCH.constant;
+ return result;
+ }
- if (tf.purity == PURE.impure)
- return;
- if (e.f && e.f.isNested())
- return;
+ /* Conversion is 'const' conversion if:
+ * 1. function is pure (weakly pure is ok)
+ * 2. implicit conversion only fails because of mod bits
+ * 3. each function parameter can be implicitly converted to the mod bits
+ */
+ auto tf = (e.f ? e.f.type : e.e1.type).toBasetype().isTypeFunction();
+ if (!tf)
+ return result;
+
+ if (tf.purity == PURE.impure)
+ return result;
+ if (e.f && e.f.isNested())
+ return result;
+
+ /* See if fail only because of mod bits.
+ *
+ * https://issues.dlang.org/show_bug.cgi?id=14155
+ * All pure functions can access global immutable data.
+ * So the returned pointer may refer an immutable global data,
+ * and then the returned pointer that points non-mutable object
+ * cannot be unique pointer.
+ *
+ * Example:
+ * immutable g;
+ * static this() { g = 1; }
+ * const(int*) foo() pure { return &g; }
+ * void test() {
+ * immutable(int*) ip = foo(); // OK
+ * int* mp = foo(); // should be disallowed
+ * }
+ */
+ if (e.type.immutableOf().implicitConvTo(t) < MATCH.constant && e.type.addMod(MODFlags.shared_).implicitConvTo(t) < MATCH.constant && e.type.implicitConvTo(t.addMod(MODFlags.shared_)) < MATCH.constant)
+ {
+ return result;
+ }
+ // Allow a conversion to immutable type, or
+ // conversions of mutable types between thread-local and shared.
- /* See if fail only because of mod bits.
- *
- * https://issues.dlang.org/show_bug.cgi?id=14155
- * All pure functions can access global immutable data.
- * So the returned pointer may refer an immutable global data,
- * and then the returned pointer that points non-mutable object
- * cannot be unique pointer.
- *
- * Example:
- * immutable g;
- * static this() { g = 1; }
- * const(int*) foo() pure { return &g; }
- * void test() {
- * immutable(int*) ip = foo(); // OK
- * int* mp = foo(); // should be disallowed
- * }
- */
- if (e.type.immutableOf().implicitConvTo(t) < MATCH.constant && e.type.addMod(MODFlags.shared_).implicitConvTo(t) < MATCH.constant && e.type.implicitConvTo(t.addMod(MODFlags.shared_)) < MATCH.constant)
- {
- return;
- }
- // Allow a conversion to immutable type, or
- // conversions of mutable types between thread-local and shared.
+ /* Get mod bits of what we're converting to
+ */
+ Type tb = t.toBasetype();
+ MOD mod = tb.mod;
+ if (tf.isref)
+ {
+ }
+ else
+ {
+ if (Type ti = getIndirection(t))
+ mod = ti.mod;
+ }
+ static if (LOG)
+ {
+ printf("mod = x%x\n", mod);
+ }
+ if (mod & MODFlags.wild)
+ return result; // not sure what to do with this
- /* Get mod bits of what we're converting to
- */
- Type tb = t.toBasetype();
- MOD mod = tb.mod;
- if (tf.isref)
- {
- }
- else
- {
- if (Type ti = getIndirection(t))
- mod = ti.mod;
- }
- static if (LOG)
- {
- printf("mod = x%x\n", mod);
- }
- if (mod & MODFlags.wild)
- return; // not sure what to do with this
+ /* Apply mod bits to each function parameter,
+ * and see if we can convert the function argument to the modded type
+ */
- /* Apply mod bits to each function parameter,
- * and see if we can convert the function argument to the modded type
+ size_t nparams = tf.parameterList.length;
+ size_t j = tf.isDstyleVariadic(); // if TypeInfoArray was prepended
+ if (auto dve = e.e1.isDotVarExp())
+ {
+ /* Treat 'this' as just another function argument
*/
-
- size_t nparams = tf.parameterList.length;
- size_t j = tf.isDstyleVariadic(); // if TypeInfoArray was prepended
- if (auto dve = e.e1.isDotVarExp())
+ Type targ = dve.e1.type;
+ if (targ.constConv(targ.castMod(mod)) == MATCH.nomatch)
+ return result;
+ }
+ foreach (const i; j .. e.arguments.dim)
+ {
+ Expression earg = (*e.arguments)[i];
+ Type targ = earg.type.toBasetype();
+ static if (LOG)
{
- /* Treat 'this' as just another function argument
- */
- Type targ = dve.e1.type;
- if (targ.constConv(targ.castMod(mod)) == MATCH.nomatch)
- return;
+ printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
}
- foreach (const i; j .. e.arguments.dim)
+ if (i - j < nparams)
{
- Expression earg = (*e.arguments)[i];
- Type targ = earg.type.toBasetype();
- static if (LOG)
+ Parameter fparam = tf.parameterList[i - j];
+ if (fparam.storageClass & STC.lazy_)
+ return result; // not sure what to do with this
+ Type tparam = fparam.type;
+ if (!tparam)
+ continue;
+ if (fparam.isReference())
{
- printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
+ if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch)
+ return result;
+ continue;
}
- if (i - j < nparams)
- {
- Parameter fparam = tf.parameterList[i - j];
- if (fparam.storageClass & STC.lazy_)
- return; // not sure what to do with this
- Type tparam = fparam.type;
- if (!tparam)
- continue;
- if (fparam.isReference())
- {
- if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch)
- return;
- continue;
- }
- }
- static if (LOG)
- {
- printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
- }
- if (implicitMod(earg, targ, mod) == MATCH.nomatch)
- return;
}
-
- /* Success
- */
- result = MATCH.constant;
+ static if (LOG)
+ {
+ printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
+ }
+ if (implicitMod(earg, targ, mod) == MATCH.nomatch)
+ return result;
}
- override void visit(AddrExp e)
+ /* Success
+ */
+ return MATCH.constant;
+ }
+
+ MATCH visitAddr(AddrExp e)
+ {
+ version (none)
{
- version (none)
- {
- printf("AddrExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
- }
- result = e.type.implicitConvTo(t);
- //printf("\tresult = %d\n", result);
+ printf("AddrExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ }
+ auto result = e.type.implicitConvTo(t);
+ //printf("\tresult = %d\n", result);
- if (result != MATCH.nomatch)
- return;
+ if (result != MATCH.nomatch)
+ return result;
- Type tb = t.toBasetype();
- Type typeb = e.type.toBasetype();
+ Type tb = t.toBasetype();
+ Type typeb = e.type.toBasetype();
- // Look for pointers to functions where the functions are overloaded.
- if (e.e1.op == EXP.overloadSet &&
- (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
+ // Look for pointers to functions where the functions are overloaded.
+ if (e.e1.op == EXP.overloadSet &&
+ (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
+ {
+ OverExp eo = e.e1.isOverExp();
+ FuncDeclaration f = null;
+ foreach (s; eo.vars.a[])
{
- OverExp eo = e.e1.isOverExp();
- FuncDeclaration f = null;
- foreach (s; eo.vars.a[])
+ FuncDeclaration f2 = s.isFuncDeclaration();
+ assert(f2);
+ if (f2.overloadExactMatch(tb.nextOf()))
{
- FuncDeclaration f2 = s.isFuncDeclaration();
- assert(f2);
- if (f2.overloadExactMatch(tb.nextOf()))
+ if (f)
{
- if (f)
- {
- /* Error if match in more than one overload set,
- * even if one is a 'better' match than the other.
- */
- ScopeDsymbol.multiplyDefined(e.loc, f, f2);
- }
- else
- f = f2;
- result = MATCH.exact;
+ /* Error if match in more than one overload set,
+ * even if one is a 'better' match than the other.
+ */
+ ScopeDsymbol.multiplyDefined(e.loc, f, f2);
}
+ else
+ f = f2;
+ result = MATCH.exact;
}
}
+ }
- if (e.e1.op == EXP.variable &&
- typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
- tb.ty == Tpointer && tb.nextOf().ty == Tfunction)
- {
- /* I don't think this can ever happen -
- * it should have been
- * converted to a SymOffExp.
- */
- assert(0);
- }
-
- //printf("\tresult = %d\n", result);
+ if (e.e1.op == EXP.variable &&
+ typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
+ tb.ty == Tpointer && tb.nextOf().ty == Tfunction)
+ {
+ /* I don't think this can ever happen -
+ * it should have been
+ * converted to a SymOffExp.
+ */
+ assert(0);
}
- override void visit(SymOffExp e)
+ //printf("\tresult = %d\n", result);
+ return result;
+ }
+
+ MATCH visitSymOff(SymOffExp e)
+ {
+ version (none)
{
- version (none)
- {
- printf("SymOffExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
- }
- result = e.type.implicitConvTo(t);
- //printf("\tresult = %d\n", result);
- if (result != MATCH.nomatch)
- return;
+ printf("SymOffExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ }
+ auto result = e.type.implicitConvTo(t);
+ //printf("\tresult = %d\n", result);
+ if (result != MATCH.nomatch)
+ return result;
- Type tb = t.toBasetype();
- Type typeb = e.type.toBasetype();
+ Type tb = t.toBasetype();
+ Type typeb = e.type.toBasetype();
- // Look for pointers to functions where the functions are overloaded.
- if (typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
- (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
+ // Look for pointers to functions where the functions are overloaded.
+ if (typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
+ (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
+ {
+ if (FuncDeclaration f = e.var.isFuncDeclaration())
{
- if (FuncDeclaration f = e.var.isFuncDeclaration())
+ f = f.overloadExactMatch(tb.nextOf());
+ if (f)
{
- f = f.overloadExactMatch(tb.nextOf());
- if (f)
+ if ((tb.ty == Tdelegate && (f.needThis() || f.isNested())) ||
+ (tb.ty == Tpointer && !(f.needThis() || f.isNested())))
{
- if ((tb.ty == Tdelegate && (f.needThis() || f.isNested())) ||
- (tb.ty == Tpointer && !(f.needThis() || f.isNested())))
- {
- result = MATCH.exact;
- }
+ result = MATCH.exact;
}
}
}
- //printf("\tresult = %d\n", result);
}
+ //printf("\tresult = %d\n", result);
+ return result;
+ }
- override void visit(DelegateExp e)
+ MATCH visitDelegate(DelegateExp e)
+ {
+ version (none)
{
- version (none)
- {
- printf("DelegateExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
- }
- result = e.type.implicitConvTo(t);
- if (result != MATCH.nomatch)
- return;
+ printf("DelegateExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ }
+ auto result = e.type.implicitConvTo(t);
+ if (result != MATCH.nomatch)
+ return result;
- Type tb = t.toBasetype();
- Type typeb = e.type.toBasetype();
+ Type tb = t.toBasetype();
+ Type typeb = e.type.toBasetype();
- // Look for pointers to functions where the functions are overloaded.
- if (typeb.ty == Tdelegate && tb.ty == Tdelegate)
- {
- if (e.func && e.func.overloadExactMatch(tb.nextOf()))
- result = MATCH.exact;
- }
+ // Look for pointers to functions where the functions are overloaded.
+ if (typeb.ty == Tdelegate && tb.ty == Tdelegate)
+ {
+ if (e.func && e.func.overloadExactMatch(tb.nextOf()))
+ result = MATCH.exact;
}
+ return result;
+ }
- override void visit(FuncExp e)
+ MATCH visitFunc(FuncExp e)
+ {
+ //printf("FuncExp::implicitConvTo type = %p %s, t = %s\n", e.type, e.type ? e.type.toChars() : NULL, t.toChars());
+ MATCH m = e.matchType(t, null, null, 1);
+ if (m > MATCH.nomatch)
{
- //printf("FuncExp::implicitConvTo type = %p %s, t = %s\n", e.type, e.type ? e.type.toChars() : NULL, t.toChars());
- MATCH m = e.matchType(t, null, null, 1);
- if (m > MATCH.nomatch)
- {
- result = m;
- return;
- }
- visit(cast(Expression)e);
+ return m;
}
+ return visit(e);
+ }
- override void visit(AndExp e)
- {
- visit(cast(Expression)e);
- if (result != MATCH.nomatch)
- return;
+ MATCH visitAnd(AndExp e)
+ {
+ auto result = visit(e);
+ if (result != MATCH.nomatch)
+ return result;
- MATCH m1 = e.e1.implicitConvTo(t);
- MATCH m2 = e.e2.implicitConvTo(t);
+ MATCH m1 = e.e1.implicitConvTo(t);
+ MATCH m2 = e.e2.implicitConvTo(t);
- // Pick the worst match
- result = (m1 < m2) ? m1 : m2;
- }
+ // Pick the worst match
+ return (m1 < m2) ? m1 : m2;
+ }
- override void visit(OrExp e)
- {
- visit(cast(Expression)e);
- if (result != MATCH.nomatch)
- return;
+ MATCH visitOr(OrExp e)
+ {
+ auto result = visit(e);
+ if (result != MATCH.nomatch)
+ return result;
- MATCH m1 = e.e1.implicitConvTo(t);
- MATCH m2 = e.e2.implicitConvTo(t);
+ MATCH m1 = e.e1.implicitConvTo(t);
+ MATCH m2 = e.e2.implicitConvTo(t);
- // Pick the worst match
- result = (m1 < m2) ? m1 : m2;
- }
+ // Pick the worst match
+ return (m1 < m2) ? m1 : m2;
+ }
- override void visit(XorExp e)
- {
- visit(cast(Expression)e);
- if (result != MATCH.nomatch)
- return;
+ MATCH visitXor(XorExp e)
+ {
+ auto result = visit(e);
+ if (result != MATCH.nomatch)
+ return result;
- MATCH m1 = e.e1.implicitConvTo(t);
- MATCH m2 = e.e2.implicitConvTo(t);
+ MATCH m1 = e.e1.implicitConvTo(t);
+ MATCH m2 = e.e2.implicitConvTo(t);
- // Pick the worst match
- result = (m1 < m2) ? m1 : m2;
- }
+ // Pick the worst match
+ return (m1 < m2) ? m1 : m2;
+ }
- override void visit(CondExp e)
- {
- MATCH m1 = e.e1.implicitConvTo(t);
- MATCH m2 = e.e2.implicitConvTo(t);
- //printf("CondExp: m1 %d m2 %d\n", m1, m2);
+ MATCH visitCond(CondExp e)
+ {
+ MATCH m1 = e.e1.implicitConvTo(t);
+ MATCH m2 = e.e2.implicitConvTo(t);
+ //printf("CondExp: m1 %d m2 %d\n", m1, m2);
- // Pick the worst match
- result = (m1 < m2) ? m1 : m2;
- }
+ // Pick the worst match
+ return (m1 < m2) ? m1 : m2;
+ }
+
+ MATCH visitComma(CommaExp e)
+ {
+ return e.e2.implicitConvTo(t);
+ }
- override void visit(CommaExp e)
+ MATCH visitCast(CastExp e)
+ {
+ version (none)
{
- e.e2.accept(this);
+ printf("CastExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
}
+ auto result = e.type.implicitConvTo(t);
+ if (result != MATCH.nomatch)
+ return result;
- override void visit(CastExp e)
- {
- version (none)
- {
- printf("CastExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
- }
- result = e.type.implicitConvTo(t);
- if (result != MATCH.nomatch)
- return;
+ if (t.isintegral() && e.e1.type.isintegral() && e.e1.implicitConvTo(t) != MATCH.nomatch)
+ result = MATCH.convert;
+ else
+ result = visit(e);
+ return result;
+ }
- if (t.isintegral() && e.e1.type.isintegral() && e.e1.implicitConvTo(t) != MATCH.nomatch)
- result = MATCH.convert;
- else
- visit(cast(Expression)e);
+ MATCH visitNew(NewExp e)
+ {
+ version (none)
+ {
+ printf("NewExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
}
+ auto result = visit(e);
+ if (result != MATCH.nomatch)
+ return result;
- override void visit(NewExp e)
- {
- version (none)
- {
- printf("NewExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
- }
- visit(cast(Expression)e);
- if (result != MATCH.nomatch)
- return;
+ /* Calling new() is like calling a pure function. We can implicitly convert the
+ * return from new() to t using the same algorithm as in CallExp, with the function
+ * 'arguments' being:
+ * thisexp
+ * arguments
+ * .init
+ * 'member' need to be pure.
+ */
- /* Calling new() is like calling a pure function. We can implicitly convert the
- * return from new() to t using the same algorithm as in CallExp, with the function
- * 'arguments' being:
- * thisexp
- * newargs
- * arguments
- * .init
- * 'member' need to be pure.
- */
+ /* See if fail only because of mod bits
+ */
+ if (e.type.immutableOf().implicitConvTo(t.immutableOf()) == MATCH.nomatch)
+ return MATCH.nomatch;
- /* See if fail only because of mod bits
- */
- if (e.type.immutableOf().implicitConvTo(t.immutableOf()) == MATCH.nomatch)
- return;
+ /* Get mod bits of what we're converting to
+ */
+ Type tb = t.toBasetype();
+ MOD mod = tb.mod;
+ if (Type ti = getIndirection(t))
+ mod = ti.mod;
+ static if (LOG)
+ {
+ printf("mod = x%x\n", mod);
+ }
+ if (mod & MODFlags.wild)
+ return MATCH.nomatch; // not sure what to do with this
- /* Get mod bits of what we're converting to
- */
- Type tb = t.toBasetype();
- MOD mod = tb.mod;
- if (Type ti = getIndirection(t))
- mod = ti.mod;
- static if (LOG)
- {
- printf("mod = x%x\n", mod);
- }
- if (mod & MODFlags.wild)
- return; // not sure what to do with this
+ /* Apply mod bits to each argument,
+ * and see if we can convert the argument to the modded type
+ */
- /* Apply mod bits to each argument,
- * and see if we can convert the argument to the modded type
+ if (e.thisexp)
+ {
+ /* Treat 'this' as just another function argument
*/
+ Type targ = e.thisexp.type;
+ if (targ.constConv(targ.castMod(mod)) == MATCH.nomatch)
+ return MATCH.nomatch;
+ }
+
+ /* Check call to 'member'
+ */
+ if (e.member)
+ {
+ FuncDeclaration fd = e.member;
+ if (fd.errors || fd.type.ty != Tfunction)
+ return MATCH.nomatch; // error
+ TypeFunction tf = fd.type.isTypeFunction();
+ if (tf.purity == PURE.impure)
+ return MATCH.nomatch; // impure
- if (e.thisexp)
+ if (e.type.immutableOf().implicitConvTo(t) < MATCH.constant && e.type.addMod(MODFlags.shared_).implicitConvTo(t) < MATCH.constant && e.type.implicitConvTo(t.addMod(MODFlags.shared_)) < MATCH.constant)
{
- /* Treat 'this' as just another function argument
- */
- Type targ = e.thisexp.type;
- if (targ.constConv(targ.castMod(mod)) == MATCH.nomatch)
- return;
+ return MATCH.nomatch;
}
+ // Allow a conversion to immutable type, or
+ // conversions of mutable types between thread-local and shared.
- /* Check call to 'member'
- */
- if (e.member)
- {
- FuncDeclaration fd = e.member;
- if (fd.errors || fd.type.ty != Tfunction)
- return; // error
- TypeFunction tf = fd.type.isTypeFunction();
- if (tf.purity == PURE.impure)
- return; // impure
+ Expressions* args = e.arguments;
- if (e.type.immutableOf().implicitConvTo(t) < MATCH.constant && e.type.addMod(MODFlags.shared_).implicitConvTo(t) < MATCH.constant && e.type.implicitConvTo(t.addMod(MODFlags.shared_)) < MATCH.constant)
+ size_t nparams = tf.parameterList.length;
+ // if TypeInfoArray was prepended
+ size_t j = tf.isDstyleVariadic();
+ for (size_t i = j; i < e.arguments.dim; ++i)
+ {
+ Expression earg = (*args)[i];
+ Type targ = earg.type.toBasetype();
+ static if (LOG)
{
- return;
+ printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
}
- // Allow a conversion to immutable type, or
- // conversions of mutable types between thread-local and shared.
-
- Expressions* args = e.arguments;
-
- size_t nparams = tf.parameterList.length;
- // if TypeInfoArray was prepended
- size_t j = tf.isDstyleVariadic();
- for (size_t i = j; i < e.arguments.dim; ++i)
+ if (i - j < nparams)
{
- Expression earg = (*args)[i];
- Type targ = earg.type.toBasetype();
- static if (LOG)
- {
- printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
- }
- if (i - j < nparams)
- {
- Parameter fparam = tf.parameterList[i - j];
- if (fparam.storageClass & STC.lazy_)
- return; // not sure what to do with this
- Type tparam = fparam.type;
- if (!tparam)
- continue;
- if (fparam.isReference())
- {
- if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch)
- return;
- continue;
- }
- }
- static if (LOG)
+ Parameter fparam = tf.parameterList[i - j];
+ if (fparam.storageClass & STC.lazy_)
+ return MATCH.nomatch; // not sure what to do with this
+ Type tparam = fparam.type;
+ if (!tparam)
+ continue;
+ if (fparam.isReference())
{
- printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
+ if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch)
+ return MATCH.nomatch;
+ continue;
}
- if (implicitMod(earg, targ, mod) == MATCH.nomatch)
- return;
}
+ static if (LOG)
+ {
+ printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
+ }
+ if (implicitMod(earg, targ, mod) == MATCH.nomatch)
+ return MATCH.nomatch;
}
+ }
- /* If no 'member', then construction is by simple assignment,
- * and just straight check 'arguments'
- */
- if (!e.member && e.arguments)
+ /* If no 'member', then construction is by simple assignment,
+ * and just straight check 'arguments'
+ */
+ if (!e.member && e.arguments)
+ {
+ for (size_t i = 0; i < e.arguments.dim; ++i)
{
- for (size_t i = 0; i < e.arguments.dim; ++i)
+ Expression earg = (*e.arguments)[i];
+ if (!earg) // https://issues.dlang.org/show_bug.cgi?id=14853
+ // if it's on overlapped field
+ continue;
+ Type targ = earg.type.toBasetype();
+ static if (LOG)
{
- Expression earg = (*e.arguments)[i];
- if (!earg) // https://issues.dlang.org/show_bug.cgi?id=14853
- // if it's on overlapped field
- continue;
- Type targ = earg.type.toBasetype();
- static if (LOG)
- {
- printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
- printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
- }
- if (implicitMod(earg, targ, mod) == MATCH.nomatch)
- return;
+ printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
+ printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
}
+ if (implicitMod(earg, targ, mod) == MATCH.nomatch)
+ return MATCH.nomatch;
}
+ }
- /* Consider the .init expression as an argument
+ /* Consider the .init expression as an argument
+ */
+ Type ntb = e.newtype.toBasetype();
+ if (ntb.ty == Tarray)
+ ntb = ntb.nextOf().toBasetype();
+ if (auto ts = ntb.isTypeStruct())
+ {
+ // Don't allow nested structs - uplevel reference may not be convertible
+ StructDeclaration sd = ts.sym;
+ sd.size(e.loc); // resolve any forward references
+ if (sd.isNested())
+ return MATCH.nomatch;
+ }
+ if (ntb.isZeroInit(e.loc))
+ {
+ /* Zeros are implicitly convertible, except for special cases.
*/
- Type ntb = e.newtype.toBasetype();
- if (ntb.ty == Tarray)
- ntb = ntb.nextOf().toBasetype();
- if (auto ts = ntb.isTypeStruct())
- {
- // Don't allow nested structs - uplevel reference may not be convertible
- StructDeclaration sd = ts.sym;
- sd.size(e.loc); // resolve any forward references
- if (sd.isNested())
- return;
- }
- if (ntb.isZeroInit(e.loc))
+ if (auto tc = ntb.isTypeClass())
{
- /* Zeros are implicitly convertible, except for special cases.
+ /* With new() must look at the class instance initializer.
*/
- if (auto tc = ntb.isTypeClass())
- {
- /* With new() must look at the class instance initializer.
- */
- ClassDeclaration cd = tc.sym;
+ ClassDeclaration cd = tc.sym;
- cd.size(e.loc); // resolve any forward references
+ cd.size(e.loc); // resolve any forward references
- if (cd.isNested())
- return; // uplevel reference may not be convertible
+ if (cd.isNested())
+ return MATCH.nomatch; // uplevel reference may not be convertible
- assert(!cd.isInterfaceDeclaration());
+ assert(!cd.isInterfaceDeclaration());
- struct ClassCheck
+ struct ClassCheck
+ {
+ extern (C++) static bool convertible(Expression e, ClassDeclaration cd, MOD mod)
{
- extern (C++) static bool convertible(Expression e, ClassDeclaration cd, MOD mod)
+ for (size_t i = 0; i < cd.fields.dim; i++)
{
- for (size_t i = 0; i < cd.fields.dim; i++)
+ VarDeclaration v = cd.fields[i];
+ Initializer _init = v._init;
+ if (_init)
{
- VarDeclaration v = cd.fields[i];
- Initializer _init = v._init;
- if (_init)
+ if (_init.isVoidInitializer())
{
- if (_init.isVoidInitializer())
- {
- }
- else if (ExpInitializer ei = _init.isExpInitializer())
- {
- // https://issues.dlang.org/show_bug.cgi?id=21319
- // This is to prevent re-analyzing the same expression
- // over and over again.
- if (ei.exp == e)
- return false;
- Type tb = v.type.toBasetype();
- if (implicitMod(ei.exp, tb, mod) == MATCH.nomatch)
- return false;
- }
- else
- {
- /* Enhancement: handle StructInitializer and ArrayInitializer
- */
+ }
+ else if (ExpInitializer ei = _init.isExpInitializer())
+ {
+ // https://issues.dlang.org/show_bug.cgi?id=21319
+ // This is to prevent re-analyzing the same expression
+ // over and over again.
+ if (ei.exp == e)
+ return false;
+ Type tb = v.type.toBasetype();
+ if (implicitMod(ei.exp, tb, mod) == MATCH.nomatch)
return false;
- }
}
- else if (!v.type.isZeroInit(e.loc))
+ else
+ {
+ /* Enhancement: handle StructInitializer and ArrayInitializer
+ */
return false;
+ }
}
- return cd.baseClass ? convertible(e, cd.baseClass, mod) : true;
+ else if (!v.type.isZeroInit(e.loc))
+ return false;
}
+ return cd.baseClass ? convertible(e, cd.baseClass, mod) : true;
}
-
- if (!ClassCheck.convertible(e, cd, mod))
- return;
}
- }
- else
- {
- Expression earg = e.newtype.defaultInitLiteral(e.loc);
- Type targ = e.newtype.toBasetype();
- if (implicitMod(earg, targ, mod) == MATCH.nomatch)
- return;
+ if (!ClassCheck.convertible(e, cd, mod))
+ return MATCH.nomatch;
}
+ }
+ else
+ {
+ Expression earg = e.newtype.defaultInitLiteral(e.loc);
+ Type targ = e.newtype.toBasetype();
- /* Success
- */
- result = MATCH.constant;
+ if (implicitMod(earg, targ, mod) == MATCH.nomatch)
+ return MATCH.nomatch;
}
- override void visit(SliceExp e)
- {
- //printf("SliceExp::implicitConvTo e = %s, type = %s\n", e.toChars(), e.type.toChars());
- visit(cast(Expression)e);
- if (result != MATCH.nomatch)
- return;
+ /* Success
+ */
+ return MATCH.constant;
+ }
- Type tb = t.toBasetype();
- Type typeb = e.type.toBasetype();
+ MATCH visitSlice(SliceExp e)
+ {
+ //printf("SliceExp::implicitConvTo e = %s, type = %s\n", e.toChars(), e.type.toChars());
+ auto result = visit(e);
+ if (result != MATCH.nomatch)
+ return result;
+
+ Type tb = t.toBasetype();
+ Type typeb = e.type.toBasetype();
- if (tb.ty == Tsarray && typeb.ty == Tarray)
+ if (tb.ty == Tsarray && typeb.ty == Tarray)
+ {
+ typeb = toStaticArrayType(e);
+ if (typeb)
{
- typeb = toStaticArrayType(e);
- if (typeb)
- {
- // Try: T[] -> T[dim]
- // (Slice with compile-time known boundaries to static array)
- result = typeb.implicitConvTo(t);
- if (result > MATCH.convert)
- result = MATCH.convert; // match with implicit conversion at most
- }
- return;
+ // Try: T[] -> T[dim]
+ // (Slice with compile-time known boundaries to static array)
+ result = typeb.implicitConvTo(t);
+ if (result > MATCH.convert)
+ result = MATCH.convert; // match with implicit conversion at most
}
+ return result;
+ }
- /* If the only reason it won't convert is because of the mod bits,
- * then test for conversion by seeing if e1 can be converted with those
- * same mod bits.
- */
- Type t1b = e.e1.type.toBasetype();
- if (tb.ty == Tarray && typeb.equivalent(tb))
- {
- Type tbn = tb.nextOf();
- Type tx = null;
+ /* If the only reason it won't convert is because of the mod bits,
+ * then test for conversion by seeing if e1 can be converted with those
+ * same mod bits.
+ */
+ Type t1b = e.e1.type.toBasetype();
+ if (tb.ty == Tarray && typeb.equivalent(tb))
+ {
+ Type tbn = tb.nextOf();
+ Type tx = null;
- /* If e.e1 is dynamic array or pointer, the uniqueness of e.e1
- * is equivalent with the uniqueness of the referred data. And in here
- * we can have arbitrary typed reference for that.
- */
- if (t1b.ty == Tarray)
- tx = tbn.arrayOf();
- if (t1b.ty == Tpointer)
- tx = tbn.pointerTo();
-
- /* If e.e1 is static array, at least it should be an rvalue.
- * If not, e.e1 is a reference, and its uniqueness does not link
- * to the uniqueness of the referred data.
- */
- if (t1b.ty == Tsarray && !e.e1.isLvalue())
- tx = tbn.sarrayOf(t1b.size() / tbn.size());
+ /* If e.e1 is dynamic array or pointer, the uniqueness of e.e1
+ * is equivalent with the uniqueness of the referred data. And in here
+ * we can have arbitrary typed reference for that.
+ */
+ if (t1b.ty == Tarray)
+ tx = tbn.arrayOf();
+ if (t1b.ty == Tpointer)
+ tx = tbn.pointerTo();
+
+ /* If e.e1 is static array, at least it should be an rvalue.
+ * If not, e.e1 is a reference, and its uniqueness does not link
+ * to the uniqueness of the referred data.
+ */
+ if (t1b.ty == Tsarray && !e.e1.isLvalue())
+ tx = tbn.sarrayOf(t1b.size() / tbn.size());
- if (tx)
- {
- result = e.e1.implicitConvTo(tx);
- if (result > MATCH.constant) // Match level is MATCH.constant at best.
- result = MATCH.constant;
- }
+ if (tx)
+ {
+ result = e.e1.implicitConvTo(tx);
+ if (result > MATCH.constant) // Match level is MATCH.constant at best.
+ result = MATCH.constant;
}
-
- // Enhancement 10724
- if (tb.ty == Tpointer && e.e1.op == EXP.string_)
- e.e1.accept(this);
}
- override void visit(TupleExp e)
- {
- result = e.type.implicitConvTo(t);
- if (result != MATCH.nomatch)
- return;
+ // Enhancement 10724
+ if (tb.ty == Tpointer && e.e1.op == EXP.string_)
+ result = e.e1.implicitConvTo(t);
+ return result;
+ }
- /* If target type is a tuple of same length, test conversion of
- * each expression to the corresponding type in the tuple.
- */
- TypeTuple totuple = t.isTypeTuple();
- if (totuple && e.exps.length == totuple.arguments.length)
+ MATCH visitTuple(TupleExp e)
+ {
+ auto result = e.type.implicitConvTo(t);
+ if (result != MATCH.nomatch)
+ return result;
+
+ /* If target type is a tuple of same length, test conversion of
+ * each expression to the corresponding type in the tuple.
+ */
+ TypeTuple totuple = t.isTypeTuple();
+ if (totuple && e.exps.length == totuple.arguments.length)
+ {
+ result = MATCH.exact;
+ foreach (i, ex; *e.exps)
{
- result = MATCH.exact;
- foreach (i, ex; *e.exps)
- {
- auto to = (*totuple.arguments)[i].type;
- MATCH mi = ex.implicitConvTo(to);
- if (mi < result)
- result = mi;
- }
+ auto to = (*totuple.arguments)[i].type;
+ MATCH mi = ex.implicitConvTo(to);
+ if (mi < result)
+ result = mi;
}
}
+ return result;
}
- scope ImplicitConvTo v = new ImplicitConvTo(t);
- e.accept(v);
- return v.result;
+ switch (e.op)
+ {
+ default : return visit(e);
+ case EXP.add : return visitAdd(e.isAddExp());
+ case EXP.min : return visitMin(e.isMinExp());
+ case EXP.int64 : return visitInteger(e.isIntegerExp());
+ case EXP.error : return visitError(e.isErrorExp());
+ case EXP.null_ : return visitNull(e.isNullExp());
+ case EXP.structLiteral : return visitStructLiteral(e.isStructLiteralExp());
+ case EXP.string_ : return visitString(e.isStringExp());
+ case EXP.arrayLiteral : return visitArrayLiteral(e.isArrayLiteralExp());
+ case EXP.assocArrayLiteral: return visitAssocArrayLiteral(e.isAssocArrayLiteralExp());
+ case EXP.call : return visitCall(e.isCallExp());
+ case EXP.address : return visitAddr(e.isAddrExp());
+ case EXP.symbolOffset : return visitSymOff(e.isSymOffExp());
+ case EXP.delegate_ : return visitDelegate(e.isDelegateExp());
+ case EXP.function_ : return visitFunc(e.isFuncExp());
+ case EXP.and : return visitAnd(e.isAndExp());
+ case EXP.or : return visitOr(e.isOrExp());
+ case EXP.xor : return visitXor(e.isXorExp());
+ case EXP.question : return visitCond(e.isCondExp());
+ case EXP.comma : return visitComma(e.isCommaExp());
+ case EXP.cast_ : return visitCast(e.isCastExp());
+ case EXP.new_ : return visitNew(e.isNewExp());
+ case EXP.slice : return visitSlice(e.isSliceExp());
+ case EXP.tuple : return visitTuple(e.isTupleExp());
+ }
}
/**
@@ -1536,1124 +1529,1081 @@ Type toStaticArrayType(SliceExp e)
*/
Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
{
- extern (C++) final class CastTo : Visitor
+ Expression visit(Expression e)
{
- alias visit = Visitor.visit;
- public:
- Type t;
- Scope* sc;
- Expression result;
-
- extern (D) this(Scope* sc, Type t)
+ //printf("Expression::castTo(this=%s, t=%s)\n", e.toChars(), t.toChars());
+ version (none)
{
- this.sc = sc;
- this.t = t;
+ printf("Expression::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
}
-
- override void visit(Expression e)
+ if (e.type.equals(t))
{
- //printf("Expression::castTo(this=%s, t=%s)\n", e.toChars(), t.toChars());
- version (none)
- {
- printf("Expression::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
- }
- if (e.type.equals(t))
- {
- result = e;
- return;
- }
- if (auto ve = e.isVarExp())
+ return e;
+ }
+ if (auto ve = e.isVarExp())
+ {
+ VarDeclaration v = ve.var.isVarDeclaration();
+ if (v && v.storage_class & STC.manifest)
{
- VarDeclaration v = ve.var.isVarDeclaration();
- if (v && v.storage_class & STC.manifest)
- {
- result = e.ctfeInterpret();
- /* https://issues.dlang.org/show_bug.cgi?id=18236
- *
- * The expression returned by ctfeInterpret points
- * to the line where the manifest constant was declared
- * so we need to update the location before trying to cast
- */
- result.loc = e.loc;
- result = result.castTo(sc, t);
- return;
- }
+ auto result = e.ctfeInterpret();
+ /* https://issues.dlang.org/show_bug.cgi?id=18236
+ *
+ * The expression returned by ctfeInterpret points
+ * to the line where the manifest constant was declared
+ * so we need to update the location before trying to cast
+ */
+ result.loc = e.loc;
+ return result.castTo(sc, t);
}
+ }
- Type tob = t.toBasetype();
- Type t1b = e.type.toBasetype();
- if (tob.equals(t1b))
- {
- result = e.copy(); // because of COW for assignment to e.type
- result.type = t;
- return;
- }
+ Type tob = t.toBasetype();
+ Type t1b = e.type.toBasetype();
+ if (tob.equals(t1b))
+ {
+ auto result = e.copy(); // because of COW for assignment to e.type
+ result.type = t;
+ return result;
+ }
- /* Make semantic error against invalid cast between concrete types.
- * Assume that 'e' is never be any placeholder expressions.
- * The result of these checks should be consistent with CastExp::toElem().
- */
+ /* Make semantic error against invalid cast between concrete types.
+ * Assume that 'e' is never be any placeholder expressions.
+ * The result of these checks should be consistent with CastExp::toElem().
+ */
- // Fat Value types
- const(bool) tob_isFV = (tob.ty == Tstruct || tob.ty == Tsarray || tob.ty == Tvector);
- const(bool) t1b_isFV = (t1b.ty == Tstruct || t1b.ty == Tsarray || t1b.ty == Tvector);
+ // Fat Value types
+ const(bool) tob_isFV = (tob.ty == Tstruct || tob.ty == Tsarray || tob.ty == Tvector);
+ const(bool) t1b_isFV = (t1b.ty == Tstruct || t1b.ty == Tsarray || t1b.ty == Tvector);
- // Fat Reference types
- const(bool) tob_isFR = (tob.ty == Tarray || tob.ty == Tdelegate);
- const(bool) t1b_isFR = (t1b.ty == Tarray || t1b.ty == Tdelegate);
+ // Fat Reference types
+ const(bool) tob_isFR = (tob.ty == Tarray || tob.ty == Tdelegate);
+ const(bool) t1b_isFR = (t1b.ty == Tarray || t1b.ty == Tdelegate);
- // Reference types
- const(bool) tob_isR = (tob_isFR || tob.ty == Tpointer || tob.ty == Taarray || tob.ty == Tclass);
- const(bool) t1b_isR = (t1b_isFR || t1b.ty == Tpointer || t1b.ty == Taarray || t1b.ty == Tclass);
+ // Reference types
+ const(bool) tob_isR = (tob_isFR || tob.ty == Tpointer || tob.ty == Taarray || tob.ty == Tclass);
+ const(bool) t1b_isR = (t1b_isFR || t1b.ty == Tpointer || t1b.ty == Taarray || t1b.ty == Tclass);
- // Arithmetic types (== valueable basic types)
- const(bool) tob_isA = ((tob.isintegral() || tob.isfloating()) && tob.ty != Tvector);
- const(bool) t1b_isA = ((t1b.isintegral() || t1b.isfloating()) && t1b.ty != Tvector);
+ // Arithmetic types (== valueable basic types)
+ const(bool) tob_isA = ((tob.isintegral() || tob.isfloating()) && tob.ty != Tvector);
+ const(bool) t1b_isA = ((t1b.isintegral() || t1b.isfloating()) && t1b.ty != Tvector);
- // Try casting the alias this member.
- // Return the expression if it succeeds, null otherwise.
- Expression tryAliasThisCast()
- {
- if (isRecursiveAliasThis(att, t1b))
- return null;
+ // Try casting the alias this member.
+ // Return the expression if it succeeds, null otherwise.
+ Expression tryAliasThisCast()
+ {
+ if (isRecursiveAliasThis(att, t1b))
+ return null;
- /* Forward the cast to our alias this member, rewrite to:
- * cast(to)e1.aliasthis
- */
- auto exp = resolveAliasThis(sc, e);
- const errors = global.startGagging();
- exp = castTo(exp, sc, t, att);
- return global.endGagging(errors) ? null : exp;
- }
+ /* Forward the cast to our alias this member, rewrite to:
+ * cast(to)e1.aliasthis
+ */
+ auto exp = resolveAliasThis(sc, e);
+ const errors = global.startGagging();
+ exp = castTo(exp, sc, t, att);
+ return global.endGagging(errors) ? null : exp;
+ }
- bool hasAliasThis;
- if (AggregateDeclaration t1ad = isAggregate(t1b))
- {
- AggregateDeclaration toad = isAggregate(tob);
- if (t1ad != toad && t1ad.aliasthis)
- {
- if (t1b.ty == Tclass && tob.ty == Tclass)
- {
- ClassDeclaration t1cd = t1b.isClassHandle();
- ClassDeclaration tocd = tob.isClassHandle();
- int offset;
- if (tocd.isBaseOf(t1cd, &offset))
- goto Lok;
- }
- hasAliasThis = true;
- }
- }
- else if (tob.ty == Tvector && t1b.ty != Tvector)
- {
- //printf("test1 e = %s, e.type = %s, tob = %s\n", e.toChars(), e.type.toChars(), tob.toChars());
- TypeVector tv = tob.isTypeVector();
- result = new CastExp(e.loc, e, tv.elementType());
- result = new VectorExp(e.loc, result, tob);
- result = result.expressionSemantic(sc);
- return;
- }
- else if (tob.ty != Tvector && t1b.ty == Tvector)
+ bool hasAliasThis;
+ if (AggregateDeclaration t1ad = isAggregate(t1b))
+ {
+ AggregateDeclaration toad = isAggregate(tob);
+ if (t1ad != toad && t1ad.aliasthis)
{
- // T[n] <-- __vector(U[m])
- if (tob.ty == Tsarray)
+ if (t1b.ty == Tclass && tob.ty == Tclass)
{
- if (t1b.size(e.loc) == tob.size(e.loc))
+ ClassDeclaration t1cd = t1b.isClassHandle();
+ ClassDeclaration tocd = tob.isClassHandle();
+ int offset;
+ if (tocd.isBaseOf(t1cd, &offset))
goto Lok;
}
- goto Lfail;
+ hasAliasThis = true;
}
- else if (t1b.implicitConvTo(tob) == MATCH.constant && t.equals(e.type.constOf()))
+ }
+ else if (tob.ty == Tvector && t1b.ty != Tvector)
+ {
+ //printf("test1 e = %s, e.type = %s, tob = %s\n", e.toChars(), e.type.toChars(), tob.toChars());
+ TypeVector tv = tob.isTypeVector();
+ Expression result = new CastExp(e.loc, e, tv.elementType());
+ result = new VectorExp(e.loc, result, tob);
+ result = result.expressionSemantic(sc);
+ return result;
+ }
+ else if (tob.ty != Tvector && t1b.ty == Tvector)
+ {
+ // T[n] <-- __vector(U[m])
+ if (tob.ty == Tsarray)
{
- result = e.copy();
- result.type = t;
- return;
+ if (t1b.size(e.loc) == tob.size(e.loc))
+ goto Lok;
}
+ goto Lfail;
+ }
+ else if (t1b.implicitConvTo(tob) == MATCH.constant && t.equals(e.type.constOf()))
+ {
+ auto result = e.copy();
+ result.type = t;
+ return result;
+ }
- // arithmetic values vs. other arithmetic values
- // arithmetic values vs. T*
- if (tob_isA && (t1b_isA || t1b.ty == Tpointer) || t1b_isA && (tob_isA || tob.ty == Tpointer))
- {
- goto Lok;
- }
+ // arithmetic values vs. other arithmetic values
+ // arithmetic values vs. T*
+ if (tob_isA && (t1b_isA || t1b.ty == Tpointer) || t1b_isA && (tob_isA || tob.ty == Tpointer))
+ {
+ goto Lok;
+ }
+
+ // arithmetic values vs. references or fat values
+ if (tob_isA && (t1b_isR || t1b_isFV) || t1b_isA && (tob_isR || tob_isFV))
+ {
+ goto Lfail;
+ }
- // arithmetic values vs. references or fat values
- if (tob_isA && (t1b_isR || t1b_isFV) || t1b_isA && (tob_isR || tob_isFV))
+ // Bugzlla 3133: A cast between fat values is possible only when the sizes match.
+ if (tob_isFV && t1b_isFV)
+ {
+ if (hasAliasThis)
{
- goto Lfail;
+ auto result = tryAliasThisCast();
+ if (result)
+ return result;
}
- // Bugzlla 3133: A cast between fat values is possible only when the sizes match.
- if (tob_isFV && t1b_isFV)
- {
- if (hasAliasThis)
- {
- result = tryAliasThisCast();
- if (result)
- return;
- }
+ if (t1b.size(e.loc) == tob.size(e.loc))
+ goto Lok;
- if (t1b.size(e.loc) == tob.size(e.loc))
- goto Lok;
+ auto ts = toAutoQualChars(e.type, t);
+ e.error("cannot cast expression `%s` of type `%s` to `%s` because of different sizes",
+ e.toChars(), ts[0], ts[1]);
+ return ErrorExp.get();
+ }
- auto ts = toAutoQualChars(e.type, t);
- e.error("cannot cast expression `%s` of type `%s` to `%s` because of different sizes",
- e.toChars(), ts[0], ts[1]);
- result = ErrorExp.get();
- return;
+ // Fat values vs. null or references
+ if (tob_isFV && (t1b.ty == Tnull || t1b_isR) || t1b_isFV && (tob.ty == Tnull || tob_isR))
+ {
+ if (tob.ty == Tpointer && t1b.ty == Tsarray)
+ {
+ // T[n] sa;
+ // cast(U*)sa; // ==> cast(U*)sa.ptr;
+ return new AddrExp(e.loc, e, t);
}
-
- // Fat values vs. null or references
- if (tob_isFV && (t1b.ty == Tnull || t1b_isR) || t1b_isFV && (tob.ty == Tnull || tob_isR))
+ if (tob.ty == Tarray && t1b.ty == Tsarray)
{
- if (tob.ty == Tpointer && t1b.ty == Tsarray)
+ // T[n] sa;
+ // cast(U[])sa; // ==> cast(U[])sa[];
+ if (global.params.useDIP1000 == FeatureState.enabled)
{
- // T[n] sa;
- // cast(U*)sa; // ==> cast(U*)sa.ptr;
- result = new AddrExp(e.loc, e, t);
- return;
- }
- if (tob.ty == Tarray && t1b.ty == Tsarray)
- {
- // T[n] sa;
- // cast(U[])sa; // ==> cast(U[])sa[];
- if (global.params.useDIP1000 == FeatureState.enabled)
+ if (auto v = expToVariable(e))
{
- if (auto v = expToVariable(e))
- {
- if (e.type.hasPointers() && !checkAddressVar(sc, e, v))
- goto Lfail;
- }
- }
- const fsize = t1b.nextOf().size();
- const tsize = tob.nextOf().size();
- if (fsize == SIZE_INVALID || tsize == SIZE_INVALID)
- {
- result = ErrorExp.get();
- return;
+ if (e.type.hasPointers() && !checkAddressVar(sc, e, v))
+ goto Lfail;
}
- if (fsize != tsize)
+ }
+ const fsize = t1b.nextOf().size();
+ const tsize = tob.nextOf().size();
+ if (fsize == SIZE_INVALID || tsize == SIZE_INVALID)
+ {
+ return ErrorExp.get();
+ }
+ if (fsize != tsize)
+ {
+ const dim = t1b.isTypeSArray().dim.toInteger();
+ if (tsize == 0 || (dim * fsize) % tsize != 0)
{
- const dim = t1b.isTypeSArray().dim.toInteger();
- if (tsize == 0 || (dim * fsize) % tsize != 0)
- {
- e.error("cannot cast expression `%s` of type `%s` to `%s` since sizes don't line up",
- e.toChars(), e.type.toChars(), t.toChars());
- result = ErrorExp.get();
- return;
- }
+ e.error("cannot cast expression `%s` of type `%s` to `%s` since sizes don't line up",
+ e.toChars(), e.type.toChars(), t.toChars());
+ return ErrorExp.get();
}
- goto Lok;
}
- goto Lfail;
+ goto Lok;
}
+ goto Lfail;
+ }
- /* For references, any reinterpret casts are allowed to same 'ty' type.
- * T* to U*
- * R1 function(P1) to R2 function(P2)
- * R1 delegate(P1) to R2 delegate(P2)
- * T[] to U[]
- * V1[K1] to V2[K2]
- * class/interface A to B (will be a dynamic cast if possible)
- */
- if (tob.ty == t1b.ty && tob_isR && t1b_isR)
- goto Lok;
+ /* For references, any reinterpret casts are allowed to same 'ty' type.
+ * T* to U*
+ * R1 function(P1) to R2 function(P2)
+ * R1 delegate(P1) to R2 delegate(P2)
+ * T[] to U[]
+ * V1[K1] to V2[K2]
+ * class/interface A to B (will be a dynamic cast if possible)
+ */
+ if (tob.ty == t1b.ty && tob_isR && t1b_isR)
+ goto Lok;
- // typeof(null) <-- non-null references or values
- if (tob.ty == Tnull && t1b.ty != Tnull)
- goto Lfail; // https://issues.dlang.org/show_bug.cgi?id=14629
- // typeof(null) --> non-null references or arithmetic values
- if (t1b.ty == Tnull && tob.ty != Tnull)
- goto Lok;
+ // typeof(null) <-- non-null references or values
+ if (tob.ty == Tnull && t1b.ty != Tnull)
+ goto Lfail; // https://issues.dlang.org/show_bug.cgi?id=14629
+ // typeof(null) --> non-null references or arithmetic values
+ if (t1b.ty == Tnull && tob.ty != Tnull)
+ goto Lok;
- // Check size mismatch of references.
- // Tarray and Tdelegate are (void*).sizeof*2, but others have (void*).sizeof.
- if (tob_isFR && t1b_isR || t1b_isFR && tob_isR)
+ // Check size mismatch of references.
+ // Tarray and Tdelegate are (void*).sizeof*2, but others have (void*).sizeof.
+ if (tob_isFR && t1b_isR || t1b_isFR && tob_isR)
+ {
+ if (tob.ty == Tpointer && t1b.ty == Tarray)
{
- if (tob.ty == Tpointer && t1b.ty == Tarray)
- {
- // T[] da;
- // cast(U*)da; // ==> cast(U*)da.ptr;
- goto Lok;
- }
- if (tob.ty == Tpointer && t1b.ty == Tdelegate)
- {
- // void delegate() dg;
- // cast(U*)dg; // ==> cast(U*)dg.ptr;
- // Note that it happens even when U is a Tfunction!
- e.deprecation("casting from %s to %s is deprecated", e.type.toChars(), t.toChars());
- goto Lok;
- }
- goto Lfail;
+ // T[] da;
+ // cast(U*)da; // ==> cast(U*)da.ptr;
+ goto Lok;
}
-
- if (t1b.ty == Tvoid && tob.ty != Tvoid)
+ if (tob.ty == Tpointer && t1b.ty == Tdelegate)
{
- Lfail:
- /* if the cast cannot be performed, maybe there is an alias
- * this that can be used for casting.
- */
- if (hasAliasThis)
- {
- result = tryAliasThisCast();
- if (result)
- return;
- }
- e.error("cannot cast expression `%s` of type `%s` to `%s`", e.toChars(), e.type.toChars(), t.toChars());
- result = ErrorExp.get();
- return;
+ // void delegate() dg;
+ // cast(U*)dg; // ==> cast(U*)dg.ptr;
+ // Note that it happens even when U is a Tfunction!
+ e.deprecation("casting from %s to %s is deprecated", e.type.toChars(), t.toChars());
+ goto Lok;
}
-
- Lok:
- result = new CastExp(e.loc, e, t);
- result.type = t; // Don't call semantic()
- //printf("Returning: %s\n", result.toChars());
+ goto Lfail;
}
- override void visit(ErrorExp e)
+ if (t1b.ty == Tvoid && tob.ty != Tvoid)
{
- result = e;
+ Lfail:
+ /* if the cast cannot be performed, maybe there is an alias
+ * this that can be used for casting.
+ */
+ if (hasAliasThis)
+ {
+ auto result = tryAliasThisCast();
+ if (result)
+ return result;
+ }
+ e.error("cannot cast expression `%s` of type `%s` to `%s`", e.toChars(), e.type.toChars(), t.toChars());
+ return ErrorExp.get();
}
- override void visit(RealExp e)
+ Lok:
+ auto result = new CastExp(e.loc, e, t);
+ result.type = t; // Don't call semantic()
+ //printf("Returning: %s\n", result.toChars());
+ return result;
+ }
+
+ Expression visitError(ErrorExp e)
+ {
+ return e;
+ }
+
+ Expression visitReal(RealExp e)
+ {
+ if (!e.type.equals(t))
{
- if (!e.type.equals(t))
+ if ((e.type.isreal() && t.isreal()) || (e.type.isimaginary() && t.isimaginary()))
{
- if ((e.type.isreal() && t.isreal()) || (e.type.isimaginary() && t.isimaginary()))
- {
- result = e.copy();
- result.type = t;
- }
- else
- visit(cast(Expression)e);
- return;
+ auto result = e.copy();
+ result.type = t;
+ return result;
}
- result = e;
+ else
+ return visit(e);
}
+ return e;
+ }
- override void visit(ComplexExp e)
+ Expression visitComplex(ComplexExp e)
+ {
+ if (!e.type.equals(t))
{
- if (!e.type.equals(t))
+ if (e.type.iscomplex() && t.iscomplex())
{
- if (e.type.iscomplex() && t.iscomplex())
- {
- result = e.copy();
- result.type = t;
- }
- else
- visit(cast(Expression)e);
- return;
+ auto result = e.copy();
+ result.type = t;
+ return result;
}
- result = e;
+ else
+ return visit(e);
+ }
+ return e;
+ }
+
+ Expression visitStructLiteral(StructLiteralExp e)
+ {
+ auto result = visit(e);
+ if (auto sle = result.isStructLiteralExp())
+ sle.stype = t; // commit type
+ return result;
+ }
+
+ Expression visitString(StringExp e)
+ {
+ /* This follows copy-on-write; any changes to 'this'
+ * will result in a copy.
+ * The this.string member is considered immutable.
+ */
+ int copied = 0;
+
+ //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t.toChars(), e.toChars(), e.committed);
+
+ if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid &&
+ (!sc || !(sc.flags & SCOPE.Cfile)))
+ {
+ e.error("cannot convert string literal to `void*`");
+ return ErrorExp.get();
+ }
+
+ StringExp se = e;
+
+ Expression lcast()
+ {
+ auto result = new CastExp(e.loc, se, t);
+ result.type = t; // so semantic() won't be run on e
+ return result;
}
- override void visit(StructLiteralExp e)
+ if (!e.committed)
{
- visit(cast(Expression)e);
- if (auto sle = result.isStructLiteralExp())
- sle.stype = t; // commit type
+ se = e.copy().isStringExp();
+ se.committed = 1;
+ copied = 1;
}
- override void visit(StringExp e)
+ if (e.type.equals(t))
{
- /* This follows copy-on-write; any changes to 'this'
- * will result in a copy.
- * The this.string member is considered immutable.
- */
- int copied = 0;
+ return se;
+ }
+
+ Type tb = t.toBasetype();
+ Type typeb = e.type.toBasetype();
- //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t.toChars(), e.toChars(), e.committed);
+ //printf("\ttype = %s\n", e.type.toChars());
+ if (tb.ty == Tdelegate && typeb.ty != Tdelegate)
+ {
+ return visit(e);
+ }
- if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid &&
- (!sc || !(sc.flags & SCOPE.Cfile)))
+ if (typeb.equals(tb))
+ {
+ if (!copied)
{
- e.error("cannot convert string literal to `void*`");
- result = ErrorExp.get();
- return;
+ se = e.copy().isStringExp();
+ copied = 1;
}
+ se.type = t;
+ return se;
+ }
- StringExp se = e;
+ /* Handle reinterpret casts:
+ * cast(wchar[3])"abcd"c --> [\u6261, \u6463, \u0000]
+ * cast(wchar[2])"abcd"c --> [\u6261, \u6463]
+ * cast(wchar[1])"abcd"c --> [\u6261]
+ * cast(char[4])"a" --> ['a', 0, 0, 0]
+ */
+ if (e.committed && tb.ty == Tsarray && typeb.ty == Tarray)
+ {
+ se = e.copy().isStringExp();
+ d_uns64 szx = tb.nextOf().size();
+ assert(szx <= 255);
+ se.sz = cast(ubyte)szx;
+ se.len = cast(size_t)tb.isTypeSArray().dim.toInteger();
+ se.committed = 1;
+ se.type = t;
- void lcast()
+ /* If larger than source, pad with zeros.
+ */
+ const fullSize = (se.len + 1) * se.sz; // incl. terminating 0
+ if (fullSize > (e.len + 1) * e.sz)
{
- result = new CastExp(e.loc, se, t);
- result.type = t; // so semantic() won't be run on e
+ void* s = mem.xmalloc(fullSize);
+ const srcSize = e.len * e.sz;
+ const data = se.peekData();
+ memcpy(s, data.ptr, srcSize);
+ memset(s + srcSize, 0, fullSize - srcSize);
+ se.setData(s, se.len, se.sz);
}
+ return se;
+ }
- if (!e.committed)
+ if (tb.ty != Tsarray && tb.ty != Tarray && tb.ty != Tpointer)
+ {
+ if (!copied)
{
se = e.copy().isStringExp();
- se.committed = 1;
copied = 1;
}
-
- if (e.type.equals(t))
+ return lcast();
+ }
+ if (typeb.ty != Tsarray && typeb.ty != Tarray && typeb.ty != Tpointer)
+ {
+ if (!copied)
{
- result = se;
- return;
+ se = e.copy().isStringExp();
+ copied = 1;
}
+ return lcast();
+ }
- Type tb = t.toBasetype();
- Type typeb = e.type.toBasetype();
-
- //printf("\ttype = %s\n", e.type.toChars());
- if (tb.ty == Tdelegate && typeb.ty != Tdelegate)
+ const nextSz = typeb.nextOf().size();
+ if (nextSz == SIZE_INVALID)
+ {
+ return ErrorExp.get();
+ }
+ if (nextSz == tb.nextOf().size())
+ {
+ if (!copied)
{
- visit(cast(Expression)e);
- return;
+ se = e.copy().isStringExp();
+ copied = 1;
}
+ if (tb.ty == Tsarray)
+ goto L2; // handle possible change in static array dimension
+ se.type = t;
+ return se;
+ }
+
+ if (e.committed)
+ goto Lcast;
+
+ auto X(T, U)(T tf, U tt)
+ {
+ return (cast(int)tf * 256 + cast(int)tt);
+ }
- if (typeb.equals(tb))
+ {
+ OutBuffer buffer;
+ size_t newlen = 0;
+ int tfty = typeb.nextOf().toBasetype().ty;
+ int ttty = tb.nextOf().toBasetype().ty;
+ switch (X(tfty, ttty))
{
- if (!copied)
+ case X(Tchar, Tchar):
+ case X(Twchar, Twchar):
+ case X(Tdchar, Tdchar):
+ break;
+
+ case X(Tchar, Twchar):
+ for (size_t u = 0; u < e.len;)
{
- se = e.copy().isStringExp();
- copied = 1;
+ dchar c;
+ if (const s = utf_decodeChar(se.peekString(), u, c))
+ e.error("%.*s", cast(int)s.length, s.ptr);
+ else
+ buffer.writeUTF16(c);
}
- se.type = t;
- result = se;
- return;
- }
+ newlen = buffer.length / 2;
+ buffer.writeUTF16(0);
+ goto L1;
- /* Handle reinterpret casts:
- * cast(wchar[3])"abcd"c --> [\u6261, \u6463, \u0000]
- * cast(wchar[2])"abcd"c --> [\u6261, \u6463]
- * cast(wchar[1])"abcd"c --> [\u6261]
- * cast(char[4])"a" --> ['a', 0, 0, 0]
- */
- if (e.committed && tb.ty == Tsarray && typeb.ty == Tarray)
- {
- se = e.copy().isStringExp();
- d_uns64 szx = tb.nextOf().size();
- assert(szx <= 255);
- se.sz = cast(ubyte)szx;
- se.len = cast(size_t)tb.isTypeSArray().dim.toInteger();
- se.committed = 1;
- se.type = t;
-
- /* If larger than source, pad with zeros.
- */
- const fullSize = (se.len + 1) * se.sz; // incl. terminating 0
- if (fullSize > (e.len + 1) * e.sz)
+ case X(Tchar, Tdchar):
+ for (size_t u = 0; u < e.len;)
{
- void* s = mem.xmalloc(fullSize);
- const srcSize = e.len * e.sz;
- const data = se.peekData();
- memcpy(s, data.ptr, srcSize);
- memset(s + srcSize, 0, fullSize - srcSize);
- se.setData(s, se.len, se.sz);
+ dchar c;
+ if (const s = utf_decodeChar(se.peekString(), u, c))
+ e.error("%.*s", cast(int)s.length, s.ptr);
+ buffer.write4(c);
+ newlen++;
}
- result = se;
- return;
- }
+ buffer.write4(0);
+ goto L1;
- if (tb.ty != Tsarray && tb.ty != Tarray && tb.ty != Tpointer)
- {
- if (!copied)
+ case X(Twchar, Tchar):
+ for (size_t u = 0; u < e.len;)
{
- se = e.copy().isStringExp();
- copied = 1;
+ dchar c;
+ if (const s = utf_decodeWchar(se.peekWstring(), u, c))
+ e.error("%.*s", cast(int)s.length, s.ptr);
+ else
+ buffer.writeUTF8(c);
}
- return lcast();
- }
- if (typeb.ty != Tsarray && typeb.ty != Tarray && typeb.ty != Tpointer)
- {
- if (!copied)
+ newlen = buffer.length;
+ buffer.writeUTF8(0);
+ goto L1;
+
+ case X(Twchar, Tdchar):
+ for (size_t u = 0; u < e.len;)
{
- se = e.copy().isStringExp();
- copied = 1;
+ dchar c;
+ if (const s = utf_decodeWchar(se.peekWstring(), u, c))
+ e.error("%.*s", cast(int)s.length, s.ptr);
+ buffer.write4(c);
+ newlen++;
}
- return lcast();
- }
+ buffer.write4(0);
+ goto L1;
- const nextSz = typeb.nextOf().size();
- if (nextSz == SIZE_INVALID)
- {
- result = ErrorExp.get();
- return;
- }
- if (nextSz == tb.nextOf().size())
- {
- if (!copied)
+ case X(Tdchar, Tchar):
+ for (size_t u = 0; u < e.len; u++)
{
- se = e.copy().isStringExp();
- copied = 1;
+ uint c = se.peekDstring()[u];
+ if (!utf_isValidDchar(c))
+ e.error("invalid UCS-32 char \\U%08x", c);
+ else
+ buffer.writeUTF8(c);
+ newlen++;
}
- if (tb.ty == Tsarray)
- goto L2; // handle possible change in static array dimension
- se.type = t;
- result = se;
- return;
- }
-
- if (e.committed)
- goto Lcast;
+ newlen = buffer.length;
+ buffer.writeUTF8(0);
+ goto L1;
- auto X(T, U)(T tf, U tt)
- {
- return (cast(int)tf * 256 + cast(int)tt);
- }
-
- {
- OutBuffer buffer;
- size_t newlen = 0;
- int tfty = typeb.nextOf().toBasetype().ty;
- int ttty = tb.nextOf().toBasetype().ty;
- switch (X(tfty, ttty))
+ case X(Tdchar, Twchar):
+ for (size_t u = 0; u < e.len; u++)
{
- case X(Tchar, Tchar):
- case X(Twchar, Twchar):
- case X(Tdchar, Tdchar):
- break;
-
- case X(Tchar, Twchar):
- for (size_t u = 0; u < e.len;)
- {
- dchar c;
- if (const s = utf_decodeChar(se.peekString(), u, c))
- e.error("%.*s", cast(int)s.length, s.ptr);
- else
- buffer.writeUTF16(c);
- }
- newlen = buffer.length / 2;
- buffer.writeUTF16(0);
- goto L1;
-
- case X(Tchar, Tdchar):
- for (size_t u = 0; u < e.len;)
- {
- dchar c;
- if (const s = utf_decodeChar(se.peekString(), u, c))
- e.error("%.*s", cast(int)s.length, s.ptr);
- buffer.write4(c);
- newlen++;
- }
- buffer.write4(0);
- goto L1;
-
- case X(Twchar, Tchar):
- for (size_t u = 0; u < e.len;)
- {
- dchar c;
- if (const s = utf_decodeWchar(se.peekWstring(), u, c))
- e.error("%.*s", cast(int)s.length, s.ptr);
- else
- buffer.writeUTF8(c);
- }
- newlen = buffer.length;
- buffer.writeUTF8(0);
- goto L1;
-
- case X(Twchar, Tdchar):
- for (size_t u = 0; u < e.len;)
- {
- dchar c;
- if (const s = utf_decodeWchar(se.peekWstring(), u, c))
- e.error("%.*s", cast(int)s.length, s.ptr);
- buffer.write4(c);
- newlen++;
- }
- buffer.write4(0);
- goto L1;
-
- case X(Tdchar, Tchar):
- for (size_t u = 0; u < e.len; u++)
- {
- uint c = se.peekDstring()[u];
- if (!utf_isValidDchar(c))
- e.error("invalid UCS-32 char \\U%08x", c);
- else
- buffer.writeUTF8(c);
- newlen++;
- }
- newlen = buffer.length;
- buffer.writeUTF8(0);
- goto L1;
-
- case X(Tdchar, Twchar):
- for (size_t u = 0; u < e.len; u++)
- {
- uint c = se.peekDstring()[u];
- if (!utf_isValidDchar(c))
- e.error("invalid UCS-32 char \\U%08x", c);
- else
- buffer.writeUTF16(c);
- newlen++;
- }
- newlen = buffer.length / 2;
- buffer.writeUTF16(0);
- goto L1;
-
- L1:
- if (!copied)
- {
- se = e.copy().isStringExp();
- copied = 1;
- }
-
- {
- d_uns64 szx = tb.nextOf().size();
- assert(szx <= 255);
- se.setData(buffer.extractSlice().ptr, newlen, cast(ubyte)szx);
- }
- break;
-
- default:
- assert(typeb.nextOf().size() != tb.nextOf().size());
- goto Lcast;
+ uint c = se.peekDstring()[u];
+ if (!utf_isValidDchar(c))
+ e.error("invalid UCS-32 char \\U%08x", c);
+ else
+ buffer.writeUTF16(c);
+ newlen++;
}
- }
- L2:
- assert(copied);
+ newlen = buffer.length / 2;
+ buffer.writeUTF16(0);
+ goto L1;
- // See if need to truncate or extend the literal
- if (auto tsa = tb.isTypeSArray())
- {
- size_t dim2 = cast(size_t)tsa.dim.toInteger();
- //printf("dim from = %d, to = %d\n", (int)se.len, (int)dim2);
+ L1:
+ if (!copied)
+ {
+ se = e.copy().isStringExp();
+ copied = 1;
+ }
- // Changing dimensions
- if (dim2 != se.len)
{
- // Copy when changing the string literal
- const newsz = se.sz;
- const d = (dim2 < se.len) ? dim2 : se.len;
- void* s = mem.xmalloc((dim2 + 1) * newsz);
- memcpy(s, se.peekData().ptr, d * newsz);
- // Extend with 0, add terminating 0
- memset(s + d * newsz, 0, (dim2 + 1 - d) * newsz);
- se.setData(s, dim2, newsz);
+ d_uns64 szx = tb.nextOf().size();
+ assert(szx <= 255);
+ se.setData(buffer.extractSlice().ptr, newlen, cast(ubyte)szx);
}
- }
- se.type = t;
- result = se;
- return;
+ break;
- Lcast:
- result = new CastExp(e.loc, se, t);
- result.type = t; // so semantic() won't be run on e
+ default:
+ assert(typeb.nextOf().size() != tb.nextOf().size());
+ goto Lcast;
+ }
}
+ L2:
+ assert(copied);
- override void visit(AddrExp e)
+ // See if need to truncate or extend the literal
+ if (auto tsa = tb.isTypeSArray())
{
- version (none)
+ size_t dim2 = cast(size_t)tsa.dim.toInteger();
+ //printf("dim from = %d, to = %d\n", (int)se.len, (int)dim2);
+
+ // Changing dimensions
+ if (dim2 != se.len)
{
- printf("AddrExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ // Copy when changing the string literal
+ const newsz = se.sz;
+ const d = (dim2 < se.len) ? dim2 : se.len;
+ void* s = mem.xmalloc((dim2 + 1) * newsz);
+ memcpy(s, se.peekData().ptr, d * newsz);
+ // Extend with 0, add terminating 0
+ memset(s + d * newsz, 0, (dim2 + 1 - d) * newsz);
+ se.setData(s, dim2, newsz);
}
- result = e;
+ }
+ se.type = t;
+ return se;
- Type tb = t.toBasetype();
- Type typeb = e.type.toBasetype();
+ Lcast:
+ auto result = new CastExp(e.loc, se, t);
+ result.type = t; // so semantic() won't be run on e
+ return result;
+ }
- if (tb.equals(typeb))
- {
- result = e.copy();
- result.type = t;
- return;
- }
+ Expression visitAddr(AddrExp e)
+ {
+ version (none)
+ {
+ printf("AddrExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ }
+ Type tb = t.toBasetype();
+ Type typeb = e.type.toBasetype();
- // Look for pointers to functions where the functions are overloaded.
- if (e.e1.isOverExp() &&
- (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
- {
- OverExp eo = e.e1.isOverExp();
- FuncDeclaration f = null;
- for (size_t i = 0; i < eo.vars.a.dim; i++)
- {
- auto s = eo.vars.a[i];
- auto f2 = s.isFuncDeclaration();
- assert(f2);
- if (f2.overloadExactMatch(tb.nextOf()))
- {
- if (f)
- {
- /* Error if match in more than one overload set,
- * even if one is a 'better' match than the other.
- */
- ScopeDsymbol.multiplyDefined(e.loc, f, f2);
- }
- else
- f = f2;
- }
- }
- if (f)
- {
- f.tookAddressOf++;
- auto se = new SymOffExp(e.loc, f, 0, false);
- auto se2 = se.expressionSemantic(sc);
- // Let SymOffExp::castTo() do the heavy lifting
- visit(se2);
- return;
- }
- }
+ if (tb.equals(typeb))
+ {
+ auto result = e.copy();
+ result.type = t;
+ return result;
+ }
- if (e.e1.isVarExp() &&
- typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
- tb.ty == Tpointer && tb.nextOf().ty == Tfunction)
+ // Look for pointers to functions where the functions are overloaded.
+ if (e.e1.isOverExp() &&
+ (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
+ {
+ OverExp eo = e.e1.isOverExp();
+ FuncDeclaration f = null;
+ for (size_t i = 0; i < eo.vars.a.dim; i++)
{
- auto ve = e.e1.isVarExp();
- auto f = ve.var.isFuncDeclaration();
- if (f)
+ auto s = eo.vars.a[i];
+ auto f2 = s.isFuncDeclaration();
+ assert(f2);
+ if (f2.overloadExactMatch(tb.nextOf()))
{
- assert(f.isImportedSymbol());
- f = f.overloadExactMatch(tb.nextOf());
if (f)
{
- result = new VarExp(e.loc, f, false);
- result.type = f.type;
- result = new AddrExp(e.loc, result, t);
- return;
+ /* Error if match in more than one overload set,
+ * even if one is a 'better' match than the other.
+ */
+ ScopeDsymbol.multiplyDefined(e.loc, f, f2);
}
+ else
+ f = f2;
}
}
+ if (f)
+ {
+ f.tookAddressOf++;
+ auto se = new SymOffExp(e.loc, f, 0, false);
+ auto se2 = se.expressionSemantic(sc);
+ // Let SymOffExp::castTo() do the heavy lifting
+ return visit(se2);
+ }
+ }
- if (auto f = isFuncAddress(e))
+ if (e.e1.isVarExp() &&
+ typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
+ tb.ty == Tpointer && tb.nextOf().ty == Tfunction)
+ {
+ auto ve = e.e1.isVarExp();
+ auto f = ve.var.isFuncDeclaration();
+ if (f)
{
- if (f.checkForwardRef(e.loc))
+ assert(f.isImportedSymbol());
+ f = f.overloadExactMatch(tb.nextOf());
+ if (f)
{
- result = ErrorExp.get();
- return;
+ Expression result = new VarExp(e.loc, f, false);
+ result.type = f.type;
+ result = new AddrExp(e.loc, result, t);
+ return result;
}
}
-
- visit(cast(Expression)e);
}
- override void visit(TupleExp e)
+ if (auto f = isFuncAddress(e))
{
- if (e.type.equals(t))
+ if (f.checkForwardRef(e.loc))
{
- result = e;
- return;
+ return ErrorExp.get();
}
+ }
- /* If target type is a tuple of same length, cast each expression to
- * the corresponding type in the tuple.
- */
- TypeTuple totuple;
- if (auto tt = t.isTypeTuple())
- totuple = e.exps.length == tt.arguments.length ? tt : null;
-
- TupleExp te = e.copy().isTupleExp();
- te.e0 = e.e0 ? e.e0.copy() : null;
- te.exps = e.exps.copy();
- for (size_t i = 0; i < te.exps.dim; i++)
- {
- Expression ex = (*te.exps)[i];
- ex = ex.castTo(sc, totuple ? (*totuple.arguments)[i].type : t);
- (*te.exps)[i] = ex;
- }
- if (totuple)
- te.type = totuple;
- result = te;
-
- /* Questionable behavior: In here, result.type is not set to t
- * if target type is not a tuple of same length.
- * Therefoe:
- * TypeTuple!(int, int) values;
- * auto values2 = cast(long)values;
- * // typeof(values2) == TypeTuple!(int, int) !!
- *
- * Only when the casted tuple is immediately expanded, it would work.
- * auto arr = [cast(long)values];
- * // typeof(arr) == long[]
- */
+ return visit(e);
+ }
+
+ Expression visitTuple(TupleExp e)
+ {
+ if (e.type.equals(t))
+ {
+ return e;
}
- override void visit(ArrayLiteralExp e)
+ /* If target type is a tuple of same length, cast each expression to
+ * the corresponding type in the tuple.
+ */
+ TypeTuple totuple;
+ if (auto tt = t.isTypeTuple())
+ totuple = e.exps.length == tt.arguments.length ? tt : null;
+
+ TupleExp te = e.copy().isTupleExp();
+ te.e0 = e.e0 ? e.e0.copy() : null;
+ te.exps = e.exps.copy();
+ for (size_t i = 0; i < te.exps.dim; i++)
+ {
+ Expression ex = (*te.exps)[i];
+ ex = ex.castTo(sc, totuple ? (*totuple.arguments)[i].type : t);
+ (*te.exps)[i] = ex;
+ }
+ if (totuple)
+ te.type = totuple;
+ return te;
+
+ /* Questionable behavior: In here, result.type is not set to t
+ * if target type is not a tuple of same length.
+ * Therefoe:
+ * TypeTuple!(int, int) values;
+ * auto values2 = cast(long)values;
+ * // typeof(values2) == TypeTuple!(int, int) !!
+ *
+ * Only when the casted tuple is immediately expanded, it would work.
+ * auto arr = [cast(long)values];
+ * // typeof(arr) == long[]
+ */
+ }
+
+ Expression visitArrayLiteral(ArrayLiteralExp e)
+ {
+ version (none)
{
- version (none)
- {
- printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", e.toChars(), e.type.toChars(), t.toChars());
- }
+ printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ }
- ArrayLiteralExp ae = e;
+ ArrayLiteralExp ae = e;
- Type tb = t.toBasetype();
- if (tb.ty == Tarray && global.params.useDIP1000 == FeatureState.enabled)
+ Type tb = t.toBasetype();
+ if (tb.ty == Tarray && global.params.useDIP1000 == FeatureState.enabled)
+ {
+ if (checkArrayLiteralEscape(sc, ae, false))
{
- if (checkArrayLiteralEscape(sc, ae, false))
- {
- result = ErrorExp.get();
- return;
- }
+ return ErrorExp.get();
}
+ }
+
+ if (e.type == t)
+ {
+ return e;
+ }
+ Type typeb = e.type.toBasetype();
- if (e.type == t)
+ if ((tb.ty == Tarray || tb.ty == Tsarray) &&
+ (typeb.ty == Tarray || typeb.ty == Tsarray))
+ {
+ if (tb.nextOf().toBasetype().ty == Tvoid && typeb.nextOf().toBasetype().ty != Tvoid)
{
- result = e;
- return;
+ // Don't do anything to cast non-void[] to void[]
}
- Type typeb = e.type.toBasetype();
-
- if ((tb.ty == Tarray || tb.ty == Tsarray) &&
- (typeb.ty == Tarray || typeb.ty == Tsarray))
+ else if (typeb.ty == Tsarray && typeb.nextOf().toBasetype().ty == Tvoid)
{
- if (tb.nextOf().toBasetype().ty == Tvoid && typeb.nextOf().toBasetype().ty != Tvoid)
- {
- // Don't do anything to cast non-void[] to void[]
- }
- else if (typeb.ty == Tsarray && typeb.nextOf().toBasetype().ty == Tvoid)
- {
- // Don't do anything for casting void[n] to others
- }
- else
- {
- if (auto tsa = tb.isTypeSArray())
- {
- if (e.elements.dim != tsa.dim.toInteger())
- goto L1;
- }
-
- ae = e.copy().isArrayLiteralExp();
- if (e.basis)
- ae.basis = e.basis.castTo(sc, tb.nextOf());
- ae.elements = e.elements.copy();
- for (size_t i = 0; i < e.elements.dim; i++)
- {
- Expression ex = (*e.elements)[i];
- if (!ex)
- continue;
- ex = ex.castTo(sc, tb.nextOf());
- (*ae.elements)[i] = ex;
- }
- ae.type = t;
- result = ae;
- return;
- }
+ // Don't do anything for casting void[n] to others
}
- else if (tb.ty == Tpointer && typeb.ty == Tsarray)
+ else
{
- Type tp = typeb.nextOf().pointerTo();
- if (!tp.equals(ae.type))
+ if (auto tsa = tb.isTypeSArray())
{
- ae = e.copy().isArrayLiteralExp();
- ae.type = tp;
+ if (e.elements.dim != tsa.dim.toInteger())
+ goto L1;
}
- }
- else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray))
- {
- // Convert array literal to vector type
- TypeVector tv = tb.isTypeVector();
- TypeSArray tbase = tv.basetype.isTypeSArray();
- assert(tbase.ty == Tsarray);
- const edim = e.elements.dim;
- const tbasedim = tbase.dim.toInteger();
- if (edim > tbasedim)
- goto L1;
ae = e.copy().isArrayLiteralExp();
- ae.type = tbase; // https://issues.dlang.org/show_bug.cgi?id=12642
+ if (e.basis)
+ ae.basis = e.basis.castTo(sc, tb.nextOf());
ae.elements = e.elements.copy();
- Type telement = tv.elementType();
- foreach (i; 0 .. edim)
+ for (size_t i = 0; i < e.elements.dim; i++)
{
Expression ex = (*e.elements)[i];
- ex = ex.castTo(sc, telement);
- (*ae.elements)[i] = ex;
- }
- // Fill in the rest with the default initializer
- ae.elements.setDim(cast(size_t)tbasedim);
- foreach (i; edim .. cast(size_t)tbasedim)
- {
- Expression ex = typeb.nextOf.defaultInitLiteral(e.loc);
- ex = ex.castTo(sc, telement);
+ if (!ex)
+ continue;
+ ex = ex.castTo(sc, tb.nextOf());
(*ae.elements)[i] = ex;
}
- Expression ev = new VectorExp(e.loc, ae, tb);
- ev = ev.expressionSemantic(sc);
- result = ev;
- return;
+ ae.type = t;
+ return ae;
}
- L1:
- visit(cast(Expression)ae);
}
-
- override void visit(AssocArrayLiteralExp e)
+ else if (tb.ty == Tpointer && typeb.ty == Tsarray)
{
- //printf("AssocArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", e.toChars(), e.type.toChars(), t.toChars());
- if (e.type == t)
- {
- result = e;
- return;
- }
-
- Type tb = t.toBasetype();
- Type typeb = e.type.toBasetype();
-
- if (tb.ty == Taarray && typeb.ty == Taarray &&
- tb.nextOf().toBasetype().ty != Tvoid)
+ Type tp = typeb.nextOf().pointerTo();
+ if (!tp.equals(ae.type))
{
- AssocArrayLiteralExp ae = e.copy().isAssocArrayLiteralExp();
- ae.keys = e.keys.copy();
- ae.values = e.values.copy();
- assert(e.keys.dim == e.values.dim);
- for (size_t i = 0; i < e.keys.dim; i++)
- {
- Expression ex = (*e.values)[i];
- ex = ex.castTo(sc, tb.nextOf());
- (*ae.values)[i] = ex;
-
- ex = (*e.keys)[i];
- ex = ex.castTo(sc, tb.isTypeAArray().index);
- (*ae.keys)[i] = ex;
- }
- ae.type = t;
- result = ae;
- return;
+ ae = e.copy().isArrayLiteralExp();
+ ae.type = tp;
}
- visit(cast(Expression)e);
}
-
- override void visit(SymOffExp e)
+ else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray))
{
- version (none)
+ // Convert array literal to vector type
+ TypeVector tv = tb.isTypeVector();
+ TypeSArray tbase = tv.basetype.isTypeSArray();
+ assert(tbase.ty == Tsarray);
+ const edim = e.elements.dim;
+ const tbasedim = tbase.dim.toInteger();
+ if (edim > tbasedim)
+ goto L1;
+
+ ae = e.copy().isArrayLiteralExp();
+ ae.type = tbase; // https://issues.dlang.org/show_bug.cgi?id=12642
+ ae.elements = e.elements.copy();
+ Type telement = tv.elementType();
+ foreach (i; 0 .. edim)
{
- printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ Expression ex = (*e.elements)[i];
+ ex = ex.castTo(sc, telement);
+ (*ae.elements)[i] = ex;
}
- if (e.type == t && !e.hasOverloads)
+ // Fill in the rest with the default initializer
+ ae.elements.setDim(cast(size_t)tbasedim);
+ foreach (i; edim .. cast(size_t)tbasedim)
{
- result = e;
- return;
+ Expression ex = typeb.nextOf.defaultInitLiteral(e.loc);
+ ex = ex.castTo(sc, telement);
+ (*ae.elements)[i] = ex;
}
+ Expression ev = new VectorExp(e.loc, ae, tb);
+ ev = ev.expressionSemantic(sc);
+ return ev;
+ }
+ L1:
+ return visit(ae);
+ }
+
+ Expression visitAssocArrayLiteral(AssocArrayLiteralExp e)
+ {
+ //printf("AssocArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ if (e.type == t)
+ {
+ return e;
+ }
- Type tb = t.toBasetype();
- Type typeb = e.type.toBasetype();
+ Type tb = t.toBasetype();
+ Type typeb = e.type.toBasetype();
- if (tb.equals(typeb))
+ if (tb.ty == Taarray && typeb.ty == Taarray &&
+ tb.nextOf().toBasetype().ty != Tvoid)
+ {
+ AssocArrayLiteralExp ae = e.copy().isAssocArrayLiteralExp();
+ ae.keys = e.keys.copy();
+ ae.values = e.values.copy();
+ assert(e.keys.dim == e.values.dim);
+ for (size_t i = 0; i < e.keys.dim; i++)
{
- result = e.copy();
- result.type = t;
- result.isSymOffExp().hasOverloads = false;
- return;
+ Expression ex = (*e.values)[i];
+ ex = ex.castTo(sc, tb.nextOf());
+ (*ae.values)[i] = ex;
+
+ ex = (*e.keys)[i];
+ ex = ex.castTo(sc, tb.isTypeAArray().index);
+ (*ae.keys)[i] = ex;
}
+ ae.type = t;
+ return ae;
+ }
+ return visit(e);
+ }
+
+ Expression visitSymOff(SymOffExp e)
+ {
+ version (none)
+ {
+ printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ }
+ if (e.type == t && !e.hasOverloads)
+ {
+ return e;
+ }
+
+ Type tb = t.toBasetype();
+ Type typeb = e.type.toBasetype();
- // Look for pointers to functions where the functions are overloaded.
- if (e.hasOverloads &&
- typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
- (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
+ if (tb.equals(typeb))
+ {
+ auto result = e.copy();
+ result.type = t;
+ result.isSymOffExp().hasOverloads = false;
+ return result;
+ }
+
+ // Look for pointers to functions where the functions are overloaded.
+ if (e.hasOverloads &&
+ typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
+ (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
+ {
+ FuncDeclaration f = e.var.isFuncDeclaration();
+ f = f ? f.overloadExactMatch(tb.nextOf()) : null;
+ if (f)
{
- FuncDeclaration f = e.var.isFuncDeclaration();
- f = f ? f.overloadExactMatch(tb.nextOf()) : null;
- if (f)
+ Expression result;
+ if (tb.ty == Tdelegate)
{
- if (tb.ty == Tdelegate)
+ if (f.needThis() && hasThis(sc))
{
- if (f.needThis() && hasThis(sc))
- {
- result = new DelegateExp(e.loc, new ThisExp(e.loc), f, false);
- result = result.expressionSemantic(sc);
- }
- else if (f.needThis())
- {
- e.error("no `this` to create delegate for `%s`", f.toChars());
- result = ErrorExp.get();
- return;
- }
- else if (f.isNested())
- {
- result = new DelegateExp(e.loc, IntegerExp.literal!0, f, false);
- result = result.expressionSemantic(sc);
- }
- else
- {
- e.error("cannot cast from function pointer to delegate");
- result = ErrorExp.get();
- return;
- }
+ result = new DelegateExp(e.loc, new ThisExp(e.loc), f, false);
+ result = result.expressionSemantic(sc);
+ }
+ else if (f.needThis())
+ {
+ e.error("no `this` to create delegate for `%s`", f.toChars());
+ return ErrorExp.get();
+ }
+ else if (f.isNested())
+ {
+ result = new DelegateExp(e.loc, IntegerExp.literal!0, f, false);
+ result = result.expressionSemantic(sc);
}
else
{
- result = new SymOffExp(e.loc, f, 0, false);
- result.type = t;
+ e.error("cannot cast from function pointer to delegate");
+ return ErrorExp.get();
}
- f.tookAddressOf++;
- return;
}
- }
-
- if (auto f = isFuncAddress(e))
- {
- if (f.checkForwardRef(e.loc))
+ else
{
- result = ErrorExp.get();
- return;
+ result = new SymOffExp(e.loc, f, 0, false);
+ result.type = t;
}
+ f.tookAddressOf++;
+ return result;
}
-
- visit(cast(Expression)e);
}
- override void visit(DelegateExp e)
+ if (auto f = isFuncAddress(e))
{
- version (none)
+ if (f.checkForwardRef(e.loc))
{
- printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ return ErrorExp.get();
}
- __gshared const(char)* msg = "cannot form delegate due to covariant return type";
+ }
- Type tb = t.toBasetype();
- Type typeb = e.type.toBasetype();
+ return visit(e);
+ }
- if (tb.equals(typeb) && !e.hasOverloads)
- {
- int offset;
- e.func.tookAddressOf++;
- if (e.func.tintro && e.func.tintro.nextOf().isBaseOf(e.func.type.nextOf(), &offset) && offset)
- e.error("%s", msg);
- result = e.copy();
- result.type = t;
- return;
- }
+ Expression visitDelegate(DelegateExp e)
+ {
+ version (none)
+ {
+ printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
+ }
+ __gshared const(char)* msg = "cannot form delegate due to covariant return type";
- // Look for delegates to functions where the functions are overloaded.
- if (typeb.ty == Tdelegate && tb.ty == Tdelegate)
- {
- if (e.func)
- {
- auto f = e.func.overloadExactMatch(tb.nextOf());
- if (f)
- {
- int offset;
- if (f.tintro && f.tintro.nextOf().isBaseOf(f.type.nextOf(), &offset) && offset)
- e.error("%s", msg);
- if (f != e.func) // if address not already marked as taken
- f.tookAddressOf++;
- result = new DelegateExp(e.loc, e.e1, f, false, e.vthis2);
- result.type = t;
- return;
- }
- if (e.func.tintro)
- e.error("%s", msg);
- }
- }
+ Type tb = t.toBasetype();
+ Type typeb = e.type.toBasetype();
+
+ if (tb.equals(typeb) && !e.hasOverloads)
+ {
+ int offset;
+ e.func.tookAddressOf++;
+ if (e.func.tintro && e.func.tintro.nextOf().isBaseOf(e.func.type.nextOf(), &offset) && offset)
+ e.error("%s", msg);
+ auto result = e.copy();
+ result.type = t;
+ return result;
+ }
- if (auto f = isFuncAddress(e))
+ // Look for delegates to functions where the functions are overloaded.
+ if (typeb.ty == Tdelegate && tb.ty == Tdelegate)
+ {
+ if (e.func)
{
- if (f.checkForwardRef(e.loc))
+ auto f = e.func.overloadExactMatch(tb.nextOf());
+ if (f)
{
- result = ErrorExp.get();
- return;
+ int offset;
+ if (f.tintro && f.tintro.nextOf().isBaseOf(f.type.nextOf(), &offset) && offset)
+ e.error("%s", msg);
+ if (f != e.func) // if address not already marked as taken
+ f.tookAddressOf++;
+ auto result = new DelegateExp(e.loc, e.e1, f, false, e.vthis2);
+ result.type = t;
+ return result;
}
+ if (e.func.tintro)
+ e.error("%s", msg);
}
-
- visit(cast(Expression)e);
}
- override void visit(FuncExp e)
+ if (auto f = isFuncAddress(e))
{
- //printf("FuncExp::castTo type = %s, t = %s\n", e.type.toChars(), t.toChars());
- FuncExp fe;
- if (e.matchType(t, sc, &fe, 1) > MATCH.nomatch)
+ if (f.checkForwardRef(e.loc))
{
- result = fe;
- return;
+ return ErrorExp.get();
}
- visit(cast(Expression)e);
}
- override void visit(CondExp e)
+ return visit(e);
+ }
+
+ Expression visitFunc(FuncExp e)
+ {
+ //printf("FuncExp::castTo type = %s, t = %s\n", e.type.toChars(), t.toChars());
+ FuncExp fe;
+ if (e.matchType(t, sc, &fe, 1) > MATCH.nomatch)
{
- if (!e.type.equals(t))
- {
- result = new CondExp(e.loc, e.econd, e.e1.castTo(sc, t), e.e2.castTo(sc, t));
- result.type = t;
- return;
- }
- result = e;
+ return fe;
}
+ return visit(e);
+ }
- override void visit(CommaExp e)
+ Expression visitCond(CondExp e)
+ {
+ if (!e.type.equals(t))
{
- Expression e2c = e.e2.castTo(sc, t);
-
- if (e2c != e.e2)
- {
- result = new CommaExp(e.loc, e.e1, e2c);
- result.type = e2c.type;
- }
- else
- {
- result = e;
- result.type = e.e2.type;
- }
+ auto result = new CondExp(e.loc, e.econd, e.e1.castTo(sc, t), e.e2.castTo(sc, t));
+ result.type = t;
+ return result;
}
+ return e;
+ }
+
+ Expression visitComma(CommaExp e)
+ {
+ Expression e2c = e.e2.castTo(sc, t);
- override void visit(SliceExp e)
+ if (e2c != e.e2)
+ {
+ auto result = new CommaExp(e.loc, e.e1, e2c);
+ result.type = e2c.type;
+ return result;
+ }
+ else
{
- //printf("SliceExp::castTo e = %s, type = %s, t = %s\n", e.toChars(), e.type.toChars(), t.toChars());
+ e.type = e.e2.type;
+ return e;
+ }
+ }
+
+ Expression visitSlice(SliceExp e)
+ {
+ //printf("SliceExp::castTo e = %s, type = %s, t = %s\n", e.toChars(), e.type.toChars(), t.toChars());
+
+ Type tb = t.toBasetype();
+ Type typeb = e.type.toBasetype();
- Type tb = t.toBasetype();
- Type typeb = e.type.toBasetype();
+ if (e.type.equals(t) || typeb.ty != Tarray ||
+ (tb.ty != Tarray && tb.ty != Tsarray))
+ {
+ return visit(e);
+ }
- if (e.type.equals(t) || typeb.ty != Tarray ||
- (tb.ty != Tarray && tb.ty != Tsarray))
+ if (tb.ty == Tarray)
+ {
+ if (typeb.nextOf().equivalent(tb.nextOf()))
{
- visit(cast(Expression)e);
- return;
+ // T[] to const(T)[]
+ auto result = e.copy();
+ result.type = t;
+ return result;
}
-
- if (tb.ty == Tarray)
+ else
{
- if (typeb.nextOf().equivalent(tb.nextOf()))
- {
- // T[] to const(T)[]
- result = e.copy();
- result.type = t;
- }
- else
- {
- visit(cast(Expression)e);
- }
- return;
+ return visit(e);
}
+ }
- // Handle the cast from Tarray to Tsarray with CT-known slicing
+ // Handle the cast from Tarray to Tsarray with CT-known slicing
- TypeSArray tsa = toStaticArrayType(e).isTypeSArray();
- if (tsa && tsa.size(e.loc) == tb.size(e.loc))
- {
- /* Match if the sarray sizes are equal:
- * T[a .. b] to const(T)[b-a]
- * T[a .. b] to U[dim] if (T.sizeof*(b-a) == U.sizeof*dim)
- *
- * If a SliceExp has Tsarray, it will become lvalue.
- * That's handled in SliceExp::isLvalue and toLvalue
- */
- result = e.copy();
- result.type = t;
- return;
- }
- if (tsa && tsa.dim.equals(tb.isTypeSArray().dim))
+ TypeSArray tsa = toStaticArrayType(e).isTypeSArray();
+ if (tsa && tsa.size(e.loc) == tb.size(e.loc))
+ {
+ /* Match if the sarray sizes are equal:
+ * T[a .. b] to const(T)[b-a]
+ * T[a .. b] to U[dim] if (T.sizeof*(b-a) == U.sizeof*dim)
+ *
+ * If a SliceExp has Tsarray, it will become lvalue.
+ * That's handled in SliceExp::isLvalue and toLvalue
+ */
+ auto result = e.copy();
+ result.type = t;
+ return result;
+ }
+ if (tsa && tsa.dim.equals(tb.isTypeSArray().dim))
+ {
+ /* Match if the dimensions are equal
+ * with the implicit conversion of e.e1:
+ * cast(float[2]) [2.0, 1.0, 0.0][0..2];
+ */
+ Type t1b = e.e1.type.toBasetype();
+ if (t1b.ty == Tsarray)
+ t1b = tb.nextOf().sarrayOf(t1b.isTypeSArray().dim.toInteger());
+ else if (t1b.ty == Tarray)
+ t1b = tb.nextOf().arrayOf();
+ else if (t1b.ty == Tpointer)
+ t1b = tb.nextOf().pointerTo();
+ else
+ assert(0);
+ if (e.e1.implicitConvTo(t1b) > MATCH.nomatch)
{
- /* Match if the dimensions are equal
- * with the implicit conversion of e.e1:
- * cast(float[2]) [2.0, 1.0, 0.0][0..2];
- */
- Type t1b = e.e1.type.toBasetype();
- if (t1b.ty == Tsarray)
- t1b = tb.nextOf().sarrayOf(t1b.isTypeSArray().dim.toInteger());
- else if (t1b.ty == Tarray)
- t1b = tb.nextOf().arrayOf();
- else if (t1b.ty == Tpointer)
- t1b = tb.nextOf().pointerTo();
- else
- assert(0);
- if (e.e1.implicitConvTo(t1b) > MATCH.nomatch)
- {
- Expression e1x = e.e1.implicitCastTo(sc, t1b);
- assert(e1x.op != EXP.error);
- e = e.copy().isSliceExp();
- e.e1 = e1x;
- e.type = t;
- result = e;
- return;
- }
+ Expression e1x = e.e1.implicitCastTo(sc, t1b);
+ assert(e1x.op != EXP.error);
+ e = e.copy().isSliceExp();
+ e.e1 = e1x;
+ e.type = t;
+ return e;
}
- auto ts = toAutoQualChars(tsa ? tsa : e.type, t);
- e.error("cannot cast expression `%s` of type `%s` to `%s`",
- e.toChars(), ts[0], ts[1]);
- result = ErrorExp.get();
}
+ auto ts = toAutoQualChars(tsa ? tsa : e.type, t);
+ e.error("cannot cast expression `%s` of type `%s` to `%s`",
+ e.toChars(), ts[0], ts[1]);
+ return ErrorExp.get();
}
// Casting to noreturn isn't an actual cast
@@ -2673,9 +2623,25 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
return Expression.combine(e, ini);
}
- scope CastTo v = new CastTo(sc, t);
- e.accept(v);
- return v.result;
+ switch (e.op)
+ {
+ default : return visit(e);
+ case EXP.error : return visitError(e.isErrorExp());
+ case EXP.float64 : return visitReal(e.isRealExp());
+ case EXP.complex80 : return visitComplex(e.isComplexExp());
+ case EXP.structLiteral : return visitStructLiteral(e.isStructLiteralExp());
+ case EXP.string_ : return visitString(e.isStringExp());
+ case EXP.address : return visitAddr(e.isAddrExp());
+ case EXP.tuple : return visitTuple(e.isTupleExp());
+ case EXP.arrayLiteral : return visitArrayLiteral(e.isArrayLiteralExp());
+ case EXP.assocArrayLiteral: return visitAssocArrayLiteral(e.isAssocArrayLiteralExp());
+ case EXP.symbolOffset : return visitSymOff(e.isSymOffExp());
+ case EXP.delegate_ : return visitDelegate(e.isDelegateExp());
+ case EXP.function_ : return visitFunc(e.isFuncExp());
+ case EXP.question : return visitCond(e.isCondExp());
+ case EXP.comma : return visitComma(e.isCommaExp());
+ case EXP.slice : return visitSlice(e.isSliceExp());
+ }
}
/****************************************
@@ -3731,172 +3697,187 @@ extern (C++) bool arrayTypeCompatibleWithoutCasting(Type t1, Type t2)
* This is used to determine if implicit narrowing conversions will
* be allowed.
*/
+@trusted
IntRange getIntRange(Expression e)
{
- extern (C++) final class IntRangeVisitor : Visitor
+ IntRange visit(Expression e)
{
- alias visit = Visitor.visit;
-
- public:
- IntRange range;
+ return IntRange.fromType(e.type);
+ }
- override void visit(Expression e)
- {
- range = IntRange.fromType(e.type);
- }
+ IntRange visitInteger(IntegerExp e)
+ {
+ return IntRange(SignExtendedNumber(e.getInteger()))._cast(e.type);
+ }
- override void visit(IntegerExp e)
- {
- range = IntRange(SignExtendedNumber(e.getInteger()))._cast(e.type);
- }
+ IntRange visitCast(CastExp e)
+ {
+ return getIntRange(e.e1)._cast(e.type);
+ }
- override void visit(CastExp e)
- {
- range = getIntRange(e.e1)._cast(e.type);
- }
+ IntRange visitAdd(AddExp e)
+ {
+ IntRange ir1 = getIntRange(e.e1);
+ IntRange ir2 = getIntRange(e.e2);
+ return (ir1 + ir2)._cast(e.type);
+ }
- override void visit(AddExp e)
- {
- IntRange ir1 = getIntRange(e.e1);
- IntRange ir2 = getIntRange(e.e2);
- range = (ir1 + ir2)._cast(e.type);
- }
+ IntRange visitMin(MinExp e)
+ {
+ IntRange ir1 = getIntRange(e.e1);
+ IntRange ir2 = getIntRange(e.e2);
+ return (ir1 - ir2)._cast(e.type);
+ }
- override void visit(MinExp e)
- {
- IntRange ir1 = getIntRange(e.e1);
- IntRange ir2 = getIntRange(e.e2);
- range = (ir1 - ir2)._cast(e.type);
- }
+ IntRange visitDiv(DivExp e)
+ {
+ IntRange ir1 = getIntRange(e.e1);
+ IntRange ir2 = getIntRange(e.e2);
- override void visit(DivExp e)
- {
- IntRange ir1 = getIntRange(e.e1);
- IntRange ir2 = getIntRange(e.e2);
+ return (ir1 / ir2)._cast(e.type);
+ }
- range = (ir1 / ir2)._cast(e.type);
- }
+ IntRange visitMul(MulExp e)
+ {
+ IntRange ir1 = getIntRange(e.e1);
+ IntRange ir2 = getIntRange(e.e2);
- override void visit(MulExp e)
- {
- IntRange ir1 = getIntRange(e.e1);
- IntRange ir2 = getIntRange(e.e2);
+ return (ir1 * ir2)._cast(e.type);
+ }
- range = (ir1 * ir2)._cast(e.type);
- }
+ IntRange visitMod(ModExp e)
+ {
+ IntRange ir1 = getIntRange(e.e1);
+ IntRange ir2 = getIntRange(e.e2);
- override void visit(ModExp e)
+ // Modding on 0 is invalid anyway.
+ if (!ir2.absNeg().imin.negative)
{
- IntRange ir1 = getIntRange(e.e1);
- IntRange ir2 = getIntRange(e.e2);
-
- // Modding on 0 is invalid anyway.
- if (!ir2.absNeg().imin.negative)
- {
- visit(cast(Expression)e);
- return;
- }
- range = (ir1 % ir2)._cast(e.type);
+ return visit(e);
}
+ return (ir1 % ir2)._cast(e.type);
+ }
- override void visit(AndExp e)
- {
- IntRange result;
- bool hasResult = false;
- result.unionOrAssign(getIntRange(e.e1) & getIntRange(e.e2), hasResult);
+ IntRange visitAnd(AndExp e)
+ {
+ IntRange result;
+ bool hasResult = false;
+ result.unionOrAssign(getIntRange(e.e1) & getIntRange(e.e2), hasResult);
- assert(hasResult);
- range = result._cast(e.type);
- }
+ assert(hasResult);
+ return result._cast(e.type);
+ }
- override void visit(OrExp e)
- {
- IntRange result;
- bool hasResult = false;
- result.unionOrAssign(getIntRange(e.e1) | getIntRange(e.e2), hasResult);
+ IntRange visitOr(OrExp e)
+ {
+ IntRange result;
+ bool hasResult = false;
+ result.unionOrAssign(getIntRange(e.e1) | getIntRange(e.e2), hasResult);
- assert(hasResult);
- range = result._cast(e.type);
- }
+ assert(hasResult);
+ return result._cast(e.type);
+ }
- override void visit(XorExp e)
- {
- IntRange result;
- bool hasResult = false;
- result.unionOrAssign(getIntRange(e.e1) ^ getIntRange(e.e2), hasResult);
+ IntRange visitXor(XorExp e)
+ {
+ IntRange result;
+ bool hasResult = false;
+ result.unionOrAssign(getIntRange(e.e1) ^ getIntRange(e.e2), hasResult);
- assert(hasResult);
- range = result._cast(e.type);
- }
+ assert(hasResult);
+ return result._cast(e.type);
+ }
- override void visit(ShlExp e)
- {
- IntRange ir1 = getIntRange(e.e1);
- IntRange ir2 = getIntRange(e.e2);
+ IntRange visitShl(ShlExp e)
+ {
+ IntRange ir1 = getIntRange(e.e1);
+ IntRange ir2 = getIntRange(e.e2);
- range = (ir1 << ir2)._cast(e.type);
- }
+ return (ir1 << ir2)._cast(e.type);
+ }
- override void visit(ShrExp e)
- {
- IntRange ir1 = getIntRange(e.e1);
- IntRange ir2 = getIntRange(e.e2);
+ IntRange visitShr(ShrExp e)
+ {
+ IntRange ir1 = getIntRange(e.e1);
+ IntRange ir2 = getIntRange(e.e2);
- range = (ir1 >> ir2)._cast(e.type);
- }
+ return (ir1 >> ir2)._cast(e.type);
+ }
- override void visit(UshrExp e)
- {
- IntRange ir1 = getIntRange(e.e1).castUnsigned(e.e1.type);
- IntRange ir2 = getIntRange(e.e2);
+ IntRange visitUshr(UshrExp e)
+ {
+ IntRange ir1 = getIntRange(e.e1).castUnsigned(e.e1.type);
+ IntRange ir2 = getIntRange(e.e2);
- range = (ir1 >>> ir2)._cast(e.type);
- }
+ return (ir1 >>> ir2)._cast(e.type);
+ }
- override void visit(AssignExp e)
- {
- range = getIntRange(e.e2)._cast(e.type);
- }
+ IntRange visitAssign(AssignExp e)
+ {
+ return getIntRange(e.e2)._cast(e.type);
+ }
- override void visit(CondExp e)
- {
- // No need to check e.econd; assume caller has called optimize()
- IntRange ir1 = getIntRange(e.e1);
- IntRange ir2 = getIntRange(e.e2);
- range = ir1.unionWith(ir2)._cast(e.type);
- }
+ IntRange visitCond(CondExp e)
+ {
+ // No need to check e.econd; assume caller has called optimize()
+ IntRange ir1 = getIntRange(e.e1);
+ IntRange ir2 = getIntRange(e.e2);
+ return ir1.unionWith(ir2)._cast(e.type);
+ }
- override void visit(VarExp e)
- {
- Expression ie;
- VarDeclaration vd = e.var.isVarDeclaration();
- if (vd && vd.range)
- range = vd.range._cast(e.type);
- else if (vd && vd._init && !vd.type.isMutable() && (ie = vd.getConstInitializer()) !is null)
- ie.accept(this);
- else
- visit(cast(Expression)e);
- }
+ IntRange visitVar(VarExp e)
+ {
+ Expression ie;
+ VarDeclaration vd = e.var.isVarDeclaration();
+ if (vd && vd.range)
+ return vd.range._cast(e.type);
+ else if (vd && vd._init && !vd.type.isMutable() && (ie = vd.getConstInitializer()) !is null)
+ return getIntRange(ie);
+ else
+ return visit(e);
+ }
- override void visit(CommaExp e)
- {
- e.e2.accept(this);
- }
+ IntRange visitComma(CommaExp e)
+ {
+ return getIntRange(e.e2);
+ }
- override void visit(ComExp e)
- {
- IntRange ir = getIntRange(e.e1);
- range = IntRange(SignExtendedNumber(~ir.imax.value, !ir.imax.negative), SignExtendedNumber(~ir.imin.value, !ir.imin.negative))._cast(e.type);
- }
+ IntRange visitCom(ComExp e)
+ {
+ IntRange ir = getIntRange(e.e1);
+ return IntRange(SignExtendedNumber(~ir.imax.value, !ir.imax.negative), SignExtendedNumber(~ir.imin.value, !ir.imin.negative))._cast(e.type);
+ }
- override void visit(NegExp e)
- {
- IntRange ir = getIntRange(e.e1);
- range = (-ir)._cast(e.type);
- }
+ IntRange visitNeg(NegExp e)
+ {
+ IntRange ir = getIntRange(e.e1);
+ return (-ir)._cast(e.type);
}
- scope IntRangeVisitor v = new IntRangeVisitor();
- e.accept(v);
- return v.range;
+ switch (e.op)
+ {
+ default : return visit(e);
+ case EXP.int64 : return visitInteger(e.isIntegerExp());
+ case EXP.cast_ : return visitCast(e.isCastExp());
+ case EXP.add : return visitAdd(e.isAddExp());
+ case EXP.min : return visitMin(e.isMinExp());
+ case EXP.div : return visitDiv(e.isDivExp());
+ case EXP.mul : return visitMul(e.isMulExp());
+ case EXP.mod : return visitMod(e.isModExp());
+ case EXP.and : return visitAnd(e.isAndExp());
+ case EXP.or : return visitOr(e.isOrExp());
+ case EXP.xor : return visitXor(e.isXorExp());
+ case EXP.leftShift : return visitShl(e.isShlExp());
+ case EXP.rightShift : return visitShr(e.isShrExp());
+ case EXP.unsignedRightShift : return visitUshr(e.isUshrExp());
+ case EXP.blit : return visitAssign(e.isBlitExp());
+ case EXP.construct : return visitAssign(e.isConstructExp());
+ case EXP.assign : return visitAssign(e.isAssignExp());
+ case EXP.question : return visitCond(e.isCondExp());
+ case EXP.variable : return visitVar(e.isVarExp());
+ case EXP.comma : return visitComma(e.isCommaExp());
+ case EXP.tilde : return visitCom(e.isComExp());
+ case EXP.negate : return visitNeg(e.isNegExp());
+ }
}
+
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index 494b60f..cdf9355 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -1064,9 +1064,8 @@ extern (C++) class VarDeclaration : Declaration
// Both these mean the var is not rebindable once assigned,
// and the destructor gets run when it goes out of scope
bool onstack; // it is a class that was allocated on the stack
- bool mynew; // it is a class new'd with custom operator new
- byte canassign; // it can be assigned to
+ byte canassign; // it can be assigned to
bool overlapped; // if it is a field and has overlapping
bool overlapUnsafe; // if it is an overlapping field and the overlaps are unsafe
bool doNotInferScope; // do not infer 'scope' for this variable
@@ -1452,7 +1451,7 @@ extern (C++) class VarDeclaration : Declaration
//if (cd.isInterfaceDeclaration())
// error("interface `%s` cannot be scope", cd.toChars());
- if (mynew || onstack) // if any destructors
+ if (onstack) // if any destructors
{
// delete'ing C++ classes crashes (and delete is deprecated anyway)
if (cd.classKind == ClassKind.cpp)
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 353d36c..e30acb4 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -248,7 +248,6 @@ public:
bool isowner; // this is an Owner, despite it being `scope`
bool setInCtorOnly; // field can only be set in a constructor, as it is const or immutable
bool onstack; // it is a class that was allocated on the stack
- bool mynew; // it is a class new'd with custom operator new
char canassign; // it can be assigned to
bool overlapped; // if it is a field and has overlapping
bool overlapUnsafe; // if it is an overlapping field and the overlaps are unsafe
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index b55b981..6c3454d 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -3820,6 +3820,21 @@ public:
payload = &(*sle.elements)[fieldi];
oldval = *payload;
+ if (auto ival = newval.isIntegerExp())
+ {
+ if (auto bf = v.isBitFieldDeclaration())
+ {
+ sinteger_t value = ival.toInteger();
+ if (bf.type.isunsigned())
+ value &= (1L << bf.fieldWidth) - 1; // zero extra bits
+ else
+ { // sign extend extra bits
+ value = value << (64 - bf.fieldWidth);
+ value = value >> (64 - bf.fieldWidth);
+ }
+ ival.setInteger(value);
+ }
+ }
}
else if (auto ie = e1.isIndexExp())
{
@@ -4851,47 +4866,6 @@ public:
result = interpret(ce, istate);
return;
}
- else if (fd.ident == Id._d_delstruct)
- {
- // Only interpret the dtor and the argument.
- assert(e.arguments.dim == 1);
-
- Type tb = (*e.arguments)[0].type.toBasetype();
- auto ts = tb.nextOf().baseElemOf().isTypeStruct();
- if (ts)
- {
- result = interpretRegion((*e.arguments)[0], istate);
- if (exceptionOrCant(result))
- return;
-
- if (result.op == EXP.null_)
- {
- result = CTFEExp.voidexp;
- return;
- }
-
- if (result.op != EXP.address ||
- (cast(AddrExp)result).e1.op != EXP.structLiteral)
- {
- e.error("`delete` on invalid struct pointer `%s`", result.toChars());
- result = CTFEExp.cantexp;
- return;
- }
-
- auto sd = ts.sym;
- if (sd.dtor)
- {
- auto sle = cast(StructLiteralExp)(cast(AddrExp)result).e1;
- result = interpretFunction(pue, sd.dtor, istate, null, sle);
- if (exceptionOrCant(result))
- return;
-
- result = CTFEExp.voidexp;
- }
- }
-
- return;
- }
}
else if (auto soe = ecall.isSymOffExp())
{
@@ -5835,56 +5809,6 @@ public:
break;
- case Tpointer:
- tb = (cast(TypePointer)tb).next.toBasetype();
- if (tb.ty == Tstruct)
- {
- if (result.op != EXP.address ||
- (cast(AddrExp)result).e1.op != EXP.structLiteral)
- {
- e.error("`delete` on invalid struct pointer `%s`", result.toChars());
- result = CTFEExp.cantexp;
- return;
- }
-
- auto sd = (cast(TypeStruct)tb).sym;
- auto sle = cast(StructLiteralExp)(cast(AddrExp)result).e1;
-
- if (sd.dtor)
- {
- result = interpretFunction(pue, sd.dtor, istate, null, sle);
- if (exceptionOrCant(result))
- return;
- }
- }
- break;
-
- case Tarray:
- auto tv = tb.nextOf().baseElemOf();
- if (tv.ty == Tstruct)
- {
- if (result.op != EXP.arrayLiteral)
- {
- e.error("`delete` on invalid struct array `%s`", result.toChars());
- result = CTFEExp.cantexp;
- return;
- }
-
- auto sd = (cast(TypeStruct)tv).sym;
-
- if (sd.dtor)
- {
- auto ale = cast(ArrayLiteralExp)result;
- foreach (el; *ale.elements)
- {
- result = interpretFunction(pue, sd.dtor, istate, null, el);
- if (exceptionOrCant(result))
- return;
- }
- }
- }
- break;
-
default:
assert(0);
}
diff --git a/gcc/d/dmd/dmangle.d b/gcc/d/dmd/dmangle.d
index 78d17b2..ad305f9 100644
--- a/gcc/d/dmd/dmangle.d
+++ b/gcc/d/dmd/dmangle.d
@@ -726,7 +726,8 @@ public:
extern (D) static const(char)[] externallyMangledIdentifier(Declaration d)
{
const par = d.toParent(); //toParent() skips over mixin templates
- if (!par || par.isModule() || d.linkage == LINK.cpp)
+ if (!par || par.isModule() || d.linkage == LINK.cpp ||
+ (d.linkage == LINK.c && d.isCsymbol() && d.isFuncDeclaration()))
{
if (d.linkage != LINK.d && d.localNum)
d.error("the same declaration cannot be in multiple scopes with non-D linkage");
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 46e89d0..84e29fe 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -524,17 +524,8 @@ extern (C++) final class Module : Package
buf.printf("%s\t(%s)", ident.toChars(), m.srcfile.toChars());
message("import %s", buf.peekChars());
}
- m = m.parse();
+ if((m = m.parse()) is null) return null;
- // Call onImport here because if the module is going to be compiled then we
- // need to determine it early because it affects semantic analysis. This is
- // being done after parsing the module so the full module name can be taken
- // from whatever was declared in the file.
- if (!m.isRoot() && Compiler.onImport(m))
- {
- m.importedFrom = m;
- assert(m.isRoot());
- }
return m;
}
@@ -727,7 +718,7 @@ extern (C++) final class Module : Package
if (buf.length & 3)
{
error("odd length of UTF-32 char source %llu", cast(ulong) buf.length);
- fatal();
+ return null;
}
const (uint)[] eBuf = cast(const(uint)[])buf;
@@ -743,7 +734,7 @@ extern (C++) final class Module : Package
if (u > 0x10FFFF)
{
error("UTF-32 value %08x greater than 0x10FFFF", u);
- fatal();
+ return null;
}
dbuf.writeUTF8(u);
}
@@ -773,7 +764,7 @@ extern (C++) final class Module : Package
if (buf.length & 1)
{
error("odd length of UTF-16 char source %llu", cast(ulong) buf.length);
- fatal();
+ return null;
}
const (ushort)[] eBuf = cast(const(ushort)[])buf;
@@ -793,13 +784,13 @@ extern (C++) final class Module : Package
if (i >= eBuf.length)
{
error("surrogate UTF-16 high value %04x at end of file", u);
- fatal();
+ return null;
}
const u2 = readNext(&eBuf[i]);
if (u2 < 0xDC00 || 0xE000 <= u2)
{
error("surrogate UTF-16 low value %04x out of range", u2);
- fatal();
+ return null;
}
u = (u - 0xD7C0) << 10;
u |= (u2 - 0xDC00);
@@ -807,12 +798,12 @@ extern (C++) final class Module : Package
else if (u >= 0xDC00 && u <= 0xDFFF)
{
error("unpaired surrogate UTF-16 value %04x", u);
- fatal();
+ return null;
}
else if (u == 0xFFFE || u == 0xFFFF)
{
error("illegal UTF-16 value %04x", u);
- fatal();
+ return null;
}
dbuf.writeUTF8(u);
}
@@ -899,7 +890,7 @@ extern (C++) final class Module : Package
if (buf[0] >= 0x80)
{
error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]);
- fatal();
+ return null;
}
}
}
@@ -929,6 +920,8 @@ extern (C++) final class Module : Package
? UTF32ToUTF8!(Endian.little)(buf)
: UTF32ToUTF8!(Endian.big)(buf);
}
+ // an error happened on UTF conversion
+ if (buf is null) return null;
}
/* If it starts with the string "Ddoc", then it's a documentation
@@ -962,6 +955,16 @@ extern (C++) final class Module : Package
isHdrFile = true;
}
+ /// Promote `this` to a root module if requested via `-i`
+ void checkCompiledImport()
+ {
+ if (!this.isRoot() && Compiler.onImport(this))
+ this.importedFrom = this;
+ }
+
+ DsymbolTable dst;
+ Package ppack = null;
+
/* If it has the extension ".c", it is a "C" file.
* If it has the extension ".i", it is a preprocessed "C" file.
*/
@@ -971,33 +974,41 @@ extern (C++) final class Module : Package
scope p = new CParser!AST(this, buf, cast(bool) docfile, target.c);
p.nextToken();
+ checkCompiledImport();
members = p.parseModule();
- md = p.md;
+ assert(!p.md); // C doesn't have module declarations
numlines = p.scanloc.linnum;
}
else
{
scope p = new Parser!AST(this, buf, cast(bool) docfile);
p.nextToken();
- members = p.parseModule();
+ p.parseModuleDeclaration();
md = p.md;
+
+ if (md)
+ {
+ /* A ModuleDeclaration, md, was provided.
+ * The ModuleDeclaration sets the packages this module appears in, and
+ * the name of this module.
+ */
+ this.ident = md.id;
+ dst = Package.resolve(md.packages, &this.parent, &ppack);
+ }
+
+ // Done after parsing the module header because `module x.y.z` may override the file name
+ checkCompiledImport();
+
+ members = p.parseModuleContent();
numlines = p.scanloc.linnum;
}
srcBuffer.destroy();
srcBuffer = null;
/* The symbol table into which the module is to be inserted.
*/
- DsymbolTable dst;
+
if (md)
{
- /* A ModuleDeclaration, md, was provided.
- * The ModuleDeclaration sets the packages this module appears in, and
- * the name of this module.
- */
- this.ident = md.id;
- Package ppack = null;
- dst = Package.resolve(md.packages, &this.parent, &ppack);
-
// Mark the package path as accessible from the current module
// https://issues.dlang.org/show_bug.cgi?id=21661
// Code taken from Import.addPackageAccess()
@@ -1201,10 +1212,13 @@ extern (C++) final class Module : Package
if (StringExp se = msg ? msg.toStringExp() : null)
{
const slice = se.peekString();
- deprecation(loc, "is deprecated - %.*s", cast(int)slice.length, slice.ptr);
+ if (slice.length)
+ {
+ deprecation(loc, "is deprecated - %.*s", cast(int)slice.length, slice.ptr);
+ return;
+ }
}
- else
- deprecation(loc, "is deprecated");
+ deprecation(loc, "is deprecated");
}
}
diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index 2a3777b..936d19a 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/dmd/dscope.d
@@ -692,7 +692,7 @@ struct Scope
}
/********************************************
- * Search enclosing scopes for ClassDeclaration.
+ * Search enclosing scopes for ClassDeclaration or StructDeclaration.
*/
extern (C++) AggregateDeclaration getStructClassScope()
{
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index 7823351..200cb76 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -51,6 +51,7 @@ import dmd.root.rootobject;
import dmd.root.speller;
import dmd.root.string;
import dmd.statement;
+import dmd.staticassert;
import dmd.tokens;
import dmd.visitor;
@@ -1305,9 +1306,10 @@ extern (C++) class Dsymbol : ASTNode
inout(AttribDeclaration) isAttribDeclaration() inout { return null; }
inout(AnonDeclaration) isAnonDeclaration() inout { return null; }
inout(CPPNamespaceDeclaration) isCPPNamespaceDeclaration() inout { return null; }
- inout(VisibilityDeclaration) isVisibilityDeclaration() inout { return null; }
+ inout(VisibilityDeclaration) isVisibilityDeclaration() inout { return null; }
inout(OverloadSet) isOverloadSet() inout { return null; }
inout(CompileDeclaration) isCompileDeclaration() inout { return null; }
+ inout(StaticAssert) isStaticAssert() inout { return null; }
}
/***********************************************************
@@ -2500,12 +2502,15 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy
if (fd.fbody) // fd is the definition
{
sds.symtab.update(fd); // replace fd2 in symbol table with fd
+ fd.overnext = fd2;
return fd;
}
- /* BUG: just like with VarDeclaration, the types should match, which needs semantic() to be run on it.
- * FuncDeclaration::semantic2() can detect this, but it relies overnext being set.
+ /* Just like with VarDeclaration, the types should match, which needs semantic() to be run on it.
+ * FuncDeclaration::semantic() detects this, but it relies on .overnext being set.
*/
+ fd2.overloadInsert(fd);
+
return fd2;
}
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index a6bd999..03d5c3d 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -71,6 +71,7 @@ class Expression;
class ExpressionDsymbol;
class AliasAssign;
class OverloadSet;
+class StaticAssert;
struct AA;
#ifdef IN_GCC
typedef union tree_node Symbol;
@@ -307,6 +308,7 @@ public:
virtual VisibilityDeclaration *isVisibilityDeclaration() { return NULL; }
virtual OverloadSet *isOverloadSet() { return NULL; }
virtual CompileDeclaration *isCompileDeclaration() { return NULL; }
+ virtual StaticAssert *isStaticAssert() { return NULL; }
void accept(Visitor *v) { v->visit(this); }
};
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index 1cb167a..8ad0178 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -847,11 +847,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
dsym.error("globals, statics, fields, manifest constants, ref and out parameters cannot be `scope`");
}
- // @@@DEPRECATED@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
+ // @@@DEPRECATED_2.097@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
// Deprecated in 2.087
// Remove this when the feature is removed from the language
- if (0 && // deprecation disabled for now to accommodate existing extensive use
- !(dsym.storage_class & STC.scope_))
+ if (!(dsym.storage_class & STC.scope_))
{
if (!(dsym.storage_class & STC.parameter) && dsym.ident != Id.withSym)
dsym.error("reference to `scope class` must be `scope`");
@@ -1040,15 +1039,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// See if initializer is a NewExp that can be allocated on the stack
if (dsym.type.toBasetype().ty == Tclass)
{
- if (ne.newargs && ne.newargs.dim > 1)
- {
- dsym.mynew = true;
- }
- else
- {
- ne.onstack = 1;
- dsym.onstack = true;
- }
+ ne.onstack = 1;
+ dsym.onstack = true;
}
}
else if (auto fe = ex.isFuncExp())
@@ -2438,8 +2430,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
Type tprev = eprev.type.toHeadMutable().equals(em.ed.type.toHeadMutable())
? em.ed.memtype
: eprev.type;
-
- Expression emax = tprev.getProperty(sc, em.ed.loc, Id.max, 0);
+ /*
+ https://issues.dlang.org/show_bug.cgi?id=20777
+ Previously this used getProperty, which doesn't consider anything user defined,
+ this construct does do that and thus fixes the bug.
+ */
+ Expression emax = DotIdExp.create(em.ed.loc, new TypeExp(em.ed.loc, tprev), Id.max);
emax = emax.expressionSemantic(sc);
emax = emax.ctfeInterpret();
@@ -2979,10 +2975,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
void funcDeclarationSemantic(FuncDeclaration funcdecl)
{
- TypeFunction f;
- AggregateDeclaration ad;
- InterfaceDeclaration id;
-
version (none)
{
printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, funcdecl, funcdecl.toPrettyChars(), sc.linkage);
@@ -3023,7 +3015,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
funcdecl.foverrides.setDim(0); // reset in case semantic() is being retried for this function
funcdecl.storage_class |= sc.stc & ~STC.ref_;
- ad = funcdecl.isThis();
+ AggregateDeclaration ad = funcdecl.isThis();
// Don't nest structs b/c of generated methods which should not access the outer scopes.
// https://issues.dlang.org/show_bug.cgi?id=16627
if (ad && !funcdecl.generated)
@@ -3042,21 +3034,22 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (sc.flags & SCOPE.compile)
funcdecl.flags |= FUNCFLAG.compileTimeOnly; // don't emit code for this function
- FuncLiteralDeclaration fld = funcdecl.isFuncLiteralDeclaration();
- if (fld && fld.treq)
+ funcdecl.linkage = sc.linkage;
+ if (auto fld = funcdecl.isFuncLiteralDeclaration())
{
- Type treq = fld.treq;
- assert(treq.nextOf().ty == Tfunction);
- if (treq.ty == Tdelegate)
- fld.tok = TOK.delegate_;
- else if (treq.isPtrToFunction())
- fld.tok = TOK.function_;
- else
- assert(0);
- funcdecl.linkage = treq.nextOf().toTypeFunction().linkage;
+ if (fld.treq)
+ {
+ Type treq = fld.treq;
+ assert(treq.nextOf().ty == Tfunction);
+ if (treq.ty == Tdelegate)
+ fld.tok = TOK.delegate_;
+ else if (treq.isPtrToFunction())
+ fld.tok = TOK.function_;
+ else
+ assert(0);
+ funcdecl.linkage = treq.nextOf().toTypeFunction().linkage;
+ }
}
- else
- funcdecl.linkage = sc.linkage;
// evaluate pragma(inline)
if (auto pragmadecl = sc.inlining)
@@ -3078,16 +3071,24 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (!funcdecl.originalType)
funcdecl.originalType = funcdecl.type.syntaxCopy();
- if (funcdecl.type.ty != Tfunction)
+
+ static TypeFunction getFunctionType(FuncDeclaration fd)
{
- if (funcdecl.type.ty != Terror)
+ if (auto tf = fd.type.isTypeFunction())
+ return tf;
+
+ if (!fd.type.isTypeError())
{
- funcdecl.error("`%s` must be a function instead of `%s`", funcdecl.toChars(), funcdecl.type.toChars());
- funcdecl.type = Type.terror;
+ fd.error("`%s` must be a function instead of `%s`", fd.toChars(), fd.type.toChars());
+ fd.type = Type.terror;
}
- funcdecl.errors = true;
- return;
+ fd.errors = true;
+ return null;
}
+
+ if (!getFunctionType(funcdecl))
+ return;
+
if (!funcdecl.type.deco)
{
sc = sc.push();
@@ -3147,14 +3148,17 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
sc.stc |= STC.property;
if (tf.purity == PURE.fwdref)
sc.stc |= STC.pure_;
+
if (tf.trust != TRUST.default_)
+ {
sc.stc &= ~STC.safeGroup;
- if (tf.trust == TRUST.safe)
- sc.stc |= STC.safe;
- if (tf.trust == TRUST.system)
- sc.stc |= STC.system;
- if (tf.trust == TRUST.trusted)
- sc.stc |= STC.trusted;
+ if (tf.trust == TRUST.safe)
+ sc.stc |= STC.safe;
+ else if (tf.trust == TRUST.system)
+ sc.stc |= STC.system;
+ else if (tf.trust == TRUST.trusted)
+ sc.stc |= STC.trusted;
+ }
if (funcdecl.isCtorDeclaration())
{
@@ -3206,37 +3210,46 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
funcdecl.type = funcdecl.type.typeSemantic(funcdecl.loc, sc);
sc = sc.pop();
}
- if (funcdecl.type.ty != Tfunction)
- {
- if (funcdecl.type.ty != Terror)
- {
- funcdecl.error("`%s` must be a function instead of `%s`", funcdecl.toChars(), funcdecl.type.toChars());
- funcdecl.type = Type.terror;
- }
- funcdecl.errors = true;
- return;
- }
- else
+
+ auto f = getFunctionType(funcdecl);
+ if (!f)
+ return; // funcdecl's type is not a function
+
{
// Merge back function attributes into 'originalType'.
// It's used for mangling, ddoc, and json output.
TypeFunction tfo = funcdecl.originalType.toTypeFunction();
- TypeFunction tfx = funcdecl.type.toTypeFunction();
- tfo.mod = tfx.mod;
- tfo.isScopeQual = tfx.isScopeQual;
- tfo.isreturninferred = tfx.isreturninferred;
- tfo.isscopeinferred = tfx.isscopeinferred;
- tfo.isref = tfx.isref;
- tfo.isnothrow = tfx.isnothrow;
- tfo.isnogc = tfx.isnogc;
- tfo.isproperty = tfx.isproperty;
- tfo.purity = tfx.purity;
- tfo.trust = tfx.trust;
+ tfo.mod = f.mod;
+ tfo.isScopeQual = f.isScopeQual;
+ tfo.isreturninferred = f.isreturninferred;
+ tfo.isscopeinferred = f.isscopeinferred;
+ tfo.isref = f.isref;
+ tfo.isnothrow = f.isnothrow;
+ tfo.isnogc = f.isnogc;
+ tfo.isproperty = f.isproperty;
+ tfo.purity = f.purity;
+ tfo.trust = f.trust;
funcdecl.storage_class &= ~(STC.TYPECTOR | STC.FUNCATTR);
}
- f = cast(TypeFunction)funcdecl.type;
+ if (funcdecl.overnext && funcdecl.isCsymbol())
+ {
+ /* C does not allow function overloading, but it does allow
+ * redeclarations of the same function. If .overnext points
+ * to a redeclaration, ok. Error if it is an overload.
+ */
+ auto fnext = funcdecl.overnext.isFuncDeclaration();
+ funcDeclarationSemantic(fnext);
+ auto fn = fnext.type.isTypeFunction();
+ if (!fn || !cFuncEquivalence(f, fn))
+ {
+ funcdecl.error("redeclaration with different type");
+ //printf("t1: %s\n", f.toChars());
+ //printf("t2: %s\n", fn.toChars());
+ }
+ funcdecl.overnext = null; // don't overload the redeclarations
+ }
if ((funcdecl.storage_class & STC.auto_) && !f.isref && !funcdecl.inferRetType)
funcdecl.error("storage class `auto` has no effect if return type is not inferred");
@@ -3355,8 +3368,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}
}
- id = parent.isInterfaceDeclaration();
- if (id)
+ if (auto id = parent.isInterfaceDeclaration())
{
funcdecl.storage_class |= STC.abstract_;
if (funcdecl.isCtorDeclaration() || funcdecl.isPostBlitDeclaration() || funcdecl.isDtorDeclaration() || funcdecl.isInvariantDeclaration() || funcdecl.isNewDeclaration() || funcdecl.isDelete())
@@ -3364,6 +3376,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (funcdecl.fbody && funcdecl.isVirtual())
funcdecl.error("function body only allowed in `final` functions in interface `%s`", id.toChars());
}
+
if (UnionDeclaration ud = parent.isUnionDeclaration())
{
if (funcdecl.isPostBlitDeclaration() || funcdecl.isDtorDeclaration() || funcdecl.isInvariantDeclaration())
@@ -3449,8 +3462,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
Dsymbol s = cd.baseClass.search(funcdecl.loc, funcdecl.ident);
if (s)
{
- FuncDeclaration f2 = s.isFuncDeclaration();
- if (f2)
+ if (auto f2 = s.isFuncDeclaration())
{
f2 = f2.overloadExactMatch(funcdecl.type);
if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_)
@@ -3802,11 +3814,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
{
if (b.sym)
{
- Dsymbol s = search_function(b.sym, funcdecl.ident);
- if (s)
+ if (auto s = search_function(b.sym, funcdecl.ident))
{
- FuncDeclaration f2 = s.isFuncDeclaration();
- if (f2)
+ if (auto f2 = s.isFuncDeclaration())
{
f2 = f2.overloadExactMatch(funcdecl.type);
if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_)
@@ -3853,8 +3863,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
*/
if (funcdecl.isVirtual())
{
- TemplateInstance ti = parent.isTemplateInstance();
- if (ti)
+ if (auto ti = parent.isTemplateInstance())
{
// Take care of nested templates
while (1)
@@ -4426,7 +4435,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
return;
int errors = global.errors;
- //printf("+StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", this, sd.toPrettyChars(), sd.sizeok);
+ //printf("+StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
Scope* scx = null;
if (sd._scope)
{
@@ -5275,7 +5284,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}
//printf("-ClassDeclaration.dsymbolSemantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
- // @@@DEPRECATED@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
+ // @@@DEPRECATED_2.097@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
// Deprecated in 2.087
// Make an error in 2.091
// Don't forget to remove code at https://github.com/dlang/dmd/blob/b2f8274ba76358607fc3297a1e9f361480f9bcf9/src/dmd/dsymbolsem.d#L1032-L1036
@@ -5582,12 +5591,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}
assert(idec.type.ty != Tclass || (cast(TypeClass)idec.type).sym == idec);
- // @@@DEPRECATED@@@https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
+ // @@@DEPRECATED_2.120@@@ https://dlang.org/deprecate.html#scope%20as%20a%20type%20constraint
// Deprecated in 2.087
- // Remove in 2.091
+ // Made an error in 2.100, but removal depends on `scope class` being removed too
// Don't forget to remove code at https://github.com/dlang/dmd/blob/b2f8274ba76358607fc3297a1e9f361480f9bcf9/src/dmd/dsymbolsem.d#L1032-L1036
if (idec.storage_class & STC.scope_)
- deprecation(idec.loc, "`scope` as a type constraint is deprecated. Use `scope` at the usage site.");
+ error(idec.loc, "`scope` as a type constraint is obsolete. Use `scope` at the usage site.");
}
}
@@ -5879,13 +5888,16 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, Expressions*
scope v = new InstMemberWalker(tempinst.inst);
tempinst.inst.accept(v);
- if (tempinst.minst) // if inst was not speculative
+ if (!global.params.allInst &&
+ tempinst.minst) // if inst was not speculative...
{
- /* Add 'inst' once again to the root module members[], then the
- * instance members will get codegen chances.
- */
+ assert(!tempinst.minst.isRoot()); // ... it was previously appended to a non-root module
+ // Append again to the root module members[], so that the instance will
+ // get codegen chances (depending on `tempinst.inst.needsCodegen()`).
tempinst.inst.appendToModuleMember();
}
+
+ assert(tempinst.inst.memberOf && tempinst.inst.memberOf.isRoot(), "no codegen chances");
}
// modules imported by an existing instance should be added to the module
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index 9fe8472..457c5d1 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -5125,15 +5125,6 @@ private bool reliesOnTemplateParameters(Expression e, TemplateParameter[] tparam
//printf("NewExp.reliesOnTemplateParameters('%s')\n", e.toChars());
if (e.thisexp)
e.thisexp.accept(this);
- if (!result && e.newargs)
- {
- foreach (ea; *e.newargs)
- {
- ea.accept(this);
- if (result)
- return;
- }
- }
result = e.newtype.reliesOnTemplateParameters(tparams);
if (!result && e.arguments)
{
@@ -7351,12 +7342,12 @@ extern (C++) class TemplateInstance : ScopeDsymbol
// toPrettyChars(),
// enclosing ? enclosing.toPrettyChars() : null,
// mi ? mi.toPrettyChars() : null);
- if (!mi || mi.isRoot())
+ if (global.params.allInst || !mi || mi.isRoot())
{
/* If the instantiated module is speculative or root, insert to the
* member of a root module. Then:
* - semantic3 pass will get called on the instance members.
- * - codegen pass will get a selection chance to do/skip it.
+ * - codegen pass will get a selection chance to do/skip it (needsCodegen()).
*/
static Dsymbol getStrictEnclosing(TemplateInstance ti)
{
@@ -7374,8 +7365,18 @@ extern (C++) class TemplateInstance : ScopeDsymbol
// where tempdecl is declared.
mi = (enc ? enc : tempdecl).getModule();
if (!mi.isRoot())
- mi = mi.importedFrom;
- assert(mi.isRoot());
+ {
+ if (mi.importedFrom)
+ {
+ mi = mi.importedFrom;
+ assert(mi.isRoot());
+ }
+ else
+ {
+ // This can happen when using the frontend as a library.
+ // Append it to the non-root module.
+ }
+ }
}
else
{
@@ -7383,24 +7384,12 @@ extern (C++) class TemplateInstance : ScopeDsymbol
* non-root module. Then:
* - semantic3 pass won't be called on the instance.
* - codegen pass won't reach to the instance.
+ * Unless it is re-appended to a root module later (with changed minst).
*/
}
//printf("\t-. mi = %s\n", mi.toPrettyChars());
- if (memberOf is mi) // already a member
- {
- debug // make sure it really is a member
- {
- auto a = mi.members;
- for (size_t i = 0; 1; ++i)
- {
- assert(i != a.dim);
- if (this == (*a)[i])
- break;
- }
- }
- return null;
- }
+ assert(!memberOf || (!memberOf.isRoot() && mi.isRoot()), "can only re-append from non-root to root module");
Dsymbols* a = mi.members;
a.push(this);
@@ -7801,15 +7790,22 @@ struct TemplateInstanceBox
{
bool res = void;
if (ti.inst && s.ti.inst)
+ {
/* This clause is only used when an instance with errors
* is replaced with a correct instance.
*/
res = ti is s.ti;
+ }
else
+ {
/* Used when a proposed instance is used to see if there's
* an existing instance.
*/
- res = (cast()s.ti).equalsx(cast()ti);
+ static if (__VERSION__ >= 2099)
+ res = (cast()ti).equalsx(cast()s.ti);
+ else // https://issues.dlang.org/show_bug.cgi?id=22717
+ res = (cast()s.ti).equalsx(cast()ti);
+ }
debug (FindExistingInstance) ++(res ? nHits : nCollisions);
return res;
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index 5871ada..a34e2cca 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -2545,29 +2545,9 @@ public:
buf.writeByte('U');
buf.writeByte('"');
- for (size_t i = 0; i < e.len; i++)
+ foreach (i; 0 .. e.len)
{
- uint c = e.charAt(i);
- switch (c)
- {
- case '"':
- case '\\':
- buf.writeByte('\\');
- goto default;
- default:
- if (c <= 0xFF)
- {
- if (c >= 0x20 && c < 0x80)
- buf.writeByte(c);
- else
- buf.printf("\\x%02x", c);
- }
- else if (c <= 0xFFFF)
- buf.printf("\\u%04x", c);
- else
- buf.printf("\\U%08x", c);
- break;
- }
+ writeCharLiteral(*buf, e.getCodeUnit(i));
}
buf.writeByte('"');
}
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index d2a9060..35c1f76 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -380,7 +380,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, Exp
notMaybeScope(v);
- if (!v.isReference() && p == sc.func)
+ if (p == sc.func)
{
if (psr == ScopeRef.Scope ||
psr == ScopeRef.RefScope ||
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 4258e9b..b3aa0b2 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -1742,11 +1742,21 @@ extern (C++) abstract class Expression : ASTNode
inout(PrettyFuncInitExp) isPrettyFuncInitExp() { return op == EXP.prettyFunction ? cast(typeof(return))this : null; }
inout(ClassReferenceExp) isClassReferenceExp() { return op == EXP.classReference ? cast(typeof(return))this : null; }
inout(ThrownExceptionExp) isThrownExceptionExp() { return op == EXP.thrownException ? cast(typeof(return))this : null; }
- }
- inout(BinAssignExp) isBinAssignExp() pure inout nothrow @nogc
- {
- return null;
+ inout(UnaExp) isUnaExp() pure inout nothrow @nogc
+ {
+ return exptab[op] & EXPFLAGS.unary ? cast(typeof(return))this : null;
+ }
+
+ inout(BinExp) isBinExp() pure inout nothrow @nogc
+ {
+ return exptab[op] & EXPFLAGS.binary ? cast(typeof(return))this : null;
+ }
+
+ inout(BinAssignExp) isBinAssignExp() pure inout nothrow @nogc
+ {
+ return exptab[op] & EXPFLAGS.binaryAssign ? cast(typeof(return))this : null;
+ }
}
override void accept(Visitor v)
@@ -2716,29 +2726,6 @@ extern (C++) final class StringExp : Expression
return ErrorExp.get();
}
- uint charAt(uinteger_t i) const
- {
- uint value;
- switch (sz)
- {
- case 1:
- value = (cast(char*)string)[cast(size_t)i];
- break;
-
- case 2:
- value = (cast(ushort*)string)[cast(size_t)i];
- break;
-
- case 4:
- value = (cast(uint*)string)[cast(size_t)i];
- break;
-
- default:
- assert(0);
- }
- return value;
- }
-
/********************************
* Convert string contents to a 0 terminated string,
* allocated by mem.xmalloc().
@@ -3516,12 +3503,11 @@ extern (C++) final class TemplateExp : Expression
}
/***********************************************************
- * thisexp.new(newargs) newtype(arguments)
+ * newtype(arguments)
*/
extern (C++) final class NewExp : Expression
{
Expression thisexp; // if !=null, 'this' for class being allocated
- Expressions* newargs; // Array of Expression's to call new operator
Type newtype;
Expressions* arguments; // Array of Expression's
@@ -3530,25 +3516,23 @@ extern (C++) final class NewExp : Expression
bool onstack; // allocate on stack
bool thrownew; // this NewExp is the expression of a ThrowStatement
- extern (D) this(const ref Loc loc, Expression thisexp, Expressions* newargs, Type newtype, Expressions* arguments)
+ extern (D) this(const ref Loc loc, Expression thisexp, Type newtype, Expressions* arguments)
{
super(loc, EXP.new_, __traits(classInstanceSize, NewExp));
this.thisexp = thisexp;
- this.newargs = newargs;
this.newtype = newtype;
this.arguments = arguments;
}
- static NewExp create(const ref Loc loc, Expression thisexp, Expressions* newargs, Type newtype, Expressions* arguments)
+ static NewExp create(const ref Loc loc, Expression thisexp, Type newtype, Expressions* arguments)
{
- return new NewExp(loc, thisexp, newargs, newtype, arguments);
+ return new NewExp(loc, thisexp, newtype, arguments);
}
override NewExp syntaxCopy()
{
return new NewExp(loc,
thisexp ? thisexp.syntaxCopy() : null,
- arraySyntaxCopy(newargs),
newtype.syntaxCopy(),
arraySyntaxCopy(arguments));
}
@@ -3560,27 +3544,25 @@ extern (C++) final class NewExp : Expression
}
/***********************************************************
- * thisexp.new(newargs) class baseclasses { } (arguments)
+ * class baseclasses { } (arguments)
*/
extern (C++) final class NewAnonClassExp : Expression
{
Expression thisexp; // if !=null, 'this' for class being allocated
- Expressions* newargs; // Array of Expression's to call new operator
ClassDeclaration cd; // class being instantiated
Expressions* arguments; // Array of Expression's to call class constructor
- extern (D) this(const ref Loc loc, Expression thisexp, Expressions* newargs, ClassDeclaration cd, Expressions* arguments)
+ extern (D) this(const ref Loc loc, Expression thisexp, ClassDeclaration cd, Expressions* arguments)
{
super(loc, EXP.newAnonymousClass, __traits(classInstanceSize, NewAnonClassExp));
this.thisexp = thisexp;
- this.newargs = newargs;
this.cd = cd;
this.arguments = arguments;
}
override NewAnonClassExp syntaxCopy()
{
- return new NewAnonClassExp(loc, thisexp ? thisexp.syntaxCopy() : null, arraySyntaxCopy(newargs), cd.syntaxCopy(null), arraySyntaxCopy(arguments));
+ return new NewAnonClassExp(loc, thisexp ? thisexp.syntaxCopy() : null, cd.syntaxCopy(null), arraySyntaxCopy(arguments));
}
override void accept(Visitor v)
@@ -4593,11 +4575,6 @@ extern (C++) class BinAssignExp : BinExp
return toLvalue(sc, this);
}
- override inout(BinAssignExp) isBinAssignExp() pure inout nothrow @nogc @safe
- {
- return this;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -7055,3 +7032,53 @@ extern(D) Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag
return exp.type ? Modifiable.yes : Modifiable.no; // default modifiable
}
}
+
+/******************************
+ * Provide efficient way to implement isUnaExp(), isBinExp(), isBinAssignExp()
+ */
+private immutable ubyte[EXP.max + 1] exptab =
+() {
+ ubyte[EXP.max + 1] tab;
+ with (EXPFLAGS)
+ {
+ foreach (i; Eunary) { tab[i] |= unary; }
+ foreach (i; Ebinary) { tab[i] |= unary | binary; }
+ foreach (i; EbinaryAssign) { tab[i] |= unary | binary | binaryAssign; }
+ }
+ return tab;
+} ();
+
+private enum EXPFLAGS : ubyte
+{
+ unary = 1,
+ binary = 2,
+ binaryAssign = 4,
+}
+
+private enum Eunary =
+ [
+ EXP.import_, EXP.assert_, EXP.throw_, EXP.dotIdentifier, EXP.dotTemplateDeclaration,
+ EXP.dotVariable, EXP.dotTemplateInstance, EXP.delegate_, EXP.dotType, EXP.call,
+ EXP.address, EXP.star, EXP.negate, EXP.uadd, EXP.tilde, EXP.not, EXP.delete_, EXP.cast_,
+ EXP.vector, EXP.vectorArray, EXP.slice, EXP.arrayLength, EXP.array, EXP.delegatePointer,
+ EXP.delegateFunctionPointer, EXP.preMinusMinus, EXP.prePlusPlus,
+ ];
+
+private enum Ebinary =
+ [
+ EXP.dot, EXP.comma, EXP.index, EXP.minusMinus, EXP.plusPlus, EXP.assign,
+ EXP.add, EXP.min, EXP.concatenate, EXP.mul, EXP.div, EXP.mod, EXP.pow, EXP.leftShift,
+ EXP.rightShift, EXP.unsignedRightShift, EXP.and, EXP.or, EXP.xor, EXP.andAnd, EXP.orOr,
+ EXP.lessThan, EXP.lessOrEqual, EXP.greaterThan, EXP.greaterOrEqual,
+ EXP.in_, EXP.remove, EXP.equal, EXP.notEqual, EXP.identity, EXP.notIdentity,
+ EXP.question,
+ EXP.construct, EXP.blit,
+ ];
+
+private enum EbinaryAssign =
+ [
+ EXP.addAssign, EXP.minAssign, EXP.mulAssign, EXP.divAssign, EXP.modAssign,
+ EXP.andAssign, EXP.orAssign, EXP.xorAssign, EXP.powAssign,
+ EXP.leftShiftAssign, EXP.rightShiftAssign, EXP.unsignedRightShiftAssign,
+ EXP.concatenateAssign, EXP.concatenateElemAssign, EXP.concatenateDcharAssign,
+ ];
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index 18ef90a..9522b23 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -234,7 +234,10 @@ public:
FuncInitExp* isFuncInitExp();
PrettyFuncInitExp* isPrettyFuncInitExp();
ClassReferenceExp* isClassReferenceExp();
- virtual BinAssignExp* isBinAssignExp();
+ ThrownExceptionExp* isThrownExceptionExp();
+ UnaExp* isUnaExp();
+ BinExp* isBinExp();
+ BinAssignExp* isBinAssignExp();
void accept(Visitor *v) { v->visit(this); }
};
@@ -374,13 +377,14 @@ public:
static StringExp *create(const Loc &loc, const void *s, size_t len);
static void emplace(UnionExp *pue, const Loc &loc, const char *s);
bool equals(const RootObject *o) const;
+ char32_t getCodeUnit(size_t i) const;
+ void setCodeUnit(size_t i, char32_t c);
StringExp *toStringExp();
StringExp *toUTF8(Scope *sc);
Optional<bool> toBool();
bool isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
- unsigned charAt(uinteger_t i) const;
void accept(Visitor *v) { v->visit(this); }
size_t numberOfCodeUnits(int tynto = 0) const;
void writeTo(void* dest, bool zero, int tyto = 0) const;
@@ -519,10 +523,9 @@ public:
class NewExp : public Expression
{
public:
- /* thisexp.new(newargs) newtype(arguments)
+ /* newtype(arguments)
*/
Expression *thisexp; // if !NULL, 'this' for class being allocated
- Expressions *newargs; // Array of Expression's to call new operator
Type *newtype;
Expressions *arguments; // Array of Expression's
@@ -532,7 +535,7 @@ public:
bool onstack; // allocate on stack
bool thrownew; // this NewExp is the expression of a ThrowStatement
- static NewExp *create(const Loc &loc, Expression *thisexp, Expressions *newargs, Type *newtype, Expressions *arguments);
+ static NewExp *create(const Loc &loc, Expression *thisexp, Type *newtype, Expressions *arguments);
NewExp *syntaxCopy();
void accept(Visitor *v) { v->visit(this); }
@@ -541,10 +544,9 @@ public:
class NewAnonClassExp : public Expression
{
public:
- /* thisexp.new(newargs) class baseclasses { } (arguments)
+ /* class baseclasses { } (arguments)
*/
Expression *thisexp; // if !NULL, 'this' for class being allocated
- Expressions *newargs; // Array of Expression's to call new operator
ClassDeclaration *cd; // class being instantiated
Expressions *arguments; // Array of Expression's to call class constructor
@@ -716,7 +718,6 @@ public:
bool isLvalue();
Expression *toLvalue(Scope *sc, Expression *ex);
Expression *modifiableLvalue(Scope *sc, Expression *e);
- BinAssignExp* isBinAssignExp();
void accept(Visitor *v) { v->visit(this); }
};
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 6eda688..0320f66 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -1236,21 +1236,21 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
tthis = null;
goto Lfd;
}
- else if (e1.op == EXP.dotVariable && e1.type && (e1.type.toBasetype().ty == Tfunction || (cast(DotVarExp)e1).var.isOverDeclaration()))
+ else if (e1.isDotVarExp() && e1.type && (e1.type.toBasetype().isTypeFunction() || e1.isDotVarExp().var.isOverDeclaration()))
{
- DotVarExp dve = cast(DotVarExp)e1;
+ DotVarExp dve = e1.isDotVarExp();
s = dve.var;
tiargs = null;
tthis = dve.e1.type;
goto Lfd;
}
- else if (sc && sc.flags & SCOPE.Cfile && e1.op == EXP.variable && !e2)
+ else if (sc && sc.flags & SCOPE.Cfile && e1.isVarExp() && !e2)
{
// ImportC: do not implicitly call function if no ( ) are present
}
- else if (e1.op == EXP.variable && e1.type && (e1.type.toBasetype().ty == Tfunction || (cast(VarExp)e1).var.isOverDeclaration()))
+ else if (e1.isVarExp() && e1.type && (e1.type.toBasetype().isTypeFunction() || e1.isVarExp().var.isOverDeclaration()))
{
- s = (cast(VarExp)e1).var;
+ s = e1.isVarExp().var;
tiargs = null;
tthis = null;
Lfd:
@@ -1272,9 +1272,9 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
return ErrorExp.get();
if (!checkSymbolAccess(sc, fd))
{
- // @@@DEPRECATED_2020-10@@@
+ // @@@DEPRECATED_2.105@@@
// When turning into error, uncomment the return statement
- TypeFunction tf = cast(TypeFunction)fd.type;
+ TypeFunction tf = fd.type.isTypeFunction();
deprecation(loc, "Function `%s` of type `%s` is not accessible from module `%s`",
fd.toPrettyChars(), tf.toChars, sc._module.toChars);
//return ErrorExp.get();
@@ -1290,13 +1290,12 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
{
if (fd.errors)
return ErrorExp.get();
- assert(fd.type.ty == Tfunction);
- TypeFunction tf = cast(TypeFunction)fd.type;
+ TypeFunction tf = fd.type.isTypeFunction();
if (!e2 || tf.isref)
{
if (!checkSymbolAccess(sc, fd))
{
- // @@@DEPRECATED_2020-10@@@
+ // @@@DEPRECATED_2.105@@@
// When turning into error, uncomment the return statement
deprecation(loc, "Function `%s` of type `%s` is not accessible from module `%s`",
fd.toPrettyChars(), tf.toChars, sc._module.toChars);
@@ -1319,17 +1318,18 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
if (e2)
goto Leprop;
}
- if (e1.op == EXP.variable)
+ if (auto ve = e1.isVarExp())
{
- VarExp ve = cast(VarExp)e1;
- VarDeclaration v = ve.var.isVarDeclaration();
- if (v && ve.checkPurity(sc, v))
- return ErrorExp.get();
+ if (auto v = ve.var.isVarDeclaration())
+ {
+ if (ve.checkPurity(sc, v))
+ return ErrorExp.get();
+ }
}
if (e2)
return null;
- if (e1.type && e1.op != EXP.type) // function type is not a property
+ if (e1.type && !e1.isTypeExp()) // function type is not a property
{
/* Look for e1 being a lazy parameter; rewrite as delegate call
* only if the symbol wasn't already treated as a delegate
@@ -1340,15 +1340,14 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
Expression e = new CallExp(loc, e1);
return e.expressionSemantic(sc);
}
- else if (e1.op == EXP.dotVariable)
+ else if (e1.isDotVarExp())
{
// Check for reading overlapped pointer field in @safe code.
if (checkUnsafeAccess(sc, e1, true, true))
return ErrorExp.get();
}
- else if (e1.op == EXP.call)
+ else if (auto ce = e1.isCallExp())
{
- CallExp ce = cast(CallExp)e1;
// Check for reading overlapped pointer field in @safe code.
if (checkUnsafeAccess(sc, ce.e1, true, true))
return ErrorExp.get();
@@ -1560,14 +1559,12 @@ private Expression opAssignToOp(const ref Loc loc, EXP op, Expression e1, Expres
*/
private Expression rewriteOpAssign(BinExp exp)
{
- Expression e;
-
- assert(exp.e1.op == EXP.arrayLength);
- ArrayLengthExp ale = cast(ArrayLengthExp)exp.e1;
- if (ale.e1.op == EXP.variable)
+ ArrayLengthExp ale = exp.e1.isArrayLengthExp();
+ if (ale.e1.isVarExp())
{
- e = opAssignToOp(exp.loc, exp.op, ale, exp.e2);
+ Expression e = opAssignToOp(exp.loc, exp.op, ale, exp.e2);
e = new AssignExp(exp.loc, ale.syntaxCopy(), e);
+ return e;
}
else
{
@@ -1578,11 +1575,11 @@ private Expression rewriteOpAssign(BinExp exp)
Expression e1 = new ArrayLengthExp(ale.loc, new PtrExp(ale.loc, new VarExp(ale.loc, tmp)));
Expression elvalue = e1.syntaxCopy();
- e = opAssignToOp(exp.loc, exp.op, e1, exp.e2);
+ Expression e = opAssignToOp(exp.loc, exp.op, e1, exp.e2);
e = new AssignExp(exp.loc, elvalue, e);
e = new CommaExp(exp.loc, new DeclarationExp(ale.loc, tmp), e);
+ return e;
}
- return e;
}
/****************************************
@@ -1650,10 +1647,9 @@ private bool preFunctionParameters(Scope* sc, Expressions* exps, const bool repo
*/
private bool checkDefCtor(Loc loc, Type t)
{
- t = t.baseElemOf();
- if (t.ty == Tstruct)
+ if (auto ts = t.baseElemOf().isTypeStruct())
{
- StructDeclaration sd = (cast(TypeStruct)t).sym;
+ StructDeclaration sd = ts.sym;
if (sd.noDefaultCtor)
{
sd.error(loc, "default construction is disabled");
@@ -1846,7 +1842,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
auto args = new Expressions(nargs - i);
foreach (u; i .. nargs)
(*args)[u - i] = (*arguments)[u];
- arg = new NewExp(loc, null, null, p.type, args);
+ arg = new NewExp(loc, null, p.type, args);
break;
}
default:
@@ -1923,7 +1919,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
}
else if (auto ff = s.isFuncDeclaration())
{
- if ((cast(TypeFunction)ff.type).iswild)
+ if (ff.type.isTypeFunction().iswild)
return errorInout(wildmatch);
if (ff.isNested() || ff.isThis())
@@ -1969,7 +1965,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
? p.type.substWildTo(wildmatch)
: p.type;
- const hasCopyCtor = (arg.type.ty == Tstruct) && (cast(TypeStruct)arg.type).sym.hasCopyCtor;
+ const hasCopyCtor = arg.type.isTypeStruct() && arg.type.isTypeStruct().sym.hasCopyCtor;
const typesMatch = arg.type.mutableOf().unSharedOf().equals(tprm.mutableOf().unSharedOf());
if (!((hasCopyCtor && typesMatch) || tprm.equals(arg.type)))
{
@@ -2059,8 +2055,8 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
/* Argument value cannot escape from the called function.
*/
Expression a = arg;
- if (a.op == EXP.cast_)
- a = (cast(CastExp)a).e1;
+ if (auto ce = a.isCastExp())
+ a = ce.e1;
ArrayLiteralExp ale;
if (p.type.toBasetype().ty == Tarray &&
@@ -2074,26 +2070,22 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
arg = CommaExp.combine(declareTmp, castToSlice);
arg = arg.expressionSemantic(sc);
}
- else if (a.op == EXP.function_)
+ else if (auto fe = a.isFuncExp())
{
/* Function literals can only appear once, so if this
* appearance was scoped, there cannot be any others.
*/
- FuncExp fe = cast(FuncExp)a;
fe.fd.tookAddressOf = 0;
}
- else if (a.op == EXP.delegate_)
+ else if (auto de = a.isDelegateExp())
{
/* For passing a delegate to a scoped parameter,
* this doesn't count as taking the address of it.
* We only worry about 'escaping' references to the function.
*/
- DelegateExp de = cast(DelegateExp)a;
- if (de.e1.op == EXP.variable)
+ if (auto ve = de.e1.isVarExp())
{
- VarExp ve = cast(VarExp)de.e1;
- FuncDeclaration f = ve.var.isFuncDeclaration();
- if (f)
+ if (auto f = ve.var.isFuncDeclaration())
{
if (f.tookAddressOf)
--f.tookAddressOf;
@@ -2174,9 +2166,8 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
// Convert static arrays to dynamic arrays
// BUG: I don't think this is right for D2
Type tb = arg.type.toBasetype();
- if (tb.ty == Tsarray)
+ if (auto ts = tb.isTypeSArray())
{
- TypeSArray ts = cast(TypeSArray)tb;
Type ta = ts.next.arrayOf();
if (ts.size(arg.loc) == 0)
arg = new NullExp(arg.loc, ta);
@@ -2188,9 +2179,8 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
//arg = callCpCtor(sc, arg);
}
// Give error for overloaded function addresses
- if (arg.op == EXP.symbolOffset)
+ if (auto se = arg.isSymOffExp())
{
- SymOffExp se = cast(SymOffExp)arg;
if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique())
{
arg.error("function `%s` is overloaded", arg.toChars());
@@ -3469,10 +3459,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// T should be analyzed first and edim should go into arguments iff it's
// not a tuple.
Expression edim = null;
- if (!exp.arguments && exp.newtype.ty == Tsarray)
+ if (!exp.arguments && exp.newtype.isTypeSArray())
{
- edim = (cast(TypeSArray)exp.newtype).dim;
- exp.newtype = (cast(TypeNext)exp.newtype).next;
+ auto ts = exp.newtype.isTypeSArray();
+ edim = ts.dim;
+ exp.newtype = ts.next;
}
ClassDeclaration cdthis = null;
@@ -3522,11 +3513,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.newtype = exp.type; // in case type gets cast to something else
Type tb = exp.type.toBasetype();
//printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco);
- if (arrayExpressionSemantic(exp.newargs, sc) ||
- preFunctionParameters(sc, exp.newargs))
- {
- return setError();
- }
if (arrayExpressionSemantic(exp.arguments, sc))
{
return setError();
@@ -3556,9 +3542,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
const size_t nargs = exp.arguments ? exp.arguments.dim : 0;
Expression newprefix = null;
- if (tb.ty == Tclass)
+ if (auto tc = tb.isTypeClass())
{
- auto cd = (cast(TypeClass)tb).sym;
+ auto cd = tc.sym;
cd.size(exp.loc);
if (cd.sizeok != Sizeok.done)
return setError();
@@ -3692,14 +3678,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
originalNewtype.toChars());
return setError();
}
- else
- {
- if (exp.newargs && exp.newargs.dim)
- {
- exp.error("no allocator for `%s`", cd.toChars());
- return setError();
- }
- }
if (cd.ctor)
{
@@ -3710,7 +3688,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
checkFunctionAttributes(exp, sc, f);
checkAccess(cd, exp.loc, sc, f);
- TypeFunction tf = cast(TypeFunction)f.type;
+ 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))
@@ -3744,9 +3722,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
}
- else if (tb.ty == Tstruct)
+ else if (auto ts = tb.isTypeStruct())
{
- auto sd = (cast(TypeStruct)tb).sym;
+ auto sd = ts.sym;
sd.size(exp.loc);
if (sd.sizeok != Sizeok.done)
return setError();
@@ -3765,14 +3743,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
originalNewtype.toChars());
return setError();
}
- else
- {
- if (exp.newargs && exp.newargs.dim)
- {
- exp.error("no allocator for `%s`", sd.toChars());
- return setError();
- }
- }
if (sd.hasRegularCtor() && nargs)
{
@@ -3783,7 +3753,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
checkFunctionAttributes(exp, sc, f);
checkAccess(sd, exp.loc, sc, f);
- TypeFunction tf = cast(TypeFunction)f.type;
+ 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))
@@ -3861,7 +3831,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
}
(*exp.arguments)[i] = arg;
- tb = (cast(TypeDArray)tb).next.toBasetype();
+ tb = tb.isTypeDArray().next.toBasetype();
}
}
else if (tb.isscalar())
@@ -3924,7 +3894,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
sds.members.push(e.cd);
}
- Expression n = new NewExp(e.loc, e.thisexp, e.newargs, e.cd.type, e.arguments);
+ Expression n = new NewExp(e.loc, e.thisexp, e.cd.type, e.arguments);
Expression c = new CommaExp(e.loc, d, n);
result = c.expressionSemantic(sc);
@@ -4097,6 +4067,15 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// Type is a "delegate to" or "pointer to" the function literal
if ((exp.fd.isNested() && exp.fd.tok == TOK.delegate_) || (exp.tok == TOK.reserved && exp.fd.treq && exp.fd.treq.ty == Tdelegate))
{
+ // https://issues.dlang.org/show_bug.cgi?id=22686
+ // if the delegate return type is an error
+ // abort semantic of the FuncExp and propagate
+ // the error
+ if (exp.fd.type.isTypeError())
+ {
+ e = ErrorExp.get();
+ goto Ldone;
+ }
exp.type = new TypeDelegate(exp.fd.type.isTypeFunction());
exp.type = exp.type.typeSemantic(exp.loc, sc);
@@ -5239,21 +5218,21 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
break;
}
- VarDeclaration v = s.isVarDeclaration();
- if (v)
- {
- // Do semantic() on initializer first, so:
- // int a = a;
- // will be illegal.
- e.declaration.dsymbolSemantic(sc);
- s.parent = sc.parent;
- }
-
//printf("inserting '%s' %p into sc = %p\n", s.toChars(), s, sc);
// Insert into both local scope and function scope.
// Must be unique in both.
if (s.ident)
{
+ VarDeclaration v = s.isVarDeclaration();
+ if (v && !(sc.flags & SCOPE.Cfile))
+ {
+ /* Do semantic() on initializer first so this will be illegal:
+ * int a = a;
+ */
+ e.declaration.dsymbolSemantic(sc);
+ s.parent = sc.parent;
+ }
+
if (!sc.insert(s))
{
auto conflict = sc.search(Loc.initial, s.ident, null);
@@ -5262,7 +5241,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
conflict.kind(), conflict.toChars());
return setError();
}
- else if (sc.func)
+
+ if (v && (sc.flags & SCOPE.Cfile))
+ {
+ /* Do semantic() on initializer last so this will be legal:
+ * int a = a;
+ */
+ e.declaration.dsymbolSemantic(sc);
+ s.parent = sc.parent;
+ }
+
+ if (sc.func)
{
// https://issues.dlang.org/show_bug.cgi?id=11720
if ((s.isFuncDeclaration() ||
@@ -5278,14 +5267,19 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// Perturb the name mangling so that the symbols can co-exist
// instead of colliding
s.localNum = cast(ushort)(originalSymbol.localNum + 1);
- assert(s.localNum); // 65535 should be enough for anyone
+ // 65535 should be enough for anyone
+ if (!s.localNum)
+ {
+ e.error("more than 65535 symbols with name `%s` generated", s.ident.toChars());
+ return setError();
+ }
// Replace originalSymbol with s, which updates the localCount
sc.func.localsymtab.update(s);
// The mangling change only works for D mangling
}
-// else
+
{
/* https://issues.dlang.org/show_bug.cgi?id=21272
* If we are in a foreach body we need to extract the
@@ -6943,15 +6937,19 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
else if (!exp.e1.type.deco)
{
- if (exp.e1.op == EXP.variable)
+ // try to resolve the type
+ exp.e1.type = exp.e1.type.typeSemantic(exp.e1.loc, null);
+ if (!exp.e1.type.deco) // still couldn't resolve it
{
- VarExp ve = cast(VarExp)exp.e1;
- Declaration d = ve.var;
- exp.error("forward reference to %s `%s`", d.kind(), d.toChars());
+ if (auto ve = exp.e1.isVarExp())
+ {
+ Declaration d = ve.var;
+ exp.error("forward reference to %s `%s`", d.kind(), d.toChars());
+ }
+ else
+ exp.error("forward reference to type `%s` of expression `%s`", exp.e1.type.toChars(), exp.e1.toChars());
+ return setError();
}
- else
- exp.error("forward reference to `%s`", exp.e1.toChars());
- return setError();
}
exp.type = exp.e1.type.pointerTo();
@@ -7327,14 +7325,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
override void visit(DeleteExp exp)
{
- if (!sc.isDeprecated)
+ // @@@DEPRECATED_2.109@@@
+ // 1. Deprecated since 2.079
+ // 2. Error since 2.099
+ // 3. Removal of keyword, "delete" can be used for other identities
+ if (!exp.isRAII)
{
- // @@@DEPRECATED_2019-02@@@
- // 1. Deprecation for 1 year
- // 2. Error for 1 year
- // 3. Removal of keyword, "delete" can be used for other identities
- if (!exp.isRAII)
- deprecation(exp.loc, "The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.");
+ error(exp.loc, "The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.");
+ return setError();
}
Expression e = exp;
@@ -7353,89 +7351,32 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
exp.type = Type.tvoid;
- AggregateDeclaration ad = null;
Type tb = exp.e1.type.toBasetype();
- switch (tb.ty)
- {
- case Tclass:
- {
- auto cd = (cast(TypeClass)tb).sym;
- if (cd.isCOMinterface())
- {
- /* Because COM classes are deleted by IUnknown.Release()
- */
- exp.error("cannot `delete` instance of COM interface `%s`", cd.toChars());
- return setError();
- }
- ad = cd;
- break;
- }
- case Tpointer:
- tb = (cast(TypePointer)tb).next.toBasetype();
- if (tb.ty == Tstruct)
- {
- ad = (cast(TypeStruct)tb).sym;
-
- Identifier hook = global.params.tracegc ? Id._d_delstructTrace : Id._d_delstruct;
- if (!verifyHookExist(exp.loc, *sc, Id._d_delstructImpl, "deleting struct with dtor", Id.object))
- return setError();
- // Lower to .object._d_delstruct{,Trace}(exp.e1)
- Expression id = new IdentifierExp(exp.loc, Id.empty);
- id = new DotIdExp(exp.loc, id, Id.object);
-
- auto tiargs = new Objects();
- tiargs.push(exp.e1.type);
- id = new DotTemplateInstanceExp(exp.loc, id, Id._d_delstructImpl, tiargs);
- id = new DotIdExp(exp.loc, id, hook);
-
- e = new CallExp(exp.loc, id, exp.e1);
- /* Gag errors generated by calls to `_d_delstruct`, because they display
- * internal compiler information, which is unnecessary to the user.
- */
- uint errors = global.startGagging();
- e = e.expressionSemantic(sc);
- global.endGagging(errors);
- }
- break;
-
- case Tarray:
- {
- Type tv = tb.nextOf().baseElemOf();
- if (tv.ty == Tstruct)
- {
- ad = (cast(TypeStruct)tv).sym;
- if (ad.dtor)
- semanticTypeInfo(sc, ad.type);
- }
- break;
- }
- default:
+ /* Now that `delete` in user code is an error, we only get here when
+ * `isRAII` has been set to true for the deletion of a `scope class`. */
+ if (tb.ty != Tclass)
+ {
exp.error("cannot delete type `%s`", exp.e1.type.toChars());
return setError();
}
- bool err = false;
- if (ad)
+ ClassDeclaration cd = (cast(TypeClass)tb).sym;
+ if (cd.isCOMinterface())
{
- if (ad.dtor)
- {
- err |= !ad.dtor.functionSemantic();
- err |= exp.checkPurity(sc, ad.dtor);
- err |= exp.checkSafety(sc, ad.dtor);
- err |= exp.checkNogc(sc, ad.dtor);
- }
- if (err)
- return setError();
+ /* Because COM classes are deleted by IUnknown.Release()
+ */
+ exp.error("cannot `delete` instance of COM interface `%s`", cd.toChars());
+ return setError();
}
- if (!sc.intypeof && sc.func &&
- !exp.isRAII &&
- !(sc.flags & SCOPE.debug_) &&
- sc.func.setUnsafe())
+ bool err = false;
+ if (cd.dtor)
{
- exp.error("`%s` is not `@safe` but is used in `@safe` function `%s`", exp.toChars(), sc.func.toChars());
- err = true;
+ err |= !cd.dtor.functionSemantic();
+ err |= exp.checkPurity(sc, cd.dtor);
+ err |= exp.checkSafety(sc, cd.dtor);
+ err |= exp.checkNogc(sc, cd.dtor);
}
if (err)
return setError();
@@ -7457,12 +7398,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
if ((sc && sc.flags & SCOPE.Cfile) &&
- exp.to && exp.to.ty == Tident &&
+ exp.to && (exp.to.ty == Tident || exp.to.ty == Tsarray) &&
(exp.e1.op == EXP.address || exp.e1.op == EXP.star ||
exp.e1.op == EXP.uadd || exp.e1.op == EXP.negate))
{
/* Ambiguous cases arise from CParser if type-name is just an identifier.
* ( identifier ) cast-expression
+ * ( identifier [expression]) cast-expression
* If we determine that `identifier` is a variable, and cast-expression
* is one of the unary operators (& * + -), then rewrite this cast
* as a binary expression.
@@ -9858,7 +9800,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
VarExp ve = cast(VarExp)exp.e1;
VarDeclaration vd = ve.var.isVarDeclaration();
- if (vd && (vd.onstack || vd.mynew))
+ if (vd && vd.onstack)
{
assert(t1.ty == Tclass);
exp.error("cannot rebind scope variables");
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index f3aeb0f..39cb845 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -567,7 +567,8 @@ extern (C++) class FuncDeclaration : Declaration
* do existing practice. But we should examine how TypeFunction does
* it, for consistency.
*/
- if (!tf.isref && isRefReturnScope(vthis.storage_class))
+ if (global.params.useDIP1000 != FeatureState.enabled &&
+ !tf.isref && isRefReturnScope(vthis.storage_class))
{
/* if `ref return scope`, evaluate to `ref` `return scope`
*/
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 43b63f1..6b8ecc5 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -991,8 +991,9 @@ public:
override void visit(VisibilityDeclaration d)
{
visibilityToBuffer(buf, d.visibility);
- buf.writeByte(' ');
AttribDeclaration ad = cast(AttribDeclaration)d;
+ if (ad.decl.dim <= 1)
+ buf.writeByte(' ');
if (ad.decl.dim == 1 && (*ad.decl)[0].isVisibilityDeclaration)
visit(cast(AttribDeclaration)(*ad.decl)[0]);
else
@@ -1693,17 +1694,8 @@ public:
override void visit(DtorDeclaration d)
{
- if (d.storage_class & STC.trusted)
- buf.writestring("@trusted ");
- if (d.storage_class & STC.safe)
- buf.writestring("@safe ");
- if (d.storage_class & STC.nogc)
- buf.writestring("@nogc ");
- if (d.storage_class & STC.live)
- buf.writestring("@live ");
- if (d.storage_class & STC.disable)
- buf.writestring("@disable ");
-
+ if (stcToBuffer(buf, d.storage_class))
+ buf.writeByte(' ');
buf.writestring("~this()");
bodyToBuffer(d);
}
@@ -1992,29 +1984,9 @@ public:
{
buf.writeByte('"');
const o = buf.length;
- for (size_t i = 0; i < e.len; i++)
+ foreach (i; 0 .. e.len)
{
- const c = e.charAt(i);
- switch (c)
- {
- case '"':
- case '\\':
- buf.writeByte('\\');
- goto default;
- default:
- if (c <= 0xFF)
- {
- if (c <= 0x7F && isprint(c))
- buf.writeByte(c);
- else
- buf.printf("\\x%02x", c);
- }
- else if (c <= 0xFFFF)
- buf.printf("\\x%02x\\x%02x", c & 0xFF, c >> 8);
- else
- buf.printf("\\x%02x\\x%02x\\x%02x\\x%02x", c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24);
- break;
- }
+ writeCharLiteral(*buf, e.getCodeUnit(i));
}
if (hgs.ddoc)
escapeDdocString(buf, o);
@@ -2113,12 +2085,6 @@ public:
buf.writeByte('.');
}
buf.writestring("new ");
- if (e.newargs && e.newargs.dim)
- {
- buf.writeByte('(');
- argsToBuffer(e.newargs, buf, hgs);
- buf.writeByte(')');
- }
typeToBuffer(e.newtype, null, buf, hgs);
if (e.arguments && e.arguments.dim)
{
@@ -2136,12 +2102,6 @@ public:
buf.writeByte('.');
}
buf.writestring("new");
- if (e.newargs && e.newargs.dim)
- {
- buf.writeByte('(');
- argsToBuffer(e.newargs, buf, hgs);
- buf.writeByte(')');
- }
buf.writestring(" class ");
if (e.arguments && e.arguments.dim)
{
@@ -2909,22 +2869,6 @@ string stcToString(ref StorageClass stc)
return null;
}
-/// Ditto
-extern (D) string trustToString(TRUST trust) pure nothrow
-{
- final switch (trust)
- {
- case TRUST.default_:
- return null;
- case TRUST.system:
- return "@system";
- case TRUST.trusted:
- return "@trusted";
- case TRUST.safe:
- return "@safe";
- }
-}
-
private void linkageToBuffer(OutBuffer* buf, LINK linkage)
{
const s = linkageToString(linkage);
@@ -3902,7 +3846,7 @@ private void typeToBufferx(Type t, OutBuffer* buf, HdrGenState* hgs)
buf.writeByte(' ');
if (t.id)
buf.writestring(t.id.toChars());
- if (t.base.ty != TY.Tint32)
+ if (t.tok == TOK.enum_ && t.base.ty != TY.Tint32)
{
buf.writestring(" : ");
visitWithMask(t.base, t.mod, buf, hgs);
diff --git a/gcc/d/dmd/iasmgcc.d b/gcc/d/dmd/iasmgcc.d
index 495126d..7d4fbc3 100644
--- a/gcc/d/dmd/iasmgcc.d
+++ b/gcc/d/dmd/iasmgcc.d
@@ -84,7 +84,7 @@ int parseExtAsmOperands(Parser)(Parser p, GccAsmStatement s)
case TOK.string_:
constraint = p.parsePrimaryExp();
- // @@@DEPRECATED@@@
+ // @@@DEPRECATED_2.101@@@
// Old parser allowed omitting parentheses around the expression.
// Deprecated in 2.091. Can be made permanent error after 2.100
if (p.token.value != TOK.leftParenthesis)
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index 7f51e92..31a44db 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -115,7 +115,6 @@ immutable Msgtable[] msgtable =
{ "line" },
{ "empty", "" },
{ "p" },
- { "q" },
{ "__vptr" },
{ "__monitor" },
{ "gate", "__gate" },
@@ -311,9 +310,6 @@ immutable Msgtable[] msgtable =
{ "__ArrayPostblit" },
{ "__ArrayDtor" },
{ "_d_delThrowable" },
- { "_d_delstructImpl" },
- { "_d_delstruct" },
- { "_d_delstructTrace" },
{ "_d_assert_fail" },
{ "dup" },
{ "_aaApply" },
diff --git a/gcc/d/dmd/importc.d b/gcc/d/dmd/importc.d
index 1b92386..a48b339 100644
--- a/gcc/d/dmd/importc.d
+++ b/gcc/d/dmd/importc.d
@@ -260,3 +260,50 @@ Expression castCallAmbiguity(Expression e, Scope* sc)
}
}
+/********************************************
+ * Implement the C11 notion of function equivalence,
+ * which allows prototyped functions to match K+R functions,
+ * even though they are different.
+ * Params:
+ * tf1 = type of first function
+ * tf2 = type of second function
+ * Returns:
+ * true if C11 considers them equivalent
+ */
+
+bool cFuncEquivalence(TypeFunction tf1, TypeFunction tf2)
+{
+ if (tf1.equals(tf2))
+ return true;
+
+ if (tf1.linkage != tf2.linkage)
+ return false;
+
+ // Allow func(void) to match func()
+ if (tf1.parameterList.length == 0 && tf2.parameterList.length == 0)
+ return true;
+
+ if (!tf1.parameterList.hasIdentifierList &&
+ !tf2.parameterList.hasIdentifierList)
+ return false; // both functions are prototyped
+
+ // Otherwise ignore variadicness, as K+R functions are all variadic
+
+ if (!tf1.nextOf().equals(tf2.nextOf()))
+ return false; // function return types don't match
+
+ if (tf1.parameterList.length != tf2.parameterList.length)
+ return false;
+
+ foreach (i, fparam ; tf1.parameterList)
+ {
+ Type t1 = fparam.type;
+ Type t2 = tf2.parameterList[i].type;
+ if (!t1.equals(t2))
+ return false;
+ }
+
+ //printf("t1: %s\n", tf1.toChars());
+ //printf("t2: %s\n", tf2.toChars());
+ return true;
+}
diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index 6b10ace..bc02bf9 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/dmd/initsem.d
@@ -590,7 +590,11 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
i.exp = ErrorExp.get();
}
}
+ Type et = i.exp.type;
+ const errors = global.startGagging();
i.exp = i.exp.implicitCastTo(sc, t);
+ if (global.endGagging(errors))
+ currExp.error("cannot implicitly convert expression `%s` of type `%s` to `%s`", currExp.toChars(), et.toChars(), t.toChars());
}
L1:
if (i.exp.op == EXP.error)
diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d
index e74b192..7c8b504 100644
--- a/gcc/d/dmd/lexer.d
+++ b/gcc/d/dmd/lexer.d
@@ -38,172 +38,6 @@ import dmd.utils;
nothrow:
-private enum LS = 0x2028; // UTF line separator
-private enum PS = 0x2029; // UTF paragraph separator
-
-/********************************************
- * Do our own char maps
- */
-private static immutable cmtable = () {
- ubyte[256] table;
- foreach (const c; 0 .. table.length)
- {
- if ('0' <= c && c <= '7')
- table[c] |= CMoctal;
- if (c_isxdigit(c))
- table[c] |= CMhex;
- if (c_isalnum(c) || c == '_')
- table[c] |= CMidchar;
-
- switch (c)
- {
- case 'x': case 'X':
- case 'b': case 'B':
- table[c] |= CMzerosecond;
- break;
-
- case '0': .. case '9':
- case 'e': case 'E':
- case 'f': case 'F':
- case 'l': case 'L':
- case 'p': case 'P':
- case 'u': case 'U':
- case 'i':
- case '.':
- case '_':
- table[c] |= CMzerosecond | CMdigitsecond;
- break;
-
- default:
- break;
- }
-
- switch (c)
- {
- case '\\':
- case '\n':
- case '\r':
- case 0:
- case 0x1A:
- case '\'':
- break;
- default:
- if (!(c & 0x80))
- table[c] |= CMsinglechar;
- break;
- }
- }
- return table;
-}();
-
-private
-{
- enum CMoctal = 0x1;
- enum CMhex = 0x2;
- enum CMidchar = 0x4;
- enum CMzerosecond = 0x8;
- enum CMdigitsecond = 0x10;
- enum CMsinglechar = 0x20;
-}
-
-private bool isoctal(const char c) pure @nogc @safe
-{
- return (cmtable[c] & CMoctal) != 0;
-}
-
-private bool ishex(const char c) pure @nogc @safe
-{
- return (cmtable[c] & CMhex) != 0;
-}
-
-private bool isidchar(const char c) pure @nogc @safe
-{
- return (cmtable[c] & CMidchar) != 0;
-}
-
-private bool isZeroSecond(const char c) pure @nogc @safe
-{
- return (cmtable[c] & CMzerosecond) != 0;
-}
-
-private bool isDigitSecond(const char c) pure @nogc @safe
-{
- return (cmtable[c] & CMdigitsecond) != 0;
-}
-
-private bool issinglechar(const char c) pure @nogc @safe
-{
- return (cmtable[c] & CMsinglechar) != 0;
-}
-
-private bool c_isxdigit(const int c) pure @nogc @safe
-{
- return (( c >= '0' && c <= '9') ||
- ( c >= 'a' && c <= 'f') ||
- ( c >= 'A' && c <= 'F'));
-}
-
-private bool c_isalnum(const int c) pure @nogc @safe
-{
- return (( c >= '0' && c <= '9') ||
- ( c >= 'a' && c <= 'z') ||
- ( c >= 'A' && c <= 'Z'));
-}
-
-unittest
-{
- //printf("lexer.unittest\n");
- /* 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);
- TOK tok;
- tok = lex1.nextToken();
- //printf("tok == %s, %d, %d\n", Token::toChars(tok), tok, TOK.int32);
- assert(tok == TOK.int32);
- tok = lex1.nextToken();
- assert(tok == TOK.endOfFile);
- tok = lex1.nextToken();
- assert(tok == TOK.endOfFile);
- tok = lex1.nextToken();
- assert(tok == TOK.endOfFile);
-}
-
-unittest
-{
- // We don't want to see Lexer error output during these tests.
- uint errors = global.startGagging();
- scope(exit) global.endGagging(errors);
-
- // Test malformed input: even malformed input should end in a TOK.endOfFile.
- static immutable char[][] testcases =
- [ // Testcase must end with 0 or 0x1A.
- [0], // not malformed, but pathological
- ['\'', 0],
- ['\'', 0x1A],
- ['{', '{', 'q', '{', 0],
- [0xFF, 0],
- [0xFF, 0x80, 0],
- [0xFF, 0xFF, 0],
- [0xFF, 0xFF, 0],
- ['x', '"', 0x1A],
- ];
-
- foreach (testcase; testcases)
- {
- scope Lexer lex2 = new Lexer(null, testcase.ptr, 0, testcase.length-1, 0, 0);
- TOK tok = lex2.nextToken();
- size_t iterations = 1;
- while ((tok != TOK.endOfFile) && (iterations++ < testcase.length))
- {
- tok = lex2.nextToken();
- }
- assert(tok == TOK.endOfFile);
- tok = lex2.nextToken();
- assert(tok == TOK.endOfFile);
- }
-}
-
version (DMDLIB)
{
version = LocOffset;
@@ -440,7 +274,7 @@ class Lexer
if (issinglechar(p[1]) && p[2] == '\'')
{
t.unsvalue = p[1]; // simple one character literal
- t.value = Ccompile ? TOK.int32Literal : TOK.charLiteral;
+ t.value = TOK.charLiteral;
p += 3;
}
else if (Ccompile)
@@ -1716,9 +1550,11 @@ class Lexer
if (*p == '"')
p++;
else if (hereid)
- error("delimited string must end in %s\"", hereid.toChars());
+ error("delimited string must end in `%s\"`", hereid.toChars());
+ else if (isspace(delimright))
+ error("delimited string must end in `\"`");
else
- error("delimited string must end in %c\"", delimright);
+ error("delimited string must end in `%c\"`", delimright);
result.setString(stringbuffer);
stringPostfix(result);
}
@@ -2030,7 +1866,7 @@ class Lexer
default:
assert(0);
}
- t.value = TOK.int32Literal;
+ t.value = n == 1 ? TOK.charLiteral : TOK.int32Literal;
t.unsvalue = u;
}
@@ -2113,7 +1949,11 @@ class Lexer
if (p[1] == '.')
goto Ldone; // if ".."
if (isalpha(p[1]) || p[1] == '_' || p[1] & 0x80)
+ {
+ if (Ccompile && (p[1] == 'f' || p[1] == 'F' || p[1] == 'l' || p[1] == 'L'))
+ goto Lreal; // if `0.f` or `0.L`
goto Ldone; // if ".identifier" or ".unicode"
+ }
goto Lreal; // '.' is part of current token
case 'i':
case 'f':
@@ -2182,7 +2022,12 @@ class Lexer
if (p[1] == '.')
goto Ldone; // if ".."
if (base <= 10 && n > 0 && (isalpha(p[1]) || p[1] == '_' || p[1] & 0x80))
+ {
+ if (Ccompile && base == 10 &&
+ (p[1] == 'f' || p[1] == 'F' || p[1] == 'l' || p[1] == 'L'))
+ goto Lreal; // if `1.f` or `1.L`
goto Ldone; // if ".identifier" or ".unicode"
+ }
if (base == 16 && (!ishex(p[1]) || p[1] == '_' || p[1] & 0x80))
goto Ldone; // if ".identifier" or ".unicode"
if (base == 2)
@@ -2421,11 +2266,6 @@ class Lexer
flags = cast(FLAGS)(flags | f);
}
- void overflow()
- {
- error("integer overflow");
- }
-
TOK result = TOK.int32Literal; // default
switch (flags)
{
@@ -2438,71 +2278,35 @@ class Lexer
* First that fits: int, unsigned, long, unsigned long,
* long long, unsigned long long
*/
- if (longsize == 4)
- {
- if (n & 0x8000000000000000L)
- result = TOK.uns64Literal;
- else if (n & 0xFFFFFFFF00000000L)
- result = TOK.int64Literal;
- else if (n & 0x80000000)
- result = TOK.uns32Literal;
- else
- result = TOK.int32Literal;
- }
+ if (n & 0x8000000000000000L)
+ result = TOK.uns64Literal; // unsigned long
+ else if (n & 0xFFFFFFFF00000000L)
+ result = TOK.int64Literal; // long
+ else if (n & 0x80000000)
+ result = TOK.uns32Literal;
else
- {
- if (n & 0x8000000000000000L)
- result = TOK.uns64Literal; // unsigned long
- else if (n & 0xFFFFFFFF00000000L)
- result = TOK.int64Literal; // long
- else if (n & 0x80000000)
- result = TOK.uns32Literal;
- else
- result = TOK.int32Literal;
- }
+ result = TOK.int32Literal;
break;
case FLAGS.decimal:
/* First that fits: int, long, long long
*/
- if (longsize == 4)
- {
- if (n & 0x8000000000000000L)
- result = TOK.uns64Literal;
- else if (n & 0xFFFFFFFF80000000L)
- result = TOK.int64Literal;
- else
- result = TOK.int32Literal;
- }
+ if (n & 0x8000000000000000L)
+ result = TOK.uns64Literal; // unsigned long
+ else if (n & 0xFFFFFFFF80000000L)
+ result = TOK.int64Literal; // long
else
- {
- if (n & 0x8000000000000000L)
- result = TOK.uns64Literal; // unsigned long
- else if (n & 0xFFFFFFFF80000000L)
- result = TOK.int64Literal; // long
- else
- result = TOK.int32Literal;
- }
+ result = TOK.int32Literal;
break;
case FLAGS.octalhex | FLAGS.unsigned:
case FLAGS.decimal | FLAGS.unsigned:
/* First that fits: unsigned, unsigned long, unsigned long long
*/
- if (longsize == 4)
- {
- if (n & 0xFFFFFFFF00000000L)
- result = TOK.uns64Literal;
- else
- result = TOK.uns32Literal;
- }
+ if (n & 0xFFFFFFFF00000000L)
+ result = TOK.uns64Literal; // unsigned long
else
- {
- if (n & 0xFFFFFFFF00000000L)
- result = TOK.uns64Literal; // unsigned long
- else
- result = TOK.uns32Literal;
- }
+ result = TOK.uns32Literal;
break;
case FLAGS.decimal | FLAGS.long_:
@@ -2510,19 +2314,14 @@ class Lexer
*/
if (longsize == 4)
{
- if (n & 0x8000000000000000L)
- overflow();
- else if (n & 0xFFFFFFFF_80000000L)
+ if (n & 0xFFFFFFFF_80000000L)
result = TOK.int64Literal;
else
- result = TOK.int32Literal; // long
+ result = TOK.int32Literal; // long
}
else
{
- if (n & 0x8000000000000000L)
- overflow();
- else
- result = TOK.int64Literal; // long
+ result = TOK.int64Literal; // long
}
break;
@@ -3353,6 +3152,11 @@ class Lexer
}
}
+
+/******************************* Private *****************************************/
+
+private:
+
/// Support for `__DATE__`, `__TIME__`, and `__TIMESTAMP__`
private struct TimeStampInfo
{
@@ -3389,6 +3193,121 @@ private struct TimeStampInfo
}
}
+private enum LS = 0x2028; // UTF line separator
+private enum PS = 0x2029; // UTF paragraph separator
+
+/********************************************
+ * Do our own char maps
+ */
+private static immutable cmtable = ()
+{
+ ubyte[256] table;
+ foreach (const c; 0 .. table.length)
+ {
+ if ('0' <= c && c <= '7')
+ table[c] |= CMoctal;
+ if (c_isxdigit(c))
+ table[c] |= CMhex;
+ if (c_isalnum(c) || c == '_')
+ table[c] |= CMidchar;
+
+ switch (c)
+ {
+ case 'x': case 'X':
+ case 'b': case 'B':
+ table[c] |= CMzerosecond;
+ break;
+
+ case '0': .. case '9':
+ case 'e': case 'E':
+ case 'f': case 'F':
+ case 'l': case 'L':
+ case 'p': case 'P':
+ case 'u': case 'U':
+ case 'i':
+ case '.':
+ case '_':
+ table[c] |= CMzerosecond | CMdigitsecond;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (c)
+ {
+ case '\\':
+ case '\n':
+ case '\r':
+ case 0:
+ case 0x1A:
+ case '\'':
+ break;
+ default:
+ if (!(c & 0x80))
+ table[c] |= CMsinglechar;
+ break;
+ }
+ }
+ return table;
+}();
+
+private
+{
+ enum CMoctal = 0x1;
+ enum CMhex = 0x2;
+ enum CMidchar = 0x4;
+ enum CMzerosecond = 0x8;
+ enum CMdigitsecond = 0x10;
+ enum CMsinglechar = 0x20;
+}
+
+private bool isoctal(const char c) pure @nogc @safe
+{
+ return (cmtable[c] & CMoctal) != 0;
+}
+
+private bool ishex(const char c) pure @nogc @safe
+{
+ return (cmtable[c] & CMhex) != 0;
+}
+
+private bool isidchar(const char c) pure @nogc @safe
+{
+ return (cmtable[c] & CMidchar) != 0;
+}
+
+private bool isZeroSecond(const char c) pure @nogc @safe
+{
+ return (cmtable[c] & CMzerosecond) != 0;
+}
+
+private bool isDigitSecond(const char c) pure @nogc @safe
+{
+ return (cmtable[c] & CMdigitsecond) != 0;
+}
+
+private bool issinglechar(const char c) pure @nogc @safe
+{
+ return (cmtable[c] & CMsinglechar) != 0;
+}
+
+private bool c_isxdigit(const int c) pure @nogc @safe
+{
+ return (( c >= '0' && c <= '9') ||
+ ( c >= 'a' && c <= 'f') ||
+ ( c >= 'A' && c <= 'F'));
+}
+
+private bool c_isalnum(const int c) pure @nogc @safe
+{
+ return (( c >= '0' && c <= '9') ||
+ ( c >= 'a' && c <= 'z') ||
+ ( c >= 'A' && c <= 'Z'));
+}
+
+/******************************* Unittest *****************************************/
+
unittest
{
import dmd.console;
@@ -3441,6 +3360,7 @@ unittest
diagnosticHandler = null;
}
+
unittest
{
import dmd.console;
@@ -3510,3 +3430,59 @@ unittest
diagnosticHandler = null;
}
+
+unittest
+{
+ //printf("lexer.unittest\n");
+ /* 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);
+ TOK tok;
+ tok = lex1.nextToken();
+ //printf("tok == %s, %d, %d\n", Token::toChars(tok), tok, TOK.int32);
+ assert(tok == TOK.int32);
+ tok = lex1.nextToken();
+ assert(tok == TOK.endOfFile);
+ tok = lex1.nextToken();
+ assert(tok == TOK.endOfFile);
+ tok = lex1.nextToken();
+ assert(tok == TOK.endOfFile);
+}
+
+unittest
+{
+ // We don't want to see Lexer error output during these tests.
+ uint errors = global.startGagging();
+ scope(exit) global.endGagging(errors);
+
+ // Test malformed input: even malformed input should end in a TOK.endOfFile.
+ static immutable char[][] testcases =
+ [ // Testcase must end with 0 or 0x1A.
+ [0], // not malformed, but pathological
+ ['\'', 0],
+ ['\'', 0x1A],
+ ['{', '{', 'q', '{', 0],
+ [0xFF, 0],
+ [0xFF, 0x80, 0],
+ [0xFF, 0xFF, 0],
+ [0xFF, 0xFF, 0],
+ ['x', '"', 0x1A],
+ ];
+
+ foreach (testcase; testcases)
+ {
+ scope Lexer lex2 = new Lexer(null, testcase.ptr, 0, testcase.length-1, 0, 0);
+ TOK tok = lex2.nextToken();
+ size_t iterations = 1;
+ while ((tok != TOK.endOfFile) && (iterations++ < testcase.length))
+ {
+ tok = lex2.nextToken();
+ }
+ assert(tok == TOK.endOfFile);
+ tok = lex2.nextToken();
+ assert(tok == TOK.endOfFile);
+ }
+}
+
+
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index fefad28..2897877 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -206,6 +206,32 @@ string MODtoString(MOD mod) nothrow pure
}
}
+/*************************************************
+ * Pick off one of the trust flags from trust,
+ * and return a string representation of it.
+ */
+string trustToString(TRUST trust) pure nothrow @nogc @safe
+{
+ final switch (trust)
+ {
+ case TRUST.default_:
+ return null;
+ case TRUST.system:
+ return "@system";
+ case TRUST.trusted:
+ return "@trusted";
+ case TRUST.safe:
+ return "@safe";
+ }
+}
+
+unittest
+{
+ assert(trustToString(TRUST.default_) == "");
+ assert(trustToString(TRUST.system) == "@system");
+ assert(trustToString(TRUST.trusted) == "@trusted");
+ assert(trustToString(TRUST.safe) == "@safe");
+}
/************************************
* Convert MODxxxx to STCxxx
@@ -400,7 +426,7 @@ extern (C++) abstract class Type : ASTNode
extern (C++) __gshared Type[TMAX] basic;
extern (D) __gshared StringTable!Type stringtable;
- extern (D) private __gshared ubyte[TMAX] sizeTy = ()
+ extern (D) private static immutable ubyte[TMAX] sizeTy = ()
{
ubyte[TMAX] sizeTy = __traits(classInstanceSize, TypeBasic);
sizeTy[Tsarray] = __traits(classInstanceSize, TypeSArray);
@@ -2604,6 +2630,10 @@ extern (C++) abstract class Type : ASTNode
default:
assert(0);
}
+ // @@@DEPRECATED_2.117@@@
+ // Deprecated in 2.097 - Can be made an error from 2.117.
+ // The deprecation period is longer than usual as `cfloat`,
+ // `cdouble`, and `creal` were quite widely used.
if (t.iscomplex())
{
deprecation(loc, "use of complex type `%s` is deprecated, use `std.complex.Complex!(%s)` instead",
@@ -4219,9 +4249,9 @@ extern (C++) final class TypeFunction : TypeNext
this.trust = TRUST.default_;
if (stc & STC.safe)
this.trust = TRUST.safe;
- if (stc & STC.system)
+ else if (stc & STC.system)
this.trust = TRUST.system;
- if (stc & STC.trusted)
+ else if (stc & STC.trusted)
this.trust = TRUST.trusted;
}
@@ -6346,7 +6376,7 @@ extern (C++) final class TypeClass : Type
/* Conversion derived to const(base)
*/
int offset = 0;
- if (to.isBaseOf(this, &offset) && offset == 0 && MODimplicitConv(mod, to.mod))
+ if (to.isBaseOf(this, &offset) && MODimplicitConv(mod, to.mod))
{
// Disallow:
// derived to base
@@ -7253,10 +7283,9 @@ void attributesApply(const TypeFunction tf, void delegate(string) dg, TRUSTforma
if (trustAttrib == TRUST.default_)
{
- if (trustFormat == TRUSTformatSystem)
- trustAttrib = TRUST.system;
- else
- return; // avoid calling with an empty string
+ if (trustFormat != TRUSTformatSystem)
+ return;
+ trustAttrib = TRUST.system; // avoid calling with an empty string
}
dg(trustToString(trustAttrib));
diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d
index f25e779..d6735d4 100644
--- a/gcc/d/dmd/nogc.d
+++ b/gcc/d/dmd/nogc.d
@@ -84,20 +84,6 @@ public:
}
f.printGCUsage(e.loc, "setting `length` may cause a GC allocation");
}
- else if (fd.ident == Id._d_delstruct)
- {
- // In expressionsem.d, `delete s` was lowererd to `_d_delstruct(s)`.
- // The following code handles the call like the original expression,
- // so the error is menaningful to the user.
- if (f.setGC())
- {
- e.error("cannot use `delete` in `@nogc` %s `%s`", f.kind(),
- f.toPrettyChars());
- err = true;
- return;
- }
- f.printGCUsage(e.loc, "`delete` requires the GC");
- }
}
override void visit(ArrayLiteralExp e)
@@ -158,32 +144,8 @@ public:
return; // delete for scope allocated class object
}
- Type tb = e.e1.type.toBasetype();
- AggregateDeclaration ad = null;
- switch (tb.ty)
- {
- case Tclass:
- ad = (cast(TypeClass)tb).sym;
- break;
-
- case Tpointer:
- tb = (cast(TypePointer)tb).next.toBasetype();
- if (tb.ty == Tstruct)
- ad = (cast(TypeStruct)tb).sym;
- break;
-
- default:
- break;
- }
-
- if (f.setGC())
- {
- e.error("cannot use `delete` in `@nogc` %s `%s`",
- f.kind(), f.toPrettyChars());
- err = true;
- return;
- }
- f.printGCUsage(e.loc, "`delete` requires the GC");
+ // Semantic should have already handled this case.
+ assert(0);
}
override void visit(IndexExp e)
diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d
index 5d6128b..01708d6 100644
--- a/gcc/d/dmd/opover.d
+++ b/gcc/d/dmd/opover.d
@@ -272,31 +272,17 @@ private Expression checkAliasThisForRhs(AggregateDeclaration ad, Scope* sc, BinE
*/
Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
{
- extern (C++) final class OpOverload : Visitor
- {
- alias visit = Visitor.visit;
- public:
- Scope* sc;
- EXP* pop;
- Expression result;
-
- extern (D) this(Scope* sc, EXP* pop)
- {
- this.sc = sc;
- this.pop = pop;
- }
-
- override void visit(Expression e)
+ Expression visit(Expression e)
{
assert(0);
}
- override void visit(UnaExp e)
+ Expression visitUna(UnaExp e)
{
//printf("UnaExp::op_overload() (%s)\n", e.toChars());
- if (e.e1.op == EXP.array)
+ Expression result;
+ if (auto ae = e.e1.isArrayExp())
{
- ArrayExp ae = cast(ArrayExp)e.e1;
ae.e1 = ae.e1.expressionSemantic(sc);
ae.e1 = resolveProperties(sc, ae.e1);
Expression ae1old = ae.e1;
@@ -304,15 +290,13 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
IntervalExp ie = null;
if (maybeSlice && ae.arguments.dim)
{
- assert((*ae.arguments)[0].op == EXP.interval);
- ie = cast(IntervalExp)(*ae.arguments)[0];
+ ie = (*ae.arguments)[0].isIntervalExp();
}
while (true)
{
if (ae.e1.op == EXP.error)
{
- result = ae.e1;
- return;
+ return ae.e1;
}
Expression e0 = null;
Expression ae1save = ae.e1;
@@ -328,7 +312,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if (!result) // op(a[i..j]) might be: a.opSliceUnary!(op)(i, j)
goto Lfallback;
if (result.op == EXP.error)
- return;
+ return result;
/* Rewrite op(a[arguments]) as:
* a.opIndexUnary!(op)(arguments)
*/
@@ -342,8 +326,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
result = result.expressionSemantic(sc);
if (result)
{
- result = Expression.combine(e0, result);
- return;
+ return Expression.combine(e0, result);
}
}
Lfallback:
@@ -352,7 +335,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
// Deal with $
result = resolveOpDollar(sc, ae, ie, &e0);
if (result.op == EXP.error)
- return;
+ return result;
/* Rewrite op(a[i..j]) as:
* a.opSliceUnary!(op)(i, j)
*/
@@ -367,7 +350,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
result = new CallExp(e.loc, result, a);
result = result.expressionSemantic(sc);
result = Expression.combine(e0, result);
- return;
+ return result;
}
// Didn't find it. Forward to aliasthis
if (ad.aliasthis && !isRecursiveAliasThis(ae.att1, ae.e1.type))
@@ -388,8 +371,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
e.e1 = resolveProperties(sc, e.e1);
if (e.e1.op == EXP.error)
{
- result = e.e1;
- return;
+ return e.e1;
}
AggregateDeclaration ad = isAggregate(e.e1.type);
if (ad)
@@ -405,7 +387,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
result = new DotTemplateInstanceExp(e.loc, e.e1, fd.ident, tiargs);
result = new CallExp(e.loc, result);
result = result.expressionSemantic(sc);
- return;
+ return result;
}
// D1-style operator overloads, deprecated
if (e.op != EXP.prePlusPlus && e.op != EXP.preMinusMinus)
@@ -420,7 +402,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
e.deprecation("`%s` is deprecated. Use `opUnary(string op)() if (op == \"%s\")` instead.", id.toChars(), EXPtoString(e.op).ptr);
// Rewrite +e1 as e1.add()
result = build_overload(e.loc, sc, e.e1, null, fd);
- return;
+ return result;
}
}
// Didn't find it. Forward to aliasthis
@@ -434,12 +416,13 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
UnaExp ue = cast(UnaExp)e.copy();
ue.e1 = e1;
result = ue.trySemantic(sc);
- return;
+ return result;
}
}
+ return result;
}
- override void visit(ArrayExp ae)
+ Expression visitArray(ArrayExp ae)
{
//printf("ArrayExp::op_overload() (%s)\n", ae.toChars());
ae.e1 = ae.e1.expressionSemantic(sc);
@@ -449,15 +432,14 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
IntervalExp ie = null;
if (maybeSlice && ae.arguments.dim)
{
- assert((*ae.arguments)[0].op == EXP.interval);
- ie = cast(IntervalExp)(*ae.arguments)[0];
+ ie = (*ae.arguments)[0].isIntervalExp();
}
+ Expression result;
while (true)
{
if (ae.e1.op == EXP.error)
{
- result = ae.e1;
- return;
+ return ae.e1;
}
Expression e0 = null;
Expression ae1save = ae.e1;
@@ -475,14 +457,14 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
{
result = new SliceExp(ae.loc, ae.e1, ie);
result = result.expressionSemantic(sc);
- return;
+ return result;
}
// Convert to IndexExp
if (ae.arguments.dim == 1)
{
result = new IndexExp(ae.loc, ae.e1, (*ae.arguments)[0]);
result = result.expressionSemantic(sc);
- return;
+ return result;
}
}
break;
@@ -494,7 +476,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if (!result) // a[i..j] might be: a.opSlice(i, j)
goto Lfallback;
if (result.op == EXP.error)
- return;
+ return result;
/* Rewrite e1[arguments] as:
* e1.opIndex(arguments)
*/
@@ -507,8 +489,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
result = result.expressionSemantic(sc);
if (result)
{
- result = Expression.combine(e0, result);
- return;
+ return Expression.combine(e0, result);
}
}
Lfallback:
@@ -517,7 +498,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
result = new SliceExp(ae.loc, ae.e1, ie);
result = result.expressionSemantic(sc);
result = Expression.combine(e0, result);
- return;
+ return result;
}
if (maybeSlice && search_function(ad, Id.slice))
{
@@ -529,7 +510,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if (!e0 && !search_function(ad, Id.dollar)) {
ae.loc.errorSupplemental("Aggregate declaration '%s' does not define 'opDollar'", ae.e1.toChars());
}
- return;
+ return result;
}
/* Rewrite a[i..j] as:
* a.opSlice(i, j)
@@ -544,7 +525,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
result = new CallExp(ae.loc, result, a);
result = result.expressionSemantic(sc);
result = Expression.combine(e0, result);
- return;
+ return result;
}
// Didn't find it. Forward to aliasthis
if (ad.aliasthis && !isRecursiveAliasThis(ae.att1, ae.e1.type))
@@ -561,15 +542,17 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
}
ae.e1 = ae1old; // recovery
ae.lengthVar = null;
+ return result;
}
/***********************************************
* This is mostly the same as UnaryExp::op_overload(), but has
* a different rewrite.
*/
- override void visit(CastExp e)
+ Expression visitCast(CastExp e)
{
//printf("CastExp::op_overload() (%s)\n", e.toChars());
+ Expression result;
AggregateDeclaration ad = isAggregate(e.e1.type);
if (ad)
{
@@ -586,8 +569,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if (fd.isFuncDeclaration())
{
// Rewrite as: e1.opCast()
- result = build_overload(e.loc, sc, e.e1, null, fd);
- return;
+ return build_overload(e.loc, sc, e.e1, null, fd);
}
}
auto tiargs = new Objects();
@@ -595,7 +577,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
result = new DotTemplateInstanceExp(e.loc, e.e1, fd.ident, tiargs);
result = new CallExp(e.loc, result);
result = result.expressionSemantic(sc);
- return;
+ return result;
}
// Didn't find it. Forward to aliasthis
if (ad.aliasthis && !isRecursiveAliasThis(e.att1, e.e1.type))
@@ -608,13 +590,14 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
result = e.copy();
(cast(UnaExp)result).e1 = e1;
result = result.op_overload(sc);
- return;
+ return result;
}
}
}
+ return result;
}
- override void visit(BinExp e)
+ Expression visitBin(BinExp e)
{
//printf("BinExp::op_overload() (%s)\n", e.toChars());
Identifier id = opId(e);
@@ -635,7 +618,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
(sd.hasBlitAssign && !e.e2.isLvalue())))
{
/* This is bitwise struct assignment. */
- return;
+ return null;
}
}
Dsymbol s = null;
@@ -645,7 +628,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
{
// Bug4099 fix
if (ad1 && search_function(ad1, Id.opUnary))
- return;
+ return null;
}
if (e.op != EXP.equal && e.op != EXP.notEqual && e.op != EXP.assign && e.op != EXP.plusPlus && e.op != EXP.minusMinus)
{
@@ -657,8 +640,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if (s && !s.isTemplateDeclaration())
{
e.e1.error("`%s.opBinary` isn't a template", e.e1.toChars());
- result = ErrorExp.get();
- return;
+ return ErrorExp.get();
}
}
if (ad2)
@@ -667,8 +649,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if (s_r && !s_r.isTemplateDeclaration())
{
e.e2.error("`%s.opBinaryRight` isn't a template", e.e2.toChars());
- result = ErrorExp.get();
- return;
+ return ErrorExp.get();
}
if (s_r && s_r == s) // https://issues.dlang.org/show_bug.cgi?id=12778
s_r = null;
@@ -735,8 +716,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2);
if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
{
- result = ErrorExp.get();
- return;
+ return ErrorExp.get();
}
}
FuncDeclaration lastf = m.lastf;
@@ -745,8 +725,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, &args1);
if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
{
- result = ErrorExp.get();
- return;
+ return ErrorExp.get();
}
}
if (m.count > 1)
@@ -766,19 +745,18 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
// as unary, but it's implemented as a binary.
// Rewrite (e1 ++ e2) as e1.postinc()
// Rewrite (e1 -- e2) as e1.postdec()
- result = build_overload(e.loc, sc, e.e1, null, m.lastf ? m.lastf : s);
+ return build_overload(e.loc, sc, e.e1, null, m.lastf ? m.lastf : s);
}
else if (lastf && m.lastf == lastf || !s_r && m.last == MATCH.nomatch)
{
// Rewrite (e1 op e2) as e1.opfunc(e2)
- result = build_overload(e.loc, sc, e.e1, e.e2, m.lastf ? m.lastf : s);
+ return build_overload(e.loc, sc, e.e1, e.e2, m.lastf ? m.lastf : s);
}
else
{
// Rewrite (e1 op e2) as e2.opfunc_r(e1)
- result = build_overload(e.loc, sc, e.e2, e.e1, m.lastf ? m.lastf : s_r);
+ return build_overload(e.loc, sc, e.e2, e.e1, m.lastf ? m.lastf : s_r);
}
- return;
}
L1:
version (all)
@@ -820,8 +798,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
functionResolve(m, s_r, e.loc, sc, tiargs, e.e1.type, &args2);
if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
{
- result = ErrorExp.get();
- return;
+ return ErrorExp.get();
}
}
FuncDeclaration lastf = m.lastf;
@@ -830,8 +807,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
functionResolve(m, s, e.loc, sc, tiargs, e.e2.type, &args1);
if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
{
- result = ErrorExp.get();
- return;
+ return ErrorExp.get();
}
}
if (m.count > 1)
@@ -847,27 +823,26 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if (lastf && m.lastf == lastf || !s && m.last == MATCH.nomatch)
{
// Rewrite (e1 op e2) as e1.opfunc_r(e2)
- result = build_overload(e.loc, sc, e.e1, e.e2, m.lastf ? m.lastf : s_r);
+ return build_overload(e.loc, sc, e.e1, e.e2, m.lastf ? m.lastf : s_r);
}
else
{
// Rewrite (e1 op e2) as e2.opfunc(e1)
- result = build_overload(e.loc, sc, e.e2, e.e1, m.lastf ? m.lastf : s);
+ Expression result = build_overload(e.loc, sc, e.e2, e.e1, m.lastf ? m.lastf : s);
// When reversing operands of comparison operators,
// need to reverse the sense of the op
if (pop)
*pop = reverseRelation(e.op);
+ return result;
}
- return;
}
}
}
- Expression tempResult;
+ Expression rewrittenLhs;
if (!(e.op == EXP.assign && ad2 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943
{
- result = checkAliasThisForLhs(ad1, sc, e);
- if (result)
+ if (Expression result = checkAliasThisForLhs(ad1, sc, e))
{
/* https://issues.dlang.org/show_bug.cgi?id=19441
*
@@ -880,43 +855,42 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
* one of the members, hence the `ad1.fields.dim == 2 && ad1.vthis`
* condition.
*/
- if (e.op != EXP.assign || e.e1.op == EXP.type)
- return;
+ if (result.op != EXP.assign)
+ return result; // i.e: Rewrote `e1 = e2` -> `e1(e2)`
+
+ auto ae = result.isAssignExp();
+ if (ae.e1.op != EXP.dotVariable)
+ return result; // i.e: Rewrote `e1 = e2` -> `e1() = e2`
- if (ad1.fields.dim == 1 || (ad1.fields.dim == 2 && ad1.vthis))
+ auto dve = ae.e1.isDotVarExp();
+ if (auto ad = dve.var.isMember2())
{
- auto var = ad1.aliasthis.sym.isVarDeclaration();
- if (var && var.type == ad1.fields[0].type)
- return;
-
- auto func = ad1.aliasthis.sym.isFuncDeclaration();
- auto tf = cast(TypeFunction)(func.type);
- if (tf.isref && ad1.fields[0].type == tf.next)
- return;
+ // i.e: Rewrote `e1 = e2` -> `e1.some.var = e2`
+ // Ensure that `var` is the only field member in `ad`
+ if (ad.fields.dim == 1 || (ad.fields.dim == 2 && ad.vthis))
+ {
+ if (dve.var == ad.aliasthis.sym)
+ return result;
+ }
}
- tempResult = result;
+ rewrittenLhs = ae.e1;
}
}
if (!(e.op == EXP.assign && ad1 && ad1 == ad2)) // https://issues.dlang.org/show_bug.cgi?id=2943
{
- result = checkAliasThisForRhs(ad2, sc, e);
- if (result)
- return;
+ if (Expression result = checkAliasThisForRhs(ad2, sc, e))
+ return result;
}
-
- // @@@DEPRECATED_2019-02@@@
- // 1. Deprecation for 1 year
- // 2. Turn to error after
- if (tempResult)
+ if (rewrittenLhs)
{
- // move this line where tempResult is assigned to result and turn to error when derecation period is over
- e.deprecation("Cannot use `alias this` to partially initialize variable `%s` of type `%s`. Use `%s`", e.e1.toChars(), ad1.toChars(), (cast(BinExp)tempResult).e1.toChars());
- // delete this line when deprecation period is over
- result = tempResult;
+ e.error("cannot use `alias this` to partially initialize variable `%s` of type `%s`. Use `%s`",
+ e.e1.toChars(), ad1.toChars(), rewrittenLhs.toChars());
+ return ErrorExp.get();
}
+ return null;
}
- override void visit(EqualExp e)
+ Expression visitEqual(EqualExp e)
{
//printf("EqualExp::op_overload() (%s)\n", e.toChars());
Type t1 = e.e1.type.toBasetype();
@@ -929,7 +903,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if ((t1.ty == Tarray || t1.ty == Tsarray) &&
(t2.ty == Tarray || t2.ty == Tsarray))
{
- return;
+ return null;
}
/* Check for class equality with null literal or typeof(null).
@@ -940,14 +914,13 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
e.error("use `%s` instead of `%s` when comparing with `null`",
EXPtoString(e.op == EXP.equal ? EXP.identity : EXP.notIdentity).ptr,
EXPtoString(e.op).ptr);
- result = ErrorExp.get();
- return;
+ return ErrorExp.get();
}
if (t1.ty == Tclass && t2.ty == Tnull ||
t1.ty == Tnull && t2.ty == Tclass)
{
// Comparing a class with typeof(null) should not call opEquals
- return;
+ return null;
}
/* Check for class equality.
@@ -973,26 +946,25 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if (cd2.isInterfaceDeclaration())
e2x = new CastExp(e.loc, e.e2, t2.isMutable() ? to : to.constOf());
- result = new IdentifierExp(e.loc, Id.empty);
+ Expression result = new IdentifierExp(e.loc, Id.empty);
result = new DotIdExp(e.loc, result, Id.object);
result = new DotIdExp(e.loc, result, Id.eq);
result = new CallExp(e.loc, result, e1x, e2x);
if (e.op == EXP.notEqual)
result = new NotExp(e.loc, result);
result = result.expressionSemantic(sc);
- return;
+ return result;
}
}
- result = compare_overload(e, sc, Id.eq, null);
- if (result)
+ if (Expression result = compare_overload(e, sc, Id.eq, null))
{
if (lastComma(result).op == EXP.call && e.op == EXP.notEqual)
{
result = new NotExp(result.loc, result);
result = result.expressionSemantic(sc);
}
- return;
+ return result;
}
/* Check for pointer equality.
@@ -1008,27 +980,25 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
* as the backend input.
*/
auto op2 = e.op == EXP.equal ? EXP.identity : EXP.notIdentity;
- result = new IdentityExp(op2, e.loc, e.e1, e.e2);
- result = result.expressionSemantic(sc);
- return;
+ Expression r = new IdentityExp(op2, e.loc, e.e1, e.e2);
+ return r.expressionSemantic(sc);
}
/* Check for struct equality without opEquals.
*/
if (t1.ty == Tstruct && t2.ty == Tstruct)
{
- auto sd = (cast(TypeStruct)t1).sym;
- if (sd != (cast(TypeStruct)t2).sym)
- return;
+ auto sd = t1.isTypeStruct().sym;
+ if (sd != t2.isTypeStruct().sym)
+ return null;
import dmd.clone : needOpEquals;
if (!global.params.fieldwise && !needOpEquals(sd))
{
// Use bitwise equality.
auto op2 = e.op == EXP.equal ? EXP.identity : EXP.notIdentity;
- result = new IdentityExp(op2, e.loc, e.e1, e.e2);
- result = result.expressionSemantic(sc);
- return;
+ Expression r = new IdentityExp(op2, e.loc, e.e1, e.e2);
+ return r.expressionSemantic(sc);
}
/* Do memberwise equality.
@@ -1042,10 +1012,10 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
* also compare the parent class's equality. Otherwise, compares
* the identity of parent context through void*.
*/
- if (e.att1 && t1.equivalent(e.att1)) return;
- if (e.att2 && t2.equivalent(e.att2)) return;
+ if (e.att1 && t1.equivalent(e.att1)) return null;
+ if (e.att2 && t2.equivalent(e.att2)) return null;
- e = cast(EqualExp)e.copy();
+ e = e.copy().isEqualExp();
if (!e.att1) e.att1 = t1;
if (!e.att2) e.att2 = t2;
e.e1 = new DotIdExp(e.loc, e.e1, Id._tupleof);
@@ -1053,38 +1023,38 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
auto sc2 = sc.push();
sc2.flags |= SCOPE.noaccesscheck;
- result = e.expressionSemantic(sc2);
+ Expression r = e.expressionSemantic(sc2);
sc2.pop();
/* https://issues.dlang.org/show_bug.cgi?id=15292
* if the rewrite result is same with the original,
* the equality is unresolvable because it has recursive definition.
*/
- if (result.op == e.op &&
- (cast(EqualExp)result).e1.type.toBasetype() == t1)
+ if (r.op == e.op &&
+ r.isEqualExp().e1.type.toBasetype() == t1)
{
e.error("cannot compare `%s` because its auto generated member-wise equality has recursive definition",
t1.toChars());
- result = ErrorExp.get();
+ return ErrorExp.get();
}
- return;
+ return r;
}
/* Check for tuple equality.
*/
if (e.e1.op == EXP.tuple && e.e2.op == EXP.tuple)
{
- auto tup1 = cast(TupleExp)e.e1;
- auto tup2 = cast(TupleExp)e.e2;
+ auto tup1 = e.e1.isTupleExp();
+ auto tup2 = e.e2.isTupleExp();
size_t dim = tup1.exps.dim;
if (dim != tup2.exps.dim)
{
e.error("mismatched tuple lengths, `%d` and `%d`",
cast(int)dim, cast(int)tup2.exps.dim);
- result = ErrorExp.get();
- return;
+ return ErrorExp.get();
}
+ Expression result;
if (dim == 0)
{
// zero-length tuple comparison should always return true or false.
@@ -1112,25 +1082,25 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
result = Expression.combine(tup1.e0, tup2.e0, result);
result = result.expressionSemantic(sc);
- return;
+ return result;
}
+ return null;
}
- override void visit(CmpExp e)
+ Expression visitCmp(CmpExp e)
{
//printf("CmpExp:: () (%s)\n", e.toChars());
- result = compare_overload(e, sc, Id.cmp, pop);
+ return compare_overload(e, sc, Id.cmp, pop);
}
/*********************************
* Operator overloading for op=
*/
- override void visit(BinAssignExp e)
+ Expression visitBinAssign(BinAssignExp e)
{
//printf("BinAssignExp::op_overload() (%s)\n", e.toChars());
- if (e.e1.op == EXP.array)
+ if (auto ae = e.e1.isArrayExp())
{
- ArrayExp ae = cast(ArrayExp)e.e1;
ae.e1 = ae.e1.expressionSemantic(sc);
ae.e1 = resolveProperties(sc, ae.e1);
Expression ae1old = ae.e1;
@@ -1138,15 +1108,13 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
IntervalExp ie = null;
if (maybeSlice && ae.arguments.dim)
{
- assert((*ae.arguments)[0].op == EXP.interval);
- ie = cast(IntervalExp)(*ae.arguments)[0];
+ ie = (*ae.arguments)[0].isIntervalExp();
}
while (true)
{
if (ae.e1.op == EXP.error)
{
- result = ae.e1;
- return;
+ return ae.e1;
}
Expression e0 = null;
Expression ae1save = ae.e1;
@@ -1158,14 +1126,14 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if (search_function(ad, Id.opIndexOpAssign))
{
// Deal with $
- result = resolveOpDollar(sc, ae, &e0);
+ Expression result = resolveOpDollar(sc, ae, &e0);
if (!result) // (a[i..j] op= e2) might be: a.opSliceOpAssign!(op)(e2, i, j)
goto Lfallback;
if (result.op == EXP.error)
- return;
+ return result;
result = e.e2.expressionSemantic(sc);
if (result.op == EXP.error)
- return;
+ return result;
e.e2 = result;
/* Rewrite a[arguments] op= e2 as:
* a.opIndexOpAssign!(op)(e2, arguments)
@@ -1181,20 +1149,19 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
result = result.expressionSemantic(sc);
if (result)
{
- result = Expression.combine(e0, result);
- return;
+ return Expression.combine(e0, result);
}
}
Lfallback:
if (maybeSlice && search_function(ad, Id.opSliceOpAssign))
{
// Deal with $
- result = resolveOpDollar(sc, ae, ie, &e0);
+ Expression result = resolveOpDollar(sc, ae, ie, &e0);
if (result.op == EXP.error)
- return;
+ return result;
result = e.e2.expressionSemantic(sc);
if (result.op == EXP.error)
- return;
+ return result;
e.e2 = result;
/* Rewrite (a[i..j] op= e2) as:
* a.opSliceOpAssign!(op)(e2, i, j)
@@ -1211,7 +1178,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
result = new CallExp(e.loc, result, a);
result = result.expressionSemantic(sc);
result = Expression.combine(e0, result);
- return;
+ return result;
}
// Didn't find it. Forward to aliasthis
if (ad.aliasthis && !isRecursiveAliasThis(ae.att1, ae.e1.type))
@@ -1228,14 +1195,13 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
ae.e1 = ae1old; // recovery
ae.lengthVar = null;
}
- result = e.binSemanticProp(sc);
+ Expression result = e.binSemanticProp(sc);
if (result)
- return;
+ return result;
// Don't attempt 'alias this' if an error occurred
if (e.e1.type.ty == Terror || e.e2.type.ty == Terror)
{
- result = ErrorExp.get();
- return;
+ return ErrorExp.get();
}
Identifier id = opId(e);
Expressions args2;
@@ -1250,8 +1216,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if (s && !s.isTemplateDeclaration())
{
e.error("`%s.opOpAssign` isn't a template", e.e1.toChars());
- result = ErrorExp.get();
- return;
+ return ErrorExp.get();
}
}
// Set tiargs, the template argument list, which will be the operator string
@@ -1290,8 +1255,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2);
if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
{
- result = ErrorExp.get();
- return;
+ return ErrorExp.get();
}
}
if (m.count > 1)
@@ -1306,23 +1270,38 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
m.lastf = null;
}
// Rewrite (e1 op e2) as e1.opOpAssign(e2)
- result = build_overload(e.loc, sc, e.e1, e.e2, m.lastf ? m.lastf : s);
- return;
+ return build_overload(e.loc, sc, e.e1, e.e2, m.lastf ? m.lastf : s);
}
L1:
result = checkAliasThisForLhs(ad1, sc, e);
if (result || !s) // no point in trying Rhs alias-this if there's no overload of any kind in lhs
- return;
+ return result;
- result = checkAliasThisForRhs(isAggregate(e.e2.type), sc, e);
+ return checkAliasThisForRhs(isAggregate(e.e2.type), sc, e);
}
- }
if (pop)
*pop = e.op;
- scope OpOverload v = new OpOverload(sc, pop);
- e.accept(v);
- return v.result;
+
+ switch (e.op)
+ {
+ case EXP.cast_ : return visitCast(e.isCastExp());
+ case EXP.array : return visitArray(e.isArrayExp());
+
+ case EXP.notEqual :
+ case EXP.equal : return visitEqual(e.isEqualExp());
+
+ case EXP.lessOrEqual :
+ case EXP.greaterThan :
+ case EXP.greaterOrEqual:
+ case EXP.lessThan : return visitCmp(cast(CmpExp)e);
+
+ default:
+ if (auto ex = e.isBinAssignExp()) return visitBinAssign(ex);
+ if (auto ex = e.isBinExp()) return visitBin(ex);
+ if (auto ex = e.isUnaExp()) return visitUna(ex);
+ return visit(e);
+ }
}
/******************************************
@@ -1505,8 +1484,8 @@ bool inferForeachAggregate(Scope* sc, bool isForeach, ref Expression feaggr, out
case Tclass:
case Tstruct:
{
- AggregateDeclaration ad = (tab.ty == Tclass) ? (cast(TypeClass)tab).sym
- : (cast(TypeStruct)tab).sym;
+ AggregateDeclaration ad = (tab.ty == Tclass) ? tab.isTypeClass().sym
+ : tab.isTypeStruct().sym;
if (!sliced)
{
sapply = search_function(ad, isForeach ? Id.apply : Id.applyReverse);
@@ -1547,9 +1526,9 @@ bool inferForeachAggregate(Scope* sc, bool isForeach, ref Expression feaggr, out
}
case Tdelegate: // https://dlang.org/spec/statement.html#foreach_over_delegates
- if (aggr.op == EXP.delegate_)
+ if (auto de = aggr.isDelegateExp())
{
- sapply = (cast(DelegateExp)aggr).func;
+ sapply = de.func;
}
break;
@@ -1600,7 +1579,7 @@ bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
else
{
assert(tab.ty == Tdelegate && fes.aggr.op == EXP.delegate_);
- ethis = (cast(DelegateExp)fes.aggr).e1;
+ ethis = fes.aggr.isDelegateExp().e1;
}
/* Look for like an
@@ -1613,7 +1592,7 @@ bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
if (fdapply)
{
// Fill in any missing types on foreach parameters[]
- matchParamsToOpApply(cast(TypeFunction)fdapply.type, fes.parameters, true);
+ matchParamsToOpApply(fdapply.type.isTypeFunction(), fes.parameters, true);
sapply = fdapply;
return true;
}
@@ -1649,7 +1628,7 @@ bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
case Taarray:
{
- TypeAArray taa = cast(TypeAArray)tab;
+ TypeAArray taa = tab.isTypeAArray();
if (fes.parameters.dim == 2)
{
if (!p.type)
@@ -1672,8 +1651,8 @@ bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
case Tclass:
case Tstruct:
{
- AggregateDeclaration ad = (tab.ty == Tclass) ? (cast(TypeClass)tab).sym
- : (cast(TypeStruct)tab).sym;
+ AggregateDeclaration ad = (tab.ty == Tclass) ? tab.isTypeClass().sym
+ : tab.isTypeStruct().sym;
if (fes.parameters.dim == 1)
{
if (!p.type)
@@ -1697,7 +1676,7 @@ bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
{
}
else if (s && s.isDeclaration())
- p.type = (cast(Declaration)s).type;
+ p.type = s.isDeclaration().type;
else
break;
}
@@ -1707,9 +1686,12 @@ bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
}
case Tdelegate:
- if (!matchParamsToOpApply(cast(TypeFunction)tab.nextOf(), fes.parameters, true))
+ {
+ auto td = tab.isTypeDelegate();
+ if (!matchParamsToOpApply(td.next.isTypeFunction(), fes.parameters, true))
return false;
break;
+ }
default:
break; // ignore error, caught later
@@ -1738,7 +1720,7 @@ private FuncDeclaration findBestOpApplyMatch(Expression ethis, FuncDeclaration f
auto f = s.isFuncDeclaration();
if (!f)
return 0; // continue
- auto tf = cast(TypeFunction)f.type;
+ auto tf = f.type.isTypeFunction();
MATCH m = MATCH.exact;
if (f.isThis())
{
@@ -1825,10 +1807,10 @@ private bool matchParamsToOpApply(TypeFunction tf, Parameters* parameters, bool
/* Get the type of opApply's dg parameter
*/
Parameter p0 = tf.parameterList[0];
- if (p0.type.ty != Tdelegate)
+ auto de = p0.type.isTypeDelegate();
+ if (!de)
return nomatch;
- TypeFunction tdg = cast(TypeFunction)p0.type.nextOf();
- assert(tdg.ty == Tfunction);
+ TypeFunction tdg = de.next.isTypeFunction();
/* We now have tdg, the type of the delegate.
* tdg's parameters must match that of the foreach arglist (i.e. parameters).
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index 5b4ebd7..3653aa8 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -631,13 +631,6 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
{
expOptimize(e.thisexp, WANTvalue);
// Optimize parameters
- if (e.newargs)
- {
- for (size_t i = 0; i < e.newargs.dim; i++)
- {
- expOptimize((*e.newargs)[i], WANTvalue);
- }
- }
if (e.arguments)
{
for (size_t i = 0; i < e.arguments.dim; i++)
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 63afeb2..e83b326 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -28,268 +28,6 @@ import dmd.root.rootobject;
import dmd.root.string;
import dmd.tokens;
-// How multiple declarations are parsed.
-// If 1, treat as C.
-// If 0, treat:
-// int *p, i;
-// as:
-// int* p;
-// int* i;
-private enum CDECLSYNTAX = 0;
-
-// Support C cast syntax:
-// (type)(expression)
-private enum CCASTSYNTAX = 1;
-
-// Support postfix C array declarations, such as
-// int a[3][4];
-private enum CARRAYDECL = 1;
-
-/**********************************
- * Set operator precedence for each operator.
- *
- * Used by hdrgen
- */
-immutable PREC[EXP.max + 1] precedence =
-[
- EXP.type : PREC.expr,
- EXP.error : PREC.expr,
- EXP.objcClassReference : PREC.expr, // Objective-C class reference, same as EXP.type
-
- EXP.typeof_ : PREC.primary,
- EXP.mixin_ : PREC.primary,
-
- EXP.import_ : PREC.primary,
- EXP.dotVariable : PREC.primary,
- EXP.scope_ : PREC.primary,
- EXP.identifier : PREC.primary,
- EXP.this_ : PREC.primary,
- EXP.super_ : PREC.primary,
- EXP.int64 : PREC.primary,
- EXP.float64 : PREC.primary,
- EXP.complex80 : PREC.primary,
- EXP.null_ : PREC.primary,
- EXP.string_ : PREC.primary,
- EXP.arrayLiteral : PREC.primary,
- EXP.assocArrayLiteral : PREC.primary,
- EXP.classReference : PREC.primary,
- EXP.file : PREC.primary,
- EXP.fileFullPath : PREC.primary,
- EXP.line : PREC.primary,
- EXP.moduleString : PREC.primary,
- EXP.functionString : PREC.primary,
- EXP.prettyFunction : PREC.primary,
- EXP.typeid_ : PREC.primary,
- EXP.is_ : PREC.primary,
- EXP.assert_ : PREC.primary,
- EXP.halt : PREC.primary,
- EXP.template_ : PREC.primary,
- EXP.dSymbol : PREC.primary,
- EXP.function_ : PREC.primary,
- EXP.variable : PREC.primary,
- EXP.symbolOffset : PREC.primary,
- EXP.structLiteral : PREC.primary,
- EXP.compoundLiteral : PREC.primary,
- EXP.arrayLength : PREC.primary,
- EXP.delegatePointer : PREC.primary,
- EXP.delegateFunctionPointer : PREC.primary,
- EXP.remove : PREC.primary,
- EXP.tuple : PREC.primary,
- EXP.traits : PREC.primary,
- EXP.default_ : PREC.primary,
- EXP.overloadSet : PREC.primary,
- EXP.void_ : PREC.primary,
- EXP.vectorArray : PREC.primary,
- EXP._Generic : PREC.primary,
-
- // post
- EXP.dotTemplateInstance : PREC.primary,
- EXP.dotIdentifier : PREC.primary,
- EXP.dotTemplateDeclaration : PREC.primary,
- EXP.dot : PREC.primary,
- EXP.dotType : PREC.primary,
- EXP.plusPlus : PREC.primary,
- EXP.minusMinus : PREC.primary,
- EXP.prePlusPlus : PREC.primary,
- EXP.preMinusMinus : PREC.primary,
- EXP.call : PREC.primary,
- EXP.slice : PREC.primary,
- EXP.array : PREC.primary,
- EXP.index : PREC.primary,
-
- EXP.delegate_ : PREC.unary,
- EXP.address : PREC.unary,
- EXP.star : PREC.unary,
- EXP.negate : PREC.unary,
- EXP.uadd : PREC.unary,
- EXP.not : PREC.unary,
- EXP.tilde : PREC.unary,
- EXP.delete_ : PREC.unary,
- EXP.new_ : PREC.unary,
- EXP.newAnonymousClass : PREC.unary,
- EXP.cast_ : PREC.unary,
- EXP.throw_ : PREC.unary,
-
- EXP.vector : PREC.unary,
- EXP.pow : PREC.pow,
-
- EXP.mul : PREC.mul,
- EXP.div : PREC.mul,
- EXP.mod : PREC.mul,
-
- EXP.add : PREC.add,
- EXP.min : PREC.add,
- EXP.concatenate : PREC.add,
-
- EXP.leftShift : PREC.shift,
- EXP.rightShift : PREC.shift,
- EXP.unsignedRightShift : PREC.shift,
-
- EXP.lessThan : PREC.rel,
- EXP.lessOrEqual : PREC.rel,
- EXP.greaterThan : PREC.rel,
- EXP.greaterOrEqual : PREC.rel,
- EXP.in_ : PREC.rel,
-
- /* Note that we changed precedence, so that < and != have the same
- * precedence. This change is in the parser, too.
- */
- EXP.equal : PREC.rel,
- EXP.notEqual : PREC.rel,
- EXP.identity : PREC.rel,
- EXP.notIdentity : PREC.rel,
-
- EXP.and : PREC.and,
- EXP.xor : PREC.xor,
- EXP.or : PREC.or,
-
- EXP.andAnd : PREC.andand,
- EXP.orOr : PREC.oror,
-
- EXP.question : PREC.cond,
-
- EXP.assign : PREC.assign,
- EXP.construct : PREC.assign,
- EXP.blit : PREC.assign,
- EXP.addAssign : PREC.assign,
- EXP.minAssign : PREC.assign,
- EXP.concatenateAssign : PREC.assign,
- EXP.concatenateElemAssign : PREC.assign,
- EXP.concatenateDcharAssign : PREC.assign,
- EXP.mulAssign : PREC.assign,
- EXP.divAssign : PREC.assign,
- EXP.modAssign : PREC.assign,
- EXP.powAssign : PREC.assign,
- EXP.leftShiftAssign : PREC.assign,
- EXP.rightShiftAssign : PREC.assign,
- EXP.unsignedRightShiftAssign : PREC.assign,
- EXP.andAssign : PREC.assign,
- EXP.orAssign : PREC.assign,
- EXP.xorAssign : PREC.assign,
-
- EXP.comma : PREC.expr,
- EXP.declaration : PREC.expr,
-
- EXP.interval : PREC.assign,
-];
-
-enum ParseStatementFlags : int
-{
- semi = 1, // empty ';' statements are allowed, but deprecated
- scope_ = 2, // start a new scope
- curly = 4, // { } statement is required
- curlyScope = 8, // { } starts a new scope
- semiOk = 0x10, // empty ';' are really ok
-}
-
-struct PrefixAttributes(AST)
-{
- StorageClass storageClass;
- AST.Expression depmsg;
- LINK link;
- AST.Visibility visibility;
- bool setAlignment;
- AST.Expression ealign;
- AST.Expressions* udas;
- const(char)* comment;
-}
-
-/// The result of the `ParseLinkage` function
-struct ParsedLinkage(AST)
-{
- /// What linkage was specified
- LINK link;
- /// If `extern(C++, class|struct)`, contains the `class|struct`
- CPPMANGLE cppmangle;
- /// If `extern(C++, some.identifier)`, will be the identifiers
- AST.Identifiers* idents;
- /// If `extern(C++, (some_tuple_expression)|"string"), will be the expressions
- AST.Expressions* identExps;
-}
-
-/*****************************
- * Destructively extract storage class from pAttrs.
- */
-private StorageClass getStorageClass(AST)(PrefixAttributes!(AST)* pAttrs)
-{
- StorageClass stc = STC.undefined_;
- if (pAttrs)
- {
- stc = pAttrs.storageClass;
- pAttrs.storageClass = STC.undefined_;
- }
- return stc;
-}
-
-/**************************************
- * dump mixin expansion to file for better debugging
- */
-private bool writeMixin(const(char)[] s, ref Loc loc)
-{
- if (!global.params.mixinOut)
- return false;
-
- OutBuffer* ob = global.params.mixinOut;
-
- ob.writestring("// expansion at ");
- ob.writestring(loc.toChars());
- ob.writenl();
-
- global.params.mixinLines++;
-
- loc = Loc(global.params.mixinFile, global.params.mixinLines + 1, loc.charnum);
-
- // write by line to create consistent line endings
- size_t lastpos = 0;
- for (size_t i = 0; i < s.length; ++i)
- {
- // detect LF and CRLF
- const c = s[i];
- if (c == '\n' || (c == '\r' && i+1 < s.length && s[i+1] == '\n'))
- {
- ob.writestring(s[lastpos .. i]);
- ob.writenl();
- global.params.mixinLines++;
- if (c == '\r')
- ++i;
- lastpos = i + 1;
- }
- }
-
- if(lastpos < s.length)
- ob.writestring(s[lastpos .. $]);
-
- if (s.length == 0 || s[$-1] != '\n')
- {
- ob.writenl(); // ensure empty line after expansion
- global.params.mixinLines++;
- }
- ob.writenl();
- global.params.mixinLines++;
-
- return true;
-}
-
/***********************************************************
*/
class Parser(AST) : Lexer
@@ -344,80 +82,49 @@ class Parser(AST) : Lexer
//nextToken(); // start up the scanner
}
+ /++
+ + Parse a module, i.e. the optional `module x.y.z` declaration and all declarations
+ + found in the current file.
+ +
+ + Returns: the list of declarations or an empty list in case of malformed declarations,
+ + the module declaration will be stored as `this.md` if found
+ +/
AST.Dsymbols* parseModule()
{
+ if (!parseModuleDeclaration())
+ return errorReturn();
+
+ return parseModuleContent();
+ }
+
+ /++
+ + Parse the optional module declaration
+ +
+ + Returns: false if a malformed module declaration was found
+ +/
+ final bool parseModuleDeclaration()
+ {
const comment = token.blockComment;
bool isdeprecated = false;
AST.Expression msg = null;
- AST.Expressions* udas = null;
- AST.Dsymbols* decldefs;
- AST.Dsymbol lastDecl = mod; // for attaching ddoc unittests to module decl
-
- Token* tk;
- if (skipAttributes(&token, &tk) && tk.value == TOK.module_)
- {
- while (token.value != TOK.module_)
- {
- switch (token.value)
- {
- case TOK.deprecated_:
- {
- // deprecated (...) module ...
- if (isdeprecated)
- error("there is only one deprecation attribute allowed for module declaration");
- isdeprecated = true;
- nextToken();
- if (token.value == TOK.leftParenthesis)
- {
- check(TOK.leftParenthesis);
- msg = parseAssignExp();
- check(TOK.rightParenthesis);
- }
- break;
- }
- case TOK.at:
- {
- AST.Expressions* exps = null;
- const stc = parseAttribute(exps);
- if (stc & atAttrGroup)
- {
- error("`@%s` attribute for module declaration is not supported", token.toChars());
- }
- else
- {
- udas = AST.UserAttributeDeclaration.concat(udas, exps);
- }
- if (stc)
- nextToken();
- break;
- }
- default:
- {
- error("`module` expected instead of `%s`", token.toChars());
- nextToken();
- break;
- }
- }
- }
- }
- if (udas)
- {
- auto a = new AST.Dsymbols();
- auto udad = new AST.UserAttributeDeclaration(udas, a);
- mod.userAttribDecl = udad;
- }
+ // Parse optional module attributes
+ parseModuleAttributes(msg, isdeprecated);
- // ModuleDeclation leads off
+ // ModuleDeclaration leads off
if (token.value == TOK.module_)
{
const loc = token.loc;
-
nextToken();
+
+ /* parse ModuleFullyQualifiedName
+ * https://dlang.org/spec/module.html#ModuleFullyQualifiedName
+ */
+
if (token.value != TOK.identifier)
{
error("identifier expected following `module`");
- goto Lerr;
+ return false;
}
Identifier[] a;
@@ -430,7 +137,7 @@ class Parser(AST) : Lexer
if (token.value != TOK.identifier)
{
error("identifier expected following `package`");
- goto Lerr;
+ return false;
}
id = token.ident;
}
@@ -442,29 +149,115 @@ class Parser(AST) : Lexer
nextToken();
addComment(mod, comment);
}
+ return true;
+ }
- decldefs = parseDeclDefs(0, &lastDecl);
+ /++
+ + Parse the content of a module, i.e. all declarations found until the end of file.
+ +
+ + Returns: the list of declarations or an empty list in case of malformed declarations
+ +/
+ final AST.Dsymbols* parseModuleContent()
+ {
+ AST.Dsymbol lastDecl = mod;
+ AST.Dsymbols* decldefs = parseDeclDefs(0, &lastDecl);
if (token.value == TOK.rightCurly)
{
error(token.loc, "unmatched closing brace");
- goto Lerr;
+ return errorReturn();
}
if (token.value != TOK.endOfFile)
{
error(token.loc, "unrecognized declaration");
- goto Lerr;
+ return errorReturn();
}
return decldefs;
+ }
- Lerr:
+ /++
+ + Skips to the end of the current declaration - denoted by either `;` or EOF
+ +
+ + Returns: An empty list of Dsymbols
+ +/
+ private AST.Dsymbols* errorReturn()
+ {
while (token.value != TOK.semicolon && token.value != TOK.endOfFile)
nextToken();
nextToken();
return new AST.Dsymbols();
}
+ /**********************************
+ * Parse the ModuleAttributes preceding a module declaration.
+ * ModuleDeclaration:
+ * ModuleAttributes(opt) module ModuleFullyQualifiedName ;
+ * https://dlang.org/spec/module.html#ModuleAttributes
+ * Params:
+ * msg = set to the AssignExpression from DeprecatedAttribute https://dlang.org/spec/module.html#DeprecatedAttribute
+ * isdeprecated = set to true if a DeprecatedAttribute is seen
+ */
+ private
+ void parseModuleAttributes(out AST.Expression msg, out bool isdeprecated)
+ {
+ Token* tk;
+ if (!(skipAttributes(&token, &tk) && tk.value == TOK.module_))
+ return; // no module attributes
+
+ AST.Expressions* udas = null;
+ while (token.value != TOK.module_)
+ {
+ switch (token.value)
+ {
+ case TOK.deprecated_:
+ {
+ // deprecated (...) module ...
+ if (isdeprecated)
+ error("there is only one deprecation attribute allowed for module declaration");
+ isdeprecated = true;
+ nextToken();
+ if (token.value == TOK.leftParenthesis)
+ {
+ check(TOK.leftParenthesis);
+ msg = parseAssignExp();
+ check(TOK.rightParenthesis);
+ }
+ break;
+ }
+ case TOK.at:
+ {
+ AST.Expressions* exps = null;
+ const stc = parseAttribute(exps);
+ if (stc & atAttrGroup)
+ {
+ error("`@%s` attribute for module declaration is not supported", token.toChars());
+ }
+ else
+ {
+ udas = AST.UserAttributeDeclaration.concat(udas, exps);
+ }
+ if (stc)
+ nextToken();
+ break;
+ }
+ default:
+ {
+ error("`module` expected instead of `%s`", token.toChars());
+ nextToken();
+ break;
+ }
+ }
+ }
+
+ if (udas)
+ {
+ auto a = new AST.Dsymbols();
+ auto udad = new AST.UserAttributeDeclaration(udas, a);
+ mod.userAttribDecl = udad;
+ }
+ }
+
final:
/**
@@ -914,7 +707,7 @@ class Parser(AST) : Lexer
tk.value == TOK.out_ || tk.value == TOK.do_ || tk.value == TOK.goesTo ||
tk.value == TOK.identifier && tk.ident == Id._body))
{
- // @@@DEPRECATED@@@
+ // @@@DEPRECATED_2.117@@@
// https://github.com/dlang/DIPs/blob/1f5959abe482b1f9094f6484a7d0a3ade77fc2fc/DIPs/accepted/DIP1003.md
// Deprecated in 2.097 - Can be removed from 2.117
// The deprecation period is longer than usual as `body`
@@ -1418,6 +1211,15 @@ class Parser(AST) : Lexer
*/
private StorageClass appendStorageClass(StorageClass orig, StorageClass added)
{
+ void checkConflictSTCGroup(bool at = false)(StorageClass group)
+ {
+ if (added & group && orig & group & ((orig & group) - 1))
+ error(
+ at ? "conflicting attribute `@%s`"
+ : "conflicting attribute `%s`",
+ token.toChars());
+ }
+
if (orig & added)
{
OutBuffer buf;
@@ -1460,24 +1262,9 @@ class Parser(AST) : Lexer
return orig;
}
- if (added & (STC.const_ | STC.immutable_ | STC.manifest))
- {
- StorageClass u = orig & (STC.const_ | STC.immutable_ | STC.manifest);
- if (u & (u - 1))
- error("conflicting attribute `%s`", Token.toChars(token.value));
- }
- if (added & (STC.gshared | STC.shared_ | STC.tls))
- {
- StorageClass u = orig & (STC.gshared | STC.shared_ | STC.tls);
- if (u & (u - 1))
- error("conflicting attribute `%s`", Token.toChars(token.value));
- }
- if (added & STC.safeGroup)
- {
- StorageClass u = orig & STC.safeGroup;
- if (u & (u - 1))
- error("conflicting attribute `@%s`", token.toChars());
- }
+ checkConflictSTCGroup(STC.const_ | STC.immutable_ | STC.manifest);
+ checkConflictSTCGroup(STC.gshared | STC.shared_ | STC.tls);
+ checkConflictSTCGroup!true(STC.safeGroup);
return orig;
}
@@ -2885,7 +2672,7 @@ class Parser(AST) : Lexer
}
nextToken();
- /* @@@DEPRECATED_2.098@@@
+ /* @@@DEPRECATED_2.108@@@
* After deprecation period (2.108), remove all code in the version(all) block.
*/
version (all)
@@ -4614,7 +4401,7 @@ class Parser(AST) : Lexer
(tk.value == TOK.leftParenthesis || tk.value == TOK.leftCurly || tk.value == TOK.in_ || tk.value == TOK.out_ || tk.value == TOK.goesTo ||
tk.value == TOK.do_ || tk.value == TOK.identifier && tk.ident == Id._body))
{
- // @@@DEPRECATED@@@
+ // @@@DEPRECATED_2.117@@@
// https://github.com/dlang/DIPs/blob/1f5959abe482b1f9094f6484a7d0a3ade77fc2fc/DIPs/accepted/DIP1003.md
// Deprecated in 2.097 - Can be removed from 2.117
// The deprecation period is longer than usual as `body`
@@ -5028,12 +4815,18 @@ class Parser(AST) : Lexer
// parseAttributes shouldn't have set these variables
assert(link == linkage && !setAlignment && ealign is null);
auto tpl_ = cast(AST.TemplateDeclaration) s;
- assert(tpl_ !is null && tpl_.members.dim == 1);
- auto fd = cast(AST.FuncLiteralDeclaration) (*tpl_.members)[0];
- auto tf = cast(AST.TypeFunction) fd.type;
- assert(tf.parameterList.parameters.dim > 0);
- auto as = new AST.Dsymbols();
- (*tf.parameterList.parameters)[0].userAttribDecl = new AST.UserAttributeDeclaration(udas, as);
+ if (tpl_ is null || tpl_.members.dim != 1)
+ {
+ error("user-defined attributes are not allowed on `alias` declarations");
+ }
+ else
+ {
+ auto fd = cast(AST.FuncLiteralDeclaration) (*tpl_.members)[0];
+ auto tf = cast(AST.TypeFunction) fd.type;
+ assert(tf.parameterList.parameters.dim > 0);
+ auto as = new AST.Dsymbols();
+ (*tf.parameterList.parameters)[0].userAttribDecl = new AST.UserAttributeDeclaration(udas, as);
+ }
}
v = new AST.AliasDeclaration(loc, ident, s);
@@ -5060,7 +4853,7 @@ class Parser(AST) : Lexer
{
OutBuffer buf;
AST.stcToBuffer(&buf, remStc);
- // @@@DEPRECATED_2.093@@@
+ // @@@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());
}
@@ -5287,7 +5080,7 @@ class Parser(AST) : Lexer
case TOK.identifier:
if (token.ident == Id._body)
{
- // @@@DEPRECATED@@@
+ // @@@DEPRECATED_2.117@@@
// https://github.com/dlang/DIPs/blob/1f5959abe482b1f9094f6484a7d0a3ade77fc2fc/DIPs/accepted/DIP1003.md
// Deprecated in 2.097 - Can be removed from 2.117
// The deprecation period is longer than usual as `body`
@@ -7607,7 +7400,7 @@ LagainStc:
case TOK.identifier:
if (t.ident == Id._body)
{
- // @@@DEPRECATED@@@
+ // @@@DEPRECATED_2.117@@@
// https://github.com/dlang/DIPs/blob/1f5959abe482b1f9094f6484a7d0a3ade77fc2fc/DIPs/accepted/DIP1003.md
// Deprecated in 2.097 - Can be removed from 2.117
// The deprecation period is longer than usual as `body`
@@ -8652,6 +8445,9 @@ LagainStc:
break;
case TOK.delete_:
+ // @@@DEPRECATED_2.109@@@
+ // Use of `delete` keyword has been an error since 2.099.
+ // Remove from the parser after 2.109.
nextToken();
e = parseUnaryExp();
e = new AST.DeleteExp(loc, e, false);
@@ -9409,12 +9205,7 @@ LagainStc:
const loc = token.loc;
nextToken();
- AST.Expressions* newargs = null;
AST.Expressions* arguments = null;
- if (token.value == TOK.leftParenthesis)
- {
- newargs = parseArguments();
- }
// An anonymous nested class starts with "class"
if (token.value == TOK.class_)
@@ -9444,7 +9235,7 @@ LagainStc:
}
auto cd = new AST.ClassDeclaration(loc, id, baseclasses, members, false);
- auto e = new AST.NewAnonClassExp(loc, thisexp, newargs, cd, arguments);
+ auto e = new AST.NewAnonClassExp(loc, thisexp, cd, arguments);
return e;
}
@@ -9469,7 +9260,7 @@ LagainStc:
arguments = parseArguments();
}
- auto e = new AST.NewExp(loc, thisexp, newargs, t, arguments);
+ auto e = new AST.NewExp(loc, thisexp, t, arguments);
return e;
}
@@ -9519,7 +9310,7 @@ LagainStc:
STC.live |
/*STC.future |*/ // probably should be included
STC.disable;
- }
+}
enum PREC : int
{
@@ -9541,3 +9332,276 @@ enum PREC : int
unary,
primary,
}
+
+/**********************************
+ * Set operator precedence for each operator.
+ *
+ * Used by hdrgen
+ */
+immutable PREC[EXP.max + 1] precedence =
+[
+ EXP.type : PREC.expr,
+ EXP.error : PREC.expr,
+ EXP.objcClassReference : PREC.expr, // Objective-C class reference, same as EXP.type
+
+ EXP.typeof_ : PREC.primary,
+ EXP.mixin_ : PREC.primary,
+
+ EXP.import_ : PREC.primary,
+ EXP.dotVariable : PREC.primary,
+ EXP.scope_ : PREC.primary,
+ EXP.identifier : PREC.primary,
+ EXP.this_ : PREC.primary,
+ EXP.super_ : PREC.primary,
+ EXP.int64 : PREC.primary,
+ EXP.float64 : PREC.primary,
+ EXP.complex80 : PREC.primary,
+ EXP.null_ : PREC.primary,
+ EXP.string_ : PREC.primary,
+ EXP.arrayLiteral : PREC.primary,
+ EXP.assocArrayLiteral : PREC.primary,
+ EXP.classReference : PREC.primary,
+ EXP.file : PREC.primary,
+ EXP.fileFullPath : PREC.primary,
+ EXP.line : PREC.primary,
+ EXP.moduleString : PREC.primary,
+ EXP.functionString : PREC.primary,
+ EXP.prettyFunction : PREC.primary,
+ EXP.typeid_ : PREC.primary,
+ EXP.is_ : PREC.primary,
+ EXP.assert_ : PREC.primary,
+ EXP.halt : PREC.primary,
+ EXP.template_ : PREC.primary,
+ EXP.dSymbol : PREC.primary,
+ EXP.function_ : PREC.primary,
+ EXP.variable : PREC.primary,
+ EXP.symbolOffset : PREC.primary,
+ EXP.structLiteral : PREC.primary,
+ EXP.compoundLiteral : PREC.primary,
+ EXP.arrayLength : PREC.primary,
+ EXP.delegatePointer : PREC.primary,
+ EXP.delegateFunctionPointer : PREC.primary,
+ EXP.remove : PREC.primary,
+ EXP.tuple : PREC.primary,
+ EXP.traits : PREC.primary,
+ EXP.default_ : PREC.primary,
+ EXP.overloadSet : PREC.primary,
+ EXP.void_ : PREC.primary,
+ EXP.vectorArray : PREC.primary,
+ EXP._Generic : PREC.primary,
+
+ // post
+ EXP.dotTemplateInstance : PREC.primary,
+ EXP.dotIdentifier : PREC.primary,
+ EXP.dotTemplateDeclaration : PREC.primary,
+ EXP.dot : PREC.primary,
+ EXP.dotType : PREC.primary,
+ EXP.plusPlus : PREC.primary,
+ EXP.minusMinus : PREC.primary,
+ EXP.prePlusPlus : PREC.primary,
+ EXP.preMinusMinus : PREC.primary,
+ EXP.call : PREC.primary,
+ EXP.slice : PREC.primary,
+ EXP.array : PREC.primary,
+ EXP.index : PREC.primary,
+
+ EXP.delegate_ : PREC.unary,
+ EXP.address : PREC.unary,
+ EXP.star : PREC.unary,
+ EXP.negate : PREC.unary,
+ EXP.uadd : PREC.unary,
+ EXP.not : PREC.unary,
+ EXP.tilde : PREC.unary,
+ EXP.delete_ : PREC.unary,
+ EXP.new_ : PREC.unary,
+ EXP.newAnonymousClass : PREC.unary,
+ EXP.cast_ : PREC.unary,
+ EXP.throw_ : PREC.unary,
+
+ EXP.vector : PREC.unary,
+ EXP.pow : PREC.pow,
+
+ EXP.mul : PREC.mul,
+ EXP.div : PREC.mul,
+ EXP.mod : PREC.mul,
+
+ EXP.add : PREC.add,
+ EXP.min : PREC.add,
+ EXP.concatenate : PREC.add,
+
+ EXP.leftShift : PREC.shift,
+ EXP.rightShift : PREC.shift,
+ EXP.unsignedRightShift : PREC.shift,
+
+ EXP.lessThan : PREC.rel,
+ EXP.lessOrEqual : PREC.rel,
+ EXP.greaterThan : PREC.rel,
+ EXP.greaterOrEqual : PREC.rel,
+ EXP.in_ : PREC.rel,
+
+ /* Note that we changed precedence, so that < and != have the same
+ * precedence. This change is in the parser, too.
+ */
+ EXP.equal : PREC.rel,
+ EXP.notEqual : PREC.rel,
+ EXP.identity : PREC.rel,
+ EXP.notIdentity : PREC.rel,
+
+ EXP.and : PREC.and,
+ EXP.xor : PREC.xor,
+ EXP.or : PREC.or,
+
+ EXP.andAnd : PREC.andand,
+ EXP.orOr : PREC.oror,
+
+ EXP.question : PREC.cond,
+
+ EXP.assign : PREC.assign,
+ EXP.construct : PREC.assign,
+ EXP.blit : PREC.assign,
+ EXP.addAssign : PREC.assign,
+ EXP.minAssign : PREC.assign,
+ EXP.concatenateAssign : PREC.assign,
+ EXP.concatenateElemAssign : PREC.assign,
+ EXP.concatenateDcharAssign : PREC.assign,
+ EXP.mulAssign : PREC.assign,
+ EXP.divAssign : PREC.assign,
+ EXP.modAssign : PREC.assign,
+ EXP.powAssign : PREC.assign,
+ EXP.leftShiftAssign : PREC.assign,
+ EXP.rightShiftAssign : PREC.assign,
+ EXP.unsignedRightShiftAssign : PREC.assign,
+ EXP.andAssign : PREC.assign,
+ EXP.orAssign : PREC.assign,
+ EXP.xorAssign : PREC.assign,
+
+ EXP.comma : PREC.expr,
+ EXP.declaration : PREC.expr,
+
+ EXP.interval : PREC.assign,
+];
+
+enum ParseStatementFlags : int
+{
+ semi = 1, // empty ';' statements are allowed, but deprecated
+ scope_ = 2, // start a new scope
+ curly = 4, // { } statement is required
+ curlyScope = 8, // { } starts a new scope
+ semiOk = 0x10, // empty ';' are really ok
+}
+
+struct PrefixAttributes(AST)
+{
+ StorageClass storageClass;
+ AST.Expression depmsg;
+ LINK link;
+ AST.Visibility visibility;
+ bool setAlignment;
+ AST.Expression ealign;
+ AST.Expressions* udas;
+ const(char)* comment;
+}
+
+/// The result of the `ParseLinkage` function
+struct ParsedLinkage(AST)
+{
+ /// What linkage was specified
+ LINK link;
+ /// If `extern(C++, class|struct)`, contains the `class|struct`
+ CPPMANGLE cppmangle;
+ /// If `extern(C++, some.identifier)`, will be the identifiers
+ AST.Identifiers* idents;
+ /// If `extern(C++, (some_tuple_expression)|"string"), will be the expressions
+ AST.Expressions* identExps;
+}
+
+
+/*********************************** Private *************************************/
+
+/***********************
+ * How multiple declarations are parsed.
+ * If 1, treat as C.
+ * If 0, treat:
+ * int *p, i;
+ * as:
+ * int* p;
+ * int* i;
+ */
+private enum CDECLSYNTAX = 0;
+
+/*****
+ * Support C cast syntax:
+ * (type)(expression)
+ */
+private enum CCASTSYNTAX = 1;
+
+/*****
+ * Support postfix C array declarations, such as
+ * int a[3][4];
+ */
+private enum CARRAYDECL = 1;
+
+/*****************************
+ * Destructively extract storage class from pAttrs.
+ */
+private StorageClass getStorageClass(AST)(PrefixAttributes!(AST)* pAttrs)
+{
+ StorageClass stc = STC.undefined_;
+ if (pAttrs)
+ {
+ stc = pAttrs.storageClass;
+ pAttrs.storageClass = STC.undefined_;
+ }
+ return stc;
+}
+
+/**************************************
+ * dump mixin expansion to file for better debugging
+ */
+private bool writeMixin(const(char)[] s, ref Loc loc)
+{
+ if (!global.params.mixinOut)
+ return false;
+
+ OutBuffer* ob = global.params.mixinOut;
+
+ ob.writestring("// expansion at ");
+ ob.writestring(loc.toChars());
+ ob.writenl();
+
+ global.params.mixinLines++;
+
+ loc = Loc(global.params.mixinFile, global.params.mixinLines + 1, loc.charnum);
+
+ // write by line to create consistent line endings
+ size_t lastpos = 0;
+ for (size_t i = 0; i < s.length; ++i)
+ {
+ // detect LF and CRLF
+ const c = s[i];
+ if (c == '\n' || (c == '\r' && i+1 < s.length && s[i+1] == '\n'))
+ {
+ ob.writestring(s[lastpos .. i]);
+ ob.writenl();
+ global.params.mixinLines++;
+ if (c == '\r')
+ ++i;
+ lastpos = i + 1;
+ }
+ }
+
+ if(lastpos < s.length)
+ ob.writestring(s[lastpos .. $]);
+
+ if (s.length == 0 || s[$-1] != '\n')
+ {
+ ob.writenl(); // ensure empty line after expansion
+ global.params.mixinLines++;
+ }
+ ob.writenl();
+ global.params.mixinLines++;
+
+ return true;
+}
+
+
diff --git a/gcc/d/dmd/printast.d b/gcc/d/dmd/printast.d
index 6133145..571c3fc 100644
--- a/gcc/d/dmd/printast.d
+++ b/gcc/d/dmd/printast.d
@@ -122,6 +122,16 @@ extern (C++) final class PrintASTVisitor : Visitor
printAST(e.e1, indent + 2);
}
+ override void visit(CastExp e)
+ {
+ printIndent(indent);
+ auto s = EXPtoString(e.op);
+ printf("%.*s %s\n", cast(int)s.length, s.ptr, e.type ? e.type.toChars() : "");
+ printIndent(indent + 2);
+ printf(".to: %s\n", e.to.toChars());
+ printAST(e.e1, indent + 2);
+ }
+
override void visit(VectorExp e)
{
printIndent(indent);
diff --git a/gcc/d/dmd/semantic2.d b/gcc/d/dmd/semantic2.d
index f36cdc9..85c4d5b 100644
--- a/gcc/d/dmd/semantic2.d
+++ b/gcc/d/dmd/semantic2.d
@@ -422,7 +422,7 @@ private extern(C++) final class Semantic2Visitor : Visitor
const sameParams = tf1.parameterList == tf2.parameterList;
// Allow the hack to declare overloads with different parameters/STC's
- // @@@DEPRECATED_2.094@@@
+ // @@@DEPRECATED_2.104@@@
// Deprecated in 2020-08, make this an error in 2.104
if (parent1.isModule() &&
f1.linkage != LINK.d && f1.linkage != LINK.cpp &&
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index 7bcb7ec..3f01966 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -377,6 +377,12 @@ private extern(C++) final class Semantic3Visitor : Visitor
// Reverts: https://issues.dlang.org/show_bug.cgi?id=5710
// No compiler supports this, and there was never any spec for it.
+ // @@@DEPRECATED_2.116@@@
+ // Deprecated in 2.096, can be made an error in 2.116.
+ // The deprecation period is longer than usual as dual-context
+ // functions may be widely used by dmd-compiled projects.
+ // It also gives more time for the implementation of dual-context
+ // functions to be reworked as a frontend-only feature.
if (funcdecl.isThis2)
{
funcdecl.deprecation("function requires a dual-context, which is deprecated");
@@ -746,7 +752,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
// Check for errors related to 'nothrow'.
const blockexit = funcdecl.fbody.blockExit(funcdecl, f.isnothrow);
if (f.isnothrow && blockexit & BE.throw_)
- error(funcdecl.loc, "`nothrow` %s `%s` may throw", funcdecl.kind(), funcdecl.toPrettyChars());
+ error(funcdecl.loc, "%s `%s` may throw but is marked as `nothrow`", funcdecl.kind(), funcdecl.toPrettyChars());
if (!(blockexit & (BE.throw_ | BE.halt) || funcdecl.flags & FUNCFLAG.hasCatches))
{
@@ -1146,14 +1152,16 @@ private extern(C++) final class Semantic3Visitor : Visitor
s = s.statementSemantic(sc2);
- bool isnothrow = f.isnothrow & !(funcdecl.flags & FUNCFLAG.nothrowInprocess);
+ immutable bool isnothrow = f.isnothrow && !(funcdecl.flags & FUNCFLAG.nothrowInprocess);
const blockexit = s.blockExit(funcdecl, isnothrow);
if (blockexit & BE.throw_)
+ {
funcdecl.eh_none = false;
- if (f.isnothrow && isnothrow && blockexit & BE.throw_)
- error(funcdecl.loc, "`nothrow` %s `%s` may throw", funcdecl.kind(), funcdecl.toPrettyChars());
- if (funcdecl.flags & FUNCFLAG.nothrowInprocess && blockexit & BE.throw_)
- f.isnothrow = false;
+ if (isnothrow)
+ error(funcdecl.loc, "%s `%s` may throw but is marked as `nothrow`", funcdecl.kind(), funcdecl.toPrettyChars());
+ else if (funcdecl.flags & FUNCFLAG.nothrowInprocess)
+ f.isnothrow = false;
+ }
if (sbody.blockExit(funcdecl, f.isnothrow) == BE.fallthru)
sbody = new CompoundStatement(Loc.initial, sbody, s);
@@ -1402,7 +1410,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
auto sexp = new ExpStatement(ctor.loc, ce);
auto ss = new ScopeStatement(ctor.loc, sexp, ctor.loc);
- // @@@DEPRECATED_2096@@@
+ // @@@DEPRECATED_2.106@@@
// Allow negligible attribute violations to allow for a smooth
// transition. Remove this after the usual deprecation period
// after 2.106.
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index 1f7f3e4..5dbe5b6 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -1608,7 +1608,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
* Params:
* sc = context
* fs = ForeachStatement
- * tfld = type of function literal to be created, can be null
+ * tfld = type of function literal to be created (type of opApply() function if any), can be null
* Returns:
* Function literal created, as an expression
* null if error.
@@ -1619,7 +1619,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
foreach (i; 0 .. fs.parameters.dim)
{
Parameter p = (*fs.parameters)[i];
- StorageClass stc = STC.ref_;
+ StorageClass stc = STC.ref_ | (p.storageClass & STC.scope_);
Identifier id;
p.type = p.type.typeSemantic(fs.loc, sc);
@@ -1628,17 +1628,17 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
{
Parameter prm = tfld.parameterList[i];
//printf("\tprm = %s%s\n", (prm.storageClass&STC.ref_?"ref ":"").ptr, prm.ident.toChars());
- stc = prm.storageClass & STC.ref_;
- id = p.ident; // argument copy is not need.
- if ((p.storageClass & STC.ref_) != stc)
+ stc = (prm.storageClass & STC.ref_) | (p.storageClass & STC.scope_);
+ if ((p.storageClass & STC.ref_) != (prm.storageClass & STC.ref_))
{
- if (!stc)
+ if (!(prm.storageClass & STC.ref_))
{
fs.error("`foreach`: cannot make `%s` `ref`", p.ident.toChars());
return null;
}
goto LcopyArg;
}
+ id = p.ident; // argument copy is not need.
}
else if (p.storageClass & STC.ref_)
{
@@ -1655,7 +1655,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
Initializer ie = new ExpInitializer(fs.loc, new IdentifierExp(fs.loc, id));
auto v = new VarDeclaration(fs.loc, p.type, p.ident, ie);
- v.storage_class |= STC.temp;
+ v.storage_class |= STC.temp | (stc & STC.scope_);
Statement s = new ExpStatement(fs.loc, v);
fs._body = new CompoundStatement(fs.loc, s, fs._body);
}
@@ -3567,7 +3567,6 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
tcs.tryBody = sc.tryBody; // chain on the in-flight tryBody
tcs._body = tcs._body.semanticScope(sc, null, null, tcs);
- assert(tcs._body);
/* Even if body is empty, still do semantic analysis on catches
*/
@@ -3610,6 +3609,11 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
if (catchErrors)
return setError();
+ // No actual code in the try (i.e. omitted any conditionally compiled code)
+ // Could also be extended to check for hasCode
+ if (!tcs._body)
+ return;
+
if (tcs._body.isErrorStatement())
{
result = tcs._body;
@@ -4764,161 +4768,71 @@ private Statements* flatten(Statement statement, Scope* sc)
}
/***********************************************************
- * Convert TemplateMixin members (== Dsymbols) to Statements.
+ * Convert TemplateMixin members (which are Dsymbols) to Statements.
+ * Params:
+ * s = the symbol to convert to a Statement
+ * Returns:
+ * s redone as a Statement
*/
private Statement toStatement(Dsymbol s)
{
- extern (C++) final class ToStmt : Visitor
- {
- alias visit = Visitor.visit;
- public:
- Statement result;
-
- Statement visitMembers(Loc loc, Dsymbols* a)
- {
- if (!a)
- return null;
-
- auto statements = new Statements();
- foreach (s; *a)
- {
- statements.push(toStatement(s));
- }
- return new CompoundStatement(loc, statements);
- }
+ Statement result;
- override void visit(Dsymbol s)
+ if (auto tm = s.isTemplateMixin())
+ {
+ auto a = new Statements();
+ foreach (m; *tm.members)
{
- .error(Loc.initial, "Internal Compiler Error: cannot mixin %s `%s`\n", s.kind(), s.toChars());
- result = new ErrorStatement();
+ if (Statement sx = toStatement(m))
+ a.push(sx);
}
-
- override void visit(TemplateMixin tm)
- {
- auto a = new Statements();
- foreach (m; *tm.members)
- {
- Statement s = toStatement(m);
- if (s)
- a.push(s);
- }
- result = new CompoundStatement(tm.loc, a);
- }
-
+ result = new CompoundStatement(tm.loc, a);
+ }
+ else if (s.isVarDeclaration() ||
+ s.isAggregateDeclaration() ||
+ s.isFuncDeclaration() ||
+ s.isEnumDeclaration() ||
+ s.isAliasDeclaration() ||
+ s.isTemplateDeclaration())
+ {
+ /* Perhaps replace the above with isScopeDsymbol() || isDeclaration()
+ */
/* An actual declaration symbol will be converted to DeclarationExp
* with ExpStatement.
*/
- Statement declStmt(Dsymbol s)
- {
- auto de = new DeclarationExp(s.loc, s);
- de.type = Type.tvoid; // avoid repeated semantic
- return new ExpStatement(s.loc, de);
- }
-
- override void visit(VarDeclaration d)
- {
- result = declStmt(d);
- }
-
- override void visit(AggregateDeclaration d)
- {
- result = declStmt(d);
- }
-
- override void visit(FuncDeclaration d)
- {
- result = declStmt(d);
- }
-
- override void visit(EnumDeclaration d)
- {
- result = declStmt(d);
- }
-
- override void visit(AliasDeclaration d)
- {
- result = declStmt(d);
- }
-
- override void visit(TemplateDeclaration d)
- {
- result = declStmt(d);
- }
-
+ auto de = new DeclarationExp(s.loc, s);
+ de.type = Type.tvoid; // avoid repeated semantic
+ result = new ExpStatement(s.loc, de);
+ }
+ else if (auto d = s.isAttribDeclaration())
+ {
/* All attributes have been already picked by the semantic analysis of
* 'bottom' declarations (function, struct, class, etc).
* So we don't have to copy them.
*/
- override void visit(StorageClassDeclaration d)
- {
- result = visitMembers(d.loc, d.decl);
- }
-
- override void visit(DeprecatedDeclaration d)
- {
- result = visitMembers(d.loc, d.decl);
- }
-
- override void visit(LinkDeclaration d)
- {
- result = visitMembers(d.loc, d.decl);
- }
-
- override void visit(VisibilityDeclaration d)
- {
- result = visitMembers(d.loc, d.decl);
- }
-
- override void visit(AlignDeclaration d)
+ if (Dsymbols* a = d.include(null))
{
- result = visitMembers(d.loc, d.decl);
- }
-
- override void visit(UserAttributeDeclaration d)
- {
- result = visitMembers(d.loc, d.decl);
- }
-
- override void visit(ForwardingAttribDeclaration d)
- {
- result = visitMembers(d.loc, d.decl);
- }
-
- override void visit(StaticAssert s)
- {
- }
-
- override void visit(Import s)
- {
- }
-
- override void visit(PragmaDeclaration d)
- {
- }
-
- override void visit(ConditionalDeclaration d)
- {
- result = visitMembers(d.loc, d.include(null));
- }
-
- override void visit(StaticForeachDeclaration d)
- {
- assert(d.sfe && !!d.sfe.aggrfe ^ !!d.sfe.rangefe);
- result = visitMembers(d.loc, d.include(null));
- }
-
- override void visit(CompileDeclaration d)
- {
- result = visitMembers(d.loc, d.include(null));
+ auto statements = new Statements();
+ foreach (sx; *a)
+ {
+ statements.push(toStatement(sx));
+ }
+ result = new CompoundStatement(d.loc, statements);
}
}
+ else if (s.isStaticAssert() ||
+ s.isImport())
+ {
+ /* Ignore as they are not Statements
+ */
+ }
+ else
+ {
+ .error(Loc.initial, "Internal Compiler Error: cannot mixin %s `%s`\n", s.kind(), s.toChars());
+ result = new ErrorStatement();
+ }
- if (!s)
- return null;
-
- scope ToStmt v = new ToStmt();
- s.accept(v);
- return v.result;
+ return result;
}
/**
diff --git a/gcc/d/dmd/staticassert.d b/gcc/d/dmd/staticassert.d
index 7daf7cd..c7d3148 100644
--- a/gcc/d/dmd/staticassert.d
+++ b/gcc/d/dmd/staticassert.d
@@ -59,6 +59,11 @@ extern (C++) final class StaticAssert : Dsymbol
return "static assert";
}
+ override inout(StaticAssert) isStaticAssert() inout
+ {
+ return this;
+ }
+
override void accept(Visitor v)
{
v.visit(this);
diff --git a/gcc/d/dmd/staticassert.h b/gcc/d/dmd/staticassert.h
index 5c00b46..38142bc 100644
--- a/gcc/d/dmd/staticassert.h
+++ b/gcc/d/dmd/staticassert.h
@@ -24,5 +24,6 @@ public:
void addMember(Scope *sc, ScopeDsymbol *sds);
bool oneMember(Dsymbol **ps, Identifier *ident);
const char *kind() const;
+ StaticAssert *isStaticAssert() { return this; }
void accept(Visitor *v) { v->visit(this); }
};
diff --git a/gcc/d/dmd/tokens.d b/gcc/d/dmd/tokens.d
index 20b8711..9c24df0 100644
--- a/gcc/d/dmd/tokens.d
+++ b/gcc/d/dmd/tokens.d
@@ -35,7 +35,6 @@ enum TOK : ubyte
leftCurly,
rightCurly,
colon,
- negate,
semicolon,
dotDotDot,
endOfFile,
@@ -44,26 +43,18 @@ enum TOK : ubyte
assert_,
true_,
false_,
- array,
- call,
- address,
- type,
throw_,
new_,
delete_,
- star,
variable,
slice,
version_,
module_,
dollar,
template_,
- declaration,
typeof_,
pragma_,
typeid_,
- uadd,
- remove,
comment,
// Operators
@@ -75,7 +66,6 @@ enum TOK : ubyte
notEqual,
identity,
notIdentity,
- index,
is_,
leftShift,
@@ -281,6 +271,7 @@ enum TOK : ubyte
_import,
__cdecl,
__declspec,
+ __stdcall,
__attribute__,
}
@@ -589,6 +580,7 @@ private immutable TOK[] keywords =
TOK._import,
TOK.__cdecl,
TOK.__declspec,
+ TOK.__stdcall,
TOK.__attribute__,
];
@@ -617,7 +609,7 @@ static immutable TOK[TOK.max + 1] Ckeywords =
restrict, return_, int16, signed, sizeof_, static_, struct_, switch_, typedef_,
union_, unsigned, void_, volatile, while_, asm_,
_Alignas, _Alignof, _Atomic, _Bool, _Complex, _Generic, _Imaginary, _Noreturn,
- _Static_assert, _Thread_local, _import, __cdecl, __declspec, __attribute__ ];
+ _Static_assert, _Thread_local, _import, __cdecl, __declspec, __stdcall, __attribute__ ];
foreach (kw; Ckwds)
tab[kw] = cast(TOK) kw;
@@ -805,18 +797,11 @@ extern (C++) struct Token
TOK.andAnd: "&&",
TOK.or: "|",
TOK.orOr: "||",
- TOK.array: "[]",
- TOK.index: "[i]",
- TOK.address: "&",
- TOK.star: "*",
TOK.tilde: "~",
TOK.dollar: "$",
TOK.plusPlus: "++",
TOK.minusMinus: "--",
- TOK.type: "type",
TOK.question: "?",
- TOK.negate: "-",
- TOK.uadd: "+",
TOK.variable: "var",
TOK.addAssign: "+=",
TOK.minAssign: "-=",
@@ -829,7 +814,6 @@ extern (C++) struct Token
TOK.andAssign: "&=",
TOK.orAssign: "|=",
TOK.concatenateAssign: "~=",
- TOK.call: "call",
TOK.identity: "is",
TOK.notIdentity: "!is",
TOK.identifier: "identifier",
@@ -844,14 +828,12 @@ extern (C++) struct Token
// For debugging
TOK.error: "error",
TOK.string_: "string",
- TOK.declaration: "declaration",
TOK.onScopeExit: "scope(exit)",
TOK.onScopeSuccess: "scope(success)",
TOK.onScopeFailure: "scope(failure)",
// Finish up
TOK.reserved: "reserved",
- TOK.remove: "remove",
TOK.comment: "comment",
TOK.int32Literal: "int32v",
TOK.uns32Literal: "uns32v",
@@ -896,6 +878,7 @@ extern (C++) struct Token
TOK._import : "__import",
TOK.__cdecl : "__cdecl",
TOK.__declspec : "__declspec",
+ TOK.__stdcall : "__stdcall",
TOK.__attribute__ : "__attribute__",
];
@@ -963,12 +946,20 @@ nothrow:
sprintf(&buffer[0], "%d", cast(d_int32)intvalue);
break;
case TOK.uns32Literal:
- case TOK.charLiteral:
case TOK.wcharLiteral:
case TOK.dcharLiteral:
case TOK.wchar_tLiteral:
sprintf(&buffer[0], "%uU", cast(d_uns32)unsvalue);
break;
+ case TOK.charLiteral:
+ {
+ const v = cast(d_int32)intvalue;
+ if (v >= ' ' && v <= '~')
+ sprintf(&buffer[0], "'%c'", v);
+ else
+ sprintf(&buffer[0], "'\\x%02x'", v);
+ break;
+ }
case TOK.int64Literal:
sprintf(&buffer[0], "%lldL", cast(long)intvalue);
break;
@@ -1006,29 +997,7 @@ nothrow:
{
dchar c;
utf_decodeChar(ustring[0 .. len], i, c);
- switch (c)
- {
- case 0:
- break;
- case '"':
- case '\\':
- buf.writeByte('\\');
- goto default;
- default:
- if (c <= 0x7F)
- {
- if (isprint(c))
- buf.writeByte(c);
- else
- buf.printf("\\x%02x", c);
- }
- else if (c <= 0xFFFF)
- buf.printf("\\u%04x", c);
- else
- buf.printf("\\U%08x", c);
- continue;
- }
- break;
+ writeCharLiteral(buf, c);
}
buf.writeByte('"');
if (postfix)
@@ -1103,3 +1072,64 @@ nothrow:
}
}
+/**
+ * Write a character, using a readable escape sequence if needed
+ *
+ * Useful for printing "" string literals in e.g. error messages, ddoc, or the `.stringof` property
+ *
+ * Params:
+ * buf = buffer to append character in
+ * c = code point to write
+ */
+nothrow
+void writeCharLiteral(ref OutBuffer buf, dchar c)
+{
+ switch (c)
+ {
+ case '\0':
+ buf.writestring("\\0");
+ break;
+ case '\n':
+ buf.writestring("\\n");
+ break;
+ case '\r':
+ buf.writestring("\\r");
+ break;
+ case '\t':
+ buf.writestring("\\t");
+ break;
+ case '\b':
+ buf.writestring("\\b");
+ break;
+ case '\f':
+ buf.writestring("\\f");
+ break;
+ case '"':
+ case '\\':
+ buf.writeByte('\\');
+ goto default;
+ default:
+ if (c <= 0x7F)
+ {
+ if (isprint(c))
+ buf.writeByte(c);
+ else
+ buf.printf("\\x%02x", c);
+ }
+ else if (c <= 0xFFFF)
+ buf.printf("\\u%04x", c);
+ else
+ buf.printf("\\U%08x", c);
+ break;
+ }
+}
+
+unittest
+{
+ OutBuffer buf;
+ foreach(dchar d; "a\n\r\t\b\f\0\x11\u7233\U00017233"d)
+ {
+ writeCharLiteral(buf, d);
+ }
+ assert(buf.extractSlice() == `a\n\r\t\b\f\0\x11\u7233\U00017233`);
+}
diff --git a/gcc/d/dmd/tokens.h b/gcc/d/dmd/tokens.h
index a7c9aa5..a9f5028 100644
--- a/gcc/d/dmd/tokens.h
+++ b/gcc/d/dmd/tokens.h
@@ -44,7 +44,6 @@ enum class TOK : unsigned char
leftCurly,
rightCurly,
colon,
- negate,
semicolon,
dotDotDot,
endOfFile,
@@ -53,26 +52,18 @@ enum class TOK : unsigned char
assert_,
true_,
false_,
- array,
- call,
- address,
- type,
throw_,
new_,
delete_,
- star,
variable,
slice,
version_,
module_,
dollar,
template_,
- declaration,
typeof_,
pragma_,
typeid_,
- uadd,
- remove,
comment,
// Operators
@@ -84,7 +75,6 @@ enum class TOK : unsigned char
notEqual,
identity,
notIdentity,
- index,
is_,
leftShift, // 64
@@ -288,8 +278,9 @@ enum class TOK : unsigned char
// C only extended keywords
_import,
- cdecl,
+ cdecl_,
declspec,
+ stdcall,
attribute__,
MAX,
diff --git a/gcc/d/dmd/transitivevisitor.d b/gcc/d/dmd/transitivevisitor.d
index 8b6ca65..615c49f 100644
--- a/gcc/d/dmd/transitivevisitor.d
+++ b/gcc/d/dmd/transitivevisitor.d
@@ -961,8 +961,6 @@ package mixin template ParseVisitMethods(AST)
//printf("Visiting NewExp\n");
if (e.thisexp)
e.thisexp.accept(this);
- if (e.newargs && e.newargs.dim)
- visitArgs(e.newargs);
visitType(e.newtype);
if (e.arguments && e.arguments.dim)
visitArgs(e.arguments);
@@ -973,8 +971,6 @@ package mixin template ParseVisitMethods(AST)
//printf("Visiting NewAnonClassExp\n");
if (e.thisexp)
e.thisexp.accept(this);
- if (e.newargs && e.newargs.dim)
- visitArgs(e.newargs);
if (e.arguments && e.arguments.dim)
visitArgs(e.arguments);
if (e.cd)
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index e11f1f7..637b32e 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -210,6 +210,9 @@ private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymb
error(loc, "undefined identifier `%s`, did you mean %s `%s`?", p, s2.kind(), s2.toChars());
else if (const q = Scope.search_correct_C(id))
error(loc, "undefined identifier `%s`, did you mean `%s`?", p, q);
+ else if ((id == Id.This && sc.getStructClassScope()) ||
+ (id == Id._super && sc.getClassScope()))
+ error(loc, "undefined identifier `%s`, did you mean `typeof(%s)`?", p, p);
else
error(loc, "undefined identifier `%s`", p);
@@ -273,7 +276,7 @@ private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymb
// Same check as in Expression.semanticY(DotIdExp)
else if (sm.isPackage() && checkAccess(sc, sm.isPackage()))
{
- // @@@DEPRECATED_2.096@@@
+ // @@@DEPRECATED_2.106@@@
// Should be an error in 2.106. Just remove the deprecation call
// and uncomment the null assignment
deprecation(loc, "%s %s is not accessible here, perhaps add 'static import %s;'", sm.kind(), sm.toPrettyChars(), sm.toPrettyChars());
@@ -2040,6 +2043,22 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
return mtype.resolved;
}
+ /* Find the current scope by skipping tag scopes.
+ * In C, tag scopes aren't considered scopes.
+ */
+ Scope* sc2 = sc;
+ while (1)
+ {
+ sc2 = sc2.inner();
+ auto scopesym = sc2.scopesym;
+ if (scopesym.isStructDeclaration())
+ {
+ sc2 = sc2.enclosing;
+ continue;
+ }
+ break;
+ }
+
/* Declare mtype as a struct/union/enum declaration
*/
void declareTag()
@@ -2047,16 +2066,16 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
void declare(ScopeDsymbol sd)
{
sd.members = mtype.members;
- auto scopesym = sc.inner().scopesym;
+ auto scopesym = sc2.inner().scopesym;
if (scopesym.members)
scopesym.members.push(sd);
if (scopesym.symtab && !scopesym.symtabInsert(sd))
{
Dsymbol s2 = scopesym.symtabLookup(sd, mtype.id);
- handleTagSymbols(*sc, sd, s2, scopesym);
+ handleTagSymbols(*sc2, sd, s2, scopesym);
}
- sd.parent = sc.parent;
- sd.dsymbolSemantic(sc);
+ sd.parent = sc2.parent;
+ sd.dsymbolSemantic(sc2);
}
switch (mtype.tok)
@@ -2098,7 +2117,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
/* look for pre-existing declaration
*/
Dsymbol scopesym;
- auto s = sc.search(mtype.loc, mtype.id, &scopesym, IgnoreErrors | TagNameSpace);
+ auto s = sc2.search(mtype.loc, mtype.id, &scopesym, IgnoreErrors | TagNameSpace);
if (!s || s.isModule())
{
// no pre-existing declaration, so declare it
@@ -2111,7 +2130,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
/* A redeclaration only happens if both declarations are in
* the same scope
*/
- const bool redeclar = (scopesym == sc.inner().scopesym);
+ const bool redeclar = (scopesym == sc2.inner().scopesym);
if (redeclar)
{
@@ -2154,7 +2173,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
* picked up and added to the symtab.
*/
sd.semanticRun = PASS.semantic;
- sd.dsymbolSemantic(sc);
+ sd.dsymbolSemantic(sc2);
}
}
else
@@ -2985,44 +3004,21 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type
void visitIdentifier(TypeIdentifier mt)
{
//printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, mt.toChars());
- if ((mt.ident.equals(Id._super) || mt.ident.equals(Id.This)) && !hasThis(sc))
- {
- // @@@DEPRECATED_v2.091@@@.
- // Made an error in 2.086.
- // Eligible for removal in 2.091.
- if (mt.ident.equals(Id._super))
- {
- error(mt.loc, "Using `super` as a type is obsolete. Use `typeof(super)` instead");
- }
- // @@@DEPRECATED_v2.091@@@.
- // Made an error in 2.086.
- // Eligible for removal in 2.091.
- if (mt.ident.equals(Id.This))
- {
- error(mt.loc, "Using `this` as a type is obsolete. Use `typeof(this)` instead");
- }
- if (AggregateDeclaration ad = sc.getStructClassScope())
- {
- if (ClassDeclaration cd = ad.isClassDeclaration())
- {
- if (mt.ident.equals(Id.This))
- mt.ident = cd.ident;
- else if (cd.baseClass && mt.ident.equals(Id._super))
- mt.ident = cd.baseClass.ident;
- }
- else
- {
- StructDeclaration sd = ad.isStructDeclaration();
- if (sd && mt.ident.equals(Id.This))
- mt.ident = sd.ident;
- }
- }
- }
if (mt.ident == Id.ctfe)
{
error(loc, "variable `__ctfe` cannot be read at compile time");
return returnError();
}
+ if (mt.ident == Id.builtin_va_list) // gcc has __builtin_va_xxxx for stdarg.h
+ {
+ /* Since we don't support __builtin_va_start, -arg, -end, we don't
+ * have to actually care what -list is. A void* will do.
+ * If we ever do care, import core.stdc.stdarg and pull
+ * the definition out of that, similarly to how std.math is handled for PowExp
+ */
+ pt = target.va_listType(loc, sc);
+ return;
+ }
Dsymbol scopesym;
Dsymbol s = sc.search(loc, mt.ident, &scopesym);
@@ -3821,7 +3817,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
* e.opDot().ident
*/
e = build_overload(e.loc, sc, e, null, fd);
- // @@@DEPRECATED_2.087@@@.
+ // @@@DEPRECATED_2.092@@@.
e.deprecation("`opDot` is deprecated. Use `alias this`");
e = new DotIdExp(e.loc, e, ident);
return returnExp(e.expressionSemantic(sc));
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index dd7ebc8..d5e4df7 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
#include "dmd/aggregate.h"
#include "dmd/ctfe.h"
#include "dmd/declaration.h"
+#include "dmd/enum.h"
#include "dmd/expression.h"
#include "dmd/identifier.h"
#include "dmd/init.h"
@@ -1460,40 +1461,6 @@ public:
t1 = build_address (t1);
this->result_ = build_libcall (libcall, Type::tvoid, 1, t1);
}
- else if (tb1->ty == TY::Tarray)
- {
- /* For dynamic arrays, the garbage collector is called to immediately
- release the memory. */
- Type *telem = tb1->nextOf ()->baseElemOf ();
- tree ti = null_pointer_node;
-
- if (TypeStruct *ts = telem->isTypeStruct ())
- {
- /* Might need to run destructor on array contents. */
- if (ts->sym->dtor)
- ti = build_typeinfo (e->loc, tb1->nextOf ());
- }
-
- /* Generate: _delarray_t (&t1, ti); */
- this->result_ = build_libcall (LIBCALL_DELARRAYT, Type::tvoid, 2,
- build_address (t1), ti);
- }
- else if (tb1->ty == TY::Tpointer)
- {
- /* For pointers to a struct instance, if the struct has overloaded
- operator delete, then that operator is called. */
- t1 = build_address (t1);
- Type *tnext = tb1->isTypePointer ()->next->toBasetype ();
-
- /* This case should have been rewritten to `_d_delstruct` in the
- semantic phase. */
- if (TypeStruct *ts = tnext->isTypeStruct ())
- gcc_assert (!ts->sym->dtor);
-
- /* Otherwise, the garbage collector is called to immediately free the
- memory allocated for the pointer. */
- this->result_ = build_libcall (LIBCALL_DELMEMORY, Type::tvoid, 1, t1);
- }
else
{
error ("don%'t know how to delete %qs", e->e1->toChars ());
@@ -1936,10 +1903,17 @@ public:
else
{
tree object = build_expr (e->e1);
+ Type *tb = e->e1->type->toBasetype ();
- if (e->e1->type->toBasetype ()->ty != TY::Tstruct)
+ if (tb->ty != TY::Tstruct)
object = build_deref (object);
+ /* __complex is represented as a struct in the front-end, but
+ underlying is really a complex type. */
+ if (e->e1->type->ty == TY::Tenum
+ && e->e1->type->isTypeEnum ()->sym->isSpecial ())
+ object = build_vconvert (build_ctype (tb), object);
+
this->result_ = component_ref (object, get_symbol_decl (vd));
}
}
@@ -2604,7 +2578,7 @@ public:
for (size_t i = 0; i < e->len; i++)
{
- tree value = build_integer_cst (e->charAt (i), etype);
+ tree value = build_integer_cst (e->getCodeUnit (i), etype);
CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
}
diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def
index d6e0c7b..acb610f 100644
--- a/gcc/d/runtime.def
+++ b/gcc/d/runtime.def
@@ -83,9 +83,6 @@ DEF_D_RUNTIME (INTERFACE_CAST, "_d_interface_cast", RT(OBJECT),
DEF_D_RUNTIME (NEWITEMT, "_d_newitemT", RT(VOIDPTR), P1(CONST_TYPEINFO), 0)
DEF_D_RUNTIME (NEWITEMIT, "_d_newitemiT", RT(VOIDPTR), P1(CONST_TYPEINFO), 0)
-/* Used when calling delete on a pointer. */
-DEF_D_RUNTIME (DELMEMORY, "_d_delmemory", RT(VOID), P1(POINTER_VOIDPTR), 0)
-
/* Used when calling new on an array. The `i' variant is for when the
initializer is nonzero, and the `m' variant is when initializing a
multi-dimensional array. */
@@ -102,10 +99,6 @@ DEF_D_RUNTIME (NEWARRAYMITX, "_d_newarraymiTX", RT(ARRAY_VOID),
DEF_D_RUNTIME (ARRAYLITERALTX, "_d_arrayliteralTX", RT(VOIDPTR),
P2(CONST_TYPEINFO, SIZE_T), 0)
-/* Used when calling delete on an array. */
-DEF_D_RUNTIME (DELARRAYT, "_d_delarray_t", RT(VOID),
- P2(ARRAYPTR_VOID, CONST_TYPEINFO), 0)
-
/* Used for value equality (x == y) and comparisons (x < y) of non-trivial
arrays. Such as an array of structs or classes. */
DEF_D_RUNTIME (ADEQ2, "_adEq2", RT(INT),
diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index 8ae6ea1..d897ec4 100644
--- a/gcc/d/types.cc
+++ b/gcc/d/types.cc
@@ -993,13 +993,17 @@ public:
t->ctype = build_variant_type_copy (build_ctype (underlying));
build_type_decl (t->ctype, t->sym);
}
- else if (!INTEGRAL_TYPE_P (basetype) || TREE_CODE (basetype) == BOOLEAN_TYPE)
+ else if (t->sym->ident == NULL
+ || !INTEGRAL_TYPE_P (basetype)
+ || TREE_CODE (basetype) == BOOLEAN_TYPE)
{
- /* Enums in D2 can have a base type that is not necessarily integral.
- For these, we simplify this a little by using the base type directly
- instead of building an ENUMERAL_TYPE. */
+ /* Enums in D2 can either be anonymous, or have a base type that is not
+ necessarily integral. For these, we simplify this a little by using
+ the base type directly instead of building an ENUMERAL_TYPE. */
t->ctype = build_variant_type_copy (basetype);
- build_type_decl (t->ctype, t->sym);
+
+ if (t->sym->ident != NULL)
+ build_type_decl (t->ctype, t->sym);
}
else
{
diff --git a/gcc/testsuite/gdc.dg/special1.d b/gcc/testsuite/gdc.dg/special1.d
new file mode 100644
index 0000000..8881dd0
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/special1.d
@@ -0,0 +1,12 @@
+// { dg-do compile }
+
+struct _Complex(T) { T re; T im; }
+enum __c_complex_float : _Complex!float;
+
+bool equals(__c_complex_float[] lhs, __c_complex_float[] rhs)
+{
+ foreach (i; 0 .. lhs.length)
+ if (lhs.ptr[i] != rhs.ptr[i])
+ return false;
+ return true;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/99bottles.d b/gcc/testsuite/gdc.test/compilable/99bottles.d
index 5341a49..ac416eb 100644
--- a/gcc/testsuite/gdc.test/compilable/99bottles.d
+++ b/gcc/testsuite/gdc.test/compilable/99bottles.d
@@ -3,7 +3,7 @@
// http://www.99-bottles-of-beer.net/language-d-1212.html
// Generates the "99 bottles of beer" song at compile time,
-// using the template metaprograming facilities of D.
+// using the template metaprograming facilities of D.
// No executable is generated. No libraries are used.
// Illustrates template default values, template string value parameters,
// compile-time concatenation of constant strings, static if.
@@ -24,13 +24,13 @@ template itoa(ulong n)
template showHowMany(int n, string where, bool needcapital = false)
{
- static if ( n > 1 )
+ static if ( n > 1 )
const string showHowMany = itoa!(n) ~ " bottles of beer" ~ where ~ "\n";
else static if ( n == 1 )
const string showHowMany = "1 bottle of beer" ~ where ~ "\n";
else static if ( needcapital )
const string showHowMany = "No more bottles of beer" ~ where ~ "\n";
- else
+ else
const string showHowMany = "no more bottles of beer" ~ where ~ "\n";
}
@@ -39,514 +39,514 @@ template beer(int maxbeers, int n = maxbeers)
static if ( n > 0 )
const string beer = showHowMany!(n, " on the wall,", true)
~ showHowMany!(n, ".")
- ~ "Take one down and pass it around, " ~ "\n"
- ~ showHowMany!( n - 1 , " on the wall.")
+ ~ "Take one down and pass it around," ~ "\n"
+ ~ showHowMany!( n - 1 , " on the wall.")
~ "\n" ~ beer!(maxbeers, n - 1); // recurse for subsequent verses.
else
const string beer = showHowMany!(n, " on the wall,", true)
~ showHowMany!(n, ".")
- ~ "Go to the store and buy some more, " ~ "\n"
+ ~ "Go to the store and buy some more," ~ "\n"
~ showHowMany!( maxbeers, " on the wall.");
}
enum expected = `99 bottles of beer on the wall,
99 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
98 bottles of beer on the wall.
98 bottles of beer on the wall,
98 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
97 bottles of beer on the wall.
97 bottles of beer on the wall,
97 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
96 bottles of beer on the wall.
96 bottles of beer on the wall,
96 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
95 bottles of beer on the wall.
95 bottles of beer on the wall,
95 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
94 bottles of beer on the wall.
94 bottles of beer on the wall,
94 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
93 bottles of beer on the wall.
93 bottles of beer on the wall,
93 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
92 bottles of beer on the wall.
92 bottles of beer on the wall,
92 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
91 bottles of beer on the wall.
91 bottles of beer on the wall,
91 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
90 bottles of beer on the wall.
90 bottles of beer on the wall,
90 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
89 bottles of beer on the wall.
89 bottles of beer on the wall,
89 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
88 bottles of beer on the wall.
88 bottles of beer on the wall,
88 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
87 bottles of beer on the wall.
87 bottles of beer on the wall,
87 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
86 bottles of beer on the wall.
86 bottles of beer on the wall,
86 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
85 bottles of beer on the wall.
85 bottles of beer on the wall,
85 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
84 bottles of beer on the wall.
84 bottles of beer on the wall,
84 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
83 bottles of beer on the wall.
83 bottles of beer on the wall,
83 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
82 bottles of beer on the wall.
82 bottles of beer on the wall,
82 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
81 bottles of beer on the wall.
81 bottles of beer on the wall,
81 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
80 bottles of beer on the wall.
80 bottles of beer on the wall,
80 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
79 bottles of beer on the wall.
79 bottles of beer on the wall,
79 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
78 bottles of beer on the wall.
78 bottles of beer on the wall,
78 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
77 bottles of beer on the wall.
77 bottles of beer on the wall,
77 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
76 bottles of beer on the wall.
76 bottles of beer on the wall,
76 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
75 bottles of beer on the wall.
75 bottles of beer on the wall,
75 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
74 bottles of beer on the wall.
74 bottles of beer on the wall,
74 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
73 bottles of beer on the wall.
73 bottles of beer on the wall,
73 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
72 bottles of beer on the wall.
72 bottles of beer on the wall,
72 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
71 bottles of beer on the wall.
71 bottles of beer on the wall,
71 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
70 bottles of beer on the wall.
70 bottles of beer on the wall,
70 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
69 bottles of beer on the wall.
69 bottles of beer on the wall,
69 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
68 bottles of beer on the wall.
68 bottles of beer on the wall,
68 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
67 bottles of beer on the wall.
67 bottles of beer on the wall,
67 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
66 bottles of beer on the wall.
66 bottles of beer on the wall,
66 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
65 bottles of beer on the wall.
65 bottles of beer on the wall,
65 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
64 bottles of beer on the wall.
64 bottles of beer on the wall,
64 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
63 bottles of beer on the wall.
63 bottles of beer on the wall,
63 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
62 bottles of beer on the wall.
62 bottles of beer on the wall,
62 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
61 bottles of beer on the wall.
61 bottles of beer on the wall,
61 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
60 bottles of beer on the wall.
60 bottles of beer on the wall,
60 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
59 bottles of beer on the wall.
59 bottles of beer on the wall,
59 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
58 bottles of beer on the wall.
58 bottles of beer on the wall,
58 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
57 bottles of beer on the wall.
57 bottles of beer on the wall,
57 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
56 bottles of beer on the wall.
56 bottles of beer on the wall,
56 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
55 bottles of beer on the wall.
55 bottles of beer on the wall,
55 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
54 bottles of beer on the wall.
54 bottles of beer on the wall,
54 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
53 bottles of beer on the wall.
53 bottles of beer on the wall,
53 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
52 bottles of beer on the wall.
52 bottles of beer on the wall,
52 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
51 bottles of beer on the wall.
51 bottles of beer on the wall,
51 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
50 bottles of beer on the wall.
50 bottles of beer on the wall,
50 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
49 bottles of beer on the wall.
49 bottles of beer on the wall,
49 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
48 bottles of beer on the wall.
48 bottles of beer on the wall,
48 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
47 bottles of beer on the wall.
47 bottles of beer on the wall,
47 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
46 bottles of beer on the wall.
46 bottles of beer on the wall,
46 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
45 bottles of beer on the wall.
45 bottles of beer on the wall,
45 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
44 bottles of beer on the wall.
44 bottles of beer on the wall,
44 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
43 bottles of beer on the wall.
43 bottles of beer on the wall,
43 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
42 bottles of beer on the wall.
42 bottles of beer on the wall,
42 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
41 bottles of beer on the wall.
41 bottles of beer on the wall,
41 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
40 bottles of beer on the wall.
40 bottles of beer on the wall,
40 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
39 bottles of beer on the wall.
39 bottles of beer on the wall,
39 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
38 bottles of beer on the wall.
38 bottles of beer on the wall,
38 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
37 bottles of beer on the wall.
37 bottles of beer on the wall,
37 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
36 bottles of beer on the wall.
36 bottles of beer on the wall,
36 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
35 bottles of beer on the wall.
35 bottles of beer on the wall,
35 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
34 bottles of beer on the wall.
34 bottles of beer on the wall,
34 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
33 bottles of beer on the wall.
33 bottles of beer on the wall,
33 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
32 bottles of beer on the wall.
32 bottles of beer on the wall,
32 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
31 bottles of beer on the wall.
31 bottles of beer on the wall,
31 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
30 bottles of beer on the wall.
30 bottles of beer on the wall,
30 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
29 bottles of beer on the wall.
29 bottles of beer on the wall,
29 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
28 bottles of beer on the wall.
28 bottles of beer on the wall,
28 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
27 bottles of beer on the wall.
27 bottles of beer on the wall,
27 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
26 bottles of beer on the wall.
26 bottles of beer on the wall,
26 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
25 bottles of beer on the wall.
25 bottles of beer on the wall,
25 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
24 bottles of beer on the wall.
24 bottles of beer on the wall,
24 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
23 bottles of beer on the wall.
23 bottles of beer on the wall,
23 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
22 bottles of beer on the wall.
22 bottles of beer on the wall,
22 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
21 bottles of beer on the wall.
21 bottles of beer on the wall,
21 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
20 bottles of beer on the wall.
20 bottles of beer on the wall,
20 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
19 bottles of beer on the wall.
19 bottles of beer on the wall,
19 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
18 bottles of beer on the wall.
18 bottles of beer on the wall,
18 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
17 bottles of beer on the wall.
17 bottles of beer on the wall,
17 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
16 bottles of beer on the wall.
16 bottles of beer on the wall,
16 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
15 bottles of beer on the wall.
15 bottles of beer on the wall,
15 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
14 bottles of beer on the wall.
14 bottles of beer on the wall,
14 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
13 bottles of beer on the wall.
13 bottles of beer on the wall,
13 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
12 bottles of beer on the wall.
12 bottles of beer on the wall,
12 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
11 bottles of beer on the wall.
11 bottles of beer on the wall,
11 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
10 bottles of beer on the wall.
10 bottles of beer on the wall,
10 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
9 bottles of beer on the wall.
9 bottles of beer on the wall,
9 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
8 bottles of beer on the wall.
8 bottles of beer on the wall,
8 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
7 bottles of beer on the wall.
7 bottles of beer on the wall,
7 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
6 bottles of beer on the wall.
6 bottles of beer on the wall,
6 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
5 bottles of beer on the wall.
5 bottles of beer on the wall,
5 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
4 bottles of beer on the wall.
4 bottles of beer on the wall,
4 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
3 bottles of beer on the wall.
3 bottles of beer on the wall,
3 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
2 bottles of beer on the wall.
2 bottles of beer on the wall,
2 bottles of beer.
-Take one down and pass it around,
+Take one down and pass it around,
1 bottle of beer on the wall.
1 bottle of beer on the wall,
1 bottle of beer.
-Take one down and pass it around,
+Take one down and pass it around,
no more bottles of beer on the wall.
No more bottles of beer on the wall,
no more bottles of beer.
-Go to the store and buy some more,
+Go to the store and buy some more,
99 bottles of beer on the wall.
`;
diff --git a/gcc/testsuite/gdc.test/compilable/b18242.d b/gcc/testsuite/gdc.test/compilable/b18242.d
index 5dcaeca..3bc699a 100644
--- a/gcc/testsuite/gdc.test/compilable/b18242.d
+++ b/gcc/testsuite/gdc.test/compilable/b18242.d
@@ -5,14 +5,14 @@ module object;
class Object { }
class TypeInfo { }
-class TypeInfo_Class : TypeInfo
-{
+class TypeInfo_Class : TypeInfo
+{
version(D_LP64) { ubyte[136] _x; } else { ubyte[68] _x; }
}
class Throwable { }
-int _d_run_main()
+int _d_run_main()
{
try { } catch(Throwable e) { return 1; }
return 0;
diff --git a/gcc/testsuite/gdc.test/compilable/b19294.d b/gcc/testsuite/gdc.test/compilable/b19294.d
index 063a9df..ed1a717 100644
--- a/gcc/testsuite/gdc.test/compilable/b19294.d
+++ b/gcc/testsuite/gdc.test/compilable/b19294.d
@@ -51,19 +51,19 @@ void test()
MT s = MyStruct!int(1);
MT[] arr = [s, 2 * s, 3 * s, 4 * s, 5 * s, 6 * s];
MT[] result = new MT[arr.length];
-
+
result[] = arr[] + s;
result[] = s + arr[];
-
+
result[] = arr[] - s;
result[] = s - arr[];
-
+
result[] = arr[] * s;
result[] = s * arr[];
-
+
result[] = arr[] / s;
result[] = s / arr[];
-
+
result[] = arr[] ^^ s;
result[] = s ^^ arr[];
}
diff --git a/gcc/testsuite/gdc.test/compilable/b20938.d b/gcc/testsuite/gdc.test/compilable/b20938.d
index efcf4aa..ba3565a 100644
--- a/gcc/testsuite/gdc.test/compilable/b20938.d
+++ b/gcc/testsuite/gdc.test/compilable/b20938.d
@@ -12,11 +12,11 @@ void fun() {
immutable S _is;
Object o;
immutable Object io;
-
+
auto a = [pi, ipi];
- auto b = [ai, iai];
+ auto b = [ai, iai];
auto c = [s, _is];
auto d = [o, io];
-
+
auto e = [A.a, B.b];
}
diff --git a/gcc/testsuite/gdc.test/compilable/b21285.d b/gcc/testsuite/gdc.test/compilable/b21285.d
index 11eea74..482faa7 100644
--- a/gcc/testsuite/gdc.test/compilable/b21285.d
+++ b/gcc/testsuite/gdc.test/compilable/b21285.d
@@ -1,27 +1,27 @@
// REQUIRED_ARGS: -unittest
-// Issue 21285 - Delegate covariance broken between 2.092 and 2.094 (git master).
+// Issue 21285 - Delegate covariance broken between 2.092 and 2.094 (git master).
unittest
{
string path;
int bank;
static string path2;
static int bank2;
-
+
// delegates
auto a = [
(string arg) { path = arg; },
(string arg) { bank = 1; throw new Exception(""); }
];
-
+
// functions
auto ab = [
(string arg) { path2 = arg; },
(string arg) { bank2 = 1; throw new Exception(""); }
];
-
+
alias dg = void delegate(string) pure @safe;
alias fn = void function(string) @safe;
-
+
static assert(is(typeof(a[0]) == dg));
static assert(is(typeof(ab[0]) == fn));
}
diff --git a/gcc/testsuite/gdc.test/compilable/commontype.d b/gcc/testsuite/gdc.test/compilable/commontype.d
index 076e29b..a740994 100644
--- a/gcc/testsuite/gdc.test/compilable/commontype.d
+++ b/gcc/testsuite/gdc.test/compilable/commontype.d
@@ -196,7 +196,8 @@ static assert(is( X!( C***, B*** ) == const(B**)* )); // `B***`
static assert(is( X!( C*, I* ) == I* ));
static assert(is( X!( I*, C* ) == I* ));
-static assert(Error!( C**, I** ));
+//static assert(Error!( C**, I** ));
+static assert(is( X!( C**, I** ) == const(I*)* ));
static assert(Error!( C*, D* )); // should work
@@ -303,13 +304,15 @@ static assert(is( X!(C[4], B[4]) ));
static assert(Error!( C[4], I[4] ));
static assert(Error!( C[4], D[4] ));
static assert(is( X!( C[4], const(B)[4] ) == const(B)[4] ));
-static assert(Error!( C[4], const(I)[4] ));
+//static assert(Error!( C[4], const(I)[4] ));
+static assert(is( X!( C[4], const(I)[4] ) == const(I)[] ));
static assert(Error!( C[4], const(D)[4] ));
static assert(Error!( C*[4], B*[4] ));
static assert(Error!( C*[4], I*[4] ));
static assert(Error!( C*[4], D*[4] ));
static assert(is( X!( C*[4], const(B*)[4] ) == const(B*)[] )); // !?
-static assert(Error!( C*[4], const(I*)[4] ));
+//static assert(Error!( C*[4], const(I*)[4] ));
+static assert(is( X!( C*[4], const(I*)[4] ) == const(I*)[] ));
static assert(Error!( C*[4], const(D*)[4] ));
static assert(Error!( C*[4], B**[4] ));
static assert(Error!( C*[4], const(B*)*[4] ));
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc10.d b/gcc/testsuite/gdc.test/compilable/ddoc10.d
index 6a7a481..2f61409 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc10.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc10.d
@@ -171,7 +171,7 @@ struct T
/****
*/
this(A...)(A args) { }
-
+
///
this(int){}
}
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc11.d b/gcc/testsuite/gdc.test/compilable/ddoc11.d
index 3fcf2ca..0082455 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc11.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc11.d
@@ -49,7 +49,7 @@ struct lldiv_t { long quot,rem; }
- void *calloc(size_t, size_t); ///
+ void *calloc(size_t, size_t); ///
void *malloc(size_t); /// dittx
/**
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc14.d b/gcc/testsuite/gdc.test/compilable/ddoc14.d
index a8b6d4d..fae99d4 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc14.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc14.d
@@ -77,7 +77,7 @@ interface Interface {
V mColon(lazy P p) ; /// 10
}
+/
-
+
public P variable; /// 0
V mNone(lazy P p) {} /// 1
pure nothrow V mPrefix(lazy P p) {} /// 2
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc3.d b/gcc/testsuite/gdc.test/compilable/ddoc3.d
index 1bcae41..3b47497 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc3.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc3.d
@@ -42,7 +42,7 @@
* $(TROW 4, 5, 6)
* )
*
- * $(D_CODE
+ * $(D_CODE
$(B pragma)( $(I name) );
$(B pragma)( $(I name) , $(I option) [ $(I option) ] );
$(U $(LPAREN))
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc5.d b/gcc/testsuite/gdc.test/compilable/ddoc5.d
index 4ddc123..5a964f3 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc5.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc5.d
@@ -15,10 +15,10 @@ class TestMembers(TemplateArg)
public:
/**
- a static method
+ a static method
Params: idx = index
-
+
*/
static void PublicStaticMethod(int idx)
{
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc5446.d b/gcc/testsuite/gdc.test/compilable/ddoc5446.d
index 0596088..29cb8c9 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc5446.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc5446.d
@@ -30,41 +30,41 @@ struct Bar
{
/** */
alias A_Foo Bar_A_Foo;
-
+
/** */
alias A_Foo_Alias Bar_A_Foo_Alias;
-
+
/** */
alias A_Int Bar_A_Int;
-
+
/** */
alias This_Foo Bar_This_Foo;
-
+
/** */
alias This_Foo_Alias Bar_This_Foo_Alias;
-
+
/** */
alias This_Int Bar_This_Int;
-
+
/** */
alias Nested Nested_Alias;
-
+
/** */
alias .Nested Fake_Nested;
-
+
/** */
struct Nested
{
/** */
alias Bar Bar_Nested_Bar_Alias;
-
+
/** */
alias .Bar Bar_Alias;
-
+
/** */
struct Bar
{
-
+
}
}
}
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc9155.d b/gcc/testsuite/gdc.test/compilable/ddoc9155.d
index 9f5a59a..e03d422 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc9155.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc9155.d
@@ -12,12 +12,12 @@ module ddoc9155;
+ ---
+ import std.stdio; //&
+ writeln("Hello world!");
- + if (test) {
+ + if (test) {
+ writefln("D programming language");
+ }
+
+ algorithm;
- +
+ +
+ xxx; //comment
+ yyy;
+ /* test
@@ -28,7 +28,7 @@ module ddoc9155;
+File f = File("./text.txt", "r");
+uint line = 0;
+ // The ElementType of data is not aggregation type
- +foreach (encoded; Base64.encoder(data))
+ +foreach (encoded; Base64.encoder(data))
+ ---
+/
@@ -45,12 +45,12 @@ module ddoc9155;
* ---
* import std.stdio; //&
* writeln("Hello world!");
- * if (test) {
+ * if (test) {
* writefln("D programming language");
* }
*
* algorithm;
- *
+ *
* xxx; //comment
* yyy;
* /+ test
diff --git a/gcc/testsuite/gdc.test/compilable/debugInference.d b/gcc/testsuite/gdc.test/compilable/debugInference.d
index 1d4f157..947d820 100644
--- a/gcc/testsuite/gdc.test/compilable/debugInference.d
+++ b/gcc/testsuite/gdc.test/compilable/debugInference.d
@@ -1,9 +1,5 @@
/*
REQUIRED_ARGS: -debug
-TEST_OUTPUT:
----
-compilable/debugInference.d(35): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
----
https://issues.dlang.org/show_bug.cgi?id=20507
*/
@@ -32,7 +28,7 @@ void bar()()
auto f2Ptr = &f2;
S s;
- delete s;
+ destroy(s);
int* ptr = cast(int*) 0;
int[] slice = ptr[0 .. 4];
diff --git a/gcc/testsuite/gdc.test/compilable/defa.d b/gcc/testsuite/gdc.test/compilable/defa.d
index a922207..5b4e589 100644
--- a/gcc/testsuite/gdc.test/compilable/defa.d
+++ b/gcc/testsuite/gdc.test/compilable/defa.d
@@ -3,7 +3,7 @@
module defa;
private import imports.defaa;
-
+
public abstract class A
{
Display d;
diff --git a/gcc/testsuite/gdc.test/compilable/dlangui_crash.d b/gcc/testsuite/gdc.test/compilable/dlangui_crash.d
new file mode 100644
index 0000000..36617f5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/dlangui_crash.d
@@ -0,0 +1,34 @@
+// https://issues.dlang.org/show_bug.cgi?id=22365
+
+class DrawableCache
+{
+ Ref _nullDrawable;
+
+ this()
+ {
+ debug Log;
+ }
+}
+
+class DrawableCacheEmpty
+{
+ Ref _nullDrawable;
+
+ this() {}
+}
+
+struct Ref
+{
+
+ ~this()
+ {
+ }
+}
+
+void foo()
+{
+ try
+ debug Log;
+ catch (Exception)
+ assert(false);
+}
diff --git a/gcc/testsuite/gdc.test/compilable/enumbasearithmetic.d b/gcc/testsuite/gdc.test/compilable/enumbasearithmetic.d
new file mode 100644
index 0000000..4dbc56d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/enumbasearithmetic.d
@@ -0,0 +1,20 @@
+//https://issues.dlang.org/show_bug.cgi?id=20777
+struct FooInt
+{
+ int i;
+ auto opBinary(string op : "+")(int j)
+ {
+ return typeof(this)(i + j);
+ }
+
+ static @property FooInt max()
+ {
+ return typeof(this)(int.max);
+ }
+}
+
+enum foolist
+{
+ hi = FooInt(0),
+ bye
+}
diff --git a/gcc/testsuite/gdc.test/compilable/header18364.d b/gcc/testsuite/gdc.test/compilable/header18364.d
index c7e1e67..080a096 100644
--- a/gcc/testsuite/gdc.test/compilable/header18364.d
+++ b/gcc/testsuite/gdc.test/compilable/header18364.d
@@ -8,7 +8,7 @@ TEST_OUTPUT:
=== ${RESULTS_DIR}/compilable/header18364.di
// D import file generated from 'compilable/header18364.d'
module foo.bar.ba;
-nothrow pure @nogc @safe package(foo)
+nothrow pure @nogc @safe package(foo)
{
void foo();
nothrow pure @nogc @safe package(foo.bar) void foo2();
diff --git a/gcc/testsuite/gdc.test/compilable/imports/b33a.d b/gcc/testsuite/gdc.test/compilable/imports/b33a.d
index 5d52c66..bd8fd0c 100644
--- a/gcc/testsuite/gdc.test/compilable/imports/b33a.d
+++ b/gcc/testsuite/gdc.test/compilable/imports/b33a.d
@@ -6,10 +6,10 @@ struct IsEqual( T )
{
return p1 == p2;
}
-}
+}
template find_( Elem, Pred = IsEqual!(Elem) )
-{
+{
size_t fn( char[] buf, Pred pred = Pred.init )
{
return 3;
diff --git a/gcc/testsuite/gdc.test/compilable/imports/imp22734.c b/gcc/testsuite/gdc.test/compilable/imports/imp22734.c
new file mode 100644
index 0000000..9df542b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/imp22734.c
@@ -0,0 +1,3 @@
+typedef enum { C } E;
+
+int a = C;
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test22714a.d b/gcc/testsuite/gdc.test/compilable/imports/test22714a.d
new file mode 100644
index 0000000..7b77272
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test22714a.d
@@ -0,0 +1,3 @@
+module imports.test22714a;
+import imports.test22714b;
+class Statement {}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test22714b.d b/gcc/testsuite/gdc.test/compilable/imports/test22714b.d
new file mode 100644
index 0000000..68bd95b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test22714b.d
@@ -0,0 +1,12 @@
+module imports.test22714b;
+import imports.test22714a;
+struct Array(T)
+{
+ T[] data;
+ T[1] smallarray;
+}
+struct Ensure
+{
+ Statement ensure;
+ Array!Ensure* arraySyntaxCopy;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/issue16472.d b/gcc/testsuite/gdc.test/compilable/issue16472.d
new file mode 100644
index 0000000..a4353ce
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/issue16472.d
@@ -0,0 +1,42 @@
+// https://issues.dlang.org/show_bug.cgi?id=16472
+enum e() = 0;
+
+template t(alias v = e!()) {} //Error
+alias dummy = t!(e!());
+
+template E(F){
+ enum E {
+ K = F(1)
+ }
+}
+
+struct S(F = float, alias e_ = E!double.K) {}
+S!float x; // Error: E!double.K is used as a type
+
+alias T = E!double.K;
+struct S2(F = float, alias e_ = T) {}
+S2!float y; // alias makes it okay...
+
+struct S3(F = float, alias e_ = (E!double.K)) {}
+S3!float z; // just putting parens make it okay as well... wat!?
+
+// for coverage
+
+template G(T)
+{
+ struct G
+ {
+ alias I = int;
+ static int i;
+ }
+}
+
+struct H(F = float, alias e_ = G!double) {}
+H!float a;
+
+struct H1(F = float, alias e_ = G!double.I) {}
+H1!float b;
+
+// https://issues.dlang.org/show_bug.cgi?id=21795
+// struct H2(F = float, alias e_ = G!double.i) {}
+// H2!float c;
diff --git a/gcc/testsuite/gdc.test/compilable/issue21340.d b/gcc/testsuite/gdc.test/compilable/issue21340.d
index 22eda6e..03d37bd 100644
--- a/gcc/testsuite/gdc.test/compilable/issue21340.d
+++ b/gcc/testsuite/gdc.test/compilable/issue21340.d
@@ -5,7 +5,7 @@ version (CppRuntime_Sun) version = CppMangle_Itanium;
template ScopeClass(C)
if (is(C == class) && __traits(getLinkage, C) == "C++")
{
-
+
extern(C++, class)
extern(C++, __traits(getCppNamespaces,C))
extern(C++, (ns))
@@ -35,4 +35,4 @@ alias ns = AliasSeq!();
immutable ns2 = AliasSeq!();
extern(C++,(ns)) class Bar {}
extern(C++,) class Baz {}
-extern(C++, (ns2)) class Quux {}
+extern(C++, (ns2)) class Quux {}
diff --git a/gcc/testsuite/gdc.test/compilable/issue21813b.d b/gcc/testsuite/gdc.test/compilable/issue21813b.d
index ef22697..0af986b 100644
--- a/gcc/testsuite/gdc.test/compilable/issue21813b.d
+++ b/gcc/testsuite/gdc.test/compilable/issue21813b.d
@@ -4,7 +4,7 @@ Target.OS defaultTargetOS()
return Target.OS.linux;
}
-struct Target
+struct Target
{
enum OS { linux }
OS os = defaultTargetOS();
diff --git a/gcc/testsuite/gdc.test/compilable/minimal.d b/gcc/testsuite/gdc.test/compilable/minimal.d
index 6398328..155f0ed 100644
--- a/gcc/testsuite/gdc.test/compilable/minimal.d
+++ b/gcc/testsuite/gdc.test/compilable/minimal.d
@@ -10,7 +10,7 @@
struct S { }
-enum E
+enum E
{
e0 = 0,
e1 = 1
diff --git a/gcc/testsuite/gdc.test/compilable/test10993.d b/gcc/testsuite/gdc.test/compilable/test10993.d
index a69d0c6..9a99187 100644
--- a/gcc/testsuite/gdc.test/compilable/test10993.d
+++ b/gcc/testsuite/gdc.test/compilable/test10993.d
@@ -19,7 +19,7 @@ auto fun()
{
auto x = foo!()(test!(a=>a)());
// pragma(msg, "fun: " ~ typeof(x).mangleof);
-
+
return x;
}
diff --git a/gcc/testsuite/gdc.test/compilable/test16107.d b/gcc/testsuite/gdc.test/compilable/test16107.d
index 2267be3..3de4dd1 100644
--- a/gcc/testsuite/gdc.test/compilable/test16107.d
+++ b/gcc/testsuite/gdc.test/compilable/test16107.d
@@ -3,12 +3,12 @@
bool check()
{
bool result = false;
-
+
result |= false;
if (result) goto ret;
-
+
result |= false;
if (result) {}
-
+
ret: return true;
}
diff --git a/gcc/testsuite/gdc.test/compilable/test17545.d b/gcc/testsuite/gdc.test/compilable/test17545.d
index bb0c2ae..6285418 100644
--- a/gcc/testsuite/gdc.test/compilable/test17545.d
+++ b/gcc/testsuite/gdc.test/compilable/test17545.d
@@ -12,5 +12,5 @@ struct Attrib {}
@Attrib enum TEST = 123;
-pragma(msg, __traits(getAttributes,
+pragma(msg, __traits(getAttributes,
__traits(getMember, example, "TEST")));
diff --git a/gcc/testsuite/gdc.test/compilable/test17906.d b/gcc/testsuite/gdc.test/compilable/test17906.d
deleted file mode 100644
index 9c4a547..0000000
--- a/gcc/testsuite/gdc.test/compilable/test17906.d
+++ /dev/null
@@ -1,7 +0,0 @@
-// REQUIRED_ARGS: -de
-// https://issues.dlang.org/show_bug.cgi?id=18647
-deprecated void main ()
-{
- Object o = new Object;
- delete o;
-}
diff --git a/gcc/testsuite/gdc.test/compilable/test18030.d b/gcc/testsuite/gdc.test/compilable/test18030.d
index f742a40..37f8630 100644
--- a/gcc/testsuite/gdc.test/compilable/test18030.d
+++ b/gcc/testsuite/gdc.test/compilable/test18030.d
@@ -9,6 +9,6 @@ struct S(T)
class C
{
alias Al = S!C;
-
+
static void func(U)(U var) { }
}
diff --git a/gcc/testsuite/gdc.test/compilable/test19014.d b/gcc/testsuite/gdc.test/compilable/test19014.d
index 7bbbc94..1110b28 100644
--- a/gcc/testsuite/gdc.test/compilable/test19014.d
+++ b/gcc/testsuite/gdc.test/compilable/test19014.d
@@ -8,5 +8,5 @@ void main()
{
static import core.stdc.math;
}
- static assert(!__traits(compiles, core.stdc.math.cos(0)));
+ static assert(!__traits(compiles, core.stdc.math.cos(0)));
}
diff --git a/gcc/testsuite/gdc.test/compilable/test19315.d b/gcc/testsuite/gdc.test/compilable/test19315.d
index 0c31ab8..e95ecac 100644
--- a/gcc/testsuite/gdc.test/compilable/test19315.d
+++ b/gcc/testsuite/gdc.test/compilable/test19315.d
@@ -1,5 +1,5 @@
//https://issues.dlang.org/show_bug.cgi?id=19315
-void main()
+void main()
{
#line 100 "file.d"
enum code = q{
diff --git a/gcc/testsuite/gdc.test/compilable/test19557.d b/gcc/testsuite/gdc.test/compilable/test19557.d
index f107e22..b11ae10 100644
--- a/gcc/testsuite/gdc.test/compilable/test19557.d
+++ b/gcc/testsuite/gdc.test/compilable/test19557.d
@@ -1,6 +1,6 @@
// https://issues.dlang.org/show_bug.cgi?id=19557
// Error: redundant linkage `extern (C++)`
-
+
extern(C++, "ns")
extern(C++, class)
struct test {}
diff --git a/gcc/testsuite/gdc.test/compilable/test19609.d b/gcc/testsuite/gdc.test/compilable/test19609.d
index 4367df1..df8f891 100644
--- a/gcc/testsuite/gdc.test/compilable/test19609.d
+++ b/gcc/testsuite/gdc.test/compilable/test19609.d
@@ -3,9 +3,9 @@
/*
TEST_OUTPUT:
---
-compilable/test19609.d(11): Deprecation: module `imports.test19609a` is deprecated -
+compilable/test19609.d(11): Deprecation: module `imports.test19609a` is deprecated
compilable/test19609.d(12): Deprecation: module `imports.test19609b` is deprecated - hello
-compilable/test19609.d(13): Deprecation: module `imports.test19609c` is deprecated -
+compilable/test19609.d(13): Deprecation: module `imports.test19609c` is deprecated
---
*/
import imports.test19609a;
diff --git a/gcc/testsuite/gdc.test/compilable/test21177.d b/gcc/testsuite/gdc.test/compilable/test21177.d
new file mode 100644
index 0000000..b3b613b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test21177.d
@@ -0,0 +1,76 @@
+// https://issues.dlang.org/show_bug.cgi?id=21177
+/*
+DISABLED: win
+TEST_OUTPUT:
+---
+compilable/test21177.d(103): Deprecation: more format specifiers than 0 arguments
+compilable/test21177.d(150): Deprecation: more format specifiers than 0 arguments
+compilable/test21177.d(151): Deprecation: more format specifiers than 0 arguments
+compilable/test21177.d(152): Deprecation: more format specifiers than 0 arguments
+compilable/test21177.d(153): Deprecation: more format specifiers than 0 arguments
+compilable/test21177.d(200): Deprecation: more format specifiers than 0 arguments
+compilable/test21177.d(203): Deprecation: format specifier `"%m"` is invalid
+compilable/test21177.d(204): Deprecation: format specifier `"%m"` is invalid
+compilable/test21177.d(205): Deprecation: argument `c` for format specification `"%a"` must be `float*`, not `char*`
+compilable/test21177.d(206): Deprecation: argument `c` for format specification `"%a"` must be `float*`, not `char*`
+---
+*/
+
+import core.stdc.stdio;
+import core.stdc.string;
+import core.stdc.stdlib;
+
+void main()
+{
+ version (CRuntime_Glibc)
+ {
+ #line 100
+ printf("%m this is a string in errno");
+ printf("%s %m", "str".ptr, 2);
+ printf("%a", 2.);
+ printf("%m %m %s");
+ printf("%*m");
+
+ char* a, b;
+ sscanf("salut poilu", "%a %m", a, b);
+ assert(!strcmp(a, b));
+ free(a);
+ free(b);
+
+ char* t, p;
+ sscanf("Tomate Patate", "%ms %as", t, p);
+ free(t);
+ free(p);
+
+ #line 150
+ sscanf("150", "%m");
+ sscanf("151", "%ms");
+ sscanf("152", "%a");
+ sscanf("153", "%as");
+
+ pragma(msg, "compilable/test21177.d(200): Deprecation: more format specifiers than 0 arguments");
+ pragma(msg, "compilable/test21177.d(203): Deprecation: format specifier `\"%m\"` is invalid");
+ pragma(msg, "compilable/test21177.d(204): Deprecation: format specifier `\"%m\"` is invalid");
+ pragma(msg, "compilable/test21177.d(205): Deprecation: argument `c` for format specification `\"%a\"` must be `float*`, not `char*`");
+ pragma(msg, "compilable/test21177.d(206): Deprecation: argument `c` for format specification `\"%a\"` must be `float*`, not `char*`");
+ }
+ else
+ {
+ // fake it
+ pragma(msg, "compilable/test21177.d(103): Deprecation: more format specifiers than 0 arguments");
+ pragma(msg, "compilable/test21177.d(150): Deprecation: more format specifiers than 0 arguments");
+ pragma(msg, "compilable/test21177.d(151): Deprecation: more format specifiers than 0 arguments");
+ pragma(msg, "compilable/test21177.d(152): Deprecation: more format specifiers than 0 arguments");
+ pragma(msg, "compilable/test21177.d(153): Deprecation: more format specifiers than 0 arguments");
+
+ #line 200
+ printf("%m");
+
+ char* c;
+ sscanf("204", "%m", c);
+ sscanf("205", "%ms", c);
+ sscanf("206", "%a", c);
+ sscanf("207", "%as", c);
+
+ }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test21196.d b/gcc/testsuite/gdc.test/compilable/test21196.d
new file mode 100644
index 0000000..f8507b4
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test21196.d
@@ -0,0 +1,71 @@
+// https://issues.dlang.org/show_bug.cgi?id=21674
+// REQUIRED_ARGS: -de
+
+struct Module
+{
+ CachedString data;
+}
+
+struct CachedString
+{
+ private size_t len;
+
+ this (string data) { this.len = data.length; }
+ public string str () const { return null; }
+ public void str (string value) { this.len = value.length; }
+
+ alias str this;
+}
+
+void test21674a()
+{
+ Module m;
+ m.data = "Hello World";
+}
+
+//////////////////////////////////////////
+
+struct StaticGetter(T)
+{
+ private static T _impl;
+ static ref T value() { return _impl; }
+ alias value this;
+}
+
+struct StaticWrapper
+{
+ StaticGetter!int get;
+ alias get this;
+}
+
+void test21674b()
+{
+ StaticGetter!float sg;
+ sg = 4.2;
+
+ StaticWrapper sw;
+ sw = 42;
+}
+
+//////////////////////////////////////////
+
+EntryType arr;
+auto getPtr() { return &arr; }
+
+struct EntryType
+{
+ bool _state;
+ alias _state this;
+}
+
+struct S19441
+{
+ @property auto ref entry() { return *getPtr(); }
+ alias entry this;
+}
+
+void test19441()
+{
+ S19441 s19441;
+ s19441 = true;
+}
diff --git a/gcc/testsuite/gdc.test/compilable/test22224.d b/gcc/testsuite/gdc.test/compilable/test22224.d
index d16b2f40..ef131e9 100644
--- a/gcc/testsuite/gdc.test/compilable/test22224.d
+++ b/gcc/testsuite/gdc.test/compilable/test22224.d
@@ -1,4 +1,4 @@
// REQUIRED_ARGS: -profile -c
-import core.stdc.stdarg;
+import core.stdc.stdarg;
void error(...) { }
diff --git a/gcc/testsuite/gdc.test/compilable/test22632.d b/gcc/testsuite/gdc.test/compilable/test22632.d
new file mode 100644
index 0000000..673b51b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22632.d
@@ -0,0 +1,4 @@
+// https://issues.dlang.org/show_bug.cgi?id=22632
+
+static assert(["one": 1] != null);
+static assert(null != ["one": 1]);
diff --git a/gcc/testsuite/gdc.test/compilable/test22714.d b/gcc/testsuite/gdc.test/compilable/test22714.d
new file mode 100644
index 0000000..2973e1d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22714.d
@@ -0,0 +1,3 @@
+// EXTRA_FILES: imports/test22714a.d imports/test22714b.d
+// https://issues.dlang.org/show_bug.cgi?id=22714
+import imports.test22714a;
diff --git a/gcc/testsuite/gdc.test/compilable/test22734.d b/gcc/testsuite/gdc.test/compilable/test22734.d
new file mode 100644
index 0000000..fdd962e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22734.d
@@ -0,0 +1,6 @@
+// https://issues.dlang.org/show_bug.cgi?id=22734
+// EXTRA_FILES: imports/imp22734.c
+
+import imports.imp22734;
+
+auto dc = C;
diff --git a/gcc/testsuite/gdc.test/compilable/test4375.d b/gcc/testsuite/gdc.test/compilable/test4375.d
index f5c4e4a..1cc7a3a 100644
--- a/gcc/testsuite/gdc.test/compilable/test4375.d
+++ b/gcc/testsuite/gdc.test/compilable/test4375.d
@@ -256,7 +256,7 @@ label1:
else
assert(89);
else
- assert(12);
+ assert(12);
with (x)
@@ -299,7 +299,7 @@ label1:
if (true)
assert(110);
else
- assert(112);
+ assert(112);
finally
assert(111);
@@ -316,7 +316,7 @@ label1:
int w;
static if (true)
- int t;
+ int t;
else static if (false)
int u;
else
diff --git a/gcc/testsuite/gdc.test/compilable/test7172.d b/gcc/testsuite/gdc.test/compilable/test7172.d
index 859f29a..a4cf663 100644
--- a/gcc/testsuite/gdc.test/compilable/test7172.d
+++ b/gcc/testsuite/gdc.test/compilable/test7172.d
@@ -7,7 +7,7 @@ void main()
static assert(!__traits(compiles, { class D : FinalC{} }));
scope class ScopeC{}
-// static assert(!__traits(compiles, { auto sc = new ScopeC(); }));
+ static assert(!__traits(compiles, { auto sc = new ScopeC(); }));
static assert( __traits(compiles, { scope sc = new ScopeC(); }));
synchronized class SyncC{ void f(){} }
diff --git a/gcc/testsuite/gdc.test/compilable/test8296.d b/gcc/testsuite/gdc.test/compilable/test8296.d
index d27ba15..cd175b5 100644
--- a/gcc/testsuite/gdc.test/compilable/test8296.d
+++ b/gcc/testsuite/gdc.test/compilable/test8296.d
@@ -10,7 +10,7 @@ struct bar2
class InnerBar {
bar2 b;
-
+
this()
{
b = bar2(0);
@@ -21,7 +21,7 @@ struct bar1
{
InnerBar b;
}
-
+
class Foo
{
bar1 m_bar1;
diff --git a/gcc/testsuite/gdc.test/compilable/test8513.d b/gcc/testsuite/gdc.test/compilable/test8513.d
index bcdc657..4b5d512 100644
--- a/gcc/testsuite/gdc.test/compilable/test8513.d
+++ b/gcc/testsuite/gdc.test/compilable/test8513.d
@@ -5,25 +5,25 @@ class Bar
{
interface I_Foo { void i_inner(); }
class C_Foo { void c_inner() { } }
-
+
class Impl1 : C_Foo, I_Foo
{
override void i_inner() { }
override void c_inner() { }
}
-
+
class Impl2 : C_Foo, .I_Foo
{
override void i_outer() { }
override void c_inner() { }
}
-
+
class Impl3 : .C_Foo, I_Foo
{
override void i_inner() { }
override void c_outer() { }
}
-
+
class Impl4 : .C_Foo, .I_Foo
{
override void i_outer() { }
diff --git a/gcc/testsuite/gdc.test/compilable/testpostblit.d b/gcc/testsuite/gdc.test/compilable/testpostblit.d
index 60a0f4a..dff4bc5 100644
--- a/gcc/testsuite/gdc.test/compilable/testpostblit.d
+++ b/gcc/testsuite/gdc.test/compilable/testpostblit.d
@@ -14,4 +14,4 @@ struct Test1c
{
const Test1b b;
@disable this(this);
-}
+}
diff --git a/gcc/testsuite/gdc.test/compilable/testsctreturn.d b/gcc/testsuite/gdc.test/compilable/testsctreturn.d
index 96b82da..7826cd4 100644
--- a/gcc/testsuite/gdc.test/compilable/testsctreturn.d
+++ b/gcc/testsuite/gdc.test/compilable/testsctreturn.d
@@ -17,3 +17,19 @@ void test()
size_t* p;
const ppi = const(PackedPtrImpl!(3))(p);
}
+
+/************************************************/
+
+// issues.dlang.org/show_bug.cgi?id=22541
+
+struct S
+{
+ int i;
+ int* ptr;
+
+ int* wannabeReturnRef() scope return
+ {
+ return &i;
+ }
+}
+
diff --git a/gcc/testsuite/gdc.test/compilable/typeid_name.d b/gcc/testsuite/gdc.test/compilable/typeid_name.d
index e77d5c8..b2292bf 100644
--- a/gcc/testsuite/gdc.test/compilable/typeid_name.d
+++ b/gcc/testsuite/gdc.test/compilable/typeid_name.d
@@ -9,6 +9,6 @@ class Panzer {}
class Tiger : Panzer {}
static assert (() {
- Panzer p = new Tiger(); return classname(p);
+ Panzer p = new Tiger(); return classname(p);
} () == "Tiger");
diff --git a/gcc/testsuite/gdc.test/compilable/vgc1.d b/gcc/testsuite/gdc.test/compilable/vgc1.d
index 8a11657..8bfe1d0 100644
--- a/gcc/testsuite/gdc.test/compilable/vgc1.d
+++ b/gcc/testsuite/gdc.test/compilable/vgc1.d
@@ -65,20 +65,9 @@ void testNewScope()
/***************** DeleteExp *******************/
-/*
-TEST_OUTPUT:
----
-compilable/vgc1.d(81): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-compilable/vgc1.d(81): vgc: `delete` requires the GC
-compilable/vgc1.d(82): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-compilable/vgc1.d(82): vgc: `delete` requires the GC
-compilable/vgc1.d(83): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-compilable/vgc1.d(83): vgc: `delete` requires the GC
----
-*/
void testDelete(int* p, Object o, S1* s)
{
- delete p;
- delete o;
- delete s;
+ destroy(p);
+ destroy(o);
+ destroy(s);
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b20011.d b/gcc/testsuite/gdc.test/fail_compilation/b20011.d
index 669dd10..7baad47 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/b20011.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/b20011.d
@@ -37,4 +37,4 @@ void main()
assignableByRef(s1.member);
assignableByOut(s1.member);
assignableByConstRef(s1.member);
-}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b3841.d b/gcc/testsuite/gdc.test/fail_compilation/b3841.d
index ceddc87..0dda8bd 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/b3841.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/b3841.d
@@ -47,7 +47,7 @@ void main()
f!(op, long, short)();
f!(op, float, long)();
f!(op, double, float)();
-
+
// Should that really be OK ?
f!(op, short, int)();
f!(op, float, double)();
diff --git a/gcc/testsuite/gdc.test/fail_compilation/bug16165.d b/gcc/testsuite/gdc.test/fail_compilation/bug16165.d
index 1818e0d..ca98797 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/bug16165.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/bug16165.d
@@ -7,7 +7,7 @@ void g()
f(5, 6, 404);
}
-/*
+/*
TEST_OUTPUT:
---
fail_compilation/bug16165.d(6): Error: function `bug16165.f(int x, Object y)` is not callable using argument types `(Object, Object, int)`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/bug8150a.d b/gcc/testsuite/gdc.test/fail_compilation/bug8150a.d
index a03f850..fab12c2 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/bug8150a.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/bug8150a.d
@@ -3,7 +3,7 @@
TEST_OUTPUT:
---
fail_compilation/bug8150a.d(14): Error: `object.Exception` is thrown but not caught
-fail_compilation/bug8150a.d(12): Error: `nothrow` constructor `bug8150a.Foo.this` may throw
+fail_compilation/bug8150a.d(12): Error: constructor `bug8150a.Foo.this` may throw but is marked as `nothrow`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/bug8150b.d b/gcc/testsuite/gdc.test/fail_compilation/bug8150b.d
index 2091bc8..606b628 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/bug8150b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/bug8150b.d
@@ -3,7 +3,7 @@
TEST_OUTPUT:
---
fail_compilation/bug8150b.d(15): Error: `object.Exception` is thrown but not caught
-fail_compilation/bug8150b.d(13): Error: `nothrow` constructor `bug8150b.Foo.__ctor!().this` may throw
+fail_compilation/bug8150b.d(13): Error: constructor `bug8150b.Foo.__ctor!().this` may throw but is marked as `nothrow`
fail_compilation/bug8150b.d(20): Error: template instance `bug8150b.Foo.__ctor!()` error instantiating
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ccast.d b/gcc/testsuite/gdc.test/fail_compilation/ccast.d
index b4897d4..dab2984 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ccast.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ccast.d
@@ -1,4 +1,4 @@
-/*
+/*
TEST_OUTPUT:
---
fail_compilation/ccast.d(9): Error: C style cast illegal, use `cast(byte)i`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ctfe14731.d b/gcc/testsuite/gdc.test/fail_compilation/ctfe14731.d
index 78e0891..0f12d99 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ctfe14731.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ctfe14731.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/ctfe14731.d(16): Error: cannot implicitly convert expression `["a b"]` of type `string[]` to `string`
+fail_compilation/ctfe14731.d(16): Error: cannot implicitly convert expression `split("a b")` of type `string[]` to `string`
fail_compilation/ctfe14731.d(17): Error: cannot implicitly convert expression `split("a b")` of type `string[]` to `string`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10319.d b/gcc/testsuite/gdc.test/fail_compilation/diag10319.d
index 4a01c54..416d563 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag10319.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag10319.d
@@ -9,7 +9,7 @@ fail_compilation/diag10319.d(28): Error: `@safe` function `D main` cannot call `
fail_compilation/diag10319.d(18): `diag10319.bar!int.bar` is declared here
fail_compilation/diag10319.d(27): Error: function `diag10319.foo` is not `nothrow`
fail_compilation/diag10319.d(28): Error: function `diag10319.bar!int.bar` is not `nothrow`
-fail_compilation/diag10319.d(25): Error: `nothrow` function `D main` may throw
+fail_compilation/diag10319.d(25): Error: function `D main` may throw but is marked as `nothrow`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10805.d b/gcc/testsuite/gdc.test/fail_compilation/diag10805.d
index 3b5df6e..ed38167 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag10805.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag10805.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/diag10805.d(12): Error: delimited string must end in FOO"
+fail_compilation/diag10805.d(12): Error: delimited string must end in `FOO"`
fail_compilation/diag10805.d(14): Error: unterminated string constant starting at fail_compilation/diag10805.d(14)
fail_compilation/diag10805.d(14): Error: Implicit string concatenation is error-prone and disallowed in D
fail_compilation/diag10805.d(14): Use the explicit syntax instead (concatenating literals is `@nogc`): "" ~ ""
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag13281.d b/gcc/testsuite/gdc.test/fail_compilation/diag13281.d
index c59b300..fc0d9f5 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag13281.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag13281.d
@@ -11,9 +11,9 @@ fail_compilation/diag13281.d(26): Error: cannot implicitly convert expression `1
fail_compilation/diag13281.d(27): Error: cannot implicitly convert expression `123.4i` of type `idouble` to `int`
fail_compilation/diag13281.d(28): Error: cannot implicitly convert expression `123.4Fi` of type `ifloat` to `int`
fail_compilation/diag13281.d(29): Error: cannot implicitly convert expression `123.4Li` of type `ireal` to `int`
-fail_compilation/diag13281.d(30): Error: cannot implicitly convert expression `(123.4+5.6i)` of type `cdouble` to `int`
-fail_compilation/diag13281.d(31): Error: cannot implicitly convert expression `(123.4F+5.6Fi)` of type `cfloat` to `int`
-fail_compilation/diag13281.d(32): Error: cannot implicitly convert expression `(123.4L+5.6Li)` of type `creal` to `int`
+fail_compilation/diag13281.d(30): Error: cannot implicitly convert expression `123.4 + 5.6i` of type `cdouble` to `int`
+fail_compilation/diag13281.d(31): Error: cannot implicitly convert expression `123.4F + 5.6Fi` of type `cfloat` to `int`
+fail_compilation/diag13281.d(32): Error: cannot implicitly convert expression `123.4L + 5.6Li` of type `creal` to `int`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag15713.d b/gcc/testsuite/gdc.test/fail_compilation/diag15713.d
index 34fc645..1c61408 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag15713.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag15713.d
@@ -2,8 +2,8 @@
TEST_OUTPUT:
---
fail_compilation/diag15713.d(19): Error: no property `widthSign` for type `diag15713.WrData.Data`
-fail_compilation/diag15713.d(39): Error: template instance `diag15713.conwritefImpl!("parse-int", "width", "\x0a", Data(null))` error instantiating
-fail_compilation/diag15713.d(44): instantiated from here: `conwritefImpl!("main", "\x0a", Data(null))`
+fail_compilation/diag15713.d(39): Error: template instance `diag15713.conwritefImpl!("parse-int", "width", "\n", Data(null))` error instantiating
+fail_compilation/diag15713.d(44): instantiated from here: `conwritefImpl!("main", "\n", Data(null))`
fail_compilation/diag15713.d(49): instantiated from here: `fdwritef!()`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag16977.d b/gcc/testsuite/gdc.test/fail_compilation/diag16977.d
index 9d8dcfd..73d6285 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag16977.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag16977.d
@@ -13,7 +13,7 @@ fail_compilation/diag16977.d(30): Error: template instance `diag16977.test.funcT
---
*/
-// when copying the expression of a default argument, location information is
+// when copying the expression of a default argument, location information is
// replaced by the location of the caller to improve debug information
// verify error messages are displayed for the original location only
@@ -26,7 +26,7 @@ void test()
void badOp(int x, int y = 1 ~ "string") {}
void lazyTemplate(int x, lazy int y = 4.templ) {}
void funcTemplate(T)(T y = 5) {}
-
+
funcTemplate!string();
undefinedId(1);
badOp(2);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d b/gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d
index 05c5d30..21a12ed 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/dtor_attributes.d
@@ -20,7 +20,7 @@ fail_compilation/dtor_attributes.d(118): Error: destructor `dtor_attributes.Stri
fail_compilation/dtor_attributes.d(113): generated `Strict.~this` is not nothrow because of the following field's destructors:
fail_compilation/dtor_attributes.d(111): - HasDtor member
fail_compilation/dtor_attributes.d(103): not nothrow `HasDtor.~this` is declared here
-fail_compilation/dtor_attributes.d(116): Error: `nothrow` function `dtor_attributes.test1` may throw
+fail_compilation/dtor_attributes.d(116): Error: function `dtor_attributes.test1` may throw but is marked as `nothrow`
---
*/
#line 100
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail10964.d b/gcc/testsuite/gdc.test/fail_compilation/fail10964.d
index de3673f..9f38cb0 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail10964.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail10964.d
@@ -7,7 +7,7 @@ fail_compilation/fail10964.d(30): Error: function `fail10964.S.__postblit` is no
fail_compilation/fail10964.d(33): Error: function `fail10964.S.__postblit` is not `nothrow`
fail_compilation/fail10964.d(34): Error: function `fail10964.S.__postblit` is not `nothrow`
fail_compilation/fail10964.d(35): Error: function `fail10964.S.__postblit` is not `nothrow`
-fail_compilation/fail10964.d(22): Error: `nothrow` function `fail10964.foo` may throw
+fail_compilation/fail10964.d(22): Error: function `fail10964.foo` may throw but is marked as `nothrow`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail11375.d b/gcc/testsuite/gdc.test/fail_compilation/fail11375.d
index 4f221bf..7592a5a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail11375.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail11375.d
@@ -2,7 +2,7 @@
TEST_OUTPUT:
---
fail_compilation/fail11375.d(17): Error: constructor `fail11375.D!().D.this` is not `nothrow`
-fail_compilation/fail11375.d(15): Error: `nothrow` function `D main` may throw
+fail_compilation/fail11375.d(15): Error: function `D main` may throw but is marked as `nothrow`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail11542.d b/gcc/testsuite/gdc.test/fail_compilation/fail11542.d
index 0198f64..3c2f9c1 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail11542.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail11542.d
@@ -4,9 +4,9 @@
TEST_OUTPUT:
---
fail_compilation/fail11542.d(15): Error: `object.Exception` is thrown but not caught
-fail_compilation/fail11542.d(12): Error: `nothrow` function `fail11542.test_success1` may throw
+fail_compilation/fail11542.d(12): Error: function `fail11542.test_success1` may throw but is marked as `nothrow`
fail_compilation/fail11542.d(25): Error: `object.Exception` is thrown but not caught
-fail_compilation/fail11542.d(22): Error: `nothrow` function `fail11542.test_success3` may throw
+fail_compilation/fail11542.d(22): Error: function `fail11542.test_success3` may throw but is marked as `nothrow`
---
*/
void test_success1() nothrow
@@ -29,7 +29,7 @@ void test_success3() nothrow
TEST_OUTPUT:
---
fail_compilation/fail11542.d(38): Error: `object.Exception` is thrown but not caught
-fail_compilation/fail11542.d(35): Error: `nothrow` function `fail11542.test_failure1` may throw
+fail_compilation/fail11542.d(35): Error: function `fail11542.test_failure1` may throw but is marked as `nothrow`
---
*/
void test_failure1() nothrow
@@ -52,7 +52,7 @@ void est_failure3() nothrow
TEST_OUTPUT:
---
fail_compilation/fail11542.d(61): Error: `object.Exception` is thrown but not caught
-fail_compilation/fail11542.d(58): Error: `nothrow` function `fail11542.test_exit1` may throw
+fail_compilation/fail11542.d(58): Error: function `fail11542.test_exit1` may throw but is marked as `nothrow`
---
*/
void test_exit1() nothrow
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail12809.d b/gcc/testsuite/gdc.test/fail_compilation/fail12809.d
index a5e9f72..65e89b1 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail12809.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail12809.d
@@ -6,10 +6,10 @@ bool cond;
TEST_OUTPUT:
---
fail_compilation/fail12809.d(18): Error: `object.Exception` is thrown but not caught
-fail_compilation/fail12809.d(15): Error: `nothrow` function `fail12809.test_finally1` may throw
+fail_compilation/fail12809.d(15): Error: function `fail12809.test_finally1` may throw but is marked as `nothrow`
fail_compilation/fail12809.d(34): Error: `object.Exception` is thrown but not caught
fail_compilation/fail12809.d(38): Error: `object.Exception` is thrown but not caught
-fail_compilation/fail12809.d(31): Error: `nothrow` function `fail12809.test_finally3` may throw
+fail_compilation/fail12809.d(31): Error: function `fail12809.test_finally3` may throw but is marked as `nothrow`
---
*/
void test_finally1() nothrow
@@ -44,10 +44,10 @@ void test_finally3() nothrow
TEST_OUTPUT:
---
fail_compilation/fail12809.d(58): Error: `object.Exception` is thrown but not caught
-fail_compilation/fail12809.d(53): Error: `nothrow` function `fail12809.test_finally4` may throw
+fail_compilation/fail12809.d(53): Error: function `fail12809.test_finally4` may throw but is marked as `nothrow`
fail_compilation/fail12809.d(74): Error: `object.Exception` is thrown but not caught
fail_compilation/fail12809.d(78): Error: `object.Exception` is thrown but not caught
-fail_compilation/fail12809.d(69): Error: `nothrow` function `fail12809.test_finally6` may throw
+fail_compilation/fail12809.d(69): Error: function `fail12809.test_finally6` may throw but is marked as `nothrow`
---
*/
void test_finally4() nothrow
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail14277.d b/gcc/testsuite/gdc.test/fail_compilation/fail14277.d
new file mode 100644
index 0000000..fd6e618
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail14277.d
@@ -0,0 +1,10 @@
+// https://issues.dlang.org/show_bug.cgi?id=14277
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail14277.d(10): Error: cannot implicitly convert expression `new char[](9999$?:32=u|64=LU$)` of type `char[]` to `ubyte[]`
+---
+*/
+
+ubyte[] u = new char[9999];
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail14486.d b/gcc/testsuite/gdc.test/fail_compilation/fail14486.d
index 07152f4..c7a2b89 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail14486.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail14486.d
@@ -3,39 +3,18 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail14486.d(56): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/fail14486.d(56): Error: `delete c0` is not `@safe` but is used in `@safe` function `test1a`
-fail_compilation/fail14486.d(57): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/fail14486.d(57): Error: `pure` function `fail14486.test1a` cannot call impure destructor `fail14486.C1a.~this`
-fail_compilation/fail14486.d(57): Error: `@safe` function `fail14486.test1a` cannot call `@system` destructor `fail14486.C1a.~this`
-fail_compilation/fail14486.d(43): `fail14486.C1a.~this` is declared here
-fail_compilation/fail14486.d(57): Error: `@nogc` function `fail14486.test1a` cannot call non-@nogc destructor `fail14486.C1a.~this`
-fail_compilation/fail14486.d(62): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/fail14486.d(63): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/fail14486.d(63): Error: destructor `fail14486.C1b.~this` is not `nothrow`
-fail_compilation/fail14486.d(60): Error: `nothrow` function `fail14486.test1b` may throw
-fail_compilation/fail14486.d(68): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/fail14486.d(68): Error: `delete s0` is not `@safe` but is used in `@safe` function `test2a`
-fail_compilation/fail14486.d(69): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/fail14486.d(69): Error: `pure` function `fail14486.test2a` cannot call impure destructor `fail14486.S1a.~this`
-fail_compilation/fail14486.d(69): Error: `@safe` function `fail14486.test2a` cannot call `@system` destructor `fail14486.S1a.~this`
-fail_compilation/fail14486.d(49): `fail14486.S1a.~this` is declared here
-fail_compilation/fail14486.d(69): Error: `@nogc` function `fail14486.test2a` cannot call non-@nogc destructor `fail14486.S1a.~this`
-fail_compilation/fail14486.d(74): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/fail14486.d(75): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/fail14486.d(75): Error: destructor `fail14486.S1b.~this` is not `nothrow`
-fail_compilation/fail14486.d(72): Error: `nothrow` function `fail14486.test2b` may throw
-fail_compilation/fail14486.d(80): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/fail14486.d(80): Error: `delete a0` is not `@safe` but is used in `@safe` function `test3a`
-fail_compilation/fail14486.d(81): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/fail14486.d(81): Error: `pure` function `fail14486.test3a` cannot call impure destructor `fail14486.S1a.~this`
-fail_compilation/fail14486.d(81): Error: `@safe` function `fail14486.test3a` cannot call `@system` destructor `fail14486.S1a.~this`
-fail_compilation/fail14486.d(49): `fail14486.S1a.~this` is declared here
-fail_compilation/fail14486.d(81): Error: `@nogc` function `fail14486.test3a` cannot call non-@nogc destructor `fail14486.S1a.~this`
-fail_compilation/fail14486.d(86): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/fail14486.d(87): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/fail14486.d(87): Error: destructor `fail14486.S1b.~this` is not `nothrow`
-fail_compilation/fail14486.d(84): Error: `nothrow` function `fail14486.test3b` may throw
+fail_compilation/fail14486.d(35): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
+fail_compilation/fail14486.d(36): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
+fail_compilation/fail14486.d(41): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
+fail_compilation/fail14486.d(42): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
+fail_compilation/fail14486.d(47): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
+fail_compilation/fail14486.d(48): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
+fail_compilation/fail14486.d(53): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
+fail_compilation/fail14486.d(54): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
+fail_compilation/fail14486.d(59): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
+fail_compilation/fail14486.d(60): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
+fail_compilation/fail14486.d(65): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
+fail_compilation/fail14486.d(66): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail14554.d b/gcc/testsuite/gdc.test/fail_compilation/fail14554.d
index 73b0a78..b71a68e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail14554.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail14554.d
@@ -25,6 +25,6 @@ struct issue14554_2 {
void test14554()
{
- issue14554_1.foo!bool(1);
- issue14554_2.foo!bool(1);
+ issue14554_1.foo!bool(1);
+ issue14554_2.foo!bool(1);
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail15089.d b/gcc/testsuite/gdc.test/fail_compilation/fail15089.d
index 221a978..9aa94f8 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail15089.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail15089.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail15089.d(10): Error: cannot implicitly convert expression `130` of type `int` to `byte`
+fail_compilation/fail15089.d(10): Error: cannot implicitly convert expression `2 ^ 128` of type `int` to `byte`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail160.d b/gcc/testsuite/gdc.test/fail_compilation/fail160.d
index c07c8d3..0c8a937 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail160.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail160.d
@@ -14,7 +14,7 @@ template Wrapper(B, alias Func, int func)
alias typeof(&Func) FuncPtr;
private static FuncPtr get_funcptr() { return func; }
-}
+}
int main(char[][] args)
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail17906.d b/gcc/testsuite/gdc.test/fail_compilation/fail17906.d
new file mode 100644
index 0000000..689dd48
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail17906.d
@@ -0,0 +1,12 @@
+// REQUIRED_ARGS: -de
+/* TEST_OUTPUT:
+---
+fail_compilation/fail17906.d(11): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
+---
+*/
+// https://issues.dlang.org/show_bug.cgi?id=18647
+deprecated void main ()
+{
+ Object o = new Object;
+ delete o;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail17969.d b/gcc/testsuite/gdc.test/fail_compilation/fail17969.d
index 57fabbb..e6b9556 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail17969.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail17969.d
@@ -4,7 +4,7 @@ fail_compilation/fail17969.d(9): Error: no property `sum` for type `fail17969.__
---
* https://issues.dlang.org/show_bug.cgi?id=17969
*/
-
+
alias fun = a => MapResult2!(b => b).sum;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18228.d b/gcc/testsuite/gdc.test/fail_compilation/fail18228.d
index 983719a..8da0b8d 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail18228.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail18228.d
@@ -1,9 +1,9 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail18228.d(12): Error: Using `this` as a type is obsolete. Use `typeof(this)` instead
-fail_compilation/fail18228.d(13): Error: Using `this` as a type is obsolete. Use `typeof(this)` instead
-fail_compilation/fail18228.d(14): Error: Using `super` as a type is obsolete. Use `typeof(super)` instead
+fail_compilation/fail18228.d(12): Error: undefined identifier `this`, did you mean `typeof(this)`?
+fail_compilation/fail18228.d(13): Error: undefined identifier `this`, did you mean `typeof(this)`?
+fail_compilation/fail18228.d(14): Error: undefined identifier `super`, did you mean `typeof(super)`?
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19441.d b/gcc/testsuite/gdc.test/fail_compilation/fail19441.d
index f1f1769..520eb76 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19441.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19441.d
@@ -2,7 +2,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail19441.d(44): Deprecation: Cannot use `alias this` to partially initialize variable `wrap[0]` of type `Wrap10595`. Use `wrap[0].i`
+fail_compilation/fail19441.d(44): Error: cannot use `alias this` to partially initialize variable `wrap[0]` of type `Wrap10595`. Use `wrap[0].i`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail196.d b/gcc/testsuite/gdc.test/fail_compilation/fail196.d
index c7b28cf..55c3bd8 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail196.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail196.d
@@ -1,14 +1,14 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail196.d(27): Error: delimited string must end in )"
+fail_compilation/fail196.d(27): Error: delimited string must end in `)"`
fail_compilation/fail196.d(27): Error: Implicit string concatenation is error-prone and disallowed in D
-fail_compilation/fail196.d(27): Use the explicit syntax instead (concatenating literals is `@nogc`): "foo(xxx)" ~ ";\x0a assert(s == "
+fail_compilation/fail196.d(27): Use the explicit syntax instead (concatenating literals is `@nogc`): "foo(xxx)" ~ ";\n assert(s == "
fail_compilation/fail196.d(28): Error: semicolon needed to end declaration of `s`, instead of `foo`
fail_compilation/fail196.d(27): `s` declared here
-fail_compilation/fail196.d(28): Error: found `");\x0a\x0a s = q"` when expecting `;` following statement
-fail_compilation/fail196.d(30): Error: found `";\x0a assert(s == "` when expecting `;` following statement
-fail_compilation/fail196.d(31): Error: found `");\x0a\x0a s = q"` when expecting `;` following statement
+fail_compilation/fail196.d(28): Error: found `");\n\n s = q"` when expecting `;` following statement
+fail_compilation/fail196.d(30): Error: found `";\n assert(s == "` when expecting `;` following statement
+fail_compilation/fail196.d(31): Error: found `");\n\n s = q"` when expecting `;` following statement
fail_compilation/fail196.d(33): Error: found `{` when expecting `;` following statement
fail_compilation/fail196.d(33): Error: found `}` when expecting `;` following statement
fail_compilation/fail196.d(34): Error: found `foo` when expecting `;` following statement
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19897.d b/gcc/testsuite/gdc.test/fail_compilation/fail19897.d
index 4f5804b..49df470 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19897.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19897.d
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail19897.d(9): Error: cannot implicitly convert expression `[]` of type `const(char[0])` to `const(char)`
+fail_compilation/fail19897.d(12): Error: cannot implicitly convert expression `a.x` of type `const(char[0])` to `const(char)`
---
*/
struct S
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19911b.d b/gcc/testsuite/gdc.test/fail_compilation/fail19911b.d
index c5d6a8a..9f2dbbb 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19911b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19911b.d
@@ -1,4 +1,4 @@
-/*
+/*
DFLAGS:
EXTRA_SOURCES: extra-files/minimal/object.d
TEST_OUTPUT:
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19911c.d b/gcc/testsuite/gdc.test/fail_compilation/fail19911c.d
index fbd7406..c1c6549 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19911c.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19911c.d
@@ -1,4 +1,4 @@
-/*
+/*
DFLAGS:
TEST_OUTPUT:
---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19922.d b/gcc/testsuite/gdc.test/fail_compilation/fail19922.d
index 201b124..1476666 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19922.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19922.d
@@ -1,4 +1,4 @@
-/*
+/*
DFLAGS:
TEST_OUTPUT:
---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19923.d b/gcc/testsuite/gdc.test/fail_compilation/fail19923.d
index 1438151..d98dd03 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail19923.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19923.d
@@ -1,4 +1,4 @@
-/*
+/*
DFLAGS:
TEST_OUTPUT:
---
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail20.d b/gcc/testsuite/gdc.test/fail_compilation/fail20.d
index 6cc4d22..4528d36 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail20.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail20.d
@@ -14,6 +14,6 @@ void main()
FOO one;
FOO two;
if (one < two){} // This should tell me that there
- // is no opCmp() defined instead
+ // is no opCmp() defined instead
// of crashing.
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail20800.d b/gcc/testsuite/gdc.test/fail_compilation/fail20800.d
index 1184b8e..185baec 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail20800.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail20800.d
@@ -15,7 +15,7 @@ struct RegexMatch
}
static m() { return RegexMatch(); }
-void fun(int a);
+void fun(int a);
void initCommands()
{
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22127.d b/gcc/testsuite/gdc.test/fail_compilation/fail22127.d
new file mode 100644
index 0000000..c6e3684
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22127.d
@@ -0,0 +1,11 @@
+/* TEST_OUTPUT:
+---
+fail_compilation/fail22127.d(101): Error: user-defined attributes are not allowed on `alias` declarations
+---
+ */
+
+// https://issues.dlang.org/show_bug.cgi?id=22127
+
+#line 100
+
+alias getOne = @(0) function int () => 1;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22634.d b/gcc/testsuite/gdc.test/fail_compilation/fail22634.d
new file mode 100644
index 0000000..320d1eb
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22634.d
@@ -0,0 +1,12 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail22634.d(9): Error: more than 65535 symbols with name `i` generated
+---
+*/
+void main()
+{
+ static foreach(i; 0..65537)
+ {
+ }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22780.d b/gcc/testsuite/gdc.test/fail_compilation/fail22780.d
new file mode 100644
index 0000000..dd83f75
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22780.d
@@ -0,0 +1,12 @@
+// https://issues.dlang.org/show_bug.cgi?id=22780
+/* TEST_OUTPUT:
+---
+fail_compilation/fail22780.d(11): Error: variable `fail22780.test10717.c` reference to `scope class` must be `scope`
+---
+*/
+scope class C10717 { }
+
+void test10717()
+{
+ C10717 c;
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail2361.d b/gcc/testsuite/gdc.test/fail_compilation/fail2361.d
index a969495..57edd3a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail2361.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail2361.d
@@ -1,8 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail2361.d(14): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/fail2361.d(14): Error: cannot modify `immutable` expression `c`
+fail_compilation/fail2361.d(13): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail258.d b/gcc/testsuite/gdc.test/fail_compilation/fail258.d
index 459d271..63cbfd4 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail258.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail258.d
@@ -1,13 +1,15 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail258.d(11): Error: delimiter cannot be whitespace
-fail_compilation/fail258.d(11): Error: delimited string must end in
-"
-fail_compilation/fail258.d(11): Error: declaration expected, not `"X"`
-fail_compilation/fail258.d(14): Error: unterminated string constant starting at fail_compilation/fail258.d(14)
+fail_compilation/fail258.d(101): Error: delimiter cannot be whitespace
+fail_compilation/fail258.d(101): Error: delimited string must end in `"`
+fail_compilation/fail258.d(101): Error: declaration expected, not `"X"`
+fail_compilation/fail258.d(104): Error: unterminated string constant starting at fail_compilation/fail258.d(104)
---
*/
+
+#line 100
+
q"
X
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail332.d b/gcc/testsuite/gdc.test/fail_compilation/fail332.d
index 12164b9..91f8046 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail332.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail332.d
@@ -21,7 +21,7 @@ void test()
{
foo();
foo(null);
-
+
baz("");
baz(3, null);
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail349.d b/gcc/testsuite/gdc.test/fail_compilation/fail349.d
index 11a392c..215453e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail349.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail349.d
@@ -2,7 +2,7 @@
TEST_OUTPUT:
---
fail_compilation/fail349.d(15): Error: function `fail349.bug6109throwing` is not `nothrow`
-fail_compilation/fail349.d(13): Error: `nothrow` function `fail349.bug6109noThrow` may throw
+fail_compilation/fail349.d(13): Error: function `fail349.bug6109noThrow` may throw but is marked as `nothrow`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail354.d b/gcc/testsuite/gdc.test/fail_compilation/fail354.d
index 8689f61..2795acc 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail354.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail354.d
@@ -10,4 +10,4 @@ struct S(int N)
{
this(T!N) { }
}
-alias S!1 M;
+alias S!1 M;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail4082.d b/gcc/testsuite/gdc.test/fail_compilation/fail4082.d
index 6f9ee61..a09f725 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail4082.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail4082.d
@@ -2,7 +2,7 @@
TEST_OUTPUT:
---
fail_compilation/fail4082.d(14): Error: destructor `fail4082.Foo.~this` is not `nothrow`
-fail_compilation/fail4082.d(12): Error: `nothrow` function `fail4082.test1` may throw
+fail_compilation/fail4082.d(12): Error: function `fail4082.test1` may throw but is marked as `nothrow`
---
*/
struct Foo
@@ -22,7 +22,7 @@ NEXT:
TEST_OUTPUT:
---
fail_compilation/fail4082.d(32): Error: destructor `fail4082.Bar.~this` is not `nothrow`
-fail_compilation/fail4082.d(32): Error: `nothrow` function `fail4082.test2` may throw
+fail_compilation/fail4082.d(32): Error: function `fail4082.test2` may throw but is marked as `nothrow`
---
*/
struct Bar
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail4269a.d b/gcc/testsuite/gdc.test/fail_compilation/fail4269a.d
index 6604f1f..69b142e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail4269a.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail4269a.d
@@ -10,6 +10,6 @@ enum bool WWW = is(typeof(A.x));
interface A {
B blah;
- void foo(B b){}
+ void foo(B b){}
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail4269b.d b/gcc/testsuite/gdc.test/fail_compilation/fail4269b.d
index 2530133..e0ebd2f 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail4269b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail4269b.d
@@ -9,6 +9,6 @@ enum bool WWW = is(typeof(A.x));
struct A {
B blah;
- void foo(B b){}
+ void foo(B b){}
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail4269c.d b/gcc/testsuite/gdc.test/fail_compilation/fail4269c.d
index 8bbfaac..5bba42e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail4269c.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail4269c.d
@@ -9,6 +9,6 @@ enum bool WWW = is(typeof(A.x));
class A {
B blah;
- void foo(B b){}
+ void foo(B b){}
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail4375d.d b/gcc/testsuite/gdc.test/fail_compilation/fail4375d.d
index 7592779..9c6aaed 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail4375d.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail4375d.d
@@ -14,7 +14,7 @@ void main() {
label2:
if (true)
assert(15);
- else
+ else
assert(16);
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail6968.d b/gcc/testsuite/gdc.test/fail_compilation/fail6968.d
index b56a5db..aca90c6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail6968.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail6968.d
@@ -29,4 +29,4 @@ template PredAny(A, B...)
void main()
{
pragma(msg, PredAny!(int, long, float));
-}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7848.d b/gcc/testsuite/gdc.test/fail_compilation/fail7848.d
index 4fc269e..e8371c4 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail7848.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail7848.d
@@ -8,13 +8,13 @@ fail_compilation/fail7848.d(27): Error: `@safe` function `fail7848.C.__unittest_
fail_compilation/fail7848.d(21): `fail7848.func` is declared here
fail_compilation/fail7848.d(27): Error: `@nogc` function `fail7848.C.__unittest_L25_C30` cannot call non-@nogc function `fail7848.func`
fail_compilation/fail7848.d(27): Error: function `fail7848.func` is not `nothrow`
-fail_compilation/fail7848.d(25): Error: `nothrow` function `fail7848.C.__unittest_L25_C30` may throw
+fail_compilation/fail7848.d(25): Error: function `fail7848.C.__unittest_L25_C30` may throw but is marked as `nothrow`
fail_compilation/fail7848.d(32): Error: `pure` function `fail7848.C.__invariant1` cannot call impure function `fail7848.func`
fail_compilation/fail7848.d(32): Error: `@safe` function `fail7848.C.__invariant1` cannot call `@system` function `fail7848.func`
fail_compilation/fail7848.d(21): `fail7848.func` is declared here
fail_compilation/fail7848.d(32): Error: `@nogc` function `fail7848.C.__invariant1` cannot call non-@nogc function `fail7848.func`
fail_compilation/fail7848.d(32): Error: function `fail7848.func` is not `nothrow`
-fail_compilation/fail7848.d(30): Error: `nothrow` function `fail7848.C.__invariant1` may throw
+fail_compilation/fail7848.d(30): Error: function `fail7848.C.__invariant1` may throw but is marked as `nothrow`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail80_m32.d b/gcc/testsuite/gdc.test/fail_compilation/fail80_m32.d
index 11facfd..a378fbb 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail80_m32.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail80_m32.d
@@ -23,7 +23,7 @@ class Test
static Image[] images;
- static void initIcons()
+ static void initIcons()
{
images["progress_rem"] = ResourceManager.getImage("progress_rem.gif"); // delete_obj_dis
images["redo"] = ResourceManager.getImage("redo.gif");
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail80_m64.d b/gcc/testsuite/gdc.test/fail_compilation/fail80_m64.d
index 59c890e..e0cc871 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail80_m64.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail80_m64.d
@@ -23,7 +23,7 @@ class Test
static Image[] images;
- static void initIcons()
+ static void initIcons()
{
images["progress_rem"] = ResourceManager.getImage("progress_rem.gif"); // delete_obj_dis
images["redo"] = ResourceManager.getImage("redo.gif");
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail8724.d b/gcc/testsuite/gdc.test/fail_compilation/fail8724.d
index c5ca98b..92d313a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail8724.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail8724.d
@@ -3,7 +3,7 @@
TEST_OUTPUT:
---
fail_compilation/fail8724.d(14): Error: `object.Exception` is thrown but not caught
-fail_compilation/fail8724.d(12): Error: `nothrow` constructor `fail8724.Foo.this` may throw
+fail_compilation/fail8724.d(12): Error: constructor `fail8724.Foo.this` may throw but is marked as `nothrow`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d b/gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d
index ed228a9..7087b0c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d
@@ -209,8 +209,7 @@ fail_compilation/fail_arrayop2.d(269): Error: array operation `"abc"[] + '\x01'`
fail_compilation/fail_arrayop2.d(272): Error: array operation `[1] * 6` without destination memory not allowed
fail_compilation/fail_arrayop2.d(275): Error: `([1] * 6)[0..2]` is not an lvalue and cannot be modified
fail_compilation/fail_arrayop2.d(278): Error: can only `*` a pointer, not a `int[]`
-fail_compilation/fail_arrayop2.d(281): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/fail_arrayop2.d(281): Error: `[1] * 6` is not an lvalue and cannot be modified
+fail_compilation/fail_arrayop2.d(281): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
fail_compilation/fail_arrayop2.d(284): Error: array operation `da[] * 6` without destination memory not allowed
fail_compilation/fail_arrayop2.d(287): Error: array operation `da[] * 6` without destination memory not allowed
fail_compilation/fail_arrayop2.d(290): Error: `[1] * 6` is not an lvalue and cannot be modified
@@ -235,6 +234,7 @@ fail_compilation/fail_arrayop2.d(321): Error: array operation `[1] * 6` without
fail_compilation/fail_arrayop2.d(321): Error: array operation `[1] * 6` without destination memory not allowed
---
*/
+
// Test all expressions, which can take arrays as their operands but cannot be a part of array operation.
void test15407exp()
{
@@ -252,7 +252,7 @@ void test15407exp()
// StructLiteralExp.elements <- preFunctionParameters in CallExp
{ auto r = S([1] * 6); }
- // NewExp.newargs/arguments <- preFunctionParameters
+ // NewExp.arguments <- preFunctionParameters
{ auto r = new S([1] * 6); }
// TODO: TypeidExp
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_typeof.d b/gcc/testsuite/gdc.test/fail_compilation/fail_typeof.d
new file mode 100644
index 0000000..392cebd
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail_typeof.d
@@ -0,0 +1,82 @@
+/* TEST_OUTPUT:
+---
+fail_compilation/fail_typeof.d(18): Error: undefined identifier `this`
+fail_compilation/fail_typeof.d(23): Error: `this` is not in a class or struct scope
+fail_compilation/fail_typeof.d(23): Error: `this` is only defined in non-static member functions, not `fail_typeof`
+fail_compilation/fail_typeof.d(28): Error: undefined identifier `super`
+fail_compilation/fail_typeof.d(33): Error: `super` is not in a class scope
+fail_compilation/fail_typeof.d(33): Error: `super` is only allowed in non-static class member functions
+fail_compilation/fail_typeof.d(40): Error: undefined identifier `this`, did you mean `typeof(this)`?
+fail_compilation/fail_typeof.d(50): Error: undefined identifier `super`
+fail_compilation/fail_typeof.d(55): Error: `super` is not in a class scope
+fail_compilation/fail_typeof.d(55): Error: `super` is only allowed in non-static class member functions
+fail_compilation/fail_typeof.d(63): Error: undefined identifier `this`, did you mean `typeof(this)`?
+fail_compilation/fail_typeof.d(73): Error: undefined identifier `super`, did you mean `typeof(super)`?
+---
+*/
+
+enum E1 : this
+{
+ fail,
+}
+
+enum E2 : typeof(this)
+{
+ fail,
+}
+
+enum E3 : super
+{
+ fail,
+}
+
+enum E4 : typeof(super)
+{
+ fail,
+}
+
+struct S1
+{
+ enum E1 : this
+ {
+ fail,
+ }
+
+ enum E2 : typeof(this)
+ {
+ ok = S1(),
+ }
+
+ enum E3 : super
+ {
+ fail,
+ }
+
+ enum E4 : typeof(super)
+ {
+ fail,
+ }
+}
+
+class C1
+{
+ enum E1 : this
+ {
+ fail,
+ }
+
+ enum E2 : typeof(this)
+ {
+ ok = new C1,
+ }
+
+ enum E3 : super
+ {
+ fail,
+ }
+
+ enum E4 : typeof(super)
+ {
+ ok = new C1,
+ }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/faildeleteaa.d b/gcc/testsuite/gdc.test/fail_compilation/faildeleteaa.d
index 95663ea..0a29997 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/faildeleteaa.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/faildeleteaa.d
@@ -1,8 +1,7 @@
/*
TEST_OUTPUT:
---
-fail_compilation/faildeleteaa.d(12): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/faildeleteaa.d(12): Error: cannot delete type `int`
+fail_compilation/faildeleteaa.d(11): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10727a.d b/gcc/testsuite/gdc.test/fail_compilation/ice10727a.d
index ebefe33..6d3b223 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice10727a.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice10727a.d
@@ -4,6 +4,8 @@
TEST_OUTPUT:
---
fail_compilation/imports/foo10727a.d(34): Error: undefined identifier `Frop`
+fail_compilation/imports/foo10727a.d(26): Error: template instance `foo10727a.CirBuff!(Foo)` error instantiating
+fail_compilation/imports/foo10727a.d(31): instantiated from here: `Bar!(Foo)`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10727b.d b/gcc/testsuite/gdc.test/fail_compilation/ice10727b.d
index 125ac12..4a59d5c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice10727b.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice10727b.d
@@ -4,6 +4,8 @@
TEST_OUTPUT:
---
fail_compilation/imports/foo10727b.d(25): Error: undefined identifier `Frop`
+fail_compilation/imports/foo10727b.d(17): Error: template instance `foo10727b.CirBuff!(Foo)` error instantiating
+fail_compilation/imports/foo10727b.d(22): instantiated from here: `Bar!(Foo)`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11968.d b/gcc/testsuite/gdc.test/fail_compilation/ice11968.d
index 651f162..ea44eae 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice11968.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice11968.d
@@ -1,8 +1,7 @@
/*
TEST_OUTPUT:
----
-fail_compilation/ice11968.d(9): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/ice11968.d(9): Error: cannot modify string literal `"fail_compilation$?:windows=\\|/$ice11968.d"`
+fail_compilation/ice11968.d(8): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
----
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice18753.d b/gcc/testsuite/gdc.test/fail_compilation/ice18753.d
index 300eab2..253025cd 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice18753.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice18753.d
@@ -14,7 +14,7 @@ struct ChunkByImpl
{
struct Group
{ }
-
+
static assert(isForwardRange!Group);
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/lexer1.d b/gcc/testsuite/gdc.test/fail_compilation/lexer1.d
index 088e897..6569d4c 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/lexer1.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/lexer1.d
@@ -10,10 +10,10 @@ fail_compilation/lexer1.d(34): Error: declaration expected, not `0.1L`
fail_compilation/lexer1.d(35): Error: declaration expected, not `0.1i`
fail_compilation/lexer1.d(36): Error: declaration expected, not `0.1fi`
fail_compilation/lexer1.d(37): Error: declaration expected, not `0.1Li`
-fail_compilation/lexer1.d(38): Error: declaration expected, not `32U`
+fail_compilation/lexer1.d(38): Error: declaration expected, not `' '`
fail_compilation/lexer1.d(39): Error: declaration expected, not `55295U`
fail_compilation/lexer1.d(40): Error: declaration expected, not `65536U`
-fail_compilation/lexer1.d(41): Error: declaration expected, not `"ab\\c\"\u1234a\U00011100a"d`
+fail_compilation/lexer1.d(41): Error: declaration expected, not `"ab\\c\"\u1234a\U00011100a\0ab"d`
fail_compilation/lexer1.d(43): Error: declaration expected, not `module`
fail_compilation/lexer1.d(45): Error: escape hex sequence has 1 hex digits instead of 2
fail_compilation/lexer1.d(46): Error: undefined escape hex sequence \xG
diff --git a/gcc/testsuite/gdc.test/fail_compilation/no_Throwable.d b/gcc/testsuite/gdc.test/fail_compilation/no_Throwable.d
index 29481e3..5a8af97 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/no_Throwable.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/no_Throwable.d
@@ -1,4 +1,4 @@
-/*
+/*
DFLAGS:
REQUIRED_ARGS: -c
EXTRA_SOURCES: extra-files/minimal/object.d
diff --git a/gcc/testsuite/gdc.test/fail_compilation/no_TypeInfo.d b/gcc/testsuite/gdc.test/fail_compilation/no_TypeInfo.d
index 328f9b9..a55332a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/no_TypeInfo.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/no_TypeInfo.d
@@ -1,4 +1,4 @@
-/*
+/*
DFLAGS:
REQUIRED_ARGS: -c
EXTRA_SOURCES: extra-files/minimal/object.d
diff --git a/gcc/testsuite/gdc.test/fail_compilation/nogc1.d b/gcc/testsuite/gdc.test/fail_compilation/nogc1.d
index a862e52..8f18ec5 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/nogc1.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/nogc1.d
@@ -63,12 +63,9 @@ fail_compilation/nogc1.d(55): Error: cannot use `new` in `@nogc` function `nogc1
/*
TEST_OUTPUT:
---
-fail_compilation/nogc1.d(76): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/nogc1.d(76): Error: cannot use `delete` in `@nogc` function `nogc1.testDelete`
-fail_compilation/nogc1.d(77): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/nogc1.d(77): Error: cannot use `delete` in `@nogc` function `nogc1.testDelete`
-fail_compilation/nogc1.d(78): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/nogc1.d(78): Error: cannot use `delete` in `@nogc` function `nogc1.testDelete`
+fail_compilation/nogc1.d(73): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
+fail_compilation/nogc1.d(74): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
+fail_compilation/nogc1.d(75): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
---
*/
@nogc void testDelete(int* p, Object o, S1* s)
diff --git a/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d b/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d
index 2d27d6d..7bb2fa9 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d
@@ -93,7 +93,7 @@ auto returnVoid3(int i)
TEST_OUTPUT:
---
fail_compilation/noreturn2.d(104): Error: `object.Exception` is thrown but not caught
-fail_compilation/noreturn2.d(100): Error: `nothrow` function `noreturn2.doesNestedThrow` may throw
+fail_compilation/noreturn2.d(100): Error: function `noreturn2.doesNestedThrow` may throw but is marked as `nothrow`
---
+/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/scope_type.d b/gcc/testsuite/gdc.test/fail_compilation/scope_type.d
index b087411..1e152f5 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/scope_type.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/scope_type.d
@@ -2,7 +2,7 @@
REQUIRED_ARGS: -de
TEST_OUTPUT:
---
-fail_compilation/scope_type.d(11): Deprecation: `scope` as a type constraint is deprecated. Use `scope` at the usage site.
+fail_compilation/scope_type.d(11): Error: `scope` as a type constraint is obsolete. Use `scope` at the usage site.
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test12228.d b/gcc/testsuite/gdc.test/fail_compilation/test12228.d
index 522bceb..a62eb86 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test12228.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test12228.d
@@ -1,10 +1,10 @@
/*
TEST_OUTPUT:
---
-fail_compilation/test12228.d(13): Error: Using `this` as a type is obsolete. Use `typeof(this)` instead
+fail_compilation/test12228.d(13): Error: undefined identifier `this`, did you mean `typeof(this)`?
fail_compilation/test12228.d(18): Error: no property `x` for type `object.Object`
-fail_compilation/test12228.d(19): Error: Using `super` as a type is obsolete. Use `typeof(super)` instead
-fail_compilation/test12228.d(20): Error: Using `super` as a type is obsolete. Use `typeof(super)` instead
+fail_compilation/test12228.d(19): Error: undefined identifier `super`, did you mean `typeof(super)`?
+fail_compilation/test12228.d(20): Error: undefined identifier `super`, did you mean `typeof(super)`?
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16195.d b/gcc/testsuite/gdc.test/fail_compilation/test16195.d
index a315f33..6d6c51e 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test16195.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test16195.d
@@ -1,8 +1,7 @@
/*
* TEST_OUTPUT:
---
-fail_compilation/test16195.d(14): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-fail_compilation/test16195.d(14): Error: `delete p` is not `@safe` but is used in `@safe` function `test`
+fail_compilation/test16195.d(13): Error: The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test17307.d b/gcc/testsuite/gdc.test/fail_compilation/test17307.d
index 470cfed..e73cca6 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test17307.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test17307.d
@@ -1,4 +1,4 @@
-/*
+/*
TEST_OUTPUT:
---
fail_compilation/test17307.d(9): Error: anonymous struct can only be a part of an aggregate, not module `test17307`
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20245.d b/gcc/testsuite/gdc.test/fail_compilation/test20245.d
index 24a6f99..74c5384 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test20245.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test20245.d
@@ -2,15 +2,23 @@
REQUIRED_ARGS: -preview=dip1000
TEST_OUTPUT:
---
-fail_compilation/test20245.d(14): Error: scope variable `a` may not be returned
-fail_compilation/test20245.d(18): Error: cannot take address of `scope` parameter `x` in `@safe` function `foo`
-fail_compilation/test20245.d(33): Error: reference to local variable `price` assigned to non-scope `this.minPrice`
+fail_compilation/test20245.d(20): Error: reference to local variable `x` assigned to non-scope parameter `ptr` calling test20245.escape
+fail_compilation/test20245.d(21): Error: copying `&x` into allocated memory escapes a reference to parameter variable `x`
+fail_compilation/test20245.d(22): Error: scope variable `a` may not be returned
+fail_compilation/test20245.d(26): Error: cannot take address of `scope` parameter `x` in `@safe` function `foo`
+fail_compilation/test20245.d(32): Error: reference to local variable `x` assigned to non-scope parameter `ptr` calling test20245.escape
+fail_compilation/test20245.d(33): Error: copying `&x` into allocated memory escapes a reference to parameter variable `x`
+fail_compilation/test20245.d(49): Error: reference to local variable `price` assigned to non-scope `this.minPrice`
+fail_compilation/test20245.d(68): Error: reference to local variable `this` assigned to non-scope parameter `msg` calling object.Exception.this
+fail_compilation/test20245.d(88): Error: reference to local variable `this` assigned to non-scope parameter `content` calling test20245.listUp
---
*/
// https://issues.dlang.org/show_bug.cgi?id=20245
@safe int* foo(ref int x) {
int* a = &x;
+ escape(&x);
+ auto b = [&x];
return a;
}
@@ -21,9 +29,17 @@ fail_compilation/test20245.d(33): Error: reference to local variable `price` ass
@safe int* foo(return ref int x) {
int* a = &x;
+ escape(&x);
+ auto b = [&x];
return a;
}
+int* gPtr;
+@safe void escape(int* ptr)
+{
+ gPtr = ptr;
+}
+
// https://issues.dlang.org/show_bug.cgi?id=21212
class MinPointerRecorder
{
@@ -41,3 +57,34 @@ void main() @safe
() { ulong[1000] stomp = 13; } ();
auto x = *r.minPrice; // "13"
}
+
+// https://issues.dlang.org/show_bug.cgi?id=22782
+struct DontDoThis
+{
+ immutable char[12] content;
+ @safe this(char ch)
+ {
+ content[] = ch;
+ throw new Exception(content[]);
+ }
+}
+
+void main1() @safe
+{
+ DontDoThis('a');
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=22783
+const(char)* charPtr;
+
+// argument is not, or should not be scope
+auto listUp(const(char)* content) {charPtr = content;}
+
+struct DontDoThis2
+{
+ char content;
+ @safe escape()
+ {
+ listUp(&content);
+ }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22145.d b/gcc/testsuite/gdc.test/fail_compilation/test22145.d
new file mode 100644
index 0000000..3e9f747
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test22145.d
@@ -0,0 +1,28 @@
+/* TEST_OUTPUT:
+---
+fail_compilation/test22145.d(115): Error: scope variable `x` assigned to non-scope `global`
+---
+ */
+
+// issues.dlang.org/show_bug.cgi?id=22145
+
+#line 100
+
+struct S
+{
+ int opApply (scope int delegate (scope int* ptr) @safe dg) @safe
+ {
+ return 0;
+ }
+}
+
+void test() @safe
+{
+ static int* global;
+ S s;
+ foreach (scope int* x; s)
+ {
+ global = x;
+ }
+}
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22686.d b/gcc/testsuite/gdc.test/fail_compilation/test22686.d
new file mode 100644
index 0000000..ee500bc
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/test22686.d
@@ -0,0 +1,21 @@
+// https://issues.dlang.org/show_bug.cgi?id=22686
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test22686.d(15): Error: `this` is only defined in non-static member functions, not `create`
+---
+*/
+
+struct S
+{
+ int[] data;
+ static auto create()
+ {
+ auto self = &this;
+ return {
+ assert(data.length);
+ return self;
+ };
+ }
+}
diff --git a/gcc/testsuite/gdc.test/runnable/b18034.d b/gcc/testsuite/gdc.test/runnable/b18034.d
index 3981aaf..f4b825f 100644
--- a/gcc/testsuite/gdc.test/runnable/b18034.d
+++ b/gcc/testsuite/gdc.test/runnable/b18034.d
@@ -3,22 +3,22 @@ import core.simd;
static if (__traits(compiles, { void16 a; ushort8 b; }))
{
- void check(void16 a)
+ void check(void16 a)
{
- foreach (x; (cast(ushort8)a).array)
+ foreach (x; (cast(ushort8)a).array)
{
assert(x == 1);
}
}
- void make(ushort x)
+ void make(ushort x)
{
ushort8 v = ushort8(x);
check(v);
}
- void main()
- {
+ void main()
+ {
make(1);
}
}
diff --git a/gcc/testsuite/gdc.test/runnable/imports/a15079.d b/gcc/testsuite/gdc.test/runnable/imports/a15079.d
index f8e3a82..82682f7 100644
--- a/gcc/testsuite/gdc.test/runnable/imports/a15079.d
+++ b/gcc/testsuite/gdc.test/runnable/imports/a15079.d
@@ -41,7 +41,7 @@ void destroy(T)(ref T obj) if (is(T == struct))
_destructRecurse(obj);
() @trusted {
auto buf = (cast(ubyte*) &obj)[0 .. T.sizeof];
- auto init = cast(ubyte[])typeid(T).init();
+ const init = cast(ubyte[]) __traits(initSymbol, T);
if (init.ptr is null) // null ptr means initialize to 0s
buf[] = 0;
else
diff --git a/gcc/testsuite/gdc.test/runnable/imports/a19a.d b/gcc/testsuite/gdc.test/runnable/imports/a19a.d
index 534ce9b..f3910cb 100644
--- a/gcc/testsuite/gdc.test/runnable/imports/a19a.d
+++ b/gcc/testsuite/gdc.test/runnable/imports/a19a.d
@@ -11,5 +11,5 @@ struct TemplatedStruct(Param)
void foo()
{
- alias TemplatedStruct!(Dummy) X;
+ alias TemplatedStruct!(Dummy) X;
}
diff --git a/gcc/testsuite/gdc.test/runnable/imports/link12144a.d b/gcc/testsuite/gdc.test/runnable/imports/link12144a.d
index f4fc8eb..677282e 100644
--- a/gcc/testsuite/gdc.test/runnable/imports/link12144a.d
+++ b/gcc/testsuite/gdc.test/runnable/imports/link12144a.d
@@ -28,7 +28,7 @@ void fun()()
{ alias P = S3*; auto p = new P; }
{ S4[int] aa; auto b = (aa == aa); }
{ S5[] a; a.length = 10; }
- { S6[] a; delete a; }
+ { S6[] a; destroy(a); }
{ S7[] a = []; }
{ S8[] a = [S8.init]; }
{ S9[int] aa = [1:S9.init]; }
diff --git a/gcc/testsuite/gdc.test/runnable/imports/test11745b.d b/gcc/testsuite/gdc.test/runnable/imports/test11745b.d
index c4e95e2..abe4aee 100644
--- a/gcc/testsuite/gdc.test/runnable/imports/test11745b.d
+++ b/gcc/testsuite/gdc.test/runnable/imports/test11745b.d
@@ -1,17 +1,17 @@
module imports.test11745b;
-unittest
+unittest
{
-
+
}
-private unittest
+private unittest
{
-
+
}
private:
-unittest
+unittest
{
-
+
}
diff --git a/gcc/testsuite/gdc.test/runnable/imports/test46c.d b/gcc/testsuite/gdc.test/runnable/imports/test46c.d
index c0f3e9f..d5cc142f 100644
--- a/gcc/testsuite/gdc.test/runnable/imports/test46c.d
+++ b/gcc/testsuite/gdc.test/runnable/imports/test46c.d
@@ -3,5 +3,5 @@ module imports.test46c;
class C(T)
{
void foo() { }
-}
+}
diff --git a/gcc/testsuite/gdc.test/runnable/inline7625.d b/gcc/testsuite/gdc.test/runnable/inline7625.d
new file mode 100644
index 0000000..eca5727
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/inline7625.d
@@ -0,0 +1,185 @@
+// REQUIRED_ARGS: -inline
+
+/***************************************************/
+
+pragma(inline, true)
+{
+ int foo1(int v)
+ {
+ return bar1(2 * v);
+ }
+
+ int bar1(int a)
+ {
+ if (a > 0)
+ return 1;
+ else
+ return baz1(a);
+ }
+}
+
+int baz1(int a)
+{
+ if (a > 0)
+ throw new Exception("a > 0");
+ return a - 1;
+}
+
+// ---
+
+pragma(inline, true)
+{
+ int foo2(int v)
+ {
+ return bar2(2 * v);
+ }
+
+ int bar2(int a)
+ {
+ if (a > 0)
+ return 1;
+ // else
+ return baz2(a);
+ }
+}
+
+int baz2(int a)
+{
+ if (a > 0)
+ throw new Exception("a > 0");
+ return a - 1;
+}
+
+// ---
+
+pragma(inline, true)
+{
+ int foo3(int v)
+ {
+ return bar3(2 * v);
+ }
+
+ int bar3(int a)
+ {
+ if (a > 0)
+ a = 1;
+ else
+ return baz3(a);
+ return a;
+ }
+}
+
+int baz3(int a)
+{
+ if (a > 0)
+ throw new Exception("a > 0");
+ return a - 1;
+}
+
+void test7625a()
+{
+ assert(foo1(1) == 1);
+ assert(foo1(0) == -1);
+ assert(foo2(1) == 1);
+ assert(foo2(0) == -1);
+ assert(foo3(1) == 1);
+ assert(foo3(0) == -1);
+}
+
+/***************************************************/
+
+@safe pragma(inline, true)
+{
+ int tembo(int x, int y)
+ {
+ if (y == 0)
+ return 0;
+ x++;
+ return x / y;
+ }
+ int pembo(int x, int y)
+ {
+ if (y == 0)
+ return 0;
+ else
+ {
+ x++;
+ return x / y;
+ }
+ }
+
+ int twiga(int x, int y, int z)
+ {
+ auto w = tembo(x, y);
+ return w * z;
+ }
+
+ int simba(int x, int y, int z)
+ {
+ auto w = pembo(x, y);
+ return w * z;
+ }
+}
+
+void test7625b()
+{
+ assert(twiga(5, 3, 4) == 8);
+ assert(twiga(5, 0, 4) == 0);
+
+ assert(simba(5, 3, 4) == 8);
+ assert(simba(5, 0, 4) == 0);
+}
+
+/***************************************************/
+
+@safe pragma(inline, true)
+{
+ bool inlineMe15483a(bool left)
+ {
+ if (left)
+ return true;
+
+ return false;
+ }
+
+ bool inlineMe15483b(bool left)
+ {
+ if (left)
+ return true;
+
+ static if (false)
+ {
+ /* https://issues.dlang.org/show_bug.cgi?id=15483
+ Even though it does absolutely nothing,
+ the mere presence of this block prevents inlining
+ of this function.
+ */
+ }
+
+ return false;
+ }
+}
+
+int foo15483()
+{
+ auto r1 = inlineMe15483a(true);
+ auto r2 = inlineMe15483b(true); // OK <- NG
+
+ return 128;
+}
+
+void test15483()
+{
+ // Prevent inlining of test function call.
+ auto fp = &foo15483;
+ assert(fp() == 128);
+}
+
+/***************************************************/
+
+void main()
+{
+ test7625a();
+ test7625b();
+ test15483();
+}
diff --git a/gcc/testsuite/gdc.test/runnable/interface.d b/gcc/testsuite/gdc.test/runnable/interface.d
index 78a712e..a53c5ee 100644
--- a/gcc/testsuite/gdc.test/runnable/interface.d
+++ b/gcc/testsuite/gdc.test/runnable/interface.d
@@ -1,11 +1,3 @@
-/*
-TEST_OUTPUT:
----
-runnable/interface.d(41): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/interface.d(55): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
----
-*/
-
import core.stdc.stdio;
/*******************************************/
@@ -38,7 +30,7 @@ void test1()
IO io = new IO();
printf("io = %p\n", io);
foo(io, io);
- delete io;
+ destroy(io);
}
/*******************************************/
@@ -52,7 +44,7 @@ class C : I
void test2()
{
I i = new C();
- delete i;
+ destroy(i);
{
scope I j = new C();
diff --git a/gcc/testsuite/gdc.test/runnable/interface2.d b/gcc/testsuite/gdc.test/runnable/interface2.d
index 328f839..fabbbfd 100644
--- a/gcc/testsuite/gdc.test/runnable/interface2.d
+++ b/gcc/testsuite/gdc.test/runnable/interface2.d
@@ -1,11 +1,4 @@
// PERMUTE_ARGS:
-/*
-TEST_OUTPUT:
----
-runnable/interface2.d(47): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/interface2.d(98): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
----
-*/
extern(C) int printf(const char*, ...);
@@ -44,7 +37,7 @@ void test1()
printf("cast(Bar)f = %p\n", b2);
assert(b is b2);
- delete f;
+ destroy(f);
}
/*******************************************************/
@@ -95,7 +88,7 @@ class E3 : D3, C3
void test3()
{
C3 c = new E3();
- delete c;
+ destroy(c);
}
diff --git a/gcc/testsuite/gdc.test/runnable/interpret.d b/gcc/testsuite/gdc.test/runnable/interpret.d
index d8059d3..4d02a92 100644
--- a/gcc/testsuite/gdc.test/runnable/interpret.d
+++ b/gcc/testsuite/gdc.test/runnable/interpret.d
@@ -4,14 +4,6 @@ TEST_OUTPUT:
true
g
&Test109S(&Test109S(<recursion>))
-runnable/interpret.d(3197): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/interpret.d(3199): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/interpret.d(3202): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/interpret.d(3205): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/interpret.d(3206): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/interpret.d(3212): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/interpret.d(3213): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/interpret.d(3216): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
tfoo
tfoo
Crash!
@@ -3187,33 +3179,96 @@ auto test110 = [Test110f(1, Test110s(1, 2, 3))];
/************************************************/
// https://issues.dlang.org/show_bug.cgi?id=6907
+// FIXME: Shouldn't this go in core.memory now that `delete` has been removed?
int test6907()
{
+ import core.memory : __delete;
+
int dtor1;
class C { ~this() { ++dtor1; } }
// delete on Object
- { Object o; delete o; }
+ { Object o; if (!__ctfe) __delete(o); }
{ scope o = new Object(); }
- { Object o = new Object(); delete o; }
+ { Object o = new Object(); if (!__ctfe) __delete(o); }
// delete on C
- { C c; delete c; }
- { { scope c = new C(); } assert(dtor1 == 1); }
- { { scope Object o = new C(); } assert(dtor1 == 2); }
- { C c = new C(); delete c; assert(dtor1 == 3); }
- { Object o = new C(); delete o; assert(dtor1 == 4); }
+ {
+ C c;
+ if (!__ctfe)
+ __delete(c);
+ }
+ {
+ { scope c = new C(); }
+ assert(dtor1 == 1);
+ }
+ {
+ { scope Object o = new C(); }
+ assert(dtor1 == 2);
+ }
+ {
+ C c = new C();
+ if (__ctfe)
+ {
+ c.__dtor();
+ c = null;
+ }
+ else
+ __delete(c);
+ assert(dtor1 == 3);
+ }
+ {
+ Object o = new C();
+ if (__ctfe)
+ {
+ (cast(C)o).__dtor();
+ o = null;
+ }
+ else
+ __delete(o);
+ assert(dtor1 == 4);
+ }
int dtor2;
struct S1 { ~this() { ++dtor2; } }
// delete on S1
- { S1* p; delete p; }
- { S1* p = new S1(); delete p; assert(dtor2 == 1); }
+ {
+ S1* p;
+ // https://issues.dlang.org/show_bug.cgi?id=22779
+ // Uncomment after druntime fix
+ version (none)
+ {
+ if (!__ctfe)
+ __delete(p);
+ }
+ }
+ {
+ S1* p = new S1();
+ if (__ctfe)
+ {
+ (*p).__dtor();
+ destroy(p);
+ }
+ else
+ __delete(p);
+ assert(dtor2 == 1);
+ }
// delete on S1[]
- { S1[] a = [S1(), S1()]; delete a; assert(dtor2 == 3); }
+ {
+ S1[] a = [S1(), S1()];
+ if (__ctfe)
+ {
+ a[1].__dtor();
+ a[0].__dtor();
+ destroy(a);
+ }
+ else
+ __delete(a);
+ assert(dtor2 == 3);
+ }
return 1;
}
diff --git a/gcc/testsuite/gdc.test/runnable/link12144.d b/gcc/testsuite/gdc.test/runnable/link12144.d
index e7bcf86..9092556 100644
--- a/gcc/testsuite/gdc.test/runnable/link12144.d
+++ b/gcc/testsuite/gdc.test/runnable/link12144.d
@@ -1,11 +1,5 @@
// COMPILE_SEPARATELY: -g
// EXTRA_SOURCES: imports/link12144a.d
-/*
-TEST_OUTPUT:
----
-runnable/imports/link12144a.d(31): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
----
-*/
import imports.link12144a;
diff --git a/gcc/testsuite/gdc.test/runnable/link15017.d b/gcc/testsuite/gdc.test/runnable/link15017.d
index 5d39547..ef52dfb 100644
--- a/gcc/testsuite/gdc.test/runnable/link15017.d
+++ b/gcc/testsuite/gdc.test/runnable/link15017.d
@@ -1,11 +1,5 @@
// COMPILE_SEPARATELY:
// EXTRA_SOURCES: imports/std15017variant.d
-/*
-TEST_OUTPUT:
----
-runnable/link15017.d(48): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
----
-*/
import imports.std15017variant;
@@ -45,7 +39,7 @@ void test()
// OK <- in DeleteExp::semantic
Variant10* p10;
- delete p10;
+ destroy(p10);
static assert(Variant10.__dtor.mangleof == "_D7imports15std15017variant__T8VariantNVki10ZQp6__dtorMFNaNbNiNfZv");
}
diff --git a/gcc/testsuite/gdc.test/runnable/mixin1.d b/gcc/testsuite/gdc.test/runnable/mixin1.d
index d8b5516..d36d3f1 100644
--- a/gcc/testsuite/gdc.test/runnable/mixin1.d
+++ b/gcc/testsuite/gdc.test/runnable/mixin1.d
@@ -1,9 +1,4 @@
/*
-TEST_OUTPUT:
----
-runnable/mixin1.d(948): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
----
-
RUN_OUTPUT:
---
Foo3.func()
@@ -945,7 +940,7 @@ class Outer38
void test38()
{
Outer38 o = new Outer38();
- delete o;
+ destroy(o);
assert(Outer38.c == 3);
}
diff --git a/gcc/testsuite/gdc.test/runnable/newdel.d b/gcc/testsuite/gdc.test/runnable/newdel.d
index 3729b2e..8ba7a0c 100644
--- a/gcc/testsuite/gdc.test/runnable/newdel.d
+++ b/gcc/testsuite/gdc.test/runnable/newdel.d
@@ -1,10 +1,4 @@
// PERMUTE_ARGS:
-/*
-TEST_OUTPUT:
----
-runnable/newdel.d(46): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
----
-*/
import core.stdc.stdio;
import core.stdc.stdlib;
@@ -43,7 +37,7 @@ void test1()
assert(f.d == 56);
assert(Foo.flags == 0);
- delete f;
+ destroy(f);
assert(Foo.flags == 1);
}
diff --git a/gcc/testsuite/gdc.test/runnable/sdtor.d b/gcc/testsuite/gdc.test/runnable/sdtor.d
index 56c5125..e6b3238 100644
--- a/gcc/testsuite/gdc.test/runnable/sdtor.d
+++ b/gcc/testsuite/gdc.test/runnable/sdtor.d
@@ -3,19 +3,13 @@
/*
TEST_OUTPUT:
---
-runnable/sdtor.d(36): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/sdtor.d(59): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/sdtor.d(93): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/sdtor.d(117): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/sdtor.d(143): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/sdtor.d(177): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/sdtor.d(203): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/sdtor.d(276): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
S7353
---
*/
import core.vararg;
+// FIXME: Shouldn't tests that use this go in core.memory now that `delete` has been removed?
+import core.memory : __delete;
extern (C) int printf(const(char*) fmt, ...) nothrow;
@@ -33,7 +27,7 @@ struct S1
void test1()
{
S1* s = new S1();
- delete s;
+ __delete(s);
assert(sdtor == 1);
}
@@ -56,7 +50,7 @@ void test3()
{
T3* s = new T3();
s.s.a = 3;
- delete s;
+ __delete(s);
assert(sdtor3 == 1);
}
@@ -90,7 +84,7 @@ void test4()
{
T4* s = new T4();
s.s.a = 4;
- delete s;
+ __delete(s);
assert(sdtor4 == 3);
}
@@ -114,7 +108,7 @@ struct T5
void test5()
{
T5* s = new T5();
- delete s;
+ __delete(s);
assert(sdtor5 == 2);
}
@@ -140,7 +134,7 @@ class T6
void test6()
{
T6 s = new T6();
- delete s;
+ __delete(s);
assert(sdtor6 == 2);
}
@@ -174,7 +168,7 @@ struct T7
void test7()
{
T7* s = new T7();
- delete s;
+ __delete(s);
assert(sdtor7 == 4);
}
@@ -200,7 +194,7 @@ void test8()
s[0].c = 2;
s[1].c = 1;
s[2].c = 0;
- delete s;
+ __delete(s);
assert(sdtor8 == 3);
}
@@ -273,7 +267,7 @@ class T11
void test11()
{
T11 s = new T11();
- delete s;
+ __delete(s);
assert(sdtor11 == 2);
}
diff --git a/gcc/testsuite/gdc.test/runnable/test11934.d b/gcc/testsuite/gdc.test/runnable/test11934.d
index 4ab65d2..7e6dc04 100644
--- a/gcc/testsuite/gdc.test/runnable/test11934.d
+++ b/gcc/testsuite/gdc.test/runnable/test11934.d
@@ -5,7 +5,7 @@ void main()
this(int i) { instances++; }
this(this) { instances++; }
~this() { instances--; }
- static size_t instances = 0;
+ static size_t instances = 0;
}
struct Range11934
diff --git a/gcc/testsuite/gdc.test/runnable/test17684.d b/gcc/testsuite/gdc.test/runnable/test17684.d
index d42baac..efdce08 100644
--- a/gcc/testsuite/gdc.test/runnable/test17684.d
+++ b/gcc/testsuite/gdc.test/runnable/test17684.d
@@ -7,17 +7,17 @@ struct StructField(T)
struct StructProperty(T)
{
static T Field;
-
+
static @property T property()
{
- return Field;
+ return Field;
}
-
+
static @property void property(T value)
{
- Field = value;
+ Field = value;
}
-
+
static alias property this;
}
@@ -30,17 +30,17 @@ class ClassField(T)
class ClassProperty(T)
{
static T Field;
-
+
static @property T property()
{
- return Field;
+ return Field;
}
-
+
static @property void property(T value)
{
- Field = value;
+ Field = value;
}
-
+
static alias property this;
}
diff --git a/gcc/testsuite/gdc.test/runnable/test17899.d b/gcc/testsuite/gdc.test/runnable/test17899.d
index fdd75e8..2ad60d0 100644
--- a/gcc/testsuite/gdc.test/runnable/test17899.d
+++ b/gcc/testsuite/gdc.test/runnable/test17899.d
@@ -1,7 +1,7 @@
module test17899;
// Test that the ICE in 13259 does not ICE but produces correct code
-auto dg = delegate {};
+auto dg = delegate {};
int setme = 0;
void delegate() bar1 = (){ setme = 1;};
diff --git a/gcc/testsuite/gdc.test/runnable/test20.d b/gcc/testsuite/gdc.test/runnable/test20.d
index 5a1985a..5d47b06 100644
--- a/gcc/testsuite/gdc.test/runnable/test20.d
+++ b/gcc/testsuite/gdc.test/runnable/test20.d
@@ -1,9 +1,3 @@
-/*
-TEST_OUTPUT:
----
-runnable/test20.d(448): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
----
-*/
import core.vararg;
extern(C) int printf(const char*, ...);
@@ -445,7 +439,7 @@ class Buffer
void test20()
{
Buffer b = new Buffer();
- delete b;
+ destroy(b);
}
/*****************************************/
diff --git a/gcc/testsuite/gdc.test/runnable/test22136.d b/gcc/testsuite/gdc.test/runnable/test22136.d
new file mode 100644
index 0000000..8b5af24
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test22136.d
@@ -0,0 +1,25 @@
+
+interface IObject
+{
+ size_t toHash() @trusted nothrow;
+}
+
+interface Dummy {}
+interface Bug(E) : Dummy, IObject {}
+interface OK(E) : IObject, Dummy {}
+
+void main()
+{
+
+ {
+ Bug!string s;
+ size_t t = hashOf(s);
+ }
+ {
+ OK!string s;
+ size_t t = hashOf(s);
+ }
+
+ static assert(is(immutable Bug!string* : immutable IObject*));
+ static assert(is(immutable OK!string* : immutable IObject*));
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test22163.d b/gcc/testsuite/gdc.test/runnable/test22163.d
new file mode 100644
index 0000000..2613763
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test22163.d
@@ -0,0 +1,13 @@
+// https://issues.dlang.org/show_bug.cgi?id=22163
+void fun(float[2] arr)
+{
+ assert(arr[0] == 10.0);
+ assert(arr[1] == 20.0);
+ auto dg = (int x) => arr[0];
+}
+
+void main()
+{
+ float[2] arr = [10.0, 20.0];
+ fun(arr);
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test22717.d b/gcc/testsuite/gdc.test/runnable/test22717.d
new file mode 100644
index 0000000..75d54c7
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/test22717.d
@@ -0,0 +1,31 @@
+// PERMUTE_ARGS: -version=XopEquals
+
+void main()
+{
+ static struct S
+ {
+ int value;
+
+ version (XopEquals)
+ {
+ bool opEquals(const S rhs) const
+ {
+ assert(this.value == 42);
+ return true;
+ }
+ }
+ else
+ {
+ bool opEquals(const ref S rhs) const
+ {
+ assert(this.value == 42);
+ return true;
+ }
+ }
+ }
+
+ auto a = S(42);
+ auto b = S(24);
+ auto ti = typeid(S);
+ assert(ti.equals(&a, &b));
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test4.d b/gcc/testsuite/gdc.test/runnable/test4.d
index 9811254..8a3f926 100644
--- a/gcc/testsuite/gdc.test/runnable/test4.d
+++ b/gcc/testsuite/gdc.test/runnable/test4.d
@@ -1,11 +1,5 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS:
-/*
-TEST_OUTPUT:
----
-runnable/test4.d(717): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
----
-*/
import core.exception;
import core.stdc.math;
@@ -714,7 +708,7 @@ void test29()
Foo29 f = new Foo29();
- delete f;
+ destroy(f);
assert(x29 == 3);
}
diff --git a/gcc/testsuite/gdc.test/runnable/testappend.d b/gcc/testsuite/gdc.test/runnable/testappend.d
index f8bff3e..cedd8d7 100644
--- a/gcc/testsuite/gdc.test/runnable/testappend.d
+++ b/gcc/testsuite/gdc.test/runnable/testappend.d
@@ -1,13 +1,5 @@
/*
PERMUTE_ARGS:
-TEST_OUTPUT:
----
-runnable/testappend.d(54): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/testappend.d(55): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/testappend.d(76): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
-runnable/testappend.d(77): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
----
-
RUN_OUTPUT:
---
Success
@@ -51,8 +43,8 @@ int main()
{
assert(isnan(v));
}
- delete a;
- delete b;
+ destroy(a);
+ destroy(b);
a = null;
for (int i = 0; i < 100000; i++)
@@ -73,8 +65,8 @@ int main()
{
assert(v == k);
}
- delete a;
- delete b;
+ destroy(a);
+ destroy(b);
test12826();
printf("Success\n");
diff --git a/gcc/testsuite/gdc.test/runnable/testconst.d b/gcc/testsuite/gdc.test/runnable/testconst.d
index 764bb1b..502dca0 100644
--- a/gcc/testsuite/gdc.test/runnable/testconst.d
+++ b/gcc/testsuite/gdc.test/runnable/testconst.d
@@ -2175,13 +2175,13 @@ void test4251b()
// derived class to const(base interface) in tail
interface I {}
class X : I {}
- static assert(!is( X[] : const(I)[] ));
+ static assert(is( X[] : const(I)[] ));
// interface to const(base interface) in tail
interface J {}
interface K : I, J {}
static assert( is( K[] : const(I)[] )); // OK, runtime offset is same
- static assert(!is( K[] : const(J)[] )); // NG, runtime offset is different
+ static assert(is( K[] : const(J)[] )); // !? NG, runtime offset is different
}
/************************************/
diff --git a/gcc/testsuite/gdc.test/runnable/testdstress.d b/gcc/testsuite/gdc.test/runnable/testdstress.d
index 6ca5500..03af207 100644
--- a/gcc/testsuite/gdc.test/runnable/testdstress.d
+++ b/gcc/testsuite/gdc.test/runnable/testdstress.d
@@ -1,10 +1,4 @@
// PERMUTE_ARGS:
-/*
-TEST_OUTPUT:
----
-runnable/testdstress.d(666): Deprecation: The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.
----
-*/
module run.module_01;
@@ -663,7 +657,7 @@ void test30()
assert(status30 == 1);
- delete m; // _d_callfinalizer
+ destroy(m); // _d_callfinalizer
}
catch (Error e) // FinalizeError
{
diff --git a/gcc/testsuite/gdc.test/runnable/testptrref.d b/gcc/testsuite/gdc.test/runnable/testptrref.d
index c616d57..7255595 100644
--- a/gcc/testsuite/gdc.test/runnable/testptrref.d
+++ b/gcc/testsuite/gdc.test/runnable/testptrref.d
@@ -21,7 +21,7 @@ version(CRuntime_Microsoft)
void[] function(string name) nothrow @nogc);
dataSection = findImageSection(".data");
}
-
+
void[] tlsRange;
static this()
{
@@ -30,7 +30,7 @@ version(CRuntime_Microsoft)
void[] function() nothrow @nogc);
tlsRange = initTLSRanges();
}
-
+
version = ptrref_supported;
}
else version(Win32)
@@ -126,7 +126,7 @@ bool findDataPtr(const(void)* ptr)
void* addr = dataSection.ptr + *p;
else
void* addr = *p;
-
+
if (addr == ptr)
return true;
}
@@ -158,7 +158,7 @@ void testRefPtr()
assert(!findTlsPtr(cast(size_t*)&tlsStr)); // length
assert(findTlsPtr(cast(size_t*)&tlsStr + 1)); // ptr
-
+
// monitor is manually managed
assert(!findDataPtr(cast(size_t*)cast(void*)Class.classinfo + 1));
assert(!findDataPtr(cast(size_t*)cast(void*)Class.classinfo + 1));
@@ -167,7 +167,7 @@ void testRefPtr()
assert(!findTlsPtr(&arr));
assert(!findDataPtr(cast(size_t*)&arr + 1));
assert(!findTlsPtr(cast(size_t*)&arr + 1));
-
+
assert(findDataPtr(cast(size_t*)&strArr[0] + 1)); // ptr in _DATA!
assert(findDataPtr(cast(size_t*)&strArr[1] + 1)); // ptr in _DATA!
strArr[1] = "c";
diff --git a/gcc/testsuite/gdc.test/runnable/xpostblit.d b/gcc/testsuite/gdc.test/runnable/xpostblit.d
index 8f8a59d..5889116 100644
--- a/gcc/testsuite/gdc.test/runnable/xpostblit.d
+++ b/gcc/testsuite/gdc.test/runnable/xpostblit.d
@@ -86,7 +86,7 @@ struct FieldThrow
bool throwExcept;
this(this)
- {
+ {
if (throwExcept)
{
throw new Exception("");
diff --git a/gcc/testsuite/gdc.test/runnable_cxx/cppa.d b/gcc/testsuite/gdc.test/runnable_cxx/cppa.d
index cd36bf2..e315889 100644
--- a/gcc/testsuite/gdc.test/runnable_cxx/cppa.d
+++ b/gcc/testsuite/gdc.test/runnable_cxx/cppa.d
@@ -469,7 +469,7 @@ extern (C++, std)
static if (__traits(getTargetInfo, "cppStd") >= 201703)
{
// std::allocator no longer derives from __gnu_cxx::new_allocator,
- // it derives from std::__new_allocator instead.
+ // it derives from std::__new_allocator instead.
struct __new_allocator(T)
{
alias size_type = size_t;
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index 251d78d..49f6ae2 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@
-dbd0c874a345438b8b4379a67525a933436d039a
+55528bd1e963d858eaa63901fc818b957c349fbc
The first line of this file holds the git revision number of the last
merge done from the dlang/druntime repository.
diff --git a/libphobos/libdruntime/__builtins.di b/libphobos/libdruntime/__builtins.di
index cd64881..e5c448e 100644
--- a/libphobos/libdruntime/__builtins.di
+++ b/libphobos/libdruntime/__builtins.di
@@ -38,3 +38,68 @@ alias __builtin_va_copy = core.stdc.stdarg.va_copy;
/* dmd's ImportC rewrites __builtin_va_arg into an instantiation of va_arg
*/
alias va_arg = core.stdc.stdarg.va_arg;
+
+version (CRuntime_Microsoft)
+{
+ //https://docs.microsoft.com/en-us/cpp/cpp/int8-int16-int32-int64?view=msvc-170
+ alias __int8 = byte;
+ alias __int16 = short;
+ alias __int32 = int;
+ alias __int64 = long;
+}
+
+/*********** floating point *************/
+
+/* https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
+ */
+
+version (DigitalMars)
+{
+ double __builtin_inf()() { return double.infinity; }
+ float __builtin_inff()() { return float.infinity; }
+ real __builtin_infl()() { return real.infinity; }
+
+ alias __builtin_huge_val = __builtin_inf;
+ alias __builtin_huge_valf = __builtin_inff;
+ alias __builtin_huge_vall = __builtin_infl;
+
+ import core.stdc.math;
+
+ alias __builtin_fabs = core.stdc.math.fabs;
+ alias __builtin_fabsf = core.stdc.math.fabsf;
+ alias __builtin_fabsl = core.stdc.math.fabsl;
+
+ ushort __builtin_bswap16()(ushort value)
+ {
+ import core.bitop;
+ return core.bitop.byteswap(value);
+ }
+
+ uint __builtin_bswap32()(uint value)
+ {
+ import core.bitop;
+ return core.bitop.bswap(value);
+ }
+
+ ulong __builtin_bswap64()(ulong value)
+ {
+ import core.bitop;
+ return core.bitop.bswap(value);
+ }
+
+ // Stub these out to no-ops
+ int __builtin_constant_p(T)(T exp) { return 0; } // should be something like __traits(compiles, enum X = expr)
+ long __builtin_expect()(long exp, long c) { return exp; }
+ void* __builtin_assume_aligned()(const void* p, size_t align_, ...) { return cast(void*)p; }
+
+ // https://releases.llvm.org/13.0.0/tools/clang/docs/LanguageExtensions.html#builtin-assume
+ void __builtin_assume(T)(lazy T arg) { }
+
+ /* Header on macOS for arm64 references this.
+ * Don't need to implement it, it just needs to compile
+ */
+ align (16) struct __uint128_t
+ {
+ ulong a, b;
+ }
+}
diff --git a/libphobos/libdruntime/core/attribute.d b/libphobos/libdruntime/core/attribute.d
index b0b973f..69b20f0 100644
--- a/libphobos/libdruntime/core/attribute.d
+++ b/libphobos/libdruntime/core/attribute.d
@@ -241,3 +241,52 @@ version (UdaGNUAbiTag) struct gnuAbiTag
this.tags = tags;
}
}
+
+/**
+ * Use this attribute to ensure that values of a `struct` or `union` type are
+ * not discarded.
+ *
+ * The value of an expression is considered to be discarded if
+ *
+ * $(UL
+ * $(LI
+ * the expression is the top-level expression in a statement or the
+ * left-hand expression in a comma expression, and
+ * ),
+ * $(LI
+ * the expression is not an assignment (`=`, `+=`, etc.), increment
+ * (`++`), or decrement (`--`) expression.
+ * ),
+ * )
+ *
+ * If the declaration of a `struct` or `union` type has the `@mustuse`
+ * attribute, the compiler will emit an error any time a value of that type
+ * would be discarded.
+ *
+ * Currently, `@mustuse` is only recognized by the compiler when attached to
+ * `struct` and `union` declarations. To allow for future expansion, attaching
+ * `@mustuse` to a `class`, `interface`, `enum`, or function declaration is
+ * currently forbidden, and will result in a compile-time error. All other uses
+ * of `@mustuse` are ignored.
+ *
+ * Examples:
+ * ---
+ * @mustuse struct ErrorCode { int value; }
+ *
+ * extern(C) ErrorCode doSomething();
+ *
+ * void main()
+ * {
+ * // error: would discard a value of type ErrorCode
+ * //doSomething();
+ *
+ * ErrorCode result;
+ * // ok: value is assigned to a variable
+ * result = doSomething();
+ *
+ * // ok: can ignore the value explicitly with a cast
+ * cast(void) doSomething();
+ * }
+ * ---
+ */
+enum mustuse;
diff --git a/libphobos/libdruntime/core/bitop.d b/libphobos/libdruntime/core/bitop.d
index 40f2242..59445f0 100644
--- a/libphobos/libdruntime/core/bitop.d
+++ b/libphobos/libdruntime/core/bitop.d
@@ -758,19 +758,6 @@ version (DigitalMars) version (AnyX86)
}
-// @@@DEPRECATED_2.099@@@
-deprecated("volatileLoad has been moved to core.volatile. Use core.volatile.volatileLoad instead.")
-{
- public import core.volatile : volatileLoad;
-}
-
-// @@@DEPRECATED_2.099@@@
-deprecated("volatileStore has been moved to core.volatile. Use core.volatile.volatileStore instead.")
-{
- public import core.volatile : volatileStore;
-}
-
-
/**
* Reverses the order of bits in a 32-bit integer.
*/
diff --git a/libphobos/libdruntime/core/int128.d b/libphobos/libdruntime/core/int128.d
index aad2cf2..2f628c0 100644
--- a/libphobos/libdruntime/core/int128.d
+++ b/libphobos/libdruntime/core/int128.d
@@ -801,6 +801,7 @@ unittest
const Cm10_0 = inc(com(C10_0)); // Cent(0, -10);
const Cm10_1 = inc(com(C10_1)); // Cent(-1, -11);
const Cm10_3 = inc(com(C10_3)); // Cent(-3, -11);
+ const Cm20_0 = inc(com(C20_0)); // Cent(0, -20);
enum Cs_3 = Cent(3, I.min);
@@ -904,6 +905,7 @@ unittest
assert(mul(C9_3, C10) == C90_30);
assert(mul(Cs_3, C10) == C30);
assert(mul(Cm10, Cm10) == C100);
+ assert(mul(C20_0, Cm1) == Cm20_0);
assert( or(C4_8, C3_1) == C7_9);
assert(and(C4_8, C7_9) == C4_8);
diff --git a/libphobos/libdruntime/core/internal/array/appending.d b/libphobos/libdruntime/core/internal/array/appending.d
index 1e58ddc..172263c 100644
--- a/libphobos/libdruntime/core/internal/array/appending.d
+++ b/libphobos/libdruntime/core/internal/array/appending.d
@@ -35,14 +35,14 @@ template _d_arrayappendcTXImpl(Tarr : T[], T)
* is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations.
*/
static if (isCopyingNothrow!T) // `nothrow` deduction doesn't work, so this is needed
- ref Tarr _d_arrayappendcTX(return scope ref Tarr px, size_t n) @trusted pure nothrow
+ ref Tarr _d_arrayappendcTX(return ref scope Tarr px, size_t n) @trusted pure nothrow
{
pragma(inline, false);
mixin(_d_arrayappendcTXBody);
}
else
- ref Tarr _d_arrayappendcTX(return scope ref Tarr px, size_t n) @trusted pure nothrow
+ ref Tarr _d_arrayappendcTX(return ref scope Tarr px, size_t n) @trusted pure nothrow
{
pragma(inline, false);
@@ -96,14 +96,14 @@ template _d_arrayappendTImpl(Tarr : T[], T)
* is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations.
*/
static if (isCopyingNothrow!T)
- ref Tarr _d_arrayappendT(return scope ref Tarr x, scope Tarr y) @trusted pure nothrow
+ ref Tarr _d_arrayappendT(return ref scope Tarr x, scope Tarr y) @trusted pure nothrow
{
pragma(inline, false);
mixin(_d_arrayappendTBody);
}
else
- ref Tarr _d_arrayappendT(return scope ref Tarr x, scope Tarr y) @trusted pure
+ ref Tarr _d_arrayappendT(return ref scope Tarr x, scope Tarr y) @trusted pure
{
pragma(inline, false);
diff --git a/libphobos/libdruntime/core/internal/array/comparison.d b/libphobos/libdruntime/core/internal/array/comparison.d
index 1a68b9b..821f96e 100644
--- a/libphobos/libdruntime/core/internal/array/comparison.d
+++ b/libphobos/libdruntime/core/internal/array/comparison.d
@@ -60,24 +60,21 @@ int __cmp(T)(scope const T[] lhs, scope const T[] rhs) @trusted
immutable len = lhs.length <= rhs.length ? lhs.length : rhs.length;
foreach (const u; 0 .. len)
{
- static if (__traits(isFloating, T))
+ auto a = lhs.ptr[u], b = rhs.ptr[u];
+ static if (is(T : creal))
{
- immutable a = lhs.ptr[u], b = rhs.ptr[u];
- static if (is(T == cfloat) || is(T == cdouble)
- || is(T == creal))
- {
- // Use rt.cmath2._Ccmp instead ?
- auto r = (a.re > b.re) - (a.re < b.re);
- if (!r) r = (a.im > b.im) - (a.im < b.im);
- }
- else
- {
- const r = (a > b) - (a < b);
- }
- if (r) return r;
+ // Use rt.cmath2._Ccmp instead ?
+ // Also: if NaN is present, numbers will appear equal.
+ auto r = (a.re > b.re) - (a.re < b.re);
+ if (!r) r = (a.im > b.im) - (a.im < b.im);
+ }
+ else
+ {
+ // This pattern for three-way comparison is better than conditional operators
+ // See e.g. https://godbolt.org/z/3j4vh1
+ const r = (a > b) - (a < b);
}
- else if (lhs.ptr[u] != rhs.ptr[u])
- return lhs.ptr[u] < rhs.ptr[u] ? -1 : 1;
+ if (r) return r;
}
return (lhs.length > rhs.length) - (lhs.length < rhs.length);
}
@@ -117,8 +114,8 @@ if (!__traits(isScalar, T1) && !__traits(isScalar, T2))
}
else static if (__traits(compiles, at(s1, u) < at(s2, u)))
{
- if (at(s1, u) != at(s2, u))
- return at(s1, u) < at(s2, u) ? -1 : 1;
+ if (int result = (at(s1, u) > at(s2, u)) - (at(s1, u) < at(s2, u)))
+ return result;
}
else
{
diff --git a/libphobos/libdruntime/core/internal/convert.d b/libphobos/libdruntime/core/internal/convert.d
index a876fcc..92eb243 100644
--- a/libphobos/libdruntime/core/internal/convert.d
+++ b/libphobos/libdruntime/core/internal/convert.d
@@ -741,28 +741,6 @@ const(ubyte)[] toUbyte(T)(const ref scope T val) if (is(T == __vector))
}
}
-// @@@DEPRECATED_2022-02@@@
-deprecated
-@trusted pure nothrow @nogc
-const(ubyte)[] toUbyte(T)(const ref return scope T val) if (__traits(isFloating, T) && is(T : creal))
-{
- if (__ctfe)
- {
- auto re = val.re;
- auto im = val.im;
- auto a = re.toUbyte();
- auto b = im.toUbyte();
- ubyte[] result = ctfe_alloc(a.length + b.length);
- result[0 .. a.length] = a[0 .. a.length];
- result[a.length .. $] = b[0 .. b.length];
- return result;
- }
- else
- {
- return (cast(const(ubyte)*)&val)[0 .. T.sizeof];
- }
-}
-
@trusted pure nothrow @nogc
const(ubyte)[] toUbyte(T)(const ref return scope T val) if (is(T == enum))
{
diff --git a/libphobos/libdruntime/core/lifetime.d b/libphobos/libdruntime/core/lifetime.d
index 091269a..3a7c8e0 100644
--- a/libphobos/libdruntime/core/lifetime.d
+++ b/libphobos/libdruntime/core/lifetime.d
@@ -2646,9 +2646,9 @@ T _d_newThrowable(T, Args...)(auto ref Args args) @trusted
{
debug(PRINTF) printf("_d_newThrowable(%s)\n", cast(char*) T.stringof);
- import core.stdc.stdlib : malloc;
+ import core.memory : pureMalloc;
auto init = __traits(initSymbol, T);
- void* p = malloc(init.length);
+ void* p = pureMalloc(init.length);
if (!p)
{
import core.exception : onOutOfMemoryError;
diff --git a/libphobos/libdruntime/core/math.d b/libphobos/libdruntime/core/math.d
index 4d46b67..30fc130 100644
--- a/libphobos/libdruntime/core/math.d
+++ b/libphobos/libdruntime/core/math.d
@@ -36,6 +36,7 @@ nothrow:
* greater than long.max, the result is
* indeterminate.
*/
+deprecated("rndtonl is to be removed by 2.100. Please use round instead")
extern (C) real rndtonl(real x);
pure:
diff --git a/libphobos/libdruntime/core/runtime.d b/libphobos/libdruntime/core/runtime.d
index 81d2d26..d1378af 100644
--- a/libphobos/libdruntime/core/runtime.d
+++ b/libphobos/libdruntime/core/runtime.d
@@ -285,7 +285,7 @@ struct Runtime
* an appropriate calling context from which to begin the trace.
*
* Params:
- * h = The new trace handler. Set to null to use the default handler.
+ * h = The new trace handler. Set to null to disable exception backtracing.
*/
extern(C) pragma(mangle, "rt_setTraceHandler") static @property void traceHandler(TraceHandler h);
diff --git a/libphobos/libdruntime/core/stdc/stdio.d b/libphobos/libdruntime/core/stdc/stdio.d
index c76b922..0dcdb6e 100644
--- a/libphobos/libdruntime/core/stdc/stdio.d
+++ b/libphobos/libdruntime/core/stdc/stdio.d
@@ -700,9 +700,8 @@ else version (Solaris)
}
else version (CRuntime_Bionic)
{
- import core.sys.posix.sys.types : off_t;
///
- alias off_t fpos_t;
+ alias c_long fpos_t; // couldn't use off_t because of static if issue
///
struct __sFILE
@@ -745,12 +744,10 @@ else version (CRuntime_UClibc)
import core.stdc.stddef : wchar_t;
import core.sys.posix.sys.types : ssize_t, pthread_mutex_t;
- alias long off_t;
-
///
struct fpos_t
{
- off_t __pos;
+ long __pos; // couldn't use off_t because of static if issue
mbstate_t __state;
int __mblen_pending;
}
@@ -759,7 +756,7 @@ else version (CRuntime_UClibc)
{
ssize_t function(void* __cookie, char* __buf, size_t __bufsize) read;
ssize_t function(void* __cookie, const char* __buf, size_t __bufsize) write;
- int function(void* __cookie, off_t* __pos, int __whence) seek;
+ int function(void* __cookie, long* __pos, int __whence) seek;
int function(void* __cookie) close;
}
@@ -900,12 +897,14 @@ else version (CRuntime_Microsoft)
extern shared void function() _fcloseallp;
+ FILE* __acrt_iob_func(int hnd); // VS2015+, reimplemented in msvc.d for VS2013-
+
///
- shared FILE* stdin; // = &__iob_func()[0];
+ FILE* stdin()() { return __acrt_iob_func(0); }
///
- shared FILE* stdout; // = &__iob_func()[1];
+ FILE* stdout()() { return __acrt_iob_func(1); }
///
- shared FILE* stderr; // = &__iob_func()[2];
+ FILE* stderr()() { return __acrt_iob_func(2); }
}
else version (CRuntime_Glibc)
{
diff --git a/libphobos/libdruntime/core/sys/linux/config.d b/libphobos/libdruntime/core/sys/linux/config.d
index 03d3e17..5d38244f 100644
--- a/libphobos/libdruntime/core/sys/linux/config.d
+++ b/libphobos/libdruntime/core/sys/linux/config.d
@@ -24,6 +24,9 @@ deprecated("use _DEFAULT_SOURCE")
enum _SVID_SOURCE = true;
}
+deprecated("use _DEFAULT_SOURCE")
enum __USE_MISC = _DEFAULT_SOURCE;
+deprecated("use _ATFILE_SOURCE")
enum __USE_ATFILE = _ATFILE_SOURCE;
+deprecated("use _GNU_SOURCE")
enum __USE_GNU = _GNU_SOURCE;
diff --git a/libphobos/libdruntime/core/sys/linux/dlfcn.d b/libphobos/libdruntime/core/sys/linux/dlfcn.d
index 4a12284..fbb8462 100644
--- a/libphobos/libdruntime/core/sys/linux/dlfcn.d
+++ b/libphobos/libdruntime/core/sys/linux/dlfcn.d
@@ -34,7 +34,7 @@ import core.sys.linux.config;
version (X86_Any)
{
// http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
- static if (__USE_GNU)
+ static if (_GNU_SOURCE)
{
RT DL_CALL_FCT(RT, Args...)(RT function(Args) fctp, auto ref Args args)
{
@@ -48,7 +48,7 @@ version (X86_Any)
else version (HPPA_Any)
{
// http://sourceware.org/git/?p=glibc.git;a=blob;f=ports/sysdeps/hppa/bits/dlfcn.h
- static if (__USE_GNU)
+ static if (_GNU_SOURCE)
{
RT DL_CALL_FCT(RT, Args...)(RT function(Args) fctp, auto ref Args args)
{
@@ -62,7 +62,7 @@ else version (HPPA_Any)
else version (MIPS_Any)
{
// http://sourceware.org/git/?p=glibc.git;a=blob;f=ports/sysdeps/mips/bits/dlfcn.h
- static if (__USE_GNU)
+ static if (_GNU_SOURCE)
{
RT DL_CALL_FCT(RT, Args...)(RT function(Args) fctp, auto ref Args args)
{
@@ -76,7 +76,7 @@ else version (MIPS_Any)
else version (PPC_Any)
{
// http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
- static if (__USE_GNU)
+ static if (_GNU_SOURCE)
{
RT DL_CALL_FCT(RT, Args...)(RT function(Args) fctp, auto ref Args args)
{
@@ -90,7 +90,7 @@ else version (PPC_Any)
else version (ARM_Any)
{
// http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
- static if (__USE_GNU)
+ static if (_GNU_SOURCE)
{
RT DL_CALL_FCT(RT, Args...)(RT function(Args) fctp, auto ref Args args)
{
@@ -104,7 +104,7 @@ else version (ARM_Any)
else version (RISCV_Any)
{
// http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
- static if (__USE_GNU)
+ static if (_GNU_SOURCE)
{
RT DL_CALL_FCT(RT, Args...)(RT function(Args) fctp, auto ref Args args)
{
@@ -118,7 +118,7 @@ else version (RISCV_Any)
else version (SPARC_Any)
{
// http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
- static if (__USE_GNU)
+ static if (_GNU_SOURCE)
{
RT DL_CALL_FCT(RT, Args...)(RT function(Args) fctp, auto ref Args args)
{
@@ -132,7 +132,7 @@ else version (SPARC_Any)
else version (IBMZ_Any)
{
// http://sourceware.org/git/?p=glibc.git;a=blob;f=bits/dlfcn.h
- static if (__USE_GNU)
+ static if (_GNU_SOURCE)
{
RT DL_CALL_FCT(RT, Args...)(RT function(Args) fctp, auto ref Args args)
{
@@ -148,7 +148,7 @@ else
// <bits/dlfcn.h>
-static if (__USE_GNU)
+static if (_GNU_SOURCE)
{
enum RTLD_NEXT = cast(void *)-1L;
enum RTLD_DEFAULT = cast(void *)0;
@@ -161,7 +161,7 @@ static if (__USE_GNU)
// int dlclose(void* __handle); // POSIX
// void* dlsym(void* __handle, const scope char* __name); // POSIX
-static if (__USE_GNU)
+static if (_GNU_SOURCE)
{
void* dlmopen(Lmid_t __nsid, const scope char* __file, int __mode);
void* dlvsym(void* __handle, const scope char* __name, const scope char* __version);
@@ -169,7 +169,7 @@ static if (__USE_GNU)
// char* dlerror(); // POSIX
-static if (__USE_GNU)
+static if (_GNU_SOURCE)
{
int dladdr1(void* __address, Dl_info* __info, void** __extra_info, int __flags);
diff --git a/libphobos/libdruntime/core/sys/linux/errno.d b/libphobos/libdruntime/core/sys/linux/errno.d
index 02ae151..d7a39ac 100644
--- a/libphobos/libdruntime/core/sys/linux/errno.d
+++ b/libphobos/libdruntime/core/sys/linux/errno.d
@@ -13,7 +13,7 @@ nothrow:
public import core.stdc.errno;
import core.sys.linux.config;
-static if (__USE_GNU)
+static if (_GNU_SOURCE)
{
extern __gshared char* program_invocation_name, program_invocation_short_name;
alias error_t = int;
diff --git a/libphobos/libdruntime/core/sys/linux/netinet/in_.d b/libphobos/libdruntime/core/sys/linux/netinet/in_.d
index 67bf654..1b428f5 100644
--- a/libphobos/libdruntime/core/sys/linux/netinet/in_.d
+++ b/libphobos/libdruntime/core/sys/linux/netinet/in_.d
@@ -115,7 +115,7 @@ version (linux_libc)
enum IN6ADDR_ANY_INIT = in6_addr.init;
enum IN6ADDR_LOOPBACK_INIT = in6_addr([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
- version (gnu_libc) static if (__USE_MISC)
+ version (gnu_libc) static if (_DEFAULT_SOURCE)
{
struct ip_mreq
{
@@ -174,13 +174,13 @@ version (linux_libc)
extern(D) bool IN6_ARE_ADDR_EQUAL(in6_addr* a, in6_addr* b) pure @safe { return *a == *b; }
- version (gnu_libc) static if (__USE_MISC)
+ version (gnu_libc) static if (_DEFAULT_SOURCE)
{
int bindresvport(int __sockfd, sockaddr_in* __sock_in);
int bindresvport6(int __sockfd, sockaddr_in6* _);
}
- version (gnu_libc) static if (__USE_GNU)
+ version (gnu_libc) static if (_GNU_SOURCE)
{
struct in6_pktinfo
{
@@ -254,7 +254,7 @@ version (linux_libc)
enum IP_DROP_SOURCE_MEMBERSHIP = 40;
enum IP_MSFILTER = 41;
- version (gnu_libc) static if (__USE_MISC)
+ version (gnu_libc) static if (_DEFAULT_SOURCE)
{
enum MCAST_JOIN_GROUP = 42;
enum MCAST_BLOCK_SOURCE = 43;
@@ -307,7 +307,7 @@ version (linux_libc)
enum IP_DEFAULT_MULTICAST_LOOP = 1;
enum IP_MAX_MEMBERSHIPS = 20;
- version (gnu_libc) static if (__USE_MISC)
+ version (gnu_libc) static if (_DEFAULT_SOURCE)
{
struct ip_opts
{
diff --git a/libphobos/libdruntime/core/sys/linux/string.d b/libphobos/libdruntime/core/sys/linux/string.d
index e3c94cf6..880faa4 100644
--- a/libphobos/libdruntime/core/sys/linux/string.d
+++ b/libphobos/libdruntime/core/sys/linux/string.d
@@ -16,7 +16,7 @@ nothrow:
@nogc:
@system:
-static if (__USE_GNU)
+static if (_GNU_SOURCE)
{
pure void* memmem(return scope const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
}
diff --git a/libphobos/libdruntime/core/sys/linux/sys/mman.d b/libphobos/libdruntime/core/sys/linux/sys/mman.d
index a6548a7..649e2af 100644
--- a/libphobos/libdruntime/core/sys/linux/sys/mman.d
+++ b/libphobos/libdruntime/core/sys/linux/sys/mman.d
@@ -37,7 +37,7 @@ version (PPC_Any)
{
enum PROT_SAO = 0x10;
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MAP_GROWSDOWN = 0x00100,
MAP_DENYWRITE = 0x00800,
@@ -60,7 +60,7 @@ version (PPC_Any)
// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/riscv/bits/mman.h
else version (RISCV_Any)
{
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MAP_GROWSDOWN = 0x00100,
MAP_DENYWRITE = 0x00800,
@@ -85,7 +85,7 @@ else version (RISCV_Any)
// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/s390/bits/mman.h
else version (IBMZ_Any)
{
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MAP_GROWSDOWN = 0x00100,
MAP_DENYWRITE = 0x00800,
@@ -101,7 +101,7 @@ else version (IBMZ_Any)
// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/sh/bits/mman.h
else version (SH)
{
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MAP_GROWSDOWN = 0x0100,
MAP_DENYWRITE = 0x0800,
@@ -117,7 +117,7 @@ else version (SH)
// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/sparc/bits/mman.h
else version (SPARC_Any)
{
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MAP_GROWSDOWN = 0x0200,
MAP_DENYWRITE = 0x0800,
@@ -141,9 +141,9 @@ else version (SPARC_Any)
// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/x86/bits/mman.h
else version (X86_Any)
{
- static if (__USE_MISC) enum MAP_32BIT = 0x40;
+ static if (_DEFAULT_SOURCE) enum MAP_32BIT = 0x40;
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MAP_GROWSDOWN = 0x00100,
MAP_DENYWRITE = 0x00800,
@@ -159,7 +159,7 @@ else version (X86_Any)
// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/aarch64/bits/mman.h
else version (AArch64)
{
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MAP_GROWSDOWN = 0x00100,
MAP_DENYWRITE = 0x00800,
@@ -187,11 +187,11 @@ else version (Alpha)
enum MAP_SHARED = 0x01;
enum MAP_PRIVATE = 0x02;
- static if (__USE_MISC)
+ static if (_DEFAULT_SOURCE)
enum MAP_TYPE = 0x0f;
enum MAP_FIXED = 0x10;
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MAP_FILE = 0,
MAP_ANONYMOUS = MAP_ANON,
@@ -201,7 +201,7 @@ else version (Alpha)
MAP_HUGE_MASK = 0x3f,
}
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MAP_GROWSDOWN = 0x01000,
MAP_DENYWRITE = 0x02000,
@@ -229,13 +229,13 @@ else version (Alpha)
// MCL_FUTURE = 16384,
// }
- static if (__USE_GNU) enum
+ static if (_GNU_SOURCE) enum
{
MREMAP_MAYMOVE = 1,
MREMAP_FIXED = 2,
}
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MADV_NORMAL = 0,
MADV_RANDOM = 1,
@@ -255,7 +255,7 @@ else version (Alpha)
}
// in core.sys.posix.sys.mman
- // static if (__USE_XOPEN2K) enum
+ // static if (_XOPEN_SOURCE >= 600) enum
// {
// POSIX_MADV_NORMAL = 0,
// POSIX_MADV_RANDOM = 1,
@@ -267,7 +267,7 @@ else version (Alpha)
// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/arm/bits/mman.h
else version (ARM)
{
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MAP_GROWSDOWN = 0x00100,
MAP_DENYWRITE = 0x00800,
@@ -295,11 +295,11 @@ else version (HPPA_Any)
enum MAP_SHARED = 0x01;
enum MAP_PRIVATE = 0x02;
- static if (__USE_MISC)
+ static if (_DEFAULT_SOURCE)
enum MAP_TYPE = 0x0f;
enum MAP_FIXED = 0x04;
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MAP_FILE = 0,
MAP_ANONYMOUS = MAP_ANON,
@@ -310,7 +310,7 @@ else version (HPPA_Any)
MAP_HUGE_MASK = 0x3f,
}
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MAP_DENYWRITE = 0x0800,
MAP_EXECUTABLE = 0x1000,
@@ -336,13 +336,13 @@ else version (HPPA_Any)
// MCL_FUTURE = 2,
// }
- static if (__USE_GNU) enum
+ static if (_GNU_SOURCE) enum
{
MREMAP_MAYMOVE = 1,
MREMAP_FIXED = 2,
}
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MADV_NORMAL = 0,
MADV_RANDOM = 1,
@@ -375,7 +375,7 @@ else version (HPPA_Any)
}
// in core.sys.posix.sys.mman
- // static if (__USE_XOPEN2K) enum
+ // static if (_XOPEN_SOURCE >= 600) enum
// {
// POSIX_MADV_NORMAL = 0,
// POSIX_MADV_RANDOM = 1,
@@ -387,7 +387,7 @@ else version (HPPA_Any)
// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/ia64/bits/mman.h
else version (IA64)
{
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MAP_GROWSDOWN = 0x00100,
MAP_GROWSUP = 0x00200,
@@ -404,7 +404,7 @@ else version (IA64)
// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/m68k/bits/mman.h
else version (M68K)
{
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MAP_GROWSDOWN = 0x00100,
MAP_DENYWRITE = 0x00800,
@@ -420,7 +420,7 @@ else version (M68K)
// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/mips/bits/mman.h
else version (MIPS_Any)
{
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MAP_NORESERVE = 0x0400,
MAP_GROWSDOWN = 0x1000,
@@ -460,11 +460,11 @@ else
enum MAP_SHARED = 0x01;
enum MAP_PRIVATE = 0x02;
- static if (__USE_MISC)
+ static if (_DEFAULT_SOURCE)
enum MAP_TYPE = 0x0f;
enum MAP_FIXED = 0x10;
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MAP_FILE = 0,
MAP_ANONYMOUS = MAP_ANON,
@@ -482,13 +482,13 @@ else
// MS_INVALIDATE = 2,
// }
- static if (__USE_GNU) enum
+ static if (_GNU_SOURCE) enum
{
MREMAP_MAYMOVE = 1,
MREMAP_FIXED = 2,
}
- static if (__USE_MISC) enum
+ static if (_DEFAULT_SOURCE) enum
{
MADV_NORMAL = 0,
MADV_RANDOM = 1,
@@ -508,7 +508,7 @@ else
}
// in core.sys.posix.sys.mman
- // static if (__USE_XOPEN2K) enum
+ // static if (_XOPEN_SOURCE >= 600) enum
// {
// POSIX_MADV_NORMAL = 0,
// POSIX_MADV_RANDOM = 1,
@@ -530,12 +530,12 @@ else
// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/sparc/bits/mman.h
version (SPARC_Any)
{
- static if (__USE_MISC) enum MAP_RENAME = MAP_ANONYMOUS;
+ static if (_DEFAULT_SOURCE) enum MAP_RENAME = MAP_ANONYMOUS;
}
// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/mips/bits/mman.h
else version (MIPS_Any)
{
- static if (__USE_MISC) enum MAP_RENAME = MAP_ANONYMOUS;
+ static if (_DEFAULT_SOURCE) enum MAP_RENAME = MAP_ANONYMOUS;
}
// http://sourceware.org/git/?p=glibc.git;a=blob;f=misc/sys/mman.h
@@ -548,14 +548,14 @@ else version (MIPS_Any)
// int munmap(void*, size_t);
// int mprotect(void *__addr, size_t __len, int __prot);
// int msync(void *__addr, size_t __len, int __flags);
-static if (__USE_MISC) int madvise(void *__addr, size_t __len, int __advice);
-// static if (__USE_XOPEN2K) int posix_madvise(void *__addr, size_t __len, int __advice);
+static if (_DEFAULT_SOURCE) int madvise(void *__addr, size_t __len, int __advice);
+// static if (_XOPEN_SOURCE >= 600) int posix_madvise(void *__addr, size_t __len, int __advice);
// int mlock(const(void) *__addr, size_t __len);
// int munlock(const(void) *__addr, size_t __len);
// int mlockall(int __flags);
// int munlockall();
-static if (__USE_MISC) int mincore(void *__start, size_t __len, ubyte *__vec);
-static if (__USE_GNU) void *mremap(void *__addr, size_t __old_len, size_t __new_len, int __flags, ...);
-static if (__USE_GNU) int remap_file_pages(void *__start, size_t __size, int __prot, size_t __pgoff, int __flags);
+static if (_DEFAULT_SOURCE) int mincore(void *__start, size_t __len, ubyte *__vec);
+static if (_GNU_SOURCE) void *mremap(void *__addr, size_t __old_len, size_t __new_len, int __flags, ...);
+static if (_GNU_SOURCE) int remap_file_pages(void *__start, size_t __size, int __prot, size_t __pgoff, int __flags);
// int shm_open(in char *__name, int __oflag, mode_t __mode);
// int shm_unlink(in char *__name);
diff --git a/libphobos/libdruntime/core/sys/posix/aio.d b/libphobos/libdruntime/core/sys/posix/aio.d
index f4e0f12..a76846e 100644
--- a/libphobos/libdruntime/core/sys/posix/aio.d
+++ b/libphobos/libdruntime/core/sys/posix/aio.d
@@ -99,57 +99,7 @@ else version (CRuntime_Musl)
}
else version (CRuntime_UClibc)
{
- import core.sys.posix.config;
- import core.sys.posix.sys.types;
-
- struct aiocb
- {
- int aio_fildes;
- int aio_lio_opcode;
- int aio_reqprio;
- void* aio_buf; //volatile
- size_t aio_nbytes;
- sigevent aio_sigevent;
-
- aiocb* __next_prio;
- int __abs_prio;
- int __policy;
- int __error_code;
- ssize_t __return_value;
-
- static if (__USE_LARGEFILE64)
- {
- off_t aio_offset;
- ubyte[off64_t.sizeof - off_t.sizeof] __pad;
- }
- else
- {
- off64_t aio_offset;
- }
- ubyte[32] __unused;
- }
-
- static if (__USE_LARGEFILE64)
- {
- struct aiocb64
- {
- int aio_fildes;
- int aio_lio_opcode;
- int aio_reqprio;
- void* aio_buf; //volatile
- size_t aio_nbytes;
- sigevent aio_sigevent;
-
- aiocb* __next_prio;
- int __abs_prio;
- int __policy;
- int __error_code;
- ssize_t __return_value;
-
- off64_t aio_offset;
- ubyte[32] __unused;
- }
- }
+ // UClibc does not implement aiocb.
}
else version (Darwin)
{
@@ -272,15 +222,6 @@ else version (CRuntime_Musl)
AIO_ALLDONE
}
}
-else version (CRuntime_UClibc)
-{
- enum
- {
- AIO_CANCELED,
- AIO_NOTCANCELED,
- AIO_ALLDONE
- }
-}
else version (Darwin)
{
enum
@@ -328,15 +269,6 @@ else version (CRuntime_Musl)
LIO_NOP
}
}
-else version (CRuntime_UClibc)
-{
- enum
- {
- LIO_READ,
- LIO_WRITE,
- LIO_NOP
- }
-}
else version (Darwin)
{
enum
@@ -382,14 +314,6 @@ else version (CRuntime_Musl)
LIO_NOWAIT
}
}
-else version (CRuntime_UClibc)
-{
- enum
- {
- LIO_WAIT,
- LIO_NOWAIT
- }
-}
else version (Darwin)
{
enum
@@ -456,37 +380,7 @@ else version (CRuntime_Bionic)
}
else version (CRuntime_UClibc)
{
- static if (__USE_LARGEFILE64)
- {
- int aio_read64(aiocb64* aiocbp);
- int aio_write64(aiocb64* aiocbp);
- int aio_fsync64(int op, aiocb64* aiocbp);
- int aio_error64(const(aiocb64)* aiocbp);
- ssize_t aio_return64(aiocb64* aiocbp);
- int aio_suspend64(const(aiocb64*)* aiocb_list, int nitems, const(timespec)* timeout);
- int aio_cancel64(int fd, aiocb64* aiocbp);
- int lio_listio64(int mode, const(aiocb64*)* aiocb_list, int nitems, sigevent* sevp);
-
- alias aio_read = aio_read64;
- alias aio_write = aio_write64;
- alias aio_fsync = aio_fsync64;
- alias aio_error = aio_error64;
- alias aio_return = aio_return64;
- alias aio_suspend = aio_suspend64;
- alias aio_cancel = aio_cancel64;
- alias lio_listio = lio_listio64;
- }
- else
- {
- int aio_read(aiocb* aiocbp);
- int aio_write(aiocb* aiocbp);
- int aio_fsync(int op, aiocb* aiocbp);
- int aio_error(const(aiocb)* aiocbp);
- ssize_t aio_return(aiocb* aiocbp);
- 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);
- }
+ // UClibc does not implement aio.h
}
else version (OpenBSD)
{
@@ -507,27 +401,7 @@ else
/* Functions outside/extending POSIX requirement. */
version (CRuntime_Glibc)
{
- static if (__USE_GNU)
- {
- /* To customize the implementation one can use the following struct. */
- struct aioinit
- {
- int aio_threads;
- int aio_num;
- int aio_locks;
- int aio_usedba;
- int aio_debug;
- int aio_numusers;
- int aio_idle_time;
- int aio_reserved;
- }
-
- void aio_init(const(aioinit)* init);
- }
-}
-else version (CRuntime_UClibc)
-{
- static if (__USE_GNU)
+ static if (_GNU_SOURCE)
{
/* To customize the implementation one can use the following struct. */
struct aioinit
diff --git a/libphobos/libdruntime/core/sys/posix/config.d b/libphobos/libdruntime/core/sys/posix/config.d
index 3b575fa..7bd0722 100644
--- a/libphobos/libdruntime/core/sys/posix/config.d
+++ b/libphobos/libdruntime/core/sys/posix/config.d
@@ -51,14 +51,24 @@ version (CRuntime_Glibc)
enum __USE_LARGEFILE = __USE_FILE_OFFSET64 && !__REDIRECT;
enum __USE_LARGEFILE64 = __USE_FILE_OFFSET64 && !__REDIRECT;
- enum __USE_XOPEN2K = _XOPEN_SOURCE >= 600;
- enum __USE_XOPEN2KXSI = _XOPEN_SOURCE >= 600;
- enum __USE_XOPEN2K8 = _XOPEN_SOURCE >= 700;
- enum __USE_XOPEN2K8XSI = _XOPEN_SOURCE >= 700;
+ deprecated("use _XOPEN_SOURCE >= 600")
+ {
+ enum __USE_XOPEN2K = _XOPEN_SOURCE >= 600;
+ enum __USE_XOPEN2KXSI = _XOPEN_SOURCE >= 600;
+ }
+ deprecated("use _XOPEN_SOURCE >= 700")
+ {
+ enum __USE_XOPEN2K8 = _XOPEN_SOURCE >= 700;
+ enum __USE_XOPEN2K8XSI = _XOPEN_SOURCE >= 700;
+ }
+ deprecated("use _DEFAULT_SOURCE")
enum __USE_MISC = _DEFAULT_SOURCE;
+ deprecated("use _ATFILE_SOURCE")
enum __USE_ATFILE = _ATFILE_SOURCE;
+ deprecated("use _GNU_SOURCE")
enum __USE_GNU = _GNU_SOURCE;
+ deprecated("use _REENTRANT")
enum __USE_REENTRANT = _REENTRANT;
version (D_LP64)
@@ -68,6 +78,10 @@ version (CRuntime_Glibc)
}
else version (CRuntime_Musl)
{
+ enum _GNU_SOURCE = false;
+ enum _DEFAULT_SOURCE = false;
+ enum _ATFILE_SOURCE = false;
+
// off_t is always 64 bits on Musl
enum _FILE_OFFSET_BITS = 64;
@@ -99,14 +113,24 @@ else version (CRuntime_UClibc)
enum __USE_LARGEFILE = __USE_FILE_OFFSET64 && !__REDIRECT;
enum __USE_LARGEFILE64 = __USE_FILE_OFFSET64 && !__REDIRECT;
- enum __USE_XOPEN2K = _XOPEN_SOURCE >= 600;
- enum __USE_XOPEN2KXSI = _XOPEN_SOURCE >= 600;
- enum __USE_XOPEN2K8 = _XOPEN_SOURCE >= 700;
- enum __USE_XOPEN2K8XSI = _XOPEN_SOURCE >= 700;
+ deprecated("use _XOPEN_SOURCE >= 600")
+ {
+ enum __USE_XOPEN2K = _XOPEN_SOURCE >= 600;
+ enum __USE_XOPEN2KXSI = _XOPEN_SOURCE >= 600;
+ }
+ deprecated("use _XOPEN_SOURCE >= 700")
+ {
+ enum __USE_XOPEN2K8 = _XOPEN_SOURCE >= 700;
+ enum __USE_XOPEN2K8XSI = _XOPEN_SOURCE >= 700;
+ }
+ deprecated("use _DEFAULT_SOURCE")
enum __USE_MISC = _DEFAULT_SOURCE;
+ deprecated("use _ATFILE_SOURCE")
enum __USE_ATFILE = _ATFILE_SOURCE;
+ deprecated("use _GNU_SOURCE")
enum __USE_GNU = _GNU_SOURCE;
+ deprecated("use _REENTRANT")
enum __USE_REENTRANT = _REENTRANT;
version (D_LP64)
@@ -117,7 +141,11 @@ else version (CRuntime_UClibc)
else version (CRuntime_Bionic)
{
enum _GNU_SOURCE = false;
+ enum _DEFAULT_SOURCE = false;
+ enum _ATFILE_SOURCE = false;
+
enum __USE_FILE_OFFSET64 = false; // see https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md
+ deprecated("use _GNU_SOURCE")
enum __USE_GNU = _GNU_SOURCE;
version (D_LP64)
@@ -187,10 +215,16 @@ else version (Solaris)
enum __USE_LARGEFILE = __USE_FILE_OFFSET64 && !__REDIRECT;
enum __USE_LARGEFILE64 = __USE_FILE_OFFSET64 && !__REDIRECT;
- enum __USE_XOPEN2K = _XOPEN_SOURCE >= 600;
- enum __USE_XOPEN2KXSI = _XOPEN_SOURCE >= 600;
- enum __USE_XOPEN2K8 = _XOPEN_SOURCE >= 700;
- enum __USE_XOPEN2K8XSI = _XOPEN_SOURCE >= 700;
+ deprecated("use _XOPEN_SOURCE >= 600")
+ {
+ enum __USE_XOPEN2K = _XOPEN_SOURCE >= 600;
+ enum __USE_XOPEN2KXSI = _XOPEN_SOURCE >= 600;
+ }
+ deprecated("use _XOPEN_SOURCE >= 700")
+ {
+ enum __USE_XOPEN2K8 = _XOPEN_SOURCE >= 700;
+ enum __USE_XOPEN2K8XSI = _XOPEN_SOURCE >= 700;
+ }
version (D_LP64)
enum __WORDSIZE = 64;
diff --git a/libphobos/libdruntime/core/sys/posix/spawn.d b/libphobos/libdruntime/core/sys/posix/spawn.d
index 86b1751..cfa3a40 100644
--- a/libphobos/libdruntime/core/sys/posix/spawn.d
+++ b/libphobos/libdruntime/core/sys/posix/spawn.d
@@ -100,8 +100,8 @@ version (linux)
POSIX_SPAWN_SETSCHEDPARAM = 0x10,
POSIX_SPAWN_SETSCHEDULER = 0x20
}
- import core.sys.posix.config : __USE_GNU;
- static if (__USE_GNU)
+ import core.sys.posix.config : _GNU_SOURCE;
+ static if (_GNU_SOURCE)
{
enum
{
@@ -140,8 +140,8 @@ version (linux)
POSIX_SPAWN_SETSCHEDPARAM = 16,
POSIX_SPAWN_SETSCHEDULER = 32
}
- import core.sys.posix.config : __USE_GNU;
- static if (__USE_GNU)
+ import core.sys.posix.config : _GNU_SOURCE;
+ static if (_GNU_SOURCE)
{
enum
{
@@ -196,8 +196,8 @@ version (linux)
POSIX_SPAWN_SETSCHEDPARAM = 0x10,
POSIX_SPAWN_SETSCHEDULER = 0x20
}
- import core.sys.posix.config : __USE_GNU;
- static if (__USE_GNU)
+ import core.sys.posix.config : _GNU_SOURCE;
+ static if (_GNU_SOURCE)
{
enum
{
diff --git a/libphobos/libdruntime/core/sys/posix/sys/ipc.d b/libphobos/libdruntime/core/sys/posix/sys/ipc.d
index 18a6cbd..1718243 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/ipc.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/ipc.d
@@ -83,7 +83,26 @@ version (linux)
}
else version (Darwin)
{
+ align(4) struct ipc_perm
+ {
+ uid_t uid;
+ gid_t gid;
+ uid_t cuid;
+ gid_t cgid;
+ mode_t mode;
+ ushort _seq;
+ key_t _key;
+ }
+
+ enum IPC_CREAT = 0x0200; // 01000
+ enum IPC_EXCL = 0x0400; // 02000
+ enum IPC_NOWAIT = 0x0800; // 04000
+
+ enum key_t IPC_PRIVATE = 0;
+ enum IPC_RMID = 0;
+ enum IPC_SET = 1;
+ enum IPC_STAT = 2;
}
else version (FreeBSD)
{
@@ -188,6 +207,46 @@ else version (DragonFlyBSD)
enum IPC_SET = 1;
enum IPC_STAT = 2;
}
+else version (Solaris)
+{
+ version (D_LP64)
+ {
+ struct ipc_perm
+ {
+ uid_t uid;
+ gid_t gid;
+ uid_t cuid;
+ gid_t cgid;
+ mode_t mode;
+ uint seq;
+ key_t key;
+ }
+ }
+ else
+ {
+ struct ipc_perm
+ {
+ uid_t uid;
+ gid_t gid;
+ uid_t cuid;
+ gid_t cgid;
+ mode_t mode;
+ uint seq;
+ key_t key;
+ int[4] pad;
+ }
+ }
+
+ enum IPC_CREAT = 0x200;
+ enum IPC_EXCL = 0x400;
+ enum IPC_NOWAIT = 0x800;
+
+ enum key_t IPC_PRIVATE = 0;
+
+ enum IPC_RMID = 10;
+ enum IPC_SET = 11;
+ enum IPC_STAT = 12;
+}
else
{
static assert(false, "Unsupported platform");
@@ -203,7 +262,7 @@ version (CRuntime_Glibc)
}
else version (Darwin)
{
-
+ key_t ftok(const scope char*, int);
}
else version (FreeBSD)
{
@@ -221,6 +280,10 @@ else version (DragonFlyBSD)
{
key_t ftok(const scope char*, int);
}
+else version (Solaris)
+{
+ key_t ftok(const scope char*, int);
+}
else version (CRuntime_Bionic)
{
key_t ftok(const scope char*, int);
diff --git a/libphobos/libdruntime/core/sys/posix/sys/mman.d b/libphobos/libdruntime/core/sys/posix/sys/mman.d
index 33ce88f..430f215 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/mman.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/mman.d
@@ -56,7 +56,7 @@ int posix_madvise(void*, size_t, int);
version (CRuntime_Glibc)
{
- static if (__USE_XOPEN2K)
+ static if (_XOPEN_SOURCE >= 600)
{
int posix_madvise(void *__addr, size_t __len, int __advice);
}
@@ -303,7 +303,7 @@ else version (CRuntime_Musl)
}
else version (CRuntime_UClibc)
{
- static if (__USE_LARGEFILE64) void* mmap64(void*, size_t, int, int, int, off64_t);
+ static if (__USE_LARGEFILE64) void* mmap64(void*, size_t, int, int, int, off_t);
static if (__USE_FILE_OFFSET64)
alias mmap = mmap64;
else
diff --git a/libphobos/libdruntime/core/sys/posix/sys/shm.d b/libphobos/libdruntime/core/sys/posix/sys/shm.d
index ce34141..d04e792 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/shm.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/shm.d
@@ -259,6 +259,18 @@ else version (CRuntime_Musl)
int shmdt(const scope void*);
int shmget(key_t, size_t, int);
}
+else version (CRuntime_Bionic)
+{
+ enum SHMLBA = 4096;
+
+ deprecated("Not useful on Android because it's disallowed by SELinux")
+ {
+ void* shmat(int, const scope void*, int);
+ int shmctl(int, int, shmid_ds*);
+ int shmdt(const scope void*);
+ int shmget(key_t, size_t, int);
+ }
+}
else version (CRuntime_UClibc)
{
int __getpagesize();
diff --git a/libphobos/libdruntime/core/sys/posix/sys/socket.d b/libphobos/libdruntime/core/sys/posix/sys/socket.d
index 670ead7..c1309a6 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/socket.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/socket.d
@@ -1038,9 +1038,9 @@ else version (OpenBSD)
{
ubyte ss_len;
sa_family_t ss_family;
- byte[6] __ss_pad1;
+ ubyte[6] __ss_pad1;
long __ss_align;
- byte[240] __ss_pad2;
+ ubyte[240] __ss_pad2;
}
struct msghdr
@@ -1063,20 +1063,25 @@ else version (OpenBSD)
enum : uint
{
- SCM_RIGHTS = 0x01
+ SCM_RIGHTS = 0x01,
+ SCM_TIMESTAMP = 0x04
}
private // <sys/_types.h>
{
- extern (D) size_t _ALIGN(size_t p) { return (p + _ALIGNBYTES) & ~_ALIGNBYTES; }
+ enum _ALIGNBYTES = c_long.sizeof - 1;
+ extern (D) size_t _ALIGN(size_t p) pure nothrow @nogc
+ {
+ return (p + _ALIGNBYTES) & ~_ALIGNBYTES;
+ }
}
- extern (D) ubyte* CMSG_DATA(cmsghdr* cmsg)
+ extern (D) ubyte* CMSG_DATA(cmsghdr* cmsg) pure nothrow @nogc
{
return cast(ubyte*) cmsg + _ALIGN(cmsghdr.sizeof);
}
- extern (D) cmsghdr* CMSG_NXTHDR(msghdr* mhdr, cmsghdr* cmsg)
+ extern (D) cmsghdr* CMSG_NXTHDR(msghdr* mhdr, cmsghdr* cmsg) pure nothrow @nogc
{
if (cast(ubyte*) cmsg + _ALIGN(cmsg.cmsg_len) + _ALIGN(cmsghdr.sizeof) >
cast(ubyte*) mhdr.msg_control + mhdr.msg_controllen)
@@ -1085,11 +1090,24 @@ else version (OpenBSD)
return cast(cmsghdr*) (cast(ubyte*) cmsg + _ALIGN(cmsg.cmsg_len));
}
- extern (D) cmsghdr* CMSG_FIRSTHDR(msghdr* mhdr)
+ extern (D) cmsghdr* CMSG_FIRSTHDR(msghdr* mhdr) pure nothrow @nogc
{
return mhdr.msg_controllen >= cmsghdr.sizeof ? cast(cmsghdr*) mhdr.msg_control : null;
}
+ extern (D)
+ {
+ size_t CMSG_LEN(size_t len) pure nothrow @nogc
+ {
+ return _ALIGN(cmsghdr.sizeof) + len;
+ }
+ }
+
+ extern (D) size_t CMSG_SPACE(size_t len) pure nothrow @nogc
+ {
+ return _ALIGN(cmsghdr.sizeof) + _ALIGN(len);
+ }
+
struct linger
{
int l_onoff;
diff --git a/libphobos/libdruntime/core/sys/posix/sys/stat.d b/libphobos/libdruntime/core/sys/posix/sys/stat.d
index 51455a9..22f4df6 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/stat.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/stat.d
@@ -89,7 +89,7 @@ version (linux)
off_t st_size;
blksize_t st_blksize;
blkcnt_t st_blocks;
- static if (__USE_MISC || __USE_XOPEN2K8)
+ static if (_DEFAULT_SOURCE || _XOPEN_SOURCE >= 700)
{
timespec st_atim;
timespec st_mtim;
@@ -136,7 +136,7 @@ version (linux)
off_t st_size;
blksize_t st_blksize;
blkcnt_t st_blocks;
- static if (__USE_MISC || __USE_XOPEN2K8)
+ static if (_DEFAULT_SOURCE || _XOPEN_SOURCE >= 700)
{
timespec st_atim;
timespec st_mtim;
@@ -218,7 +218,7 @@ version (linux)
__blkcnt64_t st_blocks;
}
- static if ( __USE_MISC || __USE_XOPEN2K8)
+ static if ( _DEFAULT_SOURCE || _XOPEN_SOURCE >= 700)
{
__timespec st_atim;
__timespec st_mtim;
@@ -278,7 +278,7 @@ version (linux)
c_long[3] st_pad2;
off_t st_size;
}
- static if (__USE_MISC || __USE_XOPEN2K8)
+ static if (_DEFAULT_SOURCE || _XOPEN_SOURCE >= 700)
{
timespec st_atim;
timespec st_mtim;
@@ -339,7 +339,7 @@ version (linux)
uint[3] st_pad2;
off_t st_size;
}
- static if (__USE_MISC || __USE_XOPEN2K8)
+ static if (_DEFAULT_SOURCE || _XOPEN_SOURCE >= 700)
{
timespec st_atim;
timespec st_mtim;
@@ -491,7 +491,7 @@ version (linux)
__blkcnt_t st_blocks;
}
- static if (__USE_MISC)
+ static if (_DEFAULT_SOURCE)
{
__timespec st_atim;
__timespec st_mtim;
@@ -573,7 +573,7 @@ version (linux)
__blkcnt64_t st_blocks;
}
- static if ( __USE_MISC || __USE_XOPEN2K8)
+ static if ( _DEFAULT_SOURCE || _XOPEN_SOURCE >= 700)
{
__timespec st_atim;
__timespec st_mtim;
@@ -668,7 +668,7 @@ version (linux)
__blkcnt64_t st_blocks;
}
- static if (__USE_MISC)
+ static if (_DEFAULT_SOURCE)
{
__timespec st_atim;
__timespec st_mtim;
@@ -753,7 +753,7 @@ version (linux)
__blkcnt64_t st_blocks;
}
- static if (__USE_XOPEN2K8)
+ static if (_XOPEN_SOURCE >= 700)
{
__timespec st_atim;
__timespec st_mtim;
@@ -830,7 +830,7 @@ version (linux)
__blkcnt_t st_blocks;
else
__blkcnt64_t st_blocks;
- static if (__USE_XOPEN2K8)
+ static if (_XOPEN_SOURCE >= 700)
{
__timespec st_atim;
__timespec st_mtim;
@@ -894,7 +894,7 @@ version (linux)
int __glibc_reserved0;
__dev_t st_rdev;
__off_t st_size;
- static if (__USE_XOPEN2K8)
+ static if (_XOPEN_SOURCE >= 700)
{
__timespec st_atim;
__timespec st_mtim;
@@ -919,7 +919,7 @@ version (linux)
__blkcnt_t st_blocks;
c_long[3] __glibc_reserved;
}
- static if (__USE_XOPEN2K8)
+ static if (_XOPEN_SOURCE >= 700)
static assert(stat_t.sizeof == 144);
else
static assert(stat_t.sizeof == 144);
diff --git a/libphobos/libdruntime/core/sys/posix/sys/statvfs.d b/libphobos/libdruntime/core/sys/posix/sys/statvfs.d
index 49c8450..df9030d 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/statvfs.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/statvfs.d
@@ -44,7 +44,7 @@ version (CRuntime_Glibc) {
}
/* Definitions for the flag in `f_flag'. These definitions should be
kept in sync with the definitions in <sys/mount.h>. */
- static if (__USE_GNU)
+ static if (_GNU_SOURCE)
{
enum FFlag
{
diff --git a/libphobos/libdruntime/core/sys/posix/sys/types.d b/libphobos/libdruntime/core/sys/posix/sys/types.d
index 02cf799..ec229dd 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/types.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/types.d
@@ -322,7 +322,7 @@ else version (Darwin)
alias uint fsfilcnt_t;
alias c_long clock_t;
alias uint id_t;
- // key_t
+ alias int key_t;
alias int suseconds_t;
alias uint useconds_t;
}
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index 7bb6bec..cf7cf96 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -1885,8 +1885,8 @@ class TypeInfo_Struct : TypeInfo
return false;
else if (xopEquals)
{
- const dg = _memberFunc(p2, xopEquals);
- return dg.xopEquals(p1);
+ const dg = _memberFunc(p1, xopEquals);
+ return dg.xopEquals(p2);
}
else if (p1 == p2)
return true;
diff --git a/libphobos/libdruntime/rt/util/typeinfo.d b/libphobos/libdruntime/rt/util/typeinfo.d
index 26c24c4..7b55693 100644
--- a/libphobos/libdruntime/rt/util/typeinfo.d
+++ b/libphobos/libdruntime/rt/util/typeinfo.d
@@ -1,8 +1,8 @@
/**
- * This module contains utilities for TypeInfo implementation.
+ * A few predefined implementations for primitive types and arrays thereof. Also a couple of helpers.
*
* Copyright: Copyright Kenji Hara 2014-.
- * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
+ * License: <a href="https://boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
* Authors: Kenji Hara
* Source: $(DRUNTIMESRC rt/util/_typeinfo.d)
*/
@@ -10,100 +10,74 @@ module rt.util.typeinfo;
import rt.util.utility : d_cfloat, d_cdouble, d_creal, isComplex;
static import core.internal.hash;
-template Floating(T)
-if (is(T == float) || is(T == double) || is(T == real))
+// Three-way compare for integrals: negative if `lhs < rhs`, positive if `lhs > rhs`, 0 otherwise.
+pragma(inline, true)
+private int cmp3(T)(const T lhs, const T rhs)
+if (__traits(isIntegral, T))
{
- pure nothrow @safe:
-
- bool equals(T f1, T f2)
- {
- return f1 == f2;
- }
-
- int compare(T d1, T d2)
- {
- if (d1 != d1 || d2 != d2) // if either are NaN
- {
- if (d1 != d1)
- {
- if (d2 != d2)
- return 0;
- return -1;
- }
- return 1;
- }
- return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
- }
+ static if (T.sizeof < int.sizeof)
+ // Taking the difference will always fit in an int.
+ return int(lhs) - int(rhs);
+ else
+ return (lhs > rhs) - (lhs < rhs);
+}
- public alias hashOf = core.internal.hash.hashOf;
+// Three-way compare for real fp types. NaN is smaller than all valid numbers.
+// Code is small and fast, see https://godbolt.org/z/fzb877
+pragma(inline, true)
+private int cmp3(T)(const T d1, const T d2)
+if (is(T == float) || is(T == double) || is(T == real))
+{
+ if (d2 != d2)
+ return d1 == d1; // 0 if both ar NaN, 1 if d1 is valid and d2 is NaN.
+ // If d1 is NaN, both comparisons are false so we get -1, as needed.
+ return (d1 > d2) - !(d1 >= d2);
}
-// @@@DEPRECATED_2.105@@@
-template Floating(T)
+// Three-way compare for complex types.
+pragma(inline, true)
+private int cmp3(T)(const T f1, const T f2)
if (isComplex!T)
{
- pure nothrow @safe:
-
- bool equals(T f1, T f2)
- {
- return f1.re == f2.re && f1.im == f2.im;
- }
-
- int compare(T f1, T f2)
- {
- int result;
-
- if (f1.re < f2.re)
- result = -1;
- else if (f1.re > f2.re)
- result = 1;
- else if (f1.im < f2.im)
- result = -1;
- else if (f1.im > f2.im)
- result = 1;
- else
- result = 0;
+ if (int result = cmp3(f1.re, f2.re))
return result;
- }
-
- size_t hashOf(scope const T val)
- {
- return core.internal.hash.hashOf(val.re, core.internal.hash.hashOf(val.im));
- }
+ return cmp3(f1.im, f2.im);
}
-template Array(T)
-if (is(T == float) || is(T == double) || is(T == real))
+unittest
{
- pure nothrow @safe:
-
- bool equals(T[] s1, T[] s2)
- {
- size_t len = s1.length;
- if (len != s2.length)
- return false;
- for (size_t u = 0; u < len; u++)
- {
- if (!Floating!T.equals(s1[u], s2[u]))
- return false;
- }
- return true;
- }
-
- int compare(T[] s1, T[] s2)
- {
- size_t len = s1.length;
- if (s2.length < len)
- len = s2.length;
- for (size_t u = 0; u < len; u++)
- {
- if (int c = Floating!T.compare(s1[u], s2[u]))
- return c;
- }
- return (s1.length > s2.length) - (s1.length < s2.length);
- }
-
- public alias hashOf = core.internal.hash.hashOf;
+ assert(cmp3(short.max, short.min) > 0);
+ assert(cmp3(42, 42) == 0);
+ assert(cmp3(int.max, int.min) > 0);
+
+ double x, y;
+ assert(cmp3(x, y) == 0);
+ assert(cmp3(y, x) == 0);
+ x = 42;
+ assert(cmp3(x, y) > 0);
+ assert(cmp3(y, x) < 0);
+ y = 43;
+ assert(cmp3(x, y) < 0);
+ assert(cmp3(y, x) > 0);
+ y = 42;
+ assert(cmp3(x, y) == 0);
+ assert(cmp3(y, x) == 0);
+
+ d_cdouble u, v;
+ assert(cmp3(u, v) == 0);
+ assert(cmp3(v, u) == 0);
+ u = d_cdouble(42, 42);
+ assert(cmp3(u, v) > 0);
+ assert(cmp3(v, u) < 0);
+ v = d_cdouble(43, 42);
+ assert(cmp3(u, v) < 0);
+ assert(cmp3(v, u) > 0);
+ v = d_cdouble(42, 43);
+ assert(cmp3(u, v) < 0);
+ assert(cmp3(v, u) > 0);
+ v = d_cdouble(42, 42);
+ assert(cmp3(u, v) == 0);
+ assert(cmp3(v, u) == 0);
}
// @@@DEPRECATED_2.105@@@
@@ -209,7 +183,7 @@ unittest
}();
}
-// Reduces to `T` if `cond` is `true` or `U` otherwise.
+// Reduces to `T` if `cond` is `true` or `U` otherwise. Consider moving elsewhere if useful.
private template Select(bool cond, T, U)
{
static if (cond) alias Select = T;
@@ -238,57 +212,38 @@ if (T.sizeof == Base.sizeof && T.alignof == Base.alignof)
static if (is(T == Base))
override size_t getHash(scope const void* p)
{
- static if (__traits(isFloating, T) || isComplex!T)
- return Floating!T.hashOf(*cast(T*)p);
- else
- return hashOf(*cast(const T *)p);
+ return hashOf(*cast(const T *)p);
}
// `equals` is the same for `Base` and `T`, introduce it just once.
static if (is(T == Base))
override bool equals(in void* p1, in void* p2)
{
- static if (__traits(isFloating, T) || isComplex!T)
- return Floating!T.equals(*cast(T*)p1, *cast(T*)p2);
- else
- return *cast(T *)p1 == *cast(T *)p2;
+ return *cast(const T *)p1 == *cast(const T *)p2;
}
// `T` and `Base` may have different signedness, so this function is introduced conditionally.
static if (is(T == Base) || (__traits(isIntegral, T) && T.max != Base.max))
override int compare(in void* p1, in void* p2)
{
- static if (__traits(isFloating, T) || isComplex!T)
- {
- return Floating!T.compare(*cast(T*)p1, *cast(T*)p2);
- }
- else static if (T.sizeof < int.sizeof)
- {
- // Taking the difference will always fit in an int.
- return int(*cast(T *) p1) - int(*cast(T *) p2);
- }
- else
- {
- auto lhs = *cast(T *) p1, rhs = *cast(T *) p2;
- return (lhs > rhs) - (lhs < rhs);
- }
+ return cmp3(*cast(const T*) p1, *cast(const T*) p2);
}
static if (is(T == Base))
- override @property size_t tsize() nothrow pure
+ override @property size_t tsize()
{
return T.sizeof;
}
static if (is(T == Base))
- override @property size_t talign() nothrow pure
+ override @property size_t talign()
{
return T.alignof;
}
// Override initializer only if necessary.
static if (is(T == Base) || T.init != Base.init)
- override const(void)[] initializer() @trusted
+ override const(void)[] initializer()
{
static if (__traits(isZeroInit, T))
{
@@ -311,7 +266,7 @@ if (T.sizeof == Base.sizeof && T.alignof == Base.alignof)
}
static if (is(T == Base) || RTInfo!T != RTInfo!Base)
- override @property immutable(void)* rtInfo() nothrow pure const @safe
+ override @property immutable(void)* rtInfo()
{
return RTInfo!T;
}
@@ -377,52 +332,33 @@ private class TypeInfoArrayGeneric(T, Base = T) : Select!(is(T == Base), TypeInf
static if (is(T == Base))
override size_t getHash(scope const void* p) @trusted const
{
- static if (__traits(isFloating, T) || isComplex!T)
- return Array!T.hashOf(*cast(T[]*)p);
- else
- return hashOf(*cast(const T[]*) p);
+ return hashOf(*cast(const T[]*) p);
}
static if (is(T == Base))
override bool equals(in void* p1, in void* p2) const
{
- static if (__traits(isFloating, T) || isComplex!T)
- {
- return Array!T.equals(*cast(T[]*)p1, *cast(T[]*)p2);
- }
- else
- {
- import core.stdc.string;
- auto s1 = *cast(T[]*)p1;
- auto s2 = *cast(T[]*)p2;
- return s1.length == s2.length &&
- memcmp(s1.ptr, s2.ptr, s1.length) == 0;
- }
+ // Just reuse the builtin.
+ return *cast(const(T)[]*) p1 == *cast(const(T)[]*) p2;
}
static if (is(T == Base) || (__traits(isIntegral, T) && T.max != Base.max))
override int compare(in void* p1, in void* p2) const
{
- static if (__traits(isFloating, T) || isComplex!T)
- {
- return Array!T.compare(*cast(T[]*)p1, *cast(T[]*)p2);
- }
- else
+ // Can't reuse __cmp in object.d because that handles NaN differently.
+ // (Q: would it make sense to unify behaviors?)
+ // return __cmp(*cast(const T[]*) p1, *cast(const T[]*) p2);
+ auto lhs = *cast(const T[]*) p1;
+ auto rhs = *cast(const T[]*) p2;
+ size_t len = lhs.length;
+ if (rhs.length < len)
+ len = rhs.length;
+ for (size_t u = 0; u < len; u++)
{
- auto s1 = *cast(T[]*)p1;
- auto s2 = *cast(T[]*)p2;
- auto len = s1.length;
-
- if (s2.length < len)
- len = s2.length;
- for (size_t u = 0; u < len; u++)
- {
- if (int result = (s1[u] > s2[u]) - (s1[u] < s2[u]))
- return result;
- }
- return (s1.length > s2.length) - (s1.length < s2.length);
+ if (int result = cmp3(lhs.ptr[u], rhs.ptr[u]))
+ return result;
}
- }
+ return cmp3(lhs.length, rhs.length); }
override @property inout(TypeInfo) next() inout
{
@@ -692,52 +628,37 @@ unittest
// typeof(null)
class TypeInfo_n : TypeInfo
{
- override string toString() const @safe { return "typeof(null)"; }
+ const: pure: @nogc: nothrow: @safe:
- override size_t getHash(scope const void* p) const
- {
- return 0;
- }
+ override string toString() { return "typeof(null)"; }
- override bool equals(in void* p1, in void* p2) const @trusted
- {
- return true;
- }
+ override size_t getHash(scope const void*) { return 0; }
- override int compare(in void* p1, in void* p2) const @trusted
- {
- return 0;
- }
+ override bool equals(in void*, in void*) { return true; }
- override @property size_t tsize() const
- {
- return typeof(null).sizeof;
- }
+ override int compare(in void*, in void*) { return 0; }
- override const(void)[] initializer() const @trusted
- {
- __gshared immutable void[typeof(null).sizeof] init;
- return init;
- }
+ override @property size_t tsize() { return typeof(null).sizeof; }
- override void swap(void *p1, void *p2) const @trusted
- {
- }
+ override const(void)[] initializer() @trusted { return (cast(void *)null)[0 .. size_t.sizeof]; }
- override @property immutable(void)* rtInfo() nothrow pure const @safe { return rtinfoNoPointers; }
+ override void swap(void*, void*) {}
- unittest
+ override @property immutable(void)* rtInfo() { return rtinfoNoPointers; }
+}
+
+unittest
+{
+ with (typeid(typeof(null)))
{
- with (typeid(typeof(null)))
- {
- assert(toString == "typeof(null)");
- assert(getHash(null) == 0);
- assert(equals(null, null));
- assert(compare(null, null) == 0);
- assert(tsize == typeof(null).sizeof);
- assert(initializer == new ubyte[(void*).sizeof]);
- assert(rtInfo == rtinfoNoPointers);
- }
+ assert(toString == "typeof(null)");
+ assert(getHash(null) == 0);
+ assert(equals(null, null));
+ assert(compare(null, null) == 0);
+ assert(tsize == typeof(null).sizeof);
+ assert(initializer.ptr is null);
+ assert(initializer.length == typeof(null).sizeof);
+ assert(rtInfo == rtinfoNoPointers);
}
}
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index 2babfbe..b5b939f 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@
-896b1d0e1e8b69bccac0e180ecd1b42a70f95d5b
+1a3e80ec25afab6123cdcfe20186f36f006b68bb
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.
diff --git a/libphobos/src/std/algorithm/internal.d b/libphobos/src/std/algorithm/internal.d
index 3caeefeb..6b45599 100644
--- a/libphobos/src/std/algorithm/internal.d
+++ b/libphobos/src/std/algorithm/internal.d
@@ -62,4 +62,6 @@ version (StdUnittest)
}
}
+// Used instead of `&object.member` when `member` may be
+// either a field or a @property function.
package(std) T* addressOf(T)(ref T val) { return &val; }
diff --git a/libphobos/src/std/bigint.d b/libphobos/src/std/bigint.d
index bbb55c2..b2fcc071 100644
--- a/libphobos/src/std/bigint.d
+++ b/libphobos/src/std/bigint.d
@@ -414,17 +414,17 @@ public:
/**
* Implements assignment operators of the form `BigInt op= BigInt`.
*/
- BigInt opOpAssign(string op, T)(T y) pure nothrow @safe scope return
+ BigInt opOpAssign(string op, T)(T y) pure nothrow @safe return scope
if ((op=="+" || op== "-" || op=="*" || op=="|" || op=="&" || op=="^" || op=="/" || op=="%")
&& is (T: BigInt))
{
static if (op == "+")
{
- data = BigUint.addOrSub(data, y.data, sign != y.sign, &sign);
+ data = BigUint.addOrSub(data, y.data, sign != y.sign, sign);
}
else static if (op == "-")
{
- data = BigUint.addOrSub(data, y.data, sign == y.sign, &sign);
+ data = BigUint.addOrSub(data, y.data, sign == y.sign, sign);
}
else static if (op == "*")
{
@@ -2244,7 +2244,7 @@ void divMod(const BigInt dividend, const BigInt divisor, out BigInt quotient, ou
BigUint.divMod(dividend.data, divisor.data, q, r);
quotient.sign = dividend.sign != divisor.sign;
quotient.data = q;
- remainder.sign = dividend.sign;
+ remainder.sign = r.isZero() ? false : dividend.sign;
remainder.data = r;
}
@@ -2291,6 +2291,14 @@ void divMod(const BigInt dividend, const BigInt divisor, out BigInt quotient, ou
assert(q * d + r == -c);
}
+// https://issues.dlang.org/show_bug.cgi?id=22771
+@safe pure nothrow unittest
+{
+ BigInt quotient, remainder;
+ divMod(BigInt(-50), BigInt(1), quotient, remainder);
+ assert(remainder == 0);
+}
+
// https://issues.dlang.org/show_bug.cgi?id=19740
@safe unittest
{
diff --git a/libphobos/src/std/container/rbtree.d b/libphobos/src/std/container/rbtree.d
index 0b0a0b2..622dee4 100644
--- a/libphobos/src/std/container/rbtree.d
+++ b/libphobos/src/std/container/rbtree.d
@@ -111,7 +111,7 @@ struct RBNode(V)
/**
* Get the left child
*/
- @property inout(RBNode)* left() inout
+ @property inout(RBNode)* left() inout return scope
{
return _left;
}
@@ -119,7 +119,7 @@ struct RBNode(V)
/**
* Get the right child
*/
- @property inout(RBNode)* right() inout
+ @property inout(RBNode)* right() inout return scope
{
return _right;
}
@@ -127,7 +127,7 @@ struct RBNode(V)
/**
* Get the parent
*/
- @property inout(RBNode)* parent() inout
+ @property inout(RBNode)* parent() inout return scope
{
return _parent;
}
@@ -377,7 +377,7 @@ struct RBNode(V)
* Returns the next highest valued node in the tree after this one, or end
* if this was the highest-valued node.
*/
- Node remove(Node end)
+ Node remove(Node end) return
{
//
// remove this node from the tree, fixing the color if necessary.
@@ -558,7 +558,7 @@ struct RBNode(V)
/**
* Return the leftmost descendant of this node.
*/
- @property inout(RBNode)* leftmost() inout
+ @property inout(RBNode)* leftmost() inout return
{
inout(RBNode)* result = &this;
while (result._left !is null)
@@ -569,7 +569,7 @@ struct RBNode(V)
/**
* Return the rightmost descendant of this node
*/
- @property inout(RBNode)* rightmost() inout
+ @property inout(RBNode)* rightmost() inout return
{
inout(RBNode)* result = &this;
while (result._right !is null)
@@ -583,7 +583,7 @@ struct RBNode(V)
* You should never call this on the marker node, as it is assumed that
* there is a valid next node.
*/
- @property inout(RBNode)* next() inout
+ @property inout(RBNode)* next() inout return
{
inout(RBNode)* n = &this;
if (n.right is null)
@@ -602,7 +602,7 @@ struct RBNode(V)
* You should never call this on the leftmost node of the tree as it is
* assumed that there is a valid previous node.
*/
- @property inout(RBNode)* prev() inout
+ @property inout(RBNode)* prev() inout return
{
inout(RBNode)* n = &this;
if (n.left is null)
diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d
index a10f4da..8512a44 100644
--- a/libphobos/src/std/conv.d
+++ b/libphobos/src/std/conv.d
@@ -1642,7 +1642,7 @@ if (!isImplicitlyConvertible!(S, T) &&
Array-to-array conversion (except when target is a string type)
converts each element in turn by using `to`.
*/
-private T toImpl(T, S)(S value)
+private T toImpl(T, S)(scope S value)
if (!isImplicitlyConvertible!(S, T) &&
!isSomeString!S && isDynamicArray!S &&
!isExactSomeString!T && isArray!T)
diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d
index c974ada..a99c517 100644
--- a/libphobos/src/std/file.d
+++ b/libphobos/src/std/file.d
@@ -4635,7 +4635,7 @@ private struct DirIteratorImpl
import std.path : chainPath;
auto searchPattern = chainPath(directory, "*.*");
- static auto trustedFindFirstFileW(typeof(searchPattern) pattern, WIN32_FIND_DATAW* findinfo) @trusted
+ static auto trustedFindFirstFileW(typeof(searchPattern) pattern, scope WIN32_FIND_DATAW* findinfo) @trusted
{
return FindFirstFileW(pattern.tempCString!FSChar(), findinfo);
}
@@ -4653,7 +4653,7 @@ private struct DirIteratorImpl
return toNext(true, &_findinfo);
}
- bool toNext(bool fetch, WIN32_FIND_DATAW* findinfo) @trusted
+ bool toNext(bool fetch, scope WIN32_FIND_DATAW* findinfo) @trusted
{
import core.stdc.wchar_ : wcscmp;
@@ -5274,7 +5274,21 @@ Returns:
*/
string tempDir() @trusted
{
- import std.path : dirSeparator;
+ // We must check that the end of a path is not a separator, before adding another
+ // If we don't we end up with https://issues.dlang.org/show_bug.cgi?id=22738
+ static string addSeparator(string input)
+ {
+ import std.path : dirSeparator;
+ import std.algorithm.searching : endsWith;
+
+ // It is very rare a directory path will reach this point with a directory separator at the end
+ // However on OSX this can happen, so we must verify lest we break user code i.e. https://github.com/dlang/dub/pull/2208
+ if (!input.endsWith(dirSeparator))
+ return input ~ dirSeparator;
+ else
+ return input;
+ }
+
static string cache;
if (cache is null)
{
@@ -5294,7 +5308,7 @@ string tempDir() @trusted
static string findExistingDir(T...)(lazy T alternatives)
{
foreach (dir; alternatives)
- if (!dir.empty && exists(dir)) return dir ~ dirSeparator;
+ if (!dir.empty && exists(dir)) return addSeparator(dir);
return null;
}
@@ -5309,7 +5323,7 @@ string tempDir() @trusted
if (cache is null)
{
- cache = getcwd() ~ dirSeparator;
+ cache = addSeparator(getcwd());
}
}
return cache;
@@ -5338,6 +5352,9 @@ string tempDir() @trusted
import std.algorithm.searching : endsWith;
import std.path : dirSeparator;
assert(tempDir.endsWith(dirSeparator));
+
+ // https://issues.dlang.org/show_bug.cgi?id=22738
+ assert(!tempDir.endsWith(dirSeparator ~ dirSeparator));
}
/**
diff --git a/libphobos/src/std/functional.d b/libphobos/src/std/functional.d
index bc8d368..da698e0 100644
--- a/libphobos/src/std/functional.d
+++ b/libphobos/src/std/functional.d
@@ -68,6 +68,8 @@ import std.traits : isCallable, Parameters;
import std.internal.attributes : betterC;
+public import core.lifetime : forward;
+
private template needOpCallAlias(alias fun)
{
/* Determine whether or not unaryFun and binaryFun need to alias to fun or
@@ -1845,10 +1847,3 @@ if (isCallable!(F))
static assert(! is(typeof(dg_xtrnC) == typeof(dg_xtrnD)));
}
}
-
-// forward used to be here but was moved to druntime
-template forward(args...)
-{
- import core.lifetime : fun = forward;
- alias forward = fun!args;
-}
diff --git a/libphobos/src/std/internal/math/biguintcore.d b/libphobos/src/std/internal/math/biguintcore.d
index 6a93e0a..d5c4768 100644
--- a/libphobos/src/std/internal/math/biguintcore.d
+++ b/libphobos/src/std/internal/math/biguintcore.d
@@ -813,7 +813,7 @@ public:
// If wantSub is false, return x + y, leaving sign unchanged.
// If wantSub is true, return abs(x - y), negating sign if x<y
- static BigUint addOrSub(scope BigUint x, scope BigUint y, bool wantSub, bool *sign)
+ static BigUint addOrSub(scope BigUint x, scope BigUint y, bool wantSub, ref bool sign)
pure nothrow @safe
{
BigUint r;
@@ -822,10 +822,10 @@ public:
bool negative;
// sub returns GC allocated array, can be safely cast to immutable
r.data = (() @trusted => cast(immutable) sub(x.data, y.data, &negative))();
- *sign ^= negative;
+ sign ^= negative;
if (r.isZero())
{
- *sign = false;
+ sign = false;
}
}
else
diff --git a/libphobos/src/std/socket.d b/libphobos/src/std/socket.d
index f8908cf..cd23232 100644
--- a/libphobos/src/std/socket.d
+++ b/libphobos/src/std/socket.d
@@ -787,13 +787,20 @@ class InternetHost
assert(ih.name == "www.digitalmars.com" || ih.name == "digitalmars.com",
ih.name);
- assert(ih.getHostByAddr(ih.addrList[0]));
- string getHostNameFromInt = ih.name.dup;
+ /* The following assert randomly fails in the test suite.
+ * https://issues.dlang.org/show_bug.cgi?id=22791
+ * So just ignore it when it fails.
+ */
+ //assert(ih.getHostByAddr(ih.addrList[0]));
+ if (ih.getHostByAddr(ih.addrList[0]))
+ {
+ string getHostNameFromInt = ih.name.dup;
- assert(ih.getHostByAddr(ia.toAddrString()));
- string getHostNameFromStr = ih.name.dup;
+ assert(ih.getHostByAddr(ia.toAddrString()));
+ string getHostNameFromStr = ih.name.dup;
- assert(getHostNameFromInt == getHostNameFromStr);
+ assert(getHostNameFromInt == getHostNameFromStr);
+ }
}
diff --git a/libphobos/src/std/sumtype.d b/libphobos/src/std/sumtype.d
index 658fd38..5e35a6b 100644
--- a/libphobos/src/std/sumtype.d
+++ b/libphobos/src/std/sumtype.d
@@ -262,6 +262,8 @@ private enum isHashable(T) = __traits(compiles,
private enum hasPostblit(T) = __traits(hasPostblit, T);
+private enum isInout(T) = is(T == inout);
+
/**
* A [tagged union](https://en.wikipedia.org/wiki/Tagged_union) that can hold a
* single value from any of a specified set of types.
@@ -419,6 +421,7 @@ public:
(
allSatisfy!(isCopyable, Map!(InoutOf, Types))
&& !anySatisfy!(hasPostblit, Map!(InoutOf, Types))
+ && allSatisfy!(isInout, Map!(InoutOf, Types))
)
{
/// Constructs a `SumType` that's a copy of another `SumType`.
@@ -1492,6 +1495,23 @@ version (D_BetterC) {} else
immutable SumType!(int*) si = &ni;
}
+// Immutable member type with copy constructor
+// https://issues.dlang.org/show_bug.cgi?id=22572
+@safe unittest
+{
+ static struct CopyConstruct
+ {
+ this(ref inout CopyConstruct other) inout {}
+ }
+
+ static immutable struct Value
+ {
+ CopyConstruct c;
+ }
+
+ SumType!Value s;
+}
+
/// True if `T` is an instance of the `SumType` template, otherwise false.
private enum bool isSumTypeInstance(T) = is(T == SumType!Args, Args...);
diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d
index 28edb9b..ea8f8bd 100644
--- a/libphobos/src/std/typecons.d
+++ b/libphobos/src/std/typecons.d
@@ -2798,13 +2798,24 @@ struct Nullable(T)
}
}
- this (ref return scope inout Nullable!T rhs) inout
+ static if (__traits(hasPostblit, T))
{
- _isNull = rhs._isNull;
- if (!_isNull)
- _value.payload = rhs._value.payload;
- else
- _value = DontCallDestructorT.init;
+ this(this)
+ {
+ if (!_isNull)
+ _value.payload.__xpostblit();
+ }
+ }
+ else static if (__traits(hasCopyConstructor, T))
+ {
+ this(ref return scope inout Nullable!T rhs) inout
+ {
+ _isNull = rhs._isNull;
+ if (!_isNull)
+ _value.payload = rhs._value.payload;
+ else
+ _value = DontCallDestructorT.init;
+ }
}
/**
@@ -9630,13 +9641,28 @@ unittest
{
int b;
@disable this(this);
- this (ref return scope inout S rhs) inout
+ this(ref return scope inout S rhs) inout
{
this.b = rhs.b + 1;
}
}
Nullable!S s1 = S(1);
+ assert(s1.get().b == 2);
+ Nullable!S s2 = s1;
+ assert(s2.get().b == 3);
+}
+
+@safe unittest
+{
+ static struct S
+ {
+ int b;
+ this(this) { ++b; }
+ }
+
+ Nullable!S s1 = S(1);
+ assert(s1.get().b == 2);
Nullable!S s2 = s1;
- assert(s2.get().b > s1.get().b);
+ assert(s2.get().b == 3);
}
diff --git a/libphobos/src/std/uni/package.d b/libphobos/src/std/uni/package.d
index 192b6fd..9780b1b 100644
--- a/libphobos/src/std/uni/package.d
+++ b/libphobos/src/std/uni/package.d
@@ -5363,7 +5363,7 @@ pure @safe unittest
pure @safe unittest
{
import std.range : stride;
- static bool testAll(Matcher, Range)(scope ref Matcher m, ref Range r)
+ static bool testAll(Matcher, Range)(ref Matcher m, ref Range r) @safe
{
bool t = m.test(r);
auto save = r.idx;
diff --git a/libphobos/src/std/zip.d b/libphobos/src/std/zip.d
index 4d7422b..72d1287 100644
--- a/libphobos/src/std/zip.d
+++ b/libphobos/src/std/zip.d
@@ -222,14 +222,6 @@ final class ArchiveMember
@property @safe pure nothrow @nogc uint expandedSize() const { return _expandedSize; }
/**
- * Should be 0.
- *
- * Returns: The number of the disk where this member can be found.
- */
- deprecated("Multidisk not supported; will be removed in 2.099.0")
- @property @safe pure nothrow @nogc ushort diskNumber() const { return 0; }
-
- /**
* Data of member in compressed form.
*
* Returns: The file data in compressed form.
@@ -452,13 +444,6 @@ public:
private bool _isZip64;
static const ushort zip64ExtractVersion = 45;
- deprecated("Use digitalSignatureLength instead; will be removed in 2.098.0")
- static const int digiSignLength = 6;
- deprecated("Use zip64EndOfCentralDirLocatorLength instead; will be removed in 2.098.0")
- static const int eocd64LocLength = 20;
- deprecated("Use zip64EndOfCentralDirLength instead; will be removed in 2.098.0")
- static const int eocd64Length = 56;
-
private Segment[] _segs;
/**
@@ -469,29 +454,11 @@ public:
@property @safe @nogc pure nothrow ubyte[] data() { return _data; }
/**
- * 0 since multi-disk zip archives are not supported.
- *
- * Returns: Number of this disk.
- */
- deprecated("Multidisk not supported; will be removed in 2.099.0")
- @property @safe @nogc pure nothrow uint diskNumber() const { return 0; }
-
- /**
- * 0 since multi-disk zip archives are not supported.
- *
- * Returns: Number of the disk, where the central directory starts.
- */
- deprecated("Multidisk not supported; will be removed in 2.099.0")
- @property @safe @nogc pure nothrow uint diskStartDir() const { return 0; }
-
- /**
* Number of ArchiveMembers in the directory.
*
* Returns: The number of files in this archive.
*/
- deprecated("Use totalEntries instead; will be removed in 2.099.0")
- @property @safe @nogc pure nothrow uint numEntries() const { return cast(uint) _directory.length; }
- @property @safe @nogc pure nothrow uint totalEntries() const { return cast(uint) _directory.length; } /// ditto
+ @property @safe @nogc pure nothrow uint totalEntries() const { return cast(uint) _directory.length; }
/**
* True when the archive is in Zip64 format. Set this to true to force building a Zip64 archive.
diff --git a/libphobos/testsuite/libphobos.betterc/test19933.d b/libphobos/testsuite/libphobos.betterc/test19933.d
new file mode 100644
index 0000000..a0faadd
--- /dev/null
+++ b/libphobos/testsuite/libphobos.betterc/test19933.d
@@ -0,0 +1,11 @@
+/*******************************************/
+// https://issues.dlang.org/show_bug.cgi?id=19933
+// https://issues.dlang.org/show_bug.cgi?id=18816
+
+import core.stdc.stdio;
+
+extern(C) int main()
+{
+ fprintf(stderr, "Hello\n");
+ return 0;
+}
diff --git a/libphobos/testsuite/libphobos.hash/test_hash.d b/libphobos/testsuite/libphobos.hash/test_hash.d
index d0a8e5fb..0ad2443 100644
--- a/libphobos/testsuite/libphobos.hash/test_hash.d
+++ b/libphobos/testsuite/libphobos.hash/test_hash.d
@@ -277,7 +277,7 @@ void issue22076()
static struct S1
{
S0 a;
- inout(S0)* b() inout nothrow { return &a; }
+ inout(S0)* b() inout return nothrow { return &a; }
alias b this;
}