public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-5887] d: Merge upstream dmd 3982604c5, druntime bc58b1e9, phobos 12329adb6.
@ 2021-12-10 4:27 Iain Buclaw
0 siblings, 0 replies; only message in thread
From: Iain Buclaw @ 2021-12-10 4:27 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:9c7d5e8846edb28e5421211ee8eaad93e234de2c
commit r12-5887-g9c7d5e8846edb28e5421211ee8eaad93e234de2c
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date: Fri Dec 10 03:14:20 2021 +0100
d: Merge upstream dmd 3982604c5, druntime bc58b1e9, phobos 12329adb6.
D front-end changes:
- Import dmd mainline development.
- Split off enum EXP from enum TOK.
- Integer promotions now follow C integral promotions by default.
- Implements __traits(initSymbol).
- Lowering of array construction has been moved to the dmd
front-end.
- Fix segfault in dmd.lexer from unaligned read (PR103529).
Druntime changes:
- Import druntime mainline development.
- Define SIG_BLOCK for Solaris (PR103528).
Phobos changes:
- Import phobos mainline development.
gcc/d/ChangeLog:
PR d/103529
* dmd/MERGE: Merge upstream dmd 3982604c5.
* Make-lang.in (D_FRONTEND_OBJS): Add d/root-optional.o.
* d-attribs.cc (build_attributes): Update for new front-end interface.
* d-codegen.cc (d_build_call): Likewise.
* d-compiler.cc (Compiler::paintAsType): Likewise.
* d-lang.cc (d_handle_option): Remove OPT_fpreview_intpromote, add
handling of OPT_frevert_intpromote.
* d-port.cc (Port::valcpy): Assert buffer is aligned.
* d-target.cc (Target::isVectorOpSupported): Update for new front-end
interface.
* decl.cc (layout_class_initializer): Likewise.
* expr.cc (lvalue_p): Likewise.
(binop_assignment): Likewise.
(ExprVisitor::visit): Likewise.
(ExprVisitor::visit (AssignExp *)): Remove generation of _d_arrayctor
and _d_arraysetctor library helpers.
(ExprVisitor::visit (VarExp *)): Support __traits(initSymbol).
* intrinsics.cc (expand_intrinsic_rotate): Update for new front-end
interface.
* lang.opt (fpreview=intpromote): Remove.
(frevert=intpromote): New.
* runtime.def (ARRAYCTOR): Remove.
(ARRAYSETCTOR): Remove.
* toir.cc (IRVisitor::visit): Update for new front-end interface.
* types.cc (layout_aggregate_members): Likewise.
* dmd/root/optional.d: New file.
* dmd/root/optional.h: New file.
libphobos/ChangeLog:
PR d/103528
* libdruntime/MERGE: Merge upstream druntime bc58b1e9.
* libdruntime/Makefile.am (DRUNTIME_DSOURCES_LINUX): Remove
core/sys/linux/syscalls.d.
* libdruntime/Makefile.in: Regenerate.
* src/MERGE: Merge upstream phobos 12329adb6.
* testsuite/libphobos.config/config.exp: Add test22523.
* libdruntime/core/sys/linux/syscalls.d: Removed.
* testsuite/libphobos.config/test22523.d: New test.
Diff:
---
gcc/d/Make-lang.in | 1 +
gcc/d/d-attribs.cc | 6 +-
gcc/d/d-codegen.cc | 6 +-
gcc/d/d-compiler.cc | 4 +-
gcc/d/d-lang.cc | 11 +-
gcc/d/d-port.cc | 2 +
gcc/d/d-target.cc | 30 +-
gcc/d/decl.cc | 2 +-
gcc/d/dmd/MERGE | 2 +-
gcc/d/dmd/access.d | 2 +-
gcc/d/dmd/aggregate.d | 14 +-
gcc/d/dmd/aliasthis.d | 4 +-
gcc/d/dmd/arrayop.d | 79 +-
gcc/d/dmd/astenums.d | 4 +-
gcc/d/dmd/attrib.d | 11 +-
gcc/d/dmd/blockexit.d | 20 +-
gcc/d/dmd/builtin.d | 2 -
gcc/d/dmd/canthrow.d | 2 +-
gcc/d/dmd/clone.d | 8 +-
gcc/d/dmd/common/outbuffer.h | 2 +-
gcc/d/dmd/cond.d | 2 +-
gcc/d/dmd/constfold.d | 166 +--
gcc/d/dmd/cparse.d | 45 +-
gcc/d/dmd/cppmangle.d | 2 +-
gcc/d/dmd/ctfeexpr.d | 394 ++---
gcc/d/dmd/dcast.d | 176 ++-
gcc/d/dmd/declaration.d | 40 +-
gcc/d/dmd/declaration.h | 9 +-
gcc/d/dmd/dinterpret.d | 634 ++++----
gcc/d/dmd/dmangle.d | 4 +-
gcc/d/dmd/dstruct.d | 18 +-
gcc/d/dmd/dsymbol.d | 16 +-
gcc/d/dmd/dsymbolsem.d | 56 +-
gcc/d/dmd/dtemplate.d | 137 +-
gcc/d/dmd/dtoh.d | 11 +-
gcc/d/dmd/escape.d | 65 +-
gcc/d/dmd/expression.d | 784 +++++-----
gcc/d/dmd/expression.h | 28 +-
gcc/d/dmd/expressionsem.d | 802 +++++-----
gcc/d/dmd/foreachvar.d | 2 +-
gcc/d/dmd/func.d | 9 +-
gcc/d/dmd/globals.d | 2 +-
gcc/d/dmd/hdrgen.d | 195 ++-
gcc/d/dmd/iasmgcc.d | 4 +-
gcc/d/dmd/id.d | 3 +
gcc/d/dmd/initsem.d | 56 +-
gcc/d/dmd/lambdacomp.d | 5 +-
gcc/d/dmd/lexer.d | 22 +-
gcc/d/dmd/mtype.d | 16 +-
gcc/d/dmd/nogc.d | 6 +-
gcc/d/dmd/ob.d | 6 +-
gcc/d/dmd/objc.d | 12 +-
gcc/d/dmd/opover.d | 323 ++--
gcc/d/dmd/optimize.d | 1535 ++++++++++----------
gcc/d/dmd/parse.d | 340 ++---
gcc/d/dmd/printast.d | 7 +-
gcc/d/dmd/root/dcompat.h | 3 +
gcc/d/dmd/root/file.d | 18 +-
gcc/d/dmd/root/optional.d | 86 ++
gcc/d/dmd/root/optional.h | 42 +
gcc/d/dmd/safe.d | 4 +-
gcc/d/dmd/semantic2.d | 18 +-
gcc/d/dmd/semantic3.d | 4 +-
gcc/d/dmd/sideeffect.d | 84 +-
gcc/d/dmd/statementsem.d | 882 ++++++-----
gcc/d/dmd/staticcond.d | 51 +-
gcc/d/dmd/target.d | 5 +-
gcc/d/dmd/target.h | 4 +-
gcc/d/dmd/templateparamsem.d | 6 +-
gcc/d/dmd/tokens.d | 160 +-
gcc/d/dmd/tokens.h | 628 +++++---
gcc/d/dmd/traits.d | 41 +-
gcc/d/dmd/typesem.d | 124 +-
gcc/d/expr.cc | 259 ++--
gcc/d/intrinsics.cc | 2 +-
gcc/d/lang.opt | 8 +-
gcc/d/runtime.def | 7 -
gcc/d/toir.cc | 3 +-
gcc/d/types.cc | 2 +-
.../gdc.test/compilable/covariant_override.d | 34 +
gcc/testsuite/gdc.test/compilable/emptygenmain.d | 3 +
gcc/testsuite/gdc.test/compilable/noreturn1.d | 12 +
gcc/testsuite/gdc.test/compilable/test17870.d | 26 +
gcc/testsuite/gdc.test/compilable/test19873.d | 37 +
gcc/testsuite/gdc.test/compilable/test21719.d | 21 +
gcc/testsuite/gdc.test/compilable/test22254.d | 19 +
gcc/testsuite/gdc.test/compilable/test22510.d | 18 +
.../gdc.test/fail_compilation/covariant_override.d | 35 +
.../gdc.test/fail_compilation/fail10964.d | 4 +-
.../gdc.test/fail_compilation/fail10968.d | 38 +-
.../gdc.test/fail_compilation/fail16997.d | 38 +-
gcc/testsuite/gdc.test/fail_compilation/fail809.d | 12 -
gcc/testsuite/gdc.test/fail_compilation/fob2.d | 2 +-
.../gdc.test/fail_compilation/imports/test20023b.d | 10 +
gcc/testsuite/gdc.test/fail_compilation/retscope.d | 8 +-
.../gdc.test/fail_compilation/test15191.d | 42 +-
.../gdc.test/fail_compilation/test17977.d | 20 +
.../gdc.test/fail_compilation/test20023.d | 16 +
.../gdc.test/fail_compilation/traits_initSymbol.d | 63 +
gcc/testsuite/gdc.test/runnable/b19294.d | 163 +++
gcc/testsuite/gdc.test/runnable/mars1.d | 2 +-
gcc/testsuite/gdc.test/runnable/test15862.d | 39 +
gcc/testsuite/gdc.test/runnable/test21367.d | 47 +
gcc/testsuite/gdc.test/runnable/test22227.d | 16 +
gcc/testsuite/gdc.test/runnable/testOpApply.d | 31 +-
gcc/testsuite/gdc.test/runnable/testcgelem.d | 2 +-
gcc/testsuite/gdc.test/runnable/testconst.d | 8 +-
.../gdc.test/runnable/traits_initSymbol.d | 119 ++
gcc/testsuite/gdc.test/runnable/xtest46.d | 7 +-
| 103 ++
gcc/testsuite/gdc.test/runnable_cxx/test7925.d | 151 ++
libphobos/libdruntime/MERGE | 2 +-
libphobos/libdruntime/Makefile.am | 5 +-
libphobos/libdruntime/Makefile.in | 12 +-
libphobos/libdruntime/core/demangle.d | 8 +-
.../libdruntime/core/internal/array/construction.d | 43 +-
libphobos/libdruntime/core/internal/convert.d | 8 +-
libphobos/libdruntime/core/internal/lifetime.d | 49 +-
libphobos/libdruntime/core/internal/string.d | 2 +-
libphobos/libdruntime/core/internal/utf.d | 10 +-
libphobos/libdruntime/core/lifetime.d | 111 +-
libphobos/libdruntime/core/memory.d | 21 +-
libphobos/libdruntime/core/stdc/stdlib.d | 10 +
libphobos/libdruntime/core/stdc/string.d | 28 +-
libphobos/libdruntime/core/stdc/wchar_.d | 26 +-
libphobos/libdruntime/core/stdcpp/exception.d | 2 +
libphobos/libdruntime/core/sync/mutex.d | 4 +-
libphobos/libdruntime/core/sys/bionic/string.d | 2 +-
libphobos/libdruntime/core/sys/darwin/mach/nlist.d | 2 +-
libphobos/libdruntime/core/sys/darwin/string.d | 2 +-
.../libdruntime/core/sys/dragonflybsd/string.d | 2 +-
libphobos/libdruntime/core/sys/freebsd/string.d | 2 +-
libphobos/libdruntime/core/sys/linux/string.d | 2 +-
libphobos/libdruntime/core/sys/linux/syscalls.d | 745 ----------
libphobos/libdruntime/core/sys/linux/unistd.d | 26 +-
libphobos/libdruntime/core/sys/netbsd/string.d | 2 +-
libphobos/libdruntime/core/sys/openbsd/string.d | 2 +-
libphobos/libdruntime/core/sys/posix/signal.d | 26 +-
libphobos/libdruntime/core/sys/posix/string.d | 8 +-
libphobos/libdruntime/core/sys/posix/sys/socket.d | 2 +-
libphobos/libdruntime/core/sys/solaris/sys/elf.d | 5 +-
.../libdruntime/core/sys/solaris/sys/elf_386.d | 3 -
.../libdruntime/core/sys/solaris/sys/elf_SPARC.d | 3 -
libphobos/libdruntime/core/sys/windows/dbghelp.d | 8 +-
libphobos/libdruntime/core/thread/osthread.d | 5 +-
libphobos/libdruntime/core/thread/threadbase.d | 5 +-
libphobos/libdruntime/object.d | 8 +-
libphobos/libdruntime/rt/aaA.d | 4 +-
libphobos/libdruntime/rt/cast_.d | 2 +-
libphobos/libdruntime/rt/config.d | 3 +
libphobos/libdruntime/rt/lifetime.d | 4 +-
libphobos/libdruntime/rt/monitor_.d | 2 +-
libphobos/src/MERGE | 2 +-
libphobos/src/std/algorithm/iteration.d | 52 +-
libphobos/src/std/algorithm/mutation.d | 29 +-
libphobos/src/std/algorithm/sorting.d | 26 +-
libphobos/src/std/concurrency.d | 32 +-
libphobos/src/std/container/dlist.d | 6 +
libphobos/src/std/container/rbtree.d | 2 +-
libphobos/src/std/datetime/interval.d | 6 +-
libphobos/src/std/datetime/systime.d | 27 +-
libphobos/src/std/datetime/timezone.d | 74 +-
libphobos/src/std/file.d | 28 +-
libphobos/src/std/internal/cstring.d | 2 +-
libphobos/src/std/internal/math/biguintcore.d | 12 +-
libphobos/src/std/json.d | 10 +-
libphobos/src/std/net/isemail.d | 2 +-
libphobos/src/std/process.d | 4 +-
libphobos/src/std/random.d | 12 +-
libphobos/src/std/stdio.d | 2 +-
libphobos/src/std/typecons.d | 35 +-
libphobos/src/std/uni/package.d | 4 +-
libphobos/src/std/utf.d | 12 +-
libphobos/testsuite/libphobos.config/config.exp | 1 +
libphobos/testsuite/libphobos.config/test22523.d | 11 +
175 files changed, 6436 insertions(+), 4902 deletions(-)
diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in
index d7f714760f7..00169a743a1 100644
--- a/gcc/d/Make-lang.in
+++ b/gcc/d/Make-lang.in
@@ -162,6 +162,7 @@ D_FRONTEND_OBJS = \
d/root-filename.o \
d/root-hash.o \
d/root-longdouble.o \
+ d/root-optional.o \
d/root-port.o \
d/root-region.o \
d/root-rmem.o \
diff --git a/gcc/d/d-attribs.cc b/gcc/d/d-attribs.cc
index 04b9791ab1b..5c9f569d1c4 100644
--- a/gcc/d/d-attribs.cc
+++ b/gcc/d/d-attribs.cc
@@ -337,10 +337,10 @@ build_attributes (Expressions *eattrs)
continue;
/* Get the result of the attribute if it hasn't already been folded. */
- if (attr->op == TOKcall)
+ if (attr->op == EXP::call)
attr = attr->ctfeInterpret ();
- if (attr->op != TOKstructliteral)
+ if (attr->op != EXP::structLiteral)
{
warning_at (make_location_t (attr->loc), OPT_Wattributes,
"%qE attribute has no effect",
@@ -353,7 +353,7 @@ build_attributes (Expressions *eattrs)
Expressions *elems = attr->isStructLiteralExp ()->elements;
Expression *e0 = (*elems)[0];
- if (e0->op != TOKstring)
+ if (e0->op != EXP::string_)
{
warning_at (make_location_t (attr->loc), OPT_Wattributes,
"unknown attribute %qs", e0->toChars());
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index c082ac5ab80..39c3c6ce987 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -2154,9 +2154,9 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
{
Lagain:
Expression *arg = (*arguments)[i];
- gcc_assert (arg->op != TOKtuple);
+ gcc_assert (arg->op != EXP::tuple);
- if (arg->op == TOKcomma)
+ if (arg->op == EXP::comma)
{
CommaExp *ce = arg->isCommaExp ();
tree tce = build_expr (ce->e1);
@@ -2200,7 +2200,7 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
/* Nested structs also have ADDRESSABLE set, but if the type has
neither a copy constructor nor a destructor available, then we
need to take care of copying its value before passing it. */
- if (arg->op == TOKstructliteral || (!sd->postblit && !sd->dtor))
+ if (arg->op == EXP::structLiteral || (!sd->postblit && !sd->dtor))
targ = force_target_expr (targ);
targ = convert (build_reference_type (TREE_TYPE (targ)),
diff --git a/gcc/d/d-compiler.cc b/gcc/d/d-compiler.cc
index 3df40073ac5..c1e78c0a5de 100644
--- a/gcc/d/d-compiler.cc
+++ b/gcc/d/d-compiler.cc
@@ -50,7 +50,7 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
cst = build_integer_cst (expr->toInteger (), build_ctype (expr->type));
else if (expr->type->isfloating ())
cst = build_float_cst (expr->toReal (), expr->type);
- else if (expr->op == TOKarrayliteral)
+ else if (expr->op == EXP::arrayLiteral)
{
/* Build array as VECTOR_CST, assumes EXPR is constant. */
Expressions *elements = expr->isArrayLiteralExp ()->elements;
@@ -99,7 +99,7 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
cst = native_interpret_expr (vectype, buffer, len);
Expression *e = d_eval_constant_expression (expr->loc, cst);
- gcc_assert (e != NULL && e->op == TOKvector);
+ gcc_assert (e != NULL && e->op == EXP::vector);
return e->isVectorExp ()->e1;
}
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index 576eefcc01f..2c5d206a95f 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -620,10 +620,6 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
global.params.inclusiveInContracts = value;
break;
- case OPT_fpreview_intpromote:
- global.params.fix16997 = value;
- break;
-
case OPT_fpreview_nosharedaccess:
global.params.noSharedAccess = value;
break;
@@ -642,8 +638,9 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
case OPT_frevert_all:
global.params.useDIP25 = FeatureState::disabled;
- global.params.markdown = !value;
global.params.dtorFields = FeatureState::disabled;
+ global.params.fix16997 = !value;
+ global.params.markdown = !value;
break;
case OPT_frevert_dip25:
@@ -654,6 +651,10 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
global.params.dtorFields = FeatureState::disabled;
break;
+ case OPT_frevert_intpromote:
+ global.params.fix16997 = !value;
+ break;
+
case OPT_frevert_markdown:
global.params.markdown = !value;
break;
diff --git a/gcc/d/d-port.cc b/gcc/d/d-port.cc
index 58b3fe138b2..4e867a7db4a 100644
--- a/gcc/d/d-port.cc
+++ b/gcc/d/d-port.cc
@@ -145,6 +145,8 @@ Port::readlongBE (const void *buffer)
void
Port::valcpy (void *buffer, uint64_t value, size_t sz)
{
+ gcc_assert (((size_t) buffer) % sz == 0);
+
switch (sz)
{
case 1:
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index 21417dddf78..dd244f12119 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -287,7 +287,7 @@ Target::isVectorTypeSupported (int sz, Type *type)
Returns true if the operation is supported or type is not a vector. */
bool
-Target::isVectorOpSupported (Type *type, unsigned op, Type *)
+Target::isVectorOpSupported (Type *type, EXP op, Type *)
{
if (type->ty != TY::Tvector)
return true;
@@ -299,31 +299,31 @@ Target::isVectorOpSupported (Type *type, unsigned op, Type *)
/* Don't support if expression cannot be represented. */
switch (op)
{
- case TOKpow:
- case TOKpowass:
+ case EXP::pow:
+ case EXP::powAssign:
/* pow() is lowered as a function call. */
return false;
- case TOKmod:
- case TOKmodass:
+ case EXP::mod:
+ case EXP::modAssign:
/* fmod() is lowered as a function call. */
if (type->isfloating ())
return false;
break;
- case TOKandand:
- case TOKoror:
+ case EXP::andAnd:
+ case EXP::orOr:
/* Logical operators must have a result type of bool. */
return false;
- case TOKle:
- case TOKlt:
- case TOKge:
- case TOKgt:
- case TOKequal:
- case TOKnotequal:
- case TOKidentity:
- case TOKnotidentity:
+ case EXP::lessOrEqual:
+ case EXP::lessThan:
+ case EXP::greaterOrEqual:
+ case EXP::greaterThan:
+ case EXP::equal:
+ case EXP::notEqual:
+ case EXP::identity:
+ case EXP::notIdentity:
/* Comparison operators must have a result type of bool. */
return false;
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index c69f5664e8c..bbde4a669e4 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -2239,7 +2239,7 @@ layout_class_initializer (ClassDeclaration *cd)
ne->type = cd->type;
Expression *e = ne->ctfeInterpret ();
- gcc_assert (e->op == TOKclassreference);
+ gcc_assert (e->op == EXP::classReference);
return build_class_instance (e->isClassReferenceExp ());
}
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index d23e1fedba4..4bae16c86eb 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-568496d5b6ed02d577dfa86f73c7bb4edee05813
+3982604c54e8770585985a33577fbf19b9b5c9ce
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/access.d b/gcc/d/dmd/access.d
index 944c9d3e124..d8a65179a9e 100644
--- a/gcc/d/dmd/access.d
+++ b/gcc/d/dmd/access.d
@@ -201,7 +201,7 @@ bool checkAccess(Loc loc, Scope* sc, Expression e, Dsymbol d)
{
// Do access check
ClassDeclaration cd = tc.sym;
- if (e.op == TOK.super_)
+ if (e.op == EXP.super_)
{
if (ClassDeclaration cd2 = sc.func.toParent().isClassDeclaration())
cd = cd2;
diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d
index 1fe8e809aa5..dc772e8eeac 100644
--- a/gcc/d/dmd/aggregate.d
+++ b/gcc/d/dmd/aggregate.d
@@ -472,7 +472,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
}
foreach (e; *elements)
{
- if (e && e.op == TOK.error)
+ if (e && e.op == EXP.error)
return false;
}
@@ -565,6 +565,18 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
override final Type getType()
{
+ /* Apply storage classes to forward references. (Issue 22254)
+ * Note: Avoid interfaces for now. Implementing qualifiers on interface
+ * definitions exposed some issues in their TypeInfo generation in DMD.
+ * Related PR: https://github.com/dlang/dmd/pull/13312
+ */
+ if (semanticRun == PASS.init && !isInterfaceDeclaration())
+ {
+ auto stc = storage_class;
+ if (_scope)
+ stc |= _scope.stc;
+ type = type.addSTC(stc);
+ }
return type;
}
diff --git a/gcc/d/dmd/aliasthis.d b/gcc/d/dmd/aliasthis.d
index e048cdc2e1b..80db47ded1d 100644
--- a/gcc/d/dmd/aliasthis.d
+++ b/gcc/d/dmd/aliasthis.d
@@ -91,7 +91,7 @@ Expression resolveAliasThis(Scope* sc, Expression e, bool gag = false, bool find
if (ad.aliasthis)
{
Loc loc = e.loc;
- Type tthis = (e.op == TOK.type ? e.type : null);
+ Type tthis = (e.op == EXP.type ? e.type : null);
const flags = DotExpFlag.noAliasThis | (gag ? DotExpFlag.gag : 0);
uint olderrors = gag ? global.startGagging() : 0;
e = dotExp(e.type, sc, e, ad.aliasthis.ident, flags);
@@ -100,7 +100,7 @@ Expression resolveAliasThis(Scope* sc, Expression e, bool gag = false, bool find
if (tthis && ad.aliasthis.sym.needThis())
{
- if (e.op == TOK.variable)
+ if (e.op == EXP.variable)
{
if (auto fd = (cast(VarExp)e).var.isFuncDeclaration())
{
diff --git a/gcc/d/dmd/arrayop.d b/gcc/d/dmd/arrayop.d
index e2b33194f06..a234501075c 100644
--- a/gcc/d/dmd/arrayop.d
+++ b/gcc/d/dmd/arrayop.d
@@ -23,6 +23,7 @@ import dmd.expression;
import dmd.expressionsem;
import dmd.func;
import dmd.globals;
+import dmd.hdrgen;
import dmd.id;
import dmd.identifier;
import dmd.mtype;
@@ -37,9 +38,9 @@ import dmd.visitor;
bool isArrayOpValid(Expression e)
{
//printf("isArrayOpValid() %s\n", e.toChars());
- if (e.op == TOK.slice)
+ if (e.op == EXP.slice)
return true;
- if (e.op == TOK.arrayLiteral)
+ if (e.op == EXP.arrayLiteral)
{
Type t = e.type.toBasetype();
while (t.ty == Tarray || t.ty == Tsarray)
@@ -53,17 +54,17 @@ bool isArrayOpValid(Expression e)
{
return isArrayOpValid((cast(UnaExp)e).e1);
}
- if (isBinArrayOp(e.op) || isBinAssignArrayOp(e.op) || e.op == TOK.assign)
+ if (isBinArrayOp(e.op) || isBinAssignArrayOp(e.op) || e.op == EXP.assign)
{
BinExp be = cast(BinExp)e;
return isArrayOpValid(be.e1) && isArrayOpValid(be.e2);
}
- if (e.op == TOK.construct)
+ if (e.op == EXP.construct)
{
BinExp be = cast(BinExp)e;
- return be.e1.op == TOK.slice && isArrayOpValid(be.e2);
+ return be.e1.op == EXP.slice && isArrayOpValid(be.e2);
}
- // if (e.op == TOK.call)
+ // if (e.op == EXP.call)
// {
// TODO: Decide if [] is required after arrayop calls.
// }
@@ -74,7 +75,7 @@ bool isArrayOpValid(Expression e)
bool isNonAssignmentArrayOp(Expression e)
{
- if (e.op == TOK.slice)
+ if (e.op == EXP.slice)
return isNonAssignmentArrayOp((cast(SliceExp)e).e1);
Type tb = e.type.toBasetype();
@@ -166,11 +167,11 @@ Expression arrayOp(BinAssignExp e, Scope* sc)
if (tn && (!tn.isMutable() || !tn.isAssignable()))
{
e.error("slice `%s` is not mutable", e.e1.toChars());
- if (e.op == TOK.addAssign)
+ if (e.op == EXP.addAssign)
checkPossibleAddCatError!(AddAssignExp, CatAssignExp)(e.isAddAssignExp);
return ErrorExp.get();
}
- if (e.e1.op == TOK.arrayLiteral)
+ if (e.e1.op == EXP.arrayLiteral)
{
return e.e1.modifiableLvalue(sc, e.e1);
}
@@ -228,7 +229,7 @@ private void buildArrayOp(Scope* sc, Expression e, Objects* tiargs, Expressions*
// RPN, prefix unary ops with u
OutBuffer buf;
buf.writestring("u");
- buf.writestring(Token.toString(e.op));
+ buf.writestring(EXPtoString(e.op));
e.e1.accept(this);
tiargs.push(new StringExp(Loc.initial, buf.extractSlice()).expressionSemantic(sc));
}
@@ -246,7 +247,7 @@ private void buildArrayOp(Scope* sc, Expression e, Objects* tiargs, Expressions*
// RPN
e.e1.accept(this);
e.e2.accept(this);
- tiargs.push(new StringExp(Loc.initial, Token.toString(e.op)).expressionSemantic(sc));
+ tiargs.push(new StringExp(Loc.initial, EXPtoString(e.op)).expressionSemantic(sc));
}
}
}
@@ -274,12 +275,12 @@ bool isArrayOpImplicitCast(TypeDArray tfrom, TypeDArray tto)
/***********************************************
* Test if expression is a unary array op.
*/
-bool isUnaArrayOp(TOK op)
+bool isUnaArrayOp(EXP op)
{
switch (op)
{
- case TOK.negate:
- case TOK.tilde:
+ case EXP.negate:
+ case EXP.tilde:
return true;
default:
break;
@@ -290,19 +291,19 @@ bool isUnaArrayOp(TOK op)
/***********************************************
* Test if expression is a binary array op.
*/
-bool isBinArrayOp(TOK op)
+bool isBinArrayOp(EXP op)
{
switch (op)
{
- case TOK.add:
- case TOK.min:
- case TOK.mul:
- case TOK.div:
- case TOK.mod:
- case TOK.xor:
- case TOK.and:
- case TOK.or:
- case TOK.pow:
+ case EXP.add:
+ case EXP.min:
+ case EXP.mul:
+ case EXP.div:
+ case EXP.mod:
+ case EXP.xor:
+ case EXP.and:
+ case EXP.or:
+ case EXP.pow:
return true;
default:
break;
@@ -313,19 +314,19 @@ bool isBinArrayOp(TOK op)
/***********************************************
* Test if expression is a binary assignment array op.
*/
-bool isBinAssignArrayOp(TOK op)
+bool isBinAssignArrayOp(EXP op)
{
switch (op)
{
- case TOK.addAssign:
- case TOK.minAssign:
- case TOK.mulAssign:
- case TOK.divAssign:
- case TOK.modAssign:
- case TOK.xorAssign:
- case TOK.andAssign:
- case TOK.orAssign:
- case TOK.powAssign:
+ case EXP.addAssign:
+ case EXP.minAssign:
+ case EXP.mulAssign:
+ case EXP.divAssign:
+ case EXP.modAssign:
+ case EXP.xorAssign:
+ case EXP.andAssign:
+ case EXP.orAssign:
+ case EXP.powAssign:
return true;
default:
break;
@@ -339,9 +340,9 @@ bool isBinAssignArrayOp(TOK op)
bool isArrayOpOperand(Expression e)
{
//printf("Expression.isArrayOpOperand() %s\n", e.toChars());
- if (e.op == TOK.slice)
+ if (e.op == EXP.slice)
return true;
- if (e.op == TOK.arrayLiteral)
+ if (e.op == EXP.arrayLiteral)
{
Type t = e.type.toBasetype();
while (t.ty == Tarray || t.ty == Tsarray)
@@ -354,7 +355,7 @@ bool isArrayOpOperand(Expression e)
return (isUnaArrayOp(e.op) ||
isBinArrayOp(e.op) ||
isBinAssignArrayOp(e.op) ||
- e.op == TOK.assign);
+ e.op == EXP.assign);
}
return false;
}
@@ -371,9 +372,9 @@ bool isArrayOpOperand(Expression e)
ErrorExp arrayOpInvalidError(Expression e)
{
e.error("invalid array operation `%s` (possible missing [])", e.toChars());
- if (e.op == TOK.add)
+ if (e.op == EXP.add)
checkPossibleAddCatError!(AddExp, CatExp)(e.isAddExp());
- else if (e.op == TOK.addAssign)
+ else if (e.op == EXP.addAssign)
checkPossibleAddCatError!(AddAssignExp, CatAssignExp)(e.isAddAssignExp());
return ErrorExp.get();
}
diff --git a/gcc/d/dmd/astenums.d b/gcc/d/dmd/astenums.d
index df88bb97bdf..f6387651e5f 100644
--- a/gcc/d/dmd/astenums.d
+++ b/gcc/d/dmd/astenums.d
@@ -62,7 +62,7 @@ enum STC : ulong // transfer changes to declaration.h
foreach_ = 0x4000, /// variable for foreach loop
variadic = 0x8000, /// the `variadic` parameter in: T foo(T a, U b, V variadic...)
- ctorinit = 0x1_0000, /// can only be set inside constructor
+ // = 0x1_0000,
templateparameter = 0x2_0000, /// template parameter
ref_ = 0x4_0000, /// `ref`
scope_ = 0x8_0000, /// `scope`
@@ -74,7 +74,7 @@ enum STC : ulong // transfer changes to declaration.h
returninferred = 0x100_0000, /// `return` has been inferred and should not be part of mangling, `return_` must also be set
immutable_ = 0x200_0000, /// `immutable`
- init = 0x400_0000, /// has explicit initializer
+ // = 0x400_0000,
manifest = 0x800_0000, /// manifest constant
nodtor = 0x1000_0000, /// do not run destructor
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index 0bf40ef9a72..e8704aabf73 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -929,12 +929,13 @@ extern (C++) final class PragmaDeclaration : AttribDeclaration
(*args)[0] = e;
}
- if (e.isBool(true))
+ const opt = e.toBool();
+ if (opt.isEmpty())
+ return PINLINE.default_;
+ else if (opt.get())
return PINLINE.always;
- else if (e.isBool(false))
- return PINLINE.never;
else
- return PINLINE.default_;
+ return PINLINE.never;
}
override const(char)* kind() const
@@ -1198,7 +1199,7 @@ extern (C++) final class StaticForeachDeclaration : AttribDeclaration
// expand static foreach
import dmd.statementsem: makeTupleForeach;
- Dsymbols* d = makeTupleForeach!(true,true)(_scope, sfe.aggrfe, decl, sfe.needExpansion).decl;
+ Dsymbols* d = makeTupleForeach(_scope, true, true, sfe.aggrfe, decl, sfe.needExpansion).decl;
if (d) // process generated declarations
{
// Add members lazily.
diff --git a/gcc/d/dmd/blockexit.d b/gcc/d/dmd/blockexit.d
index 0ecd6351f7d..5945644482a 100644
--- a/gcc/d/dmd/blockexit.d
+++ b/gcc/d/dmd/blockexit.d
@@ -94,15 +94,15 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
result = BE.fallthru;
if (s.exp)
{
- if (s.exp.op == TOK.halt)
+ if (s.exp.op == EXP.halt)
{
result = BE.halt;
return;
}
- if (s.exp.op == TOK.assert_)
+ if (s.exp.op == EXP.assert_)
{
AssertExp a = cast(AssertExp)s.exp;
- if (a.e1.isBool(false)) // if it's an assert(0)
+ if (a.e1.toBool().hasValue(false)) // if it's an assert(0)
{
result = BE.halt;
return;
@@ -216,7 +216,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
{
if (canThrow(s.condition, func, mustNotThrow))
result |= BE.throw_;
- if (!(result & BE.break_) && s.condition.isBool(true))
+ if (!(result & BE.break_) && s.condition.toBool().hasValue(true))
result &= ~BE.fallthru;
}
result &= ~(BE.break_ | BE.continue_);
@@ -235,9 +235,10 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
{
if (canThrow(s.condition, func, mustNotThrow))
result |= BE.throw_;
- if (s.condition.isBool(true))
+ const opt = s.condition.toBool();
+ if (opt.hasValue(true))
result &= ~BE.fallthru;
- else if (s.condition.isBool(false))
+ else if (opt.hasValue(false))
return;
}
else
@@ -274,11 +275,13 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
result = BE.none;
if (canThrow(s.condition, func, mustNotThrow))
result |= BE.throw_;
- if (s.condition.isBool(true))
+
+ const opt = s.condition.toBool();
+ if (opt.hasValue(true))
{
result |= blockExit(s.ifbody, func, mustNotThrow);
}
- else if (s.condition.isBool(false))
+ else if (opt.hasValue(false))
{
result |= blockExit(s.elsebody, func, mustNotThrow);
}
@@ -534,4 +537,3 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
s.accept(be);
return be.result;
}
-
diff --git a/gcc/d/dmd/builtin.d b/gcc/d/dmd/builtin.d
index c4f84b12968..2f5b6c734a6 100644
--- a/gcc/d/dmd/builtin.d
+++ b/gcc/d/dmd/builtin.d
@@ -13,8 +13,6 @@
module dmd.builtin;
-import core.stdc.math;
-import core.stdc.string;
import dmd.arraytypes;
import dmd.expression;
import dmd.func;
diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d
index ed05af6ac7c..b67a9d14dd4 100644
--- a/gcc/d/dmd/canthrow.d
+++ b/gcc/d/dmd/canthrow.d
@@ -150,7 +150,7 @@ extern (C++) bool canThrow(Expression e, FuncDeclaration func, bool mustNotThrow
override void visit(AssignExp ae)
{
// blit-init cannot throw
- if (ae.op == TOK.blit)
+ if (ae.op == EXP.blit)
return;
/* Element-wise assignment could invoke postblits.
*/
diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d
index da66812b954..c536d25f0a3 100644
--- a/gcc/d/dmd/clone.d
+++ b/gcc/d/dmd/clone.d
@@ -578,7 +578,7 @@ FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc)
fop.generated = true;
Expression e1 = new IdentifierExp(loc, Id.p);
Expression e2 = new IdentifierExp(loc, Id.q);
- Expression e = new EqualExp(TOK.equal, loc, e1, e2);
+ Expression e = new EqualExp(EXP.equal, loc, e1, e2);
fop.fbody = new ReturnStatement(loc, e);
uint errors = global.startGagging(); // Do not report errors
Scope* sc2 = sc.push();
@@ -642,13 +642,13 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc)
Dsymbol s = null;
switch (e.op)
{
- case TOK.overloadSet:
+ case EXP.overloadSet:
s = (cast(OverExp)e).vars;
break;
- case TOK.scope_:
+ case EXP.scope_:
s = (cast(ScopeExp)e).sds;
break;
- case TOK.variable:
+ case EXP.variable:
s = (cast(VarExp)e).var;
break;
default:
diff --git a/gcc/d/dmd/common/outbuffer.h b/gcc/d/dmd/common/outbuffer.h
index a5e3f9c541d..ce23436d782 100644
--- a/gcc/d/dmd/common/outbuffer.h
+++ b/gcc/d/dmd/common/outbuffer.h
@@ -49,7 +49,7 @@ public:
void reserve(d_size_t nbytes);
void setsize(d_size_t size);
void reset();
- void write(const void *data, size_t nbytes);
+ void write(const void *data, d_size_t nbytes);
void writestring(const char *string);
void prependstring(const char *string);
void writenl(); // write newline
diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d
index 05bd4bd550d..abf28144c41 100644
--- a/gcc/d/dmd/cond.d
+++ b/gcc/d/dmd/cond.d
@@ -152,7 +152,7 @@ extern (C++) final class StaticForeach : RootObject
sc = sc.endCTFE();
el = el.optimize(WANTvalue);
el = el.ctfeInterpret();
- if (el.op == TOK.int64)
+ if (el.op == EXP.int64)
{
Expressions *es = void;
if (auto ale = aggr.isArrayLiteralExp())
diff --git a/gcc/d/dmd/constfold.d b/gcc/d/dmd/constfold.d
index 1dada60de3b..3ca23f24d7e 100644
--- a/gcc/d/dmd/constfold.d
+++ b/gcc/d/dmd/constfold.d
@@ -56,13 +56,13 @@ int isConst(Expression e)
//printf("Expression::isConst(): %s\n", e.toChars());
switch (e.op)
{
- case TOK.int64:
- case TOK.float64:
- case TOK.complex80:
+ case EXP.int64:
+ case EXP.float64:
+ case EXP.complex80:
return 1;
- case TOK.null_:
+ case EXP.null_:
return 0;
- case TOK.symbolOffset:
+ case EXP.symbolOffset:
return 2;
default:
return 0;
@@ -71,13 +71,13 @@ int isConst(Expression e)
}
/**********************************
- * Initialize a TOK.cantExpression Expression.
+ * Initialize a EXP.cantExpression Expression.
* Params:
* ue = where to write it
*/
void cantExp(out UnionExp ue)
{
- emplaceExp!(CTFEExp)(&ue, TOK.cantExpression);
+ emplaceExp!(CTFEExp)(&ue, EXP.cantExpression);
}
/* =============================== constFold() ============================== */
@@ -120,7 +120,7 @@ UnionExp Not(Type type, Expression e1)
{
UnionExp ue = void;
Loc loc = e1.loc;
- emplaceExp!(IntegerExp)(&ue, loc, e1.isBool(false) ? 1 : 0, type);
+ emplaceExp!(IntegerExp)(&ue, loc, e1.toBool().hasValue(false) ? 1 : 0, type);
return ue;
}
@@ -128,7 +128,7 @@ private UnionExp Bool(Type type, Expression e1)
{
UnionExp ue = void;
Loc loc = e1.loc;
- emplaceExp!(IntegerExp)(&ue, loc, e1.isBool(true) ? 1 : 0, type);
+ emplaceExp!(IntegerExp)(&ue, loc, e1.toBool().hasValue(true) ? 1 : 0, type);
return ue;
}
@@ -222,13 +222,13 @@ UnionExp Add(const ref Loc loc, Type type, Expression e1, Expression e2)
}
emplaceExp!(ComplexExp)(&ue, loc, v, type);
}
- else if (e1.op == TOK.symbolOffset)
+ else if (e1.op == EXP.symbolOffset)
{
SymOffExp soe = cast(SymOffExp)e1;
emplaceExp!(SymOffExp)(&ue, loc, soe.var, soe.offset + e2.toInteger());
ue.exp().type = type;
}
- else if (e2.op == TOK.symbolOffset)
+ else if (e2.op == EXP.symbolOffset)
{
SymOffExp soe = cast(SymOffExp)e2;
emplaceExp!(SymOffExp)(&ue, loc, soe.var, soe.offset + e1.toInteger());
@@ -325,7 +325,7 @@ UnionExp Min(const ref Loc loc, Type type, Expression e1, Expression e2)
}
emplaceExp!(ComplexExp)(&ue, loc, v, type);
}
- else if (e1.op == TOK.symbolOffset)
+ else if (e1.op == EXP.symbolOffset)
{
SymOffExp soe = cast(SymOffExp)e1;
emplaceExp!(SymOffExp)(&ue, loc, soe.var, soe.offset - e2.toInteger());
@@ -722,26 +722,26 @@ UnionExp Xor(const ref Loc loc, Type type, Expression e1, Expression e2)
return ue;
}
-/* Also returns TOK.cantExpression if cannot be computed.
+/* Also returns EXP.cantExpression if cannot be computed.
*/
-UnionExp Equal(TOK op, const ref Loc loc, Type type, Expression e1, Expression e2)
+UnionExp Equal(EXP op, const ref Loc loc, Type type, Expression e1, Expression e2)
{
UnionExp ue = void;
int cmp = 0;
real_t r1 = CTFloat.zero;
real_t r2 = CTFloat.zero;
//printf("Equal(e1 = %s, e2 = %s)\n", e1.toChars(), e2.toChars());
- assert(op == TOK.equal || op == TOK.notEqual);
- if (e1.op == TOK.null_)
+ assert(op == EXP.equal || op == EXP.notEqual);
+ if (e1.op == EXP.null_)
{
- if (e2.op == TOK.null_)
+ if (e2.op == EXP.null_)
cmp = 1;
- else if (e2.op == TOK.string_)
+ else if (e2.op == EXP.string_)
{
StringExp es2 = cast(StringExp)e2;
cmp = (0 == es2.len);
}
- else if (e2.op == TOK.arrayLiteral)
+ else if (e2.op == EXP.arrayLiteral)
{
ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2;
cmp = !es2.elements || (0 == es2.elements.dim);
@@ -752,14 +752,14 @@ UnionExp Equal(TOK op, const ref Loc loc, Type type, Expression e1, Expression e
return ue;
}
}
- else if (e2.op == TOK.null_)
+ else if (e2.op == EXP.null_)
{
- if (e1.op == TOK.string_)
+ if (e1.op == EXP.string_)
{
StringExp es1 = cast(StringExp)e1;
cmp = (0 == es1.len);
}
- else if (e1.op == TOK.arrayLiteral)
+ else if (e1.op == EXP.arrayLiteral)
{
ArrayLiteralExp es1 = cast(ArrayLiteralExp)e1;
cmp = !es1.elements || (0 == es1.elements.dim);
@@ -770,7 +770,7 @@ UnionExp Equal(TOK op, const ref Loc loc, Type type, Expression e1, Expression e
return ue;
}
}
- else if (e1.op == TOK.string_ && e2.op == TOK.string_)
+ else if (e1.op == EXP.string_ && e2.op == EXP.string_)
{
StringExp es1 = cast(StringExp)e1;
StringExp es2 = cast(StringExp)e2;
@@ -787,7 +787,7 @@ UnionExp Equal(TOK op, const ref Loc loc, Type type, Expression e1, Expression e
else
cmp = 0;
}
- else if (e1.op == TOK.arrayLiteral && e2.op == TOK.arrayLiteral)
+ else if (e1.op == EXP.arrayLiteral && e2.op == EXP.arrayLiteral)
{
ArrayLiteralExp es1 = cast(ArrayLiteralExp)e1;
ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2;
@@ -803,7 +803,7 @@ UnionExp Equal(TOK op, const ref Loc loc, Type type, Expression e1, Expression e
{
auto ee1 = es1[i];
auto ee2 = es2[i];
- ue = Equal(TOK.equal, loc, Type.tint32, ee1, ee2);
+ ue = Equal(EXP.equal, loc, Type.tint32, ee1, ee2);
if (CTFEExp.isCantExp(ue.exp()))
return ue;
cmp = cast(int)ue.exp().toInteger();
@@ -812,7 +812,7 @@ UnionExp Equal(TOK op, const ref Loc loc, Type type, Expression e1, Expression e
}
}
}
- else if (e1.op == TOK.arrayLiteral && e2.op == TOK.string_)
+ else if (e1.op == EXP.arrayLiteral && e2.op == EXP.string_)
{
// Swap operands and use common code
Expression etmp = e1;
@@ -820,7 +820,7 @@ UnionExp Equal(TOK op, const ref Loc loc, Type type, Expression e1, Expression e
e2 = etmp;
goto Lsa;
}
- else if (e1.op == TOK.string_ && e2.op == TOK.arrayLiteral)
+ else if (e1.op == EXP.string_ && e2.op == EXP.arrayLiteral)
{
Lsa:
StringExp es1 = cast(StringExp)e1;
@@ -847,7 +847,7 @@ UnionExp Equal(TOK op, const ref Loc loc, Type type, Expression e1, Expression e
}
}
}
- else if (e1.op == TOK.structLiteral && e2.op == TOK.structLiteral)
+ else if (e1.op == EXP.structLiteral && e2.op == EXP.structLiteral)
{
StructLiteralExp es1 = cast(StructLiteralExp)e1;
StructLiteralExp es2 = cast(StructLiteralExp)e2;
@@ -873,8 +873,8 @@ UnionExp Equal(TOK op, const ref Loc loc, Type type, Expression e1, Expression e
cmp = 0;
break;
}
- ue = Equal(TOK.equal, loc, Type.tint32, ee1, ee2);
- if (ue.exp().op == TOK.cantExpression)
+ ue = Equal(EXP.equal, loc, Type.tint32, ee1, ee2);
+ if (ue.exp().op == EXP.cantExpression)
return ue;
cmp = cast(int)ue.exp().toInteger();
if (cmp == 0)
@@ -920,25 +920,25 @@ UnionExp Equal(TOK op, const ref Loc loc, Type type, Expression e1, Expression e
cantExp(ue);
return ue;
}
- if (op == TOK.notEqual)
+ if (op == EXP.notEqual)
cmp ^= 1;
emplaceExp!(IntegerExp)(&ue, loc, cmp, type);
return ue;
}
-UnionExp Identity(TOK op, const ref Loc loc, Type type, Expression e1, Expression e2)
+UnionExp Identity(EXP op, const ref Loc loc, Type type, Expression e1, Expression e2)
{
UnionExp ue = void;
int cmp;
- if (e1.op == TOK.null_)
+ if (e1.op == EXP.null_)
{
- cmp = (e2.op == TOK.null_);
+ cmp = (e2.op == EXP.null_);
}
- else if (e2.op == TOK.null_)
+ else if (e2.op == EXP.null_)
{
cmp = 0;
}
- else if (e1.op == TOK.symbolOffset && e2.op == TOK.symbolOffset)
+ else if (e1.op == EXP.symbolOffset && e2.op == EXP.symbolOffset)
{
SymOffExp es1 = cast(SymOffExp)e1;
SymOffExp es2 = cast(SymOffExp)e2;
@@ -962,24 +962,24 @@ UnionExp Identity(TOK op, const ref Loc loc, Type type, Expression e1, Expressio
}
else
{
- ue = Equal((op == TOK.identity) ? TOK.equal : TOK.notEqual, loc, type, e1, e2);
+ ue = Equal((op == EXP.identity) ? EXP.equal : EXP.notEqual, loc, type, e1, e2);
return ue;
}
}
- if (op == TOK.notIdentity)
+ if (op == EXP.notIdentity)
cmp ^= 1;
emplaceExp!(IntegerExp)(&ue, loc, cmp, type);
return ue;
}
-UnionExp Cmp(TOK op, const ref Loc loc, Type type, Expression e1, Expression e2)
+UnionExp Cmp(EXP op, const ref Loc loc, Type type, Expression e1, Expression e2)
{
UnionExp ue = void;
dinteger_t n;
real_t r1 = CTFloat.zero;
real_t r2 = CTFloat.zero;
//printf("Cmp(e1 = %s, e2 = %s)\n", e1.toChars(), e2.toChars());
- if (e1.op == TOK.string_ && e2.op == TOK.string_)
+ if (e1.op == EXP.string_ && e2.op == EXP.string_)
{
StringExp es1 = cast(StringExp)e1;
StringExp es2 = cast(StringExp)e2;
@@ -1032,7 +1032,7 @@ UnionExp Cmp(TOK op, const ref Loc loc, Type type, Expression e1, Expression e2)
return ue;
}
-/* Also returns TOK.cantExpression if cannot be computed.
+/* Also returns EXP.cantExpression if cannot be computed.
* to: type to cast to
* type: type to paint the result
*/
@@ -1048,7 +1048,7 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
emplaceExp!(UnionExp)(&ue, e1);
return ue;
}
- if (e1.op == TOK.vector && (cast(TypeVector)e1.type).basetype.equals(type) && type.equals(to))
+ if (e1.op == EXP.vector && (cast(TypeVector)e1.type).basetype.equals(type) && type.equals(to))
{
Expression ex = (cast(VectorExp)e1).e1;
emplaceExp!(UnionExp)(&ue, ex);
@@ -1067,14 +1067,14 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
}
/* Allow casting from one string type to another
*/
- if (e1.op == TOK.string_)
+ if (e1.op == EXP.string_)
{
if (tb.ty == Tarray && typeb.ty == Tarray && tb.nextOf().size() == typeb.nextOf().size())
{
goto L1;
}
}
- if (e1.op == TOK.arrayLiteral && typeb == tb)
+ if (e1.op == EXP.arrayLiteral && typeb == tb)
{
L1:
Expression ex = expType(to, e1);
@@ -1157,7 +1157,7 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
{
cantExp(ue);
}
- else if (tb.ty == Tstruct && e1.op == TOK.int64)
+ else if (tb.ty == Tstruct && e1.op == EXP.int64)
{
// Struct = 0;
StructDeclaration sd = tb.toDsymbol(null).isStructDeclaration();
@@ -1169,7 +1169,7 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
UnionExp zero;
emplaceExp!(IntegerExp)(&zero, 0);
ue = Cast(loc, v.type, v.type, zero.exp());
- if (ue.exp().op == TOK.cantExpression)
+ if (ue.exp().op == EXP.cantExpression)
return ue;
elements.push(ue.exp().copy());
}
@@ -1193,18 +1193,18 @@ UnionExp ArrayLength(Type type, Expression e1)
{
UnionExp ue = void;
Loc loc = e1.loc;
- if (e1.op == TOK.string_)
+ if (e1.op == EXP.string_)
{
StringExp es1 = cast(StringExp)e1;
emplaceExp!(IntegerExp)(&ue, loc, es1.len, type);
}
- else if (e1.op == TOK.arrayLiteral)
+ else if (e1.op == EXP.arrayLiteral)
{
ArrayLiteralExp ale = cast(ArrayLiteralExp)e1;
size_t dim = ale.elements ? ale.elements.dim : 0;
emplaceExp!(IntegerExp)(&ue, loc, dim, type);
}
- else if (e1.op == TOK.assocArrayLiteral)
+ else if (e1.op == EXP.assocArrayLiteral)
{
AssocArrayLiteralExp ale = cast(AssocArrayLiteralExp)e1;
size_t dim = ale.keys.dim;
@@ -1220,7 +1220,7 @@ UnionExp ArrayLength(Type type, Expression e1)
return ue;
}
-/* Also return TOK.cantExpression if this fails
+/* Also return EXP.cantExpression if this fails
*/
UnionExp Index(Type type, Expression e1, Expression e2)
{
@@ -1228,7 +1228,7 @@ UnionExp Index(Type type, Expression e1, Expression e2)
Loc loc = e1.loc;
//printf("Index(e1 = %s, e2 = %s)\n", e1.toChars(), e2.toChars());
assert(e1.type);
- if (e1.op == TOK.string_ && e2.op == TOK.int64)
+ if (e1.op == EXP.string_ && e2.op == EXP.int64)
{
StringExp es1 = cast(StringExp)e1;
uinteger_t i = e2.toInteger();
@@ -1242,7 +1242,7 @@ UnionExp Index(Type type, Expression e1, Expression e2)
emplaceExp!(IntegerExp)(&ue, loc, es1.charAt(i), type);
}
}
- else if (e1.type.toBasetype().ty == Tsarray && e2.op == TOK.int64)
+ else if (e1.type.toBasetype().ty == Tsarray && e2.op == EXP.int64)
{
TypeSArray tsa = cast(TypeSArray)e1.type.toBasetype();
uinteger_t length = tsa.dim.toInteger();
@@ -1252,7 +1252,7 @@ UnionExp Index(Type type, Expression e1, Expression e2)
e1.error("array index %llu is out of bounds `%s[0 .. %llu]`", i, e1.toChars(), length);
emplaceExp!(ErrorExp)(&ue);
}
- else if (e1.op == TOK.arrayLiteral)
+ else if (e1.op == EXP.arrayLiteral)
{
ArrayLiteralExp ale = cast(ArrayLiteralExp)e1;
auto e = ale[cast(size_t)i];
@@ -1266,10 +1266,10 @@ UnionExp Index(Type type, Expression e1, Expression e2)
else
cantExp(ue);
}
- else if (e1.type.toBasetype().ty == Tarray && e2.op == TOK.int64)
+ else if (e1.type.toBasetype().ty == Tarray && e2.op == EXP.int64)
{
uinteger_t i = e2.toInteger();
- if (e1.op == TOK.arrayLiteral)
+ if (e1.op == EXP.arrayLiteral)
{
ArrayLiteralExp ale = cast(ArrayLiteralExp)e1;
if (i >= ale.elements.dim)
@@ -1291,7 +1291,7 @@ UnionExp Index(Type type, Expression e1, Expression e2)
else
cantExp(ue);
}
- else if (e1.op == TOK.assocArrayLiteral)
+ else if (e1.op == EXP.assocArrayLiteral)
{
AssocArrayLiteralExp ae = cast(AssocArrayLiteralExp)e1;
/* Search the keys backwards, in case there are duplicate keys
@@ -1300,10 +1300,10 @@ UnionExp Index(Type type, Expression e1, Expression e2)
{
i--;
Expression ekey = (*ae.keys)[i];
- ue = Equal(TOK.equal, loc, Type.tbool, ekey, e2);
+ ue = Equal(EXP.equal, loc, Type.tbool, ekey, e2);
if (CTFEExp.isCantExp(ue.exp()))
return ue;
- if (ue.exp().isBool(true))
+ if (ue.exp().toBool().hasValue(true))
{
Expression e = (*ae.values)[i];
e.type = type;
@@ -1322,7 +1322,7 @@ UnionExp Index(Type type, Expression e1, Expression e2)
return ue;
}
-/* Also return TOK.cantExpression if this fails
+/* Also return EXP.cantExpression if this fails
*/
UnionExp Slice(Type type, Expression e1, Expression lwr, Expression upr)
{
@@ -1347,7 +1347,7 @@ UnionExp Slice(Type type, Expression e1, Expression lwr, Expression upr)
newupr <= upr);
}
- if (e1.op == TOK.string_ && lwr.op == TOK.int64 && upr.op == TOK.int64)
+ if (e1.op == EXP.string_ && lwr.op == EXP.int64 && upr.op == EXP.int64)
{
StringExp es1 = cast(StringExp)e1;
const uinteger_t ilwr = lwr.toInteger();
@@ -1367,7 +1367,7 @@ UnionExp Slice(Type type, Expression e1, Expression lwr, Expression upr)
es.type = type;
}
}
- else if (e1.op == TOK.arrayLiteral && lwr.op == TOK.int64 && upr.op == TOK.int64 && !hasSideEffect(e1))
+ else if (e1.op == EXP.arrayLiteral && lwr.op == EXP.int64 && upr.op == EXP.int64 && !hasSideEffect(e1))
{
ArrayLiteralExp es1 = cast(ArrayLiteralExp)e1;
const uinteger_t ilwr = lwr.toInteger();
@@ -1480,14 +1480,14 @@ private Expressions* copyElements(Expression e1, Expression e2 = null)
}
}
- if (e1.op == TOK.arrayLiteral)
+ if (e1.op == EXP.arrayLiteral)
append(cast(ArrayLiteralExp)e1);
else
elems.push(e1);
if (e2)
{
- if (e2.op == TOK.arrayLiteral)
+ if (e2.op == EXP.arrayLiteral)
append(cast(ArrayLiteralExp)e2);
else
elems.push(e2);
@@ -1496,7 +1496,7 @@ private Expressions* copyElements(Expression e1, Expression e2 = null)
return elems;
}
-/* Also return TOK.cantExpression if this fails
+/* Also return EXP.cantExpression if this fails
*/
UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
{
@@ -1507,13 +1507,13 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
Type t2 = e2.type.toBasetype();
//printf("Cat(e1 = %s, e2 = %s)\n", e1.toChars(), e2.toChars());
//printf("\tt1 = %s, t2 = %s, type = %s\n", t1.toChars(), t2.toChars(), type.toChars());
- if (e1.op == TOK.null_ && (e2.op == TOK.int64 || e2.op == TOK.structLiteral))
+ if (e1.op == EXP.null_ && (e2.op == EXP.int64 || e2.op == EXP.structLiteral))
{
e = e2;
t = t1;
goto L2;
}
- else if ((e1.op == TOK.int64 || e1.op == TOK.structLiteral) && e2.op == TOK.null_)
+ else if ((e1.op == EXP.int64 || e1.op == EXP.structLiteral) && e2.op == EXP.null_)
{
e = e1;
t = t2;
@@ -1547,7 +1547,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
assert(ue.exp().type);
return ue;
}
- else if (e1.op == TOK.null_ && e2.op == TOK.null_)
+ else if (e1.op == EXP.null_ && e2.op == EXP.null_)
{
if (type == e1.type)
{
@@ -1575,7 +1575,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
assert(ue.exp().type);
return ue;
}
- else if (e1.op == TOK.string_ && e2.op == TOK.string_)
+ else if (e1.op == EXP.string_ && e2.op == EXP.string_)
{
// Concatenate the strings
StringExp es1 = cast(StringExp)e1;
@@ -1604,7 +1604,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
assert(ue.exp().type);
return ue;
}
- else if (e2.op == TOK.string_ && e1.op == TOK.arrayLiteral && t1.nextOf().isintegral())
+ else if (e2.op == EXP.string_ && e1.op == EXP.arrayLiteral && t1.nextOf().isintegral())
{
// [chars] ~ string --> [chars]
StringExp es = cast(StringExp)e2;
@@ -1621,7 +1621,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
assert(ue.exp().type);
return ue;
}
- else if (e1.op == TOK.string_ && e2.op == TOK.arrayLiteral && t2.nextOf().isintegral())
+ else if (e1.op == EXP.string_ && e2.op == EXP.arrayLiteral && t2.nextOf().isintegral())
{
// string ~ [chars] --> [chars]
StringExp es = cast(StringExp)e1;
@@ -1638,7 +1638,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
assert(ue.exp().type);
return ue;
}
- else if (e1.op == TOK.string_ && e2.op == TOK.int64)
+ else if (e1.op == EXP.string_ && e2.op == EXP.int64)
{
// string ~ char --> string
StringExp es1 = cast(StringExp)e1;
@@ -1663,7 +1663,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
assert(ue.exp().type);
return ue;
}
- else if (e1.op == TOK.int64 && e2.op == TOK.string_)
+ else if (e1.op == EXP.int64 && e2.op == EXP.string_)
{
// [w|d]?char ~ string --> string
// We assume that we only ever prepend one char of the same type
@@ -1684,7 +1684,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
assert(ue.exp().type);
return ue;
}
- else if (e1.op == TOK.arrayLiteral && e2.op == TOK.arrayLiteral && t1.nextOf().equals(t2.nextOf()))
+ else if (e1.op == EXP.arrayLiteral && e2.op == EXP.arrayLiteral && t1.nextOf().equals(t2.nextOf()))
{
// Concatenate the arrays
auto elems = copyElements(e1, e2);
@@ -1701,12 +1701,12 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
assert(ue.exp().type);
return ue;
}
- else if (e1.op == TOK.arrayLiteral && e2.op == TOK.null_ && t1.nextOf().equals(t2.nextOf()))
+ else if (e1.op == EXP.arrayLiteral && e2.op == EXP.null_ && t1.nextOf().equals(t2.nextOf()))
{
e = e1;
goto L3;
}
- else if (e1.op == TOK.null_ && e2.op == TOK.arrayLiteral && t1.nextOf().equals(t2.nextOf()))
+ else if (e1.op == EXP.null_ && e2.op == EXP.arrayLiteral && t1.nextOf().equals(t2.nextOf()))
{
e = e2;
L3:
@@ -1725,9 +1725,9 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
assert(ue.exp().type);
return ue;
}
- else if ((e1.op == TOK.arrayLiteral || e1.op == TOK.null_) && e1.type.toBasetype().nextOf() && e1.type.toBasetype().nextOf().equals(e2.type))
+ else if ((e1.op == EXP.arrayLiteral || e1.op == EXP.null_) && e1.type.toBasetype().nextOf() && e1.type.toBasetype().nextOf().equals(e2.type))
{
- auto elems = (e1.op == TOK.arrayLiteral)
+ auto elems = (e1.op == EXP.arrayLiteral)
? copyElements(e1) : new Expressions();
elems.push(e2);
@@ -1743,7 +1743,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
assert(ue.exp().type);
return ue;
}
- else if (e2.op == TOK.arrayLiteral && e2.type.toBasetype().nextOf().equals(e1.type))
+ else if (e2.op == EXP.arrayLiteral && e2.type.toBasetype().nextOf().equals(e1.type))
{
auto elems = copyElements(e1, e2);
@@ -1759,13 +1759,13 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
assert(ue.exp().type);
return ue;
}
- else if (e1.op == TOK.null_ && e2.op == TOK.string_)
+ else if (e1.op == EXP.null_ && e2.op == EXP.string_)
{
t = e1.type;
e = e2;
goto L1;
}
- else if (e1.op == TOK.string_ && e2.op == TOK.null_)
+ else if (e1.op == EXP.string_ && e2.op == EXP.null_)
{
e = e1;
t = e2.type;
@@ -1801,13 +1801,13 @@ UnionExp Ptr(Type type, Expression e1)
{
//printf("Ptr(e1 = %s)\n", e1.toChars());
UnionExp ue = void;
- if (e1.op == TOK.add)
+ if (e1.op == EXP.add)
{
AddExp ae = cast(AddExp)e1;
- if (ae.e1.op == TOK.address && ae.e2.op == TOK.int64)
+ if (ae.e1.op == EXP.address && ae.e2.op == EXP.int64)
{
AddrExp ade = cast(AddrExp)ae.e1;
- if (ade.e1.op == TOK.structLiteral)
+ if (ade.e1.op == EXP.structLiteral)
{
StructLiteralExp se = cast(StructLiteralExp)ade.e1;
uint offset = cast(uint)ae.e2.toInteger();
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 7d8ab67ee6a..dfc45e0bc31 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -212,7 +212,7 @@ final class CParser(AST) : Parser!AST
case TOK.sizeof_:
Lexp:
auto exp = cparseExpression();
- if (token.value == TOK.identifier && exp.op == TOK.identifier)
+ if (token.value == TOK.identifier && exp.op == EXP.identifier)
{
error("found `%s` when expecting `;` or `=`, did you mean `%s %s = %s`?", peek(&token).toChars(), exp.toChars(), token.toChars(), peek(peek(&token)).toChars());
nextToken();
@@ -781,11 +781,11 @@ final class CParser(AST) : Parser!AST
break;
case TOK.plusPlus:
- e = new AST.PostExp(TOK.plusPlus, loc, e);
+ e = new AST.PostExp(EXP.plusPlus, loc, e);
break;
case TOK.minusMinus:
- e = new AST.PostExp(TOK.minusMinus, loc, e);
+ e = new AST.PostExp(EXP.minusMinus, loc, e);
break;
case TOK.leftParenthesis:
@@ -841,14 +841,14 @@ final class CParser(AST) : Parser!AST
// Parse `++` as an unary operator so that cast expressions only give
// an error for being non-lvalues.
e = cparseCastExp();
- e = new AST.PreExp(TOK.prePlusPlus, loc, e);
+ e = new AST.PreExp(EXP.prePlusPlus, loc, e);
break;
case TOK.minusMinus:
nextToken();
// Parse `--` as an unary operator, same as prefix increment.
e = cparseCastExp();
- e = new AST.PreExp(TOK.preMinusMinus, loc, e);
+ e = new AST.PreExp(EXP.preMinusMinus, loc, e);
break;
case TOK.and:
@@ -1122,14 +1122,15 @@ final class CParser(AST) : Parser!AST
const loc = token.loc;
auto e = cparseShiftExp();
- TOK op = token.value;
- switch (op)
+ EXP op = EXP.reserved;
+ switch (token.value)
{
- case TOK.lessThan:
- case TOK.lessOrEqual:
- case TOK.greaterThan:
- case TOK.greaterOrEqual:
+ case TOK.lessThan: op = EXP.lessThan; goto Lcmp;
+ case TOK.lessOrEqual: op = EXP.lessOrEqual; goto Lcmp;
+ case TOK.greaterThan: op = EXP.greaterThan; goto Lcmp;
+ case TOK.greaterOrEqual: op = EXP.greaterOrEqual; goto Lcmp;
+ Lcmp:
nextToken();
auto e2 = cparseShiftExp();
e = new AST.CmpExp(op, loc, e, e2);
@@ -1153,12 +1154,13 @@ final class CParser(AST) : Parser!AST
const loc = token.loc;
auto e = cparseRelationalExp();
- const TOK op = token.value;
- switch (op)
+ EXP op = EXP.reserved;
+ switch (token.value)
{
- case TOK.equal:
- case TOK.notEqual:
+ case TOK.equal: op = EXP.equal; goto Lequal;
+ case TOK.notEqual: op = EXP.notEqual; goto Lequal;
+ Lequal:
nextToken();
auto e2 = cparseRelationalExp();
e = new AST.EqualExp(op, loc, e, e2);
@@ -1245,7 +1247,7 @@ final class CParser(AST) : Parser!AST
{
nextToken();
auto e2 = cparseOrExp();
- e = new AST.LogicalExp(loc, TOK.andAnd, e, e2);
+ e = new AST.LogicalExp(loc, EXP.andAnd, e, e2);
}
return e;
}
@@ -1265,7 +1267,7 @@ final class CParser(AST) : Parser!AST
{
nextToken();
auto e2 = cparseAndAndExp();
- e = new AST.LogicalExp(loc, TOK.orOr, e, e2);
+ e = new AST.LogicalExp(loc, EXP.orOr, e, e2);
}
return e;
}
@@ -1693,7 +1695,11 @@ final class CParser(AST) : Parser!AST
switch (token.value)
{
case TOK.identifier:
- error("missing comma");
+ if (s)
+ {
+ error("missing comma or semicolon after declaration of `%s`, found `%s` instead", s.toChars(), token.toChars());
+ goto Lend;
+ }
goto default;
case TOK.semicolon:
@@ -1707,7 +1713,8 @@ final class CParser(AST) : Parser!AST
break;
default:
- error("`=`, `;` or `,` expected");
+ error("`=`, `;` or `,` expected to end declaration instead of `%s`", token.toChars());
+ Lend:
while (token.value != TOK.semicolon && token.value != TOK.endOfFile)
nextToken();
nextToken();
diff --git a/gcc/d/dmd/cppmangle.d b/gcc/d/dmd/cppmangle.d
index df742c0bd8f..4ad79da02f2 100644
--- a/gcc/d/dmd/cppmangle.d
+++ b/gcc/d/dmd/cppmangle.d
@@ -490,7 +490,7 @@ private final class CppMangleVisitor : Visitor
mangle_function(d.isFuncDeclaration());
buf.writestring("EE");
}
- else if (e && e.op == TOK.variable && (cast(VarExp)e).var.isVarDeclaration())
+ else if (e && e.op == EXP.variable && (cast(VarExp)e).var.isVarDeclaration())
{
VarDeclaration vd = (cast(VarExp)e).var.isVarDeclaration();
buf.writeByte('L');
diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d
index 7f76d7565e0..9cd09bab643 100644
--- a/gcc/d/dmd/ctfeexpr.d
+++ b/gcc/d/dmd/ctfeexpr.d
@@ -46,7 +46,7 @@ extern (C++) final class ClassReferenceExp : Expression
extern (D) this(const ref Loc loc, StructLiteralExp lit, Type type)
{
- super(loc, TOK.classReference, __traits(classInstanceSize, ClassReferenceExp));
+ super(loc, EXP.classReference, __traits(classInstanceSize, ClassReferenceExp));
assert(lit && lit.sd && lit.sd.isClassDeclaration());
this.value = lit;
this.type = type;
@@ -131,7 +131,7 @@ extern (C++) final class ThrownExceptionExp : Expression
extern (D) this(const ref Loc loc, ClassReferenceExp victim)
{
- super(loc, TOK.thrownException, __traits(classInstanceSize, ThrownExceptionExp));
+ super(loc, EXP.thrownException, __traits(classInstanceSize, ThrownExceptionExp));
this.thrown = victim;
this.type = victim.type;
}
@@ -167,7 +167,7 @@ extern (C++) final class ThrownExceptionExp : Expression
*/
extern (C++) final class CTFEExp : Expression
{
- extern (D) this(TOK tok)
+ extern (D) this(EXP tok)
{
super(Loc.initial, tok, __traits(classInstanceSize, CTFEExp));
type = Type.tvoid;
@@ -177,17 +177,17 @@ extern (C++) final class CTFEExp : Expression
{
switch (op)
{
- case TOK.cantExpression:
+ case EXP.cantExpression:
return "<cant>";
- case TOK.voidExpression:
+ case EXP.voidExpression:
return "cast(void)0";
- case TOK.showCtfeContext:
+ case EXP.showCtfeContext:
return "<error>";
- case TOK.break_:
+ case EXP.break_:
return "<break>";
- case TOK.continue_:
+ case EXP.continue_:
return "<continue>";
- case TOK.goto_:
+ case EXP.goto_:
return "<goto>";
default:
assert(0);
@@ -206,19 +206,19 @@ extern (C++) final class CTFEExp : Expression
extern (D) static bool isCantExp(const Expression e)
{
- return e && e.op == TOK.cantExpression;
+ return e && e.op == EXP.cantExpression;
}
extern (D) static bool isGotoExp(const Expression e)
{
- return e && e.op == TOK.goto_;
+ return e && e.op == EXP.goto_;
}
}
// True if 'e' is CTFEExp::cantexp, or an exception
bool exceptionOrCantInterpret(const Expression e)
{
- return e && (e.op == TOK.cantExpression || e.op == TOK.thrownException || e.op == TOK.showCtfeContext);
+ return e && (e.op == EXP.cantExpression || e.op == EXP.thrownException || e.op == EXP.showCtfeContext);
}
/************** Aggregate literals (AA/string/array/struct) ******************/
@@ -231,29 +231,29 @@ bool needToCopyLiteral(const Expression expr)
{
switch (e.op)
{
- case TOK.arrayLiteral:
+ case EXP.arrayLiteral:
return (cast(ArrayLiteralExp)e).ownedByCtfe == OwnedBy.code;
- case TOK.assocArrayLiteral:
+ case EXP.assocArrayLiteral:
return (cast(AssocArrayLiteralExp)e).ownedByCtfe == OwnedBy.code;
- case TOK.structLiteral:
+ case EXP.structLiteral:
return (cast(StructLiteralExp)e).ownedByCtfe == OwnedBy.code;
- case TOK.string_:
- case TOK.this_:
- case TOK.variable:
+ case EXP.string_:
+ case EXP.this_:
+ case EXP.variable:
return false;
- case TOK.assign:
+ case EXP.assign:
return false;
- case TOK.index:
- case TOK.dotVariable:
- case TOK.slice:
- case TOK.cast_:
+ case EXP.index:
+ case EXP.dotVariable:
+ case EXP.slice:
+ case EXP.cast_:
e = (cast(UnaExp)e).e1;
continue;
- case TOK.concatenate:
+ case EXP.concatenate:
return needToCopyLiteral((cast(BinExp)e).e1) || needToCopyLiteral((cast(BinExp)e).e2);
- case TOK.concatenateAssign:
- case TOK.concatenateElemAssign:
- case TOK.concatenateDcharAssign:
+ case EXP.concatenateAssign:
+ case EXP.concatenateElemAssign:
+ case EXP.concatenateDcharAssign:
e = (cast(BinExp)e).e2;
continue;
default:
@@ -358,7 +358,7 @@ UnionExp copyLiteral(Expression e)
r.origin = sle.origin;
return ue;
}
- if (e.op == TOK.function_ || e.op == TOK.delegate_ || e.op == TOK.symbolOffset || e.op == TOK.null_ || e.op == TOK.variable || e.op == TOK.dotVariable || e.op == TOK.int64 || e.op == TOK.float64 || e.op == TOK.char_ || e.op == TOK.complex80 || e.op == TOK.void_ || e.op == TOK.vector || e.op == TOK.typeid_)
+ if (e.op == EXP.function_ || e.op == EXP.delegate_ || e.op == EXP.symbolOffset || e.op == EXP.null_ || e.op == EXP.variable || e.op == EXP.dotVariable || e.op == EXP.int64 || e.op == EXP.float64 || e.op == EXP.char_ || e.op == EXP.complex80 || e.op == EXP.void_ || e.op == EXP.vector || e.op == EXP.typeid_)
{
// Simple value types
// Keep e1 for DelegateExp and DotVarExp
@@ -372,7 +372,7 @@ UnionExp copyLiteral(Expression e)
if (se.type.toBasetype().ty == Tsarray)
{
// same with resolveSlice()
- if (se.e1.op == TOK.null_)
+ if (se.e1.op == EXP.null_)
{
emplaceExp!(NullExp)(&ue, se.loc, se.type);
return ue;
@@ -415,7 +415,7 @@ UnionExp copyLiteral(Expression e)
emplaceExp!(ClassReferenceExp)(&ue, e.loc, cre.value, e.type);
return ue;
}
- if (e.op == TOK.error)
+ if (e.op == EXP.error)
{
emplaceExp!(UnionExp)(&ue, e);
return ue;
@@ -468,11 +468,11 @@ private UnionExp paintTypeOntoLiteralCopy(Type type, Expression lit)
{
emplaceExp!(IndexExp)(&ue, lit.loc, ie.e1, ie.e2);
}
- else if (lit.op == TOK.arrayLiteral)
+ else if (lit.op == EXP.arrayLiteral)
{
emplaceExp!(SliceExp)(&ue, lit.loc, lit, ctfeEmplaceExp!IntegerExp(Loc.initial, 0, Type.tsize_t), ArrayLength(Type.tsize_t, lit).copy());
}
- else if (lit.op == TOK.string_)
+ else if (lit.op == EXP.string_)
{
// For strings, we need to introduce another level of indirection
emplaceExp!(SliceExp)(&ue, lit.loc, lit, ctfeEmplaceExp!IntegerExp(Loc.initial, 0, Type.tsize_t), ArrayLength(Type.tsize_t, lit).copy());
@@ -490,7 +490,7 @@ private UnionExp paintTypeOntoLiteralCopy(Type type, Expression lit)
{
// Can't type paint from struct to struct*; this needs another
// level of indirection
- if (lit.op == TOK.structLiteral && isPointer(type))
+ if (lit.op == EXP.structLiteral && isPointer(type))
lit.error("CTFE internal error: painting `%s`", type.toChars());
ue = copyLiteral(lit);
}
@@ -511,7 +511,7 @@ Expression resolveSlice(Expression e, UnionExp* pue = null)
SliceExp se = e.isSliceExp();
if (!se)
return e;
- if (se.e1.op == TOK.null_)
+ if (se.e1.op == EXP.null_)
return se.e1;
if (pue)
{
@@ -531,13 +531,13 @@ uinteger_t resolveArrayLength(const Expression e)
{
switch (e.op)
{
- case TOK.vector:
+ case EXP.vector:
return e.isVectorExp().dim;
- case TOK.null_:
+ case EXP.null_:
return 0;
- case TOK.slice:
+ case EXP.slice:
{
auto se = cast(SliceExp)e;
const ilo = se.lwr.toInteger();
@@ -545,16 +545,16 @@ uinteger_t resolveArrayLength(const Expression e)
return iup - ilo;
}
- case TOK.string_:
+ case EXP.string_:
return e.isStringExp().len;
- case TOK.arrayLiteral:
+ case EXP.arrayLiteral:
{
const ale = e.isArrayLiteralExp();
return ale.elements ? ale.elements.dim : 0;
}
- case TOK.assocArrayLiteral:
+ case EXP.assocArrayLiteral:
{
return e.isAssocArrayLiteralExp().keys.dim;
}
@@ -667,7 +667,7 @@ bool isPointer(Type t)
// For CTFE only. Returns true if 'e' is true or a non-null pointer.
bool isTrueBool(Expression e)
{
- return e.isBool(true) || ((e.type.ty == Tpointer || e.type.ty == Tclass) && e.op != TOK.null_);
+ return e.toBool().hasValue(true) || ((e.type.ty == Tpointer || e.type.ty == Tclass) && e.op != EXP.null_);
}
/* Is it safe to convert from srcPointee* to destPointee* ?
@@ -725,12 +725,12 @@ Expression getAggregateFromPointer(Expression e, dinteger_t* ofs)
const ex = dve.e1;
const v = dve.var.isVarDeclaration();
assert(v);
- StructLiteralExp se = (ex.op == TOK.classReference)
+ StructLiteralExp se = (ex.op == EXP.classReference)
? (cast(ClassReferenceExp)ex).value
: cast(StructLiteralExp)ex;
// We can't use getField, because it makes a copy
- const i = (ex.op == TOK.classReference)
+ const i = (ex.op == EXP.classReference)
? (cast(ClassReferenceExp)ex).getFieldIndex(e.type, v.offset)
: se.getFieldIndex(e.type, v.offset);
e = (*se.elements)[i];
@@ -738,7 +738,7 @@ Expression getAggregateFromPointer(Expression e, dinteger_t* ofs)
if (auto ie = e.isIndexExp())
{
// Note that each AA element is part of its own memory block
- if ((ie.e1.type.ty == Tarray || ie.e1.type.ty == Tsarray || ie.e1.op == TOK.string_ || ie.e1.op == TOK.arrayLiteral) && ie.e2.op == TOK.int64)
+ if ((ie.e1.type.ty == Tarray || ie.e1.type.ty == Tsarray || ie.e1.op == EXP.string_ || ie.e1.op == EXP.arrayLiteral) && ie.e2.op == EXP.int64)
{
*ofs = ie.e2.toInteger();
return ie.e1;
@@ -747,7 +747,7 @@ Expression getAggregateFromPointer(Expression e, dinteger_t* ofs)
if (auto se = e.isSliceExp())
{
if (se && e.type.toBasetype().ty == Tsarray &&
- (se.e1.type.ty == Tarray || se.e1.type.ty == Tsarray || se.e1.op == TOK.string_ || se.e1.op == TOK.arrayLiteral) && se.lwr.op == TOK.int64)
+ (se.e1.type.ty == Tarray || se.e1.type.ty == Tsarray || se.e1.op == EXP.string_ || se.e1.op == EXP.arrayLiteral) && se.lwr.op == EXP.int64)
{
*ofs = se.lwr.toInteger();
return se.e1;
@@ -773,17 +773,17 @@ bool pointToSameMemoryBlock(Expression agg1, Expression agg2)
return true;
// For integers cast to pointers, we regard them as non-comparable
// unless they are identical. (This may be overly strict).
- if (agg1.op == TOK.int64 && agg2.op == TOK.int64 && agg1.toInteger() == agg2.toInteger())
+ if (agg1.op == EXP.int64 && agg2.op == EXP.int64 && agg1.toInteger() == agg2.toInteger())
{
return true;
}
// Note that type painting can occur with VarExp, so we
// must compare the variables being pointed to.
- if (agg1.op == TOK.variable && agg2.op == TOK.variable && (cast(VarExp)agg1).var == (cast(VarExp)agg2).var)
+ if (agg1.op == EXP.variable && agg2.op == EXP.variable && (cast(VarExp)agg1).var == (cast(VarExp)agg2).var)
{
return true;
}
- if (agg1.op == TOK.symbolOffset && agg2.op == TOK.symbolOffset && (cast(SymOffExp)agg1).var == (cast(SymOffExp)agg2).var)
+ if (agg1.op == EXP.symbolOffset && agg2.op == EXP.symbolOffset && (cast(SymOffExp)agg1).var == (cast(SymOffExp)agg2).var)
{
return true;
}
@@ -803,14 +803,14 @@ UnionExp pointerDifference(const ref Loc loc, Type type, Expression e1, Expressi
const sz = pointee.size();
emplaceExp!(IntegerExp)(&ue, loc, (ofs1 - ofs2) * sz, type);
}
- else if (agg1.op == TOK.string_ && agg2.op == TOK.string_ &&
+ else if (agg1.op == EXP.string_ && agg2.op == EXP.string_ &&
(cast(StringExp)agg1).peekString().ptr == (cast(StringExp)agg2).peekString().ptr)
{
Type pointee = (cast(TypePointer)agg1.type).next;
const sz = pointee.size();
emplaceExp!(IntegerExp)(&ue, loc, (ofs1 - ofs2) * sz, type);
}
- else if (agg1.op == TOK.symbolOffset && agg2.op == TOK.symbolOffset &&
+ else if (agg1.op == EXP.symbolOffset && agg2.op == EXP.symbolOffset &&
(cast(SymOffExp)agg1).var == (cast(SymOffExp)agg2).var)
{
emplaceExp!(IntegerExp)(&ue, loc, ofs1 - ofs2, type);
@@ -818,28 +818,28 @@ UnionExp pointerDifference(const ref Loc loc, Type type, Expression e1, Expressi
else
{
error(loc, "`%s - %s` cannot be interpreted at compile time: cannot subtract pointers to two different memory blocks", e1.toChars(), e2.toChars());
- emplaceExp!(CTFEExp)(&ue, TOK.cantExpression);
+ emplaceExp!(CTFEExp)(&ue, EXP.cantExpression);
}
return ue;
}
// Return eptr op e2, where eptr is a pointer, e2 is an integer,
-// and op is TOK.add or TOK.min
-UnionExp pointerArithmetic(const ref Loc loc, TOK op, Type type, Expression eptr, Expression e2)
+// and op is EXP.add or EXP.min
+UnionExp pointerArithmetic(const ref Loc loc, EXP op, Type type, Expression eptr, Expression e2)
{
UnionExp ue;
if (eptr.type.nextOf().ty == Tvoid)
{
error(loc, "cannot perform arithmetic on `void*` pointers at compile time");
Lcant:
- emplaceExp!(CTFEExp)(&ue, TOK.cantExpression);
+ emplaceExp!(CTFEExp)(&ue, EXP.cantExpression);
return ue;
}
- if (eptr.op == TOK.address)
+ if (eptr.op == EXP.address)
eptr = (cast(AddrExp)eptr).e1;
dinteger_t ofs1;
Expression agg1 = getAggregateFromPointer(eptr, &ofs1);
- if (agg1.op == TOK.symbolOffset)
+ if (agg1.op == EXP.symbolOffset)
{
if ((cast(SymOffExp)agg1).var.type.ty != Tsarray)
{
@@ -847,7 +847,7 @@ UnionExp pointerArithmetic(const ref Loc loc, TOK op, Type type, Expression eptr
goto Lcant;
}
}
- else if (agg1.op != TOK.string_ && agg1.op != TOK.arrayLiteral)
+ else if (agg1.op != EXP.string_ && agg1.op != EXP.arrayLiteral)
{
error(loc, "cannot perform pointer arithmetic on non-arrays at compile time");
goto Lcant;
@@ -857,7 +857,7 @@ UnionExp pointerArithmetic(const ref Loc loc, TOK op, Type type, Expression eptr
dinteger_t sz = pointee.size();
sinteger_t indx;
dinteger_t len;
- if (agg1.op == TOK.symbolOffset)
+ if (agg1.op == EXP.symbolOffset)
{
indx = ofs1 / sz;
len = (cast(TypeSArray)(cast(SymOffExp)agg1).var.type).dim.toInteger();
@@ -869,9 +869,9 @@ UnionExp pointerArithmetic(const ref Loc loc, TOK op, Type type, Expression eptr
indx = ofs1;
len = dollar.toInteger();
}
- if (op == TOK.add || op == TOK.addAssign || op == TOK.plusPlus)
+ if (op == EXP.add || op == EXP.addAssign || op == EXP.plusPlus)
indx += ofs2 / sz;
- else if (op == TOK.min || op == TOK.minAssign || op == TOK.minusMinus)
+ else if (op == EXP.min || op == EXP.minAssign || op == EXP.minusMinus)
indx -= ofs2 / sz;
else
{
@@ -883,14 +883,14 @@ UnionExp pointerArithmetic(const ref Loc loc, TOK op, Type type, Expression eptr
error(loc, "cannot assign pointer to index %lld inside memory block `[0..%lld]`", indx, len);
goto Lcant;
}
- if (agg1.op == TOK.symbolOffset)
+ if (agg1.op == EXP.symbolOffset)
{
emplaceExp!(SymOffExp)(&ue, loc, (cast(SymOffExp)agg1).var, indx * sz);
SymOffExp se = cast(SymOffExp)ue.exp();
se.type = type;
return ue;
}
- if (agg1.op != TOK.arrayLiteral && agg1.op != TOK.string_)
+ if (agg1.op != EXP.arrayLiteral && agg1.op != EXP.string_)
{
error(loc, "CTFE internal error: pointer arithmetic `%s`", agg1.toChars());
goto Lcant;
@@ -918,31 +918,31 @@ UnionExp pointerArithmetic(const ref Loc loc, TOK op, Type type, Expression eptr
// Return 1 if true, 0 if false
// -1 if comparison is illegal because they point to non-comparable memory blocks
-int comparePointers(TOK op, Expression agg1, dinteger_t ofs1, Expression agg2, dinteger_t ofs2)
+int comparePointers(EXP op, Expression agg1, dinteger_t ofs1, Expression agg2, dinteger_t ofs2)
{
if (pointToSameMemoryBlock(agg1, agg2))
{
int n;
switch (op)
{
- case TOK.lessThan:
+ case EXP.lessThan:
n = (ofs1 < ofs2);
break;
- case TOK.lessOrEqual:
+ case EXP.lessOrEqual:
n = (ofs1 <= ofs2);
break;
- case TOK.greaterThan:
+ case EXP.greaterThan:
n = (ofs1 > ofs2);
break;
- case TOK.greaterOrEqual:
+ case EXP.greaterOrEqual:
n = (ofs1 >= ofs2);
break;
- case TOK.identity:
- case TOK.equal:
+ case EXP.identity:
+ case EXP.equal:
n = (ofs1 == ofs2);
break;
- case TOK.notIdentity:
- case TOK.notEqual:
+ case EXP.notIdentity:
+ case EXP.notEqual:
n = (ofs1 != ofs2);
break;
default:
@@ -950,29 +950,29 @@ int comparePointers(TOK op, Expression agg1, dinteger_t ofs1, Expression agg2, d
}
return n;
}
- const null1 = (agg1.op == TOK.null_);
- const null2 = (agg2.op == TOK.null_);
+ const null1 = (agg1.op == EXP.null_);
+ const null2 = (agg2.op == EXP.null_);
int cmp;
if (null1 || null2)
{
switch (op)
{
- case TOK.lessThan:
+ case EXP.lessThan:
cmp = null1 && !null2;
break;
- case TOK.greaterThan:
+ case EXP.greaterThan:
cmp = !null1 && null2;
break;
- case TOK.lessOrEqual:
+ case EXP.lessOrEqual:
cmp = null1;
break;
- case TOK.greaterOrEqual:
+ case EXP.greaterOrEqual:
cmp = null2;
break;
- case TOK.identity:
- case TOK.equal:
- case TOK.notIdentity: // 'cmp' gets inverted below
- case TOK.notEqual:
+ case EXP.identity:
+ case EXP.equal:
+ case EXP.notIdentity: // 'cmp' gets inverted below
+ case EXP.notEqual:
cmp = (null1 == null2);
break;
default:
@@ -983,17 +983,17 @@ int comparePointers(TOK op, Expression agg1, dinteger_t ofs1, Expression agg2, d
{
switch (op)
{
- case TOK.identity:
- case TOK.equal:
- case TOK.notIdentity: // 'cmp' gets inverted below
- case TOK.notEqual:
+ case EXP.identity:
+ case EXP.equal:
+ case EXP.notIdentity: // 'cmp' gets inverted below
+ case EXP.notEqual:
cmp = 0;
break;
default:
return -1; // memory blocks are different
}
}
- if (op == TOK.notIdentity || op == TOK.notEqual)
+ if (op == EXP.notIdentity || op == EXP.notEqual)
cmp ^= 1;
return cmp;
}
@@ -1019,35 +1019,35 @@ Expression paintFloatInt(UnionExp* pue, Expression fromVal, Type to)
/// with >,is, ==, etc, using ctfeCmp, ctfeEqual, ctfeIdentity
bool isCtfeComparable(Expression e)
{
- if (e.op == TOK.slice)
+ if (e.op == EXP.slice)
e = (cast(SliceExp)e).e1;
if (e.isConst() != 1)
{
- if (e.op == TOK.null_ || e.op == TOK.string_ || e.op == TOK.function_ || e.op == TOK.delegate_ || e.op == TOK.arrayLiteral || e.op == TOK.structLiteral || e.op == TOK.assocArrayLiteral || e.op == TOK.classReference)
+ if (e.op == EXP.null_ || e.op == EXP.string_ || e.op == EXP.function_ || e.op == EXP.delegate_ || e.op == EXP.arrayLiteral || e.op == EXP.structLiteral || e.op == EXP.assocArrayLiteral || e.op == EXP.classReference)
{
return true;
}
// https://issues.dlang.org/show_bug.cgi?id=14123
// TypeInfo object is comparable in CTFE
- if (e.op == TOK.typeid_)
+ if (e.op == EXP.typeid_)
return true;
return false;
}
return true;
}
-/// Map TOK comparison ops
-private bool numCmp(N)(TOK op, N n1, N n2)
+/// Map EXP comparison ops
+private bool numCmp(N)(EXP op, N n1, N n2)
{
switch (op)
{
- case TOK.lessThan:
+ case EXP.lessThan:
return n1 < n2;
- case TOK.lessOrEqual:
+ case EXP.lessOrEqual:
return n1 <= n2;
- case TOK.greaterThan:
+ case EXP.greaterThan:
return n1 > n2;
- case TOK.greaterOrEqual:
+ case EXP.greaterOrEqual:
return n1 >= n2;
default:
@@ -1056,35 +1056,35 @@ private bool numCmp(N)(TOK op, N n1, N n2)
}
/// Returns cmp OP 0; where OP is ==, !=, <, >=, etc. Result is 0 or 1
-bool specificCmp(TOK op, int rawCmp)
+bool specificCmp(EXP op, int rawCmp)
{
return numCmp!int(op, rawCmp, 0);
}
/// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1
-bool intUnsignedCmp(TOK op, dinteger_t n1, dinteger_t n2)
+bool intUnsignedCmp(EXP op, dinteger_t n1, dinteger_t n2)
{
return numCmp!dinteger_t(op, n1, n2);
}
/// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1
-bool intSignedCmp(TOK op, sinteger_t n1, sinteger_t n2)
+bool intSignedCmp(EXP op, sinteger_t n1, sinteger_t n2)
{
return numCmp!sinteger_t(op, n1, n2);
}
/// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1
-bool realCmp(TOK op, real_t r1, real_t r2)
+bool realCmp(EXP op, real_t r1, real_t r2)
{
// Don't rely on compiler, handle NAN arguments separately
if (CTFloat.isNaN(r1) || CTFloat.isNaN(r2)) // if unordered
{
switch (op)
{
- case TOK.lessThan:
- case TOK.lessOrEqual:
- case TOK.greaterThan:
- case TOK.greaterOrEqual:
+ case EXP.lessThan:
+ case EXP.lessOrEqual:
+ case EXP.greaterThan:
+ case EXP.greaterOrEqual:
return false;
default:
@@ -1128,7 +1128,7 @@ private int ctfeCmpArrays(const ref Loc loc, Expression e1, Expression e2, uinte
auto se2 = x2.isStringExp();
auto ae2 = x2.isArrayLiteralExp();
- // Now both must be either TOK.arrayLiteral or TOK.string_
+ // Now both must be either EXP.arrayLiteral or EXP.string_
if (se1 && se2)
return sliceCmpStringWithString(se1, se2, cast(size_t)lo1, cast(size_t)lo2, cast(size_t)len);
if (se1 && ae2)
@@ -1171,13 +1171,13 @@ private FuncDeclaration funcptrOf(Expression e)
return de.func;
if (auto fe = e.isFuncExp())
return fe.fd;
- assert(e.op == TOK.null_);
+ assert(e.op == EXP.null_);
return null;
}
private bool isArray(const Expression e)
{
- return e.op == TOK.arrayLiteral || e.op == TOK.string_ || e.op == TOK.slice || e.op == TOK.null_;
+ return e.op == EXP.arrayLiteral || e.op == EXP.string_ || e.op == EXP.slice || e.op == EXP.null_;
}
/*****
@@ -1192,14 +1192,14 @@ private bool isArray(const Expression e)
*/
private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool identity = false)
{
- if (e1.op == TOK.classReference || e2.op == TOK.classReference)
+ if (e1.op == EXP.classReference || e2.op == EXP.classReference)
{
- if (e1.op == TOK.classReference && e2.op == TOK.classReference &&
+ if (e1.op == EXP.classReference && e2.op == EXP.classReference &&
(cast(ClassReferenceExp)e1).value == (cast(ClassReferenceExp)e2).value)
return 0;
return 1;
}
- if (e1.op == TOK.typeid_ && e2.op == TOK.typeid_)
+ if (e1.op == EXP.typeid_ && e2.op == EXP.typeid_)
{
// printf("e1: %s\n", e1.toChars());
// printf("e2: %s\n", e2.toChars());
@@ -1210,7 +1210,7 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
return t1 != t2;
}
// null == null, regardless of type
- if (e1.op == TOK.null_ && e2.op == TOK.null_)
+ if (e1.op == EXP.null_ && e2.op == EXP.null_)
return 0;
if (e1.type.ty == Tpointer && e2.type.ty == Tpointer)
{
@@ -1218,7 +1218,7 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
dinteger_t ofs1, ofs2;
Expression agg1 = getAggregateFromPointer(e1, &ofs1);
Expression agg2 = getAggregateFromPointer(e2, &ofs2);
- if ((agg1 == agg2) || (agg1.op == TOK.variable && agg2.op == TOK.variable && (cast(VarExp)agg1).var == (cast(VarExp)agg2).var))
+ if ((agg1 == agg2) || (agg1.op == EXP.variable && agg2.op == EXP.variable && (cast(VarExp)agg1).var == (cast(VarExp)agg2).var))
{
if (ofs1 == ofs2)
return 0;
@@ -1232,17 +1232,17 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
return 1;
// If both are delegate literals, assume they have the
// same closure pointer. TODO: We don't support closures yet!
- if (e1.op == TOK.function_ && e2.op == TOK.function_)
+ if (e1.op == EXP.function_ && e2.op == EXP.function_)
return 0;
- assert(e1.op == TOK.delegate_ && e2.op == TOK.delegate_);
+ assert(e1.op == EXP.delegate_ && e2.op == EXP.delegate_);
// Same .funcptr. Do they have the same .ptr?
Expression ptr1 = (cast(DelegateExp)e1).e1;
Expression ptr2 = (cast(DelegateExp)e2).e1;
dinteger_t ofs1, ofs2;
Expression agg1 = getAggregateFromPointer(ptr1, &ofs1);
Expression agg2 = getAggregateFromPointer(ptr2, &ofs2);
- // If they are TOK.variable, it means they are FuncDeclarations
- if ((agg1 == agg2 && ofs1 == ofs2) || (agg1.op == TOK.variable && agg2.op == TOK.variable && (cast(VarExp)agg1).var == (cast(VarExp)agg2).var))
+ // If they are EXP.variable, it means they are FuncDeclarations
+ if ((agg1 == agg2 && ofs1 == ofs2) || (agg1.op == EXP.variable && agg2.op == EXP.variable && (cast(VarExp)agg1).var == (cast(VarExp)agg2).var))
{
return 0;
}
@@ -1293,7 +1293,7 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
}
return c1 != c2;
}
- if (e1.op == TOK.structLiteral && e2.op == TOK.structLiteral)
+ if (e1.op == EXP.structLiteral && e2.op == EXP.structLiteral)
{
StructLiteralExp es1 = cast(StructLiteralExp)e1;
StructLiteralExp es2 = cast(StructLiteralExp)e2;
@@ -1314,7 +1314,7 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
Expression ee2 = (*es2.elements)[i];
// https://issues.dlang.org/show_bug.cgi?id=16284
- if (ee1.op == TOK.void_ && ee2.op == TOK.void_) // if both are VoidInitExp
+ if (ee1.op == EXP.void_ && ee2.op == EXP.void_) // if both are VoidInitExp
continue;
if (ee1 == ee2)
@@ -1328,7 +1328,7 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
return 0; // All elements are equal
}
}
- if (e1.op == TOK.assocArrayLiteral && e2.op == TOK.assocArrayLiteral)
+ if (e1.op == EXP.assocArrayLiteral && e2.op == EXP.assocArrayLiteral)
{
AssocArrayLiteralExp es1 = cast(AssocArrayLiteralExp)e1;
AssocArrayLiteralExp es2 = cast(AssocArrayLiteralExp)e2;
@@ -1367,27 +1367,27 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
}
/// Evaluate ==, !=. Resolves slices before comparing. Returns 0 or 1
-bool ctfeEqual(const ref Loc loc, TOK op, Expression e1, Expression e2)
+bool ctfeEqual(const ref Loc loc, EXP op, Expression e1, Expression e2)
{
- return !ctfeRawCmp(loc, e1, e2) ^ (op == TOK.notEqual);
+ return !ctfeRawCmp(loc, e1, e2) ^ (op == EXP.notEqual);
}
/// Evaluate is, !is. Resolves slices before comparing. Returns 0 or 1
-bool ctfeIdentity(const ref Loc loc, TOK op, Expression e1, Expression e2)
+bool ctfeIdentity(const ref Loc loc, EXP op, Expression e1, Expression e2)
{
//printf("ctfeIdentity %s %s\n", e1.toChars(), e2.toChars());
- //printf("ctfeIdentity op = '%s', e1 = %s %s, e2 = %s %s\n", Token::toChars(op),
- // Token::toChars(e1.op), e1.toChars(), Token::toChars(e2.op), e1.toChars());
+ //printf("ctfeIdentity op = '%s', e1 = %s %s, e2 = %s %s\n", EXPtoString(op).ptr,
+ // EXPtoString(e1.op).ptr, e1.toChars(), EXPtoString(e2.op).ptr, e1.toChars());
bool cmp;
- if (e1.op == TOK.null_)
+ if (e1.op == EXP.null_)
{
- cmp = (e2.op == TOK.null_);
+ cmp = (e2.op == EXP.null_);
}
- else if (e2.op == TOK.null_)
+ else if (e2.op == EXP.null_)
{
cmp = false;
}
- else if (e1.op == TOK.symbolOffset && e2.op == TOK.symbolOffset)
+ else if (e1.op == EXP.symbolOffset && e2.op == EXP.symbolOffset)
{
SymOffExp es1 = cast(SymOffExp)e1;
SymOffExp es2 = cast(SymOffExp)e2;
@@ -1407,13 +1407,13 @@ bool ctfeIdentity(const ref Loc loc, TOK op, Expression e1, Expression e2)
{
cmp = !ctfeRawCmp(loc, e1, e2, true);
}
- if (op == TOK.notIdentity || op == TOK.notEqual)
+ if (op == EXP.notIdentity || op == EXP.notEqual)
cmp ^= true;
return cmp;
}
/// Evaluate >,<=, etc. Resolves slices before comparing. Returns 0 or 1
-bool ctfeCmp(const ref Loc loc, TOK op, Expression e1, Expression e2)
+bool ctfeCmp(const ref Loc loc, EXP op, Expression e1, Expression e2)
{
Type t1 = e1.type.toBasetype();
Type t2 = e2.type.toBasetype();
@@ -1435,7 +1435,7 @@ UnionExp ctfeCat(const ref Loc loc, Type type, Expression e1, Expression e2)
Type t1 = e1.type.toBasetype();
Type t2 = e2.type.toBasetype();
UnionExp ue;
- if (e2.op == TOK.string_ && e1.op == TOK.arrayLiteral && t1.nextOf().isintegral())
+ if (e2.op == EXP.string_ && e1.op == EXP.arrayLiteral && t1.nextOf().isintegral())
{
// [chars] ~ string => string (only valid for CTFE)
StringExp es1 = cast(StringExp)e2;
@@ -1448,9 +1448,9 @@ UnionExp ctfeCat(const ref Loc loc, Type type, Expression e1, Expression e2)
foreach (size_t i; 0 .. es2.elements.dim)
{
Expression es2e = (*es2.elements)[i];
- if (es2e.op != TOK.int64)
+ if (es2e.op != EXP.int64)
{
- emplaceExp!(CTFEExp)(&ue, TOK.cantExpression);
+ emplaceExp!(CTFEExp)(&ue, EXP.cantExpression);
return ue;
}
dinteger_t v = es2e.toInteger();
@@ -1464,7 +1464,7 @@ UnionExp ctfeCat(const ref Loc loc, Type type, Expression e1, Expression e2)
es.type = type;
return ue;
}
- if (e1.op == TOK.string_ && e2.op == TOK.arrayLiteral && t2.nextOf().isintegral())
+ if (e1.op == EXP.string_ && e2.op == EXP.arrayLiteral && t2.nextOf().isintegral())
{
// string ~ [chars] => string (only valid for CTFE)
// Concatenate the strings
@@ -1478,9 +1478,9 @@ UnionExp ctfeCat(const ref Loc loc, Type type, Expression e1, Expression e2)
foreach (size_t i; 0 .. es2.elements.dim)
{
Expression es2e = (*es2.elements)[i];
- if (es2e.op != TOK.int64)
+ if (es2e.op != EXP.int64)
{
- emplaceExp!(CTFEExp)(&ue, TOK.cantExpression);
+ emplaceExp!(CTFEExp)(&ue, EXP.cantExpression);
return ue;
}
const v = es2e.toInteger();
@@ -1495,7 +1495,7 @@ UnionExp ctfeCat(const ref Loc loc, Type type, Expression e1, Expression e2)
es.type = type;
return ue;
}
- if (e1.op == TOK.arrayLiteral && e2.op == TOK.arrayLiteral && t1.nextOf().equals(t2.nextOf()))
+ if (e1.op == EXP.arrayLiteral && e2.op == EXP.arrayLiteral && t1.nextOf().equals(t2.nextOf()))
{
// [ e1 ] ~ [ e2 ] ---> [ e1, e2 ]
ArrayLiteralExp es1 = cast(ArrayLiteralExp)e1;
@@ -1505,13 +1505,13 @@ UnionExp ctfeCat(const ref Loc loc, Type type, Expression e1, Expression e2)
es1.elements.insert(es1.elements.dim, copyLiteralArray(es2.elements));
return ue;
}
- if (e1.op == TOK.arrayLiteral && e2.op == TOK.null_ && t1.nextOf().equals(t2.nextOf()))
+ if (e1.op == EXP.arrayLiteral && e2.op == EXP.null_ && t1.nextOf().equals(t2.nextOf()))
{
// [ e1 ] ~ null ----> [ e1 ].dup
ue = paintTypeOntoLiteralCopy(type, copyLiteral(e1).copy());
return ue;
}
- if (e1.op == TOK.null_ && e2.op == TOK.arrayLiteral && t1.nextOf().equals(t2.nextOf()))
+ if (e1.op == EXP.null_ && e2.op == EXP.arrayLiteral && t1.nextOf().equals(t2.nextOf()))
{
// null ~ [ e2 ] ----> [ e2 ].dup
ue = paintTypeOntoLiteralCopy(type, copyLiteral(e2).copy());
@@ -1532,7 +1532,7 @@ Expression findKeyInAA(const ref Loc loc, AssocArrayLiteralExp ae, Expression e2
{
--i;
Expression ekey = (*ae.keys)[i];
- const int eq = ctfeEqual(loc, TOK.equal, ekey, e2);
+ const int eq = ctfeEqual(loc, EXP.equal, ekey, e2);
if (eq)
{
return (*ae.values)[i];
@@ -1581,10 +1581,10 @@ Expression ctfeCast(UnionExp* pue, const ref Loc loc, Type type, Type to, Expres
return paintTypeOntoLiteral(pue, to, e);
}
- if (e.op == TOK.null_)
+ if (e.op == EXP.null_)
return paint();
- if (e.op == TOK.classReference)
+ if (e.op == EXP.classReference)
{
// Disallow reinterpreting class casts. Do this by ensuring that
// the original class can implicitly convert to the target class
@@ -1603,7 +1603,7 @@ Expression ctfeCast(UnionExp* pue, const ref Loc loc, Type type, Type to, Expres
return paint();
// Allow casting away const for struct literals
- if (e.op == TOK.structLiteral && e.type.toBasetype().castMod(0) == to.toBasetype().castMod(0))
+ if (e.op == EXP.structLiteral && e.type.toBasetype().castMod(0) == to.toBasetype().castMod(0))
return paint();
Expression r;
@@ -1647,14 +1647,14 @@ Expression ctfeCast(UnionExp* pue, const ref Loc loc, Type type, Type to, Expres
*/
void assignInPlace(Expression dest, Expression src)
{
- if (!(dest.op == TOK.structLiteral || dest.op == TOK.arrayLiteral || dest.op == TOK.string_))
+ if (!(dest.op == EXP.structLiteral || dest.op == EXP.arrayLiteral || dest.op == EXP.string_))
{
printf("invalid op %d %d\n", src.op, dest.op);
assert(0);
}
Expressions* oldelems;
Expressions* newelems;
- if (dest.op == TOK.structLiteral)
+ if (dest.op == EXP.structLiteral)
{
assert(dest.op == src.op);
oldelems = (cast(StructLiteralExp)dest).elements;
@@ -1666,22 +1666,22 @@ void assignInPlace(Expression dest, Expression src)
foreach (_; 0 .. newelems.dim - oldelems.dim)
oldelems.push(null);
}
- else if (dest.op == TOK.arrayLiteral && src.op == TOK.arrayLiteral)
+ else if (dest.op == EXP.arrayLiteral && src.op == EXP.arrayLiteral)
{
oldelems = (cast(ArrayLiteralExp)dest).elements;
newelems = (cast(ArrayLiteralExp)src).elements;
}
- else if (dest.op == TOK.string_ && src.op == TOK.string_)
+ else if (dest.op == EXP.string_ && src.op == EXP.string_)
{
sliceAssignStringFromString(cast(StringExp)dest, cast(StringExp)src, 0);
return;
}
- else if (dest.op == TOK.arrayLiteral && src.op == TOK.string_)
+ else if (dest.op == EXP.arrayLiteral && src.op == EXP.string_)
{
sliceAssignArrayLiteralFromString(cast(ArrayLiteralExp)dest, cast(StringExp)src, 0);
return;
}
- else if (src.op == TOK.arrayLiteral && dest.op == TOK.string_)
+ else if (src.op == EXP.arrayLiteral && dest.op == EXP.string_)
{
sliceAssignStringFromArrayLiteral(cast(StringExp)dest, cast(ArrayLiteralExp)src, 0);
return;
@@ -1696,12 +1696,12 @@ void assignInPlace(Expression dest, Expression src)
{
Expression e = (*newelems)[i];
Expression o = (*oldelems)[i];
- if (e.op == TOK.structLiteral)
+ if (e.op == EXP.structLiteral)
{
assert(o.op == e.op);
assignInPlace(o, e);
}
- else if (e.type.ty == Tsarray && e.op != TOK.void_ && o.type.ty == Tsarray)
+ else if (e.type.ty == Tsarray && e.op != EXP.void_ && o.type.ty == Tsarray)
{
assignInPlace(o, e);
}
@@ -1724,7 +1724,7 @@ Expression assignAssocArrayElement(const ref Loc loc, AssocArrayLiteralExp aae,
{
j--;
Expression ekey = (*aae.keys)[j];
- int eq = ctfeEqual(loc, TOK.equal, ekey, index);
+ int eq = ctfeEqual(loc, EXP.equal, ekey, index);
if (eq)
{
(*valuesx)[j] = newval;
@@ -1752,13 +1752,13 @@ UnionExp changeArrayLiteralLength(const ref Loc loc, TypeArray arrayType, Expres
auto elements = new Expressions(newlen);
// Resolve slices
size_t indxlo = 0;
- if (oldval.op == TOK.slice)
+ if (oldval.op == EXP.slice)
{
indxlo = cast(size_t)(cast(SliceExp)oldval).lwr.toInteger();
oldval = (cast(SliceExp)oldval).e1;
}
size_t copylen = oldlen < newlen ? oldlen : newlen;
- if (oldval.op == TOK.string_)
+ if (oldval.op == EXP.string_)
{
StringExp oldse = cast(StringExp)oldval;
void* s = mem.xcalloc(newlen + 1, oldse.sz);
@@ -1793,7 +1793,7 @@ UnionExp changeArrayLiteralLength(const ref Loc loc, TypeArray arrayType, Expres
{
if (oldlen != 0)
{
- assert(oldval.op == TOK.arrayLiteral);
+ assert(oldval.op == EXP.arrayLiteral);
ArrayLiteralExp ae = cast(ArrayLiteralExp)oldval;
foreach (size_t i; 0 .. copylen)
(*elements)[i] = (*ae.elements)[indxlo + i];
@@ -1825,13 +1825,13 @@ bool isCtfeValueValid(Expression newval)
Type tb = newval.type.toBasetype();
switch (newval.op)
{
- case TOK.int64:
- case TOK.float64:
- case TOK.char_:
- case TOK.complex80:
+ case EXP.int64:
+ case EXP.float64:
+ case EXP.char_:
+ case EXP.complex80:
return tb.isscalar();
- case TOK.null_:
+ case EXP.null_:
return tb.ty == Tnull ||
tb.ty == Tpointer ||
tb.ty == Tarray ||
@@ -1839,75 +1839,75 @@ bool isCtfeValueValid(Expression newval)
tb.ty == Tclass ||
tb.ty == Tdelegate;
- case TOK.string_:
+ case EXP.string_:
return true; // CTFE would directly use the StringExp in AST.
- case TOK.arrayLiteral:
+ case EXP.arrayLiteral:
return true; //((ArrayLiteralExp *)newval)->ownedByCtfe;
- case TOK.assocArrayLiteral:
+ case EXP.assocArrayLiteral:
return true; //((AssocArrayLiteralExp *)newval)->ownedByCtfe;
- case TOK.structLiteral:
+ case EXP.structLiteral:
return true; //((StructLiteralExp *)newval)->ownedByCtfe;
- case TOK.classReference:
+ case EXP.classReference:
return true;
- case TOK.type:
+ case EXP.type:
return true;
- case TOK.vector:
+ case EXP.vector:
return true; // vector literal
- case TOK.function_:
+ case EXP.function_:
return true; // function literal or delegate literal
- case TOK.delegate_:
+ case EXP.delegate_:
{
// &struct.func or &clasinst.func
// &nestedfunc
Expression ethis = (cast(DelegateExp)newval).e1;
- return (ethis.op == TOK.structLiteral || ethis.op == TOK.classReference || ethis.op == TOK.variable && (cast(VarExp)ethis).var == (cast(DelegateExp)newval).func);
+ return (ethis.op == EXP.structLiteral || ethis.op == EXP.classReference || ethis.op == EXP.variable && (cast(VarExp)ethis).var == (cast(DelegateExp)newval).func);
}
- case TOK.symbolOffset:
+ case EXP.symbolOffset:
{
// function pointer, or pointer to static variable
Declaration d = (cast(SymOffExp)newval).var;
return d.isFuncDeclaration() || d.isDataseg();
}
- case TOK.typeid_:
+ case EXP.typeid_:
{
// always valid
return true;
}
- case TOK.address:
+ case EXP.address:
{
// e1 should be a CTFE reference
Expression e1 = (cast(AddrExp)newval).e1;
return tb.ty == Tpointer &&
(
- (e1.op == TOK.structLiteral || e1.op == TOK.arrayLiteral) && isCtfeValueValid(e1) ||
- e1.op == TOK.variable ||
- e1.op == TOK.dotVariable && isCtfeReferenceValid(e1) ||
- e1.op == TOK.index && isCtfeReferenceValid(e1) ||
- e1.op == TOK.slice && e1.type.toBasetype().ty == Tsarray
+ (e1.op == EXP.structLiteral || e1.op == EXP.arrayLiteral) && isCtfeValueValid(e1) ||
+ e1.op == EXP.variable ||
+ e1.op == EXP.dotVariable && isCtfeReferenceValid(e1) ||
+ e1.op == EXP.index && isCtfeReferenceValid(e1) ||
+ e1.op == EXP.slice && e1.type.toBasetype().ty == Tsarray
);
}
- case TOK.slice:
+ case EXP.slice:
{
// e1 should be an array aggregate
const SliceExp se = cast(SliceExp)newval;
- assert(se.lwr && se.lwr.op == TOK.int64);
- assert(se.upr && se.upr.op == TOK.int64);
- return (tb.ty == Tarray || tb.ty == Tsarray) && (se.e1.op == TOK.string_ || se.e1.op == TOK.arrayLiteral);
+ assert(se.lwr && se.lwr.op == EXP.int64);
+ assert(se.upr && se.upr.op == EXP.int64);
+ return (tb.ty == Tarray || tb.ty == Tsarray) && (se.e1.op == EXP.string_ || se.e1.op == EXP.arrayLiteral);
}
- case TOK.void_:
+ case EXP.void_:
return true; // uninitialized value
default:
@@ -1920,10 +1920,10 @@ bool isCtfeReferenceValid(Expression newval)
{
switch (newval.op)
{
- case TOK.this_:
+ case EXP.this_:
return true;
- case TOK.variable:
+ case EXP.variable:
{
const VarDeclaration v = (cast(VarExp)newval).var.isVarDeclaration();
assert(v);
@@ -1931,16 +1931,16 @@ bool isCtfeReferenceValid(Expression newval)
return true;
}
- case TOK.index:
+ case EXP.index:
{
const Expression eagg = (cast(IndexExp)newval).e1;
- return eagg.op == TOK.string_ || eagg.op == TOK.arrayLiteral || eagg.op == TOK.assocArrayLiteral;
+ return eagg.op == EXP.string_ || eagg.op == EXP.arrayLiteral || eagg.op == EXP.assocArrayLiteral;
}
- case TOK.dotVariable:
+ case EXP.dotVariable:
{
Expression eagg = (cast(DotVarExp)newval).e1;
- return (eagg.op == TOK.structLiteral || eagg.op == TOK.classReference) && isCtfeValueValid(eagg);
+ return (eagg.op == EXP.structLiteral || eagg.op == EXP.classReference) && isCtfeValueValid(eagg);
}
default:
@@ -1959,44 +1959,44 @@ void showCtfeExpr(Expression e, int level = 0)
// We need the struct definition to detect block assignment
StructDeclaration sd = null;
ClassDeclaration cd = null;
- if (e.op == TOK.structLiteral)
+ if (e.op == EXP.structLiteral)
{
elements = (cast(StructLiteralExp)e).elements;
sd = (cast(StructLiteralExp)e).sd;
printf("STRUCT type = %s %p:\n", e.type.toChars(), e);
}
- else if (e.op == TOK.classReference)
+ else if (e.op == EXP.classReference)
{
elements = (cast(ClassReferenceExp)e).value.elements;
cd = (cast(ClassReferenceExp)e).originalClass();
printf("CLASS type = %s %p:\n", e.type.toChars(), (cast(ClassReferenceExp)e).value);
}
- else if (e.op == TOK.arrayLiteral)
+ else if (e.op == EXP.arrayLiteral)
{
elements = (cast(ArrayLiteralExp)e).elements;
printf("ARRAY LITERAL type=%s %p:\n", e.type.toChars(), e);
}
- else if (e.op == TOK.assocArrayLiteral)
+ else if (e.op == EXP.assocArrayLiteral)
{
printf("AA LITERAL type=%s %p:\n", e.type.toChars(), e);
}
- else if (e.op == TOK.string_)
+ else if (e.op == EXP.string_)
{
printf("STRING %s %p\n", e.toChars(), e.isStringExp.peekString.ptr);
}
- else if (e.op == TOK.slice)
+ else if (e.op == EXP.slice)
{
printf("SLICE %p: %s\n", e, e.toChars());
showCtfeExpr((cast(SliceExp)e).e1, level + 1);
}
- else if (e.op == TOK.variable)
+ else if (e.op == EXP.variable)
{
printf("VAR %p %s\n", e, e.toChars());
VarDeclaration v = (cast(VarExp)e).var.isVarDeclaration();
if (v && getValue(v))
showCtfeExpr(getValue(v), level + 1);
}
- else if (e.op == TOK.address)
+ else if (e.op == EXP.address)
{
// This is potentially recursive. We mustn't try to print the thing we're pointing to.
printf("POINTER %p to %p: %s\n", e, (cast(AddrExp)e).e1, e.toChars());
@@ -2069,7 +2069,7 @@ UnionExp voidInitLiteral(Type t, VarDeclaration var)
Expression elem = voidInitLiteral(tsa.next, var).copy();
// For aggregate value types (structs, static arrays) we must
// create an a separate copy for each element.
- const mustCopy = (elem.op == TOK.arrayLiteral || elem.op == TOK.structLiteral);
+ const mustCopy = (elem.op == EXP.arrayLiteral || elem.op == EXP.structLiteral);
const d = cast(size_t)tsa.dim.toInteger();
auto elements = new Expressions(d);
foreach (i; 0 .. d)
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 87c3adae9e6..2e5a79d0feb 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -29,6 +29,7 @@ import dmd.expression;
import dmd.expressionsem;
import dmd.func;
import dmd.globals;
+import dmd.hdrgen;
import dmd.impcnvtab;
import dmd.id;
import dmd.importc;
@@ -994,7 +995,7 @@ MATCH implicitConvTo(Expression e, Type t)
Type typeb = e.type.toBasetype();
// Look for pointers to functions where the functions are overloaded.
- if (e.e1.op == TOK.overloadSet &&
+ if (e.e1.op == EXP.overloadSet &&
(tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
{
OverExp eo = e.e1.isOverExp();
@@ -1019,7 +1020,7 @@ MATCH implicitConvTo(Expression e, Type t)
}
}
- if (e.e1.op == TOK.variable &&
+ if (e.e1.op == EXP.variable &&
typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
tb.ty == Tpointer && tb.nextOf().ty == Tfunction)
{
@@ -1443,7 +1444,7 @@ MATCH implicitConvTo(Expression e, Type t)
}
// Enhancement 10724
- if (tb.ty == Tpointer && e.e1.op == TOK.string_)
+ if (tb.ty == Tpointer && e.e1.op == EXP.string_)
e.e1.accept(this);
}
@@ -1564,7 +1565,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
result = e;
return;
}
- if (e.op == TOK.variable)
+ if (e.op == EXP.variable)
{
VarDeclaration v = (cast(VarExp)e).var.isVarDeclaration();
if (v && v.storage_class & STC.manifest)
@@ -1728,6 +1729,11 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
}
const fsize = t1b.nextOf().size();
const tsize = tob.nextOf().size();
+ if (fsize == SIZE_INVALID || tsize == SIZE_INVALID)
+ {
+ result = ErrorExp.get();
+ return;
+ }
if (fsize != tsize)
{
const dim = t1b.isTypeSArray().dim.toInteger();
@@ -1846,7 +1852,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
override void visit(StructLiteralExp e)
{
visit(cast(Expression)e);
- if (result.op == TOK.structLiteral)
+ if (result.op == EXP.structLiteral)
(cast(StructLiteralExp)result).stype = t; // commit type
}
@@ -1868,6 +1874,13 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
}
StringExp se = e;
+
+ void lcast()
+ {
+ result = new CastExp(e.loc, se, t);
+ result.type = t; // so semantic() won't be run on e
+ }
+
if (!e.committed)
{
se = cast(StringExp)e.copy();
@@ -1942,7 +1955,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
se = cast(StringExp)e.copy();
copied = 1;
}
- goto Lcast;
+ return lcast();
}
if (typeb.ty != Tsarray && typeb.ty != Tarray && typeb.ty != Tpointer)
{
@@ -1951,10 +1964,16 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
se = cast(StringExp)e.copy();
copied = 1;
}
- goto Lcast;
+ return lcast();
}
- if (typeb.nextOf().size() == tb.nextOf().size())
+ const nextSz = typeb.nextOf().size();
+ if (nextSz == SIZE_INVALID)
+ {
+ result = ErrorExp.get();
+ return;
+ }
+ if (nextSz == tb.nextOf().size())
{
if (!copied)
{
@@ -2135,7 +2154,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
}
// Look for pointers to functions where the functions are overloaded.
- if (e.e1.op == TOK.overloadSet &&
+ if (e.e1.op == EXP.overloadSet &&
(tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
{
OverExp eo = cast(OverExp)e.e1;
@@ -2169,7 +2188,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
}
}
- if (e.e1.op == TOK.variable &&
+ if (e.e1.op == EXP.variable &&
typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
tb.ty == Tpointer && tb.nextOf().ty == Tfunction)
{
@@ -2621,7 +2640,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
if (e.e1.implicitConvTo(t1b) > MATCH.nomatch)
{
Expression e1x = e.e1.implicitCastTo(sc, t1b);
- assert(e1x.op != TOK.error);
+ assert(e1x.op != EXP.error);
e = cast(SliceExp)e.copy();
e.e1 = e1x;
e.type = t;
@@ -2732,10 +2751,10 @@ Expression inferType(Expression e, Type t, int flag = 0)
if (t) switch (e.op)
{
- case TOK.arrayLiteral: return visitAle(cast(ArrayLiteralExp) e);
- case TOK.assocArrayLiteral: return visitAar(cast(AssocArrayLiteralExp) e);
- case TOK.function_: return visitFun(cast(FuncExp) e);
- case TOK.question: return visitTer(cast(CondExp) e);
+ case EXP.arrayLiteral: return visitAle(cast(ArrayLiteralExp) e);
+ case EXP.assocArrayLiteral: return visitAar(cast(AssocArrayLiteralExp) e);
+ case EXP.function_: return visitFun(cast(FuncExp) e);
+ case EXP.question: return visitTer(cast(CondExp) e);
default:
}
return e;
@@ -2789,7 +2808,7 @@ Expression scaleFactor(BinExp be, Scope* sc)
if (sc.func && !sc.intypeof)
{
eoff = eoff.optimize(WANTvalue);
- if (eoff.op == TOK.int64 && eoff.toInteger() == 0)
+ if (eoff.op == EXP.int64 && eoff.toInteger() == 0)
{
}
else if (sc.func.setUnsafe())
@@ -2811,7 +2830,7 @@ Expression scaleFactor(BinExp be, Scope* sc)
*/
private bool isVoidArrayLiteral(Expression e, Type other)
{
- while (e.op == TOK.arrayLiteral && e.type.ty == Tarray && ((cast(ArrayLiteralExp)e).elements.dim == 1))
+ while (e.op == EXP.arrayLiteral && e.type.ty == Tarray && ((cast(ArrayLiteralExp)e).elements.dim == 1))
{
auto ale = cast(ArrayLiteralExp)e;
e = ale[0];
@@ -2823,7 +2842,7 @@ private bool isVoidArrayLiteral(Expression e, Type other)
if (other.ty != Tsarray && other.ty != Tarray)
return false;
Type t = e.type;
- return (e.op == TOK.arrayLiteral && t.ty == Tarray && t.nextOf().ty == Tvoid && (cast(ArrayLiteralExp)e).elements.dim == 0);
+ return (e.op == EXP.arrayLiteral && t.ty == Tarray && t.nextOf().ty == Tvoid && (cast(ArrayLiteralExp)e).elements.dim == 0);
}
/**
@@ -2833,7 +2852,7 @@ private bool isVoidArrayLiteral(Expression e, Type other)
*
* Params:
* sc = Current scope
- * op = Operator such as `e1 op e2`. In practice, either TOK.question
+ * op = Operator such as `e1 op e2`. In practice, either EXP.question
* or one of the binary operator.
* pe1 = The LHS of the operation, will be rewritten
* pe2 = The RHS of the operation, will be rewritten
@@ -2841,7 +2860,7 @@ private bool isVoidArrayLiteral(Expression e, Type other)
* Returns:
* The resulting type in case of success, `null` in case of error
*/
-Type typeMerge(Scope* sc, TOK op, ref Expression pe1, ref Expression pe2)
+Type typeMerge(Scope* sc, EXP op, ref Expression pe1, ref Expression pe2)
{
//printf("typeMerge() %s op %s\n", e1.toChars(), e2.toChars());
@@ -2906,9 +2925,9 @@ Type typeMerge(Scope* sc, TOK op, ref Expression pe1, ref Expression pe2)
}
}
- if (op != TOK.question || t1b.ty != t2b.ty && (t1b.isTypeBasic() && t2b.isTypeBasic()))
+ if (op != EXP.question || t1b.ty != t2b.ty && (t1b.isTypeBasic() && t2b.isTypeBasic()))
{
- if (op == TOK.question && t1b.ty.isSomeChar() && t2b.ty.isSomeChar())
+ if (op == EXP.question && t1b.ty.isSomeChar() && t2b.ty.isSomeChar())
{
e1 = e1.castTo(sc, Type.tdchar);
e2 = e2.castTo(sc, Type.tdchar);
@@ -3077,7 +3096,7 @@ Lagain:
return null;
}
- if ((t1.ty == Tsarray || t1.ty == Tarray) && (e2.op == TOK.null_ && t2.ty == Tpointer && t2.nextOf().ty == Tvoid || e2.op == TOK.arrayLiteral && t2.ty == Tsarray && t2.nextOf().ty == Tvoid && t2.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e2, t1)))
+ if ((t1.ty == Tsarray || t1.ty == Tarray) && (e2.op == EXP.null_ && t2.ty == Tpointer && t2.nextOf().ty == Tvoid || e2.op == EXP.arrayLiteral && t2.ty == Tsarray && t2.nextOf().ty == Tvoid && t2.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e2, t1)))
{
/* (T[n] op void*) => T[]
* (T[] op void*) => T[]
@@ -3089,7 +3108,7 @@ Lagain:
return coerce(t1.nextOf().arrayOf());
}
- if ((t2.ty == Tsarray || t2.ty == Tarray) && (e1.op == TOK.null_ && t1.ty == Tpointer && t1.nextOf().ty == Tvoid || e1.op == TOK.arrayLiteral && t1.ty == Tsarray && t1.nextOf().ty == Tvoid && t1.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e1, t2)))
+ if ((t2.ty == Tsarray || t2.ty == Tarray) && (e1.op == EXP.null_ && t1.ty == Tpointer && t1.nextOf().ty == Tvoid || e1.op == EXP.arrayLiteral && t1.ty == Tsarray && t1.nextOf().ty == Tvoid && t1.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e1, t2)))
{
/* (void* op T[n]) => T[]
* (void* op T[]) => T[]
@@ -3107,9 +3126,9 @@ Lagain:
// Tsarray op [x, y, ...] should to be Tsarray
// https://issues.dlang.org/show_bug.cgi?id=14737
// Tsarray ~ [x, y, ...] should to be Tarray
- if (t1.ty == Tsarray && e2.op == TOK.arrayLiteral && op != TOK.concatenate)
+ if (t1.ty == Tsarray && e2.op == EXP.arrayLiteral && op != EXP.concatenate)
return convert(e2, t1);
- if (m == MATCH.constant && (op == TOK.addAssign || op == TOK.minAssign || op == TOK.mulAssign || op == TOK.divAssign || op == TOK.modAssign || op == TOK.powAssign || op == TOK.andAssign || op == TOK.orAssign || op == TOK.xorAssign))
+ if (m == MATCH.constant && (op == EXP.addAssign || op == EXP.minAssign || op == EXP.mulAssign || op == EXP.divAssign || op == EXP.modAssign || op == EXP.powAssign || op == EXP.andAssign || op == EXP.orAssign || op == EXP.xorAssign))
{
// Don't make the lvalue const
return Lret(t2);
@@ -3121,7 +3140,7 @@ Lagain:
{
// https://issues.dlang.org/show_bug.cgi?id=7285
// https://issues.dlang.org/show_bug.cgi?id=14737
- if (t2.ty == Tsarray && e1.op == TOK.arrayLiteral && op != TOK.concatenate)
+ if (t2.ty == Tsarray && e1.op == EXP.arrayLiteral && op != EXP.concatenate)
return convert(e1, t2);
return convert(e2, t1);
}
@@ -3134,9 +3153,9 @@ Lagain:
Type t1n = t1.nextOf();
Type t2n = t2.nextOf();
ubyte mod;
- if (e1.op == TOK.null_ && e2.op != TOK.null_)
+ if (e1.op == EXP.null_ && e2.op != EXP.null_)
mod = t2n.mod;
- else if (e1.op != TOK.null_ && e2.op == TOK.null_)
+ else if (e1.op != EXP.null_ && e2.op == EXP.null_)
mod = t1n.mod;
else if (!t1n.isImmutable() && !t2n.isImmutable() && t1n.isShared() != t2n.isShared())
return null;
@@ -3161,9 +3180,9 @@ Lagain:
if (t1.mod != t2.mod)
{
ubyte mod;
- if (e1.op == TOK.null_ && e2.op != TOK.null_)
+ if (e1.op == EXP.null_ && e2.op != EXP.null_)
mod = t2.mod;
- else if (e1.op != TOK.null_ && e2.op == TOK.null_)
+ else if (e1.op != EXP.null_ && e2.op == EXP.null_)
mod = t1.mod;
else if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared())
return null;
@@ -3352,9 +3371,9 @@ Lagain:
goto Lagain;
}
- if ((e1.op == TOK.string_ || e1.op == TOK.null_) && e1.implicitConvTo(t2))
+ if ((e1.op == EXP.string_ || e1.op == EXP.null_) && e1.implicitConvTo(t2))
return convert(e1, t2);
- if ((e2.op == TOK.string_ || e2.op == TOK.null_) && e2.implicitConvTo(t1))
+ if ((e2.op == EXP.string_ || e2.op == EXP.null_) && e2.implicitConvTo(t1))
return convert(e2, t1);
if (t1.ty == Tsarray && t2.ty == Tsarray && e2.implicitConvTo(t1.nextOf().arrayOf()))
return coerce(t1.nextOf().arrayOf());
@@ -3427,6 +3446,69 @@ LmodCompare:
if (t1.ty == Tnull && (t2.ty == Tpointer || t2.ty == Taarray || t2.ty == Tarray))
return convert(e1, t2);
+ /// Covers array operations for user-defined types
+ Type checkArrayOpType(Expression e1, Expression e2, EXP op, Scope *sc)
+ {
+ // scalar op scalar - we shouldn't be here
+ if (e1.type.ty != Tarray && e1.type.ty != Tsarray && e2.type.ty != Tarray && e2.type.ty != Tsarray)
+ return null;
+
+ // only supporting slices and array literals
+ if (!e1.isSliceExp() && !e1.isArrayLiteralExp() && !e2.isSliceExp() && !e2.isArrayLiteralExp())
+ return null;
+
+ // start with e1 op e2 and if either one of e1 or e2 is a slice or array literal,
+ // replace it with the first element of the array
+ Expression lhs = e1;
+ Expression rhs = e2;
+
+ // T[x .. y] op ?
+ if (e1.isSliceExp())
+ lhs = new IndexExp(Loc.initial, (cast(UnaExp)e1).e1, IntegerExp.literal!0);
+
+ // [t1, t2, .. t3] op ?
+ if (e1.isArrayLiteralExp())
+ lhs = (cast(ArrayLiteralExp)e1).opIndex(0);
+
+ // ? op U[z .. t]
+ if (e2.isSliceExp())
+ rhs = new IndexExp(Loc.initial, (cast(UnaExp)e2).e1, IntegerExp.literal!0);
+
+ // ? op [u1, u2, .. u3]
+ if (e2.isArrayLiteralExp())
+ rhs = (cast(ArrayLiteralExp)e2).opIndex(0);
+
+ // create a new binary expression with the new lhs and rhs (at this stage, at least
+ // one of lhs/rhs has been replaced with the 0'th element of the array it was before)
+ Expression exp;
+ switch (op)
+ {
+ case EXP.add:
+ exp = new AddExp(Loc.initial, lhs, rhs); break;
+ case EXP.min:
+ exp = new MinExp(Loc.initial, lhs, rhs); break;
+ case EXP.mul:
+ exp = new MulExp(Loc.initial, lhs, rhs); break;
+ case EXP.div:
+ exp = new DivExp(Loc.initial, lhs, rhs); break;
+ case EXP.pow:
+ exp = new PowExp(Loc.initial, lhs, rhs); break;
+ default:
+ exp = null;
+ }
+
+ if (exp)
+ {
+ // if T op U is valid and has type V
+ // then T[] op U and T op U[] should be valid and have type V[]
+ Expression e = exp.trySemantic(sc);
+ if (e && e.type)
+ return e.type.arrayOf;
+ }
+
+ return null;
+ }
+
if (t1.ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e1))
{
if (e2.implicitConvTo(t1.nextOf()))
@@ -3463,8 +3545,12 @@ LmodCompare:
e2 = e2.castTo(sc, t);
return Lret(t);
}
- return null;
}
+
+ t = checkArrayOpType(e1, e2, op, sc);
+ if (t !is null)
+ return Lret(t);
+
return null;
}
else if (t2.ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e2))
@@ -3483,15 +3569,19 @@ LmodCompare:
t = e1.type.arrayOf();
}
else
- return null;
+ {
+ t = checkArrayOpType(e1, e2, op, sc);
+ if (t is null)
+ return null;
+ }
- //printf("test %s\n", Token::toChars(op));
+ //printf("test %s\n", EXPtoString(op).ptr);
e1 = e1.optimize(WANTvalue);
if (isCommutative(op) && e1.isConst())
{
/* Swap operands to minimize number of functions generated
*/
- //printf("swap %s\n", Token::toChars(op));
+ //printf("swap %s\n", EXPtoString(op).ptr);
Expression tmp = e1;
e1 = e2;
e2 = tmp;
@@ -3512,7 +3602,7 @@ Expression typeCombine(BinExp be, Scope* sc)
Expression errorReturn()
{
Expression ex = be.incompatibleTypes();
- if (ex.op == TOK.error)
+ if (ex.op == EXP.error)
return ex;
return ErrorExp.get();
}
@@ -3520,7 +3610,7 @@ Expression typeCombine(BinExp be, Scope* sc)
Type t1 = be.e1.type.toBasetype();
Type t2 = be.e2.type.toBasetype();
- if (be.op == TOK.min || be.op == TOK.add)
+ if (be.op == EXP.min || be.op == EXP.add)
{
// struct+struct, and class+class are errors
if (t1.ty == Tstruct && t2.ty == Tstruct)
@@ -3540,9 +3630,9 @@ Expression typeCombine(BinExp be, Scope* sc)
return errorReturn();
// If the types have no value, return an error
- if (be.e1.op == TOK.error)
+ if (be.e1.op == EXP.error)
return be.e1;
- if (be.e2.op == TOK.error)
+ if (be.e2.op == EXP.error)
return be.e2;
return null;
}
@@ -3606,8 +3696,8 @@ void fix16997(Scope* sc, UnaExp ue)
case Tchar:
case Twchar:
case Tdchar:
- ue.deprecation("integral promotion not done for `%s`, use '-preview=intpromote' switch or `%scast(int)(%s)`",
- ue.toChars(), Token.toChars(ue.op), ue.e1.toChars());
+ ue.deprecation("integral promotion not done for `%s`, remove '-revert=intpromote' switch or `%scast(int)(%s)`",
+ ue.toChars(), EXPtoString(ue.op).ptr, ue.e1.toChars());
break;
default:
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index e3f135a03d8..18c8ca2da74 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -94,7 +94,7 @@ bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
((fd.isCtorDeclaration() && var.isField()) ||
(fd.isStaticCtorDeclaration() && !var.isField())) &&
fd.toParentDecl() == var.toParent2() &&
- (!e1 || e1.op == TOK.this_))
+ (!e1 || e1.op == EXP.this_))
{
bool result = true;
@@ -250,7 +250,10 @@ extern (C++) abstract class Declaration : Dsymbol
override final d_uns64 size(const ref Loc loc)
{
assert(type);
- return type.size();
+ const sz = type.size();
+ if (sz == SIZE_INVALID)
+ errors = true;
+ return sz;
}
/**
@@ -371,7 +374,7 @@ extern (C++) abstract class Declaration : Dsymbol
}
}
- if (e1 && e1.op == TOK.this_ && isField())
+ if (e1 && e1.op == EXP.this_ && isField())
{
VarDeclaration vthis = (cast(ThisExp)e1).var;
for (Scope* scx = sc; scx; scx = scx.enclosing)
@@ -385,7 +388,7 @@ extern (C++) abstract class Declaration : Dsymbol
}
}
- if (v && (isCtorinit() || isField()))
+ if (v && (v.isCtorinit() || isField()))
{
// It's only modifiable if inside the right constructor
if ((storage_class & (STC.foreach_ | STC.ref_)) == (STC.foreach_ | STC.ref_))
@@ -434,11 +437,6 @@ extern (C++) abstract class Declaration : Dsymbol
return false;
}
- final bool isCtorinit() const pure nothrow @nogc @safe
- {
- return (storage_class & STC.ctorinit) != 0;
- }
-
final bool isFinal() const pure nothrow @nogc @safe
{
return (storage_class & STC.final_) != 0;
@@ -655,7 +653,7 @@ extern (C++) final class TupleDeclaration : Declaration
if (o.dyncast() == DYNCAST.expression)
{
Expression e = cast(Expression)o;
- if (e.op == TOK.dSymbol)
+ if (e.op == EXP.dSymbol)
{
DsymbolExp ve = cast(DsymbolExp)e;
Declaration d = ve.s.isDeclaration();
@@ -1062,6 +1060,7 @@ extern (C++) class VarDeclaration : Declaration
bool ctorinit; // it has been initialized in a ctor
bool iscatchvar; // this is the exception object variable in catch() clause
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
// Both these mean the var is not rebindable once assigned,
// and the destructor gets run when it goes out of scope
@@ -1131,7 +1130,7 @@ extern (C++) class VarDeclaration : Declaration
RootObject o = (*v2.objects)[i];
assert(o.dyncast() == DYNCAST.expression);
Expression e = cast(Expression)o;
- assert(e.op == TOK.dSymbol);
+ assert(e.op == EXP.dSymbol);
DsymbolExp se = cast(DsymbolExp)e;
se.s.setFieldOffset(ad, fieldState, isunion);
}
@@ -1250,6 +1249,11 @@ extern (C++) class VarDeclaration : Declaration
return false;
}
+ final bool isCtorinit() const pure nothrow @nogc @safe
+ {
+ return setInCtorOnly;
+ }
+
/*******************************
* Does symbol go into data segment?
* Includes extern variables.
@@ -1607,7 +1611,7 @@ extern (C++) class VarDeclaration : Declaration
ExpInitializer ez = _init.isExpInitializer();
assert(ez);
Expression e = ez.exp;
- if (e.op == TOK.construct || e.op == TOK.blit)
+ if (e.op == EXP.construct || e.op == EXP.blit)
e = (cast(AssignExp)e).e2;
return lambdaCheckForNestedRef(e, sc);
}
@@ -1670,11 +1674,11 @@ extern (C++) class VarDeclaration : Declaration
assert(this.loc != Loc.initial);
assert(v.loc != Loc.initial);
- if (auto ld = this.loc.linnum - v.loc.linnum)
- return ld < 0;
+ if (this.loc.linnum != v.loc.linnum)
+ return this.loc.linnum < v.loc.linnum;
- if (auto cd = this.loc.charnum - v.loc.charnum)
- return cd < 0;
+ if (this.loc.charnum != v.loc.charnum)
+ return this.loc.charnum < v.loc.charnum;
// Default fallback
return this.sequenceNumber < v.sequenceNumber;
@@ -1930,9 +1934,9 @@ extern (C++) class BitFieldDeclaration : VarDeclaration
*/
extern (C++) final class SymbolDeclaration : Declaration
{
- StructDeclaration dsym;
+ AggregateDeclaration dsym;
- extern (D) this(const ref Loc loc, StructDeclaration dsym)
+ extern (D) this(const ref Loc loc, AggregateDeclaration dsym)
{
super(loc, dsym.ident);
this.dsym = dsym;
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 4a4c3530417..884146e1416 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -53,7 +53,7 @@ struct IntRange;
#define STCforeach 0x4000ULL /// variable for foreach loop
#define STCvariadic 0x8000ULL /// the `variadic` parameter in: T foo(T a, U b, V variadic...)
- #define STCctorinit 0x10000ULL /// can only be set inside constructor
+ // 0x10000ULL
#define STCtemplateparameter 0x20000ULL /// template parameter
#define STCref 0x40000ULL /// `ref`
#define STCscope 0x80000ULL /// `scope`
@@ -65,7 +65,7 @@ struct IntRange;
#define STCreturninferred 0x1000000ULL /// `return` has been inferred and should not be part of mangling, `return` must also be set
#define STCimmutable 0x2000000ULL /// `immutable`
- #define STCinit 0x4000000ULL /// has explicit initializer
+ // 0x4000000ULL
#define STCmanifest 0x8000000ULL /// manifest constant
#define STCnodtor 0x10000000ULL /// do not run destructor
@@ -131,7 +131,6 @@ public:
virtual bool isDataseg();
virtual bool isThreadlocal();
virtual bool isCodeseg() const;
- bool isCtorinit() const { return (storage_class & STCctorinit) != 0; }
bool isFinal() const { return (storage_class & STCfinal) != 0; }
virtual bool isAbstract() { return (storage_class & STCabstract) != 0; }
bool isConst() const { return (storage_class & STCconst) != 0; }
@@ -247,6 +246,7 @@ public:
bool ctorinit; // it has been initialized in a ctor
bool iscatchvar; // this is the exception object variable in catch() clause
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
@@ -266,6 +266,7 @@ public:
bool needThis();
bool isExport() const;
bool isImportedSymbol() const;
+ bool isCtorinit() const;
bool isDataseg();
bool isThreadlocal();
bool isCTFE();
@@ -303,7 +304,7 @@ public:
class SymbolDeclaration : public Declaration
{
public:
- StructDeclaration *dsym;
+ AggregateDeclaration *dsym;
// Eliminate need for dynamic_cast
SymbolDeclaration *isSymbolDeclaration() { return (SymbolDeclaration *)this; }
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index a1f36c0c48f..891adb3c6bd 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -34,6 +34,7 @@ import dmd.expression;
import dmd.expressionsem;
import dmd.func;
import dmd.globals;
+import dmd.hdrgen;
import dmd.id;
import dmd.identifier;
import dmd.init;
@@ -63,26 +64,26 @@ public Expression ctfeInterpret(Expression e)
{
switch (e.op)
{
- case TOK.int64:
- case TOK.float64:
- case TOK.complex80:
- case TOK.null_:
- case TOK.void_:
- case TOK.string_:
- case TOK.this_:
- case TOK.super_:
- case TOK.type:
- case TOK.typeid_:
- case TOK.template_: // non-eponymous template/instance
- case TOK.scope_: // ditto
- case TOK.dotTemplateDeclaration: // ditto, e.e1 doesn't matter here
- case TOK.dotTemplateInstance: // ditto
- case TOK.dot: // ditto
+ case EXP.int64:
+ case EXP.float64:
+ case EXP.complex80:
+ case EXP.null_:
+ case EXP.void_:
+ case EXP.string_:
+ case EXP.this_:
+ case EXP.super_:
+ case EXP.type:
+ case EXP.typeid_:
+ case EXP.template_: // non-eponymous template/instance
+ case EXP.scope_: // ditto
+ case EXP.dotTemplateDeclaration: // ditto, e.e1 doesn't matter here
+ case EXP.dotTemplateInstance: // ditto
+ case EXP.dot: // ditto
if (e.type.ty == Terror)
return ErrorExp.get();
- goto case TOK.error;
+ goto case EXP.error;
- case TOK.error:
+ case EXP.error:
return e;
default:
@@ -115,7 +116,7 @@ public Expression ctfeInterpret(Expression e)
*/
public Expression ctfeInterpretForPragmaMsg(Expression e)
{
- if (e.op == TOK.error || e.op == TOK.type)
+ if (e.op == EXP.error || e.op == EXP.type)
return e;
// It's also OK for it to be a function declaration (happens only with
@@ -410,7 +411,7 @@ private struct InterState
* thisarg = 'this', if a needThis() function, NULL if not.
*
* Returns:
- * result expression if successful, TOK.cantExpression if not,
+ * result expression if successful, EXP.cantExpression if not,
* or CTFEExp if function returned void.
*/
private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterState* istate, Expressions* arguments, Expression thisarg)
@@ -507,7 +508,7 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
/* Struct literals are passed by value, but we don't need to
* copy them if they are passed as const
*/
- if (earg.op == TOK.structLiteral && !(fparam.storageClass & (STC.const_ | STC.immutable_)))
+ if (earg.op == EXP.structLiteral && !(fparam.storageClass & (STC.const_ | STC.immutable_)))
earg = copyLiteral(earg).copy();
}
if (auto tee = earg.isThrownExceptionExp())
@@ -563,7 +564,7 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
}
ctfeGlobals.stack.push(v);
- if (fparam.isReference() && earg.op == TOK.variable &&
+ if (fparam.isReference() && earg.op == EXP.variable &&
earg.isVarExp().var.toParent2() == fd)
{
VarDeclaration vx = earg.isVarExp().var.isVarDeclaration();
@@ -660,16 +661,16 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
}
else
{
- assert(!e || (e.op != TOK.continue_ && e.op != TOK.break_));
+ assert(!e || (e.op != EXP.continue_ && e.op != EXP.break_));
break;
}
}
// If fell off the end of a void function, return void
if (!e && tf.next.ty == Tvoid)
e = CTFEExp.voidexp;
- if (tf.isref && e.op == TOK.variable && e.isVarExp().var == fd.vthis)
+ if (tf.isref && e.op == EXP.variable && e.isVarExp().var == fd.vthis)
e = thisarg;
- if (tf.isref && fd.isThis2 && e.op == TOK.index)
+ if (tf.isref && fd.isThis2 && e.op == EXP.index)
{
auto ie = e.isIndexExp();
auto pe = ie.e1.isPtrExp();
@@ -733,14 +734,14 @@ public:
this.goal = goal;
}
- // If e is TOK.throw_exception or TOK.cantExpression,
+ // If e is EXP.throw_exception or EXP.cantExpression,
// set it to 'result' and returns true.
bool exceptionOrCant(Expression e)
{
if (exceptionOrCantInterpret(e))
{
// Make sure e is not pointing to a stack temporary
- result = (e.op == TOK.cantExpression) ? CTFEExp.cantexp : e;
+ result = (e.op == EXP.cantExpression) ? CTFEExp.cantexp : e;
return true;
}
return false;
@@ -839,7 +840,7 @@ public:
continue;
if (exceptionOrCant(e))
return;
- if (e.op == TOK.break_)
+ if (e.op == EXP.break_)
{
if (istate.gotoTarget && istate.gotoTarget != s)
{
@@ -850,7 +851,7 @@ public:
result = null;
return;
}
- if (e.op == TOK.continue_)
+ if (e.op == EXP.continue_)
{
if (istate.gotoTarget && istate.gotoTarget != s)
{
@@ -894,7 +895,7 @@ public:
if (isTrueBool(e))
result = interpret(pue, s.ifbody, istate);
- else if (e.isBool(false))
+ else if (e.toBool().hasValue(false))
result = interpret(pue, s.elsebody, istate);
else
{
@@ -935,7 +936,7 @@ public:
if (auto eaddr = e.isAddrExp())
x = eaddr.e1;
VarDeclaration v;
- while (x.op == TOK.variable && (v = (cast(VarExp)x).var.isVarDeclaration()) !is null)
+ while (x.op == EXP.variable && (v = (cast(VarExp)x).var.isVarDeclaration()) !is null)
{
if (v.storage_class & STC.ref_)
{
@@ -952,7 +953,7 @@ public:
else
break;
}
- // TODO: If it is a TOK.dotVariable or TOK.index, we should check that it is not
+ // TODO: If it is a EXP.dotVariable or EXP.index, we should check that it is not
// pointing to a local struct or static array.
}
if (auto se = e.isStructLiteralExp())
@@ -1023,7 +1024,7 @@ public:
return;
}
- // We need to treat pointers specially, because TOK.symbolOffset can be used to
+ // We need to treat pointers specially, because EXP.symbolOffset can be used to
// return a value OR a pointer
Expression e = interpret(pue, s.exp, istate);
if (exceptionOrCant(e))
@@ -1122,7 +1123,7 @@ public:
if (exceptionOrCant(e))
return;
- if (e && e.op == TOK.break_)
+ if (e && e.op == EXP.break_)
{
if (istate.gotoTarget && istate.gotoTarget != s)
{
@@ -1132,7 +1133,7 @@ public:
istate.gotoTarget = null;
break;
}
- if (e && e.op == TOK.continue_)
+ if (e && e.op == EXP.continue_)
{
if (istate.gotoTarget && istate.gotoTarget != s)
{
@@ -1158,7 +1159,7 @@ public:
result = CTFEExp.cantexp;
return;
}
- if (e.isBool(false))
+ if (e.toBool().hasValue(false))
break;
assert(isTrueBool(e));
}
@@ -1189,7 +1190,7 @@ public:
Expression e = interpret(&ue, s.condition, istate);
if (exceptionOrCant(e))
return;
- if (e.isBool(false))
+ if (e.toBool().hasValue(false))
break;
assert(isTrueBool(e));
}
@@ -1201,7 +1202,7 @@ public:
if (exceptionOrCant(e))
return;
- if (e && e.op == TOK.break_)
+ if (e && e.op == EXP.break_)
{
if (istate.gotoTarget && istate.gotoTarget != s)
{
@@ -1211,7 +1212,7 @@ public:
istate.gotoTarget = null;
break;
}
- if (e && e.op == TOK.continue_)
+ if (e && e.op == EXP.continue_)
{
if (istate.gotoTarget && istate.gotoTarget != s)
{
@@ -1263,7 +1264,7 @@ public:
return;
if (exceptionOrCant(e))
return;
- if (e && e.op == TOK.break_)
+ if (e && e.op == EXP.break_)
{
if (istate.gotoTarget && istate.gotoTarget != s)
{
@@ -1290,7 +1291,7 @@ public:
Expression ecase = interpret(&uecase, cs.exp, istate);
if (exceptionOrCant(ecase))
return;
- if (ctfeEqual(cs.exp.loc, TOK.equal, econdition, ecase))
+ if (ctfeEqual(cs.exp.loc, EXP.equal, econdition, ecase))
{
scase = cs;
break;
@@ -1310,7 +1311,7 @@ public:
istate.start = scase;
Expression e = interpret(pue, s._body, istate);
assert(!istate.start); // jump must not fail
- if (e && e.op == TOK.break_)
+ if (e && e.op == EXP.break_)
{
if (istate.gotoTarget && istate.gotoTarget != s)
{
@@ -1515,7 +1516,7 @@ public:
(*collateral.value.elements)[bypass] = boss;
return newest;
}
- while ((*boss.value.elements)[next].op == TOK.classReference)
+ while ((*boss.value.elements)[next].op == EXP.classReference)
{
boss = cast(ClassReferenceExp)(*boss.value.elements)[next];
}
@@ -1606,7 +1607,7 @@ public:
if (exceptionOrCant(e))
return;
- assert(e.op == TOK.classReference);
+ assert(e.op == EXP.classReference);
result = ctfeEmplaceExp!ThrownExceptionExp(s.loc, e.isClassReferenceExp());
}
@@ -1630,7 +1631,7 @@ public:
}
// If it is with(Enum) {...}, just execute the body.
- if (s.exp.op == TOK.scope_ || s.exp.op == TOK.type)
+ if (s.exp.op == EXP.scope_ || s.exp.op == EXP.type)
{
result = interpret(pue, s._body, istate);
return;
@@ -1707,7 +1708,7 @@ public:
{
debug (LOG)
{
- printf("%s Expression::interpret() '%s' %s\n", e.loc.toChars(), Token.toChars(e.op), e.toChars());
+ printf("%s Expression::interpret() '%s' %s\n", e.loc.toChars(), EXPtoString(e.op).ptr, e.toChars());
printf("type = %s\n", e.type.toChars());
showCtfeExpr(e);
}
@@ -1755,9 +1756,9 @@ public:
{
if (istate && istate.fd.isThis2)
{
- assert(result.op == TOK.address);
+ assert(result.op == EXP.address);
result = (cast(AddrExp)result).e1;
- assert(result.op == TOK.arrayLiteral);
+ assert(result.op == EXP.arrayLiteral);
result = (*(cast(ArrayLiteralExp)result).elements)[0];
if (e.type.ty == Tstruct)
{
@@ -1765,7 +1766,7 @@ public:
}
return;
}
- assert(result.op == TOK.structLiteral || result.op == TOK.classReference || result.op == TOK.type);
+ assert(result.op == EXP.structLiteral || result.op == EXP.classReference || result.op == EXP.type);
return;
}
e.error("value of `this` is not known at compile time");
@@ -1909,7 +1910,7 @@ public:
dinteger_t indx = e.offset / sz;
assert(sz * indx == e.offset);
Expression aggregate = null;
- if (val.op == TOK.arrayLiteral || val.op == TOK.string_)
+ if (val.op == EXP.arrayLiteral || val.op == EXP.string_)
{
aggregate = val;
}
@@ -2054,13 +2055,13 @@ public:
return CTFEExp.cantexp;
assert(e.type);
- if (e.op == TOK.construct || e.op == TOK.blit)
+ if (e.op == EXP.construct || e.op == EXP.blit)
{
AssignExp ae = cast(AssignExp)e;
e = ae.e2;
}
- if (e.op == TOK.error)
+ if (e.op == EXP.error)
{
// FIXME: Ultimately all errors should be detected in prior semantic analysis stage.
}
@@ -2142,12 +2143,20 @@ public:
}
else if (SymbolDeclaration s = d.isSymbolDeclaration())
{
+ // exclude void[]-typed `__traits(initSymbol)`
+ if (auto ta = s.type.toBasetype().isTypeDArray())
+ {
+ assert(ta.next.ty == Tvoid);
+ error(loc, "cannot determine the address of the initializer symbol during CTFE");
+ return CTFEExp.cantexp;
+ }
+
// Struct static initializers, for example
e = s.dsym.type.defaultInitLiteral(loc);
- if (e.op == TOK.error)
+ if (e.op == EXP.error)
error(loc, "CTFE failed because of previous errors in `%s.init`", s.toChars());
e = e.expressionSemantic(null);
- if (e.op == TOK.error)
+ if (e.op == EXP.error)
e = CTFEExp.cantexp;
else // Convert NULL to CTFEExp
e = interpret(e, istate, goal);
@@ -2195,10 +2204,10 @@ public:
{
// Strip off the nest of ref variables
Expression ev = getValue(v);
- if (ev.op == TOK.variable ||
- ev.op == TOK.index ||
- (ev.op == TOK.slice && ev.type.toBasetype().ty == Tsarray) ||
- ev.op == TOK.dotVariable)
+ if (ev.op == EXP.variable ||
+ ev.op == EXP.index ||
+ (ev.op == EXP.slice && ev.type.toBasetype().ty == Tsarray) ||
+ ev.op == EXP.dotVariable)
{
result = interpret(pue, ev, istate, goal);
return;
@@ -2363,13 +2372,13 @@ public:
if (exceptionOrCant(ex))
return;
- if (result.op == TOK.null_)
+ if (result.op == EXP.null_)
{
e.error("null pointer dereference evaluating typeid. `%s` is `null`", ex.toChars());
result = CTFEExp.cantexp;
return;
}
- if (result.op != TOK.classReference)
+ if (result.op != EXP.classReference)
{
e.error("CTFE internal error: determining classinfo");
result = CTFEExp.cantexp;
@@ -2406,7 +2415,7 @@ public:
// A tuple of assignments can contain void (Bug 5676).
if (goal == CTFEGoal.Nothing)
continue;
- if (ex.op == TOK.voidExpression)
+ if (ex.op == EXP.voidExpression)
{
e.error("CTFE internal error: void element `%s` in tuple", exp.toChars());
assert(0);
@@ -2464,7 +2473,7 @@ public:
else
{
// segfault bug 6250
- assert(exp.op != TOK.index || (cast(IndexExp)exp).e1 != e);
+ assert(exp.op != EXP.index || (cast(IndexExp)exp).e1 != e);
ex = interpretRegion(exp, istate);
if (exceptionOrCant(ex))
@@ -2569,7 +2578,7 @@ public:
for (size_t j = i; j < keysx.dim; j++)
{
auto ekey2 = (*keysx)[j];
- if (!ctfeEqual(e.loc, TOK.equal, ekey, ekey2))
+ if (!ctfeEqual(e.loc, EXP.equal, ekey, ekey2))
continue;
// Remove ekey
@@ -2904,15 +2913,15 @@ public:
return;
switch (e.op)
{
- case TOK.negate:
+ case EXP.negate:
*pue = Neg(e.type, e1);
break;
- case TOK.tilde:
+ case EXP.tilde:
*pue = Com(e.type, e1);
break;
- case TOK.not:
+ case EXP.not:
*pue = Not(e.type, e1);
break;
@@ -2948,7 +2957,7 @@ public:
{
printf("%s BinExp::interpretCommon() %s\n", e.loc.toChars(), e.toChars());
}
- if (e.e1.type.ty == Tpointer && e.e2.type.ty == Tpointer && e.op == TOK.min)
+ if (e.e1.type.ty == Tpointer && e.e2.type.ty == Tpointer && e.op == EXP.min)
{
UnionExp ue1 = void;
Expression e1 = interpret(&ue1, e.e1, istate);
@@ -2976,7 +2985,7 @@ public:
result = (*pue).exp();
return;
}
- if (e.e2.type.ty == Tpointer && e.e1.type.isintegral() && e.op == TOK.add)
+ if (e.e2.type.ty == Tpointer && e.e1.type.isintegral() && e.op == EXP.add)
{
UnionExp ue1 = void;
Expression e1 = interpret(&ue1, e.e1, istate);
@@ -3015,7 +3024,7 @@ public:
if (!evalOperand(&ue2, e.e2, e2))
return;
- if (e.op == TOK.rightShift || e.op == TOK.leftShift || e.op == TOK.unsignedRightShift)
+ if (e.op == EXP.rightShift || e.op == EXP.leftShift || e.op == EXP.unsignedRightShift)
{
const sinteger_t i2 = e2.toInteger();
const d_uns64 sz = e1.type.size() * 8;
@@ -3073,13 +3082,13 @@ public:
{
// The following should really be an assert()
e1.error("CTFE internal error: non-constant value `%s`", e1.toChars());
- emplaceExp!CTFEExp(&ue, TOK.cantExpression);
+ emplaceExp!CTFEExp(&ue, EXP.cantExpression);
return ue;
}
if (e2.isConst() != 1)
{
e2.error("CTFE internal error: non-constant value `%s`", e2.toChars());
- emplaceExp!CTFEExp(&ue, TOK.cantExpression);
+ emplaceExp!CTFEExp(&ue, EXP.cantExpression);
return ue;
}
@@ -3116,7 +3125,7 @@ public:
const cmp = comparePointers(e.op, agg1, ofs1, agg2, ofs2);
if (cmp == -1)
{
- char dir = (e.op == TOK.greaterThan || e.op == TOK.greaterOrEqual) ? '<' : '>';
+ char dir = (e.op == EXP.greaterThan || e.op == EXP.greaterOrEqual) ? '<' : '>';
e.error("the ordering of pointers to unrelated memory blocks is indeterminate in CTFE. To check if they point to the same memory block, use both `>` and `<` inside `&&` or `||`, eg `%s && %s %c= %s + 1`", e.toChars(), e.e1.toChars(), dir, e.e2.toChars());
result = CTFEExp.cantexp;
return;
@@ -3162,73 +3171,73 @@ public:
{
switch (e.op)
{
- case TOK.add:
+ case EXP.add:
interpretCommon(e, &Add);
return;
- case TOK.min:
+ case EXP.min:
interpretCommon(e, &Min);
return;
- case TOK.mul:
+ case EXP.mul:
interpretCommon(e, &Mul);
return;
- case TOK.div:
+ case EXP.div:
interpretCommon(e, &Div);
return;
- case TOK.mod:
+ case EXP.mod:
interpretCommon(e, &Mod);
return;
- case TOK.leftShift:
+ case EXP.leftShift:
interpretCommon(e, &Shl);
return;
- case TOK.rightShift:
+ case EXP.rightShift:
interpretCommon(e, &Shr);
return;
- case TOK.unsignedRightShift:
+ case EXP.unsignedRightShift:
interpretCommon(e, &Ushr);
return;
- case TOK.and:
+ case EXP.and:
interpretCommon(e, &And);
return;
- case TOK.or:
+ case EXP.or:
interpretCommon(e, &Or);
return;
- case TOK.xor:
+ case EXP.xor:
interpretCommon(e, &Xor);
return;
- case TOK.pow:
+ case EXP.pow:
interpretCommon(e, &Pow);
return;
- case TOK.equal:
- case TOK.notEqual:
+ case EXP.equal:
+ case EXP.notEqual:
interpretCompareCommon(e, &ctfeEqual);
return;
- case TOK.identity:
- case TOK.notIdentity:
+ case EXP.identity:
+ case EXP.notIdentity:
interpretCompareCommon(e, &ctfeIdentity);
return;
- case TOK.lessThan:
- case TOK.lessOrEqual:
- case TOK.greaterThan:
- case TOK.greaterOrEqual:
+ case EXP.lessThan:
+ case EXP.lessOrEqual:
+ case EXP.greaterThan:
+ case EXP.greaterOrEqual:
interpretCompareCommon(e, &ctfeCmp);
return;
default:
- printf("be = '%s' %s at [%s]\n", Token.toChars(e.op), e.toChars(), e.loc.toChars());
+ printf("be = '%s' %s at [%s]\n", EXPtoString(e.op).ptr, e.toChars(), e.loc.toChars());
assert(0);
}
}
@@ -3286,7 +3295,7 @@ public:
* So we need to recurse to determine if it is a block assignment.
*/
bool isBlockAssignment = false;
- if (e1.op == TOK.slice)
+ if (e1.op == EXP.slice)
{
// a[] = e can have const e. So we compare the naked types.
Type tdst = e1.type.toBasetype();
@@ -3306,7 +3315,7 @@ public:
// Deal with reference assignment
// ---------------------------------------
// If it is a construction of a ref variable, it is a ref assignment
- if ((e.op == TOK.construct || e.op == TOK.blit) &&
+ if ((e.op == EXP.construct || e.op == EXP.blit) &&
((cast(AssignExp)e).memset == MemorySet.referenceInit))
{
assert(!fp);
@@ -3329,7 +3338,7 @@ public:
if (fp)
{
- while (e1.op == TOK.cast_)
+ while (e1.op == EXP.cast_)
{
CastExp ce = cast(CastExp)e1;
e1 = ce.e1;
@@ -3342,7 +3351,7 @@ public:
AssocArrayLiteralExp existingAA = null;
Expression lastIndex = null;
Expression oldval = null;
- if (e1.op == TOK.index && (cast(IndexExp)e1).e1.type.toBasetype().ty == Taarray)
+ if (e1.op == EXP.index && (cast(IndexExp)e1).e1.type.toBasetype().ty == Taarray)
{
// ---------------------------------------
// Deal with AA index assignment
@@ -3356,7 +3365,7 @@ public:
*/
IndexExp ie = cast(IndexExp)e1;
int depth = 0; // how many nested AA indices are there?
- while (ie.e1.op == TOK.index && (cast(IndexExp)ie.e1).e1.type.toBasetype().ty == Taarray)
+ while (ie.e1.op == EXP.index && (cast(IndexExp)ie.e1).e1.type.toBasetype().ty == Taarray)
{
assert(ie.modifiable);
ie = cast(IndexExp)ie.e1;
@@ -3430,7 +3439,7 @@ public:
oldval = copyLiteral(e.e1.type.defaultInitLiteral(e.loc)).copy();
Expression newaae = oldval;
- while (e1.op == TOK.index && (cast(IndexExp)e1).e1.type.toBasetype().ty == Taarray)
+ while (e1.op == EXP.index && (cast(IndexExp)e1).e1.type.toBasetype().ty == Taarray)
{
Expression ekey = interpretRegion((cast(IndexExp)e1).e2, istate);
if (exceptionOrCant(ekey))
@@ -3465,13 +3474,13 @@ public:
assert(existingAA && lastIndex);
e1 = null; // stomp
}
- else if (e1.op == TOK.arrayLength)
+ else if (e1.op == EXP.arrayLength)
{
oldval = interpretRegion(e1, istate);
if (exceptionOrCant(oldval))
return;
}
- else if (e.op == TOK.construct || e.op == TOK.blit)
+ else if (e.op == EXP.construct || e.op == EXP.blit)
{
// Unless we have a simple var assignment, we're
// only modifying part of the variable. So we need to make sure
@@ -3501,10 +3510,10 @@ public:
if (exceptionOrCant(e1))
return;
- if (e1.op == TOK.index && (cast(IndexExp)e1).e1.type.toBasetype().ty == Taarray)
+ if (e1.op == EXP.index && (cast(IndexExp)e1).e1.type.toBasetype().ty == Taarray)
{
IndexExp ie = cast(IndexExp)e1;
- assert(ie.e1.op == TOK.assocArrayLiteral);
+ assert(ie.e1.op == EXP.assocArrayLiteral);
existingAA = cast(AssocArrayLiteralExp)ie.e1;
lastIndex = ie.e2;
}
@@ -3516,7 +3525,7 @@ public:
Expression newval = interpretRegion(e.e2, istate);
if (exceptionOrCant(newval))
return;
- if (e.op == TOK.blit && newval.op == TOK.int64)
+ if (e.op == EXP.blit && newval.op == EXP.int64)
{
Type tbn = e.type.baseElemOf();
if (tbn.ty == Tstruct)
@@ -3524,7 +3533,7 @@ public:
/* Look for special case of struct being initialized with 0.
*/
newval = e.type.defaultInitLiteral(e.loc);
- if (newval.op == TOK.error)
+ if (newval.op == EXP.error)
{
result = CTFEExp.cantexp;
return;
@@ -3554,7 +3563,7 @@ public:
if (e.e1.type.ty != Tpointer)
{
// ~= can create new values (see bug 6052)
- if (e.op == TOK.concatenateAssign || e.op == TOK.concatenateElemAssign || e.op == TOK.concatenateDcharAssign)
+ if (e.op == EXP.concatenateAssign || e.op == EXP.concatenateElemAssign || e.op == EXP.concatenateDcharAssign)
{
// We need to dup it and repaint the type. For a dynamic array
// we can skip duplication, because it gets copied later anyway.
@@ -3574,10 +3583,10 @@ public:
newval = (*fp)(e.loc, e.type, oldval, newval).copy();
}
else if (e.e2.type.isintegral() &&
- (e.op == TOK.addAssign ||
- e.op == TOK.minAssign ||
- e.op == TOK.plusPlus ||
- e.op == TOK.minusMinus))
+ (e.op == EXP.addAssign ||
+ e.op == EXP.minAssign ||
+ e.op == EXP.plusPlus ||
+ e.op == EXP.minusMinus))
{
newval = pointerArithmetic(e.loc, e.op, e.type, oldval, newval).copy();
}
@@ -3612,7 +3621,7 @@ public:
result = ctfeCast(pue, e.loc, e.type, e.type, fp && post ? oldval : newval);
return;
}
- if (e1.op == TOK.arrayLength)
+ if (e1.op == EXP.arrayLength)
{
/* Change the assignment from:
* arr.length = n;
@@ -3692,11 +3701,11 @@ public:
/* Block assignment or element-wise assignment.
*/
- if (e1.op == TOK.slice ||
- e1.op == TOK.vector ||
- e1.op == TOK.arrayLiteral ||
- e1.op == TOK.string_ ||
- e1.op == TOK.null_ && e1.type.toBasetype().ty == Tarray)
+ if (e1.op == EXP.slice ||
+ e1.op == EXP.vector ||
+ e1.op == EXP.arrayLiteral ||
+ e1.op == EXP.string_ ||
+ e1.op == EXP.null_ && e1.type.toBasetype().ty == Tarray)
{
// Note that slice assignments don't support things like ++, so
// we don't need to remember 'returnValue'.
@@ -3709,8 +3718,8 @@ public:
if (auto dve = e1x.isDotVarExp())
{
auto ex = dve.e1;
- auto sle = ex.op == TOK.structLiteral ? (cast(StructLiteralExp)ex)
- : ex.op == TOK.classReference ? (cast(ClassReferenceExp)ex).value
+ auto sle = ex.op == EXP.structLiteral ? (cast(StructLiteralExp)ex)
+ : ex.op == EXP.classReference ? (cast(ClassReferenceExp)ex).value
: null;
auto v = dve.var.isVarDeclaration();
if (!sle || !v)
@@ -3745,7 +3754,7 @@ public:
if (v is v2 || !v.isOverlappedWith(v2))
continue;
auto e = (*sle.elements)[i];
- if (e.op != TOK.void_)
+ if (e.op != EXP.void_)
(*sle.elements)[i] = voidInitLiteral(e.type, v).copy();
}
}
@@ -3768,8 +3777,8 @@ public:
* e.v = newval
*/
auto ex = dve.e1;
- auto sle = ex.op == TOK.structLiteral ? (cast(StructLiteralExp)ex)
- : ex.op == TOK.classReference ? (cast(ClassReferenceExp)ex).value
+ auto sle = ex.op == EXP.structLiteral ? (cast(StructLiteralExp)ex)
+ : ex.op == EXP.classReference ? (cast(ClassReferenceExp)ex).value
: null;
auto v = (cast(DotVarExp)e1).var.isVarDeclaration();
if (!sle || !v)
@@ -3783,7 +3792,7 @@ public:
return CTFEExp.cantexp;
}
- int fieldi = ex.op == TOK.structLiteral ? findFieldIndexByName(sle.sd, v)
+ int fieldi = ex.op == EXP.structLiteral ? findFieldIndexByName(sle.sd, v)
: (cast(ClassReferenceExp)ex).findFieldIndexByName(v);
if (fieldi == -1)
{
@@ -3820,7 +3829,7 @@ public:
existingSE.setCodeUnit(index, cast(dchar)newval.toInteger());
return null;
}
- if (aggregate.op != TOK.arrayLiteral)
+ if (aggregate.op != EXP.arrayLiteral)
{
e.error("index assignment `%s` is not yet supported in CTFE ", e.toChars());
return CTFEExp.cantexp;
@@ -3848,7 +3857,7 @@ public:
if (auto ve = newval.isVectorExp())
{
// Ensure ve is an array literal, and not a broadcast
- if (ve.e1.op == TOK.int64 || ve.e1.op == TOK.float64) // if broadcast
+ if (ve.e1.op == EXP.int64 || ve.e1.op == EXP.float64) // if broadcast
{
UnionExp ue = void;
Expression ex = interpretVectorToArray(&ue, ve);
@@ -3856,13 +3865,13 @@ public:
}
}
- if (newval.op == TOK.structLiteral && oldval)
+ if (newval.op == EXP.structLiteral && oldval)
{
- assert(oldval.op == TOK.structLiteral || oldval.op == TOK.arrayLiteral || oldval.op == TOK.string_);
+ assert(oldval.op == EXP.structLiteral || oldval.op == EXP.arrayLiteral || oldval.op == EXP.string_);
newval = copyLiteral(newval).copy();
assignInPlace(oldval, newval);
}
- else if (wantCopy && e.op == TOK.assign)
+ else if (wantCopy && e.op == EXP.assign)
{
// Currently postblit/destructor calls on static array are done
// in the druntime internal functions so they don't appear in AST.
@@ -3878,8 +3887,8 @@ public:
return CTFEExp.cantexp;
}
}
- assert(oldval.op == TOK.arrayLiteral);
- assert(newval.op == TOK.arrayLiteral);
+ assert(oldval.op == EXP.arrayLiteral);
+ assert(newval.op == EXP.arrayLiteral);
Expressions* oldelems = (cast(ArrayLiteralExp)oldval).elements;
Expressions* newelems = (cast(ArrayLiteralExp)newval).elements;
@@ -3907,7 +3916,7 @@ public:
if (wantCopy)
newval = copyLiteral(newval).copy();
- if (t1b.ty == Tsarray && e.op == TOK.construct && e.e2.isLvalue())
+ if (t1b.ty == Tsarray && e.op == EXP.construct && e.e2.isLvalue())
{
// https://issues.dlang.org/show_bug.cgi?id=9245
if (Expression ex = evaluatePostblit(istate, newval))
@@ -3923,7 +3932,7 @@ public:
*payload = oldval;
// Blit assignment should return the newly created value.
- if (e.op == TOK.blit)
+ if (e.op == EXP.blit)
return oldval;
return null;
@@ -3938,7 +3947,7 @@ public:
* This could be a slice assignment or a block assignment, and
* dest could be either an array literal, or a string.
*
- * Returns TOK.cantExpression on failure. If there are no errors,
+ * Returns EXP.cantExpression on failure. If there are no errors,
* it returns aggregate[low..upp], except that as an optimisation,
* if goal == CTFEGoal.Nothing, it will return NULL
*/
@@ -4024,7 +4033,7 @@ public:
lowerbound = 0;
upperbound = se.len;
}
- else if (e1.op == TOK.null_)
+ else if (e1.op == EXP.null_)
{
lowerbound = 0;
upperbound = 0;
@@ -4088,7 +4097,7 @@ public:
return CTFEExp.cantexp;
}
}
- assert(newval.op != TOK.slice);
+ assert(newval.op != EXP.slice);
}
if (auto se = newval.isStringExp())
{
@@ -4126,7 +4135,7 @@ public:
return CTFEExp.cantexp;
}
- if (newval.op == TOK.slice && !isBlockAssignment)
+ if (newval.op == EXP.slice && !isBlockAssignment)
{
auto se = cast(SliceExp)newval;
auto aggr2 = se.e1;
@@ -4142,7 +4151,7 @@ public:
// Currently overlapping for struct array is allowed.
// The order of elements processing depends on the overlapping.
// https://issues.dlang.org/show_bug.cgi?id=14024
- assert(aggr2.op == TOK.arrayLiteral);
+ assert(aggr2.op == EXP.arrayLiteral);
Expressions* oldelems = existingAE.elements;
Expressions* newelems = (cast(ArrayLiteralExp)aggr2).elements;
@@ -4210,9 +4219,9 @@ public:
}
// no overlapping
//length?
- assert(newval.op != TOK.slice);
+ assert(newval.op != EXP.slice);
}
- if (newval.op == TOK.string_ && !isBlockAssignment)
+ if (newval.op == EXP.string_ && !isBlockAssignment)
{
/* Mixed slice: it was initialized as an array literal of chars/integers.
* Now a slice of it is being set with a string.
@@ -4220,12 +4229,12 @@ public:
sliceAssignArrayLiteralFromString(existingAE, cast(StringExp)newval, cast(size_t)firstIndex);
return newval;
}
- if (newval.op == TOK.arrayLiteral && !isBlockAssignment)
+ if (newval.op == EXP.arrayLiteral && !isBlockAssignment)
{
Expressions* oldelems = existingAE.elements;
Expressions* newelems = (cast(ArrayLiteralExp)newval).elements;
Type elemtype = existingAE.type.nextOf();
- bool needsPostblit = e.op != TOK.blit && e.e2.isLvalue();
+ bool needsPostblit = e.op != EXP.blit && e.e2.isLvalue();
foreach (j, newelem; *newelems)
{
newelem = paintTypeOntoLiteral(elemtype, newelem);
@@ -4265,7 +4274,7 @@ public:
bool directblk = (cast(TypeArray)ae.type).next.equivalent(newval.type);
for (size_t k = lwr; k < upr; k++)
{
- if (!directblk && (*w)[k].op == TOK.arrayLiteral)
+ if (!directblk && (*w)[k].op == EXP.arrayLiteral)
{
// Multidimensional array block assign
if (Expression ex = assignTo(cast(ArrayLiteralExp)(*w)[k]))
@@ -4303,7 +4312,7 @@ public:
Type tn = newval.type.toBasetype();
bool wantRef = (tn.ty == Tarray || isAssocArray(tn) || tn.ty == Tclass);
- bool cow = newval.op != TOK.structLiteral && newval.op != TOK.arrayLiteral && newval.op != TOK.string_;
+ bool cow = newval.op != EXP.structLiteral && newval.op != EXP.arrayLiteral && newval.op != EXP.string_;
Type tb = tn.baseElemOf();
StructDeclaration sd = (tb.ty == Tstruct ? (cast(TypeStruct)tb).sym : null);
@@ -4311,8 +4320,8 @@ public:
rb.istate = istate;
rb.newval = newval;
rb.refCopy = wantRef || cow;
- rb.needsPostblit = sd && sd.postblit && e.op != TOK.blit && e.e2.isLvalue();
- rb.needsDtor = sd && sd.dtor && e.op == TOK.assign;
+ rb.needsPostblit = sd && sd.postblit && e.op != EXP.blit && e.e2.isLvalue();
+ rb.needsDtor = sd && sd.dtor && e.op == EXP.assign;
if (Expression ex = rb.assignTo(existingAE, cast(size_t)lowerbound, cast(size_t)upperbound))
return ex;
@@ -4338,57 +4347,57 @@ public:
{
switch (e.op)
{
- case TOK.addAssign:
+ case EXP.addAssign:
interpretAssignCommon(e, &Add);
return;
- case TOK.minAssign:
+ case EXP.minAssign:
interpretAssignCommon(e, &Min);
return;
- case TOK.concatenateAssign:
- case TOK.concatenateElemAssign:
- case TOK.concatenateDcharAssign:
+ case EXP.concatenateAssign:
+ case EXP.concatenateElemAssign:
+ case EXP.concatenateDcharAssign:
interpretAssignCommon(e, &ctfeCat);
return;
- case TOK.mulAssign:
+ case EXP.mulAssign:
interpretAssignCommon(e, &Mul);
return;
- case TOK.divAssign:
+ case EXP.divAssign:
interpretAssignCommon(e, &Div);
return;
- case TOK.modAssign:
+ case EXP.modAssign:
interpretAssignCommon(e, &Mod);
return;
- case TOK.leftShiftAssign:
+ case EXP.leftShiftAssign:
interpretAssignCommon(e, &Shl);
return;
- case TOK.rightShiftAssign:
+ case EXP.rightShiftAssign:
interpretAssignCommon(e, &Shr);
return;
- case TOK.unsignedRightShiftAssign:
+ case EXP.unsignedRightShiftAssign:
interpretAssignCommon(e, &Ushr);
return;
- case TOK.andAssign:
+ case EXP.andAssign:
interpretAssignCommon(e, &And);
return;
- case TOK.orAssign:
+ case EXP.orAssign:
interpretAssignCommon(e, &Or);
return;
- case TOK.xorAssign:
+ case EXP.xorAssign:
interpretAssignCommon(e, &Xor);
return;
- case TOK.powAssign:
+ case EXP.powAssign:
interpretAssignCommon(e, &Pow);
return;
@@ -4403,7 +4412,7 @@ public:
{
printf("%s PostExp::interpret() %s\n", e.loc.toChars(), e.toChars());
}
- if (e.op == TOK.plusPlus)
+ if (e.op == EXP.plusPlus)
interpretAssignCommon(e, &Add, 1);
else
interpretAssignCommon(e, &Min, 1);
@@ -4421,19 +4430,19 @@ public:
static int isPointerCmpExp(Expression e, Expression* p1, Expression* p2)
{
int ret = 1;
- while (e.op == TOK.not)
+ while (e.op == EXP.not)
{
ret *= -1;
e = (cast(NotExp)e).e1;
}
switch (e.op)
{
- case TOK.lessThan:
- case TOK.lessOrEqual:
+ case EXP.lessThan:
+ case EXP.lessOrEqual:
ret *= -1;
goto case; /+ fall through +/
- case TOK.greaterThan:
- case TOK.greaterOrEqual:
+ case EXP.greaterThan:
+ case EXP.greaterOrEqual:
*p1 = (cast(BinExp)e).e1;
*p2 = (cast(BinExp)e).e2;
if (!(isPointer((*p1).type) && isPointer((*p2).type)))
@@ -4465,7 +4474,7 @@ public:
*/
private void interpretFourPointerRelation(UnionExp* pue, BinExp e)
{
- assert(e.op == TOK.andAnd || e.op == TOK.orOr);
+ assert(e.op == EXP.andAnd || e.op == EXP.orOr);
/* It can only be an isInside expression, if both e1 and e2 are
* directional pointer comparisons.
@@ -4506,7 +4515,7 @@ public:
Expression agg1 = getAggregateFromPointer(p1, &ofs1);
Expression agg2 = getAggregateFromPointer(p2, &ofs2);
- if (!pointToSameMemoryBlock(agg1, agg2) && agg1.op != TOK.null_ && agg2.op != TOK.null_)
+ if (!pointToSameMemoryBlock(agg1, agg2) && agg1.op != EXP.null_ && agg2.op != EXP.null_)
{
// Here it is either CANT_INTERPRET,
// or an IsInside comparison returning false.
@@ -4545,7 +4554,7 @@ public:
(dir1 != dir2 && pointToSameMemoryBlock(agg1, agg3) && pointToSameMemoryBlock(agg2, agg4)))
{
// it's a legal two-sided comparison
- emplaceExp!(IntegerExp)(pue, e.loc, (e.op == TOK.andAnd) ? 0 : 1, e.type);
+ emplaceExp!(IntegerExp)(pue, e.loc, (e.op == EXP.andAnd) ? 0 : 1, e.type);
result = pue.exp();
return;
}
@@ -4582,29 +4591,29 @@ public:
* Returns:
* negate operator
*/
- static TOK negateRelation(TOK op) pure
+ static EXP negateRelation(EXP op) pure
{
switch (op)
{
- case TOK.greaterOrEqual: op = TOK.lessThan; break;
- case TOK.greaterThan: op = TOK.lessOrEqual; break;
- case TOK.lessOrEqual: op = TOK.greaterThan; break;
- case TOK.lessThan: op = TOK.greaterOrEqual; break;
+ case EXP.greaterOrEqual: op = EXP.lessThan; break;
+ case EXP.greaterThan: op = EXP.lessOrEqual; break;
+ case EXP.lessOrEqual: op = EXP.greaterThan; break;
+ case EXP.lessThan: op = EXP.greaterOrEqual; break;
default: assert(0);
}
return op;
}
- const TOK cmpop = nott ? negateRelation(ex.op) : ex.op;
+ const EXP cmpop = nott ? negateRelation(ex.op) : ex.op;
const cmp = comparePointers(cmpop, agg1, ofs1, agg2, ofs2);
// We already know this is a valid comparison.
assert(cmp >= 0);
- if (e.op == TOK.andAnd && cmp == 1 || e.op == TOK.orOr && cmp == 0)
+ if (e.op == EXP.andAnd && cmp == 1 || e.op == EXP.orOr && cmp == 0)
{
result = interpret(pue, e.e2, istate);
return;
}
- emplaceExp!(IntegerExp)(pue, e.loc, (e.op == TOK.andAnd) ? 0 : 1, e.type);
+ emplaceExp!(IntegerExp)(pue, e.loc, (e.op == EXP.andAnd) ? 0 : 1, e.type);
result = pue.exp();
}
@@ -4625,22 +4634,22 @@ public:
return;
bool res;
- const andand = e.op == TOK.andAnd;
- if (andand ? result.isBool(false) : isTrueBool(result))
+ const andand = e.op == EXP.andAnd;
+ if (andand ? result.toBool().hasValue(false) : isTrueBool(result))
res = !andand;
- else if (andand ? isTrueBool(result) : result.isBool(false))
+ else if (andand ? isTrueBool(result) : result.toBool().hasValue(false))
{
UnionExp ue2 = void;
result = interpret(&ue2, e.e2, istate);
if (exceptionOrCant(result))
return;
- if (result.op == TOK.voidExpression)
+ if (result.op == EXP.voidExpression)
{
assert(e.type.ty == Tvoid);
result = null;
return;
}
- if (result.isBool(false))
+ if (result.toBool().hasValue(false))
res = false;
else if (isTrueBool(result))
res = true;
@@ -4762,8 +4771,8 @@ public:
if (auto ce = ea.isCastExp())
ea = ce.e1;
- // printf("2 ea = %s, %s %s\n", ea.type.toChars(), Token.toChars(ea.op), ea.toChars());
- if (ea.op == TOK.variable || ea.op == TOK.symbolOffset)
+ // printf("2 ea = %s, %s %s\n", ea.type.toChars(), EXPtoString(ea.op).ptr, ea.toChars());
+ if (ea.op == EXP.variable || ea.op == EXP.symbolOffset)
result = getVarExp(e.loc, istate, (cast(SymbolExp)ea).var, CTFEGoal.RValue);
else if (auto ae = ea.isAddrExp())
result = interpretRegion(ae.e1, istate);
@@ -4805,6 +4814,29 @@ public:
result = interpretRegion(ae, istate);
return;
}
+ else if (fd.ident == Id._d_arrayctor || fd.ident == Id._d_arraysetctor)
+ {
+ // In expressionsem.d `T[x] ea = eb;` was lowered to `_d_array{,set}ctor(ea[], eb[]);`.
+ // The following code will rewrite it back to `ea = eb` and then interpret that expression.
+ if (fd.ident == Id._d_arraysetctor)
+ assert(e.arguments.dim == 2);
+ else
+ assert(e.arguments.dim == 3);
+
+ Expression ea = (*e.arguments)[0];
+ if (ea.isCastExp)
+ ea = ea.isCastExp.e1;
+
+ Expression eb = (*e.arguments)[1];
+ if (eb.isCastExp && fd.ident == Id._d_arrayctor)
+ eb = eb.isCastExp.e1;
+
+ ConstructExp ce = new ConstructExp(e.loc, ea, eb);
+ ce.type = ea.type;
+
+ result = interpret(ce, istate);
+ return;
+ }
}
else if (auto soe = ecall.isSymOffExp())
{
@@ -4848,7 +4880,7 @@ public:
// Currently this is satisfied because closure is not yet supported.
assert(!fd.isNested() || fd.needThis());
- if (pthis.op == TOK.typeid_)
+ if (pthis.op == EXP.typeid_)
{
pthis.error("static variable `%s` cannot be read at compile time", pthis.toChars());
result = CTFEExp.cantexp;
@@ -4856,7 +4888,7 @@ public:
}
assert(pthis);
- if (pthis.op == TOK.null_)
+ if (pthis.op == EXP.null_)
{
assert(pthis.type.toBasetype().ty == Tclass);
e.error("function call through null class reference `%s`", pthis.toChars());
@@ -4864,7 +4896,7 @@ public:
return;
}
- assert(pthis.op == TOK.structLiteral || pthis.op == TOK.classReference || pthis.op == TOK.type);
+ assert(pthis.op == EXP.structLiteral || pthis.op == EXP.classReference || pthis.op == EXP.type);
if (fd.isVirtual() && !e.directcall)
{
@@ -4899,7 +4931,7 @@ public:
}
result = interpretFunction(pue, fd, istate, e.arguments, pthis);
- if (result.op == TOK.voidExpression)
+ if (result.op == EXP.voidExpression)
return;
if (!exceptionOrCantInterpret(result))
{
@@ -4929,7 +4961,7 @@ public:
// If it creates a variable, and there's no context for
// the variable to be created in, we need to create one now.
InterState istateComma;
- if (!istate && firstComma(e.e1).op == TOK.declaration)
+ if (!istate && firstComma(e.e1).op == EXP.declaration)
{
ctfeGlobals.stack.startFrame(null);
istate = &istateComma;
@@ -4946,8 +4978,8 @@ public:
// If the comma returns a temporary variable, it needs to be an lvalue
// (this is particularly important for struct constructors)
- if (e.e1.op == TOK.declaration &&
- e.e2.op == TOK.variable &&
+ if (e.e1.op == EXP.declaration &&
+ e.e2.op == EXP.variable &&
e.e1.isDeclarationExp().declaration == e.e2.isVarExp().var &&
e.e2.isVarExp().var.storage_class & STC.ctfe)
{
@@ -4967,7 +4999,7 @@ public:
newval = interpretRegion(newval, istate);
if (exceptionOrCant(newval))
return endTempStackFrame();
- if (newval.op != TOK.voidExpression)
+ if (newval.op != EXP.voidExpression)
{
// v isn't necessarily null.
setValueWithoutChecking(v, copyLiteral(newval).copy());
@@ -4999,7 +5031,7 @@ public:
if (isPointer(e.econd.type))
{
- if (econd.op != TOK.null_)
+ if (econd.op != EXP.null_)
{
econd = IntegerExp.createBool(true);
}
@@ -5010,7 +5042,7 @@ public:
result = interpret(pue, e.e1, istate, goal);
incUsageCtfe(istate, e.e1.loc);
}
- else if (econd.isBool(false))
+ else if (econd.toBool().hasValue(false))
{
result = interpret(pue, e.e2, istate, goal);
incUsageCtfe(istate, e.e2.loc);
@@ -5033,7 +5065,7 @@ public:
assert(e1);
if (exceptionOrCant(e1))
return;
- if (e1.op != TOK.string_ && e1.op != TOK.arrayLiteral && e1.op != TOK.slice && e1.op != TOK.null_)
+ if (e1.op != EXP.string_ && e1.op != EXP.arrayLiteral && e1.op != EXP.slice && e1.op != EXP.null_)
{
e.error("`%s` cannot be evaluated at compile time", e.toChars());
result = CTFEExp.cantexp;
@@ -5055,7 +5087,7 @@ public:
{
if (auto ale = e.e1.isArrayLiteralExp())
return ale; // it's already an array literal
- if (e.e1.op == TOK.int64 || e.e1.op == TOK.float64)
+ if (e.e1.op == EXP.int64 || e.e1.op == EXP.float64)
{
// Convert literal __vector(int) -> __vector([array])
auto elements = new Expressions(e.dim);
@@ -5086,7 +5118,7 @@ public:
assert(e1);
if (exceptionOrCant(e1))
return;
- if (e1.op != TOK.arrayLiteral && e1.op != TOK.int64 && e1.op != TOK.float64)
+ if (e1.op != EXP.arrayLiteral && e1.op != EXP.int64 && e1.op != EXP.float64)
{
e.error("`%s` cannot be evaluated at compile time", e.toChars());
result = CTFEExp.cantexp;
@@ -5115,7 +5147,7 @@ public:
if (auto ve = e1.isVectorExp())
{
result = interpretVectorToArray(pue, ve);
- if (result.op != TOK.vector)
+ if (result.op != EXP.vector)
return;
}
e.error("`%s` cannot be evaluated at compile time", e.toChars());
@@ -5169,24 +5201,24 @@ public:
dinteger_t ofs;
Expression agg = getAggregateFromPointer(e1, &ofs);
- if (agg.op == TOK.null_)
+ if (agg.op == EXP.null_)
{
e.error("cannot index through null pointer `%s`", e.e1.toChars());
return false;
}
- if (agg.op == TOK.int64)
+ if (agg.op == EXP.int64)
{
e.error("cannot index through invalid pointer `%s` of value `%s`", e.e1.toChars(), e1.toChars());
return false;
}
// Pointer to a non-array variable
- if (agg.op == TOK.symbolOffset)
+ if (agg.op == EXP.symbolOffset)
{
e.error("mutable variable `%s` cannot be %s at compile time, even through a pointer", cast(char*)(modify ? "modified" : "read"), (cast(SymOffExp)agg).var.toChars());
return false;
}
- if (agg.op == TOK.arrayLiteral || agg.op == TOK.string_)
+ if (agg.op == EXP.arrayLiteral || agg.op == EXP.string_)
{
dinteger_t len = resolveArrayLength(agg);
if (ofs + indx >= len)
@@ -5211,7 +5243,7 @@ public:
Expression e1 = interpretRegion(e.e1, istate);
if (exceptionOrCantInterpret(e1))
return false;
- if (e1.op == TOK.null_)
+ if (e1.op == EXP.null_)
{
e.error("cannot index null array `%s`", e.e1.toChars());
return false;
@@ -5225,11 +5257,11 @@ public:
// Set the $ variable, and find the array literal to modify
dinteger_t len;
- if (e1.op == TOK.variable && e1.type.toBasetype().ty == Tsarray)
+ if (e1.op == EXP.variable && e1.type.toBasetype().ty == Tsarray)
len = e1.type.toBasetype().isTypeSArray().dim.toInteger();
else
{
- if (e1.op != TOK.arrayLiteral && e1.op != TOK.string_ && e1.op != TOK.slice && e1.op != TOK.vector)
+ if (e1.op != EXP.arrayLiteral && e1.op != EXP.string_ && e1.op != EXP.slice && e1.op != EXP.vector)
{
e.error("cannot determine length of `%s` at compile time", e.e1.toChars());
return false;
@@ -5248,7 +5280,7 @@ public:
ctfeGlobals.stack.pop(e.lengthVar); // $ is defined only inside []
if (exceptionOrCantInterpret(e2))
return false;
- if (e2.op != TOK.int64)
+ if (e2.op != EXP.int64)
{
e.error("CTFE internal error: non-integral index `[%s]`", e.e2.toChars());
return false;
@@ -5297,7 +5329,7 @@ public:
result = CTFEExp.cantexp;
return;
}
- if (agg.op == TOK.arrayLiteral || agg.op == TOK.string_)
+ if (agg.op == EXP.arrayLiteral || agg.op == EXP.string_)
{
if (goal == CTFEGoal.LValue)
{
@@ -5327,7 +5359,7 @@ public:
Expression e1 = interpretRegion(e.e1, istate);
if (exceptionOrCant(e1))
return;
- if (e1.op == TOK.null_)
+ if (e1.op == EXP.null_)
{
if (goal == CTFEGoal.LValue && e1.type.ty == Taarray && e.modifiable)
{
@@ -5355,7 +5387,7 @@ public:
return;
}
- assert(e1.op == TOK.assocArrayLiteral);
+ assert(e1.op == EXP.assocArrayLiteral);
UnionExp e2tmp = void;
e2 = resolveSlice(e2, &e2tmp);
result = findKeyInAA(e.loc, cast(AssocArrayLiteralExp)e1, e2);
@@ -5387,7 +5419,7 @@ public:
result = ctfeIndex(pue, e.loc, e.type, agg, indexToAccess);
if (exceptionOrCant(result))
return;
- if (result.op == TOK.void_)
+ if (result.op == EXP.void_)
{
e.error("`%s` is used before initialized", e.toChars());
errorSupplemental(result.loc, "originally uninitialized here");
@@ -5410,7 +5442,7 @@ public:
Expression e1 = interpretRegion(e.e1, istate);
if (exceptionOrCant(e1))
return;
- if (e1.op == TOK.int64)
+ if (e1.op == EXP.int64)
{
e.error("cannot slice invalid pointer `%s` of value `%s`", e.e1.toChars(), e1.toChars());
result = CTFEExp.cantexp;
@@ -5432,7 +5464,7 @@ public:
Expression agg = getAggregateFromPointer(e1, &ofs);
ilwr += ofs;
iupr += ofs;
- if (agg.op == TOK.null_)
+ if (agg.op == EXP.null_)
{
if (iupr == ilwr)
{
@@ -5444,19 +5476,19 @@ public:
result = CTFEExp.cantexp;
return;
}
- if (agg.op == TOK.symbolOffset)
+ if (agg.op == EXP.symbolOffset)
{
e.error("slicing pointers to static variables is not supported in CTFE");
result = CTFEExp.cantexp;
return;
}
- if (agg.op != TOK.arrayLiteral && agg.op != TOK.string_)
+ if (agg.op != EXP.arrayLiteral && agg.op != EXP.string_)
{
e.error("pointer `%s` cannot be sliced at compile time (it does not point to an array)", e.e1.toChars());
result = CTFEExp.cantexp;
return;
}
- assert(agg.op == TOK.arrayLiteral || agg.op == TOK.string_);
+ assert(agg.op == EXP.arrayLiteral || agg.op == EXP.string_);
dinteger_t len = ArrayLength(Type.tsize_t, agg).exp().toInteger();
//Type *pointee = ((TypePointer *)agg.type)->next;
if (iupr > (len + 1) || iupr < ilwr)
@@ -5503,11 +5535,11 @@ public:
/* Set dollar to the length of the array
*/
uinteger_t dollar;
- if ((e1.op == TOK.variable || e1.op == TOK.dotVariable) && e1.type.toBasetype().ty == Tsarray)
+ if ((e1.op == EXP.variable || e1.op == EXP.dotVariable) && e1.type.toBasetype().ty == Tsarray)
dollar = e1.type.toBasetype().isTypeSArray().dim.toInteger();
else
{
- if (e1.op != TOK.arrayLiteral && e1.op != TOK.string_ && e1.op != TOK.null_ && e1.op != TOK.slice && e1.op != TOK.vector)
+ if (e1.op != EXP.arrayLiteral && e1.op != EXP.string_ && e1.op != EXP.null_ && e1.op != EXP.slice && e1.op != EXP.vector)
{
e.error("cannot determine length of `%s` at compile time", e1.toChars());
result = CTFEExp.cantexp;
@@ -5546,7 +5578,7 @@ public:
uinteger_t ilwr = lwr.toInteger();
uinteger_t iupr = upr.toInteger();
- if (e1.op == TOK.null_)
+ if (e1.op == EXP.null_)
{
if (ilwr == 0 && iupr == 0)
{
@@ -5578,7 +5610,7 @@ public:
result.type = e.type;
return;
}
- if (e1.op == TOK.arrayLiteral || e1.op == TOK.string_)
+ if (e1.op == EXP.arrayLiteral || e1.op == EXP.string_)
{
if (iupr < ilwr || dollar < iupr)
{
@@ -5604,13 +5636,13 @@ public:
Expression e2 = interpretRegion(e.e2, istate);
if (exceptionOrCant(e2))
return;
- if (e2.op == TOK.null_)
+ if (e2.op == EXP.null_)
{
emplaceExp!(NullExp)(pue, e.loc, e.type);
result = pue.exp();
return;
}
- if (e2.op != TOK.assocArrayLiteral)
+ if (e2.op != EXP.assocArrayLiteral)
{
e.error("`%s` cannot be interpreted at compile time", e.toChars());
result = CTFEExp.cantexp;
@@ -5663,7 +5695,7 @@ public:
* result in [x,y] and then x or y is on the stack.
* But if they are both strings, we can, because it isn't the x~[y] case.
*/
- if (!(e1.op == TOK.string_ && e2.op == TOK.string_))
+ if (!(e1.op == EXP.string_ && e2.op == EXP.string_))
{
if (e1 == ue1.exp())
e1 = ue1.copy();
@@ -5706,7 +5738,7 @@ public:
if (exceptionOrCant(result))
return;
- if (result.op == TOK.null_)
+ if (result.op == EXP.null_)
{
result = CTFEExp.voidexp;
return;
@@ -5716,7 +5748,7 @@ public:
switch (tb.ty)
{
case Tclass:
- if (result.op != TOK.classReference)
+ if (result.op != EXP.classReference)
{
e.error("`delete` on invalid class reference `%s`", result.toChars());
result = CTFEExp.cantexp;
@@ -5752,8 +5784,8 @@ public:
tb = (cast(TypePointer)tb).next.toBasetype();
if (tb.ty == Tstruct)
{
- if (result.op != TOK.address ||
- (cast(AddrExp)result).e1.op != TOK.structLiteral)
+ 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;
@@ -5776,7 +5808,7 @@ public:
auto tv = tb.nextOf().baseElemOf();
if (tv.ty == Tstruct)
{
- if (result.op != TOK.arrayLiteral)
+ if (result.op != EXP.arrayLiteral)
{
e.error("`delete` on invalid struct array `%s`", result.toChars());
result = CTFEExp.cantexp;
@@ -5819,11 +5851,11 @@ public:
result = CTFEExp.voidexp;
return;
}
- if (e.to.ty == Tpointer && e1.op != TOK.null_)
+ if (e.to.ty == Tpointer && e1.op != EXP.null_)
{
Type pointee = (cast(TypePointer)e.type).next;
// Implement special cases of normally-unsafe casts
- if (e1.op == TOK.int64)
+ if (e1.op == EXP.int64)
{
// Happens with Windows HANDLEs, for example.
result = paintTypeOntoLiteral(pue, e.to, e1);
@@ -5869,7 +5901,7 @@ public:
if (auto se = e1.isSliceExp())
{
- if (se.e1.op == TOK.null_)
+ if (se.e1.op == EXP.null_)
{
result = paintTypeOntoLiteral(pue, e.type, se.e1);
return;
@@ -5881,7 +5913,7 @@ public:
result = pue.exp();
return;
}
- if (e1.op == TOK.arrayLiteral || e1.op == TOK.string_)
+ if (e1.op == EXP.arrayLiteral || e1.op == EXP.string_)
{
// Create a CTFE pointer &[1,2,3][0] or &"abc"[0]
auto ei = ctfeEmplaceExp!IndexExp(e.loc, e1, ctfeEmplaceExp!IntegerExp(e.loc, 0, Type.tsize_t));
@@ -5890,7 +5922,7 @@ public:
result = pue.exp();
return;
}
- if (e1.op == TOK.index && !(cast(IndexExp)e1).e1.type.equals(e1.type))
+ if (e1.op == EXP.index && !(cast(IndexExp)e1).e1.type.equals(e1.type))
{
// type painting operation
IndexExp ie = cast(IndexExp)e1;
@@ -5899,7 +5931,7 @@ public:
// get the original type. For strings, it's just the type...
Type origType = ie.e1.type.nextOf();
// ..but for arrays of type void*, it's the type of the element
- if (ie.e1.op == TOK.arrayLiteral && ie.e2.op == TOK.int64)
+ if (ie.e1.op == EXP.arrayLiteral && ie.e2.op == EXP.int64)
{
ArrayLiteralExp ale = cast(ArrayLiteralExp)ie.e1;
const indx = cast(size_t)ie.e2.toInteger();
@@ -5939,7 +5971,7 @@ public:
return;
}
- if (castToSarrayPointer && pointee.toBasetype().ty == Tsarray && ae.e1.op == TOK.index)
+ if (castToSarrayPointer && pointee.toBasetype().ty == Tsarray && ae.e1.op == EXP.index)
{
// &val[idx]
dinteger_t dim = (cast(TypeSArray)pointee.toBasetype()).dim.toInteger();
@@ -5956,7 +5988,7 @@ public:
}
}
- if (e1.op == TOK.variable || e1.op == TOK.symbolOffset)
+ if (e1.op == EXP.variable || e1.op == EXP.symbolOffset)
{
// type painting operation
Type origType = (cast(SymbolExp)e1).var.type;
@@ -5977,7 +6009,7 @@ public:
// Check if we have a null pointer (eg, inside a struct)
e1 = interpretRegion(e1, istate);
- if (e1.op != TOK.null_)
+ if (e1.op != EXP.null_)
{
e.error("pointer cast from `%s` to `%s` is not supported at compile time", e1.type.toChars(), e.to.toChars());
result = CTFEExp.cantexp;
@@ -5990,10 +6022,10 @@ public:
e1 = interpretRegion(e.e1, istate);
if (exceptionOrCant(e1))
return;
- assert(e1.op == TOK.vector);
+ assert(e1.op == EXP.vector);
e1 = interpretVectorToArray(pue, e1.isVectorExp());
}
- if (e.to.ty == Tarray && e1.op == TOK.slice)
+ if (e.to.ty == Tarray && e1.op == EXP.slice)
{
// Note that the slice may be void[], so when checking for dangerous
// casts, we need to use the original type, which is se.e1.
@@ -6023,11 +6055,11 @@ public:
auto tobt = e.to.toBasetype();
if (tobt.ty == Tbool && e1.type.ty == Tpointer)
{
- emplaceExp!(IntegerExp)(pue, e.loc, e1.op != TOK.null_, e.to);
+ emplaceExp!(IntegerExp)(pue, e.loc, e1.op != EXP.null_, e.to);
result = pue.exp();
return;
}
- else if (tobt.isTypeBasic() && e1.op == TOK.null_)
+ else if (tobt.isTypeBasic() && e1.op == EXP.null_)
{
if (tobt.isintegral())
emplaceExp!(IntegerExp)(pue, e.loc, 0, e.to);
@@ -6051,7 +6083,7 @@ public:
if (isTrueBool(e1))
{
}
- else if (e1.isBool(false))
+ else if (e1.toBool().hasValue(false))
{
if (e.msg)
{
@@ -6106,7 +6138,7 @@ public:
// Constant fold *(&structliteral + offset)
if (auto ae = e.e1.isAddExp())
{
- if (ae.e1.op == TOK.address && ae.e2.op == TOK.int64)
+ if (ae.e1.op == EXP.address && ae.e2.op == EXP.int64)
{
AddrExp ade = cast(AddrExp)ae.e1;
Expression ex = interpretRegion(ade.e1, istate);
@@ -6128,7 +6160,7 @@ public:
if (exceptionOrCant(result))
return;
- if (result.op == TOK.function_)
+ if (result.op == EXP.function_)
return;
if (auto soe = result.isSymOffExp())
{
@@ -6142,9 +6174,9 @@ public:
if (result.isStringExp())
return;
- if (result.op != TOK.address)
+ if (result.op != EXP.address)
{
- if (result.op == TOK.null_)
+ if (result.op == EXP.null_)
e.error("dereference of null pointer `%s`", e.e1.toChars());
else
e.error("dereference of invalid pointer `%s`", result.toChars());
@@ -6155,7 +6187,7 @@ public:
// *(&x) ==> x
result = (cast(AddrExp)result).e1;
- if (result.op == TOK.slice && e.type.toBasetype().ty == Tsarray)
+ if (result.op == EXP.slice && e.type.toBasetype().ty == Tsarray)
{
/* aggr[lwr..upr]
* upr may exceed the upper boundary of aggr, but the check is deferred
@@ -6212,7 +6244,7 @@ public:
return;
}
- if (ex.op == TOK.null_)
+ if (ex.op == EXP.null_)
{
if (ex.type.toBasetype().ty == Tclass)
e.error("class `%s` is `null` and cannot be dereferenced", e.e1.toChars());
@@ -6225,18 +6257,18 @@ public:
StructLiteralExp se;
int i;
- if (ex.op != TOK.structLiteral && ex.op != TOK.classReference && ex.op != TOK.typeid_)
+ if (ex.op != EXP.structLiteral && ex.op != EXP.classReference && ex.op != EXP.typeid_)
{
return notImplementedYet();
}
// We can't use getField, because it makes a copy
- if (ex.op == TOK.classReference)
+ if (ex.op == EXP.classReference)
{
se = (cast(ClassReferenceExp)ex).value;
i = (cast(ClassReferenceExp)ex).findFieldIndexByName(v);
}
- else if (ex.op == TOK.typeid_)
+ else if (ex.op == EXP.typeid_)
{
if (v.ident == Identifier.idPool("name"))
{
@@ -6336,7 +6368,7 @@ public:
Expression index = interpret(e.e2, istate);
if (exceptionOrCant(index))
return;
- if (agg.op == TOK.null_)
+ if (agg.op == EXP.null_)
{
result = CTFEExp.voidexp;
return;
@@ -6349,7 +6381,7 @@ public:
foreach (j, evalue; *valuesx)
{
Expression ekey = (*keysx)[j];
- int eq = ctfeEqual(e.loc, TOK.equal, ekey, index);
+ int eq = ctfeEqual(e.loc, EXP.equal, ekey, index);
if (eq)
++removed;
else if (removed != 0)
@@ -6435,11 +6467,11 @@ Expression interpretRegion(Expression e, InterState* istate, CTFEGoal goal = CTF
// mimicking UnionExp.copy, but with region allocation
switch (uexp.op)
{
- case TOK.cantExpression: return CTFEExp.cantexp;
- case TOK.voidExpression: return CTFEExp.voidexp;
- case TOK.break_: return CTFEExp.breakexp;
- case TOK.continue_: return CTFEExp.continueexp;
- case TOK.goto_: return CTFEExp.gotoexp;
+ case EXP.cantExpression: return CTFEExp.cantexp;
+ case EXP.voidExpression: return CTFEExp.voidexp;
+ case EXP.break_: return CTFEExp.breakexp;
+ case EXP.continue_: return CTFEExp.continueexp;
+ case EXP.goto_: return CTFEExp.gotoexp;
default: break;
}
auto p = ctfeGlobals.region.malloc(uexp.size);
@@ -6454,7 +6486,7 @@ Expression interpretRegion(Expression e, InterState* istate, CTFEGoal goal = CTF
* istate = context
* Returns:
* NULL continue to next statement
- * TOK.cantExpression cannot interpret statement at compile time
+ * EXP.cantExpression cannot interpret statement at compile time
* !NULL expression from return statement, or thrown exception
*/
Expression interpret(UnionExp* pue, Statement s, InterState* istate)
@@ -6490,7 +6522,7 @@ private Expression scrubReturnValue(const ref Loc loc, Expression e)
*/
static bool isVoid(const Expression e, bool checkArrayType = false) pure
{
- if (e.op == TOK.void_)
+ if (e.op == EXP.void_)
return true;
static bool isEntirelyVoid(const Expressions* elems)
@@ -6539,7 +6571,7 @@ private Expression scrubReturnValue(const ref Loc loc, Expression e)
else
{
e = scrubReturnValue(loc, e);
- if (CTFEExp.isCantExp(e) || e.op == TOK.error)
+ if (CTFEExp.isCantExp(e) || e.op == EXP.error)
return e;
}
}
@@ -6560,7 +6592,7 @@ private Expression scrubReturnValue(const ref Loc loc, Expression e)
return null;
}
- if (e.op == TOK.classReference)
+ if (e.op == EXP.classReference)
{
StructLiteralExp sle = (cast(ClassReferenceExp)e).value;
if (auto ex = scrubSE(sle))
@@ -6640,7 +6672,7 @@ private Expression scrubCacheValue(Expression e)
return null;
}
- if (e.op == TOK.classReference)
+ if (e.op == EXP.classReference)
{
if (auto ex = scrubSE((cast(ClassReferenceExp)e).value))
return ex;
@@ -6717,14 +6749,14 @@ private Expression copyRegionExp(Expression e)
switch (e.op)
{
- case TOK.classReference:
+ case EXP.classReference:
{
auto cre = e.isClassReferenceExp();
cre.value = copyRegionExp(cre.value).isStructLiteralExp();
break;
}
- case TOK.structLiteral:
+ case EXP.structLiteral:
{
auto sle = e.isStructLiteralExp();
@@ -6754,7 +6786,7 @@ private Expression copyRegionExp(Expression e)
return slec;
}
- case TOK.arrayLiteral:
+ case EXP.arrayLiteral:
{
auto ale = e.isArrayLiteralExp();
ale.basis = copyRegionExp(ale.basis);
@@ -6762,12 +6794,12 @@ private Expression copyRegionExp(Expression e)
break;
}
- case TOK.assocArrayLiteral:
+ case EXP.assocArrayLiteral:
copyArray(e.isAssocArrayLiteralExp().keys);
copyArray(e.isAssocArrayLiteralExp().values);
break;
- case TOK.slice:
+ case EXP.slice:
{
auto se = e.isSliceExp();
se.e1 = copyRegionExp(se.e1);
@@ -6776,7 +6808,7 @@ private Expression copyRegionExp(Expression e)
break;
}
- case TOK.tuple:
+ case EXP.tuple:
{
auto te = e.isTupleExp();
te.e0 = copyRegionExp(te.e0);
@@ -6784,17 +6816,17 @@ private Expression copyRegionExp(Expression e)
break;
}
- case TOK.address:
- case TOK.delegate_:
- case TOK.vector:
- case TOK.dotVariable:
+ case EXP.address:
+ case EXP.delegate_:
+ case EXP.vector:
+ case EXP.dotVariable:
{
UnaExp ue = cast(UnaExp)e;
ue.e1 = copyRegionExp(ue.e1);
break;
}
- case TOK.index:
+ case EXP.index:
{
BinExp be = cast(BinExp)e;
be.e1 = copyRegionExp(be.e1);
@@ -6802,30 +6834,30 @@ private Expression copyRegionExp(Expression e)
break;
}
- case TOK.this_:
- case TOK.super_:
- case TOK.variable:
- case TOK.type:
- case TOK.function_:
- case TOK.typeid_:
- case TOK.string_:
- case TOK.int64:
- case TOK.error:
- case TOK.float64:
- case TOK.complex80:
- case TOK.null_:
- case TOK.void_:
- case TOK.symbolOffset:
- case TOK.char_:
+ case EXP.this_:
+ case EXP.super_:
+ case EXP.variable:
+ case EXP.type:
+ case EXP.function_:
+ case EXP.typeid_:
+ case EXP.string_:
+ case EXP.int64:
+ case EXP.error:
+ case EXP.float64:
+ case EXP.complex80:
+ case EXP.null_:
+ case EXP.void_:
+ case EXP.symbolOffset:
+ case EXP.char_:
break;
- case TOK.cantExpression:
- case TOK.voidExpression:
- case TOK.showCtfeContext:
+ case EXP.cantExpression:
+ case EXP.voidExpression:
+ case EXP.showCtfeContext:
return e;
default:
- printf("e: %s, %s\n", Token.toChars(e.op), e.toChars());
+ printf("e: %s, %s\n", EXPtoString(e.op).ptr, e.toChars());
assert(0);
}
@@ -6848,7 +6880,7 @@ private Expression interpret_length(UnionExp* pue, InterState* istate, Expressio
if (auto aae = earg.isAssocArrayLiteralExp())
len = aae.keys.dim;
else
- assert(earg.op == TOK.null_);
+ assert(earg.op == EXP.null_);
emplaceExp!(IntegerExp)(pue, earg.loc, len, Type.tsize_t);
return pue.exp();
}
@@ -6862,12 +6894,12 @@ private Expression interpret_keys(UnionExp* pue, InterState* istate, Expression
earg = interpret(pue, earg, istate);
if (exceptionOrCantInterpret(earg))
return earg;
- if (earg.op == TOK.null_)
+ if (earg.op == EXP.null_)
{
emplaceExp!(NullExp)(pue, earg.loc, earg.type);
return pue.exp();
}
- if (earg.op != TOK.assocArrayLiteral && earg.type.toBasetype().ty != Taarray)
+ if (earg.op != EXP.assocArrayLiteral && earg.type.toBasetype().ty != Taarray)
return null;
AssocArrayLiteralExp aae = earg.isAssocArrayLiteralExp();
auto ae = ctfeEmplaceExp!ArrayLiteralExp(aae.loc, returnType, aae.keys);
@@ -6885,12 +6917,12 @@ private Expression interpret_values(UnionExp* pue, InterState* istate, Expressio
earg = interpret(pue, earg, istate);
if (exceptionOrCantInterpret(earg))
return earg;
- if (earg.op == TOK.null_)
+ if (earg.op == EXP.null_)
{
emplaceExp!(NullExp)(pue, earg.loc, earg.type);
return pue.exp();
}
- if (earg.op != TOK.assocArrayLiteral && earg.type.toBasetype().ty != Taarray)
+ if (earg.op != EXP.assocArrayLiteral && earg.type.toBasetype().ty != Taarray)
return null;
auto aae = earg.isAssocArrayLiteralExp();
auto ae = ctfeEmplaceExp!ArrayLiteralExp(aae.loc, returnType, aae.values);
@@ -6909,12 +6941,12 @@ private Expression interpret_dup(UnionExp* pue, InterState* istate, Expression e
earg = interpret(pue, earg, istate);
if (exceptionOrCantInterpret(earg))
return earg;
- if (earg.op == TOK.null_)
+ if (earg.op == EXP.null_)
{
emplaceExp!(NullExp)(pue, earg.loc, earg.type);
return pue.exp();
}
- if (earg.op != TOK.assocArrayLiteral && earg.type.toBasetype().ty != Taarray)
+ if (earg.op != EXP.assocArrayLiteral && earg.type.toBasetype().ty != Taarray)
return null;
auto aae = copyLiteral(earg).copy().isAssocArrayLiteralExp();
for (size_t i = 0; i < aae.keys.dim; i++)
@@ -6935,7 +6967,7 @@ private Expression interpret_aaApply(UnionExp* pue, InterState* istate, Expressi
aa = interpret(aa, istate);
if (exceptionOrCantInterpret(aa))
return aa;
- if (aa.op != TOK.assocArrayLiteral)
+ if (aa.op != EXP.assocArrayLiteral)
{
emplaceExp!(IntegerExp)(pue, deleg.loc, 0, Type.tsize_t);
return pue.exp();
@@ -7316,7 +7348,7 @@ private Expression evaluateIfBuiltin(UnionExp* pue, InterState* istate, const re
}
if (pthis && !fd.fbody && fd.isCtorDeclaration() && fd.parent && fd.parent.parent && fd.parent.parent.ident == Id.object)
{
- if (pthis.op == TOK.classReference && fd.parent.ident == Id.Throwable)
+ if (pthis.op == EXP.classReference && fd.parent.ident == Id.Throwable)
{
// At present, the constructors just copy their arguments into the struct.
// But we might need some magic if stack tracing gets added to druntime.
@@ -7383,7 +7415,7 @@ private Expression evaluatePostblit(InterState* istate, Expression e)
}
return null;
}
- if (e.op == TOK.structLiteral)
+ if (e.op == EXP.structLiteral)
{
// e.__postblit()
UnionExp ue = void;
@@ -7412,7 +7444,7 @@ private Expression evaluateDtor(InterState* istate, Expression e)
foreach_reverse (elem; *ale.elements)
e = evaluateDtor(istate, elem);
}
- else if (e.op == TOK.structLiteral)
+ else if (e.op == EXP.structLiteral)
{
// e.__dtor()
e = interpretFunction(&ue, sd.dtor, istate, null, e);
diff --git a/gcc/d/dmd/dmangle.d b/gcc/d/dmd/dmangle.d
index c417f93c353..065968025a6 100644
--- a/gcc/d/dmd/dmangle.d
+++ b/gcc/d/dmd/dmangle.d
@@ -979,7 +979,7 @@ public:
goto Lsa;
}
buf.writeByte('V');
- if (ea.op == TOK.tuple)
+ if (ea.op == EXP.tuple)
{
ea.error("tuple is not a valid template value argument");
continue;
@@ -987,7 +987,7 @@ public:
// Now that we know it is not an alias, we MUST obtain a value
uint olderr = global.errors;
ea = ea.ctfeInterpret();
- if (ea.op == TOK.error || olderr != global.errors)
+ if (ea.op == EXP.error || olderr != global.errors)
continue;
/* Use type mangling that matches what it would be for a function parameter
diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d
index 0925e7cd38a..1f05642d301 100644
--- a/gcc/d/dmd/dstruct.d
+++ b/gcc/d/dmd/dstruct.d
@@ -522,14 +522,14 @@ private bool _isZeroInit(Expression exp)
{
switch (exp.op)
{
- case TOK.int64:
+ case EXP.int64:
return exp.toInteger() == 0;
- case TOK.null_:
- case TOK.false_:
+ case EXP.null_:
+ case EXP.false_:
return true;
- case TOK.structLiteral:
+ case EXP.structLiteral:
{
auto sle = cast(StructLiteralExp) exp;
foreach (i; 0 .. sle.sd.fields.dim)
@@ -546,7 +546,7 @@ private bool _isZeroInit(Expression exp)
return true;
}
- case TOK.arrayLiteral:
+ case EXP.arrayLiteral:
{
auto ale = cast(ArrayLiteralExp)exp;
@@ -566,7 +566,7 @@ private bool _isZeroInit(Expression exp)
return true;
}
- case TOK.string_:
+ case EXP.string_:
{
StringExp se = cast(StringExp)exp;
@@ -581,14 +581,14 @@ private bool _isZeroInit(Expression exp)
return true;
}
- case TOK.vector:
+ case EXP.vector:
{
auto ve = cast(VectorExp) exp;
return _isZeroInit(ve.e1);
}
- case TOK.float64:
- case TOK.complex80:
+ case EXP.float64:
+ case EXP.complex80:
{
import dmd.root.ctfloat : CTFloat;
return (exp.toReal() is CTFloat.zero) &&
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index 9aa435d6463..b1d1b1d8d7c 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -1785,11 +1785,11 @@ extern (C++) final class WithScopeSymbol : ScopeDsymbol
Expression eold = null;
for (Expression e = withstate.exp; e != eold; e = resolveAliasThis(_scope, e))
{
- if (e.op == TOK.scope_)
+ if (e.op == EXP.scope_)
{
s = (cast(ScopeExp)e).sds;
}
- else if (e.op == TOK.type)
+ else if (e.op == EXP.type)
{
s = e.type.toDsymbol(null);
}
@@ -1826,14 +1826,14 @@ extern (C++) final class WithScopeSymbol : ScopeDsymbol
extern (C++) final class ArrayScopeSymbol : ScopeDsymbol
{
// either a SliceExp, an IndexExp, an ArrayExp, a TypeTuple or a TupleDeclaration.
- // Discriminated using DYNCAST and, for expressions, also TOK
+ // Discriminated using DYNCAST and, for expressions, also EXP
private RootObject arrayContent;
Scope* sc;
extern (D) this(Scope* sc, Expression exp)
{
super(exp.loc, null);
- assert(exp.op == TOK.index || exp.op == TOK.slice || exp.op == TOK.array);
+ assert(exp.op == EXP.index || exp.op == EXP.slice || exp.op == EXP.array);
this.sc = sc;
this.arrayContent = exp;
}
@@ -1950,7 +1950,7 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol
else if (ce.type && (t = ce.type.toBasetype()) !is null && (t.ty == Tstruct || t.ty == Tclass))
{
// Look for opDollar
- assert(exp.op == TOK.array || exp.op == TOK.slice);
+ assert(exp.op == EXP.array || exp.op == EXP.slice);
AggregateDeclaration ad = isAggregate(t);
assert(ad);
Dsymbol s = ad.search(loc, Id.opDollar);
@@ -1962,11 +1962,11 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol
if (TemplateDeclaration td = s.isTemplateDeclaration())
{
dinteger_t dim = 0;
- if (exp.op == TOK.array)
+ if (exp.op == EXP.array)
{
dim = (cast(ArrayExp)exp).currentDimension;
}
- else if (exp.op == TOK.slice)
+ else if (exp.op == EXP.slice)
{
dim = 0; // slices are currently always one-dimensional
}
@@ -1987,7 +1987,7 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol
* Note that it's impossible to have both template & function opDollar,
* because both take no arguments.
*/
- if (exp.op == TOK.array && (cast(ArrayExp)exp).arguments.dim != 1)
+ if (exp.op == EXP.array && (cast(ArrayExp)exp).arguments.dim != 1)
{
exp.error("`%s` only defines opDollar for one dimension", ad.toChars());
return null;
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index 047c1eb6f69..0bf9a80f37d 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -133,7 +133,7 @@ AlignDeclaration getAlignment(AlignDeclaration ad, Scope* sc)
e = e.ctfeInterpret();
exp = e; // could be re-evaluated if exps are assigned to more than one AlignDeclaration by CParser.applySpecifier(),
// e.g. `_Alignas(8) int a, b;`
- if (e.op == TOK.error)
+ if (e.op == EXP.error)
errors = true;
else
{
@@ -611,7 +611,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}
Lnomatch:
- if (ie && ie.op == TOK.tuple)
+ if (ie && ie.op == EXP.tuple)
{
auto te = ie.isTupleExp();
size_t tedim = te.exps.dim;
@@ -652,6 +652,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
storage_class |= arg.storageClass;
auto v = new VarDeclaration(dsym.loc, arg.type, id, ti, storage_class);
//printf("declaring field %s of type %s\n", v.toChars(), v.type.toChars());
+ v.overlapped = dsym.overlapped;
+
v.dsymbolSemantic(sc);
if (sc.scopesym)
@@ -879,11 +881,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if ((!dsym._init || dsym._init.isVoidInitializer) && !fd)
{
// If not mutable, initializable by constructor only
- dsym.storage_class |= STC.ctorinit;
+ dsym.setInCtorOnly = true;
}
if (dsym._init)
- dsym.storage_class |= STC.init; // remember we had an explicit initializer
+ { } // remember we had an explicit initializer
else if (dsym.storage_class & STC.manifest)
dsym.error("manifest constants must have initializers");
@@ -1013,7 +1015,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
exp = exp.expressionSemantic(sc);
dsym.canassign--;
exp = exp.optimize(WANTvalue);
- if (exp.op == TOK.error)
+ if (exp.op == EXP.error)
{
dsym._init = new ErrorInitializer();
ei = null;
@@ -1024,7 +1026,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (ei && dsym.isScope())
{
Expression ex = ei.exp.lastComma();
- if (ex.op == TOK.blit || ex.op == TOK.construct)
+ if (ex.op == EXP.blit || ex.op == EXP.construct)
ex = (cast(AssignExp)ex).e2;
if (auto ne = ex.isNewExp())
{
@@ -1057,7 +1059,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// Don't run CTFE for the temporary variables inside typeof
dsym._init = dsym._init.initializerSemantic(sc, dsym.type, sc.intypeof == 1 ? INITnointerpret : INITinterpret);
const init_err = dsym._init.isExpInitializer();
- if (init_err && init_err.exp.op == TOK.showCtfeContext)
+ if (init_err && init_err.exp.op == EXP.showCtfeContext)
{
errorSupplemental(dsym.loc, "compile time context created here");
}
@@ -1085,7 +1087,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
dsym.inuse++;
// Bug 20549. Don't try this on modules or packages, syntaxCopy
// could crash (inf. recursion) on a mod/pkg referencing itself
- if (ei && (ei.exp.op != TOK.scope_ ? true : !ei.exp.isScopeExp().sds.isPackage()))
+ if (ei && (ei.exp.op != EXP.scope_ ? true : !ei.exp.isScopeExp().sds.isPackage()))
{
if (ei.exp.type)
{
@@ -1241,7 +1243,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
width.error("bit-field `%s` has zero width", dsym.toChars());
dsym.errors = true;
}
- const max_width = dsym.type.size() * 8;
+ const sz = dsym.type.size();
+ if (sz == SIZE_INVALID)
+ dsym.errors = true;
+ const max_width = sz * 8;
if (uwidth > max_width)
{
width.error("width `%lld` of bit-field `%s` does not fit in type `%s`", cast(long)uwidth, dsym.toChars(), dsym.type.toChars());
@@ -1459,7 +1464,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
override void visit(AnonDeclaration scd)
{
- //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
+ //printf("\tAnonDeclaration::semantic isunion:%d ptr:%p\n", scd.isunion, scd);
assert(sc.parent);
auto p = sc.parent.pastMixin();
auto ad = p.isAggregateDeclaration();
@@ -1479,6 +1484,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
for (size_t i = 0; i < scd.decl.dim; i++)
{
Dsymbol s = (*scd.decl)[i];
+ if (auto var = s.isVarDeclaration)
+ {
+ if (scd.isunion)
+ var.overlapped = true;
+ }
s.dsymbolSemantic(sc);
}
sc = sc.pop();
@@ -1651,7 +1661,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
e = resolveProperties(sc, e);
sc = sc.endCTFE();
e = ctfeInterpretForPragmaMsg(e);
- if (e.op == TOK.error)
+ if (e.op == EXP.error)
{
errorSupplemental(pd.loc, "while evaluating `pragma(msg, %s)`", (*pd.args)[i].toChars());
return;
@@ -2185,7 +2195,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
e = resolveProperties(sc, e);
e = e.integralPromotions(sc);
e = e.ctfeInterpret();
- if (e.op == TOK.error)
+ if (e.op == EXP.error)
return errorReturn(em);
auto ie = e.isIntegerExp();
if (!ie)
@@ -2303,7 +2313,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
e = e.expressionSemantic(sc);
e = resolveProperties(sc, e);
e = e.ctfeInterpret();
- if (e.op == TOK.error)
+ if (e.op == EXP.error)
return errorReturn();
if (first && !em.ed.memtype && !em.ed.isAnonymous())
{
@@ -2331,7 +2341,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
ev = ev.implicitCastTo(sc, em.ed.memtype);
ev = ev.ctfeInterpret();
ev = ev.castTo(sc, em.ed.type);
- if (ev.op == TOK.error)
+ if (ev.op == EXP.error)
em.ed.errors = true;
enm.value = ev;
});
@@ -2429,7 +2439,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// Set value to (eprev + 1).
// But first check that (eprev != emax)
assert(eprev);
- Expression e = new EqualExp(TOK.equal, em.loc, eprev, emax);
+ Expression e = new EqualExp(EXP.equal, em.loc, eprev, emax);
e = e.expressionSemantic(sc);
e = e.ctfeInterpret();
if (e.toInteger())
@@ -2446,7 +2456,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
e = e.ctfeInterpret();
// save origValue (without cast) for better json output
- if (e.op != TOK.error) // avoid duplicate diagnostics
+ if (e.op != EXP.error) // avoid duplicate diagnostics
{
assert(emprev.origValue);
em.origValue = new AddExp(em.loc, emprev.origValue, IntegerExp.literal!1);
@@ -2454,12 +2464,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
em.origValue = em.origValue.ctfeInterpret();
}
- if (e.op == TOK.error)
+ if (e.op == EXP.error)
return errorReturn();
if (e.type.isfloating())
{
// Check that e != eprev (not always true for floats)
- Expression etest = new EqualExp(TOK.equal, em.loc, e, eprev);
+ Expression etest = new EqualExp(EXP.equal, em.loc, e, eprev);
etest = etest.expressionSemantic(sc);
etest = etest.ctfeInterpret();
if (etest.toInteger())
@@ -4162,7 +4172,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
Expression e = new IdentifierExp(Loc.initial, v.ident);
e = new AddAssignExp(Loc.initial, e, IntegerExp.literal!1);
- e = new EqualExp(TOK.notEqual, Loc.initial, e, IntegerExp.literal!1);
+ e = new EqualExp(EXP.notEqual, Loc.initial, e, IntegerExp.literal!1);
s = new IfStatement(Loc.initial, null, e, new ReturnStatement(Loc.initial, null), null, Loc.initial);
sa.push(s);
@@ -4239,7 +4249,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
Expression e = new IdentifierExp(Loc.initial, v.ident);
e = new AddAssignExp(Loc.initial, e, IntegerExp.literal!(-1));
- e = new EqualExp(TOK.notEqual, Loc.initial, e, IntegerExp.literal!0);
+ e = new EqualExp(EXP.notEqual, Loc.initial, e, IntegerExp.literal!0);
s = new IfStatement(Loc.initial, null, e, new ReturnStatement(Loc.initial, null), null, Loc.initial);
sa.push(s);
@@ -4616,6 +4626,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (cldec.errors)
cldec.type = Type.terror;
+ if (cldec.semanticRun == PASS.init)
+ cldec.type = cldec.type.addSTC(sc.stc | cldec.storage_class);
cldec.type = cldec.type.typeSemantic(cldec.loc, sc);
if (auto tc = cldec.type.isTypeClass())
if (tc.sym != cldec)
@@ -6422,7 +6434,7 @@ void aliasSemantic(AliasDeclaration ds, Scope* sc)
s = getDsymbol(e);
if (!s)
{
- if (e.op != TOK.error)
+ if (e.op != EXP.error)
ds.error("cannot alias an expression `%s`", e.toChars());
return errorRet();
}
@@ -6606,7 +6618,7 @@ private void aliasAssignSemantic(AliasAssign ds, Scope* sc)
s = getDsymbol(e);
if (!s)
{
- if (e.op != TOK.error)
+ if (e.op != EXP.error)
ds.error("cannot alias an expression `%s`", e.toChars());
return errorRet();
}
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index 9d7957a975d..5dedcba5627 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -144,7 +144,7 @@ extern (C++) bool isError(const RootObject o)
if (const t = isType(o))
return (t.ty == Terror);
if (const e = isExpression(o))
- return (e.op == TOK.error || !e.type || e.type.ty == Terror);
+ return (e.op == EXP.error || !e.type || e.type.ty == Terror);
if (const v = isTuple(o))
return arrayObjectIsError(&v.objects);
const s = isDsymbol(o);
@@ -297,8 +297,8 @@ private bool match(RootObject o1, RootObject o2)
static if (log)
{
- printf("\te1 = %s '%s' %s\n", e1.type ? e1.type.toChars() : "null", Token.toChars(e1.op), e1.toChars());
- printf("\te2 = %s '%s' %s\n", e2.type ? e2.type.toChars() : "null", Token.toChars(e2.op), e2.toChars());
+ printf("\te1 = %s '%s' %s\n", e1.type ? e1.type.toChars() : "null", EXPtoString(e1.op).ptr, e1.toChars());
+ printf("\te2 = %s '%s' %s\n", e2.type ? e2.type.toChars() : "null", EXPtoString(e2.op).ptr, e2.toChars());
}
// two expressions can be equal although they do not have the same
@@ -421,26 +421,26 @@ private size_t expressionHash(Expression e)
switch (e.op)
{
- case TOK.int64:
+ case EXP.int64:
return cast(size_t) e.isIntegerExp().getInteger();
- case TOK.float64:
+ case EXP.float64:
return CTFloat.hash(e.isRealExp().value);
- case TOK.complex80:
+ case EXP.complex80:
auto ce = e.isComplexExp();
return mixHash(CTFloat.hash(ce.toReal), CTFloat.hash(ce.toImaginary));
- case TOK.identifier:
+ case EXP.identifier:
return cast(size_t)cast(void*) e.isIdentifierExp().ident;
- case TOK.null_:
+ case EXP.null_:
return cast(size_t)cast(void*) e.isNullExp().type;
- case TOK.string_:
+ case EXP.string_:
return calcHash(e.isStringExp.peekData());
- case TOK.tuple:
+ case EXP.tuple:
{
auto te = e.isTupleExp();
size_t hash = 0;
@@ -450,7 +450,7 @@ private size_t expressionHash(Expression e)
return hash;
}
- case TOK.arrayLiteral:
+ case EXP.arrayLiteral:
{
auto ae = e.isArrayLiteralExp();
size_t hash;
@@ -459,7 +459,7 @@ private size_t expressionHash(Expression e)
return hash;
}
- case TOK.assocArrayLiteral:
+ case EXP.assocArrayLiteral:
{
auto ae = e.isAssocArrayLiteralExp();
size_t hash;
@@ -469,7 +469,7 @@ private size_t expressionHash(Expression e)
return hash;
}
- case TOK.structLiteral:
+ case EXP.structLiteral:
{
auto se = e.isStructLiteralExp();
size_t hash;
@@ -478,10 +478,10 @@ private size_t expressionHash(Expression e)
return hash;
}
- case TOK.variable:
+ case EXP.variable:
return cast(size_t)cast(void*) e.isVarExp().var;
- case TOK.function_:
+ case EXP.function_:
return cast(size_t)cast(void*) e.isFuncExp().fd;
default:
@@ -1629,7 +1629,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
farg = (*fargs)[argi + i];
// Check invalid arguments to detect errors early.
- if (farg.op == TOK.error || farg.type.ty == Terror)
+ if (farg.op == EXP.error || farg.type.ty == Terror)
return nomatch();
if (!(fparam.storageClass & STC.lazy_) && farg.type.ty == Tvoid)
@@ -1825,7 +1825,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
}
{
// Check invalid arguments to detect errors early.
- if (farg.op == TOK.error || farg.type.ty == Terror)
+ if (farg.op == EXP.error || farg.type.ty == Terror)
return nomatch();
Type att = null;
@@ -1837,7 +1837,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
}
Type argtype = farg.type;
- if (!(fparam.storageClass & STC.lazy_) && argtype.ty == Tvoid && farg.op != TOK.function_)
+ if (!(fparam.storageClass & STC.lazy_) && argtype.ty == Tvoid && farg.op != EXP.function_)
return nomatch();
// https://issues.dlang.org/show_bug.cgi?id=12876
@@ -1853,17 +1853,17 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
Type taai;
if (argtype.ty == Tarray && (prmtype.ty == Tsarray || prmtype.ty == Taarray && (taai = (cast(TypeAArray)prmtype).index).ty == Tident && (cast(TypeIdentifier)taai).idents.dim == 0))
{
- if (farg.op == TOK.string_)
+ if (farg.op == EXP.string_)
{
StringExp se = cast(StringExp)farg;
argtype = se.type.nextOf().sarrayOf(se.len);
}
- else if (farg.op == TOK.arrayLiteral)
+ else if (farg.op == EXP.arrayLiteral)
{
ArrayLiteralExp ae = cast(ArrayLiteralExp)farg;
argtype = ae.type.nextOf().sarrayOf(ae.elements.dim);
}
- else if (farg.op == TOK.slice)
+ else if (farg.op == EXP.slice)
{
SliceExp se = cast(SliceExp)farg;
if (Type tsa = toStaticArrayType(se))
@@ -1939,7 +1939,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
{
if (!farg.isLvalue())
{
- if ((farg.op == TOK.string_ || farg.op == TOK.slice) && (prmtype.ty == Tsarray || prmtype.ty == Taarray))
+ if ((farg.op == EXP.string_ || farg.op == EXP.slice) && (prmtype.ty == Tsarray || prmtype.ty == Taarray))
{
// Allow conversion from T[lwr .. upr] to ref T[upr-lwr]
}
@@ -2280,13 +2280,13 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
Declaration d;
VarDeclaration v = null;
- if (ea && ea.op == TOK.type)
+ if (ea && ea.op == EXP.type)
ta = ea.type;
- else if (ea && ea.op == TOK.scope_)
+ else if (ea && ea.op == EXP.scope_)
sa = (cast(ScopeExp)ea).sds;
- else if (ea && (ea.op == TOK.this_ || ea.op == TOK.super_))
+ else if (ea && (ea.op == EXP.this_ || ea.op == EXP.super_))
sa = (cast(ThisExp)ea).var;
- else if (ea && ea.op == TOK.function_)
+ else if (ea && ea.op == EXP.function_)
{
if ((cast(FuncExp)ea).td)
sa = (cast(FuncExp)ea).td;
@@ -3826,7 +3826,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
if (tparam.ty == Tsarray)
{
TypeSArray tsa = cast(TypeSArray)tparam;
- if (tsa.dim.op == TOK.variable && (cast(VarExp)tsa.dim).var.storage_class & STC.templateparameter)
+ if (tsa.dim.op == EXP.variable && (cast(VarExp)tsa.dim).var.storage_class & STC.templateparameter)
{
Identifier id = (cast(VarExp)tsa.dim).var.ident;
i = templateIdentifierLookup(id, parameters);
@@ -4209,7 +4209,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
/* If it is one of the template parameters for this template,
* we should not attempt to interpret it. It already has a value.
*/
- if (e2.op == TOK.variable && ((cast(VarExp)e2).var.storage_class & STC.templateparameter))
+ if (e2.op == EXP.variable && ((cast(VarExp)e2).var.storage_class & STC.templateparameter))
{
/*
* (T:Number!(e2), int e2)
@@ -4847,9 +4847,9 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
// Reset inference target for the later re-semantic
e.fd.treq = null;
- if (ex.op == TOK.error)
+ if (ex.op == EXP.error)
return;
- if (ex.op != TOK.function_)
+ if (ex.op != EXP.function_)
return;
visit(ex.type);
return;
@@ -6642,13 +6642,13 @@ extern (C++) class TemplateInstance : ScopeDsymbol
else if (ea)
{
Lexpr:
- //printf("+[%d] ea = %s %s\n", j, Token.toChars(ea.op), ea.toChars());
+ //printf("+[%d] ea = %s %s\n", j, EXPtoString(ea.op).ptr, ea.toChars());
if (flags & 1) // only used by __traits
{
ea = ea.expressionSemantic(sc);
// must not interpret the args, excepting template parameters
- if (ea.op != TOK.variable || ((cast(VarExp)ea).var.storage_class & STC.templateparameter))
+ if (ea.op != EXP.variable || ((cast(VarExp)ea).var.storage_class & STC.templateparameter))
{
ea = ea.optimize(WANTvalue);
}
@@ -6659,7 +6659,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
ea = ea.expressionSemantic(sc);
sc = sc.endCTFE();
- if (ea.op == TOK.variable)
+ if (ea.op == EXP.variable)
{
/* If the parameter is a function that is not called
* explicitly, i.e. `foo!func` as opposed to `foo!func()`,
@@ -6687,8 +6687,8 @@ extern (C++) class TemplateInstance : ScopeDsymbol
ea = ErrorExp.get();
}
}
- //printf("-[%d] ea = %s %s\n", j, Token.toChars(ea.op), ea.toChars());
- if (ea.op == TOK.tuple)
+ //printf("-[%d] ea = %s %s\n", j, EXPtoString(ea.op).ptr, ea.toChars());
+ if (ea.op == EXP.tuple)
{
// Expand tuple
TupleExp te = cast(TupleExp)ea;
@@ -6703,24 +6703,24 @@ extern (C++) class TemplateInstance : ScopeDsymbol
j--;
continue;
}
- if (ea.op == TOK.error)
+ if (ea.op == EXP.error)
{
err = true;
continue;
}
(*tiargs)[j] = ea;
- if (ea.op == TOK.type)
+ if (ea.op == EXP.type)
{
ta = ea.type;
goto Ltype;
}
- if (ea.op == TOK.scope_)
+ if (ea.op == EXP.scope_)
{
sa = (cast(ScopeExp)ea).sds;
goto Ldsym;
}
- if (ea.op == TOK.function_)
+ if (ea.op == EXP.function_)
{
FuncExp fe = cast(FuncExp)ea;
/* A function literal, that is passed to template and
@@ -6741,24 +6741,24 @@ extern (C++) class TemplateInstance : ScopeDsymbol
//goto Ldsym;
}
}
- if (ea.op == TOK.dotVariable && !(flags & 1))
+ if (ea.op == EXP.dotVariable && !(flags & 1))
{
// translate expression to dsymbol.
sa = (cast(DotVarExp)ea).var;
goto Ldsym;
}
- if (ea.op == TOK.template_)
+ if (ea.op == EXP.template_)
{
sa = (cast(TemplateExp)ea).td;
goto Ldsym;
}
- if (ea.op == TOK.dotTemplateDeclaration && !(flags & 1))
+ if (ea.op == EXP.dotTemplateDeclaration && !(flags & 1))
{
// translate expression to dsymbol.
sa = (cast(DotTemplateExp)ea).td;
goto Ldsym;
}
- if (ea.op == TOK.dot)
+ if (ea.op == EXP.dot)
{
if (auto se = (cast(DotExp)ea).e2.isScopeExp())
{
@@ -7256,17 +7256,17 @@ extern (C++) class TemplateInstance : ScopeDsymbol
Tuple va = isTuple(o);
if (ea)
{
- if (ea.op == TOK.variable)
+ if (ea.op == EXP.variable)
{
sa = (cast(VarExp)ea).var;
goto Lsa;
}
- if (ea.op == TOK.this_)
+ if (ea.op == EXP.this_)
{
sa = (cast(ThisExp)ea).var;
goto Lsa;
}
- if (ea.op == TOK.function_)
+ if (ea.op == EXP.function_)
{
if ((cast(FuncExp)ea).td)
sa = (cast(FuncExp)ea).td;
@@ -7275,7 +7275,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
goto Lsa;
}
// Emulate Expression.toMangleBuffer call that had exist in TemplateInstance.genIdent.
- if (ea.op != TOK.int64 && ea.op != TOK.float64 && ea.op != TOK.complex80 && ea.op != TOK.null_ && ea.op != TOK.string_ && ea.op != TOK.arrayLiteral && ea.op != TOK.assocArrayLiteral && ea.op != TOK.structLiteral)
+ if (ea.op != EXP.int64 && ea.op != EXP.float64 && ea.op != EXP.complex80 && ea.op != EXP.null_ && ea.op != EXP.string_ && ea.op != EXP.arrayLiteral && ea.op != EXP.assocArrayLiteral && ea.op != EXP.structLiteral)
{
ea.error("expression `%s` is not a valid template value argument", ea.toChars());
errors = true;
@@ -7319,6 +7319,19 @@ extern (C++) class TemplateInstance : ScopeDsymbol
goto L1; // dparent is most nested
}
}
+ //https://issues.dlang.org/show_bug.cgi?id=17870
+ if (dparent.isClassDeclaration() && enclosing.isClassDeclaration())
+ {
+ auto pc = dparent.isClassDeclaration();
+ auto ec = enclosing.isClassDeclaration();
+ if (pc.isBaseOf(ec, null))
+ goto L1;
+ else if (ec.isBaseOf(pc, null))
+ {
+ enclosing = dparent;
+ goto L1;
+ }
+ }
error("`%s` is nested in both `%s` and `%s`", toChars(), enclosing.toChars(), dparent.toChars());
errors = true;
}
@@ -7584,15 +7597,15 @@ void unSpeculative(Scope* sc, RootObject o)
bool definitelyValueParameter(Expression e)
{
// None of these can be value parameters
- if (e.op == TOK.tuple || e.op == TOK.scope_ ||
- e.op == TOK.type || e.op == TOK.dotType ||
- e.op == TOK.template_ || e.op == TOK.dotTemplateDeclaration ||
- e.op == TOK.function_ || e.op == TOK.error ||
- e.op == TOK.this_ || e.op == TOK.super_ ||
- e.op == TOK.dot)
+ if (e.op == EXP.tuple || e.op == EXP.scope_ ||
+ e.op == EXP.type || e.op == EXP.dotType ||
+ e.op == EXP.template_ || e.op == EXP.dotTemplateDeclaration ||
+ e.op == EXP.function_ || e.op == EXP.error ||
+ e.op == EXP.this_ || e.op == EXP.super_ ||
+ e.op == EXP.dot)
return false;
- if (e.op != TOK.dotVariable)
+ if (e.op != EXP.dotVariable)
return true;
/* Template instantiations involving a DotVar expression are difficult.
@@ -7606,20 +7619,20 @@ bool definitelyValueParameter(Expression e)
if (f)
return false;
- while (e.op == TOK.dotVariable)
+ while (e.op == EXP.dotVariable)
{
e = (cast(DotVarExp)e).e1;
}
// this.x.y and super.x.y couldn't possibly be valid values.
- if (e.op == TOK.this_ || e.op == TOK.super_)
+ if (e.op == EXP.this_ || e.op == EXP.super_)
return false;
// e.type.x could be an alias
- if (e.op == TOK.dotType)
+ if (e.op == EXP.dotType)
return false;
// var.x.y is the only other possible form of alias
- if (e.op != TOK.variable)
+ if (e.op != EXP.variable)
return true;
VarDeclaration v = (cast(VarExp)e).var.isVarDeclaration();
@@ -8010,7 +8023,7 @@ MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, Templ
uint olderrors = global.startGagging();
ei = resolveProperties(sc, ei);
ei = ei.ctfeInterpret();
- if (global.endGagging(olderrors) || ei.op == TOK.error)
+ if (global.endGagging(olderrors) || ei.op == EXP.error)
return matchArgNoMatch();
/* https://issues.dlang.org/show_bug.cgi?id=14520
@@ -8032,7 +8045,7 @@ MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, Templ
m = MATCH.convert;
}
- if (ei && ei.op == TOK.variable)
+ if (ei && ei.op == EXP.variable)
{
// Resolve const variables that we had skipped earlier
ei = ei.ctfeInterpret();
@@ -8110,9 +8123,9 @@ MATCH matchArg(TemplateParameter tp, Scope* sc, RootObject oarg, size_t i, Templ
Type ta = isType(oarg);
RootObject sa = ta && !ta.deco ? null : getDsymbol(oarg);
Expression ea = isExpression(oarg);
- if (ea && (ea.op == TOK.this_ || ea.op == TOK.super_))
+ if (ea && (ea.op == EXP.this_ || ea.op == EXP.super_))
sa = (cast(ThisExp)ea).var;
- else if (ea && ea.op == TOK.scope_)
+ else if (ea && ea.op == EXP.scope_)
sa = (cast(ScopeExp)ea).sds;
if (sa)
{
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index e19adfc4b14..51f53c8402f 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -21,6 +21,7 @@ import dmd.attrib;
import dmd.dsymbol;
import dmd.errors;
import dmd.globals;
+import dmd.hdrgen;
import dmd.identifier;
import dmd.root.filename;
import dmd.visitor;
@@ -2395,7 +2396,7 @@ public:
{
debug (Debug_DtoH) mixin(traceVisit!e);
- buf.writestring(tokToString(e.op));
+ buf.writestring(expToString(e.op));
e.e1.accept(this);
}
@@ -2405,20 +2406,20 @@ public:
e.e1.accept(this);
buf.writeByte(' ');
- buf.writestring(tokToString(e.op));
+ buf.writestring(expToString(e.op));
buf.writeByte(' ');
e.e2.accept(this);
}
/// Translates operator `op` into the C++ representation
- private extern(D) static string tokToString(const TOK op)
+ private extern(D) static string expToString(const EXP op)
{
- switch (op) with (TOK)
+ switch (op) with (EXP)
{
case identity: return "==";
case notIdentity: return "!=";
default:
- return Token.toString(op);
+ return EXPtoString(op);
}
}
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index d502f80975b..62f87e506ab 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -536,8 +536,8 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
{
enum log = false;
if (log) printf("checkAssignEscape(e: %s)\n", e.toChars());
- if (e.op != TOK.assign && e.op != TOK.blit && e.op != TOK.construct &&
- e.op != TOK.concatenateAssign && e.op != TOK.concatenateElemAssign && e.op != TOK.concatenateDcharAssign)
+ if (e.op != EXP.assign && e.op != EXP.blit && e.op != EXP.construct &&
+ e.op != EXP.concatenateAssign && e.op != EXP.concatenateElemAssign && e.op != EXP.concatenateDcharAssign)
return false;
auto ae = cast(BinExp)e;
Expression e1 = ae.e1;
@@ -568,7 +568,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
VarDeclaration va = expToVariable(e1);
- if (va && e.op == TOK.concatenateElemAssign)
+ if (va && e.op == EXP.concatenateElemAssign)
{
/* https://issues.dlang.org/show_bug.cgi?id=17842
* Draw an equivalence between:
@@ -596,11 +596,6 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
FuncDeclaration fd = sc.func;
- // Try to infer 'scope' for va if in a function not marked @system
- bool inferScope = false;
- if (va && fd && fd.type && fd.type.isTypeFunction())
- inferScope = fd.type.isTypeFunction().trust != TRUST.system;
- //printf("inferScope = %d, %d\n", inferScope, (va.storage_class & STCmaybescope) != 0);
// Determine if va is a parameter that is an indirect reference
const bool vaIsRef = va && va.storage_class & STC.parameter &&
@@ -677,7 +672,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
if (va.isScope())
continue;
- if (inferScope && !va.doNotInferScope)
+ if (!va.doNotInferScope)
{
if (log) printf("inferring scope for lvalue %s\n", va.toChars());
va.storage_class |= STC.scope_ | STC.scopeinferred;
@@ -713,7 +708,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
if (va && !va.isDataseg() && !va.doNotInferScope)
{
- if (!va.isScope() && inferScope)
+ if (!va.isScope())
{ /* v is scope, and va is not scope, so va needs to
* infer scope
*/
@@ -749,7 +744,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
{
if (va && !va.isDataseg() && !va.doNotInferScope)
{
- if (!va.isScope() && inferScope)
+ if (!va.isScope())
{ //printf("inferring scope for %s\n", va.toChars());
va.storage_class |= STC.scope_ | STC.scopeinferred;
}
@@ -840,7 +835,7 @@ ByRef:
if (va && !va.isDataseg() && !va.doNotInferScope)
{
- if (!va.isScope() && inferScope)
+ if (!va.isScope())
{ //printf("inferring scope for %s\n", va.toChars());
va.storage_class |= STC.scope_ | STC.scopeinferred;
}
@@ -848,7 +843,7 @@ ByRef:
va.storage_class |= STC.return_ | STC.returninferred;
continue;
}
- if (e1.op == TOK.structLiteral)
+ if (e1.op == EXP.structLiteral)
continue;
if (fd.setUnsafe())
{
@@ -890,7 +885,7 @@ ByRef:
/* Don't infer STC.scope_ for va, because then a closure
* won't be generated for fd.
*/
- //if (!va.isScope() && inferScope)
+ //if (!va.isScope())
//va.storage_class |= STC.scope_ | STC.scopeinferred;
continue;
}
@@ -909,7 +904,7 @@ ByRef:
/* Do not allow slicing of a static array returned by a function
*/
- if (ee.op == TOK.call && ee.type.toBasetype().isTypeSArray() && e1.type.toBasetype().isTypeDArray() &&
+ if (ee.op == EXP.call && ee.type.toBasetype().isTypeSArray() && e1.type.toBasetype().isTypeDArray() &&
!(va && va.storage_class & STC.temp))
{
if (!gag)
@@ -919,7 +914,7 @@ ByRef:
continue;
}
- if (ee.op == TOK.call && ee.type.toBasetype().isTypeStruct() &&
+ if (ee.op == EXP.call && ee.type.toBasetype().isTypeStruct() &&
(!va || !(va.storage_class & STC.temp)) &&
fd.setUnsafe())
{
@@ -930,7 +925,7 @@ ByRef:
continue;
}
- if (ee.op == TOK.structLiteral &&
+ if (ee.op == EXP.structLiteral &&
(!va || !(va.storage_class & STC.temp)) &&
fd.setUnsafe())
{
@@ -943,7 +938,7 @@ ByRef:
if (va && !va.isDataseg() && !va.doNotInferScope)
{
- if (!va.isScope() && inferScope)
+ if (!va.isScope())
{ //printf("inferring scope for %s\n", va.toChars());
va.storage_class |= STC.scope_ | STC.scopeinferred;
}
@@ -993,17 +988,13 @@ bool checkThrowEscape(Scope* sc, Expression e, bool gag)
if (v.isScope() && !v.iscatchvar) // special case: allow catch var to be rethrown
// despite being `scope`
{
- if (sc._module && sc._module.isRoot())
+ if (global.params.useDIP1000 == FeatureState.enabled) // https://issues.dlang.org/show_bug.cgi?id=17029
{
- // Only look for errors if in module listed on command line
- if (global.params.useDIP1000 == FeatureState.enabled) // https://issues.dlang.org/show_bug.cgi?id=17029
- {
- if (!gag)
- error(e.loc, "scope variable `%s` may not be thrown", v.toChars());
- result = true;
- }
- continue;
+ if (!gag)
+ error(e.loc, "scope variable `%s` may not be thrown", v.toChars());
+ result = true;
}
+ continue;
}
else
{
@@ -1051,7 +1042,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
if (v.isScope())
{
- if (sc._module && sc._module.isRoot() &&
+ if (
/* This case comes up when the ReturnStatement of a __foreachbody is
* checked for escapes by the caller of __foreachbody. Skip it.
*
@@ -1128,9 +1119,6 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
if (!v.isReference())
continue;
- if (!sc._module || !sc._module.isRoot())
- continue;
-
// https://dlang.org/spec/function.html#return-ref-parameters
// Only look for errors if in module listed on command line
if (p == sc.func)
@@ -1264,7 +1252,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
continue;
auto pfunc = p.isFuncDeclaration();
- if (pfunc && sc._module && sc._module.isRoot() &&
+ if (pfunc &&
/* This case comes up when the ReturnStatement of a __foreachbody is
* checked for escapes by the caller of __foreachbody. Skip it.
*
@@ -1284,7 +1272,8 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
)
{
// Only look for errors if in module listed on command line
- if (global.params.useDIP1000 == FeatureState.enabled) // https://issues.dlang.org/show_bug.cgi?id=17029
+ // https://issues.dlang.org/show_bug.cgi?id=17029
+ if (global.params.useDIP1000 == FeatureState.enabled && sc.func.setUnsafe())
{
if (!gag)
error(e.loc, "scope variable `%s` may not be returned", v.toChars());
@@ -1398,7 +1387,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
{
inferReturn(sc.func, v); // infer addition of 'return'
}
- else if (sc._module && sc._module.isRoot())
+ else
{
// https://dlang.org/spec/function.html#return-ref-parameters
// Only look for errors if in module listed on command line
@@ -1528,7 +1517,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false)
* allowed, but CTFE can generate one out of a new expression,
* but it'll be placed in static data so no need to check it.
*/
- if (e.e1.op != TOK.structLiteral)
+ if (e.e1.op != EXP.structLiteral)
escapeByRef(e.e1, er, live);
}
@@ -1768,7 +1757,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false)
}
}
// If 'this' is returned, check it too
- if (e.e1.op == TOK.dotVariable && t1.ty == Tfunction)
+ if (e.e1.op == EXP.dotVariable && t1.ty == Tfunction)
{
DotVarExp dve = e.e1.isDotVarExp();
FuncDeclaration fd = dve.var.isFuncDeclaration();
@@ -2024,7 +2013,7 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false)
}
}
// If 'this' is returned by ref, check it too
- if (e.e1.op == TOK.dotVariable && t1.ty == Tfunction)
+ if (e.e1.op == EXP.dotVariable && t1.ty == Tfunction)
{
DotVarExp dve = e.e1.isDotVarExp();
@@ -2051,7 +2040,7 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false)
}
}
// If it's a delegate, check it too
- if (e.e1.op == TOK.variable && t1.ty == Tdelegate)
+ if (e.e1.op == EXP.variable && t1.ty == Tdelegate)
{
escapeByValue(e.e1, er, live);
}
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 2a623324454..e6b7e3014f1 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -60,6 +60,7 @@ import dmd.optimize;
import dmd.root.ctfloat;
import dmd.root.filename;
import dmd.common.outbuffer;
+import dmd.root.optional;
import dmd.root.rmem;
import dmd.root.rootobject;
import dmd.root.string;
@@ -116,7 +117,7 @@ enum ModifyFlags
inout(Expression) firstComma(inout Expression e)
{
Expression ex = cast()e;
- while (ex.op == TOK.comma)
+ while (ex.op == EXP.comma)
ex = (cast(CommaExp)ex).e1;
return cast(inout)ex;
@@ -133,7 +134,7 @@ inout(Expression) firstComma(inout Expression e)
inout(Expression) lastComma(inout Expression e)
{
Expression ex = cast()e;
- while (ex.op == TOK.comma)
+ while (ex.op == EXP.comma)
ex = (cast(CommaExp)ex).e2;
return cast(inout)ex;
@@ -286,7 +287,7 @@ extern (C++) void expandTuples(Expressions* exps)
}
// Inline expand all the tuples
- while (arg.op == TOK.tuple)
+ while (arg.op == EXP.tuple)
{
TupleExp te = cast(TupleExp)arg;
exps.remove(i); // remove arg
@@ -356,7 +357,7 @@ int expandAliasThisTuples(Expressions* exps, size_t starti = 0)
printf("expansion ->\n");
foreach (e; exps)
{
- printf("\texps[%d] e = %s %s\n", i, Token.tochars[e.op], e.toChars());
+ printf("\texps[%d] e = %s %s\n", i, EXPtoString(e.op), e.toChars());
}
}
return cast(int)u;
@@ -528,15 +529,15 @@ extern (C++) struct UnionExp
extern (C++) Expression copy()
{
Expression e = exp();
- //if (e.size > sizeof(u)) printf("%s\n", Token::toChars(e.op));
+ //if (e.size > sizeof(u)) printf("%s\n", EXPtoString(e.op).ptr);
assert(e.size <= u.sizeof);
switch (e.op)
{
- case TOK.cantExpression: return CTFEExp.cantexp;
- case TOK.voidExpression: return CTFEExp.voidexp;
- case TOK.break_: return CTFEExp.breakexp;
- case TOK.continue_: return CTFEExp.continueexp;
- case TOK.goto_: return CTFEExp.gotoexp;
+ case EXP.cantExpression: return CTFEExp.cantexp;
+ case EXP.voidExpression: return CTFEExp.voidexp;
+ case EXP.break_: return CTFEExp.breakexp;
+ case EXP.continue_: return CTFEExp.continueexp;
+ case EXP.goto_: return CTFEExp.gotoexp;
default: return e.copy();
}
}
@@ -610,14 +611,14 @@ VarDeclaration expToVariable(Expression e)
{
switch (e.op)
{
- case TOK.variable:
+ case EXP.variable:
return (cast(VarExp)e).var.isVarDeclaration();
- case TOK.dotVariable:
+ case EXP.dotVariable:
e = (cast(DotVarExp)e).e1;
continue;
- case TOK.index:
+ case EXP.index:
{
IndexExp ei = cast(IndexExp)e;
e = ei.e1;
@@ -627,7 +628,7 @@ VarDeclaration expToVariable(Expression e)
return null;
}
- case TOK.slice:
+ case EXP.slice:
{
SliceExp ei = cast(SliceExp)e;
e = ei.e1;
@@ -637,8 +638,8 @@ VarDeclaration expToVariable(Expression e)
return null;
}
- case TOK.this_:
- case TOK.super_:
+ case EXP.this_:
+ case EXP.super_:
return (cast(ThisExp)e).var.isVarDeclaration();
default:
@@ -662,13 +663,13 @@ enum WANTexpand = 1; // expand const/immutable variables if possible
*/
extern (C++) abstract class Expression : ASTNode
{
- const TOK op; // to minimize use of dynamic_cast
+ const EXP op; // to minimize use of dynamic_cast
ubyte size; // # of bytes in Expression so we can copy() it
ubyte parens; // if this is a parenthesized expression
Type type; // !=null means that semantic() has been run
Loc loc; // file location
- extern (D) this(const ref Loc loc, TOK op, int size)
+ extern (D) this(const ref Loc loc, EXP op, int size)
{
//printf("Expression::Expression(op = %d) this = %p\n", op, this);
this.loc = loc;
@@ -678,12 +679,12 @@ extern (C++) abstract class Expression : ASTNode
static void _init()
{
- CTFEExp.cantexp = new CTFEExp(TOK.cantExpression);
- CTFEExp.voidexp = new CTFEExp(TOK.voidExpression);
- CTFEExp.breakexp = new CTFEExp(TOK.break_);
- CTFEExp.continueexp = new CTFEExp(TOK.continue_);
- CTFEExp.gotoexp = new CTFEExp(TOK.goto_);
- CTFEExp.showcontext = new CTFEExp(TOK.showCtfeContext);
+ CTFEExp.cantexp = new CTFEExp(EXP.cantExpression);
+ CTFEExp.voidexp = new CTFEExp(EXP.voidExpression);
+ CTFEExp.breakexp = new CTFEExp(EXP.break_);
+ CTFEExp.continueexp = new CTFEExp(EXP.continue_);
+ CTFEExp.gotoexp = new CTFEExp(EXP.goto_);
+ CTFEExp.showcontext = new CTFEExp(EXP.showCtfeContext);
}
/**
@@ -874,13 +875,13 @@ extern (C++) abstract class Expression : ASTNode
*/
extern (D) static Expression extractLast(Expression e, out Expression e0)
{
- if (e.op != TOK.comma)
+ if (e.op != EXP.comma)
{
return e;
}
CommaExp ce = cast(CommaExp)e;
- if (ce.e2.op != TOK.comma)
+ if (ce.e2.op != EXP.comma)
{
e0 = ce.e1;
return ce.e2;
@@ -890,11 +891,11 @@ extern (C++) abstract class Expression : ASTNode
e0 = e;
Expression* pce = &ce.e2;
- while ((cast(CommaExp)(*pce)).e2.op == TOK.comma)
+ while ((cast(CommaExp)(*pce)).e2.op == EXP.comma)
{
pce = &(cast(CommaExp)(*pce)).e2;
}
- assert((*pce).op == TOK.comma);
+ assert((*pce).op == EXP.comma);
ce = cast(CommaExp)(*pce);
*pce = ce.e1;
@@ -918,14 +919,14 @@ extern (C++) abstract class Expression : ASTNode
dinteger_t toInteger()
{
- //printf("Expression %s\n", Token::toChars(op));
+ //printf("Expression %s\n", EXPtoString(op).ptr);
error("integer constant expression expected instead of `%s`", toChars());
return 0;
}
uinteger_t toUInteger()
{
- //printf("Expression %s\n", Token::toChars(op));
+ //printf("Expression %s\n", EXPtoString(op).ptr);
return cast(uinteger_t)toInteger();
}
@@ -976,7 +977,7 @@ extern (C++) abstract class Expression : ASTNode
else if (!loc.isValid())
loc = e.loc;
- if (e.op == TOK.type)
+ if (e.op == EXP.type)
error("`%s` is a `%s` definition and cannot be modified", e.type.toChars(), e.type.kind());
else
error("`%s` is not an lvalue and cannot be modified", e.toChars());
@@ -1079,7 +1080,7 @@ extern (C++) abstract class Expression : ASTNode
extern (D) final bool checkScalar()
{
- if (op == TOK.error)
+ if (op == EXP.error)
return true;
if (type.toBasetype().ty == Terror)
return true;
@@ -1093,7 +1094,7 @@ extern (C++) abstract class Expression : ASTNode
extern (D) final bool checkNoBool()
{
- if (op == TOK.error)
+ if (op == EXP.error)
return true;
if (type.toBasetype().ty == Terror)
return true;
@@ -1107,7 +1108,7 @@ extern (C++) abstract class Expression : ASTNode
extern (D) final bool checkIntegral()
{
- if (op == TOK.error)
+ if (op == EXP.error)
return true;
if (type.toBasetype().ty == Terror)
return true;
@@ -1121,7 +1122,7 @@ extern (C++) abstract class Expression : ASTNode
extern (D) final bool checkArithmetic()
{
- if (op == TOK.error)
+ if (op == EXP.error)
return true;
if (type.toBasetype().ty == Terror)
return true;
@@ -1492,9 +1493,9 @@ extern (C++) abstract class Expression : ASTNode
extern (D) final bool checkRightThis(Scope* sc)
{
- if (op == TOK.error)
+ if (op == EXP.error)
return true;
- if (op == TOK.variable && type.ty != Terror)
+ if (op == EXP.variable && type.ty != Terror)
{
VarExp ve = cast(VarExp)this;
if (isNeedThisScope(sc, ve.var))
@@ -1513,7 +1514,7 @@ extern (C++) abstract class Expression : ASTNode
* ex is the RHS expression, or NULL if ++/-- is used (for diagnostics)
* Returns true if error occurs.
*/
- extern (D) final bool checkReadModifyWrite(TOK rmwOp, Expression ex = null)
+ extern (D) final bool checkReadModifyWrite(EXP rmwOp, Expression ex = null)
{
//printf("Expression::checkReadModifyWrite() %s %s", toChars(), ex ? ex.toChars() : "");
if (!type || !type.isShared() || type.isTypeStruct() || type.isTypeClass())
@@ -1522,13 +1523,13 @@ extern (C++) abstract class Expression : ASTNode
// atomicOp uses opAssign (+=/-=) rather than opOp (++/--) for the CT string literal.
switch (rmwOp)
{
- case TOK.plusPlus:
- case TOK.prePlusPlus:
- rmwOp = TOK.addAssign;
+ case EXP.plusPlus:
+ case EXP.prePlusPlus:
+ rmwOp = EXP.addAssign;
break;
- case TOK.minusMinus:
- case TOK.preMinusMinus:
- rmwOp = TOK.minAssign;
+ case EXP.minusMinus:
+ case EXP.preMinusMinus:
+ rmwOp = EXP.minAssign;
break;
default:
break;
@@ -1536,7 +1537,7 @@ extern (C++) abstract class Expression : ASTNode
error("read-modify-write operations are not allowed for `shared` variables");
errorSupplemental("Use `core.atomic.atomicOp!\"%s\"(%s, %s)` instead",
- Token.toChars(rmwOp), toChars(), ex ? ex.toChars() : "1");
+ EXPtoString(rmwOp).ptr, toChars(), ex ? ex.toChars() : "1");
return true;
}
@@ -1558,7 +1559,7 @@ extern (C++) abstract class Expression : ASTNode
//printf("Expression::addressOf()\n");
debug
{
- assert(op == TOK.error || isLvalue());
+ assert(op == EXP.error || isLvalue());
}
Expression e = new AddrExp(loc, this, type.pointerTo());
return e;
@@ -1597,12 +1598,11 @@ extern (C++) abstract class Expression : ASTNode
return .isConst(this);
}
- /********************************
- * Does this expression statically evaluate to a boolean 'result' (true or false)?
- */
- bool isBool(bool result)
+ /// Statically evaluate this expression to a `bool` if possible
+ /// Returns: an optional thath either contains the value or is empty
+ Optional!bool toBool()
{
- return false;
+ return typeof(return)();
}
bool hasCode()
@@ -1612,127 +1612,127 @@ extern (C++) abstract class Expression : ASTNode
final pure inout nothrow @nogc @safe
{
- inout(IntegerExp) isIntegerExp() { return op == TOK.int64 ? cast(typeof(return))this : null; }
- inout(ErrorExp) isErrorExp() { return op == TOK.error ? cast(typeof(return))this : null; }
- inout(VoidInitExp) isVoidInitExp() { return op == TOK.void_ ? cast(typeof(return))this : null; }
- inout(RealExp) isRealExp() { return op == TOK.float64 ? cast(typeof(return))this : null; }
- inout(ComplexExp) isComplexExp() { return op == TOK.complex80 ? cast(typeof(return))this : null; }
- inout(IdentifierExp) isIdentifierExp() { return op == TOK.identifier ? cast(typeof(return))this : null; }
- inout(DollarExp) isDollarExp() { return op == TOK.dollar ? cast(typeof(return))this : null; }
- inout(DsymbolExp) isDsymbolExp() { return op == TOK.dSymbol ? cast(typeof(return))this : null; }
- inout(ThisExp) isThisExp() { return op == TOK.this_ ? cast(typeof(return))this : null; }
- inout(SuperExp) isSuperExp() { return op == TOK.super_ ? cast(typeof(return))this : null; }
- inout(NullExp) isNullExp() { return op == TOK.null_ ? cast(typeof(return))this : null; }
- inout(StringExp) isStringExp() { return op == TOK.string_ ? cast(typeof(return))this : null; }
- inout(TupleExp) isTupleExp() { return op == TOK.tuple ? cast(typeof(return))this : null; }
- inout(ArrayLiteralExp) isArrayLiteralExp() { return op == TOK.arrayLiteral ? cast(typeof(return))this : null; }
- inout(AssocArrayLiteralExp) isAssocArrayLiteralExp() { return op == TOK.assocArrayLiteral ? cast(typeof(return))this : null; }
- inout(StructLiteralExp) isStructLiteralExp() { return op == TOK.structLiteral ? cast(typeof(return))this : null; }
- inout(CompoundLiteralExp) isCompoundLiteralExp() { return op == TOK.compoundLiteral ? cast(typeof(return))this : null; }
- inout(TypeExp) isTypeExp() { return op == TOK.type ? cast(typeof(return))this : null; }
- inout(ScopeExp) isScopeExp() { return op == TOK.scope_ ? cast(typeof(return))this : null; }
- inout(TemplateExp) isTemplateExp() { return op == TOK.template_ ? cast(typeof(return))this : null; }
- inout(NewExp) isNewExp() { return op == TOK.new_ ? cast(typeof(return))this : null; }
- inout(NewAnonClassExp) isNewAnonClassExp() { return op == TOK.newAnonymousClass ? cast(typeof(return))this : null; }
- inout(SymOffExp) isSymOffExp() { return op == TOK.symbolOffset ? cast(typeof(return))this : null; }
- inout(VarExp) isVarExp() { return op == TOK.variable ? cast(typeof(return))this : null; }
- inout(OverExp) isOverExp() { return op == TOK.overloadSet ? cast(typeof(return))this : null; }
- inout(FuncExp) isFuncExp() { return op == TOK.function_ ? cast(typeof(return))this : null; }
- inout(DeclarationExp) isDeclarationExp() { return op == TOK.declaration ? cast(typeof(return))this : null; }
- inout(TypeidExp) isTypeidExp() { return op == TOK.typeid_ ? cast(typeof(return))this : null; }
- inout(TraitsExp) isTraitsExp() { return op == TOK.traits ? cast(typeof(return))this : null; }
- inout(HaltExp) isHaltExp() { return op == TOK.halt ? cast(typeof(return))this : null; }
- inout(IsExp) isExp() { return op == TOK.is_ ? cast(typeof(return))this : null; }
- inout(MixinExp) isMixinExp() { return op == TOK.mixin_ ? cast(typeof(return))this : null; }
- inout(ImportExp) isImportExp() { return op == TOK.import_ ? cast(typeof(return))this : null; }
- inout(AssertExp) isAssertExp() { return op == TOK.assert_ ? cast(typeof(return))this : null; }
- inout(DotIdExp) isDotIdExp() { return op == TOK.dotIdentifier ? cast(typeof(return))this : null; }
- inout(DotTemplateExp) isDotTemplateExp() { return op == TOK.dotTemplateDeclaration ? cast(typeof(return))this : null; }
- inout(DotVarExp) isDotVarExp() { return op == TOK.dotVariable ? cast(typeof(return))this : null; }
- inout(DotTemplateInstanceExp) isDotTemplateInstanceExp() { return op == TOK.dotTemplateInstance ? cast(typeof(return))this : null; }
- inout(DelegateExp) isDelegateExp() { return op == TOK.delegate_ ? cast(typeof(return))this : null; }
- inout(DotTypeExp) isDotTypeExp() { return op == TOK.dotType ? cast(typeof(return))this : null; }
- inout(CallExp) isCallExp() { return op == TOK.call ? cast(typeof(return))this : null; }
- inout(AddrExp) isAddrExp() { return op == TOK.address ? cast(typeof(return))this : null; }
- inout(PtrExp) isPtrExp() { return op == TOK.star ? cast(typeof(return))this : null; }
- inout(NegExp) isNegExp() { return op == TOK.negate ? cast(typeof(return))this : null; }
- inout(UAddExp) isUAddExp() { return op == TOK.uadd ? cast(typeof(return))this : null; }
- inout(ComExp) isComExp() { return op == TOK.tilde ? cast(typeof(return))this : null; }
- inout(NotExp) isNotExp() { return op == TOK.not ? cast(typeof(return))this : null; }
- inout(DeleteExp) isDeleteExp() { return op == TOK.delete_ ? cast(typeof(return))this : null; }
- inout(CastExp) isCastExp() { return op == TOK.cast_ ? cast(typeof(return))this : null; }
- inout(VectorExp) isVectorExp() { return op == TOK.vector ? cast(typeof(return))this : null; }
- inout(VectorArrayExp) isVectorArrayExp() { return op == TOK.vectorArray ? cast(typeof(return))this : null; }
- inout(SliceExp) isSliceExp() { return op == TOK.slice ? cast(typeof(return))this : null; }
- inout(ArrayLengthExp) isArrayLengthExp() { return op == TOK.arrayLength ? cast(typeof(return))this : null; }
- inout(ArrayExp) isArrayExp() { return op == TOK.array ? cast(typeof(return))this : null; }
- inout(DotExp) isDotExp() { return op == TOK.dot ? cast(typeof(return))this : null; }
- inout(CommaExp) isCommaExp() { return op == TOK.comma ? cast(typeof(return))this : null; }
- inout(IntervalExp) isIntervalExp() { return op == TOK.interval ? cast(typeof(return))this : null; }
- inout(DelegatePtrExp) isDelegatePtrExp() { return op == TOK.delegatePointer ? cast(typeof(return))this : null; }
- inout(DelegateFuncptrExp) isDelegateFuncptrExp() { return op == TOK.delegateFunctionPointer ? cast(typeof(return))this : null; }
- inout(IndexExp) isIndexExp() { return op == TOK.index ? cast(typeof(return))this : null; }
- inout(PostExp) isPostExp() { return (op == TOK.plusPlus || op == TOK.minusMinus) ? cast(typeof(return))this : null; }
- inout(PreExp) isPreExp() { return (op == TOK.prePlusPlus || op == TOK.preMinusMinus) ? cast(typeof(return))this : null; }
- inout(AssignExp) isAssignExp() { return op == TOK.assign ? cast(typeof(return))this : null; }
- inout(ConstructExp) isConstructExp() { return op == TOK.construct ? cast(typeof(return))this : null; }
- inout(BlitExp) isBlitExp() { return op == TOK.blit ? cast(typeof(return))this : null; }
- inout(AddAssignExp) isAddAssignExp() { return op == TOK.addAssign ? cast(typeof(return))this : null; }
- inout(MinAssignExp) isMinAssignExp() { return op == TOK.minAssign ? cast(typeof(return))this : null; }
- inout(MulAssignExp) isMulAssignExp() { return op == TOK.mulAssign ? cast(typeof(return))this : null; }
-
- inout(DivAssignExp) isDivAssignExp() { return op == TOK.divAssign ? cast(typeof(return))this : null; }
- inout(ModAssignExp) isModAssignExp() { return op == TOK.modAssign ? cast(typeof(return))this : null; }
- inout(AndAssignExp) isAndAssignExp() { return op == TOK.andAssign ? cast(typeof(return))this : null; }
- inout(OrAssignExp) isOrAssignExp() { return op == TOK.orAssign ? cast(typeof(return))this : null; }
- inout(XorAssignExp) isXorAssignExp() { return op == TOK.xorAssign ? cast(typeof(return))this : null; }
- inout(PowAssignExp) isPowAssignExp() { return op == TOK.powAssign ? cast(typeof(return))this : null; }
-
- inout(ShlAssignExp) isShlAssignExp() { return op == TOK.leftShiftAssign ? cast(typeof(return))this : null; }
- inout(ShrAssignExp) isShrAssignExp() { return op == TOK.rightShiftAssign ? cast(typeof(return))this : null; }
- inout(UshrAssignExp) isUshrAssignExp() { return op == TOK.unsignedRightShiftAssign ? cast(typeof(return))this : null; }
-
- inout(CatAssignExp) isCatAssignExp() { return op == TOK.concatenateAssign
+ inout(IntegerExp) isIntegerExp() { return op == EXP.int64 ? cast(typeof(return))this : null; }
+ inout(ErrorExp) isErrorExp() { return op == EXP.error ? cast(typeof(return))this : null; }
+ inout(VoidInitExp) isVoidInitExp() { return op == EXP.void_ ? cast(typeof(return))this : null; }
+ inout(RealExp) isRealExp() { return op == EXP.float64 ? cast(typeof(return))this : null; }
+ inout(ComplexExp) isComplexExp() { return op == EXP.complex80 ? cast(typeof(return))this : null; }
+ inout(IdentifierExp) isIdentifierExp() { return op == EXP.identifier ? cast(typeof(return))this : null; }
+ inout(DollarExp) isDollarExp() { return op == EXP.dollar ? cast(typeof(return))this : null; }
+ inout(DsymbolExp) isDsymbolExp() { return op == EXP.dSymbol ? cast(typeof(return))this : null; }
+ inout(ThisExp) isThisExp() { return op == EXP.this_ ? cast(typeof(return))this : null; }
+ inout(SuperExp) isSuperExp() { return op == EXP.super_ ? cast(typeof(return))this : null; }
+ inout(NullExp) isNullExp() { return op == EXP.null_ ? cast(typeof(return))this : null; }
+ inout(StringExp) isStringExp() { return op == EXP.string_ ? cast(typeof(return))this : null; }
+ inout(TupleExp) isTupleExp() { return op == EXP.tuple ? cast(typeof(return))this : null; }
+ inout(ArrayLiteralExp) isArrayLiteralExp() { return op == EXP.arrayLiteral ? cast(typeof(return))this : null; }
+ inout(AssocArrayLiteralExp) isAssocArrayLiteralExp() { return op == EXP.assocArrayLiteral ? cast(typeof(return))this : null; }
+ inout(StructLiteralExp) isStructLiteralExp() { return op == EXP.structLiteral ? cast(typeof(return))this : null; }
+ inout(CompoundLiteralExp) isCompoundLiteralExp() { return op == EXP.compoundLiteral ? cast(typeof(return))this : null; }
+ inout(TypeExp) isTypeExp() { return op == EXP.type ? cast(typeof(return))this : null; }
+ inout(ScopeExp) isScopeExp() { return op == EXP.scope_ ? cast(typeof(return))this : null; }
+ inout(TemplateExp) isTemplateExp() { return op == EXP.template_ ? cast(typeof(return))this : null; }
+ inout(NewExp) isNewExp() { return op == EXP.new_ ? cast(typeof(return))this : null; }
+ inout(NewAnonClassExp) isNewAnonClassExp() { return op == EXP.newAnonymousClass ? cast(typeof(return))this : null; }
+ inout(SymOffExp) isSymOffExp() { return op == EXP.symbolOffset ? cast(typeof(return))this : null; }
+ inout(VarExp) isVarExp() { return op == EXP.variable ? cast(typeof(return))this : null; }
+ inout(OverExp) isOverExp() { return op == EXP.overloadSet ? cast(typeof(return))this : null; }
+ inout(FuncExp) isFuncExp() { return op == EXP.function_ ? cast(typeof(return))this : null; }
+ inout(DeclarationExp) isDeclarationExp() { return op == EXP.declaration ? cast(typeof(return))this : null; }
+ inout(TypeidExp) isTypeidExp() { return op == EXP.typeid_ ? cast(typeof(return))this : null; }
+ inout(TraitsExp) isTraitsExp() { return op == EXP.traits ? cast(typeof(return))this : null; }
+ inout(HaltExp) isHaltExp() { return op == EXP.halt ? cast(typeof(return))this : null; }
+ inout(IsExp) isExp() { return op == EXP.is_ ? cast(typeof(return))this : null; }
+ inout(MixinExp) isMixinExp() { return op == EXP.mixin_ ? cast(typeof(return))this : null; }
+ inout(ImportExp) isImportExp() { return op == EXP.import_ ? cast(typeof(return))this : null; }
+ inout(AssertExp) isAssertExp() { return op == EXP.assert_ ? cast(typeof(return))this : null; }
+ inout(DotIdExp) isDotIdExp() { return op == EXP.dotIdentifier ? cast(typeof(return))this : null; }
+ inout(DotTemplateExp) isDotTemplateExp() { return op == EXP.dotTemplateDeclaration ? cast(typeof(return))this : null; }
+ inout(DotVarExp) isDotVarExp() { return op == EXP.dotVariable ? cast(typeof(return))this : null; }
+ inout(DotTemplateInstanceExp) isDotTemplateInstanceExp() { return op == EXP.dotTemplateInstance ? cast(typeof(return))this : null; }
+ inout(DelegateExp) isDelegateExp() { return op == EXP.delegate_ ? cast(typeof(return))this : null; }
+ inout(DotTypeExp) isDotTypeExp() { return op == EXP.dotType ? cast(typeof(return))this : null; }
+ inout(CallExp) isCallExp() { return op == EXP.call ? cast(typeof(return))this : null; }
+ inout(AddrExp) isAddrExp() { return op == EXP.address ? cast(typeof(return))this : null; }
+ inout(PtrExp) isPtrExp() { return op == EXP.star ? cast(typeof(return))this : null; }
+ inout(NegExp) isNegExp() { return op == EXP.negate ? cast(typeof(return))this : null; }
+ inout(UAddExp) isUAddExp() { return op == EXP.uadd ? cast(typeof(return))this : null; }
+ inout(ComExp) isComExp() { return op == EXP.tilde ? cast(typeof(return))this : null; }
+ inout(NotExp) isNotExp() { return op == EXP.not ? cast(typeof(return))this : null; }
+ inout(DeleteExp) isDeleteExp() { return op == EXP.delete_ ? cast(typeof(return))this : null; }
+ inout(CastExp) isCastExp() { return op == EXP.cast_ ? cast(typeof(return))this : null; }
+ inout(VectorExp) isVectorExp() { return op == EXP.vector ? cast(typeof(return))this : null; }
+ inout(VectorArrayExp) isVectorArrayExp() { return op == EXP.vectorArray ? cast(typeof(return))this : null; }
+ inout(SliceExp) isSliceExp() { return op == EXP.slice ? cast(typeof(return))this : null; }
+ inout(ArrayLengthExp) isArrayLengthExp() { return op == EXP.arrayLength ? cast(typeof(return))this : null; }
+ inout(ArrayExp) isArrayExp() { return op == EXP.array ? cast(typeof(return))this : null; }
+ inout(DotExp) isDotExp() { return op == EXP.dot ? cast(typeof(return))this : null; }
+ inout(CommaExp) isCommaExp() { return op == EXP.comma ? cast(typeof(return))this : null; }
+ inout(IntervalExp) isIntervalExp() { return op == EXP.interval ? cast(typeof(return))this : null; }
+ inout(DelegatePtrExp) isDelegatePtrExp() { return op == EXP.delegatePointer ? cast(typeof(return))this : null; }
+ inout(DelegateFuncptrExp) isDelegateFuncptrExp() { return op == EXP.delegateFunctionPointer ? cast(typeof(return))this : null; }
+ inout(IndexExp) isIndexExp() { return op == EXP.index ? cast(typeof(return))this : null; }
+ inout(PostExp) isPostExp() { return (op == EXP.plusPlus || op == EXP.minusMinus) ? cast(typeof(return))this : null; }
+ inout(PreExp) isPreExp() { return (op == EXP.prePlusPlus || op == EXP.preMinusMinus) ? cast(typeof(return))this : null; }
+ inout(AssignExp) isAssignExp() { return op == EXP.assign ? cast(typeof(return))this : null; }
+ inout(ConstructExp) isConstructExp() { return op == EXP.construct ? cast(typeof(return))this : null; }
+ inout(BlitExp) isBlitExp() { return op == EXP.blit ? cast(typeof(return))this : null; }
+ inout(AddAssignExp) isAddAssignExp() { return op == EXP.addAssign ? cast(typeof(return))this : null; }
+ inout(MinAssignExp) isMinAssignExp() { return op == EXP.minAssign ? cast(typeof(return))this : null; }
+ inout(MulAssignExp) isMulAssignExp() { return op == EXP.mulAssign ? cast(typeof(return))this : null; }
+
+ inout(DivAssignExp) isDivAssignExp() { return op == EXP.divAssign ? cast(typeof(return))this : null; }
+ inout(ModAssignExp) isModAssignExp() { return op == EXP.modAssign ? cast(typeof(return))this : null; }
+ inout(AndAssignExp) isAndAssignExp() { return op == EXP.andAssign ? cast(typeof(return))this : null; }
+ inout(OrAssignExp) isOrAssignExp() { return op == EXP.orAssign ? cast(typeof(return))this : null; }
+ inout(XorAssignExp) isXorAssignExp() { return op == EXP.xorAssign ? cast(typeof(return))this : null; }
+ inout(PowAssignExp) isPowAssignExp() { return op == EXP.powAssign ? cast(typeof(return))this : null; }
+
+ inout(ShlAssignExp) isShlAssignExp() { return op == EXP.leftShiftAssign ? cast(typeof(return))this : null; }
+ inout(ShrAssignExp) isShrAssignExp() { return op == EXP.rightShiftAssign ? cast(typeof(return))this : null; }
+ inout(UshrAssignExp) isUshrAssignExp() { return op == EXP.unsignedRightShiftAssign ? cast(typeof(return))this : null; }
+
+ inout(CatAssignExp) isCatAssignExp() { return op == EXP.concatenateAssign
? cast(typeof(return))this
: null; }
- inout(CatElemAssignExp) isCatElemAssignExp() { return op == TOK.concatenateElemAssign
+ inout(CatElemAssignExp) isCatElemAssignExp() { return op == EXP.concatenateElemAssign
? cast(typeof(return))this
: null; }
- inout(CatDcharAssignExp) isCatDcharAssignExp() { return op == TOK.concatenateDcharAssign
+ inout(CatDcharAssignExp) isCatDcharAssignExp() { return op == EXP.concatenateDcharAssign
? cast(typeof(return))this
: null; }
- inout(AddExp) isAddExp() { return op == TOK.add ? cast(typeof(return))this : null; }
- inout(MinExp) isMinExp() { return op == TOK.min ? cast(typeof(return))this : null; }
- inout(CatExp) isCatExp() { return op == TOK.concatenate ? cast(typeof(return))this : null; }
- inout(MulExp) isMulExp() { return op == TOK.mul ? cast(typeof(return))this : null; }
- inout(DivExp) isDivExp() { return op == TOK.div ? cast(typeof(return))this : null; }
- inout(ModExp) isModExp() { return op == TOK.mod ? cast(typeof(return))this : null; }
- inout(PowExp) isPowExp() { return op == TOK.pow ? cast(typeof(return))this : null; }
- inout(ShlExp) isShlExp() { return op == TOK.leftShift ? cast(typeof(return))this : null; }
- inout(ShrExp) isShrExp() { return op == TOK.rightShift ? cast(typeof(return))this : null; }
- inout(UshrExp) isUshrExp() { return op == TOK.unsignedRightShift ? cast(typeof(return))this : null; }
- inout(AndExp) isAndExp() { return op == TOK.and ? cast(typeof(return))this : null; }
- inout(OrExp) isOrExp() { return op == TOK.or ? cast(typeof(return))this : null; }
- inout(XorExp) isXorExp() { return op == TOK.xor ? cast(typeof(return))this : null; }
- inout(LogicalExp) isLogicalExp() { return (op == TOK.andAnd || op == TOK.orOr) ? cast(typeof(return))this : null; }
- //inout(CmpExp) isCmpExp() { return op == TOK. ? cast(typeof(return))this : null; }
- inout(InExp) isInExp() { return op == TOK.in_ ? cast(typeof(return))this : null; }
- inout(RemoveExp) isRemoveExp() { return op == TOK.remove ? cast(typeof(return))this : null; }
- inout(EqualExp) isEqualExp() { return (op == TOK.equal || op == TOK.notEqual) ? cast(typeof(return))this : null; }
- inout(IdentityExp) isIdentityExp() { return (op == TOK.identity || op == TOK.notIdentity) ? cast(typeof(return))this : null; }
- inout(CondExp) isCondExp() { return op == TOK.question ? cast(typeof(return))this : null; }
- inout(GenericExp) isGenericExp() { return op == TOK._Generic ? cast(typeof(return))this : null; }
+ inout(AddExp) isAddExp() { return op == EXP.add ? cast(typeof(return))this : null; }
+ inout(MinExp) isMinExp() { return op == EXP.min ? cast(typeof(return))this : null; }
+ inout(CatExp) isCatExp() { return op == EXP.concatenate ? cast(typeof(return))this : null; }
+ inout(MulExp) isMulExp() { return op == EXP.mul ? cast(typeof(return))this : null; }
+ inout(DivExp) isDivExp() { return op == EXP.div ? cast(typeof(return))this : null; }
+ inout(ModExp) isModExp() { return op == EXP.mod ? cast(typeof(return))this : null; }
+ inout(PowExp) isPowExp() { return op == EXP.pow ? cast(typeof(return))this : null; }
+ inout(ShlExp) isShlExp() { return op == EXP.leftShift ? cast(typeof(return))this : null; }
+ inout(ShrExp) isShrExp() { return op == EXP.rightShift ? cast(typeof(return))this : null; }
+ inout(UshrExp) isUshrExp() { return op == EXP.unsignedRightShift ? cast(typeof(return))this : null; }
+ inout(AndExp) isAndExp() { return op == EXP.and ? cast(typeof(return))this : null; }
+ inout(OrExp) isOrExp() { return op == EXP.or ? cast(typeof(return))this : null; }
+ inout(XorExp) isXorExp() { return op == EXP.xor ? cast(typeof(return))this : null; }
+ inout(LogicalExp) isLogicalExp() { return (op == EXP.andAnd || op == EXP.orOr) ? cast(typeof(return))this : null; }
+ //inout(CmpExp) isCmpExp() { return op == EXP. ? cast(typeof(return))this : null; }
+ inout(InExp) isInExp() { return op == EXP.in_ ? cast(typeof(return))this : null; }
+ inout(RemoveExp) isRemoveExp() { return op == EXP.remove ? cast(typeof(return))this : null; }
+ inout(EqualExp) isEqualExp() { return (op == EXP.equal || op == EXP.notEqual) ? cast(typeof(return))this : null; }
+ inout(IdentityExp) isIdentityExp() { return (op == EXP.identity || op == EXP.notIdentity) ? cast(typeof(return))this : null; }
+ inout(CondExp) isCondExp() { return op == EXP.question ? cast(typeof(return))this : null; }
+ inout(GenericExp) isGenericExp() { return op == EXP._Generic ? cast(typeof(return))this : null; }
inout(DefaultInitExp) isDefaultInitExp() { return isDefaultInitOp(op) ? cast(typeof(return))this: null; }
- inout(FileInitExp) isFileInitExp() { return (op == TOK.file || op == TOK.fileFullPath) ? cast(typeof(return))this : null; }
- inout(LineInitExp) isLineInitExp() { return op == TOK.line ? cast(typeof(return))this : null; }
- inout(ModuleInitExp) isModuleInitExp() { return op == TOK.moduleString ? cast(typeof(return))this : null; }
- inout(FuncInitExp) isFuncInitExp() { return op == TOK.functionString ? cast(typeof(return))this : null; }
- inout(PrettyFuncInitExp) isPrettyFuncInitExp() { return op == TOK.prettyFunction ? cast(typeof(return))this : null; }
- inout(ClassReferenceExp) isClassReferenceExp() { return op == TOK.classReference ? cast(typeof(return))this : null; }
- inout(ThrownExceptionExp) isThrownExceptionExp() { return op == TOK.thrownException ? cast(typeof(return))this : null; }
+ inout(FileInitExp) isFileInitExp() { return (op == EXP.file || op == EXP.fileFullPath) ? cast(typeof(return))this : null; }
+ inout(LineInitExp) isLineInitExp() { return op == EXP.line ? cast(typeof(return))this : null; }
+ inout(ModuleInitExp) isModuleInitExp() { return op == EXP.moduleString ? cast(typeof(return))this : null; }
+ inout(FuncInitExp) isFuncInitExp() { return op == EXP.functionString ? cast(typeof(return))this : null; }
+ 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
@@ -1754,7 +1754,7 @@ extern (C++) final class IntegerExp : Expression
extern (D) this(const ref Loc loc, dinteger_t value, Type type)
{
- super(loc, TOK.int64, __traits(classInstanceSize, IntegerExp));
+ super(loc, EXP.int64, __traits(classInstanceSize, IntegerExp));
//printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type.toChars() : "");
assert(type);
if (!type.isscalar())
@@ -1770,7 +1770,7 @@ extern (C++) final class IntegerExp : Expression
extern (D) this(dinteger_t value)
{
- super(Loc.initial, TOK.int64, __traits(classInstanceSize, IntegerExp));
+ super(Loc.initial, EXP.int64, __traits(classInstanceSize, IntegerExp));
this.type = Type.tint32;
this.value = cast(d_int32)value;
}
@@ -1827,10 +1827,10 @@ extern (C++) final class IntegerExp : Expression
return complex_t(toReal());
}
- override bool isBool(bool result)
+ override Optional!bool toBool()
{
bool r = toInteger() != 0;
- return result ? r : !r;
+ return typeof(return)(r);
}
override Expression toLvalue(Scope* sc, Expression e)
@@ -1969,7 +1969,7 @@ extern (C++) final class ErrorExp : Expression
{
private extern (D) this()
{
- super(Loc.initial, TOK.error, __traits(classInstanceSize, ErrorExp));
+ super(Loc.initial, EXP.error, __traits(classInstanceSize, ErrorExp));
type = Type.terror;
}
@@ -2015,7 +2015,7 @@ extern (C++) final class VoidInitExp : Expression
extern (D) this(VarDeclaration var)
{
- super(var.loc, TOK.void_, __traits(classInstanceSize, VoidInitExp));
+ super(var.loc, EXP.void_, __traits(classInstanceSize, VoidInitExp));
this.var = var;
this.type = var.type;
}
@@ -2040,7 +2040,7 @@ extern (C++) final class RealExp : Expression
extern (D) this(const ref Loc loc, real_t value, Type type)
{
- super(loc, TOK.float64, __traits(classInstanceSize, RealExp));
+ super(loc, EXP.float64, __traits(classInstanceSize, RealExp));
//printf("RealExp::RealExp(%Lg)\n", value);
this.value = value;
this.type = type;
@@ -2096,9 +2096,9 @@ extern (C++) final class RealExp : Expression
return complex_t(toReal(), toImaginary());
}
- override bool isBool(bool result)
+ override Optional!bool toBool()
{
- return result ? cast(bool)value : !cast(bool)value;
+ return typeof(return)(!!value);
}
override void accept(Visitor v)
@@ -2115,7 +2115,7 @@ extern (C++) final class ComplexExp : Expression
extern (D) this(const ref Loc loc, complex_t value, Type type)
{
- super(loc, TOK.complex80, __traits(classInstanceSize, ComplexExp));
+ super(loc, EXP.complex80, __traits(classInstanceSize, ComplexExp));
this.value = value;
this.type = type;
//printf("ComplexExp::ComplexExp(%s)\n", toChars());
@@ -2171,12 +2171,9 @@ extern (C++) final class ComplexExp : Expression
return value;
}
- override bool isBool(bool result)
+ override Optional!bool toBool()
{
- if (result)
- return cast(bool)value;
- else
- return !value;
+ return typeof(return)(!!value);
}
override void accept(Visitor v)
@@ -2193,7 +2190,7 @@ extern (C++) class IdentifierExp : Expression
extern (D) this(const ref Loc loc, Identifier ident)
{
- super(loc, TOK.identifier, __traits(classInstanceSize, IdentifierExp));
+ super(loc, EXP.identifier, __traits(classInstanceSize, IdentifierExp));
this.ident = ident;
}
@@ -2243,7 +2240,7 @@ extern (C++) final class DsymbolExp : Expression
extern (D) this(const ref Loc loc, Dsymbol s, bool hasOverloads = true)
{
- super(loc, TOK.dSymbol, __traits(classInstanceSize, DsymbolExp));
+ super(loc, EXP.dSymbol, __traits(classInstanceSize, DsymbolExp));
this.s = s;
this.hasOverloads = hasOverloads;
}
@@ -2273,11 +2270,11 @@ extern (C++) class ThisExp : Expression
extern (D) this(const ref Loc loc)
{
- super(loc, TOK.this_, __traits(classInstanceSize, ThisExp));
+ super(loc, EXP.this_, __traits(classInstanceSize, ThisExp));
//printf("ThisExp::ThisExp() loc = %d\n", loc.linnum);
}
- this(const ref Loc loc, const TOK tok)
+ this(const ref Loc loc, const EXP tok)
{
super(loc, tok, __traits(classInstanceSize, ThisExp));
//printf("ThisExp::ThisExp() loc = %d\n", loc.linnum);
@@ -2292,9 +2289,10 @@ extern (C++) class ThisExp : Expression
return r;
}
- override final bool isBool(bool result)
+ override Optional!bool toBool()
{
- return result;
+ // `this` is never null (what about structs?)
+ return typeof(return)(true);
}
override final bool isLvalue()
@@ -2326,7 +2324,7 @@ extern (C++) final class SuperExp : ThisExp
{
extern (D) this(const ref Loc loc)
{
- super(loc, TOK.super_);
+ super(loc, EXP.super_);
}
override void accept(Visitor v)
@@ -2342,7 +2340,7 @@ extern (C++) final class NullExp : Expression
{
extern (D) this(const ref Loc loc, Type type = null)
{
- super(loc, TOK.null_, __traits(classInstanceSize, NullExp));
+ super(loc, EXP.null_, __traits(classInstanceSize, NullExp));
this.type = type;
}
@@ -2350,7 +2348,7 @@ extern (C++) final class NullExp : Expression
{
if (auto e = o.isExpression())
{
- if (e.op == TOK.null_ && type.equals(e.type))
+ if (e.op == EXP.null_ && type.equals(e.type))
{
return true;
}
@@ -2358,9 +2356,10 @@ extern (C++) final class NullExp : Expression
return false;
}
- override bool isBool(bool result)
+ override Optional!bool toBool()
{
- return result ? false : true;
+ // null in any type is false
+ return typeof(return)(false);
}
override StringExp toStringExp()
@@ -2400,7 +2399,7 @@ extern (C++) final class StringExp : Expression
extern (D) this(const ref Loc loc, const(void)[] string)
{
- super(loc, TOK.string_, __traits(classInstanceSize, StringExp));
+ super(loc, EXP.string_, __traits(classInstanceSize, StringExp));
this.string = cast(char*)string.ptr; // note that this.string should be const
this.len = string.length;
this.sz = 1; // work around LDC bug #1286
@@ -2408,7 +2407,7 @@ extern (C++) final class StringExp : Expression
extern (D) this(const ref Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix = NoPostfix)
{
- super(loc, TOK.string_, __traits(classInstanceSize, StringExp));
+ super(loc, EXP.string_, __traits(classInstanceSize, StringExp));
this.string = cast(char*)string.ptr; // note that this.string should be const
this.len = len;
this.sz = sz;
@@ -2681,9 +2680,11 @@ extern (C++) final class StringExp : Expression
return cast(int)(len1 - len2);
}
- override bool isBool(bool result)
+ override Optional!bool toBool()
{
- return result;
+ // Keep the old behaviour for this refactoring
+ // Should probably match language spec instead and check for length
+ return typeof(return)(true);
}
override bool isLvalue()
@@ -2810,7 +2811,7 @@ extern (C++) final class TupleExp : Expression
extern (D) this(const ref Loc loc, Expression e0, Expressions* exps)
{
- super(loc, TOK.tuple, __traits(classInstanceSize, TupleExp));
+ super(loc, EXP.tuple, __traits(classInstanceSize, TupleExp));
//printf("TupleExp(this = %p)\n", this);
this.e0 = e0;
this.exps = exps;
@@ -2818,14 +2819,14 @@ extern (C++) final class TupleExp : Expression
extern (D) this(const ref Loc loc, Expressions* exps)
{
- super(loc, TOK.tuple, __traits(classInstanceSize, TupleExp));
+ super(loc, EXP.tuple, __traits(classInstanceSize, TupleExp));
//printf("TupleExp(this = %p)\n", this);
this.exps = exps;
}
extern (D) this(const ref Loc loc, TupleDeclaration tup)
{
- super(loc, TOK.tuple, __traits(classInstanceSize, TupleExp));
+ super(loc, EXP.tuple, __traits(classInstanceSize, TupleExp));
this.exps = new Expressions();
this.exps.reserve(tup.objects.dim);
@@ -2919,14 +2920,14 @@ extern (C++) final class ArrayLiteralExp : Expression
extern (D) this(const ref Loc loc, Type type, Expressions* elements)
{
- super(loc, TOK.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
+ super(loc, EXP.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
this.type = type;
this.elements = elements;
}
extern (D) this(const ref Loc loc, Type type, Expression e)
{
- super(loc, TOK.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
+ super(loc, EXP.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
this.type = type;
elements = new Expressions();
elements.push(e);
@@ -2934,7 +2935,7 @@ extern (C++) final class ArrayLiteralExp : Expression
extern (D) this(const ref Loc loc, Type type, Expression basis, Expressions* elements)
{
- super(loc, TOK.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
+ super(loc, EXP.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
this.type = type;
this.basis = basis;
this.elements = elements;
@@ -3000,10 +3001,10 @@ extern (C++) final class ArrayLiteralExp : Expression
return el ? el : basis;
}
- override bool isBool(bool result)
+ override Optional!bool toBool()
{
size_t dim = elements ? elements.dim : 0;
- return result ? (dim != 0) : (dim == 0);
+ return typeof(return)(dim != 0);
}
override StringExp toStringExp()
@@ -3023,7 +3024,7 @@ extern (C++) final class ArrayLiteralExp : Expression
foreach (i; 0 .. elements.dim)
{
auto ch = this[i];
- if (ch.op != TOK.int64)
+ if (ch.op != EXP.int64)
return null;
if (sz == 1)
buf.writeByte(cast(uint)ch.toInteger());
@@ -3079,7 +3080,7 @@ extern (C++) final class AssocArrayLiteralExp : Expression
extern (D) this(const ref Loc loc, Expressions* keys, Expressions* values)
{
- super(loc, TOK.assocArrayLiteral, __traits(classInstanceSize, AssocArrayLiteralExp));
+ super(loc, EXP.assocArrayLiteral, __traits(classInstanceSize, AssocArrayLiteralExp));
assert(keys.dim == values.dim);
this.keys = keys;
this.values = values;
@@ -3119,10 +3120,10 @@ extern (C++) final class AssocArrayLiteralExp : Expression
return new AssocArrayLiteralExp(loc, arraySyntaxCopy(keys), arraySyntaxCopy(values));
}
- override bool isBool(bool result)
+ override Optional!bool toBool()
{
size_t dim = keys.dim;
- return result ? (dim != 0) : (dim == 0);
+ return typeof(return)(dim != 0);
}
override void accept(Visitor v)
@@ -3172,7 +3173,7 @@ extern (C++) final class StructLiteralExp : Expression
extern (D) this(const ref Loc loc, StructDeclaration sd, Expressions* elements, Type stype = null)
{
- super(loc, TOK.structLiteral, __traits(classInstanceSize, StructLiteralExp));
+ super(loc, EXP.structLiteral, __traits(classInstanceSize, StructLiteralExp));
this.sd = sd;
if (!elements)
elements = new Expressions();
@@ -3278,9 +3279,12 @@ extern (C++) final class StructLiteralExp : Expression
*/
if (elements.dim)
{
+ const sz = type.size();
+ if (sz == SIZE_INVALID)
+ return -1;
foreach (i, v; sd.fields)
{
- if (offset == v.offset && type.size() == v.type.size())
+ if (offset == v.offset && sz == v.type.size())
{
/* context fields might not be filled. */
if (i >= sd.nonHiddenFields())
@@ -3348,7 +3352,7 @@ extern (C++) final class CompoundLiteralExp : Expression
extern (D) this(const ref Loc loc, Type type_name, Initializer initializer)
{
- super(loc, TOK.compoundLiteral, __traits(classInstanceSize, CompoundLiteralExp));
+ super(loc, EXP.compoundLiteral, __traits(classInstanceSize, CompoundLiteralExp));
super.type = type_name;
this.initializer = initializer;
//printf("CompoundLiteralExp::CompoundLiteralExp(%s)\n", toChars());
@@ -3367,7 +3371,7 @@ extern (C++) final class TypeExp : Expression
{
extern (D) this(const ref Loc loc, Type type)
{
- super(loc, TOK.type, __traits(classInstanceSize, TypeExp));
+ super(loc, EXP.type, __traits(classInstanceSize, TypeExp));
//printf("TypeExp::TypeExp(%s)\n", type.toChars());
this.type = type;
}
@@ -3409,7 +3413,7 @@ extern (C++) final class ScopeExp : Expression
extern (D) this(const ref Loc loc, ScopeDsymbol sds)
{
- super(loc, TOK.scope_, __traits(classInstanceSize, ScopeExp));
+ super(loc, EXP.scope_, __traits(classInstanceSize, ScopeExp));
//printf("ScopeExp::ScopeExp(sds = '%s')\n", sds.toChars());
//static int count; if (++count == 38) *(char*)0=0;
this.sds = sds;
@@ -3464,7 +3468,7 @@ extern (C++) final class TemplateExp : Expression
extern (D) this(const ref Loc loc, TemplateDeclaration td, FuncDeclaration fd = null)
{
- super(loc, TOK.template_, __traits(classInstanceSize, TemplateExp));
+ super(loc, EXP.template_, __traits(classInstanceSize, TemplateExp));
//printf("TemplateExp(): %s\n", td.toChars());
this.td = td;
this.fd = fd;
@@ -3519,7 +3523,7 @@ extern (C++) final class NewExp : Expression
extern (D) this(const ref Loc loc, Expression thisexp, Expressions* newargs, Type newtype, Expressions* arguments)
{
- super(loc, TOK.new_, __traits(classInstanceSize, NewExp));
+ super(loc, EXP.new_, __traits(classInstanceSize, NewExp));
this.thisexp = thisexp;
this.newargs = newargs;
this.newtype = newtype;
@@ -3558,7 +3562,7 @@ extern (C++) final class NewAnonClassExp : Expression
extern (D) this(const ref Loc loc, Expression thisexp, Expressions* newargs, ClassDeclaration cd, Expressions* arguments)
{
- super(loc, TOK.newAnonymousClass, __traits(classInstanceSize, NewAnonClassExp));
+ super(loc, EXP.newAnonymousClass, __traits(classInstanceSize, NewAnonClassExp));
this.thisexp = thisexp;
this.newargs = newargs;
this.cd = cd;
@@ -3584,7 +3588,7 @@ extern (C++) class SymbolExp : Expression
Dsymbol originalScope; // original scope before inlining
bool hasOverloads;
- extern (D) this(const ref Loc loc, TOK op, int size, Declaration var, bool hasOverloads)
+ extern (D) this(const ref Loc loc, EXP op, int size, Declaration var, bool hasOverloads)
{
super(loc, op, size);
assert(var);
@@ -3615,13 +3619,13 @@ extern (C++) final class SymOffExp : SymbolExp
.error(loc, "need `this` for address of `%s`", v.toChars());
hasOverloads = false;
}
- super(loc, TOK.symbolOffset, __traits(classInstanceSize, SymOffExp), var, hasOverloads);
+ super(loc, EXP.symbolOffset, __traits(classInstanceSize, SymOffExp), var, hasOverloads);
this.offset = offset;
}
- override bool isBool(bool result)
+ override Optional!bool toBool()
{
- return result ? true : false;
+ return typeof(return)(true);
}
override void accept(Visitor v)
@@ -3641,7 +3645,7 @@ extern (C++) final class VarExp : SymbolExp
if (var.isVarDeclaration())
hasOverloads = false;
- super(loc, TOK.variable, __traits(classInstanceSize, VarExp), var, hasOverloads);
+ super(loc, EXP.variable, __traits(classInstanceSize, VarExp), var, hasOverloads);
//printf("VarExp(this = %p, '%s', loc = %s)\n", this, var.toChars(), loc.toChars());
//if (strcmp(var.ident.toChars(), "func") == 0) assert(0);
this.type = var.type;
@@ -3725,7 +3729,7 @@ extern (C++) final class OverExp : Expression
extern (D) this(const ref Loc loc, OverloadSet s)
{
- super(loc, TOK.overloadSet, __traits(classInstanceSize, OverExp));
+ super(loc, EXP.overloadSet, __traits(classInstanceSize, OverExp));
//printf("OverExp(this = %p, '%s')\n", this, var.toChars());
vars = s;
type = Type.tvoid;
@@ -3755,11 +3759,11 @@ extern (C++) final class FuncExp : Expression
{
FuncLiteralDeclaration fd;
TemplateDeclaration td;
- TOK tok;
+ TOK tok; // TOK.reserved, TOK.delegate_, TOK.function_
extern (D) this(const ref Loc loc, Dsymbol s)
{
- super(loc, TOK.function_, __traits(classInstanceSize, FuncExp));
+ super(loc, EXP.function_, __traits(classInstanceSize, FuncExp));
this.td = s.isTemplateDeclaration();
this.fd = s.isFuncLiteralDeclaration();
if (td)
@@ -3927,7 +3931,7 @@ extern (C++) final class FuncExp : Expression
// Reset inference target for the later re-semantic
fd.treq = null;
- if (ex.op == TOK.error)
+ if (ex.op == EXP.error)
return MATCH.nomatch;
if (auto ef = ex.isFuncExp())
return ef.matchType(to, sc, presult, flag);
@@ -4057,7 +4061,7 @@ extern (C++) final class DeclarationExp : Expression
extern (D) this(const ref Loc loc, Dsymbol declaration)
{
- super(loc, TOK.declaration, __traits(classInstanceSize, DeclarationExp));
+ super(loc, EXP.declaration, __traits(classInstanceSize, DeclarationExp));
this.declaration = declaration;
}
@@ -4090,7 +4094,7 @@ extern (C++) final class TypeidExp : Expression
extern (D) this(const ref Loc loc, RootObject o)
{
- super(loc, TOK.typeid_, __traits(classInstanceSize, TypeidExp));
+ super(loc, EXP.typeid_, __traits(classInstanceSize, TypeidExp));
this.obj = o;
}
@@ -4115,7 +4119,7 @@ extern (C++) final class TraitsExp : Expression
extern (D) this(const ref Loc loc, Identifier ident, Objects* args)
{
- super(loc, TOK.traits, __traits(classInstanceSize, TraitsExp));
+ super(loc, EXP.traits, __traits(classInstanceSize, TraitsExp));
this.ident = ident;
this.args = args;
}
@@ -4137,7 +4141,7 @@ extern (C++) final class HaltExp : Expression
{
extern (D) this(const ref Loc loc)
{
- super(loc, TOK.halt, __traits(classInstanceSize, HaltExp));
+ super(loc, EXP.halt, __traits(classInstanceSize, HaltExp));
}
override void accept(Visitor v)
@@ -4161,7 +4165,7 @@ extern (C++) final class IsExp : Expression
extern (D) this(const ref Loc loc, Type targ, Identifier id, TOK tok, Type tspec, TOK tok2, TemplateParameters* parameters)
{
- super(loc, TOK.is_, __traits(classInstanceSize, IsExp));
+ super(loc, EXP.is_, __traits(classInstanceSize, IsExp));
this.targ = targ;
this.id = id;
this.tok = tok;
@@ -4196,7 +4200,7 @@ extern (C++) abstract class UnaExp : Expression
Expression e1;
Type att1; // Save alias this type to detect recursion
- extern (D) this(const ref Loc loc, TOK op, int size, Expression e1)
+ extern (D) this(const ref Loc loc, EXP op, int size, Expression e1)
{
super(loc, op, size);
this.e1 = e1;
@@ -4221,13 +4225,13 @@ extern (C++) abstract class UnaExp : Expression
if (e1.type.toBasetype() == Type.terror)
return e1;
- if (e1.op == TOK.type)
+ if (e1.op == EXP.type)
{
- error("incompatible type for `%s(%s)`: cannot use `%s` with types", Token.toChars(op), e1.toChars(), Token.toChars(op));
+ error("incompatible type for `%s(%s)`: cannot use `%s` with types", EXPtoString(op).ptr, e1.toChars(), EXPtoString(op).ptr);
}
else
{
- error("incompatible type for `%s(%s)`: `%s`", Token.toChars(op), e1.toChars(), e1.type.toChars());
+ error("incompatible type for `%s(%s)`: `%s`", EXPtoString(op).ptr, e1.toChars(), e1.type.toChars());
}
return ErrorExp.get();
}
@@ -4257,7 +4261,7 @@ extern (C++) abstract class UnaExp : Expression
}
alias fp_t = UnionExp function(const ref Loc loc, Type, Expression, Expression);
-alias fp2_t = bool function(const ref Loc loc, TOK, Expression, Expression);
+alias fp2_t = bool function(const ref Loc loc, EXP, Expression, Expression);
/***********************************************************
*/
@@ -4268,7 +4272,7 @@ extern (C++) abstract class BinExp : Expression
Type att1; // Save alias this type to detect recursion
Type att2; // Save alias this type to detect recursion
- extern (D) this(const ref Loc loc, TOK op, int size, Expression e1, Expression e2)
+ extern (D) this(const ref Loc loc, EXP op, int size, Expression e1, Expression e2)
{
super(loc, op, size);
this.e1 = e1;
@@ -4298,22 +4302,22 @@ extern (C++) abstract class BinExp : Expression
return e2;
// CondExp uses 'a ? b : c' but we're comparing 'b : c'
- TOK thisOp = (op == TOK.question) ? TOK.colon : op;
- if (e1.op == TOK.type || e2.op == TOK.type)
+ const(char)* thisOp = (op == EXP.question) ? ":" : EXPtoString(op).ptr;
+ if (e1.op == EXP.type || e2.op == EXP.type)
{
error("incompatible types for `(%s) %s (%s)`: cannot use `%s` with types",
- e1.toChars(), Token.toChars(thisOp), e2.toChars(), Token.toChars(op));
+ e1.toChars(), thisOp, e2.toChars(), EXPtoString(op).ptr);
}
else if (e1.type.equals(e2.type))
{
error("incompatible types for `(%s) %s (%s)`: both operands are of type `%s`",
- e1.toChars(), Token.toChars(thisOp), e2.toChars(), e1.type.toChars());
+ e1.toChars(), thisOp, e2.toChars(), e1.type.toChars());
}
else
{
auto ts = toAutoQualChars(e1.type, e2.type);
error("incompatible types for `(%s) %s (%s)`: `%s` and `%s`",
- e1.toChars(), Token.toChars(thisOp), e2.toChars(), ts[0], ts[1]);
+ e1.toChars(), thisOp, e2.toChars(), ts[0], ts[1]);
}
return ErrorExp.get();
}
@@ -4327,22 +4331,22 @@ extern (C++) abstract class BinExp : Expression
// T opAssign floating yields a floating. Prevent truncating conversions (float to int).
// See issue 3841.
// Should we also prevent double to float (type.isfloating() && type.size() < t2.size()) ?
- if (op == TOK.addAssign || op == TOK.minAssign ||
- op == TOK.mulAssign || op == TOK.divAssign || op == TOK.modAssign ||
- op == TOK.powAssign)
+ if (op == EXP.addAssign || op == EXP.minAssign ||
+ op == EXP.mulAssign || op == EXP.divAssign || op == EXP.modAssign ||
+ op == EXP.powAssign)
{
if ((type.isintegral() && t2.isfloating()))
{
- warning("`%s %s %s` is performing truncating conversion", type.toChars(), Token.toChars(op), t2.toChars());
+ warning("`%s %s %s` is performing truncating conversion", type.toChars(), EXPtoString(op).ptr, t2.toChars());
}
}
// generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary
- if (op == TOK.mulAssign || op == TOK.divAssign || op == TOK.modAssign)
+ if (op == EXP.mulAssign || op == EXP.divAssign || op == EXP.modAssign)
{
// Any multiplication by an imaginary or complex number yields a complex result.
// r *= c, i*=c, r*=i, i*=i are all forbidden operations.
- const(char)* opstr = Token.toChars(op);
+ const(char)* opstr = EXPtoString(op).ptr;
if (t1.isreal() && t2.iscomplex())
{
error("`%s %s %s` is undefined. Did you mean `%s %s %s.re`?", t1.toChars(), opstr, t2.toChars(), t1.toChars(), opstr, t2.toChars());
@@ -4361,13 +4365,13 @@ extern (C++) abstract class BinExp : Expression
}
// generate an error if this is a nonsensical += or -=, eg real += imaginary
- if (op == TOK.addAssign || op == TOK.minAssign)
+ if (op == EXP.addAssign || op == EXP.minAssign)
{
// Addition or subtraction of a real and an imaginary is a complex result.
// Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations.
if ((t1.isreal() && (t2.isimaginary() || t2.iscomplex())) || (t1.isimaginary() && (t2.isreal() || t2.iscomplex())))
{
- error("`%s %s %s` is undefined (result is complex)", t1.toChars(), Token.toChars(op), t2.toChars());
+ error("`%s %s %s` is undefined (result is complex)", t1.toChars(), EXPtoString(op).ptr, t2.toChars());
return ErrorExp.get();
}
if (type.isreal() || type.isimaginary())
@@ -4376,7 +4380,7 @@ extern (C++) abstract class BinExp : Expression
e2 = e2.castTo(sc, t1);
}
}
- if (op == TOK.mulAssign)
+ if (op == EXP.mulAssign)
{
if (t2.isfloating())
{
@@ -4413,7 +4417,7 @@ extern (C++) abstract class BinExp : Expression
}
}
}
- else if (op == TOK.divAssign)
+ else if (op == EXP.divAssign)
{
if (t2.isimaginary())
{
@@ -4454,7 +4458,7 @@ extern (C++) abstract class BinExp : Expression
}
}
}
- else if (op == TOK.modAssign)
+ else if (op == EXP.modAssign)
{
if (t2.iscomplex())
{
@@ -4558,7 +4562,7 @@ extern (C++) abstract class BinExp : Expression
*/
extern (C++) class BinAssignExp : BinExp
{
- extern (D) this(const ref Loc loc, TOK op, int size, Expression e1, Expression e2)
+ extern (D) this(const ref Loc loc, EXP op, int size, Expression e1, Expression e2)
{
super(loc, op, size, e1, e2);
}
@@ -4600,7 +4604,7 @@ extern (C++) final class MixinExp : Expression
extern (D) this(const ref Loc loc, Expressions* exps)
{
- super(loc, TOK.mixin_, __traits(classInstanceSize, MixinExp));
+ super(loc, EXP.mixin_, __traits(classInstanceSize, MixinExp));
this.exps = exps;
}
@@ -4643,7 +4647,7 @@ extern (C++) final class ImportExp : UnaExp
{
extern (D) this(const ref Loc loc, Expression e)
{
- super(loc, TOK.import_, __traits(classInstanceSize, ImportExp), e);
+ super(loc, EXP.import_, __traits(classInstanceSize, ImportExp), e);
}
override void accept(Visitor v)
@@ -4661,7 +4665,7 @@ extern (C++) final class AssertExp : UnaExp
extern (D) this(const ref Loc loc, Expression e, Expression msg = null)
{
- super(loc, TOK.assert_, __traits(classInstanceSize, AssertExp), e);
+ super(loc, EXP.assert_, __traits(classInstanceSize, AssertExp), e);
this.msg = msg;
}
@@ -4687,7 +4691,7 @@ extern (C++) final class DotIdExp : UnaExp
extern (D) this(const ref Loc loc, Expression e, Identifier ident)
{
- super(loc, TOK.dotIdentifier, __traits(classInstanceSize, DotIdExp), e);
+ super(loc, EXP.dotIdentifier, __traits(classInstanceSize, DotIdExp), e);
this.ident = ident;
}
@@ -4711,7 +4715,7 @@ extern (C++) final class DotTemplateExp : UnaExp
extern (D) this(const ref Loc loc, Expression e, TemplateDeclaration td)
{
- super(loc, TOK.dotTemplateDeclaration, __traits(classInstanceSize, DotTemplateExp), e);
+ super(loc, EXP.dotTemplateDeclaration, __traits(classInstanceSize, DotTemplateExp), e);
this.td = td;
}
@@ -4745,7 +4749,7 @@ extern (C++) final class DotVarExp : UnaExp
if (var.isVarDeclaration())
hasOverloads = false;
- super(loc, TOK.dotVariable, __traits(classInstanceSize, DotVarExp), e);
+ super(loc, EXP.dotVariable, __traits(classInstanceSize, DotVarExp), e);
//printf("DotVarExp()\n");
this.var = var;
this.hasOverloads = hasOverloads;
@@ -4753,7 +4757,7 @@ extern (C++) final class DotVarExp : UnaExp
override bool isLvalue()
{
- if (e1.op != TOK.structLiteral)
+ if (e1.op != EXP.structLiteral)
return true;
auto vd = var.isVarDeclaration();
return !(vd && vd.isField());
@@ -4772,7 +4776,7 @@ extern (C++) final class DotVarExp : UnaExp
}
if (!isLvalue())
return Expression.toLvalue(sc, e);
- if (e1.op == TOK.this_ && sc.ctorflow.fieldinit.length && !(sc.ctorflow.callSuper & CSX.any_ctor))
+ if (e1.op == EXP.this_ && sc.ctorflow.fieldinit.length && !(sc.ctorflow.callSuper & CSX.any_ctor))
{
if (VarDeclaration vd = var.isVarDeclaration())
{
@@ -4826,14 +4830,14 @@ extern (C++) final class DotTemplateInstanceExp : UnaExp
extern (D) this(const ref Loc loc, Expression e, Identifier name, Objects* tiargs)
{
- super(loc, TOK.dotTemplateInstance, __traits(classInstanceSize, DotTemplateInstanceExp), e);
+ super(loc, EXP.dotTemplateInstance, __traits(classInstanceSize, DotTemplateInstanceExp), e);
//printf("DotTemplateInstanceExp()\n");
this.ti = new TemplateInstance(loc, name, tiargs);
}
extern (D) this(const ref Loc loc, Expression e, TemplateInstance ti)
{
- super(loc, TOK.dotTemplateInstance, __traits(classInstanceSize, DotTemplateInstanceExp), e);
+ super(loc, EXP.dotTemplateInstance, __traits(classInstanceSize, DotTemplateInstanceExp), e);
this.ti = ti;
}
@@ -4853,29 +4857,29 @@ extern (C++) final class DotTemplateInstanceExp : UnaExp
Expression e = new DotIdExp(loc, e1, ti.name);
e = e.expressionSemantic(sc);
- if (e.op == TOK.dot)
+ if (e.op == EXP.dot)
e = (cast(DotExp)e).e2;
Dsymbol s = null;
switch (e.op)
{
- case TOK.overloadSet:
+ case EXP.overloadSet:
s = (cast(OverExp)e).vars;
break;
- case TOK.dotTemplateDeclaration:
+ case EXP.dotTemplateDeclaration:
s = (cast(DotTemplateExp)e).td;
break;
- case TOK.scope_:
+ case EXP.scope_:
s = (cast(ScopeExp)e).sds;
break;
- case TOK.dotVariable:
+ case EXP.dotVariable:
s = (cast(DotVarExp)e).var;
break;
- case TOK.variable:
+ case EXP.variable:
s = (cast(VarExp)e).var;
break;
@@ -4926,7 +4930,7 @@ extern (C++) final class DelegateExp : UnaExp
extern (D) this(const ref Loc loc, Expression e, FuncDeclaration f, bool hasOverloads = true, VarDeclaration vthis2 = null)
{
- super(loc, TOK.delegate_, __traits(classInstanceSize, DelegateExp), e);
+ super(loc, EXP.delegate_, __traits(classInstanceSize, DelegateExp), e);
this.func = f;
this.hasOverloads = hasOverloads;
this.vthis2 = vthis2;
@@ -4946,7 +4950,7 @@ extern (C++) final class DotTypeExp : UnaExp
extern (D) this(const ref Loc loc, Expression e, Dsymbol s)
{
- super(loc, TOK.dotType, __traits(classInstanceSize, DotTypeExp), e);
+ super(loc, EXP.dotType, __traits(classInstanceSize, DotTypeExp), e);
this.sym = s;
}
@@ -4969,18 +4973,18 @@ extern (C++) final class CallExp : UnaExp
extern (D) this(const ref Loc loc, Expression e, Expressions* exps)
{
- super(loc, TOK.call, __traits(classInstanceSize, CallExp), e);
+ super(loc, EXP.call, __traits(classInstanceSize, CallExp), e);
this.arguments = exps;
}
extern (D) this(const ref Loc loc, Expression e)
{
- super(loc, TOK.call, __traits(classInstanceSize, CallExp), e);
+ super(loc, EXP.call, __traits(classInstanceSize, CallExp), e);
}
extern (D) this(const ref Loc loc, Expression e, Expression earg1)
{
- super(loc, TOK.call, __traits(classInstanceSize, CallExp), e);
+ super(loc, EXP.call, __traits(classInstanceSize, CallExp), e);
this.arguments = new Expressions();
if (earg1)
this.arguments.push(earg1);
@@ -4988,7 +4992,7 @@ extern (C++) final class CallExp : UnaExp
extern (D) this(const ref Loc loc, Expression e, Expression earg1, Expression earg2)
{
- super(loc, TOK.call, __traits(classInstanceSize, CallExp), e);
+ super(loc, EXP.call, __traits(classInstanceSize, CallExp), e);
auto arguments = new Expressions(2);
(*arguments)[0] = earg1;
(*arguments)[1] = earg2;
@@ -5143,7 +5147,7 @@ extern (C++) final class AddrExp : UnaExp
{
extern (D) this(const ref Loc loc, Expression e)
{
- super(loc, TOK.address, __traits(classInstanceSize, AddrExp), e);
+ super(loc, EXP.address, __traits(classInstanceSize, AddrExp), e);
}
extern (D) this(const ref Loc loc, Expression e, Type t)
@@ -5164,14 +5168,14 @@ extern (C++) final class PtrExp : UnaExp
{
extern (D) this(const ref Loc loc, Expression e)
{
- super(loc, TOK.star, __traits(classInstanceSize, PtrExp), e);
+ super(loc, EXP.star, __traits(classInstanceSize, PtrExp), e);
//if (e.type)
// type = ((TypePointer *)e.type).next;
}
extern (D) this(const ref Loc loc, Expression e, Type t)
{
- super(loc, TOK.star, __traits(classInstanceSize, PtrExp), e);
+ super(loc, EXP.star, __traits(classInstanceSize, PtrExp), e);
type = t;
}
@@ -5216,7 +5220,7 @@ extern (C++) final class NegExp : UnaExp
{
extern (D) this(const ref Loc loc, Expression e)
{
- super(loc, TOK.negate, __traits(classInstanceSize, NegExp), e);
+ super(loc, EXP.negate, __traits(classInstanceSize, NegExp), e);
}
override void accept(Visitor v)
@@ -5231,7 +5235,7 @@ extern (C++) final class UAddExp : UnaExp
{
extern (D) this(const ref Loc loc, Expression e)
{
- super(loc, TOK.uadd, __traits(classInstanceSize, UAddExp), e);
+ super(loc, EXP.uadd, __traits(classInstanceSize, UAddExp), e);
}
override void accept(Visitor v)
@@ -5246,7 +5250,7 @@ extern (C++) final class ComExp : UnaExp
{
extern (D) this(const ref Loc loc, Expression e)
{
- super(loc, TOK.tilde, __traits(classInstanceSize, ComExp), e);
+ super(loc, EXP.tilde, __traits(classInstanceSize, ComExp), e);
}
override void accept(Visitor v)
@@ -5261,7 +5265,7 @@ extern (C++) final class NotExp : UnaExp
{
extern (D) this(const ref Loc loc, Expression e)
{
- super(loc, TOK.not, __traits(classInstanceSize, NotExp), e);
+ super(loc, EXP.not, __traits(classInstanceSize, NotExp), e);
}
override void accept(Visitor v)
@@ -5278,7 +5282,7 @@ extern (C++) final class DeleteExp : UnaExp
extern (D) this(const ref Loc loc, Expression e, bool isRAII)
{
- super(loc, TOK.delete_, __traits(classInstanceSize, DeleteExp), e);
+ super(loc, EXP.delete_, __traits(classInstanceSize, DeleteExp), e);
this.isRAII = isRAII;
}
@@ -5298,7 +5302,7 @@ extern (C++) final class CastExp : UnaExp
extern (D) this(const ref Loc loc, Expression e, Type t)
{
- super(loc, TOK.cast_, __traits(classInstanceSize, CastExp), e);
+ super(loc, EXP.cast_, __traits(classInstanceSize, CastExp), e);
this.to = t;
}
@@ -5306,7 +5310,7 @@ extern (C++) final class CastExp : UnaExp
*/
extern (D) this(const ref Loc loc, Expression e, ubyte mod)
{
- super(loc, TOK.cast_, __traits(classInstanceSize, CastExp), e);
+ super(loc, EXP.cast_, __traits(classInstanceSize, CastExp), e);
this.mod = mod;
}
@@ -5360,7 +5364,7 @@ extern (C++) final class VectorExp : UnaExp
extern (D) this(const ref Loc loc, Expression e, Type t)
{
- super(loc, TOK.vector, __traits(classInstanceSize, VectorExp), e);
+ super(loc, EXP.vector, __traits(classInstanceSize, VectorExp), e);
assert(t.ty == Tvector);
to = cast(TypeVector)t;
}
@@ -5396,7 +5400,7 @@ extern (C++) final class VectorArrayExp : UnaExp
{
extern (D) this(const ref Loc loc, Expression e1)
{
- super(loc, TOK.vectorArray, __traits(classInstanceSize, VectorArrayExp), e1);
+ super(loc, EXP.vectorArray, __traits(classInstanceSize, VectorArrayExp), e1);
}
override bool isLvalue()
@@ -5434,14 +5438,14 @@ extern (C++) final class SliceExp : UnaExp
/************************************************************/
extern (D) this(const ref Loc loc, Expression e1, IntervalExp ie)
{
- super(loc, TOK.slice, __traits(classInstanceSize, SliceExp), e1);
+ super(loc, EXP.slice, __traits(classInstanceSize, SliceExp), e1);
this.upr = ie ? ie.upr : null;
this.lwr = ie ? ie.lwr : null;
}
extern (D) this(const ref Loc loc, Expression e1, Expression lwr, Expression upr)
{
- super(loc, TOK.slice, __traits(classInstanceSize, SliceExp), e1);
+ super(loc, EXP.slice, __traits(classInstanceSize, SliceExp), e1);
this.upr = upr;
this.lwr = lwr;
}
@@ -5473,9 +5477,9 @@ extern (C++) final class SliceExp : UnaExp
return this;
}
- override bool isBool(bool result)
+ override Optional!bool toBool()
{
- return e1.isBool(result);
+ return e1.toBool();
}
override void accept(Visitor v)
@@ -5490,7 +5494,7 @@ extern (C++) final class ArrayLengthExp : UnaExp
{
extern (D) this(const ref Loc loc, Expression e1)
{
- super(loc, TOK.arrayLength, __traits(classInstanceSize, ArrayLengthExp), e1);
+ super(loc, EXP.arrayLength, __traits(classInstanceSize, ArrayLengthExp), e1);
}
override void accept(Visitor v)
@@ -5513,7 +5517,7 @@ extern (C++) final class ArrayExp : UnaExp
extern (D) this(const ref Loc loc, Expression e1, Expression index = null)
{
- super(loc, TOK.array, __traits(classInstanceSize, ArrayExp), e1);
+ super(loc, EXP.array, __traits(classInstanceSize, ArrayExp), e1);
arguments = new Expressions();
if (index)
arguments.push(index);
@@ -5521,7 +5525,7 @@ extern (C++) final class ArrayExp : UnaExp
extern (D) this(const ref Loc loc, Expression e1, Expressions* args)
{
- super(loc, TOK.array, __traits(classInstanceSize, ArrayExp), e1);
+ super(loc, EXP.array, __traits(classInstanceSize, ArrayExp), e1);
arguments = args;
}
@@ -5558,7 +5562,7 @@ extern (C++) final class DotExp : BinExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.dot, __traits(classInstanceSize, DotExp), e1, e2);
+ super(loc, EXP.dot, __traits(classInstanceSize, DotExp), e1, e2);
}
override void accept(Visitor v)
@@ -5584,7 +5588,7 @@ extern (C++) final class CommaExp : BinExp
extern (D) this(const ref Loc loc, Expression e1, Expression e2, bool generated = true)
{
- super(loc, TOK.comma, __traits(classInstanceSize, CommaExp), e1, e2);
+ super(loc, EXP.comma, __traits(classInstanceSize, CommaExp), e1, e2);
allowCommaExp = isGenerated = generated;
}
@@ -5605,9 +5609,9 @@ extern (C++) final class CommaExp : BinExp
return this;
}
- override bool isBool(bool result)
+ override Optional!bool toBool()
{
- return e2.isBool(result);
+ return e2.toBool();
}
override Expression addDtorHook(Scope* sc)
@@ -5653,7 +5657,7 @@ extern (C++) final class IntervalExp : Expression
extern (D) this(const ref Loc loc, Expression lwr, Expression upr)
{
- super(loc, TOK.interval, __traits(classInstanceSize, IntervalExp));
+ super(loc, EXP.interval, __traits(classInstanceSize, IntervalExp));
this.lwr = lwr;
this.upr = upr;
}
@@ -5673,7 +5677,7 @@ extern (C++) final class DelegatePtrExp : UnaExp
{
extern (D) this(const ref Loc loc, Expression e1)
{
- super(loc, TOK.delegatePointer, __traits(classInstanceSize, DelegatePtrExp), e1);
+ super(loc, EXP.delegatePointer, __traits(classInstanceSize, DelegatePtrExp), e1);
}
override bool isLvalue()
@@ -5709,7 +5713,7 @@ extern (C++) final class DelegateFuncptrExp : UnaExp
{
extern (D) this(const ref Loc loc, Expression e1)
{
- super(loc, TOK.delegateFunctionPointer, __traits(classInstanceSize, DelegateFuncptrExp), e1);
+ super(loc, EXP.delegateFunctionPointer, __traits(classInstanceSize, DelegateFuncptrExp), e1);
}
override bool isLvalue()
@@ -5750,7 +5754,7 @@ extern (C++) final class IndexExp : BinExp
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.index, __traits(classInstanceSize, IndexExp), e1, e2);
+ super(loc, EXP.index, __traits(classInstanceSize, IndexExp), e1, e2);
//printf("IndexExp::IndexExp('%s')\n", toChars());
}
@@ -5763,10 +5767,10 @@ extern (C++) final class IndexExp : BinExp
override bool isLvalue()
{
- if (e1.op == TOK.assocArrayLiteral)
+ if (e1.op == EXP.assocArrayLiteral)
return false;
if (e1.type.ty == Tsarray ||
- (e1.op == TOK.index && e1.type.ty != Tarray))
+ (e1.op == EXP.index && e1.type.ty != Tarray))
{
return e1.isLvalue();
}
@@ -5784,7 +5788,7 @@ extern (C++) final class IndexExp : BinExp
{
//printf("IndexExp::modifiableLvalue(%s)\n", toChars());
Expression ex = markSettingAAElem();
- if (ex.op == TOK.error)
+ if (ex.op == EXP.error)
return ex;
return Expression.modifiableLvalue(sc, e);
@@ -5805,7 +5809,7 @@ extern (C++) final class IndexExp : BinExp
if (auto ie = e1.isIndexExp())
{
Expression ex = ie.markSettingAAElem();
- if (ex.op == TOK.error)
+ if (ex.op == EXP.error)
return ex;
assert(ex == e1);
}
@@ -5824,10 +5828,10 @@ extern (C++) final class IndexExp : BinExp
*/
extern (C++) final class PostExp : BinExp
{
- extern (D) this(TOK op, const ref Loc loc, Expression e)
+ extern (D) this(EXP op, const ref Loc loc, Expression e)
{
super(loc, op, __traits(classInstanceSize, PostExp), e, IntegerExp.literal!1);
- assert(op == TOK.minusMinus || op == TOK.plusPlus);
+ assert(op == EXP.minusMinus || op == EXP.plusPlus);
}
override void accept(Visitor v)
@@ -5841,10 +5845,10 @@ extern (C++) final class PostExp : BinExp
*/
extern (C++) final class PreExp : UnaExp
{
- extern (D) this(TOK op, const ref Loc loc, Expression e)
+ extern (D) this(EXP op, const ref Loc loc, Expression e)
{
super(loc, op, __traits(classInstanceSize, PreExp), e);
- assert(op == TOK.preMinusMinus || op == TOK.prePlusPlus);
+ assert(op == EXP.preMinusMinus || op == EXP.prePlusPlus);
}
override void accept(Visitor v)
@@ -5867,13 +5871,13 @@ extern (C++) class AssignExp : BinExp
MemorySet memset;
/************************************************************/
- /* op can be TOK.assign, TOK.construct, or TOK.blit */
+ /* op can be EXP.assign, EXP.construct, or EXP.blit */
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.assign, __traits(classInstanceSize, AssignExp), e1, e2);
+ super(loc, EXP.assign, __traits(classInstanceSize, AssignExp), e1, e2);
}
- this(const ref Loc loc, TOK tok, Expression e1, Expression e2)
+ this(const ref Loc loc, EXP tok, Expression e1, Expression e2)
{
super(loc, tok, __traits(classInstanceSize, AssignExp), e1, e2);
}
@@ -5882,7 +5886,7 @@ extern (C++) class AssignExp : BinExp
{
// Array-op 'x[] = y[]' should make an rvalue.
// Setting array length 'x.length = v' should make an rvalue.
- if (e1.op == TOK.slice || e1.op == TOK.arrayLength)
+ if (e1.op == EXP.slice || e1.op == EXP.arrayLength)
{
return false;
}
@@ -5891,7 +5895,7 @@ extern (C++) class AssignExp : BinExp
override final Expression toLvalue(Scope* sc, Expression ex)
{
- if (e1.op == TOK.slice || e1.op == TOK.arrayLength)
+ if (e1.op == EXP.slice || e1.op == EXP.arrayLength)
{
return Expression.toLvalue(sc, ex);
}
@@ -5915,7 +5919,7 @@ extern (C++) final class ConstructExp : AssignExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.construct, e1, e2);
+ super(loc, EXP.construct, e1, e2);
}
// Internal use only. If `v` is a reference variable, the assignment
@@ -5925,7 +5929,7 @@ extern (C++) final class ConstructExp : AssignExp
auto ve = new VarExp(loc, v);
assert(v.type && ve.type);
- super(loc, TOK.construct, ve, e2);
+ super(loc, EXP.construct, ve, e2);
if (v.isReference())
memset = MemorySet.referenceInit;
@@ -5943,7 +5947,7 @@ extern (C++) final class BlitExp : AssignExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.blit, e1, e2);
+ super(loc, EXP.blit, e1, e2);
}
// Internal use only. If `v` is a reference variable, the assinment
@@ -5953,7 +5957,7 @@ extern (C++) final class BlitExp : AssignExp
auto ve = new VarExp(loc, v);
assert(v.type && ve.type);
- super(loc, TOK.blit, ve, e2);
+ super(loc, EXP.blit, ve, e2);
if (v.isReference())
memset = MemorySet.referenceInit;
@@ -5971,7 +5975,7 @@ extern (C++) final class AddAssignExp : BinAssignExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.addAssign, __traits(classInstanceSize, AddAssignExp), e1, e2);
+ super(loc, EXP.addAssign, __traits(classInstanceSize, AddAssignExp), e1, e2);
}
override void accept(Visitor v)
@@ -5986,7 +5990,7 @@ extern (C++) final class MinAssignExp : BinAssignExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.minAssign, __traits(classInstanceSize, MinAssignExp), e1, e2);
+ super(loc, EXP.minAssign, __traits(classInstanceSize, MinAssignExp), e1, e2);
}
override void accept(Visitor v)
@@ -6001,7 +6005,7 @@ extern (C++) final class MulAssignExp : BinAssignExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.mulAssign, __traits(classInstanceSize, MulAssignExp), e1, e2);
+ super(loc, EXP.mulAssign, __traits(classInstanceSize, MulAssignExp), e1, e2);
}
override void accept(Visitor v)
@@ -6016,7 +6020,7 @@ extern (C++) final class DivAssignExp : BinAssignExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.divAssign, __traits(classInstanceSize, DivAssignExp), e1, e2);
+ super(loc, EXP.divAssign, __traits(classInstanceSize, DivAssignExp), e1, e2);
}
override void accept(Visitor v)
@@ -6031,7 +6035,7 @@ extern (C++) final class ModAssignExp : BinAssignExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.modAssign, __traits(classInstanceSize, ModAssignExp), e1, e2);
+ super(loc, EXP.modAssign, __traits(classInstanceSize, ModAssignExp), e1, e2);
}
override void accept(Visitor v)
@@ -6046,7 +6050,7 @@ extern (C++) final class AndAssignExp : BinAssignExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.andAssign, __traits(classInstanceSize, AndAssignExp), e1, e2);
+ super(loc, EXP.andAssign, __traits(classInstanceSize, AndAssignExp), e1, e2);
}
override void accept(Visitor v)
@@ -6061,7 +6065,7 @@ extern (C++) final class OrAssignExp : BinAssignExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.orAssign, __traits(classInstanceSize, OrAssignExp), e1, e2);
+ super(loc, EXP.orAssign, __traits(classInstanceSize, OrAssignExp), e1, e2);
}
override void accept(Visitor v)
@@ -6076,7 +6080,7 @@ extern (C++) final class XorAssignExp : BinAssignExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.xorAssign, __traits(classInstanceSize, XorAssignExp), e1, e2);
+ super(loc, EXP.xorAssign, __traits(classInstanceSize, XorAssignExp), e1, e2);
}
override void accept(Visitor v)
@@ -6091,7 +6095,7 @@ extern (C++) final class PowAssignExp : BinAssignExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.powAssign, __traits(classInstanceSize, PowAssignExp), e1, e2);
+ super(loc, EXP.powAssign, __traits(classInstanceSize, PowAssignExp), e1, e2);
}
override void accept(Visitor v)
@@ -6106,7 +6110,7 @@ extern (C++) final class ShlAssignExp : BinAssignExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.leftShiftAssign, __traits(classInstanceSize, ShlAssignExp), e1, e2);
+ super(loc, EXP.leftShiftAssign, __traits(classInstanceSize, ShlAssignExp), e1, e2);
}
override void accept(Visitor v)
@@ -6121,7 +6125,7 @@ extern (C++) final class ShrAssignExp : BinAssignExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.rightShiftAssign, __traits(classInstanceSize, ShrAssignExp), e1, e2);
+ super(loc, EXP.rightShiftAssign, __traits(classInstanceSize, ShrAssignExp), e1, e2);
}
override void accept(Visitor v)
@@ -6136,7 +6140,7 @@ extern (C++) final class UshrAssignExp : BinAssignExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.unsignedRightShiftAssign, __traits(classInstanceSize, UshrAssignExp), e1, e2);
+ super(loc, EXP.unsignedRightShiftAssign, __traits(classInstanceSize, UshrAssignExp), e1, e2);
}
override void accept(Visitor v)
@@ -6148,21 +6152,21 @@ extern (C++) final class UshrAssignExp : BinAssignExp
/***********************************************************
* The ~= operator. It can have one of the following operators:
*
- * TOK.concatenateAssign - appending T[] to T[]
- * TOK.concatenateElemAssign - appending T to T[]
- * TOK.concatenateDcharAssign - appending dchar to T[]
+ * EXP.concatenateAssign - appending T[] to T[]
+ * EXP.concatenateElemAssign - appending T to T[]
+ * EXP.concatenateDcharAssign - appending dchar to T[]
*
- * The parser initially sets it to TOK.concatenateAssign, and semantic() later decides which
+ * The parser initially sets it to EXP.concatenateAssign, and semantic() later decides which
* of the three it will be set to.
*/
extern (C++) class CatAssignExp : BinAssignExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.concatenateAssign, __traits(classInstanceSize, CatAssignExp), e1, e2);
+ super(loc, EXP.concatenateAssign, __traits(classInstanceSize, CatAssignExp), e1, e2);
}
- extern (D) this(const ref Loc loc, TOK tok, Expression e1, Expression e2)
+ extern (D) this(const ref Loc loc, EXP tok, Expression e1, Expression e2)
{
super(loc, tok, __traits(classInstanceSize, CatAssignExp), e1, e2);
}
@@ -6178,7 +6182,7 @@ extern (C++) final class CatElemAssignExp : CatAssignExp
{
extern (D) this(const ref Loc loc, Type type, Expression e1, Expression e2)
{
- super(loc, TOK.concatenateElemAssign, e1, e2);
+ super(loc, EXP.concatenateElemAssign, e1, e2);
this.type = type;
}
@@ -6193,7 +6197,7 @@ extern (C++) final class CatDcharAssignExp : CatAssignExp
{
extern (D) this(const ref Loc loc, Type type, Expression e1, Expression e2)
{
- super(loc, TOK.concatenateDcharAssign, e1, e2);
+ super(loc, EXP.concatenateDcharAssign, e1, e2);
this.type = type;
}
@@ -6210,7 +6214,7 @@ extern (C++) final class AddExp : BinExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.add, __traits(classInstanceSize, AddExp), e1, e2);
+ super(loc, EXP.add, __traits(classInstanceSize, AddExp), e1, e2);
}
override void accept(Visitor v)
@@ -6225,7 +6229,7 @@ extern (C++) final class MinExp : BinExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.min, __traits(classInstanceSize, MinExp), e1, e2);
+ super(loc, EXP.min, __traits(classInstanceSize, MinExp), e1, e2);
}
override void accept(Visitor v)
@@ -6241,7 +6245,7 @@ extern (C++) final class CatExp : BinExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.concatenate, __traits(classInstanceSize, CatExp), e1, e2);
+ super(loc, EXP.concatenate, __traits(classInstanceSize, CatExp), e1, e2);
}
override Expression resolveLoc(const ref Loc loc, Scope* sc)
@@ -6264,7 +6268,7 @@ extern (C++) final class MulExp : BinExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.mul, __traits(classInstanceSize, MulExp), e1, e2);
+ super(loc, EXP.mul, __traits(classInstanceSize, MulExp), e1, e2);
}
override void accept(Visitor v)
@@ -6280,7 +6284,7 @@ extern (C++) final class DivExp : BinExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.div, __traits(classInstanceSize, DivExp), e1, e2);
+ super(loc, EXP.div, __traits(classInstanceSize, DivExp), e1, e2);
}
override void accept(Visitor v)
@@ -6296,7 +6300,7 @@ extern (C++) final class ModExp : BinExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.mod, __traits(classInstanceSize, ModExp), e1, e2);
+ super(loc, EXP.mod, __traits(classInstanceSize, ModExp), e1, e2);
}
override void accept(Visitor v)
@@ -6312,7 +6316,7 @@ extern (C++) final class PowExp : BinExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.pow, __traits(classInstanceSize, PowExp), e1, e2);
+ super(loc, EXP.pow, __traits(classInstanceSize, PowExp), e1, e2);
}
override void accept(Visitor v)
@@ -6327,7 +6331,7 @@ extern (C++) final class ShlExp : BinExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.leftShift, __traits(classInstanceSize, ShlExp), e1, e2);
+ super(loc, EXP.leftShift, __traits(classInstanceSize, ShlExp), e1, e2);
}
override void accept(Visitor v)
@@ -6342,7 +6346,7 @@ extern (C++) final class ShrExp : BinExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.rightShift, __traits(classInstanceSize, ShrExp), e1, e2);
+ super(loc, EXP.rightShift, __traits(classInstanceSize, ShrExp), e1, e2);
}
override void accept(Visitor v)
@@ -6357,7 +6361,7 @@ extern (C++) final class UshrExp : BinExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.unsignedRightShift, __traits(classInstanceSize, UshrExp), e1, e2);
+ super(loc, EXP.unsignedRightShift, __traits(classInstanceSize, UshrExp), e1, e2);
}
override void accept(Visitor v)
@@ -6372,7 +6376,7 @@ extern (C++) final class AndExp : BinExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.and, __traits(classInstanceSize, AndExp), e1, e2);
+ super(loc, EXP.and, __traits(classInstanceSize, AndExp), e1, e2);
}
override void accept(Visitor v)
@@ -6387,7 +6391,7 @@ extern (C++) final class OrExp : BinExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.or, __traits(classInstanceSize, OrExp), e1, e2);
+ super(loc, EXP.or, __traits(classInstanceSize, OrExp), e1, e2);
}
override void accept(Visitor v)
@@ -6402,7 +6406,7 @@ extern (C++) final class XorExp : BinExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.xor, __traits(classInstanceSize, XorExp), e1, e2);
+ super(loc, EXP.xor, __traits(classInstanceSize, XorExp), e1, e2);
}
override void accept(Visitor v)
@@ -6417,10 +6421,10 @@ extern (C++) final class XorExp : BinExp
*/
extern (C++) final class LogicalExp : BinExp
{
- extern (D) this(const ref Loc loc, TOK op, Expression e1, Expression e2)
+ extern (D) this(const ref Loc loc, EXP op, Expression e1, Expression e2)
{
super(loc, op, __traits(classInstanceSize, LogicalExp), e1, e2);
- assert(op == TOK.andAnd || op == TOK.orOr);
+ assert(op == EXP.andAnd || op == EXP.orOr);
}
override void accept(Visitor v)
@@ -6431,16 +6435,16 @@ extern (C++) final class LogicalExp : BinExp
/***********************************************************
* `op` is one of:
- * TOK.lessThan, TOK.lessOrEqual, TOK.greaterThan, TOK.greaterOrEqual
+ * EXP.lessThan, EXP.lessOrEqual, EXP.greaterThan, EXP.greaterOrEqual
*
* http://dlang.org/spec/expression.html#relation_expressions
*/
extern (C++) final class CmpExp : BinExp
{
- extern (D) this(TOK op, const ref Loc loc, Expression e1, Expression e2)
+ extern (D) this(EXP op, const ref Loc loc, Expression e1, Expression e2)
{
super(loc, op, __traits(classInstanceSize, CmpExp), e1, e2);
- assert(op == TOK.lessThan || op == TOK.lessOrEqual || op == TOK.greaterThan || op == TOK.greaterOrEqual);
+ assert(op == EXP.lessThan || op == EXP.lessOrEqual || op == EXP.greaterThan || op == EXP.greaterOrEqual);
}
override void accept(Visitor v)
@@ -6455,7 +6459,7 @@ extern (C++) final class InExp : BinExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.in_, __traits(classInstanceSize, InExp), e1, e2);
+ super(loc, EXP.in_, __traits(classInstanceSize, InExp), e1, e2);
}
override void accept(Visitor v)
@@ -6471,7 +6475,7 @@ extern (C++) final class RemoveExp : BinExp
{
extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
- super(loc, TOK.remove, __traits(classInstanceSize, RemoveExp), e1, e2);
+ super(loc, EXP.remove, __traits(classInstanceSize, RemoveExp), e1, e2);
type = Type.tbool;
}
@@ -6484,16 +6488,16 @@ extern (C++) final class RemoveExp : BinExp
/***********************************************************
* `==` and `!=`
*
- * TOK.equal and TOK.notEqual
+ * EXP.equal and EXP.notEqual
*
* http://dlang.org/spec/expression.html#equality_expressions
*/
extern (C++) final class EqualExp : BinExp
{
- extern (D) this(TOK op, const ref Loc loc, Expression e1, Expression e2)
+ extern (D) this(EXP op, const ref Loc loc, Expression e1, Expression e2)
{
super(loc, op, __traits(classInstanceSize, EqualExp), e1, e2);
- assert(op == TOK.equal || op == TOK.notEqual);
+ assert(op == EXP.equal || op == EXP.notEqual);
}
override void accept(Visitor v)
@@ -6505,16 +6509,16 @@ extern (C++) final class EqualExp : BinExp
/***********************************************************
* `is` and `!is`
*
- * TOK.identity and TOK.notIdentity
+ * EXP.identity and EXP.notIdentity
*
* http://dlang.org/spec/expression.html#identity_expressions
*/
extern (C++) final class IdentityExp : BinExp
{
- extern (D) this(TOK op, const ref Loc loc, Expression e1, Expression e2)
+ extern (D) this(EXP op, const ref Loc loc, Expression e1, Expression e2)
{
super(loc, op, __traits(classInstanceSize, IdentityExp), e1, e2);
- assert(op == TOK.identity || op == TOK.notIdentity);
+ assert(op == EXP.identity || op == EXP.notIdentity);
}
override void accept(Visitor v)
@@ -6534,7 +6538,7 @@ extern (C++) final class CondExp : BinExp
extern (D) this(const ref Loc loc, Expression econd, Expression e1, Expression e2)
{
- super(loc, TOK.question, __traits(classInstanceSize, CondExp), e1, e2);
+ super(loc, EXP.question, __traits(classInstanceSize, CondExp), e1, e2);
this.econd = econd;
}
@@ -6623,9 +6627,9 @@ extern (C++) final class CondExp : BinExp
//printf("\t++v = %s, v.edtor = %s\n", v.toChars(), v.edtor.toChars());
Expression ve = new VarExp(vcond.loc, vcond);
if (isThen)
- v.edtor = new LogicalExp(v.edtor.loc, TOK.andAnd, ve, v.edtor);
+ v.edtor = new LogicalExp(v.edtor.loc, EXP.andAnd, ve, v.edtor);
else
- v.edtor = new LogicalExp(v.edtor.loc, TOK.orOr, ve, v.edtor);
+ v.edtor = new LogicalExp(v.edtor.loc, EXP.orOr, ve, v.edtor);
v.edtor = v.edtor.expressionSemantic(sc);
//printf("\t--v = %s, v.edtor = %s\n", v.toChars(), v.edtor.toChars());
}
@@ -6649,18 +6653,18 @@ extern (C++) final class CondExp : BinExp
}
/// Returns: if this token is the `op` for a derived `DefaultInitExp` class.
-bool isDefaultInitOp(TOK op) pure nothrow @safe @nogc
+bool isDefaultInitOp(EXP op) pure nothrow @safe @nogc
{
- return op == TOK.prettyFunction || op == TOK.functionString ||
- op == TOK.line || op == TOK.moduleString ||
- op == TOK.file || op == TOK.fileFullPath ;
+ return op == EXP.prettyFunction || op == EXP.functionString ||
+ op == EXP.line || op == EXP.moduleString ||
+ op == EXP.file || op == EXP.fileFullPath ;
}
/***********************************************************
*/
extern (C++) class DefaultInitExp : Expression
{
- extern (D) this(const ref Loc loc, TOK op, int size)
+ extern (D) this(const ref Loc loc, EXP op, int size)
{
super(loc, op, size);
}
@@ -6675,7 +6679,7 @@ extern (C++) class DefaultInitExp : Expression
*/
extern (C++) final class FileInitExp : DefaultInitExp
{
- extern (D) this(const ref Loc loc, TOK tok)
+ extern (D) this(const ref Loc loc, EXP tok)
{
super(loc, tok, __traits(classInstanceSize, FileInitExp));
}
@@ -6684,7 +6688,7 @@ extern (C++) final class FileInitExp : DefaultInitExp
{
//printf("FileInitExp::resolve() %s\n", toChars());
const(char)* s;
- if (op == TOK.fileFullPath)
+ if (op == EXP.fileFullPath)
s = FileName.toAbsolute(loc.isValid() ? loc.filename : sc._module.srcfile.toChars());
else
s = loc.isValid() ? loc.filename : sc._module.ident.toChars();
@@ -6707,7 +6711,7 @@ extern (C++) final class LineInitExp : DefaultInitExp
{
extern (D) this(const ref Loc loc)
{
- super(loc, TOK.line, __traits(classInstanceSize, LineInitExp));
+ super(loc, EXP.line, __traits(classInstanceSize, LineInitExp));
}
override Expression resolveLoc(const ref Loc loc, Scope* sc)
@@ -6729,7 +6733,7 @@ extern (C++) final class ModuleInitExp : DefaultInitExp
{
extern (D) this(const ref Loc loc)
{
- super(loc, TOK.moduleString, __traits(classInstanceSize, ModuleInitExp));
+ super(loc, EXP.moduleString, __traits(classInstanceSize, ModuleInitExp));
}
override Expression resolveLoc(const ref Loc loc, Scope* sc)
@@ -6753,7 +6757,7 @@ extern (C++) final class FuncInitExp : DefaultInitExp
{
extern (D) this(const ref Loc loc)
{
- super(loc, TOK.functionString, __traits(classInstanceSize, FuncInitExp));
+ super(loc, EXP.functionString, __traits(classInstanceSize, FuncInitExp));
}
override Expression resolveLoc(const ref Loc loc, Scope* sc)
@@ -6783,7 +6787,7 @@ extern (C++) final class PrettyFuncInitExp : DefaultInitExp
{
extern (D) this(const ref Loc loc)
{
- super(loc, TOK.prettyFunction, __traits(classInstanceSize, PrettyFuncInitExp));
+ super(loc, EXP.prettyFunction, __traits(classInstanceSize, PrettyFuncInitExp));
}
override Expression resolveLoc(const ref Loc loc, Scope* sc)
@@ -6828,7 +6832,7 @@ extern (C++) final class ObjcClassReferenceExp : Expression
extern (D) this(const ref Loc loc, ClassDeclaration classDeclaration)
{
- super(loc, TOK.objcClassReference,
+ super(loc, EXP.objcClassReference,
__traits(classInstanceSize, ObjcClassReferenceExp));
this.classDeclaration = classDeclaration;
type = objc.getRuntimeMetaclass(classDeclaration).getType();
@@ -6852,7 +6856,7 @@ extern (C++) final class GenericExp : Expression
extern (D) this(const ref Loc loc, Expression cntlExp, Types* types, Expressions* exps)
{
- super(loc, TOK._Generic, __traits(classInstanceSize, GenericExp));
+ super(loc, EXP._Generic, __traits(classInstanceSize, GenericExp));
this.cntlExp = cntlExp;
this.types = types;
this.exps = exps;
@@ -6883,18 +6887,18 @@ extern(D) Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag
{
switch(exp.op)
{
- case TOK.variable:
+ case EXP.variable:
auto varExp = cast(VarExp)exp;
//printf("VarExp::checkModifiable %s", varExp.toChars());
assert(varExp.type);
return varExp.var.checkModify(varExp.loc, sc, null, flag);
- case TOK.dotVariable:
+ case EXP.dotVariable:
auto dotVarExp = cast(DotVarExp)exp;
//printf("DotVarExp::checkModifiable %s %s\n", dotVarExp.toChars(), dotVarExp.type.toChars());
- if (dotVarExp.e1.op == TOK.this_)
+ if (dotVarExp.e1.op == EXP.this_)
return dotVarExp.var.checkModify(dotVarExp.loc, sc, dotVarExp.e1, flag);
/* https://issues.dlang.org/show_bug.cgi?id=12764
@@ -6925,13 +6929,13 @@ extern(D) Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag
onlyUnion = false;
// Another DotVarExp left?
- if (!dve.e1 || dve.e1.op != TOK.dotVariable)
+ if (!dve.e1 || dve.e1.op != EXP.dotVariable)
break;
dve = cast(DotVarExp) dve.e1;
}
- if (dve.e1.op == TOK.this_)
+ if (dve.e1.op == EXP.this_)
{
scope v = dve.var.isVarDeclaration();
/* if v is a struct member field with no initializer, no default construction
@@ -6968,7 +6972,7 @@ extern(D) Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag
//printf("\te1 = %s\n", e1.toChars());
return dotVarExp.e1.checkModifiable(sc, flag);
- case TOK.star:
+ case EXP.star:
auto ptrExp = cast(PtrExp)exp;
if (auto se = ptrExp.e1.isSymOffExp())
{
@@ -6980,33 +6984,33 @@ extern(D) Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag
}
return Modifiable.yes;
- case TOK.slice:
+ case EXP.slice:
auto sliceExp = cast(SliceExp)exp;
//printf("SliceExp::checkModifiable %s\n", sliceExp.toChars());
auto e1 = sliceExp.e1;
- if (e1.type.ty == Tsarray || (e1.op == TOK.index && e1.type.ty != Tarray) || e1.op == TOK.slice)
+ if (e1.type.ty == Tsarray || (e1.op == EXP.index && e1.type.ty != Tarray) || e1.op == EXP.slice)
{
return e1.checkModifiable(sc, flag);
}
return Modifiable.yes;
- case TOK.comma:
+ case EXP.comma:
return (cast(CommaExp)exp).e2.checkModifiable(sc, flag);
- case TOK.index:
+ case EXP.index:
auto indexExp = cast(IndexExp)exp;
auto e1 = indexExp.e1;
if (e1.type.ty == Tsarray ||
e1.type.ty == Taarray ||
- (e1.op == TOK.index && e1.type.ty != Tarray) ||
- e1.op == TOK.slice)
+ (e1.op == EXP.index && e1.type.ty != Tarray) ||
+ e1.op == EXP.slice)
{
return e1.checkModifiable(sc, flag);
}
return Modifiable.yes;
- case TOK.question:
+ case EXP.question:
auto condExp = cast(CondExp)exp;
if (condExp.e1.checkModifiable(sc, flag) != Modifiable.no
&& condExp.e2.checkModifiable(sc, flag) != Modifiable.no)
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index 691364cb265..411822cb9d6 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -18,6 +18,7 @@
#include "tokens.h"
#include "root/dcompat.h"
+#include "root/optional.h"
class Type;
class TypeVector;
@@ -76,7 +77,7 @@ enum class ModifyFlags
class Expression : public ASTNode
{
public:
- TOK op; // to minimize use of dynamic_cast
+ EXP op; // to minimize use of dynamic_cast
unsigned char size; // # of bytes in Expression so we can copy() it
unsigned char parens; // if this is a parenthesized expression
Type *type; // !=NULL means that semantic() has been run
@@ -121,8 +122,7 @@ public:
// A compile-time result is required. Give an error if not possible
Expression *ctfeInterpret();
int isConst();
- virtual bool isBool(bool result);
-
+ virtual Optional<bool> toBool();
virtual bool hasCode()
{
return true;
@@ -249,7 +249,7 @@ public:
real_t toReal();
real_t toImaginary();
complex_t toComplex();
- bool isBool(bool result);
+ Optional<bool> toBool();
Expression *toLvalue(Scope *sc, Expression *e);
void accept(Visitor *v) { v->visit(this); }
dinteger_t getInteger() { return value; }
@@ -280,7 +280,7 @@ public:
real_t toReal();
real_t toImaginary();
complex_t toComplex();
- bool isBool(bool result);
+ Optional<bool> toBool();
void accept(Visitor *v) { v->visit(this); }
};
@@ -297,7 +297,7 @@ public:
real_t toReal();
real_t toImaginary();
complex_t toComplex();
- bool isBool(bool result);
+ Optional<bool> toBool();
void accept(Visitor *v) { v->visit(this); }
};
@@ -336,7 +336,7 @@ public:
VarDeclaration *var;
ThisExp *syntaxCopy();
- bool isBool(bool result);
+ Optional<bool> toBool();
bool isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
@@ -353,7 +353,7 @@ class NullExp : public Expression
{
public:
bool equals(const RootObject *o) const;
- bool isBool(bool result);
+ Optional<bool> toBool();
StringExp *toStringExp();
void accept(Visitor *v) { v->visit(this); }
};
@@ -374,7 +374,7 @@ public:
bool equals(const RootObject *o) const;
StringExp *toStringExp();
StringExp *toUTF8(Scope *sc);
- bool isBool(bool result);
+ Optional<bool> toBool();
bool isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
@@ -420,7 +420,7 @@ public:
bool equals(const RootObject *o) const;
Expression *getElement(d_size_t i); // use opIndex instead
Expression *opIndex(d_size_t i);
- bool isBool(bool result);
+ Optional<bool> toBool();
StringExp *toStringExp();
void accept(Visitor *v) { v->visit(this); }
@@ -435,7 +435,7 @@ public:
bool equals(const RootObject *o) const;
AssocArrayLiteralExp *syntaxCopy();
- bool isBool(bool result);
+ Optional<bool> toBool();
void accept(Visitor *v) { v->visit(this); }
};
@@ -567,7 +567,7 @@ class SymOffExp : public SymbolExp
public:
dinteger_t offset;
- bool isBool(bool result);
+ Optional<bool> toBool();
void accept(Visitor *v) { v->visit(this); }
};
@@ -926,7 +926,7 @@ public:
bool isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
- bool isBool(bool result);
+ Optional<bool> toBool();
void accept(Visitor *v) { v->visit(this); }
};
@@ -997,7 +997,7 @@ public:
bool isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
- bool isBool(bool result);
+ Optional<bool> toBool();
Expression *addDtorHook(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
};
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 8e152d6a1fc..ec2bce47b47 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -108,7 +108,7 @@ bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps)
// allowed to contain types as well as expressions
auto e4 = ctfeInterpretForPragmaMsg(e3);
- if (!e4 || e4.op == TOK.error)
+ if (!e4 || e4.op == EXP.error)
return true;
// expand tuple
@@ -153,14 +153,14 @@ StringExp semanticString(Scope *sc, Expression exp, const char* s)
exp = resolveProperties(sc, exp);
sc = sc.endCTFE();
- if (exp.op == TOK.error)
+ if (exp.op == EXP.error)
return null;
auto e = exp;
if (exp.type.isString())
{
e = e.ctfeInterpret();
- if (e.op == TOK.error)
+ if (e.op == EXP.error)
return null;
}
@@ -215,7 +215,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
if (i == 0)
*pe0 = extractOpDollarSideEffect(sc, ae);
- if (e.op == TOK.interval && !(slice && slice.isTemplateDeclaration()))
+ if (e.op == EXP.interval && !(slice && slice.isTemplateDeclaration()))
{
Lfallback:
if (ae.arguments.dim == 1)
@@ -273,7 +273,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
ae.error("`%s` has no value", e.toChars());
e = ErrorExp.get();
}
- if (e.op == TOK.error)
+ if (e.op == EXP.error)
return e;
(*ae.arguments)[i] = e;
@@ -342,9 +342,9 @@ bool arrayExpressionSemantic(Expressions* exps, Scope* sc, bool preserveErrors =
if (e)
{
auto e2 = e.expressionSemantic(sc);
- if (e2.op == TOK.error)
+ if (e2.op == EXP.error)
err = true;
- if (preserveErrors || e2.op != TOK.error)
+ if (preserveErrors || e2.op != EXP.error)
e = e2;
}
}
@@ -531,7 +531,7 @@ private Expression resolveUFCS(Scope* sc, CallExp ce)
{
if (Expression ey = die.semanticY(sc, 1))
{
- if (ey.op == TOK.error)
+ if (ey.op == EXP.error)
return ey;
ce.e1 = ey;
if (isDotOpDispatch(ey))
@@ -1024,7 +1024,7 @@ L1:
Type t = e1.type.toBasetype();
//printf("e1.type = %s, var.type = %s\n", e1.type.toChars(), var.type.toChars());
- if (e1.op == TOK.objcClassReference)
+ if (e1.op == EXP.objcClassReference)
{
// We already have an Objective-C class reference, just use that as 'this'.
return e1;
@@ -1040,7 +1040,7 @@ L1:
* class A { inc(alias m)() { ++m; } } // `m` needs `this` of `B`
* class B {int m; inc() { new A().inc!m(); } }
*/
- if (e1.op == TOK.this_)
+ if (e1.op == EXP.this_)
{
FuncDeclaration f = hasThis(sc);
if (f && f.isThis2)
@@ -1051,7 +1051,7 @@ L1:
e1 = new PtrExp(loc, e1);
e1 = new IndexExp(loc, e1, IntegerExp.literal!1);
e1 = getThisSkipNestedFuncs(loc, sc, f.toParent2(), ad, e1, t, var);
- if (e1.op == TOK.error)
+ if (e1.op == EXP.error)
return e1;
goto L1;
}
@@ -1089,7 +1089,7 @@ L1:
// Skip up over nested functions, and get the enclosing
// class type.
e1 = getThisSkipNestedFuncs(loc, sc, tcd.toParentP(ad), ad, e1, t, var);
- if (e1.op == TOK.error)
+ if (e1.op == EXP.error)
return e1;
goto L1;
}
@@ -1110,7 +1110,7 @@ L1:
*/
private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = null)
{
- //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token.toChars(e1.op), e1.toChars(), e2 ? e2.toChars() : null);
+ //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", EXPtoString(e1.op).ptr, e1.toChars(), e2 ? e2.toChars() : null);
Loc loc = e1.loc;
OverloadSet os;
@@ -1138,7 +1138,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
if (e2)
{
e2 = e2.expressionSemantic(sc);
- if (e2.op == TOK.error)
+ if (e2.op == EXP.error)
return ErrorExp.get();
e2 = resolveProperties(sc, e2);
@@ -1233,7 +1233,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
tthis = null;
goto Lfd;
}
- else if (e1.op == TOK.dotVariable && e1.type && (e1.type.toBasetype().ty == Tfunction || (cast(DotVarExp)e1).var.isOverDeclaration()))
+ else if (e1.op == EXP.dotVariable && e1.type && (e1.type.toBasetype().ty == Tfunction || (cast(DotVarExp)e1).var.isOverDeclaration()))
{
DotVarExp dve = cast(DotVarExp)e1;
s = dve.var;
@@ -1241,11 +1241,11 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
tthis = dve.e1.type;
goto Lfd;
}
- else if (sc && sc.flags & SCOPE.Cfile && e1.op == TOK.variable && !e2)
+ else if (sc && sc.flags & SCOPE.Cfile && e1.op == EXP.variable && !e2)
{
// ImportC: do not implicitly call function if no ( ) are present
}
- else if (e1.op == TOK.variable && e1.type && (e1.type.toBasetype().ty == Tfunction || (cast(VarExp)e1).var.isOverDeclaration()))
+ else if (e1.op == EXP.variable && e1.type && (e1.type.toBasetype().ty == Tfunction || (cast(VarExp)e1).var.isOverDeclaration()))
{
s = (cast(VarExp)e1).var;
tiargs = null;
@@ -1255,7 +1255,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
if (e2)
{
e2 = e2.expressionSemantic(sc);
- if (e2.op == TOK.error)
+ if (e2.op == EXP.error)
return ErrorExp.get();
e2 = resolveProperties(sc, e2);
@@ -1316,7 +1316,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
if (e2)
goto Leprop;
}
- if (e1.op == TOK.variable)
+ if (e1.op == EXP.variable)
{
VarExp ve = cast(VarExp)e1;
VarDeclaration v = ve.var.isVarDeclaration();
@@ -1326,7 +1326,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
if (e2)
return null;
- if (e1.type && e1.op != TOK.type) // function type is not a property
+ if (e1.type && e1.op != EXP.type) // 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
@@ -1337,13 +1337,13 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
Expression e = new CallExp(loc, e1);
return e.expressionSemantic(sc);
}
- else if (e1.op == TOK.dotVariable)
+ else if (e1.op == EXP.dotVariable)
{
// Check for reading overlapped pointer field in @safe code.
if (checkUnsafeAccess(sc, e1, true, true))
return ErrorExp.get();
}
- else if (e1.op == TOK.call)
+ else if (e1.op == EXP.call)
{
CallExp ce = cast(CallExp)e1;
// Check for reading overlapped pointer field in @safe code.
@@ -1409,7 +1409,7 @@ private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps)
t0 = Type.terror;
continue;
}
- if (e.op == TOK.type)
+ if (e.op == EXP.type)
{
foundType = true; // do not break immediately, there might be more errors
e.checkValue(); // report an error "type T has no value"
@@ -1440,9 +1440,9 @@ private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps)
condexp.e2 = e;
condexp.loc = e.loc;
Expression ex = condexp.expressionSemantic(sc);
- if (ex.op == TOK.error)
+ if (ex.op == EXP.error)
e = ex;
- else if (e.op == TOK.function_ || e.op == TOK.delegate_)
+ else if (e.op == EXP.function_ || e.op == EXP.delegate_)
{
// https://issues.dlang.org/show_bug.cgi?id=21285
// Functions and delegates don't convert correctly with castTo below
@@ -1458,7 +1458,7 @@ private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps)
}
e0 = e;
t0 = e.type;
- if (e.op != TOK.error)
+ if (e.op != EXP.error)
exps[i] = e;
}
@@ -1477,7 +1477,7 @@ private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps)
continue;
e = e.implicitCastTo(sc, t0);
- if (e.op == TOK.error)
+ if (e.op == EXP.error)
{
/* https://issues.dlang.org/show_bug.cgi?id=13024
* a workaround for the bug in typeMerge -
@@ -1491,52 +1491,52 @@ private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps)
return t0;
}
-private Expression opAssignToOp(const ref Loc loc, TOK op, Expression e1, Expression e2)
+private Expression opAssignToOp(const ref Loc loc, EXP op, Expression e1, Expression e2)
{
Expression e;
switch (op)
{
- case TOK.addAssign:
+ case EXP.addAssign:
e = new AddExp(loc, e1, e2);
break;
- case TOK.minAssign:
+ case EXP.minAssign:
e = new MinExp(loc, e1, e2);
break;
- case TOK.mulAssign:
+ case EXP.mulAssign:
e = new MulExp(loc, e1, e2);
break;
- case TOK.divAssign:
+ case EXP.divAssign:
e = new DivExp(loc, e1, e2);
break;
- case TOK.modAssign:
+ case EXP.modAssign:
e = new ModExp(loc, e1, e2);
break;
- case TOK.andAssign:
+ case EXP.andAssign:
e = new AndExp(loc, e1, e2);
break;
- case TOK.orAssign:
+ case EXP.orAssign:
e = new OrExp(loc, e1, e2);
break;
- case TOK.xorAssign:
+ case EXP.xorAssign:
e = new XorExp(loc, e1, e2);
break;
- case TOK.leftShiftAssign:
+ case EXP.leftShiftAssign:
e = new ShlExp(loc, e1, e2);
break;
- case TOK.rightShiftAssign:
+ case EXP.rightShiftAssign:
e = new ShrExp(loc, e1, e2);
break;
- case TOK.unsignedRightShiftAssign:
+ case EXP.unsignedRightShiftAssign:
e = new UshrExp(loc, e1, e2);
break;
@@ -1559,9 +1559,9 @@ private Expression rewriteOpAssign(BinExp exp)
{
Expression e;
- assert(exp.e1.op == TOK.arrayLength);
+ assert(exp.e1.op == EXP.arrayLength);
ArrayLengthExp ale = cast(ArrayLengthExp)exp.e1;
- if (ale.e1.op == TOK.variable)
+ if (ale.e1.op == EXP.variable)
{
e = opAssignToOp(exp.loc, exp.op, ale, exp.e2);
e = new AssignExp(exp.loc, ale.syntaxCopy(), e);
@@ -1604,12 +1604,12 @@ private bool preFunctionParameters(Scope* sc, Expressions* exps, const bool repo
Expression arg = (*exps)[i];
arg = resolveProperties(sc, arg);
arg = arg.arrayFuncConv(sc);
- if (arg.op == TOK.type)
+ if (arg.op == EXP.type)
{
// for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
arg = resolveAliasThis(sc, arg);
- if (arg.op == TOK.type)
+ if (arg.op == EXP.type)
{
if (reportErrors)
{
@@ -2056,7 +2056,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
/* Argument value cannot escape from the called function.
*/
Expression a = arg;
- if (a.op == TOK.cast_)
+ if (a.op == EXP.cast_)
a = (cast(CastExp)a).e1;
ArrayLiteralExp ale;
@@ -2071,7 +2071,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
arg = CommaExp.combine(declareTmp, castToSlice);
arg = arg.expressionSemantic(sc);
}
- else if (a.op == TOK.function_)
+ else if (a.op == EXP.function_)
{
/* Function literals can only appear once, so if this
* appearance was scoped, there cannot be any others.
@@ -2079,14 +2079,14 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
FuncExp fe = cast(FuncExp)a;
fe.fd.tookAddressOf = 0;
}
- else if (a.op == TOK.delegate_)
+ else if (a.op == EXP.delegate_)
{
/* 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 == TOK.variable)
+ if (de.e1.op == EXP.variable)
{
VarExp ve = cast(VarExp)de.e1;
FuncDeclaration f = ve.var.isFuncDeclaration();
@@ -2185,7 +2185,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
//arg = callCpCtor(sc, arg);
}
// Give error for overloaded function addresses
- if (arg.op == TOK.symbolOffset)
+ if (arg.op == EXP.symbolOffset)
{
SymOffExp se = cast(SymOffExp)arg;
if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique())
@@ -2357,7 +2357,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
// edtor => (__gate || edtor)
assert(tmp.edtor);
Expression e = tmp.edtor;
- e = new LogicalExp(e.loc, TOK.orOr, new VarExp(e.loc, gate), e);
+ e = new LogicalExp(e.loc, EXP.orOr, new VarExp(e.loc, gate), e);
tmp.edtor = e.expressionSemantic(sc);
//printf("edtor: %s\n", tmp.edtor.toChars());
}
@@ -2766,7 +2766,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
// Try Type.opDispatch (so the static version)
- else if (ss.withstate.exp && ss.withstate.exp.op == TOK.type)
+ else if (ss.withstate.exp && ss.withstate.exp.op == EXP.type)
{
if (Type t = ss.withstate.exp.isTypeExp().type)
{
@@ -3077,7 +3077,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.error("`%s` has no value", e.toChars());
err = true;
}
- else if (e.op == TOK.error)
+ else if (e.op == EXP.error)
err = true;
else
(*exp.exps)[i] = e;
@@ -3110,7 +3110,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (e.basis)
e.basis = e.basis.expressionSemantic(sc);
- if (arrayExpressionSemantic(e.elements, sc) || (e.basis && e.basis.op == TOK.error))
+ if (arrayExpressionSemantic(e.elements, sc) || (e.basis && e.basis.op == EXP.error))
return setError();
expandTuples(e.elements);
@@ -3474,7 +3474,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (exp.thisexp)
{
exp.thisexp = exp.thisexp.expressionSemantic(sc);
- if (exp.thisexp.op == TOK.error)
+ if (exp.thisexp.op == EXP.error)
return setError();
cdthis = exp.thisexp.type.isClassHandle();
@@ -3619,7 +3619,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
exp.thisexp = exp.thisexp.expressionSemantic(sc);
- if (exp.thisexp.op == TOK.error)
+ if (exp.thisexp.op == EXP.error)
return setError();
cdthis = exp.thisexp.type.isClassHandle();
}
@@ -3666,9 +3666,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (AggregateDeclaration ad2 = cd.isMember2())
{
Expression te = new ThisExp(exp.loc).expressionSemantic(sc);
- if (te.op != TOK.error)
+ if (te.op != EXP.error)
te = getRightThis(exp.loc, sc, ad2, te, cd);
- if (te.op == TOK.error)
+ if (te.op == EXP.error)
{
exp.error("need `this` of type `%s` needed to `new` nested class `%s`", ad2.toChars(), cd.toChars());
return setError();
@@ -3764,7 +3764,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
- if (sd.ctor && nargs)
+ if (sd.hasRegularCtor() && nargs)
{
FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard);
if (!f || f.errors)
@@ -3842,10 +3842,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Expression arg = (*exp.arguments)[i];
arg = resolveProperties(sc, arg);
arg = arg.implicitCastTo(sc, Type.tsize_t);
- if (arg.op == TOK.error)
+ if (arg.op == EXP.error)
return setError();
arg = arg.optimize(WANTvalue);
- if (arg.op == TOK.int64 && cast(sinteger_t)arg.toInteger() < 0)
+ if (arg.op == EXP.int64 && cast(sinteger_t)arg.toInteger() < 0)
{
exp.error("negative array index `%s`", arg.toChars());
return setError();
@@ -4104,7 +4104,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* auto foo(void function() fp) { return 1; }
* assert(foo({}) == 1);
*
- * So, should keep fd.tok == TOKreserve if fd.treq == NULL.
+ * So, should keep fd.tok == TOK.reserve if fd.treq == NULL.
*/
if (exp.fd.treq && exp.fd.treq.ty == Tpointer)
{
@@ -4135,7 +4135,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
for (size_t k = 0; k < arguments.dim; k++)
{
Expression checkarg = (*arguments)[k];
- if (checkarg.op == TOK.error)
+ if (checkarg.op == EXP.error)
return checkarg;
}
@@ -4213,7 +4213,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Type tthis = null;
Expression e1org = exp.e1;
- if (exp.e1.op == TOK.comma)
+ if (exp.e1.op == EXP.comma)
{
/* Rewrite (a,b)(args) as (a,(b(args)))
*/
@@ -4223,14 +4223,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = ce.expressionSemantic(sc);
return;
}
- if (exp.e1.op == TOK.delegate_)
+ if (exp.e1.op == EXP.delegate_)
{
DelegateExp de = cast(DelegateExp)exp.e1;
exp.e1 = new DotVarExp(de.loc, de.e1, de.func, de.hasOverloads);
visit(exp);
return;
}
- if (exp.e1.op == TOK.function_)
+ if (exp.e1.op == EXP.function_)
{
if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments))
return setError();
@@ -4238,7 +4238,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// Run e1 semantic even if arguments have any errors
FuncExp fe = cast(FuncExp)exp.e1;
exp.e1 = callExpSemantic(fe, sc, exp.arguments);
- if (exp.e1.op == TOK.error)
+ if (exp.e1.op == EXP.error)
{
result = exp.e1;
return;
@@ -4254,7 +4254,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* This recognizes:
* foo!(tiargs)(funcargs)
*/
- if (exp.e1.op == TOK.scope_)
+ if (exp.e1.op == EXP.scope_)
{
ScopeExp se = cast(ScopeExp)exp.e1;
TemplateInstance ti = se.sds.isTemplateInstance();
@@ -4288,7 +4288,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
else
{
Expression e1x = exp.e1.expressionSemantic(sc);
- if (e1x.op == TOK.error)
+ if (e1x.op == EXP.error)
{
result = e1x;
return;
@@ -4302,7 +4302,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* expr.foo!(tiargs)(funcargs)
*/
Ldotti:
- if (exp.e1.op == TOK.dotTemplateInstance)
+ if (exp.e1.op == EXP.dotTemplateInstance)
{
DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)exp.e1;
TemplateInstance ti = se.ti;
@@ -4330,7 +4330,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
else
{
Expression e1x = exp.e1.expressionSemantic(sc);
- if (e1x.op == TOK.error)
+ if (e1x.op == EXP.error)
{
result = e1x;
return;
@@ -4343,13 +4343,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Lagain:
//printf("Lagain: %s\n", toChars());
exp.f = null;
- if (exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_)
+ if (exp.e1.op == EXP.this_ || exp.e1.op == EXP.super_)
{
// semantic() run later for these
}
else
{
- if (exp.e1.op == TOK.dotIdentifier)
+ if (exp.e1.op == EXP.dotIdentifier)
{
DotIdExp die = cast(DotIdExp)exp.e1;
exp.e1 = die.expressionSemantic(sc);
@@ -4357,7 +4357,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* We handle such earlier, so go back.
* Note that in the rewrite, we carefully did not run semantic() on e1
*/
- if (exp.e1.op == TOK.dotTemplateInstance)
+ if (exp.e1.op == EXP.dotTemplateInstance)
{
goto Ldotti;
}
@@ -4382,7 +4382,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* Look for e1 being a lazy parameter
*/
- if (exp.e1.op == TOK.variable)
+ if (exp.e1.op == EXP.variable)
{
VarExp ve = cast(VarExp)exp.e1;
if (ve.var.storage_class & STC.lazy_)
@@ -4400,29 +4400,29 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
}
- if (exp.e1.op == TOK.symbolOffset && (cast(SymOffExp)exp.e1).hasOverloads)
+ if (exp.e1.op == EXP.symbolOffset && (cast(SymOffExp)exp.e1).hasOverloads)
{
SymOffExp se = cast(SymOffExp)exp.e1;
exp.e1 = new VarExp(se.loc, se.var, true);
exp.e1 = exp.e1.expressionSemantic(sc);
}
- else if (exp.e1.op == TOK.dot)
+ else if (exp.e1.op == EXP.dot)
{
DotExp de = cast(DotExp)exp.e1;
- if (de.e2.op == TOK.overloadSet)
+ if (de.e2.op == EXP.overloadSet)
{
ethis = de.e1;
tthis = de.e1.type;
exp.e1 = de.e2;
}
}
- else if (exp.e1.op == TOK.star && exp.e1.type.ty == Tfunction)
+ else if (exp.e1.op == EXP.star && exp.e1.type.ty == Tfunction)
{
// Rewrite (*fp)(arguments) to fp(arguments)
exp.e1 = (cast(PtrExp)exp.e1).e1;
}
- else if (exp.e1.op == TOK.type && (sc && sc.flags & SCOPE.Cfile))
+ else if (exp.e1.op == EXP.type && (sc && sc.flags & SCOPE.Cfile))
{
const numArgs = exp.arguments ? exp.arguments.length : 0;
if (e1org.parens && numArgs >= 1)
@@ -4480,7 +4480,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Type t1 = exp.e1.type ? exp.e1.type.toBasetype() : null;
- if (exp.e1.op == TOK.error)
+ if (exp.e1.op == EXP.error)
{
result = exp.e1;
return;
@@ -4515,7 +4515,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
// First look for constructor
- if (exp.e1.op == TOK.type && sd.ctor)
+ if (exp.e1.op == EXP.type && sd.ctor)
{
if (!sd.noDefaultCtor && !(exp.arguments && exp.arguments.dim))
goto Lx;
@@ -4566,7 +4566,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (search_function(sd, Id.call))
goto L1;
// overload of opCall, therefore it's a call
- if (exp.e1.op != TOK.type)
+ if (exp.e1.op != EXP.type)
{
if (sd.aliasthis && !isRecursiveAliasThis(exp.att1, exp.e1.type))
{
@@ -4595,7 +4595,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = e;
return;
}
- else if (exp.e1.op == TOK.type && t1.isscalar())
+ else if (exp.e1.op == EXP.type && t1.isscalar())
{
Expression e;
@@ -4659,7 +4659,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
bool isSuper = false;
- if (exp.e1.op == TOK.dotVariable && t1.ty == Tfunction || exp.e1.op == TOK.dotTemplateDeclaration)
+ if (exp.e1.op == EXP.dotVariable && t1.ty == Tfunction || exp.e1.op == EXP.dotTemplateDeclaration)
{
UnaExp ue = cast(UnaExp)exp.e1;
@@ -4667,7 +4667,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
DotVarExp dve;
DotTemplateExp dte;
Dsymbol s;
- if (exp.e1.op == TOK.dotVariable)
+ if (exp.e1.op == EXP.dotVariable)
{
dve = cast(DotVarExp)exp.e1;
dte = null;
@@ -4703,7 +4703,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
AggregateDeclaration ad = exp.f.toParentLocal().isAggregateDeclaration();
ue.e1 = getRightThis(exp.loc, sc, ad, ue.e1, exp.f);
- if (ue.e1.op == TOK.error)
+ if (ue.e1.op == EXP.error)
{
result = ue.e1;
return;
@@ -4720,7 +4720,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* Cannot call public functions from inside invariant
* (because then the invariant would have infinite recursion)
*/
- if (sc.func && sc.func.isInvariantDeclaration() && ue.e1.op == TOK.this_ && exp.f.addPostInvariant())
+ if (sc.func && sc.func.isInvariantDeclaration() && ue.e1.op == EXP.this_ && exp.f.addPostInvariant())
{
exp.error("cannot call `public`/`export` function `%s` from invariant", exp.f.toChars());
return setError();
@@ -4737,7 +4737,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
if (ue1old.checkRightThis(sc))
return setError();
- if (exp.e1.op == TOK.dotVariable)
+ if (exp.e1.op == EXP.dotVariable)
{
dve.var = exp.f;
exp.e1.type = exp.f.type;
@@ -4746,7 +4746,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
exp.e1 = new DotVarExp(exp.loc, dte.e1, exp.f, false);
exp.e1 = exp.e1.expressionSemantic(sc);
- if (exp.e1.op == TOK.error)
+ if (exp.e1.op == EXP.error)
return setError();
ue = cast(UnaExp)exp.e1;
}
@@ -4764,12 +4764,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
ClassDeclaration cd = ue.e1.type.isClassHandle();
if (ad && cd && ad.isClassDeclaration())
{
- if (ue.e1.op == TOK.dotType)
+ if (ue.e1.op == EXP.dotType)
{
ue.e1 = (cast(DotTypeExp)ue.e1).e1;
exp.directcall = true;
}
- else if (ue.e1.op == TOK.super_)
+ else if (ue.e1.op == EXP.super_)
exp.directcall = true;
else if ((cd.storage_class & STC.final_) != 0) // https://issues.dlang.org/show_bug.cgi?id=14211
exp.directcall = true;
@@ -4791,12 +4791,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
t1 = exp.e1.type;
}
- else if (exp.e1.op == TOK.super_ || exp.e1.op == TOK.this_)
+ else if (exp.e1.op == EXP.super_ || exp.e1.op == EXP.this_)
{
auto ad = sc.func ? sc.func.isThis() : null;
auto cd = ad ? ad.isClassDeclaration() : null;
- isSuper = exp.e1.op == TOK.super_;
+ isSuper = exp.e1.op == EXP.super_;
if (isSuper)
{
// Base class constructor call
@@ -4858,7 +4858,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.e1 = new DotVarExp(exp.e1.loc, exp.e1, exp.f, false);
exp.e1 = exp.e1.expressionSemantic(sc);
// https://issues.dlang.org/show_bug.cgi?id=21095
- if (exp.e1.op == TOK.error)
+ if (exp.e1.op == EXP.error)
return setError();
t1 = exp.e1.type;
@@ -4870,7 +4870,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
}
}
- else if (exp.e1.op == TOK.overloadSet)
+ else if (exp.e1.op == EXP.overloadSet)
{
auto os = (cast(OverExp)exp.e1).vars;
exp.f = resolveOverloadSet(exp.loc, sc, os, tiargs, tthis, exp.arguments);
@@ -4897,7 +4897,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
const(char)* p;
Dsymbol s;
exp.f = null;
- if (exp.e1.op == TOK.function_)
+ if (exp.e1.op == EXP.function_)
{
// function literal that direct called is always inferred.
assert((cast(FuncExp)exp.e1).fd);
@@ -4917,7 +4917,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
tf = tfx;
p = "function pointer";
}
- else if (exp.e1.op == TOK.dotVariable && (cast(DotVarExp)exp.e1).var.isOverDeclaration())
+ else if (exp.e1.op == EXP.dotVariable && (cast(DotVarExp)exp.e1).var.isOverDeclaration())
{
DotVarExp dve = cast(DotVarExp)exp.e1;
exp.f = resolveFuncCall(exp.loc, sc, dve.var, tiargs, dve.e1.type, exp.arguments, FuncResolveFlag.overloadOnly);
@@ -4935,12 +4935,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = e.expressionSemantic(sc);
return;
}
- else if (exp.e1.op == TOK.variable && (cast(VarExp)exp.e1).var.isOverDeclaration())
+ else if (exp.e1.op == EXP.variable && (cast(VarExp)exp.e1).var.isOverDeclaration())
{
s = (cast(VarExp)exp.e1).var;
goto L2;
}
- else if (exp.e1.op == TOK.template_)
+ else if (exp.e1.op == EXP.template_)
{
s = (cast(TemplateExp)exp.e1).td;
L2:
@@ -5031,7 +5031,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
t1 = tf;
}
- else if (exp.e1.op == TOK.variable)
+ else if (exp.e1.op == EXP.variable)
{
// Do overload resolution
VarExp ve = cast(VarExp)exp.e1;
@@ -5188,9 +5188,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (AggregateDeclaration ad2 = exp.f.isMember2())
{
Expression te = new ThisExp(exp.loc).expressionSemantic(sc);
- if (te.op != TOK.error)
+ if (te.op != EXP.error)
te = getRightThis(exp.loc, sc, ad2, te, exp.f);
- if (te.op == TOK.error)
+ if (te.op == EXP.error)
{
exp.error("need `this` of type `%s` to call function `%s`", ad2.toChars(), exp.f.toChars());
return setError();
@@ -5368,7 +5368,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
ea = ea.expressionSemantic(sc);
ea = resolveProperties(sc, ea);
ta = ea.type;
- if (ea.op == TOK.type)
+ if (ea.op == EXP.type)
ea = null;
}
@@ -5644,7 +5644,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* If one of the default arguments was an error,
don't return an invalid tuple
*/
- if (e.tok2 == TOK.parameters && arg.defaultArg && arg.defaultArg.op == TOK.error)
+ if (e.tok2 == TOK.parameters && arg.defaultArg && arg.defaultArg.op == EXP.error)
return setError();
args.push(new Parameter(arg.storageClass, arg.type, (e.tok2 == TOK.parameters) ? arg.ident : null, (e.tok2 == TOK.parameters) ? arg.defaultArg : null, arg.userAttribDecl));
}
@@ -5819,7 +5819,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
- if (exp.e1.op == TOK.arrayLength)
+ if (exp.e1.op == EXP.arrayLength)
{
// arr.length op= e2;
e = rewriteOpAssign(exp);
@@ -5827,12 +5827,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = e;
return;
}
- if (exp.e1.op == TOK.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
+ if (exp.e1.op == EXP.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
{
if (checkNonAssignmentArrayOp(exp.e1))
return setError();
- if (exp.e1.op == TOK.slice)
+ if (exp.e1.op == EXP.slice)
(cast(SliceExp)exp.e1).arrayop = true;
// T[] op= ...
@@ -5869,16 +5869,16 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.e1.checkSharedAccess(sc))
return setError();
- int arith = (exp.op == TOK.addAssign || exp.op == TOK.minAssign || exp.op == TOK.mulAssign || exp.op == TOK.divAssign || exp.op == TOK.modAssign || exp.op == TOK.powAssign);
- int bitwise = (exp.op == TOK.andAssign || exp.op == TOK.orAssign || exp.op == TOK.xorAssign);
- int shift = (exp.op == TOK.leftShiftAssign || exp.op == TOK.rightShiftAssign || exp.op == TOK.unsignedRightShiftAssign);
+ int arith = (exp.op == EXP.addAssign || exp.op == EXP.minAssign || exp.op == EXP.mulAssign || exp.op == EXP.divAssign || exp.op == EXP.modAssign || exp.op == EXP.powAssign);
+ int bitwise = (exp.op == EXP.andAssign || exp.op == EXP.orAssign || exp.op == EXP.xorAssign);
+ int shift = (exp.op == EXP.leftShiftAssign || exp.op == EXP.rightShiftAssign || exp.op == EXP.unsignedRightShiftAssign);
if (bitwise && exp.type.toBasetype().ty == Tbool)
exp.e2 = exp.e2.implicitCastTo(sc, exp.type);
else if (exp.checkNoBool())
return setError();
- if ((exp.op == TOK.addAssign || exp.op == TOK.minAssign) && exp.e1.type.toBasetype().ty == Tpointer && exp.e2.type.toBasetype().isintegral())
+ if ((exp.op == EXP.addAssign || exp.op == EXP.minAssign) && exp.e1.type.toBasetype().ty == Tpointer && exp.e2.type.toBasetype().isintegral())
{
result = scaleFactor(exp, sc);
return;
@@ -5907,17 +5907,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
- if (exp.e1.op == TOK.error || exp.e2.op == TOK.error)
+ if (exp.e1.op == EXP.error || exp.e2.op == EXP.error)
return setError();
e = exp.checkOpAssignTypes(sc);
- if (e.op == TOK.error)
+ if (e.op == EXP.error)
{
result = e;
return;
}
- assert(e.op == TOK.assign || e == exp);
+ assert(e.op == EXP.assign || e == exp);
result = (cast(BinExp)e).reorderSettingAAElem(sc);
}
@@ -6209,9 +6209,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Objects* tiargs;
Loc loc = exp.e1.loc;
- const tok = exp.e1.op;
+ const op = exp.e1.op;
bool isEqualsCallExpression;
- if (tok == TOK.call)
+ if (op == EXP.call)
{
const callExp = cast(CallExp) exp.e1;
@@ -6225,11 +6225,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
callExpIdent == Id.eq;
}
}
- if (tok == TOK.equal || tok == TOK.notEqual ||
- tok == TOK.lessThan || tok == TOK.greaterThan ||
- tok == TOK.lessOrEqual || tok == TOK.greaterOrEqual ||
- tok == TOK.identity || tok == TOK.notIdentity ||
- tok == TOK.in_ ||
+ if (op == EXP.equal || op == EXP.notEqual ||
+ op == EXP.lessThan || op == EXP.greaterThan ||
+ op == EXP.lessOrEqual || op == EXP.greaterOrEqual ||
+ op == EXP.identity || op == EXP.notIdentity ||
+ op == EXP.in_ ||
isEqualsCallExpression)
{
es = new Expressions(3);
@@ -6269,7 +6269,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
// template args
- Expression comp = new StringExp(loc, isEqualsCallExpression ? "==" : Token.toString(exp.e1.op));
+ Expression comp = new StringExp(loc, isEqualsCallExpression ? "==" : EXPtoString(exp.e1.op));
comp = comp.expressionSemantic(sc);
(*es)[0] = comp;
(*tiargs)[0] = (*es)[1].type;
@@ -6277,7 +6277,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// Format exp.e1 before any additional boolean conversion
// Ignore &&/|| because "assert(...) failed" is more informative than "false != true"
- else if (tok != TOK.andAnd && tok != TOK.orOr)
+ else if (op != EXP.andAnd && op != EXP.orOr)
{
es = new Expressions(2);
tiargs = new Objects(1);
@@ -6343,7 +6343,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.e1 = exp.e1.optimize(WANTvalue);
exp.e1 = exp.e1.toBoolean(sc);
- if (exp.e1.op == TOK.error)
+ if (exp.e1.op == EXP.error)
{
result = exp.e1;
return;
@@ -6358,7 +6358,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
checkParamArgumentEscape(sc, null, null, exp.msg, true, false);
}
- if (exp.msg && exp.msg.op == TOK.error)
+ if (exp.msg && exp.msg.op == EXP.error)
{
result = exp.msg;
return;
@@ -6369,7 +6369,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (f1 || f2)
return setError();
- if (exp.e1.isBool(false))
+ if (exp.e1.toBool().hasValue(false))
{
/* This is an `assert(0)` which means halt program execution
*/
@@ -6688,7 +6688,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
AggregateDeclaration ad = f.toParentLocal().isAggregateDeclaration();
if (f.needThis())
e.e1 = getRightThis(e.loc, sc, ad, e.e1, f);
- if (e.e1.op == TOK.error)
+ if (e.e1.op == EXP.error)
return setError();
/* A delegate takes the address of e.e1 in order to set the .ptr field
@@ -6731,9 +6731,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (AggregateDeclaration ad2 = f.isMember2())
{
Expression te = new ThisExp(e.loc).expressionSemantic(sc);
- if (te.op != TOK.error)
+ if (te.op != EXP.error)
te = getRightThis(e.loc, sc, ad2, te, f);
- if (te.op == TOK.error)
+ if (te.op == EXP.error)
{
e.error("need `this` of type `%s` to make delegate from function `%s`", ad2.toChars(), f.toChars());
return setError();
@@ -6806,9 +6806,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
- int wasCond = exp.e1.op == TOK.question;
+ int wasCond = exp.e1.op == EXP.question;
- if (exp.e1.op == TOK.dotTemplateInstance)
+ if (exp.e1.op == EXP.dotTemplateInstance)
{
DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)exp.e1;
TemplateInstance ti = dti.ti;
@@ -6827,7 +6827,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
}
- else if (exp.e1.op == TOK.scope_)
+ else if (exp.e1.op == EXP.scope_)
{
TemplateInstance ti = (cast(ScopeExp)exp.e1).sds.isTemplateInstance();
if (ti)
@@ -6891,7 +6891,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
exp.e1 = exp.e1.toLvalue(sc, null);
- if (exp.e1.op == TOK.error)
+ if (exp.e1.op == EXP.error)
{
result = exp.e1;
return;
@@ -6913,7 +6913,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
else if (!exp.e1.type.deco)
{
- if (exp.e1.op == TOK.variable)
+ if (exp.e1.op == EXP.variable)
{
VarExp ve = cast(VarExp)exp.e1;
Declaration d = ve.var;
@@ -6927,7 +6927,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.type = exp.e1.type.pointerTo();
// See if this should really be a delegate
- if (exp.e1.op == TOK.dotVariable)
+ if (exp.e1.op == EXP.dotVariable)
{
DotVarExp dve = cast(DotVarExp)exp.e1;
FuncDeclaration f = dve.var.isFuncDeclaration();
@@ -6961,7 +6961,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
}
- else if (exp.e1.op == TOK.variable)
+ else if (exp.e1.op == EXP.variable)
{
VarExp ve = cast(VarExp)exp.e1;
VarDeclaration v = ve.var.isVarDeclaration();
@@ -7023,7 +7023,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
}
- else if ((exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_) && global.params.useDIP1000 == FeatureState.enabled)
+ else if ((exp.e1.op == EXP.this_ || exp.e1.op == EXP.super_) && global.params.useDIP1000 == FeatureState.enabled)
{
if (VarDeclaration v = expToVariable(exp.e1))
{
@@ -7031,20 +7031,21 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
}
}
- else if (exp.e1.op == TOK.call)
+ else if (exp.e1.op == EXP.call)
{
CallExp ce = cast(CallExp)exp.e1;
if (ce.e1.type.ty == Tfunction)
{
TypeFunction tf = cast(TypeFunction)ce.e1.type;
- if (tf.isref && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
+ if (tf.isref && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_)
+ && tf.next.hasPointers() && sc.func.setUnsafe())
{
exp.error("cannot take address of `ref return` of `%s()` in `@safe` function `%s`",
ce.e1.toChars(), sc.func.toChars());
}
}
}
- else if (exp.e1.op == TOK.index)
+ else if (exp.e1.op == EXP.index)
{
/* For:
* int[3] a;
@@ -7064,12 +7065,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* a ? b : c was transformed to *(a ? &b : &c), but we still
* need to do safety checks
*/
- assert(exp.e1.op == TOK.star);
+ assert(exp.e1.op == EXP.star);
PtrExp pe = cast(PtrExp)exp.e1;
- assert(pe.e1.op == TOK.question);
+ assert(pe.e1.op == EXP.question);
CondExp ce = cast(CondExp)pe.e1;
- assert(ce.e1.op == TOK.address);
- assert(ce.e2.op == TOK.address);
+ assert(ce.e1.op == EXP.address);
+ assert(ce.e2.op == EXP.address);
// Re-run semantic on the address expressions only
ce.e1.type = null;
@@ -7270,7 +7271,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
// for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
- if (e.e1.op == TOK.type)
+ if (e.e1.op == EXP.type)
e.e1 = resolveAliasThis(sc, e.e1);
e.e1 = resolveProperties(sc, e.e1);
@@ -7313,7 +7314,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
exp.e1 = resolveProperties(sc, exp.e1);
exp.e1 = exp.e1.modifiableLvalue(sc, null);
- if (exp.e1.op == TOK.error)
+ if (exp.e1.op == EXP.error)
{
result = exp.e1;
return;
@@ -7405,8 +7406,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if ((sc && sc.flags & SCOPE.Cfile) &&
exp.to && exp.to.ty == Tident &&
- (exp.e1.op == TOK.address || exp.e1.op == TOK.star ||
- exp.e1.op == TOK.uadd || exp.e1.op == TOK.negate))
+ (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
@@ -7457,11 +7458,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
// for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
- if (exp.e1.op == TOK.type)
+ if (exp.e1.op == EXP.type)
exp.e1 = resolveAliasThis(sc, exp.e1);
auto e1x = resolveProperties(sc, exp.e1);
- if (e1x.op == TOK.error)
+ if (e1x.op == EXP.error)
{
result = e1x;
return;
@@ -7557,7 +7558,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
Expression ex = exp.e1.castTo(sc, exp.to);
- if (ex.op == TOK.error)
+ if (ex.op == EXP.error)
{
result = ex;
return;
@@ -7591,16 +7592,18 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
- if(t1b.ty == Tarray && exp.e1.op != TOK.arrayLiteral && (sc.flags & SCOPE.ctfe) == 0)
+ if(t1b.ty == Tarray && exp.e1.op != EXP.arrayLiteral && (sc.flags & SCOPE.ctfe) == 0)
{
auto tFrom = t1b.nextOf();
auto tTo = tob.nextOf();
// https://issues.dlang.org/show_bug.cgi?id=20130
- if (exp.e1.op != TOK.string_ || !ex.isStringExp)
+ if (exp.e1.op != EXP.string_ || !ex.isStringExp)
{
const uint fromSize = cast(uint)tFrom.size();
const uint toSize = cast(uint)tTo.size();
+ if (fromSize == SIZE_INVALID || toSize == SIZE_INVALID)
+ return setError();
// If array element sizes do not match, we must adjust the dimensions
if (fromSize != toSize)
@@ -7664,7 +7667,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.e1 = exp.e1.expressionSemantic(sc);
exp.type = exp.to.typeSemantic(exp.loc, sc);
- if (exp.e1.op == TOK.error || exp.type.ty == Terror)
+ if (exp.e1.op == EXP.error || exp.type.ty == Terror)
{
result = exp.e1;
return;
@@ -7687,7 +7690,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.e1 = exp.e1.optimize(WANTvalue);
bool res;
- if (exp.e1.op == TOK.arrayLiteral)
+ if (exp.e1.op == EXP.arrayLiteral)
{
foreach (i; 0 .. exp.dim)
{
@@ -7712,7 +7715,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
unaSemantic(e, sc);
e.e1 = resolveProperties(sc, e.e1);
- if (e.e1.op == TOK.error)
+ if (e.e1.op == EXP.error)
{
result = e.e1;
return;
@@ -7742,7 +7745,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
exp.e1 = resolveProperties(sc, exp.e1);
- if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple)
+ if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
{
if (exp.lwr || exp.upr)
{
@@ -7755,7 +7758,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
if (!exp.lwr && !exp.upr)
{
- if (exp.e1.op == TOK.arrayLiteral)
+ if (exp.e1.op == EXP.arrayLiteral)
{
// Convert [a,b,c][] to [a,b,c]
Type t1b = exp.e1.type.toBasetype();
@@ -7768,7 +7771,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = e;
return;
}
- if (exp.e1.op == TOK.slice)
+ if (exp.e1.op == EXP.slice)
{
// Convert e[][] to e[]
SliceExp se = cast(SliceExp)exp.e1;
@@ -7785,7 +7788,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
}
- if (exp.e1.op == TOK.error)
+ if (exp.e1.op == EXP.error)
{
result = exp.e1;
return;
@@ -7824,10 +7827,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
*/
if (VarDeclaration v = expToVariable(exp.e1))
{
- if (exp.e1.op == TOK.dotVariable)
+ if (exp.e1.op == EXP.dotVariable)
{
DotVarExp dve = cast(DotVarExp)exp.e1;
- if ((dve.e1.op == TOK.this_ || dve.e1.op == TOK.super_) &&
+ if ((dve.e1.op == EXP.this_ || dve.e1.op == EXP.super_) &&
!(v.storage_class & STC.ref_))
{
// because it's a class
@@ -7912,13 +7915,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
TupleExp te;
TypeTuple tup;
size_t length;
- if (exp.e1.op == TOK.tuple) // slicing an expression tuple
+ if (exp.e1.op == EXP.tuple) // slicing an expression tuple
{
te = cast(TupleExp)exp.e1;
tup = null;
length = te.exps.dim;
}
- else if (exp.e1.op == TOK.type) // slicing a type tuple
+ else if (exp.e1.op == EXP.type) // slicing a type tuple
{
te = null;
tup = cast(TypeTuple)t1b;
@@ -7936,7 +7939,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
size_t j1 = cast(size_t)i1;
size_t j2 = cast(size_t)i2;
Expression e;
- if (exp.e1.op == TOK.tuple)
+ if (exp.e1.op == EXP.tuple)
{
auto exps = new Expressions(j2 - j1);
for (size_t i = 0; i < j2 - j1; i++)
@@ -7982,29 +7985,29 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Expression el = new ArrayLengthExp(exp.loc, exp.e1);
el = el.expressionSemantic(sc);
el = el.optimize(WANTvalue);
- if (el.op == TOK.int64)
+ if (el.op == EXP.int64)
{
// Array length is known at compile-time. Upper is in bounds if it fits length.
dinteger_t length = el.toInteger();
auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length));
exp.upperIsInBounds = bounds.contains(uprRange);
- if (exp.lwr.op == TOK.int64 && exp.upr.op == TOK.int64 && exp.lwr.toInteger() > exp.upr.toInteger())
+ if (exp.lwr.op == EXP.int64 && exp.upr.op == EXP.int64 && exp.lwr.toInteger() > exp.upr.toInteger())
{
exp.error("in slice `%s[%llu .. %llu]`, lower bound is greater than upper bound", exp.e1.toChars, exp.lwr.toInteger(), exp.upr.toInteger());
return setError();
}
- if (exp.upr.op == TOK.int64 && exp.upr.toInteger() > length)
+ if (exp.upr.op == EXP.int64 && exp.upr.toInteger() > length)
{
exp.error("in slice `%s[%llu .. %llu]`, upper bound is greater than array length `%llu`", exp.e1.toChars, exp.lwr.toInteger(), exp.upr.toInteger(), length);
return setError();
}
}
- else if (exp.upr.op == TOK.int64 && exp.upr.toInteger() == 0)
+ else if (exp.upr.op == EXP.int64 && exp.upr.toInteger() == 0)
{
// Upper slice expression is '0'. Value is always in bounds.
exp.upperIsInBounds = true;
}
- else if (exp.upr.op == TOK.variable && (cast(VarExp)exp.upr).var.ident == Id.dollar)
+ else if (exp.upr.op == EXP.variable && (cast(VarExp)exp.upr).var.ident == Id.dollar)
{
// Upper slice expression is '$'. Value is always in bounds.
exp.upperIsInBounds = true;
@@ -8069,7 +8072,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (isAggregate(exp.e1.type))
exp.error("no `[]` operator overload for type `%s`", exp.e1.type.toChars());
- else if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple)
+ else if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
exp.error("static array of `%s` with multiple lengths not allowed", exp.e1.type.toChars());
else if (isIndexableNonAggregate(exp.e1.type))
exp.error("only one index allowed to index `%s`", exp.e1.type.toChars());
@@ -8090,17 +8093,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.e1 = exp.e1.expressionSemantic(sc);
exp.e2 = exp.e2.expressionSemantic(sc);
- if (exp.e1.op == TOK.type)
+ if (exp.e1.op == EXP.type)
{
result = exp.e2;
return;
}
- if (exp.e2.op == TOK.type)
+ if (exp.e2.op == EXP.type)
{
result = exp.e2;
return;
}
- if (exp.e2.op == TOK.template_)
+ if (exp.e2.op == EXP.template_)
{
auto td = (cast(TemplateExp)exp.e2).td;
Expression e = new DotTemplateExp(exp.loc, exp.e1, td);
@@ -8169,12 +8172,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
ue = ue.expressionSemantic(sc);
ue = resolveProperties(sc, ue);
- if (le.op == TOK.error)
+ if (le.op == EXP.error)
{
result = le;
return;
}
- if (ue.op == TOK.error)
+ if (ue.op == EXP.error)
{
result = ue;
return;
@@ -8198,7 +8201,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
unaSemantic(e, sc);
e.e1 = resolveProperties(sc, e.e1);
- if (e.e1.op == TOK.error)
+ if (e.e1.op == EXP.error)
{
result = e.e1;
return;
@@ -8218,7 +8221,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
unaSemantic(e, sc);
e.e1 = resolveProperties(sc, e.e1);
- if (e.e1.op == TOK.error)
+ if (e.e1.op == EXP.error)
{
result = e.e1;
return;
@@ -8244,12 +8247,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (!exp.e1.type)
exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
assert(exp.e1.type); // semantic() should already be run on it
- if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple)
+ if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
{
exp.e2 = exp.e2.expressionSemantic(sc);
exp.e2 = resolveProperties(sc, exp.e2);
Type nt;
- if (exp.e2.op == TOK.type)
+ if (exp.e2.op == EXP.type)
nt = new TypeAArray(exp.e1.type, exp.e2.type);
else
nt = new TypeSArray(exp.e1.type, exp.e2);
@@ -8257,7 +8260,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = e.expressionSemantic(sc);
return;
}
- if (exp.e1.op == TOK.error)
+ if (exp.e1.op == EXP.error)
{
result = exp.e1;
return;
@@ -8294,7 +8297,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.e2 = resolveProperties(sc, exp.e2);
if (t1b.ty == Ttuple)
sc = sc.endCTFE();
- if (exp.e2.op == TOK.tuple)
+ if (exp.e2.op == EXP.tuple)
{
TupleExp te = cast(TupleExp)exp.e2;
if (te.exps && te.exps.dim == 1)
@@ -8320,7 +8323,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (exp.e2.type == Type.terror)
return setError();
exp.e2 = exp.e2.optimize(WANTvalue);
- if (exp.e2.op == TOK.int64 && exp.e2.toInteger() == 0)
+ if (exp.e2.op == EXP.int64 && exp.e2.toInteger() == 0)
{
}
else if (sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
@@ -8378,13 +8381,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
TupleExp te;
TypeTuple tup;
size_t length;
- if (exp.e1.op == TOK.tuple)
+ if (exp.e1.op == EXP.tuple)
{
te = cast(TupleExp)exp.e1;
tup = null;
length = te.exps.dim;
}
- else if (exp.e1.op == TOK.type)
+ else if (exp.e1.op == EXP.type)
{
te = null;
tup = cast(TypeTuple)t1b;
@@ -8399,7 +8402,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
}
Expression e;
- if (exp.e1.op == TOK.tuple)
+ if (exp.e1.op == EXP.tuple)
{
e = (*te.exps)[cast(size_t)index];
e = Expression.combine(te.e0, e);
@@ -8422,7 +8425,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Expression el = new ArrayLengthExp(exp.loc, exp.e1);
el = el.expressionSemantic(sc);
el = el.optimize(WANTvalue);
- if (el.op == TOK.int64)
+ if (el.op == EXP.int64)
{
exp.e2 = exp.e2.optimize(WANTvalue);
dinteger_t length = el.toInteger();
@@ -8455,7 +8458,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
Expression e1x = resolveProperties(sc, exp.e1);
- if (e1x.op == TOK.error)
+ if (e1x.op == EXP.error)
{
result = e1x;
return;
@@ -8472,15 +8475,15 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (exp.e1.checkReadModifyWrite(exp.op))
return setError();
- if (exp.e1.op == TOK.slice)
+ if (exp.e1.op == EXP.slice)
{
- const(char)* s = exp.op == TOK.plusPlus ? "increment" : "decrement";
+ const(char)* s = exp.op == EXP.plusPlus ? "increment" : "decrement";
exp.error("cannot post-%s array slice `%s`, use pre-%s instead", s, exp.e1.toChars(), s);
return setError();
}
Type t1 = exp.e1.type.toBasetype();
- if (t1.ty == Tclass || t1.ty == Tstruct || exp.e1.op == TOK.arrayLength)
+ if (t1.ty == Tclass || t1.ty == Tstruct || exp.e1.op == EXP.arrayLength)
{
/* Check for operator overloading,
* but rewrite in terms of ++e instead of e++
@@ -8489,7 +8492,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* If e1 is not trivial, take a reference to it
*/
Expression de = null;
- if (exp.e1.op != TOK.variable && exp.e1.op != TOK.arrayLength)
+ if (exp.e1.op != EXP.variable && exp.e1.op != EXP.arrayLength)
{
// ref v = e1;
auto v = copyToTemp(STC.ref_, "__postref", exp.e1);
@@ -8504,7 +8507,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Expression ea = new DeclarationExp(exp.loc, tmp);
Expression eb = exp.e1.syntaxCopy();
- eb = new PreExp(exp.op == TOK.plusPlus ? TOK.prePlusPlus : TOK.preMinusMinus, exp.loc, eb);
+ eb = new PreExp(exp.op == EXP.plusPlus ? EXP.prePlusPlus : EXP.preMinusMinus, exp.loc, eb);
Expression ec = new VarExp(exp.loc, tmp);
@@ -8547,7 +8550,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
// Rewrite as e1+=1 or e1-=1
- if (exp.op == TOK.prePlusPlus)
+ if (exp.op == EXP.prePlusPlus)
e = new AddAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
else
e = new MinAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
@@ -8596,8 +8599,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
printf("AssignExp::semantic('%s')\n", exp.toChars());
}
- //printf("exp.e1.op = %d, '%s'\n", exp.e1.op, Token.toChars(exp.e1.op));
- //printf("exp.e2.op = %d, '%s'\n", exp.e2.op, Token.toChars(exp.e2.op));
+ //printf("exp.e1.op = %d, '%s'\n", exp.e1.op, EXPtoString(exp.e1.op).ptr);
+ //printf("exp.e2.op = %d, '%s'\n", exp.e2.op, EXPtoString(exp.e2.op).ptr);
void setResult(Expression e, int line = __LINE__)
{
@@ -8640,17 +8643,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
const(bool) maybeSlice =
(ae.arguments.dim == 0 ||
- ae.arguments.dim == 1 && (*ae.arguments)[0].op == TOK.interval);
+ ae.arguments.dim == 1 && (*ae.arguments)[0].op == EXP.interval);
IntervalExp ie = null;
if (maybeSlice && ae.arguments.dim)
{
- assert((*ae.arguments)[0].op == TOK.interval);
+ assert((*ae.arguments)[0].op == EXP.interval);
ie = cast(IntervalExp)(*ae.arguments)[0];
}
while (true)
{
- if (ae.e1.op == TOK.error)
+ if (ae.e1.op == EXP.error)
return setResult(ae.e1);
Expression e0 = null;
@@ -8667,11 +8670,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
res = resolveOpDollar(sc, ae, &e0);
if (!res) // a[i..j] = e2 might be: a.opSliceAssign(e2, i, j)
goto Lfallback;
- if (res.op == TOK.error)
+ if (res.op == EXP.error)
return setResult(res);
res = exp.e2.expressionSemantic(sc);
- if (res.op == TOK.error)
+ if (res.op == EXP.error)
return setResult(res);
exp.e2 = res;
@@ -8695,11 +8698,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
// Deal with $
res = resolveOpDollar(sc, ae, ie, &e0);
- if (res.op == TOK.error)
+ if (res.op == EXP.error)
return setResult(res);
res = exp.e2.expressionSemantic(sc);
- if (res.op == TOK.error)
+ if (res.op == EXP.error)
return setResult(res);
exp.e2 = res;
@@ -8826,9 +8829,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (!t1.isTypeSArray())
e2x = e2x.arrayFuncConv(sc);
e2x = resolveProperties(sc, e2x);
- if (e2x.op == TOK.type)
+ if (e2x.op == EXP.type)
e2x = resolveAliasThis(sc, e2x); //https://issues.dlang.org/show_bug.cgi?id=17684
- if (e2x.op == TOK.error)
+ if (e2x.op == EXP.error)
return setResult(e2x);
// We delay checking the value for structs/classes as these might have
// an opAssign defined.
@@ -8844,7 +8847,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Expression e2x = exp.e2;
Ltupleassign:
- if (exp.e1.op == TOK.tuple && e2x.op == TOK.tuple)
+ if (exp.e1.op == EXP.tuple && e2x.op == EXP.tuple)
{
TupleExp tup1 = cast(TupleExp)exp.e1;
TupleExp tup2 = cast(TupleExp)e2x;
@@ -8877,7 +8880,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* Look for form: e1 = e2.aliasthis.
*/
- if (exp.e1.op == TOK.tuple)
+ if (exp.e1.op == EXP.tuple)
{
TupleDeclaration td = isAliasThisTuple(e2x);
if (!td)
@@ -8915,7 +8918,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
e2x = new TupleExp(e2x.loc, e0, iexps);
e2x = e2x.expressionSemantic(sc);
- if (e2x.op == TOK.error)
+ if (e2x.op == EXP.error)
{
result = e2x;
return;
@@ -8929,7 +8932,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* Inside constructor, if this is the first assignment of object field,
* rewrite this to initializing the field.
*/
- if (exp.op == TOK.assign
+ if (exp.op == EXP.assign
&& exp.e1.checkModifiable(sc) == Modifiable.initialization)
{
//printf("[%s] change to init - %s\n", exp.loc.toChars(), exp.toChars());
@@ -8942,20 +8945,20 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (auto ie1 = exp.e1.isIndexExp())
{
Expression e1x = ie1.markSettingAAElem();
- if (e1x.op == TOK.error)
+ if (e1x.op == EXP.error)
{
result = e1x;
return;
}
}
}
- else if (exp.op == TOK.construct && exp.e1.op == TOK.variable &&
+ else if (exp.op == EXP.construct && exp.e1.op == EXP.variable &&
(cast(VarExp)exp.e1).var.storage_class & (STC.out_ | STC.ref_))
{
exp.memset = MemorySet.referenceInit;
}
- if (exp.op == TOK.assign) // skip TOK.blit and TOK.construct, which are initializations
+ if (exp.op == EXP.assign) // skip EXP.blit and EXP.construct, which are initializations
{
exp.e1.checkSharedAccess(sc);
checkUnsafeAccess(sc, exp.e1, false, true);
@@ -8977,7 +8980,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
auto e2x = exp.e2;
auto sd = (cast(TypeStruct)t1).sym;
- if (exp.op == TOK.construct)
+ if (exp.op == EXP.construct)
{
Type t2 = e2x.type.toBasetype();
if (t2.ty == Tstruct && sd == (cast(TypeStruct)t2).sym)
@@ -8992,12 +8995,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// Look for the form from last of comma chain.
auto e2y = lastComma(e2x);
- CallExp ce = (e2y.op == TOK.call) ? cast(CallExp)e2y : null;
- DotVarExp dve = (ce && ce.e1.op == TOK.dotVariable)
+ CallExp ce = (e2y.op == EXP.call) ? cast(CallExp)e2y : null;
+ DotVarExp dve = (ce && ce.e1.op == EXP.dotVariable)
? cast(DotVarExp)ce.e1 : null;
if (sd.ctor && ce && dve && dve.var.isCtorDeclaration() &&
// https://issues.dlang.org/show_bug.cgi?id=19389
- dve.e1.op != TOK.dotVariable &&
+ dve.e1.op != EXP.dotVariable &&
e2y.type.implicitConvTo(t1))
{
/* Look for form of constructor call which is:
@@ -9009,7 +9012,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* initializer
*/
Expression einit = getInitExp(sd, exp.loc, sc, t1);
- if (einit.op == TOK.error)
+ if (einit.op == EXP.error)
{
result = einit;
return;
@@ -9043,7 +9046,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// a temporary created and an extra destructor call.
// AST will be rewritten to:
// a ? e1 = 0, e1.this(1) : ...; -> blitting plus construction
- if (e2x.op == TOK.question)
+ if (e2x.op == EXP.question)
{
/* Rewrite as:
* a ? e1 = b : e1 = c;
@@ -9158,7 +9161,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* Foo f = new Foo2(0); is a valid expression if Foo has a constructor
* which receives an instance of a Foo2 class
*/
- if (exp.e2.op == TOK.new_)
+ if (exp.e2.op == EXP.new_)
{
auto newExp = cast(NewExp)(exp.e2);
if (newExp.newtype && newExp.newtype == t1)
@@ -9193,7 +9196,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
e2x = e2x.expressionSemantic(sc);
e2x = resolveProperties(sc, e2x);
- if (e2x.op == TOK.error)
+ if (e2x.op == EXP.error)
{
result = e2x;
return;
@@ -9216,9 +9219,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
}
- else if (exp.op == TOK.assign)
+ else if (exp.op == EXP.assign)
{
- if (e1x.op == TOK.index && (cast(IndexExp)e1x).e1.type.toBasetype().ty == Taarray)
+ if (e1x.op == EXP.index && (cast(IndexExp)e1x).e1.type.toBasetype().ty == Taarray)
{
/*
* Rewrite:
@@ -9233,12 +9236,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
*/
// ensure we keep the expr modifiable
Expression esetting = (cast(IndexExp)e1x).markSettingAAElem();
- if (esetting.op == TOK.error)
+ if (esetting.op == EXP.error)
{
result = esetting;
return;
}
- assert(esetting.op == TOK.index);
+ assert(esetting.op == EXP.index);
IndexExp ie = cast(IndexExp) esetting;
Type t2 = e2x.type.toBasetype();
@@ -9279,7 +9282,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
ey = new ConstructExp(exp.loc, ex, ey);
ey = ey.expressionSemantic(sc);
- if (ey.op == TOK.error)
+ if (ey.op == EXP.error)
{
result = ey;
return;
@@ -9290,7 +9293,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// The whole expression should have the common type
// of opAssign() return and assigned AA entry.
// Even if there's no common type, expression should be typed as void.
- if (!typeMerge(sc, TOK.question, ex, ey))
+ if (!typeMerge(sc, EXP.question, ex, ey))
{
ex = new CastExp(ex.loc, ex, Type.tvoid);
ey = new CastExp(ey.loc, ey, Type.tvoid);
@@ -9314,7 +9317,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
else
- assert(exp.op == TOK.blit);
+ assert(exp.op == EXP.blit);
if (e2x.checkValue())
return setError();
@@ -9325,7 +9328,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
else if (t1.ty == Tclass)
{
// Disallow assignment operator overloads for same type
- if (exp.op == TOK.assign && !exp.e2.implicitConvTo(exp.e1.type))
+ if (exp.op == EXP.assign && !exp.e2.implicitConvTo(exp.e1.type))
{
Expression e = exp.op_overload(sc);
if (e)
@@ -9340,13 +9343,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
else if (t1.ty == Tsarray)
{
// SliceExp cannot have static array type without context inference.
- assert(exp.e1.op != TOK.slice);
+ assert(exp.e1.op != EXP.slice);
Expression e1x = exp.e1;
Expression e2x = exp.e2;
if (e2x.implicitConvTo(e1x.type))
{
- if (exp.op != TOK.blit && (e2x.op == TOK.slice && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op == TOK.cast_ && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op != TOK.slice && e2x.isLvalue()))
+ if (exp.op != EXP.blit && (e2x.op == EXP.slice && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op == EXP.cast_ && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op != EXP.slice && e2x.isLvalue()))
{
if (e1x.checkPostblit(sc, t1))
return setError();
@@ -9392,7 +9395,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// May be block or element-wise assignment, so
// convert e1 to e1[]
- if (exp.op != TOK.assign)
+ if (exp.op != EXP.assign)
{
// If multidimensional static array, treat as one large array
//
@@ -9435,9 +9438,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
sle.arrayop = true;
e1x = sle.expressionSemantic(sc);
}
- if (e1x.op == TOK.error)
+ if (e1x.op == EXP.error)
return setResult(e1x);
- if (e2x.op == TOK.error)
+ if (e2x.op == EXP.error)
return setResult(e2x);
exp.e1 = e1x;
@@ -9451,7 +9454,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// e1 is not an lvalue, but we let code generator handle it
auto ale1x = ale.e1.modifiableLvalue(sc, exp.e1);
- if (ale1x.op == TOK.error)
+ if (ale1x.op == EXP.error)
return setResult(ale1x);
ale.e1 = ale1x;
@@ -9466,7 +9469,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
auto lc = lastComma(exp.e2);
lc = lc.optimize(WANTvalue);
// use slice expression when arr.length = 0 to avoid runtime call
- if(lc.op == TOK.int64 && lc.toInteger() == 0)
+ if(lc.op == EXP.int64 && lc.toInteger() == 0)
{
Expression se = new SliceExp(ale.loc, ale.e1, lc, lc);
Expression as = new AssignExp(ale.loc, ale.e1, se);
@@ -9507,7 +9510,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
Type tn = se.type.nextOf();
const fun = sc.func;
- if (exp.op == TOK.assign && !tn.isMutable() &&
+ if (exp.op == EXP.assign && !tn.isMutable() &&
// allow modifiation in module ctor, see
// https://issues.dlang.org/show_bug.cgi?id=9884
(!fun || (fun && !fun.isStaticCtorDeclaration())))
@@ -9516,7 +9519,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
}
- if (exp.op == TOK.assign && !tn.baseElemOf().isAssignable())
+ if (exp.op == EXP.assign && !tn.baseElemOf().isAssignable())
{
exp.error("slice `%s` is not mutable, struct `%s` has immutable members",
exp.e1.toChars(), tn.baseElemOf().toChars());
@@ -9525,18 +9528,18 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
// For conditional operator, both branches need conversion.
- while (se.e1.op == TOK.slice)
+ while (se.e1.op == EXP.slice)
se = cast(SliceExp)se.e1;
- if (se.e1.op == TOK.question && se.e1.type.toBasetype().ty == Tsarray)
+ if (se.e1.op == EXP.question && se.e1.type.toBasetype().ty == Tsarray)
{
se.e1 = se.e1.modifiableLvalue(sc, exp.e1);
- if (se.e1.op == TOK.error)
+ if (se.e1.op == EXP.error)
return setResult(se.e1);
}
}
else
{
- if (t1.ty == Tsarray && exp.op == TOK.assign)
+ if (t1.ty == Tsarray && exp.op == EXP.assign)
{
Type tn = exp.e1.type.nextOf();
if (tn && !tn.baseElemOf().isAssignable())
@@ -9552,12 +9555,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// Try to do a decent error message with the expression
// before it gets constant folded
- if (exp.op == TOK.assign)
+ if (exp.op == EXP.assign)
e1x = e1x.modifiableLvalue(sc, e1old);
e1x = e1x.optimize(WANTvalue, /*keepLvalue*/ true);
- if (e1x.op == TOK.error)
+ if (e1x.op == EXP.error)
{
result = e1x;
return;
@@ -9576,18 +9579,18 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
while (telem.ty == Tarray)
telem = telem.nextOf();
- if (exp.e1.op == TOK.slice && t1.nextOf() &&
- (telem.ty != Tvoid || e2x.op == TOK.null_) &&
+ if (exp.e1.op == EXP.slice && t1.nextOf() &&
+ (telem.ty != Tvoid || e2x.op == EXP.null_) &&
e2x.implicitConvTo(t1.nextOf()))
{
// Check for block assignment. If it is of type void[], void[][], etc,
// '= null' is the only allowable block assignment (Bug 7493)
exp.memset = MemorySet.blockAssign; // make it easy for back end to tell what this is
e2x = e2x.implicitCastTo(sc, t1.nextOf());
- if (exp.op != TOK.blit && e2x.isLvalue() && exp.e1.checkPostblit(sc, t1.nextOf()))
+ if (exp.op != EXP.blit && e2x.isLvalue() && exp.e1.checkPostblit(sc, t1.nextOf()))
return setError();
}
- else if (exp.e1.op == TOK.slice &&
+ else if (exp.e1.op == EXP.slice &&
(t2.ty == Tarray || t2.ty == Tsarray) &&
t2.nextOf().implicitConvTo(t1.nextOf()))
{
@@ -9616,24 +9619,24 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
- if (exp.op != TOK.blit &&
- (e2x.op == TOK.slice && (cast(UnaExp)e2x).e1.isLvalue() ||
- e2x.op == TOK.cast_ && (cast(UnaExp)e2x).e1.isLvalue() ||
- e2x.op != TOK.slice && e2x.isLvalue()))
+ if (exp.op != EXP.blit &&
+ (e2x.op == EXP.slice && (cast(UnaExp)e2x).e1.isLvalue() ||
+ e2x.op == EXP.cast_ && (cast(UnaExp)e2x).e1.isLvalue() ||
+ e2x.op != EXP.slice && e2x.isLvalue()))
{
if (exp.e1.checkPostblit(sc, t1.nextOf()))
return setError();
}
- if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == TOK.assign &&
- e2x.op != TOK.slice && e2x.op != TOK.assign &&
- e2x.op != TOK.arrayLiteral && e2x.op != TOK.string_ &&
- !(e2x.op == TOK.add || e2x.op == TOK.min ||
- e2x.op == TOK.mul || e2x.op == TOK.div ||
- e2x.op == TOK.mod || e2x.op == TOK.xor ||
- e2x.op == TOK.and || e2x.op == TOK.or ||
- e2x.op == TOK.pow ||
- e2x.op == TOK.tilde || e2x.op == TOK.negate))
+ if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign &&
+ e2x.op != EXP.slice && e2x.op != EXP.assign &&
+ e2x.op != EXP.arrayLiteral && e2x.op != EXP.string_ &&
+ !(e2x.op == EXP.add || e2x.op == EXP.min ||
+ e2x.op == EXP.mul || e2x.op == EXP.div ||
+ e2x.op == EXP.mod || e2x.op == EXP.xor ||
+ e2x.op == EXP.and || e2x.op == EXP.or ||
+ e2x.op == EXP.pow ||
+ e2x.op == EXP.tilde || e2x.op == EXP.negate))
{
const(char)* e1str = exp.e1.toChars();
const(char)* e2str = e2x.toChars();
@@ -9673,7 +9676,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* elements need to be const at best. So we should give a chance
* to change code unit size for polysemous string literal.
*/
- if (e2x.op == TOK.string_)
+ if (e2x.op == EXP.string_)
e2x = e2x.implicitCastTo(sc, exp.e1.type.constOf());
else
e2x = e2x.implicitCastTo(sc, exp.e1.type);
@@ -9689,19 +9692,19 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
else
{
- if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == TOK.assign &&
+ if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign &&
t1.ty == Tarray && t2.ty == Tsarray &&
- e2x.op != TOK.slice &&
+ e2x.op != EXP.slice &&
t2.implicitConvTo(t1))
{
// Disallow ar[] = sa (Converted to ar[] = sa[])
// Disallow da = sa (Converted to da = sa[])
const(char)* e1str = exp.e1.toChars();
const(char)* e2str = e2x.toChars();
- const(char)* atypestr = exp.e1.op == TOK.slice ? "element-wise" : "slice";
+ const(char)* atypestr = exp.e1.op == EXP.slice ? "element-wise" : "slice";
exp.warning("explicit %s assignment `%s = (%s)[]` is better than `%s = %s`", atypestr, e1str, e2str, e1str, e2str);
}
- if (exp.op == TOK.blit)
+ if (exp.op == EXP.blit)
e2x = e2x.castTo(sc, exp.e1.type);
else
{
@@ -9711,7 +9714,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// If the implicit cast has failed and the assign expression is
// the initialization of a struct member field
- if (e2x.op == TOK.error && exp.op == TOK.construct && t1.ty == Tstruct)
+ if (e2x.op == EXP.error && exp.op == EXP.construct && t1.ty == Tstruct)
{
scope sd = (cast(TypeStruct)t1).sym;
Dsymbol opAssign = search_function(sd, Id.assign);
@@ -9729,7 +9732,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
}
- if (e2x.op == TOK.error)
+ if (e2x.op == EXP.error)
{
result = e2x;
return;
@@ -9743,11 +9746,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
// Look for valid array operations
if (exp.memset != MemorySet.blockAssign &&
- exp.e1.op == TOK.slice &&
+ exp.e1.op == EXP.slice &&
(isUnaArrayOp(exp.e2.op) || isBinArrayOp(exp.e2.op)))
{
exp.type = exp.e1.type;
- if (exp.op == TOK.construct) // https://issues.dlang.org/show_bug.cgi?id=10282
+ if (exp.op == EXP.construct) // https://issues.dlang.org/show_bug.cgi?id=10282
// tweak mutability of e1 element
exp.e1.type = exp.e1.type.nextOf().mutableOf().arrayOf();
result = arrayOp(exp, sc);
@@ -9756,7 +9759,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// Drop invalid array operations in e2
// d = a[] + b[], d = (a[] + b[])[0..2], etc
- if (checkNonAssignmentArrayOp(exp.e2, exp.memset != MemorySet.blockAssign && exp.op == TOK.assign))
+ if (checkNonAssignmentArrayOp(exp.e2, exp.memset != MemorySet.blockAssign && exp.op == EXP.assign))
return setError();
// Remains valid array assignments
@@ -9766,7 +9769,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* Don't allow assignment to classes that were allocated on the stack with:
* scope Class c = new Class();
*/
- if (exp.e1.op == TOK.variable && exp.op == TOK.assign)
+ if (exp.e1.op == EXP.variable && exp.op == EXP.assign)
{
VarExp ve = cast(VarExp)exp.e1;
VarDeclaration vd = ve.var.isVarDeclaration();
@@ -9777,14 +9780,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
- if (exp.e1.op == TOK.variable && (cast(VarExp)exp.e1).var.ident == Id.ctfe)
+ if (exp.e1.op == EXP.variable && (cast(VarExp)exp.e1).var.ident == Id.ctfe)
{
exp.error("cannot modify compiler-generated variable `__ctfe`");
}
exp.type = exp.e1.type;
assert(exp.type);
- auto res = exp.op == TOK.assign ? exp.reorderSettingAAElem(sc) : exp;
+ auto res = exp.op == EXP.assign ? exp.reorderSettingAAElem(sc) : exp;
Expression tmp;
/* https://issues.dlang.org/show_bug.cgi?id=22366
*
@@ -9792,6 +9795,84 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* `checkAssignExp` expects only AssignExps.
*/
checkAssignEscape(sc, Expression.extractLast(res, tmp), false);
+
+ if (auto ae = res.isConstructExp())
+ {
+ Type t1b = ae.e1.type.toBasetype();
+ if (t1b.ty != Tsarray && t1b.ty != Tarray)
+ return setResult(res);
+
+ /* Do not lower Rvalues and references, as they need to be moved,
+ * not copied.
+ * Skip the lowering when the RHS is an array literal, as e2ir
+ * already handles such cases more elegantly.
+ */
+ const isArrayCtor =
+ (ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) &&
+ ae.e2.isLvalue &&
+ !(ae.e1.isVarExp &&
+ ae.e1.isVarExp.var.isVarDeclaration.isReference) &&
+ (ae.e2.isVarExp ||
+ ae.e2.isSliceExp ||
+ (ae.e2.type.ty == Tsarray && !ae.e2.isArrayLiteralExp)) &&
+ ae.e1.type.nextOf &&
+ ae.e2.type.nextOf &&
+ ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf);
+
+ const isArraySetCtor =
+ (ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) &&
+ ae.e2.isLvalue &&
+ (ae.e2.type.ty == Tstruct || ae.e2.type.ty == Tsarray) &&
+ ae.e1.type.nextOf &&
+ ae.e1.type.nextOf.equivalent(ae.e2.type);
+
+ if (isArrayCtor || isArraySetCtor)
+ {
+ const ts = t1b.nextOf().baseElemOf().isTypeStruct();
+ if (!ts || (!ts.sym.postblit && !ts.sym.dtor))
+ return setResult(res);
+
+ auto func = isArrayCtor ? Id._d_arrayctor : Id._d_arraysetctor;
+ const other = isArrayCtor ? "other array" : "value";
+ if (!verifyHookExist(exp.loc, *sc, func, "construct array with " ~ other, Id.object))
+ return setError();
+
+ // Lower to object._d_array{,set}ctor(e1, e2)
+ Expression id = new IdentifierExp(exp.loc, Id.empty);
+ id = new DotIdExp(exp.loc, id, Id.object);
+ id = new DotIdExp(exp.loc, id, func);
+ id = id.expressionSemantic(sc);
+
+ auto arguments = new Expressions();
+ arguments.push(new CastExp(ae.loc, ae.e1, ae.e1.type.nextOf.arrayOf).expressionSemantic(sc));
+ if (isArrayCtor)
+ {
+ arguments.push(new CastExp(ae.loc, ae.e2, ae.e2.type.nextOf.arrayOf).expressionSemantic(sc));
+ Expression ce = new CallExp(exp.loc, id, arguments);
+ res = ce.expressionSemantic(sc);
+ }
+ else
+ {
+ Expression e0;
+ // If ae.e2 is not a variable, construct a temp variable, as _d_arraysetctor requires `ref` access
+ if (!ae.e2.isVarExp)
+ {
+ auto vd = copyToTemp(STC.scope_, "__setctor", ae.e2);
+ e0 = new DeclarationExp(vd.loc, vd).expressionSemantic(sc);
+ arguments.push(new VarExp(vd.loc, vd).expressionSemantic(sc));
+ }
+ else
+ arguments.push(ae.e2);
+
+ Expression ce = new CallExp(exp.loc, id, arguments);
+ res = Expression.combine(e0, ce).expressionSemantic(sc);
+ }
+
+ if (global.params.verbose)
+ message("lowered %s =>\n %s", exp.toChars(), res.toChars());
+ }
+ }
+
return setResult(res);
}
@@ -9814,7 +9895,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
assert(exp.e1.type && exp.e2.type);
- if (exp.e1.op == TOK.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
+ if (exp.e1.op == EXP.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
{
if (checkNonAssignmentArrayOp(exp.e1))
return setError();
@@ -9855,7 +9936,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
e = Expression.extractLast(e, e0);
assert(e == exp);
- if (exp.e1.op == TOK.variable)
+ if (exp.e1.op == EXP.variable)
{
// Rewrite: e1 = e1 ^^ e2
e = new PowExp(exp.loc, exp.e1.syntaxCopy(), exp.e2);
@@ -9895,7 +9976,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
- if (exp.e1.op == TOK.slice)
+ if (exp.e1.op == EXP.slice)
{
SliceExp se = cast(SliceExp)exp.e1;
if (se.e1.type.toBasetype().ty == Tsarray)
@@ -9906,12 +9987,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
- if (exp.e1.op == TOK.error)
+ if (exp.e1.op == EXP.error)
{
result = exp.e1;
return;
}
- if (exp.e2.op == TOK.error)
+ if (exp.e2.op == EXP.error)
{
result = exp.e2;
return;
@@ -9925,9 +10006,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Type tb2 = exp.e2.type.toBasetype();
/* Possibilities:
- * TOK.concatenateAssign: appending T[] to T[]
- * TOK.concatenateElemAssign: appending T to T[]
- * TOK.concatenateDcharAssign: appending dchar to T[]
+ * EXP.concatenateAssign: appending T[] to T[]
+ * EXP.concatenateElemAssign: appending T to T[]
+ * EXP.concatenateDcharAssign: appending dchar to T[]
*/
if ((tb1.ty == Tarray) &&
(tb2.ty == Tarray || tb2.ty == Tsarray) &&
@@ -9935,8 +10016,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
(tb2.nextOf().implicitConvTo(tb1next) &&
(tb2.nextOf().size(Loc.initial) == tb1next.size(Loc.initial)))))
{
- // TOK.concatenateAssign
- assert(exp.op == TOK.concatenateAssign);
+ // EXP.concatenateAssign
+ assert(exp.op == EXP.concatenateAssign);
if (exp.e1.checkPostblit(sc, tb1next))
return setError();
@@ -10033,7 +10114,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.type = exp.e1.type;
auto res = exp.reorderSettingAAElem(sc);
- if ((exp.op == TOK.concatenateElemAssign || exp.op == TOK.concatenateDcharAssign) &&
+ if ((exp.op == EXP.concatenateElemAssign || exp.op == EXP.concatenateDcharAssign) &&
global.params.useDIP1000 == FeatureState.enabled)
checkAssignEscape(sc, res, false);
result = res;
@@ -10227,6 +10308,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
e = new IntegerExp(exp.loc, 0, Type.tptrdiff_t);
}
+ else if (stride == cast(d_int64)SIZE_INVALID)
+ e = ErrorExp.get();
else
{
e = new DivExp(exp.loc, exp, new IntegerExp(Loc.initial, stride, Type.tptrdiff_t));
@@ -10336,7 +10419,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Type tb2next = tb2.nextOf();
// Check for: array ~ array
- if (tb1next && tb2next && (tb1next.implicitConvTo(tb2next) >= MATCH.constant || tb2next.implicitConvTo(tb1next) >= MATCH.constant || exp.e1.op == TOK.arrayLiteral && exp.e1.implicitConvTo(tb2) || exp.e2.op == TOK.arrayLiteral && exp.e2.implicitConvTo(tb1)))
+ if (tb1next && tb2next && (tb1next.implicitConvTo(tb2next) >= MATCH.constant || tb2next.implicitConvTo(tb1next) >= MATCH.constant || exp.e1.op == EXP.arrayLiteral && exp.e1.implicitConvTo(tb2) || exp.e2.op == EXP.arrayLiteral && exp.e2.implicitConvTo(tb1)))
{
/* https://issues.dlang.org/show_bug.cgi?id=9248
* Here to avoid the case of:
@@ -10360,14 +10443,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// Check for: array ~ element
if ((tb1.ty == Tsarray || tb1.ty == Tarray) && tb2.ty != Tvoid)
{
- if (exp.e1.op == TOK.arrayLiteral)
+ if (exp.e1.op == EXP.arrayLiteral)
{
exp.e2 = doCopyOrMove(sc, exp.e2);
// https://issues.dlang.org/show_bug.cgi?id=14686
// Postblit call appears in AST, and this is
// finally translated to an ArrayLiteralExp in below optimize().
}
- else if (exp.e1.op == TOK.string_)
+ else if (exp.e1.op == EXP.string_)
{
// No postblit call exists on character (integer) value.
}
@@ -10378,7 +10461,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// Postblit call will be done in runtime helper function
}
- if (exp.e1.op == TOK.arrayLiteral && exp.e1.implicitConvTo(tb2.arrayOf()))
+ if (exp.e1.op == EXP.arrayLiteral && exp.e1.implicitConvTo(tb2.arrayOf()))
{
exp.e1 = exp.e1.implicitCastTo(sc, tb2.arrayOf());
exp.type = tb2.arrayOf();
@@ -10403,11 +10486,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// Check for: element ~ array
if ((tb2.ty == Tsarray || tb2.ty == Tarray) && tb1.ty != Tvoid)
{
- if (exp.e2.op == TOK.arrayLiteral)
+ if (exp.e2.op == EXP.arrayLiteral)
{
exp.e1 = doCopyOrMove(sc, exp.e1);
}
- else if (exp.e2.op == TOK.string_)
+ else if (exp.e2.op == EXP.string_)
{
}
else
@@ -10416,7 +10499,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
}
- if (exp.e2.op == TOK.arrayLiteral && exp.e2.implicitConvTo(tb1.arrayOf()))
+ if (exp.e2.op == EXP.arrayLiteral && exp.e2.implicitConvTo(tb1.arrayOf()))
{
exp.e2 = exp.e2.implicitCastTo(sc, tb1.arrayOf());
exp.type = tb1.arrayOf();
@@ -10444,11 +10527,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
Type t1 = tb1next.mutableOf().constOf().arrayOf();
Type t2 = tb2next.mutableOf().constOf().arrayOf();
- if (exp.e1.op == TOK.string_ && !(cast(StringExp)exp.e1).committed)
+ if (exp.e1.op == EXP.string_ && !(cast(StringExp)exp.e1).committed)
exp.e1.type = t1;
else
exp.e1 = exp.e1.castTo(sc, t1);
- if (exp.e2.op == TOK.string_ && !(cast(StringExp)exp.e2).committed)
+ if (exp.e2.op == EXP.string_ && !(cast(StringExp)exp.e2).committed)
exp.e2.type = t2;
else
exp.e2 = exp.e2.castTo(sc, t2);
@@ -10804,7 +10887,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// First, attempt to fold the expression.
e = exp.optimize(WANTvalue);
- if (e.op != TOK.pow)
+ if (e.op != EXP.pow)
{
e = e.expressionSemantic(sc);
result = e;
@@ -10819,7 +10902,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
e = new ScopeExp(exp.loc, mmath);
- if (exp.e2.op == TOK.float64 && exp.e2.toReal() == CTFloat.half)
+ if (exp.e2.op == EXP.float64 && exp.e2.toReal() == CTFloat.half)
{
// Replace e1 ^^ 0.5 with .std.math.sqrt(e1)
e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._sqrt), exp.e1);
@@ -11126,7 +11209,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Expression e1x = exp.e1.expressionSemantic(sc);
// for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
- if (e1x.op == TOK.type)
+ if (e1x.op == EXP.type)
e1x = resolveAliasThis(sc, e1x);
e1x = resolveProperties(sc, e1x);
@@ -11137,9 +11220,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* If in static if, don't evaluate e2 if we don't have to.
*/
e1x = e1x.optimize(WANTvalue);
- if (e1x.isBool(exp.op == TOK.orOr))
+ if (e1x.toBool().hasValue(exp.op == EXP.orOr))
{
- result = IntegerExp.createBool(exp.op == TOK.orOr);
+ result = IntegerExp.createBool(exp.op == EXP.orOr);
return;
}
}
@@ -11150,7 +11233,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
ctorflow.freeFieldinit();
// for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
- if (e2x.op == TOK.type)
+ if (e2x.op == EXP.type)
e2x = resolveAliasThis(sc, e2x);
e2x = resolveProperties(sc, e2x);
@@ -11164,17 +11247,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (e2x.type.ty != Tvoid)
e2x = e2x.toBoolean(sc);
- if (e2x.op == TOK.type || e2x.op == TOK.scope_)
+ if (e2x.op == EXP.type || e2x.op == EXP.scope_)
{
exp.error("`%s` is not an expression", exp.e2.toChars());
return setError();
}
- if (e1x.op == TOK.error || e1x.type.ty == Tnoreturn)
+ if (e1x.op == EXP.error || e1x.type.ty == Tnoreturn)
{
result = e1x;
return;
}
- if (e2x.op == TOK.error)
+ if (e2x.op == EXP.error)
{
result = e2x;
return;
@@ -11213,13 +11296,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
Type t1 = exp.e1.type.toBasetype();
Type t2 = exp.e2.type.toBasetype();
- if (t1.ty == Tclass && exp.e2.op == TOK.null_ || t2.ty == Tclass && exp.e1.op == TOK.null_)
+ if (t1.ty == Tclass && exp.e2.op == EXP.null_ || t2.ty == Tclass && exp.e1.op == EXP.null_)
{
exp.error("do not use `null` when comparing class types");
return setError();
}
- TOK cmpop;
+ EXP cmpop;
if (auto e = exp.op_overload(sc, &cmpop))
{
if (!e.type.isscalar() && e.type.equals(exp.e1.type))
@@ -11227,7 +11310,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.error("recursive `opCmp` expansion");
return setError();
}
- if (e.op == TOK.call)
+ if (e.op == EXP.call)
{
e = new CmpExp(cmpop, exp.loc, e, IntegerExp.literal!0);
e = e.expressionSemantic(sc);
@@ -11298,7 +11381,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
else if (t1.ty == Taarray || t2.ty == Taarray)
{
- exp.error("`%s` is not defined for associative arrays", Token.toChars(exp.op));
+ exp.error("`%s` is not defined for associative arrays", EXPtoString(exp.op).ptr);
return setError();
}
else if (!target.isVectorOpSupported(t1, exp.op, t2))
@@ -11402,7 +11485,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = e;
return;
}
- if (exp.e1.op == TOK.type || exp.e2.op == TOK.type)
+ if (exp.e1.op == EXP.type || exp.e2.op == EXP.type)
{
/* https://issues.dlang.org/show_bug.cgi?id=12520
* empty tuples are represented as types so special cases are added
@@ -11411,7 +11494,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
static auto extractTypeTupAndExpTup(Expression e)
{
static struct Result { bool ttEmpty; bool te; }
- auto tt = e.op == TOK.type ? e.isTypeExp().type.isTypeTuple() : null;
+ auto tt = e.op == EXP.type ? e.isTypeExp().type.isTypeTuple() : null;
return Result(tt && (!tt.arguments || !tt.arguments.dim), e.isTupleExp() !is null);
}
auto tups1 = extractTypeTupAndExpTup(exp.e1);
@@ -11419,19 +11502,19 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// AliasSeq!() == AliasSeq!(<at least a value>)
if (tups1.ttEmpty && tups2.te)
{
- result = IntegerExp.createBool(exp.op != TOK.equal);
+ result = IntegerExp.createBool(exp.op != EXP.equal);
return;
}
// AliasSeq!(<at least a value>) == AliasSeq!()
else if (tups1.te && tups2.ttEmpty)
{
- result = IntegerExp.createBool(exp.op != TOK.equal);
+ result = IntegerExp.createBool(exp.op != EXP.equal);
return;
}
// AliasSeq!() == AliasSeq!()
else if (tups1.ttEmpty && tups2.ttEmpty)
{
- result = IntegerExp.createBool(exp.op == TOK.equal);
+ result = IntegerExp.createBool(exp.op == EXP.equal);
return;
}
// otherwise, two types are really not comparable
@@ -11451,18 +11534,18 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* comparing the addresses of two statics. If so, we can just see
* if they are the same symbol.
*/
- if (exp.e1.op == TOK.address && exp.e2.op == TOK.address)
+ if (exp.e1.op == EXP.address && exp.e2.op == EXP.address)
{
AddrExp ae1 = cast(AddrExp)exp.e1;
AddrExp ae2 = cast(AddrExp)exp.e2;
- if (ae1.e1.op == TOK.variable && ae2.e1.op == TOK.variable)
+ if (ae1.e1.op == EXP.variable && ae2.e1.op == EXP.variable)
{
VarExp ve1 = cast(VarExp)ae1.e1;
VarExp ve2 = cast(VarExp)ae2.e1;
if (ve1.var == ve2.var)
{
// They are the same, result is 'true' for ==, 'false' for !=
- result = IntegerExp.createBool(exp.op == TOK.equal);
+ result = IntegerExp.createBool(exp.op == EXP.equal);
return;
}
}
@@ -11555,7 +11638,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
(*arguments)[1] = exp.e2;
__equals = new CallExp(exp.loc, __equals, arguments);
- if (exp.op == TOK.notEqual)
+ if (exp.op == EXP.notEqual)
{
__equals = new NotExp(exp.loc, __equals);
}
@@ -11611,7 +11694,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (f1 || f2)
return setError();
- if (exp.e1.op == TOK.type || exp.e2.op == TOK.type)
+ if (exp.e1.op == EXP.type || exp.e2.op == EXP.type)
{
result = exp.incompatibleTypes();
return;
@@ -11634,9 +11717,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
- if (exp.e1.op == TOK.call)
+ if (exp.e1.op == EXP.call)
exp.e1 = (cast(CallExp)exp.e1).addDtorHook(sc);
- if (exp.e2.op == TOK.call)
+ if (exp.e2.op == EXP.call)
exp.e2 = (cast(CallExp)exp.e2).addDtorHook(sc);
if (exp.e1.type.toBasetype().ty == Tsarray ||
@@ -11660,7 +11743,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
- if (exp.econd.op == TOK.dotIdentifier)
+ if (exp.econd.op == EXP.dotIdentifier)
(cast(DotIdExp)exp.econd).noderef = true;
Expression ec = exp.econd.expressionSemantic(sc);
@@ -11679,7 +11762,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
sc.merge(exp.loc, ctorflow1);
ctorflow1.freeFieldinit();
- if (ec.op == TOK.error)
+ if (ec.op == EXP.error)
{
result = ec;
return;
@@ -11688,7 +11771,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
exp.econd = ec;
- if (e1x.op == TOK.error)
+ if (e1x.op == EXP.error)
{
result = e1x;
return;
@@ -11697,7 +11780,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
exp.e1 = e1x;
- if (e2x.op == TOK.error)
+ if (e2x.op == EXP.error)
{
result = e2x;
return;
@@ -11957,7 +12040,7 @@ Expression unaSemantic(UnaExp e, Scope* sc)
printf("UnaExp::semantic('%s')\n", e.toChars());
}
Expression e1x = e.e1.expressionSemantic(sc);
- if (e1x.op == TOK.error)
+ if (e1x.op == EXP.error)
return e1x;
e.e1 = e1x;
return null;
@@ -11977,14 +12060,14 @@ Expression binSemantic(BinExp e, Scope* sc)
Expression e2x = e.e2.expressionSemantic(sc);
// for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
- if (e1x.op == TOK.type)
+ if (e1x.op == EXP.type)
e1x = resolveAliasThis(sc, e1x);
- if (e2x.op == TOK.type)
+ if (e2x.op == EXP.type)
e2x = resolveAliasThis(sc, e2x);
- if (e1x.op == TOK.error)
+ if (e1x.op == EXP.error)
return e1x;
- if (e2x.op == TOK.error)
+ if (e2x.op == EXP.error)
return e2x;
e.e1 = e1x;
e.e2 = e2x;
@@ -11997,9 +12080,9 @@ Expression binSemanticProp(BinExp e, Scope* sc)
return ex;
Expression e1x = resolveProperties(sc, e.e1);
Expression e2x = resolveProperties(sc, e.e2);
- if (e1x.op == TOK.error)
+ if (e1x.op == EXP.error)
return e1x;
- if (e2x.op == TOK.error)
+ if (e2x.op == EXP.error)
return e2x;
e.e1 = e1x;
e.e2 = e2x;
@@ -12049,11 +12132,11 @@ Expression semanticX(DotIdExp exp, Scope* sc)
Dsymbol ds;
switch (exp.e1.op)
{
- case TOK.scope_: return dotMangleof(exp.loc, sc, exp.e1.isScopeExp().sds);
- case TOK.variable: return dotMangleof(exp.loc, sc, exp.e1.isVarExp().var);
- case TOK.dotVariable: return dotMangleof(exp.loc, sc, exp.e1.isDotVarExp().var);
- case TOK.overloadSet: return dotMangleof(exp.loc, sc, exp.e1.isOverExp().vars);
- case TOK.template_:
+ case EXP.scope_: return dotMangleof(exp.loc, sc, exp.e1.isScopeExp().sds);
+ case EXP.variable: return dotMangleof(exp.loc, sc, exp.e1.isVarExp().var);
+ case EXP.dotVariable: return dotMangleof(exp.loc, sc, exp.e1.isDotVarExp().var);
+ case EXP.overloadSet: return dotMangleof(exp.loc, sc, exp.e1.isOverExp().vars);
+ case EXP.template_:
{
TemplateExp te = exp.e1.isTemplateExp();
return dotMangleof(exp.loc, sc, ds = te.fd ? te.fd.isDsymbol() : te.td);
@@ -12480,9 +12563,9 @@ Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag)
}
assert(e);
- if (e.op == TOK.error)
+ if (e.op == EXP.error)
return e;
- if (e.op == TOK.dotVariable)
+ if (e.op == EXP.dotVariable)
{
DotVarExp dve = cast(DotVarExp)e;
if (FuncDeclaration fd = dve.var.isFuncDeclaration())
@@ -12516,7 +12599,7 @@ Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag)
.expressionSemantic(sc);
}
}
- else if (e.op == TOK.variable)
+ else if (e.op == EXP.variable)
{
VarExp ve = cast(VarExp)e;
if (FuncDeclaration fd = ve.var.isFuncDeclaration())
@@ -12535,7 +12618,7 @@ Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag)
}
}
- if (e.op == TOK.dotTemplateDeclaration)
+ if (e.op == EXP.dotTemplateDeclaration)
{
DotTemplateExp dte = cast(DotTemplateExp)e;
exp.e1 = dte.e1; // pull semantic() result
@@ -12560,17 +12643,17 @@ Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag)
return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
.expressionSemantic(sc);
}
- else if (e.op == TOK.template_)
+ else if (e.op == EXP.template_)
{
exp.ti.tempdecl = (cast(TemplateExp)e).td;
return new ScopeExp(exp.loc, exp.ti)
.expressionSemantic(sc);
}
- else if (e.op == TOK.dot)
+ else if (e.op == EXP.dot)
{
DotExp de = cast(DotExp)e;
- if (de.e2.op == TOK.overloadSet)
+ if (de.e2.op == EXP.overloadSet)
{
if (!exp.findTempDecl(sc) || !exp.ti.semanticTiargs(sc))
{
@@ -12593,7 +12676,7 @@ Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag)
.expressionSemantic(sc);
}
}
- else if (e.op == TOK.overloadSet)
+ else if (e.op == EXP.overloadSet)
{
OverExp oe = cast(OverExp)e;
exp.ti.tempdecl = oe.vars;
@@ -12873,7 +12956,7 @@ Expression getThisSkipNestedFuncs(const ref Loc loc, Scope* sc, Dsymbol s, Aggre
}
s = s.toParent2();
}
- if (n > 1 || e1.op == TOK.index)
+ if (n > 1 || e1.op == EXP.index)
e1 = e1.expressionSemantic(sc);
if (s && e1.type.equivalent(Type.tvoidptr))
{
@@ -12967,7 +13050,7 @@ private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions
e = resolveProperties(sc, e);
if (i >= nfields)
{
- if (i <= sd.fields.dim && e.op == TOK.null_)
+ if (i <= sd.fields.dim && e.op == EXP.null_)
{
// CTFE sometimes creates null as hidden pointer; we'll allow this.
continue;
@@ -12988,7 +13071,10 @@ private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions
}
return false;
}
- offset = cast(uint)(v.offset + v.type.size());
+ const vsize = v.type.size();
+ if (vsize == SIZE_INVALID)
+ return false;
+ offset = cast(uint)(v.offset + vsize);
Type t = v.type;
if (stype)
@@ -13015,7 +13101,7 @@ private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions
* Allow this by doing an explicit cast, which will lengthen the string
* literal.
*/
- if (e.op == TOK.string_ && tb.ty == Tsarray)
+ if (e.op == EXP.string_ && tb.ty == Tsarray)
{
StringExp se = cast(StringExp)e;
Type typeb = se.type.toBasetype();
@@ -13042,7 +13128,7 @@ private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions
e = e.implicitCastTo(sc, t);
L1:
- if (e.op == TOK.error)
+ if (e.op == EXP.error)
return false;
(*elements)[i] = doCopyOrMove(sc, e);
@@ -13090,22 +13176,22 @@ Expression toBoolean(Expression exp, Scope* sc)
{
switch(exp.op)
{
- case TOK.delete_:
+ case EXP.delete_:
exp.error("`delete` does not give a boolean result");
return ErrorExp.get();
- case TOK.comma:
+ case EXP.comma:
auto ce = exp.isCommaExp();
auto ex2 = ce.e2.toBoolean(sc);
- if (ex2.op == TOK.error)
+ if (ex2.op == EXP.error)
return ex2;
ce.e2 = ex2;
ce.type = ce.e2.type;
return ce;
- case TOK.assign:
- case TOK.construct:
- case TOK.blit:
+ case EXP.assign:
+ case EXP.construct:
+ case EXP.blit:
// Things like:
// if (a = b) ...
// are usually mistakes.
@@ -13113,22 +13199,22 @@ Expression toBoolean(Expression exp, Scope* sc)
return ErrorExp.get();
//LogicalExp
- case TOK.andAnd:
- case TOK.orOr:
+ case EXP.andAnd:
+ case EXP.orOr:
auto le = exp.isLogicalExp();
auto ex2 = le.e2.toBoolean(sc);
- if (ex2.op == TOK.error)
+ if (ex2.op == EXP.error)
return ex2;
le.e2 = ex2;
return le;
- case TOK.question:
+ case EXP.question:
auto ce = exp.isCondExp();
auto ex1 = ce.e1.toBoolean(sc);
auto ex2 = ce.e2.toBoolean(sc);
- if (ex1.op == TOK.error)
+ if (ex1.op == EXP.error)
return ex1;
- if (ex2.op == TOK.error)
+ if (ex2.op == EXP.error)
return ex2;
ce.e1 = ex1;
ce.e2 = ex2;
diff --git a/gcc/d/dmd/foreachvar.d b/gcc/d/dmd/foreachvar.d
index 9579ac7d6a5..e9a43f92105 100644
--- a/gcc/d/dmd/foreachvar.d
+++ b/gcc/d/dmd/foreachvar.d
@@ -223,7 +223,7 @@ void foreachExpAndVar(Statement s,
void visitWith(WithStatement s)
{
// If it is with(Enum) {...}, just execute the body.
- if (s.exp.op == TOK.scope_ || s.exp.op == TOK.type)
+ if (s.exp.op == EXP.scope_ || s.exp.op == EXP.type)
{
}
else
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index 2d6a756178e..da33587fc88 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -1306,7 +1306,14 @@ extern (C++) class FuncDeclaration : Declaration
if (!fbody)
return false;
- if (isVirtualMethod())
+ if (isVirtualMethod() &&
+ /*
+ * https://issues.dlang.org/show_bug.cgi?id=21719
+ *
+ * If we have an auto virtual function we can infer
+ * the attributes.
+ */
+ !(inferRetType && !isCtorDeclaration()))
return false; // since they may be overridden
if (sc.func &&
diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d
index 747a1138905..7409dcc2902 100644
--- a/gcc/d/dmd/globals.d
+++ b/gcc/d/dmd/globals.d
@@ -148,7 +148,7 @@ extern (C++) struct Param
bool betterC; // be a "better C" compiler; no dependency on D runtime
bool addMain; // add a default main() function
bool allInst; // generate code for all template instantiations
- bool fix16997; // fix integral promotions for unary + - ~ operators
+ bool fix16997 = true; // fix integral promotions for unary + - ~ operators
// https://issues.dlang.org/show_bug.cgi?id=16997
bool fixAliasThis; // if the current scope has an alias this, check it before searching upper scopes
bool inclusiveInContracts; // 'in' contracts of overridden methods must be a superset of parent contract
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 4ff07b5de32..a4542986739 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -164,7 +164,7 @@ public:
override void visit(ExpStatement s)
{
- if (s.exp && s.exp.op == TOK.declaration &&
+ if (s.exp && s.exp.op == EXP.declaration &&
(cast(DeclarationExp)s.exp).declaration)
{
// bypass visit(DeclarationExp)
@@ -202,7 +202,7 @@ public:
foreach (sx; *s.statements)
{
auto ds = sx ? sx.isExpStatement() : null;
- if (ds && ds.exp.op == TOK.declaration)
+ if (ds && ds.exp.op == EXP.declaration)
{
auto d = (cast(DeclarationExp)ds.exp).declaration;
assert(d.isDeclaration());
@@ -1260,7 +1260,7 @@ public:
{
buf.writestring(" = ");
ExpInitializer ie = vd._init.isExpInitializer();
- if (ie && (ie.exp.op == TOK.construct || ie.exp.op == TOK.blit))
+ if (ie && (ie.exp.op == EXP.construct || ie.exp.op == EXP.blit))
(cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, hgs);
else
vd._init.initializerToBuffer(buf, hgs);
@@ -1511,7 +1511,7 @@ public:
{
buf.writestring(" = ");
auto ie = v._init.isExpInitializer();
- if (ie && (ie.exp.op == TOK.construct || ie.exp.op == TOK.blit))
+ if (ie && (ie.exp.op == EXP.construct || ie.exp.op == EXP.blit))
(cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, hgs);
else
v._init.initializerToBuffer(buf, hgs);
@@ -1569,7 +1569,7 @@ public:
buf.writestring("in");
if (auto es = frequire.isExpStatement())
{
- assert(es.exp && es.exp.op == TOK.assert_);
+ assert(es.exp && es.exp.op == EXP.assert_);
buf.writestring(" (");
(cast(AssertExp)es.exp).e1.expressionToBuffer(buf, hgs);
buf.writeByte(')');
@@ -1592,7 +1592,7 @@ public:
buf.writestring("out");
if (auto es = fensure.ensure.isExpStatement())
{
- assert(es.exp && es.exp.op == TOK.assert_);
+ assert(es.exp && es.exp.op == EXP.assert_);
buf.writestring(" (");
if (fensure.id)
{
@@ -1749,7 +1749,7 @@ public:
buf.writestring("invariant");
if(auto es = d.fbody.isExpStatement())
{
- assert(es.exp && es.exp.op == TOK.assert_);
+ assert(es.exp && es.exp.op == EXP.assert_);
buf.writestring(" (");
(cast(AssertExp)es.exp).e1.expressionToBuffer(buf, hgs);
buf.writestring(");");
@@ -1812,7 +1812,7 @@ public:
////////////////////////////////////////////////////////////////////////////
override void visit(Expression e)
{
- buf.writestring(Token.toString(e.op));
+ buf.writestring(EXPtoString(e.op));
}
override void visit(IntegerExp e)
@@ -2278,7 +2278,7 @@ public:
override void visit(UnaExp e)
{
- buf.writestring(Token.toString(e.op));
+ buf.writestring(EXPtoString(e.op));
expToBuffer(e.e1, precedence[e.op], buf, hgs);
}
@@ -2286,7 +2286,7 @@ public:
{
expToBuffer(e.e1, precedence[e.op], buf, hgs);
buf.writeByte(' ');
- buf.writestring(Token.toString(e.op));
+ buf.writestring(EXPtoString(e.op));
buf.writeByte(' ');
expToBuffer(e.e2, cast(PREC)(precedence[e.op] + 1), buf, hgs);
}
@@ -2415,7 +2415,7 @@ public:
override void visit(CallExp e)
{
- if (e.e1.op == TOK.type)
+ if (e.e1.op == EXP.type)
{
/* Avoid parens around type to prevent forbidden cast syntax:
* (sometype)(arg1)
@@ -2540,12 +2540,12 @@ public:
override void visit(PostExp e)
{
expToBuffer(e.e1, precedence[e.op], buf, hgs);
- buf.writestring(Token.toString(e.op));
+ buf.writestring(EXPtoString(e.op));
}
override void visit(PreExp e)
{
- buf.writestring(Token.toString(e.op));
+ buf.writestring(EXPtoString(e.op));
expToBuffer(e.e1, precedence[e.op], buf, hgs);
}
@@ -2568,7 +2568,7 @@ public:
override void visit(DefaultInitExp e)
{
- buf.writestring(Token.toString(e.op));
+ buf.writestring(EXPtoString(e.op));
}
override void visit(ClassReferenceExp e)
@@ -3144,7 +3144,7 @@ private void parameterToBuffer(Parameter p, OutBuffer* buf, HdrGenState* hgs)
{
buf.writeByte('@');
- bool isAnonymous = p.userAttribDecl.atts.dim > 0 && (*p.userAttribDecl.atts)[0].op != TOK.call;
+ bool isAnonymous = p.userAttribDecl.atts.dim > 0 && !(*p.userAttribDecl.atts)[0].isCallExp();
if (isAnonymous)
buf.writeByte('(');
@@ -3253,9 +3253,9 @@ private void sizeToBuffer(Expression e, OutBuffer* buf, HdrGenState* hgs)
{
if (e.type == Type.tsize_t)
{
- Expression ex = (e.op == TOK.cast_ ? (cast(CastExp)e).e1 : e);
+ Expression ex = (e.op == EXP.cast_ ? (cast(CastExp)e).e1 : e);
ex = ex.optimize(WANTvalue);
- const dinteger_t uval = ex.op == TOK.int64 ? ex.toInteger() : cast(dinteger_t)-1;
+ const dinteger_t uval = ex.op == EXP.int64 ? ex.toInteger() : cast(dinteger_t)-1;
if (cast(sinteger_t)uval >= 0)
{
dinteger_t sizemax = void;
@@ -3292,7 +3292,7 @@ private void expToBuffer(Expression e, PREC pr, OutBuffer* buf, HdrGenState* hgs
debug
{
if (precedence[e.op] == PREC.zero)
- printf("precedence not defined for token '%s'\n", Token.toChars(e.op));
+ printf("precedence not defined for token '%s'\n", EXPtoString(e.op).ptr);
}
if (e.op == 0xFF)
{
@@ -3422,7 +3422,7 @@ private void tiargsToBuffer(TemplateInstance ti, OutBuffer* buf, HdrGenState* hg
}
else if (Expression e = isExpression(oarg))
{
- if (e.op == TOK.int64 || e.op == TOK.float64 || e.op == TOK.null_ || e.op == TOK.string_ || e.op == TOK.this_)
+ if (e.op == EXP.int64 || e.op == EXP.float64 || e.op == EXP.null_ || e.op == EXP.string_ || e.op == EXP.this_)
{
buf.writestring(e.toChars());
return;
@@ -3460,7 +3460,7 @@ private void objectToBuffer(RootObject oarg, OutBuffer* buf, HdrGenState* hgs)
}
else if (auto e = isExpression(oarg))
{
- if (e.op == TOK.variable)
+ if (e.op == EXP.variable)
e = e.optimize(WANTvalue); // added to fix https://issues.dlang.org/show_bug.cgi?id=7375
expToBuffer(e, PREC.assign, buf, hgs);
}
@@ -3962,3 +3962,158 @@ private void typeToBufferx(Type t, OutBuffer* buf, HdrGenState* hgs)
case Ttag: return visitTag(cast(TypeTag)t);
}
}
+
+/****************************************
+ * Convert EXP to char*.
+ */
+
+string EXPtoString(EXP op)
+{
+ static immutable char*[EXP.max + 1] strings =
+ [
+ EXP.type : "type",
+ EXP.error : "error",
+ EXP.objcClassReference : "class",
+
+ EXP.typeof_ : "typeof",
+ EXP.mixin_ : "mixin",
+
+ EXP.import_ : "import",
+ EXP.dotVariable : "dotvar",
+ EXP.scope_ : "scope",
+ EXP.identifier : "identifier",
+ EXP.this_ : "this",
+ EXP.super_ : "super",
+ EXP.int64 : "long",
+ EXP.float64 : "double",
+ EXP.complex80 : "creal",
+ EXP.null_ : "null",
+ EXP.string_ : "string",
+ EXP.arrayLiteral : "arrayliteral",
+ EXP.assocArrayLiteral : "assocarrayliteral",
+ EXP.classReference : "classreference",
+ EXP.file : "__FILE__",
+ EXP.fileFullPath : "__FILE_FULL_PATH__",
+ EXP.line : "__LINE__",
+ EXP.moduleString : "__MODULE__",
+ EXP.functionString : "__FUNCTION__",
+ EXP.prettyFunction : "__PRETTY_FUNCTION__",
+ EXP.typeid_ : "typeid",
+ EXP.is_ : "is",
+ EXP.assert_ : "assert",
+ EXP.halt : "halt",
+ EXP.template_ : "template",
+ EXP.dSymbol : "symbol",
+ EXP.function_ : "function",
+ EXP.variable : "var",
+ EXP.symbolOffset : "symoff",
+ EXP.structLiteral : "structLiteral",
+ EXP.compoundLiteral : "compoundliteral",
+ EXP.arrayLength : "arraylength",
+ EXP.delegatePointer : "delegateptr",
+ EXP.delegateFunctionPointer : "delegatefuncptr",
+ EXP.remove : "remove",
+ EXP.tuple : "tuple",
+ EXP.traits : "__traits",
+ EXP.default_ : "default",
+ EXP.overloadSet : "__overloadset",
+ EXP.void_ : "void",
+ EXP.vectorArray : "vectorarray",
+ EXP._Generic : "_Generic",
+
+ // post
+ EXP.dotTemplateInstance : "dotti",
+ EXP.dotIdentifier : "dotid",
+ EXP.dotTemplateDeclaration : "dottd",
+ EXP.dot : ".",
+ EXP.dotType : "dottype",
+ EXP.plusPlus : "++",
+ EXP.minusMinus : "--",
+ EXP.prePlusPlus : "++",
+ EXP.preMinusMinus : "--",
+ EXP.call : "call",
+ EXP.slice : "..",
+ EXP.array : "[]",
+ EXP.index : "[i]",
+
+ EXP.delegate_ : "delegate",
+ EXP.address : "&",
+ EXP.star : "*",
+ EXP.negate : "-",
+ EXP.uadd : "+",
+ EXP.not : "!",
+ EXP.tilde : "~",
+ EXP.delete_ : "delete",
+ EXP.new_ : "new",
+ EXP.newAnonymousClass : "newanonclass",
+ EXP.cast_ : "cast",
+
+ EXP.vector : "__vector",
+ EXP.pow : "^^",
+
+ EXP.mul : "*",
+ EXP.div : "/",
+ EXP.mod : "%",
+
+ EXP.add : "+",
+ EXP.min : "-",
+ EXP.concatenate : "~",
+
+ EXP.leftShift : "<<",
+ EXP.rightShift : ">>",
+ EXP.unsignedRightShift : ">>>",
+
+ EXP.lessThan : "<",
+ EXP.lessOrEqual : "<=",
+ EXP.greaterThan : ">",
+ EXP.greaterOrEqual : ">=",
+ EXP.in_ : "in",
+
+ EXP.equal : "==",
+ EXP.notEqual : "!=",
+ EXP.identity : "is",
+ EXP.notIdentity : "!is",
+
+ EXP.and : "&",
+ EXP.xor : "^",
+ EXP.or : "|",
+
+ EXP.andAnd : "&&",
+ EXP.orOr : "||",
+
+ EXP.question : "?",
+
+ EXP.assign : "=",
+ EXP.construct : "=",
+ EXP.blit : "=",
+ EXP.addAssign : "+=",
+ EXP.minAssign : "-=",
+ EXP.concatenateAssign : "~=",
+ EXP.concatenateElemAssign : "~=",
+ EXP.concatenateDcharAssign : "~=",
+ EXP.mulAssign : "*=",
+ EXP.divAssign : "/=",
+ EXP.modAssign : "%=",
+ EXP.powAssign : "^^=",
+ EXP.leftShiftAssign : "<<=",
+ EXP.rightShiftAssign : ">>=",
+ EXP.unsignedRightShiftAssign : ">>>=",
+ EXP.andAssign : "&=",
+ EXP.orAssign : "|=",
+ EXP.xorAssign : "^=",
+
+ EXP.comma : ",",
+ EXP.declaration : "declaration",
+
+ EXP.interval : "interval",
+ ];
+ const p = strings[op];
+ if (!p)
+ {
+ printf("error: EXP %d has no string\n", op);
+ return "XXXXX";
+ //assert(0);
+ }
+ assert(p);
+ return p[0 .. strlen(p)];
+}
diff --git a/gcc/d/dmd/iasmgcc.d b/gcc/d/dmd/iasmgcc.d
index 3ff0e894e2a..cd3011731f5 100644
--- a/gcc/d/dmd/iasmgcc.d
+++ b/gcc/d/dmd/iasmgcc.d
@@ -348,7 +348,7 @@ extern (C++) public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
e = (*s.constraints)[i];
e = e.expressionSemantic(sc);
- assert(e.op == TOK.string_ && (cast(StringExp) e).sz == 1);
+ assert(e.op == EXP.string_ && (cast(StringExp) e).sz == 1);
(*s.constraints)[i] = e;
}
}
@@ -360,7 +360,7 @@ extern (C++) public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc)
{
Expression e = (*s.clobbers)[i];
e = e.expressionSemantic(sc);
- assert(e.op == TOK.string_ && (cast(StringExp) e).sz == 1);
+ assert(e.op == EXP.string_ && (cast(StringExp) e).sz == 1);
(*s.clobbers)[i] = e;
}
}
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index 1ee51533b53..83c89c05fda 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -315,6 +315,8 @@ immutable Msgtable[] msgtable =
{ "dup" },
{ "_aaApply" },
{ "_aaApply2" },
+ { "_d_arrayctor" },
+ { "_d_arraysetctor" },
// For pragma's
{ "Pinline", "inline" },
@@ -463,6 +465,7 @@ immutable Msgtable[] msgtable =
{ "getUnitTests" },
{ "getVirtualIndex" },
{ "getPointerBitmap" },
+ { "initSymbol" },
{ "getCppNamespaces" },
{ "isReturnOnStack" },
{ "isZeroInit" },
diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index 5828486c6fe..c5aa0f46dd1 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/dmd/initsem.d
@@ -225,7 +225,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
auto tm = vd.type.addMod(t.mod);
auto iz = i.value[j].initializerSemantic(sc, tm, needInterpret);
auto ex = iz.initializerToExpression();
- if (ex.op == TOK.error)
+ if (ex.op == EXP.error)
{
errors = true;
elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
@@ -331,7 +331,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
errors = true;
}
length = cast(uint)idxvalue;
- if (idx.op == TOK.error)
+ if (idx.op == EXP.error)
errors = true;
}
Initializer val = i.value[j];
@@ -344,7 +344,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
errors = true;
ei = val.isExpInitializer();
// found a tuple, expand it
- if (ei && ei.exp.op == TOK.tuple)
+ if (ei && ei.exp.op == EXP.tuple)
{
TupleExp te = cast(TupleExp)ei.exp;
i.index.remove(j);
@@ -384,6 +384,8 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
return err();
const sz = t.nextOf().size();
+ if (sz == SIZE_INVALID)
+ return err();
bool overflow;
const max = mulu(i.dim, sz, overflow);
if (overflow || max >= amax)
@@ -403,7 +405,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
i.exp = resolveProperties(sc, i.exp);
if (needInterpret)
sc = sc.endCTFE();
- if (i.exp.op == TOK.error)
+ if (i.exp.op == EXP.error)
return err();
uint olderrors = global.errors;
@@ -437,7 +439,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
*/
i.exp = i.exp.optimize(WANTvalue);
i.exp = i.exp.ctfeInterpret();
- if (i.exp.op == TOK.voidExpression)
+ if (i.exp.op == EXP.voidExpression)
error(i.loc, "variables cannot be initialized with an expression of type `void`. Use `void` initialization instead.");
}
else
@@ -455,7 +457,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
i.exp = new TupleExp(i.exp.loc, new Expressions());
i.exp.type = et;
}
- if (i.exp.op == TOK.type)
+ if (i.exp.op == EXP.type)
{
i.exp.error("initializer must be an expression, not `%s`", i.exp.toChars());
return err();
@@ -467,7 +469,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
return err();
}
Type ti = i.exp.type.toBasetype();
- if (i.exp.op == TOK.tuple && i.expandTuples && !i.exp.implicitConvTo(t))
+ if (i.exp.op == EXP.tuple && i.expandTuples && !i.exp.implicitConvTo(t))
{
return new ExpInitializer(i.loc, i.exp);
}
@@ -477,7 +479,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
* Allow this by doing an explicit cast, which will lengthen the string
* literal.
*/
- if (i.exp.op == TOK.string_ && tb.ty == Tsarray)
+ if (i.exp.op == EXP.string_ && tb.ty == Tsarray)
{
StringExp se = cast(StringExp)i.exp;
Type typeb = se.type.toBasetype();
@@ -562,12 +564,12 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
{
uinteger_t dim1 = (cast(TypeSArray)tb).dim.toInteger();
uinteger_t dim2 = dim1;
- if (i.exp.op == TOK.arrayLiteral)
+ if (i.exp.op == EXP.arrayLiteral)
{
ArrayLiteralExp ale = cast(ArrayLiteralExp)i.exp;
dim2 = ale.elements ? ale.elements.dim : 0;
}
- else if (i.exp.op == TOK.slice)
+ else if (i.exp.op == EXP.slice)
{
Type tx = toStaticArrayType(cast(SliceExp)i.exp);
if (tx)
@@ -582,7 +584,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
i.exp = i.exp.implicitCastTo(sc, t);
}
L1:
- if (i.exp.op == TOK.error)
+ if (i.exp.op == EXP.error)
{
return i;
}
@@ -667,7 +669,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
auto tm = vd.type.addMod(ts.mod);
auto iz = di.initializer.initializerSemantic(sc, tm, needInterpret);
auto ex = iz.initializerToExpression();
- if (ex.op == TOK.error)
+ if (ex.op == EXP.error)
{
errors = true;
continue;
@@ -823,6 +825,8 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ
}
const sz = tn.size(); // element size
+ if (sz == SIZE_INVALID)
+ return err();
bool overflow;
const max = mulu(edim, sz, overflow);
if (overflow || max >= amax)
@@ -930,7 +934,7 @@ Initializer inferType(Initializer init, Scope* sc)
}
assert(iz.isExpInitializer());
(*values)[i] = (cast(ExpInitializer)iz).exp;
- assert((*values)[i].op != TOK.error);
+ assert(!(*values)[i].isErrorExp());
}
Expression e = new AssocArrayLiteralExp(init.loc, keys, values);
auto ei = new ExpInitializer(init.loc, e);
@@ -953,7 +957,7 @@ Initializer inferType(Initializer init, Scope* sc)
}
assert(iz.isExpInitializer());
(*elements)[i] = (cast(ExpInitializer)iz).exp;
- assert((*elements)[i].op != TOK.error);
+ assert(!(*elements)[i].isErrorExp());
}
Expression e = new ArrayLiteralExp(init.loc, null, elements);
auto ei = new ExpInitializer(init.loc, e);
@@ -977,11 +981,11 @@ Initializer inferType(Initializer init, Scope* sc)
init.exp = init.exp.expressionSemantic(sc);
// for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
- if (init.exp.op == TOK.type)
+ if (init.exp.op == EXP.type)
init.exp = resolveAliasThis(sc, init.exp);
init.exp = resolveProperties(sc, init.exp);
- if (init.exp.op == TOK.scope_)
+ if (init.exp.op == EXP.scope_)
{
ScopeExp se = cast(ScopeExp)init.exp;
TemplateInstance ti = se.sds.isTemplateInstance();
@@ -1006,16 +1010,16 @@ Initializer inferType(Initializer init, Scope* sc)
return new ErrorInitializer();
}
}
- if (init.exp.op == TOK.address)
+ if (init.exp.op == EXP.address)
{
AddrExp ae = cast(AddrExp)init.exp;
- if (ae.e1.op == TOK.overloadSet)
+ if (ae.e1.op == EXP.overloadSet)
{
init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
return new ErrorInitializer();
}
}
- if (init.exp.op == TOK.error)
+ if (init.exp.op == EXP.error)
{
return new ErrorInitializer();
}
@@ -1125,7 +1129,7 @@ extern (C++) Expression initializerToExpression(Initializer init, Type itype = n
{
if (auto e = init.index[i])
{
- if (e.op == TOK.int64)
+ if (e.op == EXP.int64)
{
const uinteger_t idxval = e.toInteger();
if (idxval >= amax)
@@ -1206,7 +1210,7 @@ extern (C++) Expression initializerToExpression(Initializer init, Type itype = n
*/
foreach (e; (*elements)[0 .. edim])
{
- if (e.op == TOK.error)
+ if (e.op == EXP.error)
{
return e;
}
@@ -1222,7 +1226,7 @@ extern (C++) Expression initializerToExpression(Initializer init, Type itype = n
{
//printf("ExpInitializer::toExpression(t = %s) exp = %s\n", itype.toChars(), i.exp.toChars());
Type tb = itype.toBasetype();
- Expression e = (i.exp.op == TOK.construct || i.exp.op == TOK.blit) ? (cast(AssignExp)i.exp).e2 : i.exp;
+ Expression e = (i.exp.op == EXP.construct || i.exp.op == EXP.blit) ? (cast(AssignExp)i.exp).e2 : i.exp;
if (tb.ty == Tsarray && e.implicitConvTo(tb.nextOf()))
{
TypeSArray tsa = cast(TypeSArray)tb;
@@ -1277,7 +1281,7 @@ private bool hasNonConstPointers(Expression e)
if (e.type.ty == Terror)
return false;
- if (e.op == TOK.null_)
+ if (e.op == EXP.null_)
return false;
if (auto se = e.isStructLiteralExp())
{
@@ -1318,11 +1322,11 @@ private bool hasNonConstPointers(Expression e)
}
if (e.type.ty == Tpointer && !e.type.isPtrToFunction())
{
- if (e.op == TOK.symbolOffset) // address of a global is OK
+ if (e.op == EXP.symbolOffset) // address of a global is OK
return false;
- if (e.op == TOK.int64) // cast(void *)int is OK
+ if (e.op == EXP.int64) // cast(void *)int is OK
return false;
- if (e.op == TOK.string_) // "abc".ptr is OK
+ if (e.op == EXP.string_) // "abc".ptr is OK
return false;
return true;
}
diff --git a/gcc/d/dmd/lambdacomp.d b/gcc/d/dmd/lambdacomp.d
index 44a6c066507..336f8dd80ec 100644
--- a/gcc/d/dmd/lambdacomp.d
+++ b/gcc/d/dmd/lambdacomp.d
@@ -26,6 +26,7 @@ import dmd.dtemplate;
import dmd.expression;
import dmd.func;
import dmd.dmangle;
+import dmd.hdrgen;
import dmd.mtype;
import dmd.common.outbuffer;
import dmd.root.rmem;
@@ -337,7 +338,7 @@ public:
return;
buf.writeByte('(');
- buf.writestring(Token.toString(exp.op));
+ buf.writestring(EXPtoString(exp.op));
exp.e1.accept(this);
if (buf.length != 0)
buf.writestring(")_");
@@ -370,7 +371,7 @@ public:
return;
buf.writeByte('(');
- buf.writestring(Token.toChars(exp.op));
+ buf.writestring(EXPtoString(exp.op).ptr);
exp.e1.accept(this);
if (buf.length == 0)
diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d
index e2b4199b80a..d38cce4ca00 100644
--- a/gcc/d/dmd/lexer.d
+++ b/gcc/d/dmd/lexer.d
@@ -386,6 +386,20 @@ class Lexer
// Intentionally not advancing `p`, such that subsequent calls keep returning TOK.endOfFile.
return;
case ' ':
+ // Skip 4 spaces at a time after aligning 'p' to a 4-byte boundary.
+ while ((cast(size_t)p) % uint.sizeof)
+ {
+ if (*p != ' ')
+ goto LendSkipFourSpaces;
+ p++;
+ }
+ while (*(cast(uint*)p) == 0x20202020) // ' ' == 0x20
+ p += 4;
+ // Skip over any remaining space on the line.
+ while (*p == ' ')
+ p++;
+ LendSkipFourSpaces:
+ continue; // skip white space
case '\t':
case '\v':
case '\f':
@@ -394,19 +408,11 @@ class Lexer
case '\r':
p++;
if (*p != '\n') // if CR stands by itself
- {
endOfLine();
- goto skipFourSpaces;
- }
continue; // skip white space
case '\n':
p++;
endOfLine();
- skipFourSpaces:
- while (*(cast(uint*)p) == 0x20202020) //' ' == 0x20
- {
- p+=4;
- }
continue; // skip white space
case '0':
if (!isZeroSecond(p[1])) // if numeric literal does not continue
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index a21924b3aac..e338a05a524 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -515,7 +515,7 @@ extern (C++) abstract class Type : ASTNode
}
else if (tp1.ty == Tdelegate)
{
- if (tp1.implicitConvTo(tp2))
+ if (tp2.implicitConvTo(tp1))
goto Lcov;
}
}
@@ -4783,7 +4783,7 @@ extern (C++) final class TypeFunction : TypeNext
goto Nomatch;
}
- if (arg.op == TOK.string_ && tp.ty == Tsarray)
+ if (arg.op == EXP.string_ && tp.ty == Tsarray)
{
if (ta.ty != Tsarray)
{
@@ -4792,7 +4792,7 @@ extern (C++) final class TypeFunction : TypeNext
ta = tn.sarrayOf(dim);
}
}
- else if (arg.op == TOK.slice && tp.ty == Tsarray)
+ else if (arg.op == EXP.slice && tp.ty [...]
[diff truncated at 524288 bytes]
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-12-10 4:27 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-10 4:27 [gcc r12-5887] d: Merge upstream dmd 3982604c5, druntime bc58b1e9, phobos 12329adb6 Iain Buclaw
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).