aboutsummaryrefslogtreecommitdiff
path: root/gcc/d
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2022-03-29 16:57:10 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2022-04-02 23:56:52 +0200
commit235d5a96cb8dad0b4c427602346fcf966a4ec914 (patch)
treeca19c774a19ad923e5d6f09d43ee8d89c275a96e /gcc/d
parentbe07535d0f43390b8906826cc119473dea514b54 (diff)
downloadgcc-235d5a96cb8dad0b4c427602346fcf966a4ec914.zip
gcc-235d5a96cb8dad0b4c427602346fcf966a4ec914.tar.gz
gcc-235d5a96cb8dad0b4c427602346fcf966a4ec914.tar.bz2
d: Merge upstream dmd 47871363d, druntime, c52e28b7, phobos 99e9c1b77.
D front-end changes: - Import dmd v2.099.1-beta.1. - The address of NRVO variables is now stored in scoped closures when they have nested references. - Using `__traits(parameters)' in foreach loops now always returns the parameters to the function the foreach appears within. Previously, when used inside a `foreach' using an overloaded `opApply', the trait would yield the parameters to the delegate. - The deprecation period of unannotated `asm' blocks has been ended. - The `inout' attribute no longer implies the `return' attribute. - Added new `D_PreConditions', `D_PostConditions', and `D_Invariants' version identifiers. D runtime changes: - Import druntime v2.099.1-beta.1. Phobos changes: - Import phobos v2.099.1-beta.1. - `Nullable' in `std.typecons' can now act as a range. - std.experimental.logger default level changed to `info' instead of `warning'. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 47871363d. * d-builtins.cc (d_init_versions): Add predefined version identifiers D_PreConditions, D_PostConditions, and D_Invariants. * d-codegen.cc (d_build_call): Update for new front-end interface. (build_frame_type): Generate reference field for NRVO variables with nested references. (build_closure): Generate assignment of return address to closure. * d-tree.h (DECL_INSTANTIATED): Use DECL_LANG_FLAG_2. (bind_expr): Remove. * decl.cc (DeclVisitor::visit (FuncDeclaration *)): Update for new front-end interface. (get_symbol_decl): Likewise. (get_decl_tree): Check DECL_LANG_FRAME_FIELD before DECL_LANG_NRVO. Dereference the field when both are set. * expr.cc (ExprVisitor::visit (DeleteExp *)): Update for new front-end interface. * modules.cc (get_internal_fn): Likewise. * toir.cc (IRVisitor::visit (ReturnStatement *)): Likewise. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime c52e28b7. * libdruntime/Makefile.am (DRUNTIME_DSOURCES_OPENBSD): Add core/sys/openbsd/pwd.d. * libdruntime/Makefile.in: Regenerate. * src/MERGE: Merge upstream phobos 99e9c1b77. * testsuite/libphobos.exceptions/message_with_null.d: New test. gcc/testsuite/ChangeLog: * gdc.dg/nrvo1.d: New test.
Diffstat (limited to 'gcc/d')
-rw-r--r--gcc/d/d-builtins.cc9
-rw-r--r--gcc/d/d-codegen.cc28
-rw-r--r--gcc/d/d-tree.h3
-rw-r--r--gcc/d/decl.cc52
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/VERSION2
-rw-r--r--gcc/d/dmd/aggregate.d6
-rw-r--r--gcc/d/dmd/aliasthis.d4
-rw-r--r--gcc/d/dmd/arrayop.d10
-rw-r--r--gcc/d/dmd/arraytypes.d1
-rw-r--r--gcc/d/dmd/arraytypes.h1
-rw-r--r--gcc/d/dmd/blockexit.d5
-rw-r--r--gcc/d/dmd/clone.d38
-rw-r--r--gcc/d/dmd/constfold.d135
-rw-r--r--gcc/d/dmd/cparse.d70
-rw-r--r--gcc/d/dmd/ctfeexpr.d164
-rw-r--r--gcc/d/dmd/ctorflow.d1
-rw-r--r--gcc/d/dmd/dcast.d1
-rw-r--r--gcc/d/dmd/declaration.d115
-rw-r--r--gcc/d/dmd/declaration.h71
-rw-r--r--gcc/d/dmd/denum.d5
-rw-r--r--gcc/d/dmd/dinterpret.d150
-rw-r--r--gcc/d/dmd/dmangle.d6
-rw-r--r--gcc/d/dmd/dmodule.d2
-rw-r--r--gcc/d/dmd/dscope.d25
-rw-r--r--gcc/d/dmd/dsymbol.d17
-rw-r--r--gcc/d/dmd/dsymbol.h2
-rw-r--r--gcc/d/dmd/dsymbolsem.d96
-rw-r--r--gcc/d/dmd/dtemplate.d26
-rw-r--r--gcc/d/dmd/dtoh.d83
-rw-r--r--gcc/d/dmd/escape.d77
-rw-r--r--gcc/d/dmd/expression.d20
-rw-r--r--gcc/d/dmd/expressionsem.d161
-rw-r--r--gcc/d/dmd/file_manager.d35
-rw-r--r--gcc/d/dmd/foreachvar.d1
-rw-r--r--gcc/d/dmd/func.d290
-rw-r--r--gcc/d/dmd/globals.d5
-rw-r--r--gcc/d/dmd/globals.h4
-rw-r--r--gcc/d/dmd/hdrgen.d25
-rw-r--r--gcc/d/dmd/importc.d39
-rw-r--r--gcc/d/dmd/init.h2
-rw-r--r--gcc/d/dmd/initsem.d5
-rw-r--r--gcc/d/dmd/lexer.d155
-rw-r--r--gcc/d/dmd/mtype.d210
-rw-r--r--gcc/d/dmd/nogc.d4
-rw-r--r--gcc/d/dmd/ob.d9
-rw-r--r--gcc/d/dmd/opover.d14
-rw-r--r--gcc/d/dmd/optimize.d48
-rw-r--r--gcc/d/dmd/parse.d2
-rw-r--r--gcc/d/dmd/printast.d2
-rw-r--r--gcc/d/dmd/root/aav.d8
-rw-r--r--gcc/d/dmd/root/array.h1
-rw-r--r--gcc/d/dmd/root/bitarray.d3
-rw-r--r--gcc/d/dmd/root/file.d31
-rw-r--r--gcc/d/dmd/root/stringtable.d2
-rw-r--r--gcc/d/dmd/sapply.d1
-rw-r--r--gcc/d/dmd/semantic3.d35
-rw-r--r--gcc/d/dmd/statement.d3
-rw-r--r--gcc/d/dmd/statementsem.d39
-rw-r--r--gcc/d/dmd/tokens.d58
-rw-r--r--gcc/d/dmd/tokens.h1
-rw-r--r--gcc/d/dmd/traits.d23
-rw-r--r--gcc/d/dmd/typesem.d19
-rw-r--r--gcc/d/dmd/utils.d2
-rw-r--r--gcc/d/expr.cc2
-rw-r--r--gcc/d/modules.cc2
-rw-r--r--gcc/d/toir.cc2
67 files changed, 1324 insertions, 1146 deletions
diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index 73b4766..7e7fb75 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -484,6 +484,15 @@ d_init_versions (void)
if (global.params.useAssert == CHECKENABLEon)
VersionCondition::addPredefinedGlobalIdent ("assert");
+ if (global.params.useIn == CHECKENABLEon)
+ VersionCondition::addPredefinedGlobalIdent("D_PreConditions");
+
+ if (global.params.useOut == CHECKENABLEon)
+ VersionCondition::addPredefinedGlobalIdent("D_PostConditions");
+
+ if (global.params.useInvariants == CHECKENABLEon)
+ VersionCondition::addPredefinedGlobalIdent("D_Invariants");
+
if (global.params.useArrayBounds == CHECKENABLEoff)
VersionCondition::addPredefinedGlobalIdent ("D_NoBoundsChecks");
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 3206edd..bb96b2f 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -2207,9 +2207,9 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
build_address (targ));
}
- /* Type `noreturn` is a terminator, as no other arguments can possibly
- be evaluated after it. */
- if (TREE_TYPE (targ) == noreturn_type_node)
+ /* Type `noreturn` is a terminator, as no other arguments can possibly
+ be evaluated after it. */
+ if (TREE_TYPE (targ) == noreturn_type_node)
noreturn_call = true;
vec_safe_push (args, targ);
@@ -2690,9 +2690,15 @@ build_frame_type (tree ffi, FuncDeclaration *fd)
DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (vsym);
TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (vsym);
- /* Can't do nrvo if the variable is put in a frame. */
- if (fd->nrvo_can && fd->nrvo_var == v)
- fd->nrvo_can = 0;
+ if (DECL_LANG_NRVO (vsym))
+ {
+ /* Store the nrvo variable in the frame by reference. */
+ TREE_TYPE (field) = build_reference_type (TREE_TYPE (field));
+
+ /* Can't do nrvo if the variable is put in a closure, since what the
+ return slot points to may no longer exist. */
+ gcc_assert (!FRAMEINFO_IS_CLOSURE (ffi));
+ }
if (FRAMEINFO_IS_CLOSURE (ffi))
{
@@ -2769,13 +2775,17 @@ build_closure (FuncDeclaration *fd)
for (size_t i = 0; i < fd->closureVars.length; i++)
{
VarDeclaration *v = fd->closureVars[i];
+ tree vsym = get_symbol_decl (v);
- if (!v->isParameter ())
+ if (TREE_CODE (vsym) != PARM_DECL && !DECL_LANG_NRVO (vsym))
continue;
- tree vsym = get_symbol_decl (v);
-
tree field = component_ref (decl_ref, DECL_LANG_FRAME_FIELD (vsym));
+
+ /* Variable is an alias for the NRVO slot, store the reference. */
+ if (DECL_LANG_NRVO (vsym))
+ vsym = build_address (DECL_LANG_NRVO (vsym));
+
tree expr = modify_expr (field, vsym);
add_stmt (expr);
}
diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h
index 5dec2e6..d93d02c 100644
--- a/gcc/d/d-tree.h
+++ b/gcc/d/d-tree.h
@@ -392,7 +392,7 @@ lang_tree_node
/* True if the decl comes from a template instance. */
#define DECL_INSTANTIATED(NODE) \
- (DECL_LANG_FLAG_1 (VAR_OR_FUNCTION_DECL_CHECK (NODE)))
+ (DECL_LANG_FLAG_2 (VAR_OR_FUNCTION_DECL_CHECK (NODE)))
enum d_tree_index
{
@@ -580,7 +580,6 @@ extern tree build_bounds_index_condition (IndexExp *, tree, tree);
extern tree build_bounds_slice_condition (SliceExp *, tree, tree, tree);
extern bool array_bounds_check (void);
extern bool checkaction_trap_p (void);
-extern tree bind_expr (tree, tree);
extern TypeFunction *get_function_type (Type *);
extern bool call_by_alias_p (FuncDeclaration *, FuncDeclaration *);
extern tree d_build_call_expr (FuncDeclaration *, tree, Expressions *);
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 7ec0caf..ea8baef 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -791,7 +791,7 @@ public:
return;
}
- if (d->semantic3Errors)
+ if (d->hasSemantic3Errors ())
return;
if (d->isNested ())
@@ -805,7 +805,7 @@ public:
break;
/* Parent failed to compile, but errors were gagged. */
- if (fdp->semantic3Errors)
+ if (fdp->hasSemantic3Errors ())
return;
}
}
@@ -921,15 +921,6 @@ public:
}
}
- /* May change cfun->static_chain. */
- build_closure (d);
-
- if (d->vresult)
- declare_local_var (d->vresult);
-
- if (d->v_argptr)
- push_stmt_list ();
-
/* Named return value optimisation support for D.
Implemented by overriding all the RETURN_EXPRs and replacing all
occurrences of VAR with the RESULT_DECL for the function.
@@ -951,7 +942,7 @@ public:
else
d->shidden = resdecl;
- if (d->nrvo_can && d->nrvo_var)
+ if (d->isNRVO () && d->nrvo_var)
{
tree var = get_symbol_decl (d->nrvo_var);
@@ -966,6 +957,15 @@ public:
}
}
+ /* May change cfun->static_chain. */
+ build_closure (d);
+
+ if (d->vresult)
+ declare_local_var (d->vresult);
+
+ if (d->v_argptr)
+ push_stmt_list ();
+
build_function_body (d);
/* Initialize the _argptr variable. */
@@ -1284,26 +1284,26 @@ get_symbol_decl (Declaration *decl)
/* In [pragma/crtctor], Annotates a function so it is run after the C
runtime library is initialized and before the D runtime library is
initialized. */
- if (fd->isCrtCtorDtor == 1)
+ if (fd->isCrtCtor ())
{
DECL_STATIC_CONSTRUCTOR (decl->csym) = 1;
decl_init_priority_insert (decl->csym, DEFAULT_INIT_PRIORITY);
}
- else if (fd->isCrtCtorDtor == 2)
+ else if (fd->isCrtDtor ())
{
DECL_STATIC_DESTRUCTOR (decl->csym) = 1;
decl_fini_priority_insert (decl->csym, DEFAULT_INIT_PRIORITY);
- }
+ }
/* Function was declared `naked'. */
- if (fd->naked)
+ if (fd->isNaked ())
{
insert_decl_attribute (decl->csym, "naked");
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl->csym) = 1;
}
/* Mark compiler generated functions as artificial. */
- if (fd->generated)
+ if (fd->isGenerated ())
DECL_ARTIFICIAL (decl->csym) = 1;
/* Ensure and require contracts are lexically nested in the function they
@@ -1486,20 +1486,26 @@ get_decl_tree (Declaration *decl)
if (vd == NULL || fd == NULL)
return t;
- /* Get the named return value. */
- if (DECL_LANG_NRVO (t))
- return DECL_LANG_NRVO (t);
-
/* Get the closure holding the var decl. */
if (DECL_LANG_FRAME_FIELD (t))
{
FuncDeclaration *parent = vd->toParent2 ()->isFuncDeclaration ();
tree frame_ref = get_framedecl (fd, parent);
- return component_ref (build_deref (frame_ref),
- DECL_LANG_FRAME_FIELD (t));
+ tree field = component_ref (build_deref (frame_ref),
+ DECL_LANG_FRAME_FIELD (t));
+ /* Frame field can also be a reference to the DECL_RESULT of a function.
+ Dereference it to get the value. */
+ if (DECL_LANG_NRVO (t))
+ field = build_deref (field);
+
+ return field;
}
+ /* Get the named return value. */
+ if (DECL_LANG_NRVO (t))
+ return DECL_LANG_NRVO (t);
+
/* Get the non-local `this' value by going through parent link
of nested classes, this routine pretty much undoes what
getRightThis in the frontend removes from codegen. */
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 3e3e113..ca409df 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-2503f17e5767bc4fcd0cf3889c90fa0415b0edaa
+47871363d804f54b29ccfd444b082c19716c2301
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION
index 17724c6..16f49a7 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@
-v2.099.0
+v2.099.1-beta.1
diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d
index f790730..8895aa5 100644
--- a/gcc/d/dmd/aggregate.d
+++ b/gcc/d/dmd/aggregate.d
@@ -547,7 +547,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
if (overflow) assert(0);
// Skip no-op for noreturn without custom aligment
- if (memsize != 0 || !alignment.isDefault())
+ if (memalignsize != 0 || !alignment.isDefault())
alignmember(alignment, memalignsize, &ofs);
uint memoffset = ofs;
@@ -570,7 +570,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
* definitions exposed some issues in their TypeInfo generation in DMD.
* Related PR: https://github.com/dlang/dmd/pull/13312
*/
- if (semanticRun == PASS.init && !isInterfaceDeclaration())
+ if (semanticRun == PASS.initial && !isInterfaceDeclaration())
{
auto stc = storage_class;
if (_scope)
@@ -747,7 +747,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
extern (C++) static int fp(Dsymbol s, void* ctxt)
{
auto f = s.isCtorDeclaration();
- if (f && f.semanticRun == PASS.init)
+ if (f && f.semanticRun == PASS.initial)
f.dsymbolSemantic(null);
return 0;
}
diff --git a/gcc/d/dmd/aliasthis.d b/gcc/d/dmd/aliasthis.d
index 458e821..2771071b 100644
--- a/gcc/d/dmd/aliasthis.d
+++ b/gcc/d/dmd/aliasthis.d
@@ -100,9 +100,9 @@ Expression resolveAliasThis(Scope* sc, Expression e, bool gag = false, bool find
if (tthis && ad.aliasthis.sym.needThis())
{
- if (e.op == EXP.variable)
+ if (auto ve = e.isVarExp())
{
- if (auto fd = (cast(VarExp)e).var.isFuncDeclaration())
+ if (auto fd = ve.var.isFuncDeclaration())
{
// https://issues.dlang.org/show_bug.cgi?id=13009
// Support better match for the overloaded alias this.
diff --git a/gcc/d/dmd/arrayop.d b/gcc/d/dmd/arrayop.d
index e82413f..52f39d3 100644
--- a/gcc/d/dmd/arrayop.d
+++ b/gcc/d/dmd/arrayop.d
@@ -52,16 +52,16 @@ bool isArrayOpValid(Expression e)
{
if (isUnaArrayOp(e.op))
{
- return isArrayOpValid((cast(UnaExp)e).e1);
+ return isArrayOpValid(e.isUnaExp().e1);
}
if (isBinArrayOp(e.op) || isBinAssignArrayOp(e.op) || e.op == EXP.assign)
{
- BinExp be = cast(BinExp)e;
+ BinExp be = e.isBinExp();
return isArrayOpValid(be.e1) && isArrayOpValid(be.e2);
}
if (e.op == EXP.construct)
{
- BinExp be = cast(BinExp)e;
+ BinExp be = e.isBinExp();
return be.e1.op == EXP.slice && isArrayOpValid(be.e2);
}
// if (e.op == EXP.call)
@@ -76,7 +76,7 @@ bool isArrayOpValid(Expression e)
bool isNonAssignmentArrayOp(Expression e)
{
if (e.op == EXP.slice)
- return isNonAssignmentArrayOp((cast(SliceExp)e).e1);
+ return isNonAssignmentArrayOp(e.isSliceExp().e1);
Type tb = e.type.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
@@ -176,7 +176,7 @@ Expression arrayOp(BinAssignExp e, Scope* sc)
return e.e1.modifiableLvalue(sc, e.e1);
}
- return arrayOp(cast(BinExp)e, sc);
+ return arrayOp(e.isBinExp(), sc);
}
/******************************************
diff --git a/gcc/d/dmd/arraytypes.d b/gcc/d/dmd/arraytypes.d
index ffbaf95..29b3a3d 100644
--- a/gcc/d/dmd/arraytypes.d
+++ b/gcc/d/dmd/arraytypes.d
@@ -54,4 +54,3 @@ alias TemplateInstances = Array!(TemplateInstance);
alias Ensures = Array!(Ensure);
alias Designators = Array!(Designator);
alias DesigInits = Array!(DesigInit);
-
diff --git a/gcc/d/dmd/arraytypes.h b/gcc/d/dmd/arraytypes.h
index d7dfa0b..ca2051c 100644
--- a/gcc/d/dmd/arraytypes.h
+++ b/gcc/d/dmd/arraytypes.h
@@ -67,4 +67,3 @@ typedef Array<struct Ensure> Ensures;
typedef Array<struct Designator> Designators;
typedef Array<struct DesigInit> DesigInits;
-
diff --git a/gcc/d/dmd/blockexit.d b/gcc/d/dmd/blockexit.d
index 5c01204..afd7ac0 100644
--- a/gcc/d/dmd/blockexit.d
+++ b/gcc/d/dmd/blockexit.d
@@ -99,9 +99,8 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
result = BE.halt;
return;
}
- if (s.exp.op == EXP.assert_)
+ if (AssertExp a = s.exp.isAssertExp())
{
- AssertExp a = cast(AssertExp)s.exp;
if (a.e1.toBool().hasValue(false)) // if it's an assert(0)
{
result = BE.halt;
@@ -505,7 +504,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
if (!(s.stc & STC.nothrow_))
{
if (mustNotThrow && !(s.stc & STC.nothrow_))
- s.deprecation("`asm` statement is assumed to throw - mark it with `nothrow` if it does not");
+ s.error("`asm` statement is assumed to throw - mark it with `nothrow` if it does not");
else
result |= BE.throw_;
}
diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d
index a6dbd8e..2ed0dc7 100644
--- a/gcc/d/dmd/clone.d
+++ b/gcc/d/dmd/clone.d
@@ -301,7 +301,7 @@ FuncDeclaration buildOpAssign(StructDeclaration sd, Scope* sc)
auto tf = new TypeFunction(ParameterList(fparams), sd.handleType(), LINK.d, stc | STC.ref_);
auto fop = new FuncDeclaration(declLoc, Loc.initial, Id.assign, stc, tf);
fop.storage_class |= STC.inference;
- fop.generated = true;
+ fop.flags |= FUNCFLAG.generated;
Expression e;
if (stc & STC.disable)
{
@@ -575,7 +575,7 @@ FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc)
tf = tf.addSTC(STC.const_).toTypeFunction();
Identifier id = Id.xopEquals;
auto fop = new FuncDeclaration(declLoc, Loc.initial, id, 0, tf);
- fop.generated = true;
+ fop.flags |= FUNCFLAG.generated;
fop.parent = sd;
Expression e1 = new IdentifierExp(loc, Id.This);
Expression e2 = new IdentifierExp(loc, Id.p);
@@ -644,13 +644,13 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc)
switch (e.op)
{
case EXP.overloadSet:
- s = (cast(OverExp)e).vars;
+ s = e.isOverExp().vars;
break;
case EXP.scope_:
- s = (cast(ScopeExp)e).sds;
+ s = e.isScopeExp().sds;
break;
case EXP.variable:
- s = (cast(VarExp)e).var;
+ s = e.isVarExp().var;
break;
default:
break;
@@ -696,7 +696,7 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc)
tf = tf.addSTC(STC.const_).toTypeFunction();
Identifier id = Id.xopCmp;
auto fop = new FuncDeclaration(declLoc, Loc.initial, id, 0, tf);
- fop.generated = true;
+ fop.flags |= FUNCFLAG.generated;
fop.parent = sd;
Expression e1 = new IdentifierExp(loc, Id.This);
Expression e2 = new IdentifierExp(loc, Id.p);
@@ -814,7 +814,7 @@ FuncDeclaration buildXtoHash(StructDeclaration sd, Scope* sc)
auto tf = new TypeFunction(ParameterList(parameters), Type.thash_t, LINK.d, STC.nothrow_ | STC.trusted);
Identifier id = Id.xtoHash;
auto fop = new FuncDeclaration(declLoc, Loc.initial, id, STC.static_, tf);
- fop.generated = true;
+ fop.flags |= FUNCFLAG.generated;
/* Do memberwise hashing.
*
@@ -937,13 +937,13 @@ void buildDtors(AggregateDeclaration ad, Scope* sc)
if (stc & STC.safe)
stc = (stc & ~STC.safe) | STC.trusted;
- ex = new SliceExp(loc, ex, new IntegerExp(loc, 0, Type.tsize_t),
+ SliceExp se = new SliceExp(loc, ex, new IntegerExp(loc, 0, Type.tsize_t),
new IntegerExp(loc, n, Type.tsize_t));
// Prevent redundant bounds check
- (cast(SliceExp)ex).upperIsInBounds = true;
- (cast(SliceExp)ex).lowerIsLessThanUpper = true;
+ se.upperIsInBounds = true;
+ se.lowerIsLessThanUpper = true;
- ex = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), ex);
+ ex = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), se);
}
e = Expression.combine(ex, e); // combine in reverse order
}
@@ -952,7 +952,7 @@ void buildDtors(AggregateDeclaration ad, Scope* sc)
{
//printf("Building __fieldDtor(), %s\n", e.toChars());
auto dd = new DtorDeclaration(declLoc, Loc.initial, stc, Id.__fieldDtor);
- dd.generated = true;
+ dd.flags |= FUNCFLAG.generated;
dd.storage_class |= STC.inference;
dd.fbody = new ExpStatement(loc, e);
ad.members.push(dd);
@@ -1008,7 +1008,7 @@ void buildDtors(AggregateDeclaration ad, Scope* sc)
e = Expression.combine(e, ce);
}
auto dd = new DtorDeclaration(declLoc, Loc.initial, stc, Id.__aggrDtor);
- dd.generated = true;
+ dd.flags |= FUNCFLAG.generated;
dd.storage_class |= STC.inference;
dd.fbody = new ExpStatement(loc, e);
ad.members.push(dd);
@@ -1079,7 +1079,7 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara
stmts.push(new ExpStatement(loc, call));
stmts.push(new ReturnStatement(loc, new CastExp(loc, new ThisExp(loc), Type.tvoidptr)));
func.fbody = new CompoundStatement(loc, stmts);
- func.generated = true;
+ func.flags |= FUNCFLAG.generated;
auto sc2 = sc.push();
sc2.stc &= ~STC.static_; // not a static destructor
@@ -1127,7 +1127,7 @@ private DtorDeclaration buildExternDDtor(AggregateDeclaration ad, Scope* sc)
auto call = new CallExp(dtor.loc, dtor, null);
call.directcall = true; // non-virtual call Class.__dtor();
func.fbody = new ExpStatement(dtor.loc, call);
- func.generated = true;
+ func.flags |= FUNCFLAG.generated;
func.storage_class |= STC.inference;
auto sc2 = sc.push();
@@ -1403,7 +1403,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
//printf("Building __fieldPostBlit()\n");
checkShared();
auto dd = new PostBlitDeclaration(declLoc, Loc.initial, stc, Id.__fieldPostblit);
- dd.generated = true;
+ dd.flags |= FUNCFLAG.generated;
dd.storage_class |= STC.inference | STC.scope_;
dd.fbody = (stc & STC.disable) ? null : new CompoundStatement(loc, postblitCalls);
sd.postblits.shift(dd);
@@ -1441,7 +1441,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
checkShared();
auto dd = new PostBlitDeclaration(declLoc, Loc.initial, stc, Id.__aggrPostblit);
- dd.generated = true;
+ dd.flags |= FUNCFLAG.generated;
dd.storage_class |= STC.inference;
dd.fbody = new ExpStatement(loc, e);
sd.members.push(dd);
@@ -1504,7 +1504,7 @@ private CtorDeclaration generateCopyCtorDeclaration(StructDeclaration sd, const
auto ccd = new CtorDeclaration(sd.loc, Loc.initial, STC.ref_, tf, true);
ccd.storage_class |= funcStc;
ccd.storage_class |= STC.inference;
- ccd.generated = true;
+ ccd.flags |= FUNCFLAG.generated;
return ccd;
}
@@ -1691,5 +1691,3 @@ bool buildCopyCtor(StructDeclaration sd, Scope* sc)
}
return true;
}
-
-
diff --git a/gcc/d/dmd/constfold.d b/gcc/d/dmd/constfold.d
index 9941c16..75ba9ea 100644
--- a/gcc/d/dmd/constfold.d
+++ b/gcc/d/dmd/constfold.d
@@ -217,15 +217,13 @@ UnionExp Add(const ref Loc loc, Type type, Expression e1, Expression e2)
}
emplaceExp!(ComplexExp)(&ue, loc, v, type);
}
- else if (e1.op == EXP.symbolOffset)
+ else if (SymOffExp soe = e1.isSymOffExp())
{
- SymOffExp soe = cast(SymOffExp)e1;
emplaceExp!(SymOffExp)(&ue, loc, soe.var, soe.offset + e2.toInteger());
ue.exp().type = type;
}
- else if (e2.op == EXP.symbolOffset)
+ else if (SymOffExp soe = e2.isSymOffExp())
{
- SymOffExp soe = cast(SymOffExp)e2;
emplaceExp!(SymOffExp)(&ue, loc, soe.var, soe.offset + e1.toInteger());
ue.exp().type = type;
}
@@ -320,9 +318,8 @@ UnionExp Min(const ref Loc loc, Type type, Expression e1, Expression e2)
}
emplaceExp!(ComplexExp)(&ue, loc, v, type);
}
- else if (e1.op == EXP.symbolOffset)
+ else if (SymOffExp soe = e1.isSymOffExp())
{
- SymOffExp soe = cast(SymOffExp)e1;
emplaceExp!(SymOffExp)(&ue, loc, soe.var, soe.offset - e2.toInteger());
ue.exp().type = type;
}
@@ -731,14 +728,12 @@ UnionExp Equal(EXP op, const ref Loc loc, Type type, Expression e1, Expression e
{
if (e2.op == EXP.null_)
cmp = 1;
- else if (e2.op == EXP.string_)
+ else if (StringExp es2 = e2.isStringExp())
{
- StringExp es2 = cast(StringExp)e2;
cmp = (0 == es2.len);
}
- else if (e2.op == EXP.arrayLiteral)
+ else if (ArrayLiteralExp es2 = e2.isArrayLiteralExp())
{
- ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2;
cmp = !es2.elements || (0 == es2.elements.dim);
}
else
@@ -749,14 +744,12 @@ UnionExp Equal(EXP op, const ref Loc loc, Type type, Expression e1, Expression e
}
else if (e2.op == EXP.null_)
{
- if (e1.op == EXP.string_)
+ if (StringExp es1 = e1.isStringExp())
{
- StringExp es1 = cast(StringExp)e1;
cmp = (0 == es1.len);
}
- else if (e1.op == EXP.arrayLiteral)
+ else if (ArrayLiteralExp es1 = e1.isArrayLiteralExp())
{
- ArrayLiteralExp es1 = cast(ArrayLiteralExp)e1;
cmp = !es1.elements || (0 == es1.elements.dim);
}
else
@@ -767,8 +760,8 @@ UnionExp Equal(EXP op, const ref Loc loc, Type type, Expression e1, Expression e
}
else if (e1.op == EXP.string_ && e2.op == EXP.string_)
{
- StringExp es1 = cast(StringExp)e1;
- StringExp es2 = cast(StringExp)e2;
+ StringExp es1 = e1.isStringExp();
+ StringExp es2 = e2.isStringExp();
if (es1.sz != es2.sz)
{
assert(global.errors);
@@ -784,8 +777,8 @@ UnionExp Equal(EXP op, const ref Loc loc, Type type, Expression e1, Expression e
}
else if (e1.op == EXP.arrayLiteral && e2.op == EXP.arrayLiteral)
{
- ArrayLiteralExp es1 = cast(ArrayLiteralExp)e1;
- ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2;
+ ArrayLiteralExp es1 = e1.isArrayLiteralExp();
+ ArrayLiteralExp es2 = e2.isArrayLiteralExp();
if ((!es1.elements || !es1.elements.dim) && (!es2.elements || !es2.elements.dim))
cmp = 1; // both arrays are empty
else if (!es1.elements || !es2.elements)
@@ -818,8 +811,8 @@ UnionExp Equal(EXP op, const ref Loc loc, Type type, Expression e1, Expression e
else if (e1.op == EXP.string_ && e2.op == EXP.arrayLiteral)
{
Lsa:
- StringExp es1 = cast(StringExp)e1;
- ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2;
+ StringExp es1 = e1.isStringExp();
+ ArrayLiteralExp es2 = e2.isArrayLiteralExp();
size_t dim1 = es1.len;
size_t dim2 = es2.elements ? es2.elements.dim : 0;
if (dim1 != dim2)
@@ -844,8 +837,8 @@ UnionExp Equal(EXP op, const ref Loc loc, Type type, Expression e1, Expression e
}
else if (e1.op == EXP.structLiteral && e2.op == EXP.structLiteral)
{
- StructLiteralExp es1 = cast(StructLiteralExp)e1;
- StructLiteralExp es2 = cast(StructLiteralExp)e2;
+ StructLiteralExp es1 = e1.isStructLiteralExp();
+ StructLiteralExp es2 = e2.isStructLiteralExp();
if (es1.sd != es2.sd)
cmp = 0;
else if ((!es1.elements || !es1.elements.dim) && (!es2.elements || !es2.elements.dim))
@@ -935,8 +928,8 @@ UnionExp Identity(EXP op, const ref Loc loc, Type type, Expression e1, Expressio
}
else if (e1.op == EXP.symbolOffset && e2.op == EXP.symbolOffset)
{
- SymOffExp es1 = cast(SymOffExp)e1;
- SymOffExp es2 = cast(SymOffExp)e2;
+ SymOffExp es1 = e1.isSymOffExp();
+ SymOffExp es2 = e2.isSymOffExp();
cmp = (es1.var == es2.var && es1.offset == es2.offset);
}
else
@@ -976,8 +969,8 @@ UnionExp Cmp(EXP op, const ref Loc loc, Type type, Expression e1, Expression e2)
//printf("Cmp(e1 = %s, e2 = %s)\n", e1.toChars(), e2.toChars());
if (e1.op == EXP.string_ && e2.op == EXP.string_)
{
- StringExp es1 = cast(StringExp)e1;
- StringExp es2 = cast(StringExp)e2;
+ StringExp es1 = e1.isStringExp();
+ StringExp es2 = e2.isStringExp();
size_t sz = es1.sz;
assert(sz == es2.sz);
size_t len = es1.len;
@@ -1045,7 +1038,7 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
}
if (e1.op == EXP.vector && (cast(TypeVector)e1.type).basetype.equals(type) && type.equals(to))
{
- Expression ex = (cast(VectorExp)e1).e1;
+ Expression ex = e1.isVectorExp().e1;
emplaceExp!(UnionExp)(&ue, ex);
return ue;
}
@@ -1201,20 +1194,17 @@ UnionExp ArrayLength(Type type, Expression e1)
{
UnionExp ue = void;
Loc loc = e1.loc;
- if (e1.op == EXP.string_)
+ if (StringExp es1 = e1.isStringExp())
{
- StringExp es1 = cast(StringExp)e1;
emplaceExp!(IntegerExp)(&ue, loc, es1.len, type);
}
- else if (e1.op == EXP.arrayLiteral)
+ else if (ArrayLiteralExp ale = e1.isArrayLiteralExp())
{
- ArrayLiteralExp ale = cast(ArrayLiteralExp)e1;
size_t dim = ale.elements ? ale.elements.dim : 0;
emplaceExp!(IntegerExp)(&ue, loc, dim, type);
}
- else if (e1.op == EXP.assocArrayLiteral)
+ else if (AssocArrayLiteralExp ale = e1.isAssocArrayLiteralExp)
{
- AssocArrayLiteralExp ale = cast(AssocArrayLiteralExp)e1;
size_t dim = ale.keys.dim;
emplaceExp!(IntegerExp)(&ue, loc, dim, type);
}
@@ -1238,7 +1228,7 @@ UnionExp Index(Type type, Expression e1, Expression e2, bool indexIsInBounds)
assert(e1.type);
if (e1.op == EXP.string_ && e2.op == EXP.int64)
{
- StringExp es1 = cast(StringExp)e1;
+ StringExp es1 = e1.isStringExp();
uinteger_t i = e2.toInteger();
if (i >= es1.len)
{
@@ -1261,9 +1251,8 @@ UnionExp Index(Type type, Expression e1, Expression e2, bool indexIsInBounds)
e1.error("array index %llu is out of bounds `%s[0 .. %llu]`", i, e1.toChars(), length);
emplaceExp!(ErrorExp)(&ue);
}
- else if (e1.op == EXP.arrayLiteral)
+ else if (ArrayLiteralExp ale = e1.isArrayLiteralExp())
{
- ArrayLiteralExp ale = cast(ArrayLiteralExp)e1;
auto e = ale[cast(size_t)i];
e.type = type;
e.loc = loc;
@@ -1278,9 +1267,8 @@ UnionExp Index(Type type, Expression e1, Expression e2, bool indexIsInBounds)
else if (e1.type.toBasetype().ty == Tarray && e2.op == EXP.int64)
{
uinteger_t i = e2.toInteger();
- if (e1.op == EXP.arrayLiteral)
+ if (ArrayLiteralExp ale = e1.isArrayLiteralExp())
{
- ArrayLiteralExp ale = cast(ArrayLiteralExp)e1;
if (i >= ale.elements.dim)
{
e1.error("array index %llu is out of bounds `%s[0 .. %llu]`", i, e1.toChars(), cast(ulong) ale.elements.dim);
@@ -1300,9 +1288,8 @@ UnionExp Index(Type type, Expression e1, Expression e2, bool indexIsInBounds)
else
cantExp(ue);
}
- else if (e1.op == EXP.assocArrayLiteral)
+ else if (AssocArrayLiteralExp ae = e1.isAssocArrayLiteralExp())
{
- AssocArrayLiteralExp ae = cast(AssocArrayLiteralExp)e1;
/* Search the keys backwards, in case there are duplicate keys
*/
for (size_t i = ae.keys.dim; i;)
@@ -1350,7 +1337,7 @@ UnionExp Slice(Type type, Expression e1, Expression lwr, Expression upr)
if (e1.op == EXP.string_ && lwr.op == EXP.int64 && upr.op == EXP.int64)
{
- StringExp es1 = cast(StringExp)e1;
+ StringExp es1 = e1.isStringExp();
const uinteger_t ilwr = lwr.toInteger();
const uinteger_t iupr = upr.toInteger();
if (sliceBoundsCheck(0, es1.len, ilwr, iupr))
@@ -1363,14 +1350,14 @@ UnionExp Slice(Type type, Expression e1, Expression lwr, Expression upr)
const data1 = es1.peekData();
memcpy(s, data1.ptr + ilwr * sz, len * sz);
emplaceExp!(StringExp)(&ue, loc, s[0 .. len * sz], len, sz, es1.postfix);
- StringExp es = cast(StringExp)ue.exp();
+ StringExp es = ue.exp().isStringExp();
es.committed = es1.committed;
es.type = type;
}
}
else if (e1.op == EXP.arrayLiteral && lwr.op == EXP.int64 && upr.op == EXP.int64 && !hasSideEffect(e1))
{
- ArrayLiteralExp es1 = cast(ArrayLiteralExp)e1;
+ ArrayLiteralExp es1 = e1.isArrayLiteralExp();
const uinteger_t ilwr = lwr.toInteger();
const uinteger_t iupr = upr.toInteger();
if (sliceBoundsCheck(0, es1.elements.dim, ilwr, iupr))
@@ -1491,15 +1478,15 @@ private Expressions* copyElements(Expression e1, Expression e2 = null)
}
}
- if (e1.op == EXP.arrayLiteral)
- append(cast(ArrayLiteralExp)e1);
+ if (auto ale = e1.isArrayLiteralExp())
+ append(ale);
else
elems.push(e1);
if (e2)
{
- if (e2.op == EXP.arrayLiteral)
- append(cast(ArrayLiteralExp)e2);
+ if (auto ale = e2.isArrayLiteralExp())
+ append(ale);
else
elems.push(e2);
}
@@ -1544,7 +1531,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
else
utf_encode(sz, s, cast(dchar)v);
emplaceExp!(StringExp)(&ue, loc, s[0 .. len * sz], len, sz);
- StringExp es = cast(StringExp)ue.exp();
+ StringExp es = ue.exp().isStringExp();
es.type = type;
es.committed = 1;
}
@@ -1589,8 +1576,8 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
else if (e1.op == EXP.string_ && e2.op == EXP.string_)
{
// Concatenate the strings
- StringExp es1 = cast(StringExp)e1;
- StringExp es2 = cast(StringExp)e2;
+ StringExp es1 = e1.isStringExp();
+ StringExp es2 = e2.isStringExp();
size_t len = es1.len + es2.len;
ubyte sz = es1.sz;
if (sz != es2.sz)
@@ -1609,7 +1596,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
memcpy(cast(char*)s, data1.ptr, es1.len * sz);
memcpy(cast(char*)s + es1.len * sz, data2.ptr, es2.len * sz);
emplaceExp!(StringExp)(&ue, loc, s[0 .. len * sz], len, sz);
- StringExp es = cast(StringExp)ue.exp();
+ StringExp es = ue.exp().isStringExp();
es.committed = es1.committed | es2.committed;
es.type = type;
assert(ue.exp().type);
@@ -1618,8 +1605,8 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
else if (e2.op == EXP.string_ && e1.op == EXP.arrayLiteral && t1.nextOf().isintegral())
{
// [chars] ~ string --> [chars]
- StringExp es = cast(StringExp)e2;
- ArrayLiteralExp ea = cast(ArrayLiteralExp)e1;
+ StringExp es = e2.isStringExp();
+ ArrayLiteralExp ea = e1.isArrayLiteralExp();
size_t len = es.len + ea.elements.dim;
auto elems = new Expressions(len);
for (size_t i = 0; i < ea.elements.dim; ++i)
@@ -1627,7 +1614,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
(*elems)[i] = ea[i];
}
emplaceExp!(ArrayLiteralExp)(&ue, e1.loc, type, elems);
- ArrayLiteralExp dest = cast(ArrayLiteralExp)ue.exp();
+ ArrayLiteralExp dest = ue.exp().isArrayLiteralExp();
sliceAssignArrayLiteralFromString(dest, es, ea.elements.dim);
assert(ue.exp().type);
return ue;
@@ -1635,8 +1622,8 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
else if (e1.op == EXP.string_ && e2.op == EXP.arrayLiteral && t2.nextOf().isintegral())
{
// string ~ [chars] --> [chars]
- StringExp es = cast(StringExp)e1;
- ArrayLiteralExp ea = cast(ArrayLiteralExp)e2;
+ StringExp es = e1.isStringExp();
+ ArrayLiteralExp ea = e2.isArrayLiteralExp();
size_t len = es.len + ea.elements.dim;
auto elems = new Expressions(len);
for (size_t i = 0; i < ea.elements.dim; ++i)
@@ -1644,7 +1631,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
(*elems)[es.len + i] = ea[i];
}
emplaceExp!(ArrayLiteralExp)(&ue, e1.loc, type, elems);
- ArrayLiteralExp dest = cast(ArrayLiteralExp)ue.exp();
+ ArrayLiteralExp dest = ue.exp().isArrayLiteralExp();
sliceAssignArrayLiteralFromString(dest, es, 0);
assert(ue.exp().type);
return ue;
@@ -1652,7 +1639,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
else if (e1.op == EXP.string_ && e2.op == EXP.int64)
{
// string ~ char --> string
- StringExp es1 = cast(StringExp)e1;
+ StringExp es1 = e1.isStringExp();
StringExp es;
const sz = es1.sz;
dinteger_t v = e2.toInteger();
@@ -1668,7 +1655,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
else
utf_encode(sz, cast(char*)s + (sz * es1.len), cast(dchar)v);
emplaceExp!(StringExp)(&ue, loc, s[0 .. len * sz], len, sz);
- es = cast(StringExp)ue.exp();
+ es = ue.exp().isStringExp();
es.committed = es1.committed;
es.type = type;
assert(ue.exp().type);
@@ -1679,7 +1666,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
// [w|d]?char ~ string --> string
// We assume that we only ever prepend one char of the same type
// (wchar,dchar) as the string's characters.
- StringExp es2 = cast(StringExp)e2;
+ StringExp es2 = e2.isStringExp();
const len = 1 + es2.len;
const sz = es2.sz;
dinteger_t v = e1.toInteger();
@@ -1688,7 +1675,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
const data2 = es2.peekData();
memcpy(cast(char*)s + sz, data2.ptr, data2.length);
emplaceExp!(StringExp)(&ue, loc, s[0 .. len * sz], len, sz);
- StringExp es = cast(StringExp)ue.exp();
+ StringExp es = ue.exp().isStringExp();
es.sz = sz;
es.committed = es2.committed;
es.type = type;
@@ -1796,7 +1783,7 @@ UnionExp Cat(const ref Loc loc, Type type, Expression e1, Expression e2)
}
if (!e.type.equals(type))
{
- StringExp se = cast(StringExp)e.copy();
+ StringExp se = e.copy().isStringExp();
e = se.castTo(null, type);
emplaceExp!(UnionExp)(&ue, e);
e = ue.exp();
@@ -1812,23 +1799,21 @@ UnionExp Ptr(Type type, Expression e1)
{
//printf("Ptr(e1 = %s)\n", e1.toChars());
UnionExp ue = void;
- if (e1.op == EXP.add)
+ if (AddExp ae = e1.isAddExp())
{
- AddExp ae = cast(AddExp)e1;
- if (ae.e1.op == EXP.address && ae.e2.op == EXP.int64)
+ if (AddrExp ade = ae.e1.isAddrExp())
{
- AddrExp ade = cast(AddrExp)ae.e1;
- if (ade.e1.op == EXP.structLiteral)
- {
- StructLiteralExp se = cast(StructLiteralExp)ade.e1;
- uint offset = cast(uint)ae.e2.toInteger();
- Expression e = se.getField(type, offset);
- if (e)
+ if (ae.e2.op == EXP.int64)
+ if (StructLiteralExp se = ade.e1.isStructLiteralExp())
{
- emplaceExp!(UnionExp)(&ue, e);
- return ue;
+ uint offset = cast(uint)ae.e2.toInteger();
+ Expression e = se.getField(type, offset);
+ if (e)
+ {
+ emplaceExp!(UnionExp)(&ue, e);
+ return ue;
+ }
}
- }
}
}
cantExp(ue);
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index fb52b63..bb12aa7 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -981,7 +981,12 @@ final class CParser(AST) : Parser!AST
e = new AST.DotIdExp(loc, e, Id.__sizeof);
break;
}
+ // must be an expression
+ e = cparsePrimaryExp();
+ e = new AST.DotIdExp(loc, e, Id.__sizeof);
+ break;
}
+
e = cparseUnaryExp();
e = new AST.DotIdExp(loc, e, Id.__sizeof);
break;
@@ -1016,10 +1021,16 @@ final class CParser(AST) : Parser!AST
{
if (token.value == TOK.leftParenthesis)
{
+ //printf("cparseCastExp()\n");
auto tk = peek(&token);
- if (tk.value == TOK.identifier &&
- !isTypedef(tk.ident) &&
- peek(tk).value == TOK.rightParenthesis)
+ bool iscast;
+ bool isexp;
+ if (tk.value == TOK.identifier)
+ {
+ iscast = isTypedef(tk.ident);
+ isexp = !iscast;
+ }
+ if (isexp)
{
// ( identifier ) is an expression
return cparseUnaryExp();
@@ -1045,9 +1056,18 @@ final class CParser(AST) : Parser!AST
auto ce = new AST.CompoundLiteralExp(loc, t, ci);
return cparsePostfixOperators(ce);
}
- else if (t.isTypeIdentifier() &&
- token.value == TOK.leftParenthesis &&
- !isCastExpression(pt))
+
+ if (iscast)
+ {
+ // ( type-name ) cast-expression
+ auto ce = cparseCastExp();
+ return new AST.CastExp(loc, ce, t);
+ }
+
+ if (t.isTypeIdentifier() &&
+ isexp &&
+ token.value == TOK.leftParenthesis &&
+ !isCastExpression(pt))
{
/* (t)(...)... might be a cast expression or a function call,
* with different grammars: a cast would be cparseCastExp(),
@@ -1061,12 +1081,10 @@ final class CParser(AST) : Parser!AST
AST.Expression e = new AST.CallExp(loc, ie, cparseArguments());
return cparsePostfixOperators(e);
}
- else
- {
- // ( type-name ) cast-expression
- auto ce = cparseCastExp();
- return new AST.CastExp(loc, ce, t);
- }
+
+ // ( type-name ) cast-expression
+ auto ce = cparseCastExp();
+ return new AST.CastExp(loc, ce, t);
}
}
return cparseUnaryExp();
@@ -1764,8 +1782,6 @@ final class CParser(AST) : Parser!AST
symbols.push(stag);
if (tt.tok == TOK.enum_)
{
- if (!stag.members)
- error(tt.loc, "`enum %s` has no members", stag.toChars());
isalias = false;
s = new AST.AliasDeclaration(token.loc, id, stag);
}
@@ -2382,7 +2398,19 @@ final class CParser(AST) : Parser!AST
const idx = previd.toString();
if (idx.length > 2 && idx[0] == '_' && idx[1] == '_') // leading double underscore
importBuiltins = true; // probably one of those compiler extensions
- t = new AST.TypeIdentifier(loc, previd);
+ t = null;
+ if (scw & SCW.xtypedef)
+ {
+ /* Punch through to what the typedef is, to support things like:
+ * typedef T* T;
+ */
+ auto pt = lookupTypedef(previd);
+ if (pt && *pt) // if previd is a known typedef
+ t = *pt;
+ }
+
+ if (!t)
+ t = new AST.TypeIdentifier(loc, previd);
break;
}
@@ -4767,7 +4795,8 @@ final class CParser(AST) : Parser!AST
scan(&n);
if (n.value == TOK.identifier && n.ident == Id.pack)
return pragmaPack(loc);
- skipToNextLine();
+ if (n.value != TOK.endOfLine)
+ skipToNextLine();
}
/*********
@@ -4786,7 +4815,8 @@ final class CParser(AST) : Parser!AST
if (n.value != TOK.leftParenthesis)
{
error(loc, "left parenthesis expected to follow `#pragma pack`");
- skipToNextLine();
+ if (n.value != TOK.endOfLine)
+ skipToNextLine();
return;
}
@@ -4796,7 +4826,8 @@ final class CParser(AST) : Parser!AST
{
error(loc, "right parenthesis expected to close `#pragma pack(`");
}
- skipToNextLine();
+ if (n.value != TOK.endOfLine)
+ skipToNextLine();
}
void setPackAlign(ref const Token t)
@@ -4923,7 +4954,8 @@ final class CParser(AST) : Parser!AST
}
error(loc, "unrecognized `#pragma pack(%s)`", n.toChars());
- skipToNextLine();
+ if (n.value != TOK.endOfLine)
+ skipToNextLine();
}
//}
diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d
index 9078f90..32aed16 100644
--- a/gcc/d/dmd/ctfeexpr.d
+++ b/gcc/d/dmd/ctfeexpr.d
@@ -232,11 +232,11 @@ bool needToCopyLiteral(const Expression expr)
switch (e.op)
{
case EXP.arrayLiteral:
- return (cast(ArrayLiteralExp)e).ownedByCtfe == OwnedBy.code;
+ return e.isArrayLiteralExp().ownedByCtfe == OwnedBy.code;
case EXP.assocArrayLiteral:
- return (cast(AssocArrayLiteralExp)e).ownedByCtfe == OwnedBy.code;
+ return e.isAssocArrayLiteralExp().ownedByCtfe == OwnedBy.code;
case EXP.structLiteral:
- return (cast(StructLiteralExp)e).ownedByCtfe == OwnedBy.code;
+ return e.isStructLiteralExp().ownedByCtfe == OwnedBy.code;
case EXP.string_:
case EXP.this_:
case EXP.variable:
@@ -247,14 +247,14 @@ bool needToCopyLiteral(const Expression expr)
case EXP.dotVariable:
case EXP.slice:
case EXP.cast_:
- e = (cast(UnaExp)e).e1;
+ e = e.isUnaExp().e1;
continue;
case EXP.concatenate:
- return needToCopyLiteral((cast(BinExp)e).e1) || needToCopyLiteral((cast(BinExp)e).e2);
+ return needToCopyLiteral(e.isBinExp().e1) || needToCopyLiteral(e.isBinExp().e2);
case EXP.concatenateAssign:
case EXP.concatenateElemAssign:
case EXP.concatenateDcharAssign:
- e = (cast(BinExp)e).e2;
+ e = e.isBinExp().e2;
continue;
default:
return false;
@@ -286,7 +286,7 @@ UnionExp copyLiteral(Expression e)
const slice = se.peekData();
memcpy(s, slice.ptr, slice.length);
emplaceExp!(StringExp)(&ue, se.loc, s[0 .. se.len * se.sz], se.len, se.sz);
- StringExp se2 = cast(StringExp)ue.exp();
+ StringExp se2 = ue.exp().isStringExp();
se2.committed = se.committed;
se2.postfix = se.postfix;
se2.type = se.type;
@@ -299,14 +299,14 @@ UnionExp copyLiteral(Expression e)
emplaceExp!(ArrayLiteralExp)(&ue, e.loc, e.type, elements);
- ArrayLiteralExp r = cast(ArrayLiteralExp)ue.exp();
+ ArrayLiteralExp r = ue.exp().isArrayLiteralExp();
r.ownedByCtfe = OwnedBy.ctfe;
return ue;
}
if (auto aae = e.isAssocArrayLiteralExp())
{
emplaceExp!(AssocArrayLiteralExp)(&ue, e.loc, copyLiteralArray(aae.keys), copyLiteralArray(aae.values));
- AssocArrayLiteralExp r = cast(AssocArrayLiteralExp)ue.exp();
+ AssocArrayLiteralExp r = ue.exp().isAssocArrayLiteralExp();
r.type = e.type;
r.ownedByCtfe = OwnedBy.ctfe;
return ue;
@@ -482,7 +482,7 @@ private UnionExp paintTypeOntoLiteralCopy(Type type, Expression lit)
// just a ref to the keys and values.
OwnedBy wasOwned = aae.ownedByCtfe;
emplaceExp!(AssocArrayLiteralExp)(&ue, lit.loc, aae.keys, aae.values);
- aae = cast(AssocArrayLiteralExp)ue.exp();
+ aae = ue.exp().isAssocArrayLiteralExp();
aae.ownedByCtfe = wasOwned;
}
else
@@ -526,7 +526,7 @@ Expression resolveSlice(Expression e, UnionExp* pue = null)
* It's very wasteful to resolve the slice when we only
* need the length.
*/
-uinteger_t resolveArrayLength(const Expression e)
+uinteger_t resolveArrayLength(Expression e)
{
switch (e.op)
{
@@ -538,7 +538,7 @@ uinteger_t resolveArrayLength(const Expression e)
case EXP.slice:
{
- auto se = cast(SliceExp)e;
+ auto se = e.isSliceExp();
const ilo = se.lwr.toInteger();
const iup = se.upr.toInteger();
return iup - ilo;
@@ -720,16 +720,16 @@ Expression getAggregateFromPointer(Expression e, dinteger_t* ofs)
*ofs = soe.offset;
if (auto dve = e.isDotVarExp())
{
- const ex = dve.e1;
+ auto ex = dve.e1;
const v = dve.var.isVarDeclaration();
assert(v);
StructLiteralExp se = (ex.op == EXP.classReference)
- ? (cast(ClassReferenceExp)ex).value
- : cast(StructLiteralExp)ex;
+ ? ex.isClassReferenceExp().value
+ : ex.isStructLiteralExp();
// We can't use getField, because it makes a copy
const i = (ex.op == EXP.classReference)
- ? (cast(ClassReferenceExp)ex).getFieldIndex(e.type, v.offset)
+ ? ex.isClassReferenceExp().getFieldIndex(e.type, v.offset)
: se.getFieldIndex(e.type, v.offset);
e = (*se.elements)[i];
}
@@ -777,11 +777,11 @@ bool pointToSameMemoryBlock(Expression agg1, Expression agg2)
}
// Note that type painting can occur with VarExp, so we
// must compare the variables being pointed to.
- if (agg1.op == EXP.variable && agg2.op == EXP.variable && (cast(VarExp)agg1).var == (cast(VarExp)agg2).var)
+ if (agg1.op == EXP.variable && agg2.op == EXP.variable && agg1.isVarExp().var == agg2.isVarExp().var)
{
return true;
}
- if (agg1.op == EXP.symbolOffset && agg2.op == EXP.symbolOffset && (cast(SymOffExp)agg1).var == (cast(SymOffExp)agg2).var)
+ if (agg1.op == EXP.symbolOffset && agg2.op == EXP.symbolOffset && agg1.isSymOffExp().var == agg2.isSymOffExp().var)
{
return true;
}
@@ -801,14 +801,14 @@ Expression pointerDifference(UnionExp* pue, const ref Loc loc, Type type, Expres
emplaceExp!(IntegerExp)(pue, loc, (ofs1 - ofs2) * sz, type);
}
else if (agg1.op == EXP.string_ && agg2.op == EXP.string_ &&
- (cast(StringExp)agg1).peekString().ptr == (cast(StringExp)agg2).peekString().ptr)
+ agg1.isStringExp().peekString().ptr == agg2.isStringExp().peekString().ptr)
{
Type pointee = (cast(TypePointer)agg1.type).next;
const sz = pointee.size();
emplaceExp!(IntegerExp)(pue, loc, (ofs1 - ofs2) * sz, type);
}
else if (agg1.op == EXP.symbolOffset && agg2.op == EXP.symbolOffset &&
- (cast(SymOffExp)agg1).var == (cast(SymOffExp)agg2).var)
+ agg1.isSymOffExp().var == agg2.isSymOffExp().var)
{
emplaceExp!(IntegerExp)(pue, loc, ofs1 - ofs2, type);
}
@@ -832,12 +832,12 @@ Expression pointerArithmetic(UnionExp* pue, const ref Loc loc, EXP op, Type type
return pue.exp();
}
if (eptr.op == EXP.address)
- eptr = (cast(AddrExp)eptr).e1;
+ eptr = eptr.isAddrExp().e1;
dinteger_t ofs1;
Expression agg1 = getAggregateFromPointer(eptr, &ofs1);
if (agg1.op == EXP.symbolOffset)
{
- if ((cast(SymOffExp)agg1).var.type.ty != Tsarray)
+ if (agg1.isSymOffExp().var.type.ty != Tsarray)
{
error(loc, "cannot perform pointer arithmetic on arrays of unknown length at compile time");
goto Lcant;
@@ -856,7 +856,7 @@ Expression pointerArithmetic(UnionExp* pue, const ref Loc loc, EXP op, Type type
if (agg1.op == EXP.symbolOffset)
{
indx = ofs1 / sz;
- len = (cast(TypeSArray)(cast(SymOffExp)agg1).var.type).dim.toInteger();
+ len = (cast(TypeSArray)agg1.isSymOffExp().var.type).dim.toInteger();
}
else
{
@@ -881,8 +881,8 @@ Expression pointerArithmetic(UnionExp* pue, const ref Loc loc, EXP op, Type type
}
if (agg1.op == EXP.symbolOffset)
{
- emplaceExp!(SymOffExp)(pue, loc, (cast(SymOffExp)agg1).var, indx * sz);
- SymOffExp se = cast(SymOffExp)pue.exp();
+ emplaceExp!(SymOffExp)(pue, loc, agg1.isSymOffExp().var, indx * sz);
+ SymOffExp se = pue.exp().isSymOffExp();
se.type = type;
return pue.exp();
}
@@ -1016,7 +1016,7 @@ Expression paintFloatInt(UnionExp* pue, Expression fromVal, Type to)
bool isCtfeComparable(Expression e)
{
if (e.op == EXP.slice)
- e = (cast(SliceExp)e).e1;
+ e = e.isSliceExp().e1;
if (e.isConst() != 1)
{
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)
@@ -1191,7 +1191,7 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
if (e1.op == EXP.classReference || e2.op == EXP.classReference)
{
if (e1.op == EXP.classReference && e2.op == EXP.classReference &&
- (cast(ClassReferenceExp)e1).value == (cast(ClassReferenceExp)e2).value)
+ e1.isClassReferenceExp().value == e2.isClassReferenceExp().value)
return 0;
return 1;
}
@@ -1199,8 +1199,8 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
{
// printf("e1: %s\n", e1.toChars());
// printf("e2: %s\n", e2.toChars());
- Type t1 = isType((cast(TypeidExp)e1).obj);
- Type t2 = isType((cast(TypeidExp)e2).obj);
+ Type t1 = isType(e1.isTypeidExp().obj);
+ Type t2 = isType(e2.isTypeidExp().obj);
assert(t1);
assert(t2);
return t1 != t2;
@@ -1214,7 +1214,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 == EXP.variable && agg2.op == EXP.variable && (cast(VarExp)agg1).var == (cast(VarExp)agg2).var))
+ if ((agg1 == agg2) || (agg1.op == EXP.variable && agg2.op == EXP.variable && agg1.isVarExp().var == agg2.isVarExp().var))
{
if (ofs1 == ofs2)
return 0;
@@ -1232,13 +1232,13 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
return 0;
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;
+ Expression ptr1 = e1.isDelegateExp().e1;
+ Expression ptr2 = e2.isDelegateExp().e1;
dinteger_t ofs1, ofs2;
Expression agg1 = getAggregateFromPointer(ptr1, &ofs1);
Expression agg2 = getAggregateFromPointer(ptr2, &ofs2);
// 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))
+ if ((agg1 == agg2 && ofs1 == ofs2) || (agg1.op == EXP.variable && agg2.op == EXP.variable && agg1.isVarExp().var == agg2.isVarExp().var))
{
return 0;
}
@@ -1291,8 +1291,8 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
}
if (e1.op == EXP.structLiteral && e2.op == EXP.structLiteral)
{
- StructLiteralExp es1 = cast(StructLiteralExp)e1;
- StructLiteralExp es2 = cast(StructLiteralExp)e2;
+ StructLiteralExp es1 = e1.isStructLiteralExp();
+ StructLiteralExp es2 = e2.isStructLiteralExp();
// For structs, we only need to return 0 or 1 (< and > aren't legal).
if (es1.sd != es2.sd)
return 1;
@@ -1326,8 +1326,8 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide
}
if (e1.op == EXP.assocArrayLiteral && e2.op == EXP.assocArrayLiteral)
{
- AssocArrayLiteralExp es1 = cast(AssocArrayLiteralExp)e1;
- AssocArrayLiteralExp es2 = cast(AssocArrayLiteralExp)e2;
+ AssocArrayLiteralExp es1 = e1.isAssocArrayLiteralExp();
+ AssocArrayLiteralExp es2 = e2.isAssocArrayLiteralExp();
size_t dim = es1.keys.dim;
if (es2.keys.dim != dim)
return 1;
@@ -1394,8 +1394,8 @@ bool ctfeIdentity(const ref Loc loc, EXP op, Expression e1, Expression e2)
}
else if (e1.op == EXP.symbolOffset && e2.op == EXP.symbolOffset)
{
- SymOffExp es1 = cast(SymOffExp)e1;
- SymOffExp es2 = cast(SymOffExp)e2;
+ SymOffExp es1 = e1.isSymOffExp();
+ SymOffExp es2 = e2.isSymOffExp();
cmp = (es1.var == es2.var && es1.offset == es2.offset);
}
else if (e1.type.isreal())
@@ -1443,8 +1443,8 @@ UnionExp ctfeCat(const ref Loc loc, Type type, Expression e1, Expression e2)
if (e2.op == EXP.string_ && e1.op == EXP.arrayLiteral && t1.nextOf().isintegral())
{
// [chars] ~ string => string (only valid for CTFE)
- StringExp es1 = cast(StringExp)e2;
- ArrayLiteralExp es2 = cast(ArrayLiteralExp)e1;
+ StringExp es1 = e2.isStringExp();
+ ArrayLiteralExp es2 = e1.isArrayLiteralExp();
const len = es1.len + es2.elements.dim;
const sz = es1.sz;
void* s = mem.xmalloc((len + 1) * sz);
@@ -1464,7 +1464,7 @@ UnionExp ctfeCat(const ref Loc loc, Type type, Expression e1, Expression e2)
// Add terminating 0
memset(cast(char*)s + len * sz, 0, sz);
emplaceExp!(StringExp)(&ue, loc, s[0 .. len * sz], len, sz);
- StringExp es = cast(StringExp)ue.exp();
+ StringExp es = ue.exp().isStringExp();
es.committed = 0;
es.type = type;
return ue;
@@ -1473,8 +1473,8 @@ UnionExp ctfeCat(const ref Loc loc, Type type, Expression e1, Expression e2)
{
// string ~ [chars] => string (only valid for CTFE)
// Concatenate the strings
- StringExp es1 = cast(StringExp)e1;
- ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2;
+ StringExp es1 = e1.isStringExp();
+ ArrayLiteralExp es2 = e2.isArrayLiteralExp();
const len = es1.len + es2.elements.dim;
const sz = es1.sz;
void* s = mem.xmalloc((len + 1) * sz);
@@ -1494,7 +1494,7 @@ UnionExp ctfeCat(const ref Loc loc, Type type, Expression e1, Expression e2)
// Add terminating 0
memset(cast(char*)s + len * sz, 0, sz);
emplaceExp!(StringExp)(&ue, loc, s[0 .. len * sz], len, sz);
- StringExp es = cast(StringExp)ue.exp();
+ StringExp es = ue.exp().isStringExp();
es.sz = sz;
es.committed = 0; //es1.committed;
es.type = type;
@@ -1503,10 +1503,10 @@ UnionExp ctfeCat(const ref Loc loc, Type type, Expression e1, Expression e2)
if (e1.op == EXP.arrayLiteral && e2.op == EXP.arrayLiteral && t1.nextOf().equals(t2.nextOf()))
{
// [ e1 ] ~ [ e2 ] ---> [ e1, e2 ]
- ArrayLiteralExp es1 = cast(ArrayLiteralExp)e1;
- ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2;
+ ArrayLiteralExp es1 = e1.isArrayLiteralExp();
+ ArrayLiteralExp es2 = e2.isArrayLiteralExp();
emplaceExp!(ArrayLiteralExp)(&ue, es1.loc, type, copyLiteralArray(es1.elements));
- es1 = cast(ArrayLiteralExp)ue.exp();
+ es1 = ue.exp().isArrayLiteralExp();
es1.elements.insert(es1.elements.dim, copyLiteralArray(es2.elements));
return ue;
}
@@ -1594,7 +1594,7 @@ Expression ctfeCast(UnionExp* pue, const ref Loc loc, Type type, Type to, Expres
// Disallow reinterpreting class casts. Do this by ensuring that
// the original class can implicitly convert to the target class.
// Also do not check 'alias this' for explicit cast expressions.
- auto tclass = (cast(ClassReferenceExp)e).originalClass().type.isTypeClass();
+ auto tclass = e.isClassReferenceExp().originalClass().type.isTypeClass();
auto match = explicitCast ? tclass.implicitConvToWithoutAliasThis(to.mutableOf())
: tclass.implicitConvTo(to.mutableOf());
if (match)
@@ -1665,9 +1665,9 @@ void assignInPlace(Expression dest, Expression src)
if (dest.op == EXP.structLiteral)
{
assert(dest.op == src.op);
- oldelems = (cast(StructLiteralExp)dest).elements;
- newelems = (cast(StructLiteralExp)src).elements;
- auto sd = (cast(StructLiteralExp)dest).sd;
+ oldelems = dest.isStructLiteralExp().elements;
+ newelems = src.isStructLiteralExp().elements;
+ auto sd = dest.isStructLiteralExp().sd;
const nfields = sd.nonHiddenFields();
const nvthis = sd.fields.dim - nfields;
if (nvthis && oldelems.dim >= nfields && oldelems.dim < newelems.dim)
@@ -1676,22 +1676,22 @@ void assignInPlace(Expression dest, Expression src)
}
else if (dest.op == EXP.arrayLiteral && src.op == EXP.arrayLiteral)
{
- oldelems = (cast(ArrayLiteralExp)dest).elements;
- newelems = (cast(ArrayLiteralExp)src).elements;
+ oldelems = dest.isArrayLiteralExp().elements;
+ newelems = src.isArrayLiteralExp().elements;
}
else if (dest.op == EXP.string_ && src.op == EXP.string_)
{
- sliceAssignStringFromString(cast(StringExp)dest, cast(StringExp)src, 0);
+ sliceAssignStringFromString(dest.isStringExp(), src.isStringExp(), 0);
return;
}
else if (dest.op == EXP.arrayLiteral && src.op == EXP.string_)
{
- sliceAssignArrayLiteralFromString(cast(ArrayLiteralExp)dest, cast(StringExp)src, 0);
+ sliceAssignArrayLiteralFromString(dest.isArrayLiteralExp(), src.isStringExp(), 0);
return;
}
else if (src.op == EXP.arrayLiteral && dest.op == EXP.string_)
{
- sliceAssignStringFromArrayLiteral(cast(StringExp)dest, cast(ArrayLiteralExp)src, 0);
+ sliceAssignStringFromArrayLiteral(dest.isStringExp(), src.isArrayLiteralExp(), 0);
return;
}
else
@@ -1761,13 +1761,13 @@ Expression changeArrayLiteralLength(UnionExp* pue, const ref Loc loc, TypeArray
size_t indxlo = 0;
if (oldval.op == EXP.slice)
{
- indxlo = cast(size_t)(cast(SliceExp)oldval).lwr.toInteger();
- oldval = (cast(SliceExp)oldval).e1;
+ indxlo = cast(size_t)oldval.isSliceExp().lwr.toInteger();
+ oldval = oldval.isSliceExp().e1;
}
size_t copylen = oldlen < newlen ? oldlen : newlen;
if (oldval.op == EXP.string_)
{
- StringExp oldse = cast(StringExp)oldval;
+ StringExp oldse = oldval.isStringExp();
void* s = mem.xcalloc(newlen + 1, oldse.sz);
const data = oldse.peekData();
memcpy(s, data.ptr, copylen * oldse.sz);
@@ -1790,7 +1790,7 @@ Expression changeArrayLiteralLength(UnionExp* pue, const ref Loc loc, TypeArray
}
}
emplaceExp!(StringExp)(pue, loc, s[0 .. newlen * oldse.sz], newlen, oldse.sz);
- StringExp se = cast(StringExp)pue.exp();
+ StringExp se = pue.exp().isStringExp();
se.type = arrayType;
se.sz = oldse.sz;
se.committed = oldse.committed;
@@ -1801,7 +1801,7 @@ Expression changeArrayLiteralLength(UnionExp* pue, const ref Loc loc, TypeArray
if (oldlen != 0)
{
assert(oldval.op == EXP.arrayLiteral);
- ArrayLiteralExp ae = cast(ArrayLiteralExp)oldval;
+ ArrayLiteralExp ae = oldval.isArrayLiteralExp();
foreach (size_t i; 0 .. copylen)
(*elements)[i] = (*ae.elements)[indxlo + i];
}
@@ -1819,7 +1819,7 @@ Expression changeArrayLiteralLength(UnionExp* pue, const ref Loc loc, TypeArray
(*elements)[i] = defaultElem;
}
emplaceExp!(ArrayLiteralExp)(pue, loc, arrayType, elements);
- ArrayLiteralExp aae = cast(ArrayLiteralExp)pue.exp();
+ ArrayLiteralExp aae = pue.exp().isArrayLiteralExp();
aae.ownedByCtfe = OwnedBy.ctfe;
}
return pue.exp();
@@ -1874,14 +1874,14 @@ bool isCtfeValueValid(Expression newval)
{
// &struct.func or &clasinst.func
// &nestedfunc
- Expression ethis = (cast(DelegateExp)newval).e1;
- return (ethis.op == EXP.structLiteral || ethis.op == EXP.classReference || ethis.op == EXP.variable && (cast(VarExp)ethis).var == (cast(DelegateExp)newval).func);
+ Expression ethis = newval.isDelegateExp().e1;
+ return (ethis.op == EXP.structLiteral || ethis.op == EXP.classReference || ethis.op == EXP.variable && ethis.isVarExp().var == newval.isDelegateExp().func);
}
case EXP.symbolOffset:
{
// function pointer, or pointer to static variable
- Declaration d = (cast(SymOffExp)newval).var;
+ Declaration d = newval.isSymOffExp().var;
return d.isFuncDeclaration() || d.isDataseg();
}
@@ -1894,7 +1894,7 @@ bool isCtfeValueValid(Expression newval)
case EXP.address:
{
// e1 should be a CTFE reference
- Expression e1 = (cast(AddrExp)newval).e1;
+ Expression e1 = newval.isAddrExp().e1;
return tb.ty == Tpointer &&
(
(e1.op == EXP.structLiteral || e1.op == EXP.arrayLiteral) && isCtfeValueValid(e1) ||
@@ -1908,7 +1908,7 @@ bool isCtfeValueValid(Expression newval)
case EXP.slice:
{
// e1 should be an array aggregate
- const SliceExp se = cast(SliceExp)newval;
+ const SliceExp se = newval.isSliceExp();
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);
@@ -1932,7 +1932,7 @@ bool isCtfeReferenceValid(Expression newval)
case EXP.variable:
{
- const VarDeclaration v = (cast(VarExp)newval).var.isVarDeclaration();
+ const VarDeclaration v = newval.isVarExp().var.isVarDeclaration();
assert(v);
// Must not be a reference to a reference
return true;
@@ -1940,13 +1940,13 @@ bool isCtfeReferenceValid(Expression newval)
case EXP.index:
{
- const Expression eagg = (cast(IndexExp)newval).e1;
+ const Expression eagg = newval.isIndexExp().e1;
return eagg.op == EXP.string_ || eagg.op == EXP.arrayLiteral || eagg.op == EXP.assocArrayLiteral;
}
case EXP.dotVariable:
{
- Expression eagg = (cast(DotVarExp)newval).e1;
+ Expression eagg = newval.isDotVarExp().e1;
return (eagg.op == EXP.structLiteral || eagg.op == EXP.classReference) && isCtfeValueValid(eagg);
}
@@ -1968,19 +1968,19 @@ void showCtfeExpr(Expression e, int level = 0)
ClassDeclaration cd = null;
if (e.op == EXP.structLiteral)
{
- elements = (cast(StructLiteralExp)e).elements;
- sd = (cast(StructLiteralExp)e).sd;
+ elements = e.isStructLiteralExp().elements;
+ sd = e.isStructLiteralExp().sd;
printf("STRUCT type = %s %p:\n", e.type.toChars(), e);
}
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);
+ elements = e.isClassReferenceExp().value.elements;
+ cd = e.isClassReferenceExp().originalClass();
+ printf("CLASS type = %s %p:\n", e.type.toChars(), e.isClassReferenceExp().value);
}
else if (e.op == EXP.arrayLiteral)
{
- elements = (cast(ArrayLiteralExp)e).elements;
+ elements = e.isArrayLiteralExp().elements;
printf("ARRAY LITERAL type=%s %p:\n", e.type.toChars(), e);
}
else if (e.op == EXP.assocArrayLiteral)
@@ -1994,19 +1994,19 @@ void showCtfeExpr(Expression e, int level = 0)
else if (e.op == EXP.slice)
{
printf("SLICE %p: %s\n", e, e.toChars());
- showCtfeExpr((cast(SliceExp)e).e1, level + 1);
+ showCtfeExpr(e.isSliceExp().e1, level + 1);
}
else if (e.op == EXP.variable)
{
printf("VAR %p %s\n", e, e.toChars());
- VarDeclaration v = (cast(VarExp)e).var.isVarDeclaration();
+ VarDeclaration v = e.isVarExp().var.isVarDeclaration();
if (v && getValue(v))
showCtfeExpr(getValue(v), level + 1);
}
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());
+ printf("POINTER %p to %p: %s\n", e, e.isAddrExp().e1, e.toChars());
}
else
printf("VALUE %p: %s\n", e, e.toChars());
@@ -2086,7 +2086,7 @@ UnionExp voidInitLiteral(Type t, VarDeclaration var)
(*elements)[i] = elem;
}
emplaceExp!(ArrayLiteralExp)(&ue, var.loc, tsa, elements);
- ArrayLiteralExp ae = cast(ArrayLiteralExp)ue.exp();
+ ArrayLiteralExp ae = ue.exp().isArrayLiteralExp();
ae.ownedByCtfe = OwnedBy.ctfe;
}
else if (t.ty == Tstruct)
@@ -2098,7 +2098,7 @@ UnionExp voidInitLiteral(Type t, VarDeclaration var)
(*exps)[i] = voidInitLiteral(ts.sym.fields[i].type, ts.sym.fields[i]).copy();
}
emplaceExp!(StructLiteralExp)(&ue, var.loc, ts.sym, exps);
- StructLiteralExp se = cast(StructLiteralExp)ue.exp();
+ StructLiteralExp se = ue.exp().isStructLiteralExp();
se.type = ts;
se.ownedByCtfe = OwnedBy.ctfe;
}
diff --git a/gcc/d/dmd/ctorflow.d b/gcc/d/dmd/ctorflow.d
index cc251b0..c04793d 100644
--- a/gcc/d/dmd/ctorflow.d
+++ b/gcc/d/dmd/ctorflow.d
@@ -222,4 +222,3 @@ bool mergeFieldInit(ref CSX a, const CSX b) pure nothrow
}
return ok;
}
-
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 887bb89..685987b 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -3880,4 +3880,3 @@ IntRange getIntRange(Expression e)
case EXP.negate : return visitNeg(e.isNegExp());
}
}
-
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index 82a5f3b..c0e40a5 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -292,7 +292,7 @@ extern (C++) abstract class Declaration : Dsymbol
* postblit. Print the first field that has
* a disabled postblit.
*/
- if (postblit.generated)
+ if (postblit.isGenerated())
{
auto sd = p.isStructDeclaration();
assert(sd);
@@ -334,7 +334,7 @@ extern (C++) abstract class Declaration : Dsymbol
if (auto ctor = isCtorDeclaration())
{
- if (ctor.isCpCtor && ctor.generated)
+ if (ctor.isCpCtor && ctor.isGenerated())
{
.error(loc, "Generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars());
return true;
@@ -1060,24 +1060,51 @@ extern (C++) class VarDeclaration : Declaration
enum AdrOnStackNone = ~0u;
uint ctfeAdrOnStack;
- bool isargptr; // if parameter that _argptr points to
- 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` fields that are compacted into bit fields in a string mixin
+ private extern (D) static struct BitFields
+ {
+ bool isargptr; /// if parameter that _argptr points to
+ 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
+
+ /// It is a class that was allocated on the stack
+ ///
+ /// This means the var is not rebindable once assigned,
+ /// and the destructor gets run when it goes out of scope
+ bool onstack;
- // Both these mean the var is not rebindable once assigned,
- // and the destructor gets run when it goes out of scope
- bool onstack; // it is a class that was allocated on the stack
+ bool overlapped; /// if it is a field and has overlapping
+ bool overlapUnsafe; /// if it is an overlapping field and the overlaps are unsafe
+ bool doNotInferScope; /// do not infer 'scope' for this variable
+ bool doNotInferReturn; /// do not infer 'return' for this variable
+
+ bool isArgDtorVar; /// temporary created to handle scope destruction of a function argument
+ }
+ private ushort bitFields; // stores multiple booleans for BitFields
byte canassign; // it can be assigned to
- bool overlapped; // if it is a field and has overlapping
- bool overlapUnsafe; // if it is an overlapping field and the overlaps are unsafe
- bool doNotInferScope; // do not infer 'scope' for this variable
- bool doNotInferReturn; // do not infer 'return' for this variable
ubyte isdataseg; // private data for isDataseg 0 unset, 1 true, 2 false
- bool isArgDtorVar; // temporary created to handle scope destruction of a function argument
+ // Generate getter and setter functions for `bitFields`
+ extern (D) mixin(() {
+ string result = "extern (C++) pure nothrow @nogc @safe final {";
+ foreach (size_t i, mem; __traits(allMembers, BitFields))
+ {
+ result ~= "
+ /// set or get the corresponding BitFields member
+ bool "~mem~"() const { return !!(bitFields & (1 << "~i.stringof~")); }
+ /// ditto
+ bool "~mem~"(bool v)
+ {
+ v ? (bitFields |= (1 << "~i.stringof~")) : (bitFields &= ~(1 << "~i.stringof~"));
+ return v;
+ }";
+ }
+ return result ~ "}";
+ }());
+
final extern (D) this(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
in
@@ -1642,64 +1669,6 @@ extern (C++) class VarDeclaration : Declaration
{
v.visit(this);
}
-
- /**********************************
- * Determine if `this` has a lifetime that lasts past
- * the destruction of `v`
- * Params:
- * v = variable to test against
- * Returns:
- * true if it does
- */
- final bool enclosesLifetimeOf(VarDeclaration v) const pure
- {
- // VarDeclaration's with these STC's need special treatment
- enum special = STC.temp | STC.foreach_;
-
- // Sequence numbers work when there are no special VarDeclaration's involved
- if (!((this.storage_class | v.storage_class) & special))
- {
- assert(this.sequenceNumber != this.sequenceNumber.init);
- assert(v.sequenceNumber != v.sequenceNumber.init);
-
- return (this.sequenceNumber < v.sequenceNumber);
- }
-
- // Assume that semantic produces temporaries according to their lifetime
- // (It won't create a temporary before the actual content)
- if ((this.storage_class & special) && (v.storage_class & special))
- return this.sequenceNumber < v.sequenceNumber;
-
- // Fall back to lexical order
- assert(this.loc != Loc.initial);
- assert(v.loc != Loc.initial);
-
- if (this.loc.linnum != v.loc.linnum)
- return this.loc.linnum < v.loc.linnum;
-
- if (this.loc.charnum != v.loc.charnum)
- return this.loc.charnum < v.loc.charnum;
-
- // Default fallback
- return this.sequenceNumber < v.sequenceNumber;
- }
-
- /***************************************
- * Add variable to maybes[].
- * When a maybescope variable `v` is assigned to a maybescope variable `this`,
- * we cannot determine if `this` is actually scope until the semantic
- * analysis for the function is completed. Thus, we save the data
- * until then.
- * Params:
- * v = an STC.maybescope variable that was assigned to `this`
- */
- final void addMaybe(VarDeclaration v)
- {
- //printf("add %s to %s's list of dependencies\n", v.toChars(), toChars());
- if (!maybes)
- maybes = new VarDeclarations();
- maybes.push(v);
- }
}
/*******************************************************
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 9986ea3..441a966 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -241,22 +241,33 @@ public:
// When interpreting, these point to the value (NULL if value not determinable)
// The index of this variable on the CTFE stack, ~0u if not allocated
unsigned ctfeAdrOnStack;
-
- bool isargptr; // if parameter that _argptr points to
- 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
- char canassign; // it can be assigned to
- bool overlapped; // if it is a field and has overlapping
- bool overlapUnsafe; // if it is an overlapping field and the overlaps are unsafe
- bool doNotInferScope; // do not infer 'scope' for this variable
- bool doNotInferReturn; // do not infer 'return' for this variable
- unsigned char isdataseg; // private data for isDataseg
- bool isArgDtorVar; // temporary created to handle scope destruction of a function argument
-
-public:
+private:
+ uint16_t bitFields;
+public:
+ int8_t canassign; // // it can be assigned to
+ uint8_t isdataseg; // private data for isDataseg
+ bool isargptr() const; // if parameter that _argptr points to
+ bool isargptr(bool v);
+ bool ctorinit() const; // it has been initialized in a ctor
+ bool ctorinit(bool v);
+ bool iscatchvar() const; // this is the exception object variable in catch() clause
+ bool iscatchvar(bool v);
+ bool isowner() const; // this is an Owner, despite it being `scope`
+ bool isowner(bool v);
+ bool setInCtorOnly() const; // field can only be set in a constructor, as it is const or immutable
+ bool setInCtorOnly(bool v);
+ bool onstack() const; // it is a class that was allocated on the stack
+ bool onstack(bool v);
+ bool overlapped() const; // if it is a field and has overlapping
+ bool overlapped(bool v);
+ bool overlapUnsafe() const; // if it is an overlapping field and the overlaps are unsafe
+ bool overlapUnsafe(bool v);
+ bool doNotInferScope() const; // do not infer 'scope' for this variable
+ bool doNotInferScope(bool v);
+ bool doNotInferReturn() const; // do not infer 'return' for this variable
+ bool doNotInferReturn(bool v);
+ bool isArgDtorVar() const; // temporary created to handle scope destruction of a function argument
+ bool isArgDtorVar(bool v);
static VarDeclaration *create(const Loc &loc, Type *t, Identifier *id, Initializer *init, StorageClass storage_class = STCundefined);
VarDeclaration *syntaxCopy(Dsymbol *);
void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion);
@@ -273,7 +284,6 @@ public:
bool hasPointers();
bool canTakeAddressOf();
bool needsScopeDtor();
- bool enclosesLifetimeOf(VarDeclaration *v) const;
void checkCtorConstInit();
Dsymbol *toAlias();
// Eliminate need for dynamic_cast
@@ -541,7 +551,6 @@ public:
// scopes from having the same name
DsymbolTable *localsymtab;
VarDeclaration *vthis; // 'this' parameter (member and nested)
- bool isThis2; // has a dual-context 'this' parameter
VarDeclaration *v_arguments; // '_arguments' parameter
VarDeclaration *v_argptr; // '_argptr' variable
@@ -551,29 +560,20 @@ public:
FuncDeclaration *overnext0; // next in overload list (only used during IFTI)
Loc endloc; // location of closing curly bracket
int vtblIndex; // for member functions, index into vtbl[]
- bool naked; // true if naked
- bool generated; // true if function was generated by the compiler rather than
- // supplied by the user
- bool hasAlwaysInlines; // contains references to functions that must be inlined
- unsigned char isCrtCtorDtor; // has attribute pragma(crt_constructor(1)/crt_destructor(2))
- // not set before the glue layer
+
ILS inlineStatusStmt;
ILS inlineStatusExp;
PINLINE inlining;
int inlineNest; // !=0 if nested inline
- bool eh_none; /// true if no exception unwinding is needed
// true if errors in semantic3 this function's frame ptr
- bool semantic3Errors;
ForeachStatement *fes; // if foreach body, this is the foreach
BaseClass* interfaceVirtual; // if virtual, but only appears in interface vtbl[]
- bool introducing; // true if 'introducing' function
// if !=NULL, then this is the type
// of the 'introducing' function
// this one is overriding
Type *tintro;
- bool inferRetType; // true if return type is to be inferred
StorageClass storage_class2; // storage class for template onemember's
// Things that should really go into Scope
@@ -585,8 +585,6 @@ public:
// 16 if there are multiple return statements
int hasReturnExp;
- // Support for NRVO (named return value optimization)
- bool nrvo_can; // true means we can do it
VarDeclaration *nrvo_var; // variable to replace with shidden
Symbol *shidden; // hidden pointer passed to function
@@ -654,6 +652,19 @@ public:
bool isNogc();
bool isNogcBypassingInference();
+ bool isNRVO() const;
+ void isNRVO(bool v);
+ bool isNaked() const;
+ bool isGenerated() const;
+ void isGenerated(bool v);
+ bool isIntroducing() const;
+ bool hasSemantic3Errors() const;
+ bool hasNoEH() const;
+ bool inferRetType() const;
+ bool hasDualContext() const;
+ bool hasAlwaysInlines() const;
+ bool isCrtCtor() const;
+ bool isCrtDtor() const;
virtual bool isNested() const;
AggregateDeclaration *isThis();
diff --git a/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d
index 90e48f8..aba290b 100644
--- a/gcc/d/dmd/denum.d
+++ b/gcc/d/dmd/denum.d
@@ -96,7 +96,7 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
override void setScope(Scope* sc)
{
- if (semanticRun > PASS.init)
+ if (semanticRun > PASS.initial)
return;
ScopeDsymbol.setScope(sc);
}
@@ -163,6 +163,9 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
if (defaultval)
return defaultval;
+ if (isCsymbol())
+ return memtype.defaultInit(loc, true);
+
if (_scope)
dsymbolSemantic(this, _scope);
if (errors)
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 30a8a44..3cfc07a 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -535,7 +535,7 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
istatex.caller = istate;
istatex.fd = fd;
- if (fd.isThis2)
+ if (fd.hasDualContext())
{
Expression arg0 = thisarg;
if (arg0 && arg0.type.ty == Tstruct)
@@ -678,7 +678,7 @@ private Expression interpretFunction(UnionExp* pue, FuncDeclaration fd, InterSta
e = CTFEExp.voidexp;
if (tf.isref && e.op == EXP.variable && e.isVarExp().var == fd.vthis)
e = thisarg;
- if (tf.isref && fd.isThis2 && e.op == EXP.index)
+ if (tf.isref && fd.hasDualContext() && e.op == EXP.index)
{
auto ie = e.isIndexExp();
auto pe = ie.e1.isPtrExp();
@@ -944,7 +944,7 @@ public:
if (auto eaddr = e.isAddrExp())
x = eaddr.e1;
VarDeclaration v;
- while (x.op == EXP.variable && (v = (cast(VarExp)x).var.isVarDeclaration()) !is null)
+ while (x.op == EXP.variable && (v = x.isVarExp().var.isVarDeclaration()) !is null)
{
if (v.storage_class & STC.ref_)
{
@@ -1526,7 +1526,7 @@ public:
}
while ((*boss.value.elements)[next].op == EXP.classReference)
{
- boss = cast(ClassReferenceExp)(*boss.value.elements)[next];
+ boss = (*boss.value.elements)[next].isClassReferenceExp();
}
(*boss.value.elements)[next] = collateral;
return oldest;
@@ -1752,7 +1752,7 @@ public:
if (istate && istate.fd.vthis)
{
result = ctfeEmplaceExp!VarExp(e.loc, istate.fd.vthis);
- if (istate.fd.isThis2)
+ if (istate.fd.hasDualContext())
{
result = ctfeEmplaceExp!PtrExp(e.loc, result);
result.type = Type.tvoidptr.sarrayOf(2);
@@ -1768,15 +1768,15 @@ public:
result = ctfeGlobals.stack.getThis();
if (result)
{
- if (istate && istate.fd.isThis2)
+ if (istate && istate.fd.hasDualContext())
{
assert(result.op == EXP.address);
- result = (cast(AddrExp)result).e1;
+ result = result.isAddrExp().e1;
assert(result.op == EXP.arrayLiteral);
- result = (*(cast(ArrayLiteralExp)result).elements)[0];
+ result = (*result.isArrayLiteralExp().elements)[0];
if (e.type.ty == Tstruct)
{
- result = (cast(AddrExp)result).e1;
+ result = result.isAddrExp().e1;
}
return;
}
@@ -1873,7 +1873,9 @@ public:
{
fromType = (cast(TypeArray)e.var.type).next;
}
- if (e.var.isDataseg() && ((e.offset == 0 && isSafePointerCast(e.var.type, pointee)) || (fromType && isSafePointerCast(fromType, pointee))))
+ if (e.var.isDataseg() && ((e.offset == 0 && isSafePointerCast(e.var.type, pointee)) ||
+ (fromType && isSafePointerCast(fromType, pointee)) ||
+ (e.var.isCsymbol() && e.offset + pointee.size() <= e.var.type.size())))
{
result = e;
return;
@@ -1980,7 +1982,7 @@ public:
if (decl.isDataseg()) {
// Normally this is already done by optimize()
// Do it here in case optimize(WANTvalue) wasn't run before CTFE
- emplaceExp!(SymOffExp)(pue, e.loc, (cast(VarExp)e.e1).var, 0);
+ emplaceExp!(SymOffExp)(pue, e.loc, e.e1.isVarExp().var, 0);
result = pue.exp();
result.type = e.type;
return;
@@ -2399,7 +2401,7 @@ public:
return;
}
- ClassDeclaration cd = (cast(ClassReferenceExp)result).originalClass();
+ ClassDeclaration cd = result.isClassReferenceExp().originalClass();
assert(cd);
emplaceExp!(TypeidExp)(pue, e.loc, cd.type);
@@ -2487,7 +2489,7 @@ public:
else
{
// segfault bug 6250
- assert(exp.op != EXP.index || (cast(IndexExp)exp).e1 != e);
+ assert(exp.op != EXP.index || exp.isIndexExp().e1 != e);
ex = interpretRegion(exp, istate);
if (exceptionOrCant(ex))
@@ -2521,7 +2523,7 @@ public:
return;
}
emplaceExp!(ArrayLiteralExp)(pue, e.loc, e.type, basis, expsx);
- auto ale = cast(ArrayLiteralExp)pue.exp();
+ auto ale = pue.exp().isArrayLiteralExp();
ale.ownedByCtfe = OwnedBy.ctfe;
result = ale;
}
@@ -2705,7 +2707,7 @@ public:
return;
}
emplaceExp!(StructLiteralExp)(pue, e.loc, e.sd, expsx);
- auto sle = cast(StructLiteralExp)pue.exp();
+ auto sle = pue.exp().isStructLiteralExp();
sle.type = e.type;
sle.ownedByCtfe = OwnedBy.ctfe;
sle.origin = e.origin;
@@ -2737,7 +2739,7 @@ public:
foreach (ref element; *elements)
element = copyLiteral(elem).copy();
emplaceExp!(ArrayLiteralExp)(pue, loc, newtype, elements);
- auto ae = cast(ArrayLiteralExp)pue.exp();
+ auto ae = pue.exp().isArrayLiteralExp();
ae.ownedByCtfe = OwnedBy.ctfe;
return ae;
}
@@ -2959,7 +2961,7 @@ public:
result = e; // optimize: reuse this CTFE reference
else
{
- auto edt = cast(DotTypeExp)e.copy();
+ auto edt = e.copy().isDotTypeExp();
edt.e1 = (e1 == ue.exp()) ? e1.copy() : e1; // don't return pointer to ue
result = edt;
}
@@ -3335,7 +3337,7 @@ public:
if (exceptionOrCant(newval))
return;
- VarDeclaration v = (cast(VarExp)e1).var.isVarDeclaration();
+ VarDeclaration v = e1.isVarExp().var.isVarDeclaration();
setValue(v, newval);
// Get the value to return. Note that 'newval' is an Lvalue,
@@ -3351,7 +3353,7 @@ public:
{
while (e1.op == EXP.cast_)
{
- CastExp ce = cast(CastExp)e1;
+ CastExp ce = e1.isCastExp();
e1 = ce.e1;
}
}
@@ -3362,7 +3364,7 @@ public:
AssocArrayLiteralExp existingAA = null;
Expression lastIndex = null;
Expression oldval = null;
- if (e1.op == EXP.index && (cast(IndexExp)e1).e1.type.toBasetype().ty == Taarray)
+ if (e1.op == EXP.index && e1.isIndexExp().e1.type.toBasetype().ty == Taarray)
{
// ---------------------------------------
// Deal with AA index assignment
@@ -3374,12 +3376,12 @@ public:
* (2) If the ultimate AA is null, no insertion happens at all. Instead,
* we create nested AA literals, and change it into a assignment.
*/
- IndexExp ie = cast(IndexExp)e1;
+ IndexExp ie = e1.isIndexExp();
int depth = 0; // how many nested AA indices are there?
- while (ie.e1.op == EXP.index && (cast(IndexExp)ie.e1).e1.type.toBasetype().ty == Taarray)
+ while (ie.e1.op == EXP.index && ie.e1.isIndexExp().e1.type.toBasetype().ty == Taarray)
{
assert(ie.modifiable);
- ie = cast(IndexExp)ie.e1;
+ ie = ie.e1.isIndexExp();
++depth;
}
@@ -3392,7 +3394,7 @@ public:
// Normal case, ultimate parent AA already exists
// We need to walk from the deepest index up, checking that an AA literal
// already exists on each level.
- lastIndex = interpretRegion((cast(IndexExp)e1).e2, istate);
+ lastIndex = interpretRegion(e1.isIndexExp().e2, istate);
lastIndex = resolveSlice(lastIndex); // only happens with AA assignment
if (exceptionOrCant(lastIndex))
return;
@@ -3400,9 +3402,9 @@ public:
while (depth > 0)
{
// Walk the syntax tree to find the indexExp at this depth
- IndexExp xe = cast(IndexExp)e1;
+ IndexExp xe = e1.isIndexExp();
foreach (d; 0 .. depth)
- xe = cast(IndexExp)xe.e1;
+ xe = xe.e1.isIndexExp();
Expression ekey = interpretRegion(xe.e2, istate);
if (exceptionOrCant(ekey))
@@ -3450,9 +3452,9 @@ public:
oldval = copyLiteral(e.e1.type.defaultInitLiteral(e.loc)).copy();
Expression newaae = oldval;
- while (e1.op == EXP.index && (cast(IndexExp)e1).e1.type.toBasetype().ty == Taarray)
+ while (e1.op == EXP.index && e1.isIndexExp().e1.type.toBasetype().ty == Taarray)
{
- Expression ekey = interpretRegion((cast(IndexExp)e1).e2, istate);
+ Expression ekey = interpretRegion(e1.isIndexExp().e2, istate);
if (exceptionOrCant(ekey))
return;
ekey = resolveSlice(ekey); // only happens with AA assignment
@@ -3463,7 +3465,7 @@ public:
valuesx.push(newaae);
auto aae = ctfeEmplaceExp!AssocArrayLiteralExp(e.loc, keysx, valuesx);
- aae.type = (cast(IndexExp)e1).e1.type;
+ aae.type = e1.isIndexExp().e1.type;
aae.ownedByCtfe = OwnedBy.ctfe;
if (!existingAA)
{
@@ -3471,7 +3473,7 @@ public:
lastIndex = ekey;
}
newaae = aae;
- e1 = (cast(IndexExp)e1).e1;
+ e1 = e1.isIndexExp().e1;
}
// We must set to aggregate with newaae
@@ -3521,11 +3523,11 @@ public:
if (exceptionOrCant(e1))
return;
- if (e1.op == EXP.index && (cast(IndexExp)e1).e1.type.toBasetype().ty == Taarray)
+ if (e1.op == EXP.index && e1.isIndexExp().e1.type.toBasetype().ty == Taarray)
{
- IndexExp ie = cast(IndexExp)e1;
+ IndexExp ie = e1.isIndexExp();
assert(ie.e1.op == EXP.assocArrayLiteral);
- existingAA = cast(AssocArrayLiteralExp)ie.e1;
+ existingAA = ie.e1.isAssocArrayLiteralExp();
lastIndex = ie.e2;
}
}
@@ -3657,7 +3659,7 @@ public:
// We have changed it into a reference assignment
// Note that returnValue is still the new length.
- e1 = (cast(ArrayLengthExp)e1).e1;
+ e1 = e1.isArrayLengthExp().e1;
Type t = e1.type.toBasetype();
if (t.ty != Tarray)
{
@@ -3733,8 +3735,8 @@ public:
if (auto dve = e1x.isDotVarExp())
{
auto ex = dve.e1;
- auto sle = ex.op == EXP.structLiteral ? (cast(StructLiteralExp)ex)
- : ex.op == EXP.classReference ? (cast(ClassReferenceExp)ex).value
+ auto sle = ex.op == EXP.structLiteral ? ex.isStructLiteralExp()
+ : ex.op == EXP.classReference ? ex.isClassReferenceExp().value
: null;
auto v = dve.var.isVarDeclaration();
if (!sle || !v)
@@ -3792,10 +3794,10 @@ public:
* e.v = newval
*/
auto ex = dve.e1;
- auto sle = ex.op == EXP.structLiteral ? (cast(StructLiteralExp)ex)
- : ex.op == EXP.classReference ? (cast(ClassReferenceExp)ex).value
+ auto sle = ex.op == EXP.structLiteral ? ex.isStructLiteralExp()
+ : ex.op == EXP.classReference ? ex.isClassReferenceExp().value
: null;
- auto v = (cast(DotVarExp)e1).var.isVarDeclaration();
+ auto v = e1.isDotVarExp().var.isVarDeclaration();
if (!sle || !v)
{
e.error("CTFE internal error: dotvar assignment");
@@ -3808,7 +3810,7 @@ public:
}
int fieldi = ex.op == EXP.structLiteral ? findFieldIndexByName(sle.sd, v)
- : (cast(ClassReferenceExp)ex).findFieldIndexByName(v);
+ : ex.isClassReferenceExp().findFieldIndexByName(v);
if (fieldi == -1)
{
e.error("CTFE internal error: cannot find field `%s` in `%s`", v.toChars(), ex.toChars());
@@ -3865,7 +3867,7 @@ public:
return CTFEExp.cantexp;
}
- ArrayLiteralExp existingAE = cast(ArrayLiteralExp)aggregate;
+ ArrayLiteralExp existingAE = aggregate.isArrayLiteralExp();
if (existingAE.ownedByCtfe != OwnedBy.ctfe)
{
e.error("cannot modify read-only constant `%s`", existingAE.toChars());
@@ -3920,8 +3922,8 @@ public:
assert(oldval.op == EXP.arrayLiteral);
assert(newval.op == EXP.arrayLiteral);
- Expressions* oldelems = (cast(ArrayLiteralExp)oldval).elements;
- Expressions* newelems = (cast(ArrayLiteralExp)newval).elements;
+ Expressions* oldelems = oldval.isArrayLiteralExp().elements;
+ Expressions* newelems = newval.isArrayLiteralExp().elements;
assert(oldelems.dim == newelems.dim);
Type elemtype = oldval.type.nextOf();
@@ -4124,7 +4126,7 @@ public:
if (newval.op == EXP.slice && !isBlockAssignment)
{
- auto se = cast(SliceExp)newval;
+ auto se = newval.isSliceExp();
auto aggr2 = se.e1;
const srclower = se.lwr.toInteger();
const srcupper = se.upr.toInteger();
@@ -4140,7 +4142,7 @@ public:
// https://issues.dlang.org/show_bug.cgi?id=14024
assert(aggr2.op == EXP.arrayLiteral);
Expressions* oldelems = existingAE.elements;
- Expressions* newelems = (cast(ArrayLiteralExp)aggr2).elements;
+ Expressions* newelems = aggr2.isArrayLiteralExp().elements;
Type elemtype = aggregate.type.nextOf();
bool needsPostblit = e.e2.isLvalue();
@@ -4213,13 +4215,13 @@ public:
/* Mixed slice: it was initialized as an array literal of chars/integers.
* Now a slice of it is being set with a string.
*/
- sliceAssignArrayLiteralFromString(existingAE, cast(StringExp)newval, cast(size_t)firstIndex);
+ sliceAssignArrayLiteralFromString(existingAE, newval.isStringExp(), cast(size_t)firstIndex);
return newval;
}
if (newval.op == EXP.arrayLiteral && !isBlockAssignment)
{
Expressions* oldelems = existingAE.elements;
- Expressions* newelems = (cast(ArrayLiteralExp)newval).elements;
+ Expressions* newelems = newval.isArrayLiteralExp().elements;
Type elemtype = existingAE.type.nextOf();
bool needsPostblit = e.op != EXP.blit && e.e2.isLvalue();
foreach (j, newelem; *newelems)
@@ -4264,7 +4266,7 @@ public:
if (!directblk && (*w)[k].op == EXP.arrayLiteral)
{
// Multidimensional array block assign
- if (Expression ex = assignTo(cast(ArrayLiteralExp)(*w)[k]))
+ if (Expression ex = assignTo((*w)[k].isArrayLiteralExp()))
return ex;
}
else if (refCopy)
@@ -4420,7 +4422,7 @@ public:
while (e.op == EXP.not)
{
ret *= -1;
- e = (cast(NotExp)e).e1;
+ e = e.isNotExp().e1;
}
switch (e.op)
{
@@ -4430,8 +4432,8 @@ public:
goto case; /+ fall through +/
case EXP.greaterThan:
case EXP.greaterOrEqual:
- *p1 = (cast(BinExp)e).e1;
- *p2 = (cast(BinExp)e).e2;
+ *p1 = e.isBinExp().e1;
+ *p2 = e.isBinExp().e2;
if (!(isPointer((*p1).type) && isPointer((*p2).type)))
ret = 0;
break;
@@ -4898,7 +4900,7 @@ public:
}
}
- if (fd && fd.semanticRun >= PASS.semantic3done && fd.semantic3Errors)
+ if (fd && fd.semanticRun >= PASS.semantic3done && fd.hasSemantic3Errors())
{
e.error("CTFE failed because of previous errors in `%s`", fd.toChars());
result = CTFEExp.cantexp;
@@ -5201,7 +5203,7 @@ public:
// Pointer to a non-array variable
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());
+ e.error("mutable variable `%s` cannot be %s at compile time, even through a pointer", cast(char*)(modify ? "modified" : "read"), agg.isSymOffExp().var.toChars());
return false;
}
@@ -5285,7 +5287,7 @@ public:
e.error("index %llu exceeds array length %llu", index, iupr - ilwr);
return false;
}
- *pagg = (cast(SliceExp)e1).e1;
+ *pagg = e1.isSliceExp().e1;
*pidx = index + ilwr;
}
else
@@ -5377,7 +5379,7 @@ public:
assert(e1.op == EXP.assocArrayLiteral);
UnionExp e2tmp = void;
e2 = resolveSlice(e2, &e2tmp);
- result = findKeyInAA(e.loc, cast(AssocArrayLiteralExp)e1, e2);
+ result = findKeyInAA(e.loc, e1.isAssocArrayLiteralExp(), e2);
if (!result)
{
e.error("key `%s` not found in associative array `%s`", e2.toChars(), e.e1.toChars());
@@ -5637,7 +5639,7 @@ public:
}
e1 = resolveSlice(e1);
- result = findKeyInAA(e.loc, cast(AssocArrayLiteralExp)e2, e1);
+ result = findKeyInAA(e.loc, e2.isAssocArrayLiteralExp(), e1);
if (exceptionOrCant(result))
return;
if (!result)
@@ -5742,7 +5744,7 @@ public:
return;
}
- auto cre = cast(ClassReferenceExp)result;
+ auto cre = result.isClassReferenceExp();
auto cd = cre.originalClass();
// Find dtor(s) in inheritance chain
@@ -5859,10 +5861,10 @@ public:
result = pue.exp();
return;
}
- if (e1.op == EXP.index && !(cast(IndexExp)e1).e1.type.equals(e1.type))
+ if (e1.op == EXP.index && !e1.isIndexExp().e1.type.equals(e1.type))
{
// type painting operation
- IndexExp ie = cast(IndexExp)e1;
+ IndexExp ie = e1.isIndexExp();
if (castBackFromVoid)
{
// get the original type. For strings, it's just the type...
@@ -5870,7 +5872,7 @@ public:
// ..but for arrays of type void*, it's the type of the element
if (ie.e1.op == EXP.arrayLiteral && ie.e2.op == EXP.int64)
{
- ArrayLiteralExp ale = cast(ArrayLiteralExp)ie.e1;
+ ArrayLiteralExp ale = ie.e1.isArrayLiteralExp();
const indx = cast(size_t)ie.e2.toInteger();
if (indx < ale.elements.dim)
{
@@ -5912,7 +5914,7 @@ public:
{
// &val[idx]
dinteger_t dim = (cast(TypeSArray)pointee.toBasetype()).dim.toInteger();
- IndexExp ie = cast(IndexExp)ae.e1;
+ IndexExp ie = ae.e1.isIndexExp();
Expression lwr = ie.e2;
Expression upr = ctfeEmplaceExp!IntegerExp(ie.e2.loc, ie.e2.toInteger() + dim, Type.tsize_t);
@@ -5938,7 +5940,7 @@ public:
if (auto ve = e1.isVarExp())
emplaceExp!(VarExp)(pue, e.loc, ve.var);
else
- emplaceExp!(SymOffExp)(pue, e.loc, (cast(SymOffExp)e1).var, (cast(SymOffExp)e1).offset);
+ emplaceExp!(SymOffExp)(pue, e.loc, e1.isSymOffExp().var, e1.isSymOffExp().offset);
result = pue.exp();
result.type = e.to;
return;
@@ -5966,7 +5968,7 @@ public:
{
// Note that the slice may be void[], so when checking for dangerous
// casts, we need to use the original type, which is se.e1.
- SliceExp se = cast(SliceExp)e1;
+ SliceExp se = e1.isSliceExp();
if (!isSafePointerCast(se.e1.type.nextOf(), e.to.nextOf()))
{
e.error("array cast from `%s` to `%s` is not supported at compile time", se.e1.type.toChars(), e.to.toChars());
@@ -6086,7 +6088,7 @@ public:
{
if (ae.e1.op == EXP.address && ae.e2.op == EXP.int64)
{
- AddrExp ade = cast(AddrExp)ae.e1;
+ AddrExp ade = ae.e1.isAddrExp();
Expression ex = interpretRegion(ade.e1, istate);
if (exceptionOrCant(ex))
return;
@@ -6131,7 +6133,7 @@ public:
}
// *(&x) ==> x
- result = (cast(AddrExp)result).e1;
+ result = result.isAddrExp().e1;
if (result.op == EXP.slice && e.type.toBasetype().ty == Tsarray)
{
@@ -6211,8 +6213,8 @@ public:
// We can't use getField, because it makes a copy
if (ex.op == EXP.classReference)
{
- se = (cast(ClassReferenceExp)ex).value;
- i = (cast(ClassReferenceExp)ex).findFieldIndexByName(v);
+ se = ex.isClassReferenceExp().value;
+ i = ex.isClassReferenceExp().findFieldIndexByName(v);
}
else if (ex.op == EXP.typeid_)
{
@@ -6233,7 +6235,7 @@ public:
}
else
{
- se = cast(StructLiteralExp)ex;
+ se = ex.isStructLiteralExp();
i = findFieldIndexByName(se.sd, v);
}
if (i == -1)
@@ -6540,7 +6542,7 @@ private Expression scrubReturnValue(const ref Loc loc, Expression e)
if (e.op == EXP.classReference)
{
- StructLiteralExp sle = (cast(ClassReferenceExp)e).value;
+ StructLiteralExp sle = e.isClassReferenceExp().value;
if (auto ex = scrubSE(sle))
return ex;
}
@@ -6620,7 +6622,7 @@ private Expression scrubCacheValue(Expression e)
if (e.op == EXP.classReference)
{
- if (auto ex = scrubSE((cast(ClassReferenceExp)e).value))
+ if (auto ex = scrubSE(e.isClassReferenceExp().value))
return ex;
}
else if (auto sle = e.isStructLiteralExp())
@@ -6767,14 +6769,14 @@ private Expression copyRegionExp(Expression e)
case EXP.vector:
case EXP.dotVariable:
{
- UnaExp ue = cast(UnaExp)e;
+ UnaExp ue = e.isUnaExp();
ue.e1 = copyRegionExp(ue.e1);
break;
}
case EXP.index:
{
- BinExp be = cast(BinExp)e;
+ BinExp be = e.isBinExp();
be.e1 = copyRegionExp(be.e1);
be.e2 = copyRegionExp(be.e2);
break;
@@ -6939,7 +6941,7 @@ private Expression interpret_aaApply(UnionExp* pue, InterState* istate, Expressi
Expressions args = Expressions(numParams);
- AssocArrayLiteralExp ae = cast(AssocArrayLiteralExp)aa;
+ AssocArrayLiteralExp ae = aa.isAssocArrayLiteralExp();
if (!ae.keys || ae.keys.dim == 0)
return ctfeEmplaceExp!IntegerExp(deleg.loc, 0, Type.tsize_t);
Expression eresult;
@@ -7298,7 +7300,7 @@ private Expression evaluateIfBuiltin(UnionExp* pue, InterState* istate, const re
{
// At present, the constructors just copy their arguments into the struct.
// But we might need some magic if stack tracing gets added to druntime.
- StructLiteralExp se = (cast(ClassReferenceExp)pthis).value;
+ StructLiteralExp se = pthis.isClassReferenceExp().value;
assert(arguments.dim <= se.elements.dim);
foreach (i, arg; *arguments)
{
diff --git a/gcc/d/dmd/dmangle.d b/gcc/d/dmd/dmangle.d
index 1e6799f..c3662a7 100644
--- a/gcc/d/dmd/dmangle.d
+++ b/gcc/d/dmd/dmangle.d
@@ -991,10 +991,6 @@ public:
if (stc & STC.returninferred)
stc &= ~(STC.return_ | STC.returninferred);
- // 'return inout ref' is the same as 'inout ref'
- if ((stc & (STC.return_ | STC.wild)) == (STC.return_ | STC.wild))
- stc &= ~STC.return_;
-
// much like hdrgen.stcToBuffer()
string rrs;
const isout = (stc & STC.out_) != 0;
@@ -1365,5 +1361,3 @@ extern (D) const(char)[] externallyMangledIdentifier(Declaration d)
}
return null;
}
-
-
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 35d2aba..c7e6418 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -662,7 +662,7 @@ extern (C++) final class Module : Package
return true; // already read
//printf("Module::read('%s') file '%s'\n", toChars(), srcfile.toChars());
- if (auto result = FileManager.fileManager.lookup(srcfile))
+ if (auto result = global.fileManager.lookup(srcfile))
{
this.src = result.data;
if (global.params.emitMakeDeps)
diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index aa30b5d..c3a1d05 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/dmd/dscope.d
@@ -708,6 +708,31 @@ struct Scope
return null;
}
+ /********************************************
+ * Find the lexically enclosing function (if any).
+ *
+ * This function skips through generated FuncDeclarations,
+ * e.g. rewritten foreach bodies.
+ *
+ * Returns: the function or null
+ */
+ inout(FuncDeclaration) getEnclosingFunction() inout
+ {
+ if (!this.func)
+ return null;
+
+ auto fd = cast(FuncDeclaration) this.func;
+
+ // Look through foreach bodies rewritten as delegates
+ while (fd.fes)
+ {
+ assert(fd.fes.func);
+ fd = fd.fes.func;
+ }
+
+ return cast(inout(FuncDeclaration)) fd;
+ }
+
/*******************************************
* For TemplateDeclarations, we need to remember the Scope
* where it was declared. So mark the Scope as not
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index 9e50bd5..cb6c278 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -190,7 +190,7 @@ struct Visibility
enum PASS : ubyte
{
- init, // initial state
+ initial, // initial state
semantic, // semantic() started
semanticdone, // semantic() done
semantic2, // semantic2() started
@@ -249,7 +249,7 @@ extern (C++) class Dsymbol : ASTNode
Scope* _scope; // !=null means context to use for semantic()
const(char)* prettystring; // cached value of toPrettyChars()
bool errors; // this symbol failed to pass semantic()
- PASS semanticRun = PASS.init;
+ PASS semanticRun = PASS.initial;
ushort localNum; /// perturb mangled name to avoid collisions with those in FuncDeclaration.localsymtab
DeprecatedDeclaration depdecl; // customized deprecation message
@@ -621,7 +621,7 @@ extern (C++) class Dsymbol : ASTNode
static bool has2This(Dsymbol s)
{
if (auto f = s.isFuncDeclaration())
- return f.isThis2;
+ return f.hasDualContext();
if (auto ad = s.isAggregateDeclaration())
return ad.vthis2 !is null;
return false;
@@ -2399,6 +2399,7 @@ Dsymbol handleTagSymbols(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
{
enum log = false;
if (log) printf("handleTagSymbols('%s') add %p existing %p\n", s.toChars(), s, s2);
+ if (log) printf(" add %s %s, existing %s %s\n", s.kind(), s.toChars(), s2.kind(), s2.toChars());
auto sd = s.isScopeDsymbol(); // new declaration
auto sd2 = s2.isScopeDsymbol(); // existing declaration
@@ -2457,6 +2458,7 @@ Dsymbol handleTagSymbols(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
sc._module.tagSymTab[cast(void*)s] = s2;
return s;
}
+ // neither s2 nor s is a tag
if (log) printf(" collision\n");
return null;
}
@@ -2483,6 +2485,7 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy
{
enum log = false;
if (log) printf("handleSymbolRedeclarations('%s')\n", s.toChars());
+ if (log) printf(" add %s %s, existing %s %s\n", s.kind(), s.toChars(), s2.kind(), s2.toChars());
static Dsymbol collision()
{
@@ -2552,8 +2555,16 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy
if (fd.fbody) // fd is the definition
{
+ if (log) printf(" replace existing with new\n");
sds.symtab.update(fd); // replace fd2 in symbol table with fd
fd.overnext = fd2;
+
+ /* If fd2 is covering a tag symbol, then fd has to cover the same one
+ */
+ auto ps = cast(void*)fd2 in sc._module.tagSymTab;
+ if (ps)
+ sc._module.tagSymTab[cast(void*)fd] = *ps;
+
return fd;
}
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index aad0f2d..35500af 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -111,7 +111,7 @@ struct Visibility
*/
enum class PASS : uint8_t
{
- init, // initial state
+ initial, // initial state
semantic, // semantic() started
semanticdone, // semantic() done
semantic2, // semantic2() started
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index b31dc9d..c990636 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -231,7 +231,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
override void visit(AliasThis dsym)
{
- if (dsym.semanticRun != PASS.init)
+ if (dsym.semanticRun != PASS.initial)
return;
if (dsym._scope)
@@ -346,7 +346,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
printf("linkage = %d\n", dsym.linkage);
//if (strcmp(toChars(), "mul") == 0) assert(0);
}
- //if (semanticRun > PASS.init)
+ //if (semanticRun > PASS.initial)
// return;
//semanticRun = PSSsemantic;
@@ -417,7 +417,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}
//printf("inferring type for %s with init %s\n", dsym.toChars(), dsym._init.toChars());
dsym._init = dsym._init.inferType(sc);
- dsym.type = dsym._init.initializerToExpression().type;
+ dsym.type = dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0).type;
if (needctfe)
sc = sc.endCTFE();
@@ -527,7 +527,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
* and add those.
*/
size_t nelems = Parameter.dim(tt.arguments);
- Expression ie = (dsym._init && !dsym._init.isVoidInitializer()) ? dsym._init.initializerToExpression() : null;
+ Expression ie = (dsym._init && !dsym._init.isVoidInitializer()) ? dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0) : null;
if (ie)
ie = ie.expressionSemantic(sc);
if (nelems > 0 && ie)
@@ -987,12 +987,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (ai && tb.ty == Taarray)
e = ai.toAssocArrayLiteral();
else
- e = dsym._init.initializerToExpression();
+ e = dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0);
if (!e)
{
// Run semantic, but don't need to interpret
dsym._init = dsym._init.initializerSemantic(sc, dsym.type, INITnointerpret);
- e = dsym._init.initializerToExpression();
+ e = dsym._init.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0);
if (!e)
{
dsym.error("is not a static and cannot have static initializer");
@@ -1162,23 +1162,6 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
dsym.edtor = dsym.callScopeDtor(sc);
if (dsym.edtor)
{
- /* If dsym is a local variable, who's type is a struct with a scope destructor,
- * then make dsym scope, too.
- */
- if (global.params.useDIP1000 == FeatureState.enabled &&
- !(dsym.storage_class & (STC.parameter | STC.temp | STC.field | STC.in_ | STC.foreach_ | STC.result | STC.manifest)) &&
- !dsym.isDataseg() &&
- !dsym.doNotInferScope &&
- dsym.type.hasPointers())
- {
- auto tv = dsym.type.baseElemOf();
- if (tv.ty == Tstruct &&
- tv.isTypeStruct().sym.dtor.storage_class & STC.scope_)
- {
- dsym.storage_class |= STC.scope_;
- }
- }
-
if (sc.func && dsym.storage_class & (STC.static_ | STC.gshared))
dsym.edtor = dsym.edtor.expressionSemantic(sc._module._scope);
else
@@ -1256,7 +1239,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
override void visit(Import imp)
{
//printf("Import::semantic('%s') %s\n", toPrettyChars(), id.toChars());
- if (imp.semanticRun > PASS.init)
+ if (imp.semanticRun > PASS.initial)
return;
if (imp._scope)
@@ -1433,7 +1416,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
void attribSemantic(AttribDeclaration ad)
{
- if (ad.semanticRun != PASS.init)
+ if (ad.semanticRun != PASS.initial)
return;
ad.semanticRun = PASS.semantic;
Dsymbols* d = ad.include(sc);
@@ -1776,7 +1759,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}
else if (auto f = s.isFuncDeclaration())
{
- f.isCrtCtorDtor |= isCtor ? 1 : 2;
+ f.flags |= isCtor ? FUNCFLAG.CRTCtor : FUNCFLAG.CRTDtor;
return 1;
}
else
@@ -1990,7 +1973,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
override void visit(Module m)
{
- if (m.semanticRun != PASS.init)
+ if (m.semanticRun != PASS.initial)
return;
//printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
m.semanticRun = PASS.semantic;
@@ -2099,7 +2082,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
deferDsymbolSemantic(ed, scx);
Module.dprogress = dprogress_save;
//printf("\tdeferring %s\n", toChars());
- ed.semanticRun = PASS.init;
+ ed.semanticRun = PASS.initial;
return;
}
else
@@ -2503,7 +2486,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
printf("sc.stc = %llx\n", sc.stc);
printf("sc.module = %s\n", sc._module.toChars());
}
- if (tempdecl.semanticRun != PASS.init)
+ if (tempdecl.semanticRun != PASS.initial)
return; // semantic() already run
if (tempdecl._scope)
@@ -2648,11 +2631,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
printf("+TemplateMixin.dsymbolSemantic('%s', this=%p)\n", tm.toChars(), tm);
fflush(stdout);
}
- if (tm.semanticRun != PASS.init)
+ if (tm.semanticRun != PASS.initial)
{
// When a class/struct contains mixin members, and is done over
// because of forward references, never reach here so semanticRun
- // has been reset to PASS.init.
+ // has been reset to PASS.initial.
static if (LOG)
{
printf("\tsemantic done\n");
@@ -2678,7 +2661,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
*/
if (!tm.findTempDecl(sc) || !tm.semanticTiargs(sc) || !tm.findBestMatch(sc, null))
{
- if (tm.semanticRun == PASS.init) // forward reference had occurred
+ if (tm.semanticRun == PASS.initial) // forward reference had occurred
{
//printf("forward reference - deferring\n");
return deferDsymbolSemantic(tm, scx);
@@ -2865,7 +2848,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
override void visit(Nspace ns)
{
- if (ns.semanticRun != PASS.init)
+ if (ns.semanticRun != PASS.initial)
return;
static if (LOG)
{
@@ -2989,7 +2972,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
printf("type: %p, %s\n", funcdecl.type, funcdecl.type.toChars());
}
- if (funcdecl.semanticRun != PASS.init && funcdecl.isFuncLiteralDeclaration())
+ if (funcdecl.semanticRun != PASS.initial && funcdecl.isFuncLiteralDeclaration())
{
/* Member functions that have return types that are
* forward references can have semantic() run more than
@@ -3023,7 +3006,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
AggregateDeclaration ad = funcdecl.isThis();
// Don't nest structs b/c of generated methods which should not access the outer scopes.
// https://issues.dlang.org/show_bug.cgi?id=16627
- if (ad && !funcdecl.generated)
+ if (ad && !funcdecl.isGenerated())
{
funcdecl.storage_class |= ad.storage_class & (STC.TYPECTOR | STC.synchronized_);
ad.makeNested();
@@ -3061,12 +3044,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
funcdecl.inlining = pragmadecl.evalPragmaInline(sc);
// check pragma(crt_constructor)
- if (funcdecl.isCrtCtorDtor)
+ if (funcdecl.flags & (FUNCFLAG.CRTCtor | FUNCFLAG.CRTDtor))
{
if (funcdecl.linkage != LINK.c)
{
funcdecl.error("must be `extern(C)` for `pragma(%s)`",
- funcdecl.isCrtCtorDtor == 1 ? "crt_constructor".ptr : "crt_destructor".ptr);
+ (funcdecl.flags & FUNCFLAG.CRTCtor) ? "crt_constructor".ptr : "crt_destructor".ptr);
}
}
@@ -3293,7 +3276,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (sc.scopesym && sc.scopesym.isAggregateDeclaration())
funcdecl.error("`static` member has no `this` to which `return` can apply");
else
- error(funcdecl.loc, "Top-level function `%s` has no `this` to which `return` can apply", funcdecl.toChars());
+ error(funcdecl.loc, "top-level function `%s` has no `this` to which `return` can apply", funcdecl.toChars());
}
if (funcdecl.isAbstract() && !funcdecl.isVirtual())
@@ -3524,7 +3507,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
else
{
//printf("\tintroducing function %s\n", funcdecl.toChars());
- funcdecl.introducing = 1;
+ funcdecl.flags |= FUNCFLAG.introducing;
if (cd.classKind == ClassKind.cpp && target.cpp.reverseOverloads)
{
/* Overloaded functions with same name are grouped and in reverse order.
@@ -3916,8 +3899,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}
}
- if (funcdecl.isMain())
- funcdecl.checkDmain(); // Check main() parameters and return type
+ funcdecl.checkMain(); // Check main() parameters and return type
/* Purity and safety can be inferred for some functions by examining
* the function body.
@@ -4525,7 +4507,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (sd.errors)
sd.type = Type.terror;
- if (sd.semanticRun == PASS.init)
+ if (sd.semanticRun == PASS.initial)
sd.type = sd.type.addSTC(sc.stc | sd.storage_class);
sd.type = sd.type.typeSemantic(sd.loc, sc);
if (auto ts = sd.type.isTypeStruct())
@@ -4539,7 +4521,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// Ungag errors when not speculative
Ungag ungag = sd.ungagSpeculative();
- if (sd.semanticRun == PASS.init)
+ if (sd.semanticRun == PASS.initial)
{
sd.visibility = sc.visibility;
@@ -4747,7 +4729,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (cldec.errors)
cldec.type = Type.terror;
- if (cldec.semanticRun == PASS.init)
+ if (cldec.semanticRun == PASS.initial)
cldec.type = cldec.type.addSTC(sc.stc | cldec.storage_class);
cldec.type = cldec.type.typeSemantic(cldec.loc, sc);
if (auto tc = cldec.type.isTypeClass())
@@ -4761,7 +4743,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// Ungag errors when not speculative
Ungag ungag = cldec.ungagSpeculative();
- if (cldec.semanticRun == PASS.init)
+ if (cldec.semanticRun == PASS.initial)
{
cldec.visibility = sc.visibility;
@@ -5259,7 +5241,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
auto ctor = new CtorDeclaration(cldec.loc, Loc.initial, 0, tf);
ctor.storage_class |= STC.inference;
- ctor.generated = true;
+ ctor.flags |= FUNCFLAG.generated;
ctor.fbody = new CompoundStatement(Loc.initial, new Statements());
cldec.members.push(ctor);
@@ -5416,7 +5398,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// Ungag errors when not speculative
Ungag ungag = idec.ungagSpeculative();
- if (idec.semanticRun == PASS.init)
+ if (idec.semanticRun == PASS.initial)
{
idec.visibility = sc.visibility;
@@ -5750,7 +5732,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, Expressions*
}
return;
}
- if (tempinst.semanticRun != PASS.init)
+ if (tempinst.semanticRun != PASS.initial)
{
static if (LOG)
{
@@ -5761,7 +5743,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, Expressions*
global.gag = 0;
tempinst.error(tempinst.loc, "recursive template expansion");
if (tempinst.gagged)
- tempinst.semanticRun = PASS.init;
+ tempinst.semanticRun = PASS.initial;
else
tempinst.inst = tempinst;
tempinst.errors = true;
@@ -5800,7 +5782,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, Expressions*
{
// https://issues.dlang.org/show_bug.cgi?id=13220
// Roll back status for later semantic re-running
- tempinst.semanticRun = PASS.init;
+ tempinst.semanticRun = PASS.initial;
}
else
tempinst.inst = tempinst;
@@ -6034,7 +6016,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, Expressions*
// Create our own scope for the template parameters
Scope* _scope = tempdecl._scope;
- if (tempdecl.semanticRun == PASS.init)
+ if (tempdecl.semanticRun == PASS.initial)
{
tempinst.error("template instantiation `%s` forward references template declaration `%s`", tempinst.toChars(), tempdecl.toChars());
return;
@@ -6332,7 +6314,7 @@ Laftersemantic:
target_symbol_list.remove(target_symbol_list_idx);
tempinst.memberOf = null; // no longer a member
}
- tempinst.semanticRun = PASS.init;
+ tempinst.semanticRun = PASS.initial;
tempinst.inst = null;
tempinst.symtab = null;
}
@@ -6495,10 +6477,10 @@ void aliasSemantic(AliasDeclaration ds, Scope* sc)
// Ungag errors when not instantiated DeclDefs scope alias
auto ungag = Ungag(global.gag);
- //printf("%s parent = %s, gag = %d, instantiated = %d\n", toChars(), parent, global.gag, isInstantiated());
- if (ds.parent && global.gag && !ds.isInstantiated() && !ds.toParent2().isFuncDeclaration())
+ //printf("%s parent = %s, gag = %d, instantiated = %d\n", ds.toChars(), ds.parent.toChars(), global.gag, ds.isInstantiated() !is null);
+ if (ds.parent && global.gag && !ds.isInstantiated() && !ds.toParent2().isFuncDeclaration() && (sc.minst || sc.tinst))
{
- //printf("%s type = %s\n", toPrettyChars(), type.toChars());
+ //printf("%s type = %s\n", ds.toPrettyChars(), ds.type.toChars());
global.gag = 0;
}
@@ -6572,13 +6554,13 @@ void aliasSemantic(AliasDeclaration ds, Scope* sc)
}
if (s) // it's a symbolic alias
{
- //printf("alias %s resolved to %s %s\n", toChars(), s.kind(), s.toChars());
+ //printf("alias %s resolved to %s %s\n", ds.toChars(), s.kind(), s.toChars());
ds.type = null;
ds.aliassym = s;
}
else // it's a type alias
{
- //printf("alias %s resolved to type %s\n", toChars(), type.toChars());
+ //printf("alias %s resolved to type %s\n", ds.toChars(), ds.type.toChars());
ds.type = ds.type.typeSemantic(ds.loc, sc);
ds.aliassym = null;
}
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index 366ed60..a5ec63c 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -1173,7 +1173,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
fd = new FuncDeclaration(fd.loc, fd.endloc, fd.ident, fd.storage_class, tf);
fd.parent = ti;
- fd.inferRetType = true;
+ fd.flags |= FUNCFLAG.inferRetType;
// Shouldn't run semantic on default arguments and return type.
foreach (ref param; *tf.parameterList.parameters)
@@ -2827,13 +2827,13 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
if (!sc)
sc = td._scope; // workaround for Type.aliasthisOf
- if (td.semanticRun == PASS.init && td._scope)
+ if (td.semanticRun == PASS.initial && td._scope)
{
// Try to fix forward reference. Ungag errors while doing so.
Ungag ungag = td.ungagSpeculative();
td.dsymbolSemantic(td._scope);
}
- if (td.semanticRun == PASS.init)
+ if (td.semanticRun == PASS.initial)
{
.error(loc, "forward reference to template `%s`", td.toChars());
Lerror:
@@ -2851,7 +2851,7 @@ void functionResolve(ref MatchAccumulator m, Dsymbol dstart, Loc loc, Scope* sc,
tiargs = new Objects();
auto ti = new TemplateInstance(loc, td, tiargs);
Objects dedtypes = Objects(td.parameters.dim);
- assert(td.semanticRun != PASS.init);
+ assert(td.semanticRun != PASS.initial);
MATCH mta = td.matchWithInstance(sc, ti, &dedtypes, fargs, 0);
//printf("matchWithInstance = %d\n", mta);
if (mta == MATCH.nomatch || mta < ta_last) // no match or less match
@@ -6425,7 +6425,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
if (!td)
return 0;
- if (td.semanticRun == PASS.init)
+ if (td.semanticRun == PASS.initial)
{
if (td._scope)
{
@@ -6433,7 +6433,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
Ungag ungag = td.ungagSpeculative();
td.dsymbolSemantic(td._scope);
}
- if (td.semanticRun == PASS.init)
+ if (td.semanticRun == PASS.initial)
{
error("`%s` forward references template declaration `%s`",
toChars(), td.toChars());
@@ -6786,7 +6786,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
(*tiargs)[j] = sa;
TemplateDeclaration td = sa.isTemplateDeclaration();
- if (td && td.semanticRun == PASS.init && td.literal)
+ if (td && td.semanticRun == PASS.initial && td.literal)
{
td.dsymbolSemantic(sc);
}
@@ -6915,7 +6915,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
dedtypes.setDim(td.parameters.dim);
dedtypes.zero();
- assert(td.semanticRun != PASS.init);
+ assert(td.semanticRun != PASS.initial);
MATCH m = td.matchWithInstance(sc, this, &dedtypes, fargs, 0);
//printf("matchWithInstance = %d\n", m);
@@ -7093,7 +7093,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
extern (D) final bool needsTypeInference(Scope* sc, int flag = 0)
{
//printf("TemplateInstance.needsTypeInference() %s\n", toChars());
- if (semanticRun != PASS.init)
+ if (semanticRun != PASS.initial)
return false;
uint olderrs = global.errors;
@@ -7174,7 +7174,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
*/
dedtypes.setDim(td.parameters.dim);
dedtypes.zero();
- if (td.semanticRun == PASS.init)
+ if (td.semanticRun == PASS.initial)
{
if (td._scope)
{
@@ -7182,7 +7182,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
Ungag ungag = td.ungagSpeculative();
td.dsymbolSemantic(td._scope);
}
- if (td.semanticRun == PASS.init)
+ if (td.semanticRun == PASS.initial)
{
error("`%s` forward references template declaration `%s`", toChars(), td.toChars());
return 1;
@@ -7740,13 +7740,13 @@ extern (C++) final class TemplateMixin : TemplateInstance
if (!td)
return 0;
- if (td.semanticRun == PASS.init)
+ if (td.semanticRun == PASS.initial)
{
if (td._scope)
td.dsymbolSemantic(td._scope);
else
{
- semanticRun = PASS.init;
+ semanticRun = PASS.initial;
return 1;
}
}
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index 46982e3..41fb82b 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -445,6 +445,9 @@ public:
*/
private void writeIdentifier(const AST.Dsymbol s, const bool canFix = false)
{
+ if (const mn = getMangleOverride(s))
+ return buf.writestring(mn);
+
writeIdentifier(s.ident, s.loc, s.kind(), canFix);
}
@@ -719,15 +722,20 @@ public:
visited[cast(void*)fd] = true;
// silently ignore non-user-defined destructors
- if (fd.generated && fd.isDtorDeclaration())
+ if (fd.isGenerated && fd.isDtorDeclaration())
return;
// Note that tf might be null for templated (member) functions
auto tf = cast(AST.TypeFunction)fd.type;
- if ((tf && tf.linkage != LINK.c && tf.linkage != LINK.cpp) || (!tf && fd.isPostBlitDeclaration()))
+ if ((tf && (tf.linkage != LINK.c || adparent) && tf.linkage != LINK.cpp) || (!tf && fd.isPostBlitDeclaration()))
{
ignored("function %s because of linkage", fd.toPrettyChars());
- return checkVirtualFunction(fd);
+ return checkFunctionNeedsPlaceholder(fd);
+ }
+ if (fd.mangleOverride && tf && tf.linkage != LINK.c)
+ {
+ ignored("function %s because C++ doesn't support explicit mangling", fd.toPrettyChars());
+ return checkFunctionNeedsPlaceholder(fd);
}
if (!adparent && !fd.fbody)
{
@@ -742,7 +750,7 @@ public:
if (tf && !isSupportedType(tf.next))
{
ignored("function %s because its return type cannot be mapped to C++", fd.toPrettyChars());
- return checkVirtualFunction(fd);
+ return checkFunctionNeedsPlaceholder(fd);
}
if (tf) foreach (i, fparam; tf.parameterList)
{
@@ -750,7 +758,7 @@ public:
{
ignored("function %s because one of its parameters has type `%s` which cannot be mapped to C++",
fd.toPrettyChars(), fparam.type.toChars());
- return checkVirtualFunction(fd);
+ return checkFunctionNeedsPlaceholder(fd);
}
}
@@ -822,13 +830,19 @@ public:
}
- /// Checks whether `fd` is a virtual function and emits a dummy declaration
- /// if required to ensure proper vtable layout
- private void checkVirtualFunction(AST.FuncDeclaration fd)
+ /++
+ + Checks whether `fd` is a function that requires a dummy declaration
+ + instead of simply emitting the declaration (because it would cause
+ + ABI / behaviour issues). This includes:
+ +
+ + - virtual functions to ensure proper vtable layout
+ + - destructors that would break RAII
+ +/
+ private void checkFunctionNeedsPlaceholder(AST.FuncDeclaration fd)
{
// Omit redundant declarations - the slot was already
// reserved in the base class
- if (fd.isVirtual() && fd.introducing)
+ if (fd.isVirtual() && fd.isIntroducing())
{
// Hide placeholders because they are not ABI compatible
writeProtection(AST.Visibility.Kind.private_);
@@ -837,6 +851,15 @@ public:
buf.printf("virtual void __vtable_slot_%u();", counter++);
buf.writenl();
}
+ else if (fd.isDtorDeclaration())
+ {
+ // Create inaccessible dtor to prevent code from keeping instances that
+ // need to be destroyed on the C++ side (but cannot call the dtor)
+ writeProtection(AST.Visibility.Kind.private_);
+ buf.writeByte('~');
+ buf.writestring(adparent.ident.toString());
+ buf.writestringln("();");
+ }
}
override void visit(AST.UnitTestDeclaration utd)
@@ -948,6 +971,11 @@ public:
ignored("variable %s because of linkage", vd.toPrettyChars());
return;
}
+ if (vd.mangleOverride && vd.linkage != LINK.c)
+ {
+ ignored("variable %s because C++ doesn't support explicit mangling", vd.toPrettyChars());
+ return;
+ }
if (!isSupportedType(type))
{
ignored("variable %s because its type cannot be mapped to C++", vd.toPrettyChars());
@@ -1073,7 +1101,7 @@ public:
auto fd = ad.aliassym.isFuncDeclaration();
- if (fd && (fd.generated || fd.isDtorDeclaration()))
+ if (fd && (fd.isGenerated() || fd.isDtorDeclaration()))
{
// Ignore. It's taken care of while visiting FuncDeclaration
return;
@@ -1106,7 +1134,7 @@ public:
// Print prefix of the base class if this function originates from a superclass
// because alias might be resolved through multiple classes, e.g.
// e.g. for alias visit = typeof(super).visit in the visitors
- if (!fd.introducing)
+ if (!fd.isIntroducing())
printPrefix(ad.toParent().isClassDeclaration().baseClass);
else
printPrefix(pd);
@@ -1655,7 +1683,16 @@ public:
scope(exit) printf("[typeToBuffer(AST.Type, AST.Dsymbol) exit] %s sym %s\n", t.toChars(), s.toChars());
}
- this.ident = s.ident;
+ // The context pointer (represented as `ThisDeclaration`) is named
+ // `this` but accessible via `outer`
+ if (auto td = s.isThisDeclaration())
+ {
+ import dmd.id;
+ this.ident = Id.outer;
+ }
+ else
+ this.ident = s.ident;
+
auto type = origType !is null ? origType : t;
AST.Dsymbol customLength;
@@ -1702,7 +1739,12 @@ public:
if (this.ident)
{
buf.writeByte(' ');
- writeIdentifier(s, canFixup);
+ // Custom identifier doesn't need further checks
+ if (this.ident !is s.ident)
+ buf.writestring(this.ident.toString());
+ else
+ writeIdentifier(s, canFixup);
+
}
this.ident = null;
@@ -2922,6 +2964,10 @@ public:
scope(exit) printf("[writeFullName exit] %s\n", sym.toPrettyChars());
}
+ // Explicit `pragma(mangle, "<some string>` overrides the declared name
+ if (auto mn = getMangleOverride(sym))
+ return buf.writestring(mn);
+
/// Checks whether `sym` is nested in `par` and hence doesn't need the FQN
static bool isNestedIn(AST.Dsymbol sym, AST.Dsymbol par)
{
@@ -2970,6 +3016,15 @@ public:
else
buf.writestring(sym.ident.toString());
}
+
+ /// Returns: Explicit mangling for `sym` if present
+ extern(D) static const(char)[] getMangleOverride(const AST.Dsymbol sym)
+ {
+ if (auto decl = sym.isDeclaration())
+ return decl.mangleOverride;
+
+ return null;
+ }
}
/// Namespace for identifiers used to represent special enums in C++
@@ -3037,7 +3092,7 @@ void hashEndIf(ref OutBuffer buf)
/// Writes `#define <content>` into the supplied buffer
void hashDefine(ref OutBuffer buf, string content)
{
- buf.writestring("# define ");
+ buf.writestring("#define ");
buf.writestringln(content);
}
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index e9dcdc0..4196c05 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -692,9 +692,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
// If va's lifetime encloses v's, then error
if (va && !va.isDataseg() &&
- (va.enclosesLifetimeOf(v) && !(v.storage_class & STC.temp) ||
- vaIsRef ||
- va.isReference() && !(v.storage_class & (STC.parameter | STC.temp))) &&
+ ((va.enclosesLifetimeOf(v) && !(v.storage_class & STC.temp)) || vaIsRef) &&
fd.setUnsafe())
{
if (!gag)
@@ -793,7 +791,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
// If va's lifetime encloses v's, then error
if (va &&
- (va.enclosesLifetimeOf(v) || (va.isRef() && !(va.storage_class & STC.temp)) || va.isDataseg()) &&
+ (va.enclosesLifetimeOf(v) || (va.isReference() && !(va.storage_class & STC.temp)) || va.isDataseg()) &&
fd.setUnsafe())
{
if (!gag)
@@ -1284,27 +1282,24 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
{
if (!gag)
{
- const(char)* msg, supplemental;
- if (v.storage_class & STC.parameter &&
- (v.type.hasPointers() || v.storage_class & STC.ref_))
- {
- msg = "returning `%s` escapes a reference to parameter `%s`";
- supplemental = vsr == ScopeRef.Ref_ReturnScope
- ? "perhaps remove `scope` parameter annotation so `return` applies to `ref`"
- : v.ident is Id.This
- ? "perhaps annotate the function with `return`"
- : "perhaps annotate the parameter with `return`";
- }
- else
+ const(char)* varKind = v.isParameter() ? "parameter" : "local variable";
+ previewErrorFunc(sc.isDeprecated(), featureState)(e.loc,
+ "returning `%s` escapes a reference to %s `%s`", e.toChars(), varKind, v.toChars());
+
+ if (v.isParameter() && v.isReference())
{
- msg = "returning `%s` escapes a reference to local variable `%s`";
- if (v.ident is Id.This)
- supplemental = "perhaps annotate the function with `return`";
+ if (v.storage_class & STC.returnScope)
+ {
+ previewSupplementalFunc(sc.isDeprecated(), featureState)(v.loc,
+ "perhaps change the `return scope` into `scope return`");
+ }
+ else
+ {
+ const(char)* annotateKind = (v.ident is Id.This) ? "function" : "parameter";
+ previewSupplementalFunc(sc.isDeprecated(), featureState)(v.loc,
+ "perhaps annotate the %s with `return`", annotateKind);
+ }
}
-
- previewErrorFunc(sc.isDeprecated(), featureState)(e.loc, msg, e.toChars(), v.toChars());
- if (supplemental)
- previewSupplementalFunc(sc.isDeprecated(), featureState)(e.loc, supplemental);
}
result = true;
}
@@ -1897,7 +1892,7 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false)
override void visit(ThisExp e)
{
- if (e.var && e.var.toParent2().isFuncDeclaration().isThis2)
+ if (e.var && e.var.toParent2().isFuncDeclaration().hasDualContext())
escapeByValue(e, er, live);
else if (e.var)
er.byref.push(e.var);
@@ -2297,3 +2292,37 @@ bool isReferenceToMutable(Parameter p, Type t)
}
return isReferenceToMutable(p.type);
}
+
+/**********************************
+* Determine if `va` has a lifetime that lasts past
+* the destruction of `v`
+* Params:
+* va = variable assigned to
+* v = variable being assigned
+* Returns:
+* true if it does
+*/
+private bool enclosesLifetimeOf(const VarDeclaration va, const VarDeclaration v) pure
+{
+ assert(va.sequenceNumber != va.sequenceNumber.init);
+ assert(v.sequenceNumber != v.sequenceNumber.init);
+ return va.sequenceNumber < v.sequenceNumber;
+}
+
+/***************************************
+ * Add variable `v` to maybes[]
+ *
+ * When a maybescope variable `v` is assigned to a maybescope variable `va`,
+ * we cannot determine if `this` is actually scope until the semantic
+ * analysis for the function is completed. Thus, we save the data
+ * until then.
+ * Params:
+ * v = an `STC.maybescope` variable that was assigned to `this`
+ */
+private void addMaybe(VarDeclaration va, VarDeclaration v)
+{
+ //printf("add %s to %s's list of dependencies\n", v.toChars(), toChars());
+ if (!va.maybes)
+ va.maybes = new VarDeclarations();
+ va.maybes.push(v);
+}
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 7abfe7f..07d885b 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -170,7 +170,7 @@ FuncDeclaration hasThis(Scope* sc)
{
return null;
}
- if (!fd.isNested() || fd.isThis() || (fd.isThis2 && fd.isMember2()))
+ if (!fd.isNested() || fd.isThis() || (fd.hasDualContext() && fd.isMember2()))
break;
Dsymbol parent = fd.parent;
@@ -187,7 +187,7 @@ FuncDeclaration hasThis(Scope* sc)
fd = parent.isFuncDeclaration();
}
- if (!fd.isThis() && !(fd.isThis2 && fd.isMember2()))
+ if (!fd.isThis() && !(fd.hasDualContext() && fd.isMember2()))
{
return null;
}
@@ -1210,7 +1210,7 @@ extern (C++) abstract class Expression : ASTNode
scope bool function(DtorDeclaration) check, const string checkName
) {
auto dd = f.isDtorDeclaration();
- if (!dd || !dd.generated)
+ if (!dd || !dd.isGenerated())
return;
// DtorDeclaration without parents should fail at an earlier stage
@@ -1227,7 +1227,7 @@ extern (C++) abstract class Expression : ASTNode
}
dd.loc.errorSupplemental("%s`%s.~this` is %.*s because of the following field's destructors:",
- dd.generated ? "generated " : "".ptr,
+ dd.isGenerated() ? "generated " : "".ptr,
ad.toChars,
cast(int) checkName.length, checkName.ptr);
@@ -1258,7 +1258,7 @@ extern (C++) abstract class Expression : ASTNode
{
field.loc.errorSupplemental(" - %s %s", field.type.toChars(), field.toChars());
- if (fieldSd.dtor.generated)
+ if (fieldSd.dtor.isGenerated())
checkOverridenDtor(sc, fieldSd.dtor, check, checkName);
else
fieldSd.dtor.loc.errorSupplemental(" %.*s `%s.~this` is declared here",
@@ -1288,7 +1288,7 @@ extern (C++) abstract class Expression : ASTNode
return false; // magic variable never violates pure and safe
if (v.isImmutable())
return false; // always safe and pure to access immutables...
- if (v.isConst() && !v.isRef() && (v.isDataseg() || v.isParameter()) && v.type.implicitConvTo(v.type.immutableOf()))
+ if (v.isConst() && !v.isReference() && (v.isDataseg() || v.isParameter()) && v.type.implicitConvTo(v.type.immutableOf()))
return false; // or const global/parameter values which have no mutable indirections
if (v.storage_class & STC.manifest)
return false; // ...or manifest constants
@@ -3461,7 +3461,7 @@ extern (C++) final class ScopeExp : Expression
//assert(ti.needsTypeInference(sc));
if (ti.tempdecl &&
ti.semantictiargsdone &&
- ti.semanticRun == PASS.init)
+ ti.semanticRun == PASS.initial)
{
error("partial %s `%s` has no type", sds.kind(), toChars());
return true;
@@ -3859,7 +3859,7 @@ extern (C++) final class FuncExp : Expression
{
if (td)
return new FuncExp(loc, td.syntaxCopy(null));
- else if (fd.semanticRun == PASS.init)
+ else if (fd.semanticRun == PASS.initial)
return new FuncExp(loc, fd.syntaxCopy(null));
else // https://issues.dlang.org/show_bug.cgi?id=13481
// Prevent multiple semantic analysis of lambda body.
@@ -4950,7 +4950,7 @@ extern (C++) final class DotTemplateInstanceExp : UnaExp
// Same logic as ScopeExp.checkType()
if (ti.tempdecl &&
ti.semantictiargsdone &&
- ti.semanticRun == PASS.init)
+ ti.semanticRun == PASS.initial)
{
error("partial %s `%s` has no type", ti.kind(), toChars());
return true;
@@ -4962,7 +4962,7 @@ extern (C++) final class DotTemplateInstanceExp : UnaExp
{
if (ti.tempdecl &&
ti.semantictiargsdone &&
- ti.semanticRun == PASS.init)
+ ti.semanticRun == PASS.initial)
error("partial %s `%s` has no value", ti.kind(), toChars());
else
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 5802816..7b7c489 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -1046,7 +1046,7 @@ L1:
if (e1.op == EXP.this_)
{
FuncDeclaration f = hasThis(sc);
- if (f && f.isThis2)
+ if (f && f.hasDualContext())
{
if (f.followInstantiationContext(ad))
{
@@ -1444,13 +1444,6 @@ private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps)
Expression ex = condexp.expressionSemantic(sc);
if (ex.op == EXP.error)
e = ex;
- 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
- exps[i] = condexp.e1;
- e = condexp.e2;
- }
else
{
// Convert to common type
@@ -1723,7 +1716,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
if (sc._module)
sc._module.hasAlwaysInlines = true;
if (sc.func)
- sc.func.hasAlwaysInlines = true;
+ sc.func.flags |= FUNCFLAG.hasAlwaysInline;
}
const isCtorCall = fd && fd.needThis() && fd.isCtorDeclaration();
@@ -3743,7 +3736,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
}
- if (sd.hasRegularCtor() && nargs)
+ // https://issues.dlang.org/show_bug.cgi?id=22639
+ // If the new expression has arguments, we either should call a
+ // regular constructor of a copy constructor if the first argument
+ // is the same type as the struct
+ if (nargs && (sd.hasRegularCtor() || (sd.ctor && (*exp.arguments)[0].type.mutableOf() == sd.type.mutableOf())))
{
FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard);
if (!f || f.errors)
@@ -4201,30 +4198,27 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
Type tthis = null;
Expression e1org = exp.e1;
- if (exp.e1.op == EXP.comma)
+ if (auto ce = exp.e1.isCommaExp())
{
/* Rewrite (a,b)(args) as (a,(b(args)))
*/
- auto ce = cast(CommaExp)exp.e1;
exp.e1 = ce.e2;
ce.e2 = exp;
result = ce.expressionSemantic(sc);
return;
}
- if (exp.e1.op == EXP.delegate_)
+ if (DelegateExp de = exp.e1.isDelegateExp())
{
- 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 == EXP.function_)
+ if (FuncExp fe = exp.e1.isFuncExp())
{
if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments))
return setError();
// 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 == EXP.error)
{
@@ -4252,9 +4246,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* This recognizes:
* foo!(tiargs)(funcargs)
*/
- if (exp.e1.op == EXP.scope_)
+ if (ScopeExp se = exp.e1.isScopeExp())
{
- ScopeExp se = cast(ScopeExp)exp.e1;
TemplateInstance ti = se.sds.isTemplateInstance();
if (ti)
{
@@ -4300,9 +4293,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* expr.foo!(tiargs)(funcargs)
*/
Ldotti:
- if (exp.e1.op == EXP.dotTemplateInstance)
+ if (DotTemplateInstanceExp se = exp.e1.isDotTemplateInstanceExp())
{
- DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)exp.e1;
TemplateInstance ti = se.ti;
{
/* Attempt to instantiate ti. If that works, go with it.
@@ -4347,9 +4339,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
else
{
- if (exp.e1.op == EXP.dotIdentifier)
+ if (DotIdExp die = exp.e1.isDotIdExp())
{
- DotIdExp die = cast(DotIdExp)exp.e1;
exp.e1 = die.expressionSemantic(sc);
/* Look for e1 having been rewritten to expr.opDispatch!(string)
* We handle such earlier, so go back.
@@ -4380,9 +4371,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
/* Look for e1 being a lazy parameter
*/
- if (exp.e1.op == EXP.variable)
+ if (VarExp ve = exp.e1.isVarExp())
{
- VarExp ve = cast(VarExp)exp.e1;
if (ve.var.storage_class & STC.lazy_)
{
// lazy parameters can be called without violating purity and safety
@@ -4404,10 +4394,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.e1 = new VarExp(se.loc, se.var, true);
exp.e1 = exp.e1.expressionSemantic(sc);
}
- else if (exp.e1.op == EXP.dot)
+ else if (DotExp de = exp.e1.isDotExp())
{
- DotExp de = cast(DotExp)exp.e1;
-
if (de.e2.op == EXP.overloadSet)
{
ethis = de.e1;
@@ -4490,7 +4478,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (sd.ctor)
{
auto ctor = sd.ctor.isCtorDeclaration();
- if (ctor && ctor.isCpCtor && ctor.generated)
+ if (ctor && ctor.isCpCtor && ctor.isGenerated())
sd.ctor = null;
}
@@ -4504,7 +4492,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
If all constructors are copy constructors, then
try default construction.
*/
- if (!sd.hasRegularCtor)
+ if (!sd.hasRegularCtor &&
+ // https://issues.dlang.org/show_bug.cgi?id=22639
+ // we might still have a copy constructor that could be called
+ (*exp.arguments)[0].type.mutableOf != sd.type.mutableOf())
goto Lx;
auto sle = new StructLiteralExp(exp.loc, sd, null, exp.e1.type);
@@ -4850,10 +4841,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
}
}
- else if (exp.e1.op == EXP.overloadSet)
+ else if (auto oe = exp.e1.isOverExp())
{
- auto os = (cast(OverExp)exp.e1).vars;
- exp.f = resolveOverloadSet(exp.loc, sc, os, tiargs, tthis, exp.arguments);
+ exp.f = resolveOverloadSet(exp.loc, sc, oe.vars, tiargs, tthis, exp.arguments);
if (!exp.f)
return setError();
if (ethis)
@@ -4877,11 +4867,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
const(char)* p;
Dsymbol s;
exp.f = null;
- if (exp.e1.op == EXP.function_)
+ if (auto fe = exp.e1.isFuncExp())
{
// function literal that direct called is always inferred.
- assert((cast(FuncExp)exp.e1).fd);
- exp.f = (cast(FuncExp)exp.e1).fd;
+ assert(fe.fd);
+ exp.f = fe.fd;
tf = cast(TypeFunction)exp.f.type;
p = "function literal";
}
@@ -5011,11 +5001,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
t1 = tf;
}
- else if (exp.e1.op == EXP.variable)
+ else if (VarExp ve = exp.e1.isVarExp())
{
// Do overload resolution
- VarExp ve = cast(VarExp)exp.e1;
-
exp.f = ve.var.isFuncDeclaration();
assert(exp.f);
tiargs = null;
@@ -5162,7 +5150,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
// declare dual-context container
- if (exp.f && exp.f.isThis2 && !sc.intypeof && sc.func)
+ if (exp.f && exp.f.hasDualContext() && !sc.intypeof && sc.func)
{
// check access to second `this`
if (AggregateDeclaration ad2 = exp.f.isMember2())
@@ -6042,13 +6030,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
auto fileName = FileName(name.toDString);
- if (auto fmResult = FileManager.fileManager.lookup(fileName))
+ if (auto fmResult = global.fileManager.lookup(fileName))
{
se = new StringExp(e.loc, fmResult.data);
}
else
{
- auto readResult = File.read(name);
+ auto readResult = File.read(name.toDString);
if (!readResult.success)
{
e.error("cannot read file `%s`", name);
@@ -6060,9 +6048,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
auto data = readResult.extractSlice();
se = new StringExp(e.loc, data);
- FileBuffer* fileBuffer = FileBuffer.create();
- fileBuffer.data = data;
- FileManager.fileManager.add(fileName, fileBuffer);
+ FileBuffer* fileBuffer = new FileBuffer(data);
+ global.fileManager.add(fileName, fileBuffer);
}
}
}
@@ -6200,10 +6187,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
const op = exp.e1.op;
bool isEqualsCallExpression;
- if (op == EXP.call)
+ if (const callExp = exp.e1.isCallExp())
{
- const callExp = cast(CallExp) exp.e1;
-
// https://issues.dlang.org/show_bug.cgi?id=20331
// callExp.f may be null if the assert contains a call to
// a function pointer or literal
@@ -6436,7 +6421,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
else if (t)
{
- result = new IntegerExp(exp.loc, t.alignsize, Type.tsize_t);
+ // Note similarity to getProperty() implementation of __xalignof
+ const explicitAlignment = t.alignment();
+ const naturalAlignment = t.alignsize();
+ const actualAlignment = (explicitAlignment.isDefault() ? naturalAlignment : explicitAlignment.get());
+ result = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
}
else if (s)
{
@@ -6643,7 +6632,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
if (v && (v.isDataseg() || // fix https://issues.dlang.org/show_bug.cgi?id=8238
- (!v.needThis() && v.semanticRun > PASS.init))) // fix https://issues.dlang.org/show_bug.cgi?id=17258
+ (!v.needThis() && v.semanticRun > PASS.initial))) // fix https://issues.dlang.org/show_bug.cgi?id=17258
{
// (e1, v)
checkAccess(exp.loc, sc, exp.e1, v);
@@ -6736,7 +6725,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
result = e;
// declare dual-context container
- if (f.isThis2 && !sc.intypeof && sc.func)
+ if (f.hasDualContext() && !sc.intypeof && sc.func)
{
// check access to second `this`
if (AggregateDeclaration ad2 = f.isMember2())
@@ -7311,7 +7300,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (checkNonAssignmentArrayOp(e.e1))
return setError();
- e.type = Type.tbool;
+ e.type = (sc && sc.flags & SCOPE.Cfile) ? Type.tint32 : Type.tbool;
result = e;
}
@@ -7323,7 +7312,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// 3. Removal of keyword, "delete" can be used for other identities
if (!exp.isRAII)
{
- error(exp.loc, "The `delete` keyword is obsolete. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.");
+ error(exp.loc, "the `delete` keyword is obsolete");
+ errorSupplemental(exp.loc, "use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead");
return setError();
}
@@ -7847,9 +7837,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
*/
if (VarDeclaration v = expToVariable(exp.e1))
{
- if (exp.e1.op == EXP.dotVariable)
+ if (DotVarExp dve = exp.e1.isDotVarExp())
{
- DotVarExp dve = cast(DotVarExp)exp.e1;
+
if ((dve.e1.op == EXP.this_ || dve.e1.op == EXP.super_) &&
!(v.storage_class & STC.ref_))
{
@@ -8140,10 +8130,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = exp.e2;
return;
}
- if (exp.e2.op == EXP.template_)
+ if (auto te = exp.e2.isTemplateExp())
{
- auto td = (cast(TemplateExp)exp.e2).td;
- Expression e = new DotTemplateExp(exp.loc, exp.e1, td);
+ Expression e = new DotTemplateExp(exp.loc, exp.e1, te.td);
result = e.expressionSemantic(sc);
return;
}
@@ -8182,11 +8171,15 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
e.e2 = e.e2.arrayFuncConv(sc);
e.type = e.e2.type;
+ result = e;
+
+ if (sc.flags & SCOPE.Cfile)
+ return;
+
if (e.type is Type.tvoid)
discardValue(e.e1);
- else if (!e.allowCommaExp && !e.isGenerated && !(sc.flags & SCOPE.Cfile))
+ else if (!e.allowCommaExp && !e.isGenerated)
e.error("Using the result of a comma expression is not allowed");
- result = e;
}
override void visit(IntervalExp e)
@@ -8472,6 +8465,19 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// OR it in, because it might already be set for C array indexing
exp.indexIsInBounds |= bounds.contains(getIntRange(exp.e2));
}
+ else if (sc.flags & SCOPE.Cfile && t1b.ty == Tsarray)
+ {
+ if (auto ve = exp.e1.isVarExp())
+ {
+ /* Rewrite 0-length C array ve[exp.e2] as *(ve + exp.e2)
+ */
+ auto vp = ve.castTo(sc, t1b.isTypeSArray().next.pointerTo());
+ auto e = new AddExp(exp.loc, vp, exp.e2);
+ auto pe = new PtrExp(exp.loc, e);
+ result = pe.expressionSemantic(sc).optimize(WANTvalue);
+ return;
+ }
+ }
}
}
@@ -10024,9 +10030,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
- if (exp.e1.op == EXP.slice)
+ if (SliceExp se = exp.e1.isSliceExp())
{
- SliceExp se = cast(SliceExp)exp.e1;
if (se.e1.type.toBasetype().ty == Tsarray)
{
exp.error("cannot append to static array `%s`", se.e1.type.toChars());
@@ -11270,7 +11275,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
e1x = e1x.optimize(WANTvalue);
if (e1x.toBool().hasValue(exp.op == EXP.orOr))
{
- result = IntegerExp.createBool(exp.op == EXP.orOr);
+ if (sc.flags & SCOPE.Cfile)
+ result = new IntegerExp(exp.op == EXP.orOr);
+ else
+ result = IntegerExp.createBool(exp.op == EXP.orOr);
return;
}
}
@@ -11315,7 +11323,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (e2x.type.ty == Tvoid)
exp.type = Type.tvoid;
else
- exp.type = Type.tbool;
+ exp.type = (sc && sc.flags & SCOPE.Cfile) ? Type.tint32 : Type.tbool;
exp.e1 = e1x;
exp.e2 = e2x;
@@ -11412,7 +11420,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (f1 || f2)
return setError();
- exp.type = Type.tbool;
+ exp.type = (sc && sc.flags & SCOPE.Cfile) ? Type.tint32 : Type.tbool;
// Special handling for array comparisons
Expression arrayLowering = null;
@@ -11690,7 +11698,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (f1 || f2)
return setError();
- exp.type = Type.tbool;
+ exp.type = (sc && sc.flags & SCOPE.Cfile) ? Type.tint32 : Type.tbool;
if (!isArrayComparison)
{
@@ -11825,8 +11833,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
- if (exp.econd.op == EXP.dotIdentifier)
- (cast(DotIdExp)exp.econd).noderef = true;
+ if (auto die = exp.econd.isDotIdExp())
+ die.noderef = true;
Expression ec = exp.econd.expressionSemantic(sc);
ec = resolveProperties(sc, ec);
@@ -12654,9 +12662,8 @@ Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag)
if (e.op == EXP.error)
return e;
- if (e.op == EXP.dotVariable)
+ if (DotVarExp dve = e.isDotVarExp())
{
- DotVarExp dve = cast(DotVarExp)e;
if (FuncDeclaration fd = dve.var.isFuncDeclaration())
{
if (TemplateDeclaration td = fd.findTemplateDeclRoot())
@@ -12707,9 +12714,8 @@ Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag)
}
}
- if (e.op == EXP.dotTemplateDeclaration)
+ if (DotTemplateExp dte = e.isDotTemplateExp())
{
- DotTemplateExp dte = cast(DotTemplateExp)e;
exp.e1 = dte.e1; // pull semantic() result
exp.ti.tempdecl = dte.td;
@@ -12738,10 +12744,8 @@ Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag)
return new ScopeExp(exp.loc, exp.ti)
.expressionSemantic(sc);
}
- else if (e.op == EXP.dot)
+ else if (DotExp de = e.isDotExp())
{
- DotExp de = cast(DotExp)e;
-
if (de.e2.op == EXP.overloadSet)
{
if (!exp.findTempDecl(sc) || !exp.ti.semanticTiargs(sc))
@@ -12765,9 +12769,8 @@ Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag)
.expressionSemantic(sc);
}
}
- else if (e.op == EXP.overloadSet)
+ else if (OverExp oe = e.isOverExp())
{
- OverExp oe = cast(OverExp)e;
exp.ti.tempdecl = oe.vars;
return new ScopeExp(exp.loc, exp.ti)
.expressionSemantic(sc);
@@ -13055,7 +13058,7 @@ Expression getThisSkipNestedFuncs(const ref Loc loc, Scope* sc, Dsymbol s, Aggre
{
n++;
e1 = new VarExp(loc, f.vthis);
- if (f.isThis2)
+ if (f.hasDualContext())
{
// (*__this)[i]
if (n > 1)
@@ -13355,8 +13358,8 @@ Expression toBoolean(Expression exp, Scope* sc)
default:
// Default is 'yes' - do nothing
- Expression e = exp;
- Type t = exp.type;
+ Expression e = arrayFuncConv(exp, sc);
+ Type t = e.type;
Type tb = t.toBasetype();
Type att = null;
diff --git a/gcc/d/dmd/file_manager.d b/gcc/d/dmd/file_manager.d
index 9ba3807..b86c799 100644
--- a/gcc/d/dmd/file_manager.d
+++ b/gcc/d/dmd/file_manager.d
@@ -20,10 +20,15 @@ import dmd.identifier;
enum package_d = "package." ~ mars_ext;
enum package_di = "package." ~ hdr_ext;
-struct FileManager
+final class FileManager
{
private StringTable!(FileBuffer*) files;
- private __gshared bool initialized = false;
+
+ ///
+ public this () nothrow
+ {
+ this.files._init();
+ }
nothrow:
/********************************************
@@ -143,9 +148,6 @@ nothrow:
*/
const(FileBuffer)* lookup(FileName filename)
{
- if (!initialized)
- FileManager._init();
-
const name = filename.toString;
if (auto val = files.lookup(name))
return val.value;
@@ -182,9 +184,6 @@ nothrow:
*/
const(char)[][] getLines(FileName file)
{
- if (!initialized)
- FileManager._init();
-
const(char)[][] lines;
if (const buffer = lookup(file))
{
@@ -241,29 +240,9 @@ nothrow:
*/
FileBuffer* add(FileName filename, FileBuffer* filebuffer)
{
- if (!initialized)
- FileManager._init();
-
auto val = files.insert(filename.toString, filebuffer);
return val == null ? null : val.value;
}
-
- __gshared fileManager = FileManager();
-
- // Initialize the global FileManager singleton
- private void _init()
- {
- if (!initialized)
- {
- fileManager.initialize();
- initialized = true;
- }
- }
-
- void initialize()
- {
- files._init();
- }
}
private FileBuffer readFromStdin() nothrow
diff --git a/gcc/d/dmd/foreachvar.d b/gcc/d/dmd/foreachvar.d
index b779eae..53ed62e 100644
--- a/gcc/d/dmd/foreachvar.d
+++ b/gcc/d/dmd/foreachvar.d
@@ -320,4 +320,3 @@ void foreachExpAndVar(Statement s,
visit(s);
}
-
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index afc0ebb..8d83951 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -140,7 +140,7 @@ public:
override void visit(TryFinallyStatement s)
{
DtorExpStatement des;
- if (fd.nrvo_can && s.finalbody && (des = s.finalbody.isDtorExpStatement()) !is null &&
+ if (fd.isNRVO() && s.finalbody && (des = s.finalbody.isDtorExpStatement()) !is null &&
fd.nrvo_var == des.var)
{
if (!(global.params.useExceptions && ClassDeclaration.throwable))
@@ -182,7 +182,7 @@ public:
catches.push(ctch);
Statement s2 = new TryCatchStatement(Loc.initial, s._body, catches);
- fd.eh_none = false;
+ fd.flags &= ~FUNCFLAG.noEH;
replaceCurrent(s2);
s2.accept(this);
}
@@ -205,6 +205,17 @@ enum FUNCFLAG : uint
printf = 0x200, /// is a printf-like function
scanf = 0x400, /// is a scanf-like function
noreturn = 0x800, /// the function does not return
+ NRVO = 0x1000, /// Support for named return value optimization
+ naked = 0x2000, /// The function is 'naked' (see inline ASM)
+ generated = 0x4000, /// The function is compiler generated (e.g. `opCmp`)
+ introducing = 0x8000, /// If this function introduces the overload set
+ semantic3Errors = 0x10000, /// If errors in semantic3 this function's frame ptr
+ noEH = 0x20000, /// No exception unwinding is needed
+ inferRetType = 0x40000, /// Return type is to be inferred
+ dualContext = 0x80000, /// has a dual-context 'this' parameter
+ hasAlwaysInline = 0x100000, /// Contains references to functions that must be inlined
+ CRTCtor = 0x200000, /// Has attribute pragma(crt_constructor)
+ CRTDtor = 0x400000, /// Has attribute pragma(crt_destructor)
}
/***********************************************************
@@ -268,7 +279,6 @@ extern (C++) class FuncDeclaration : Declaration
// scopes from having the same name
DsymbolTable localsymtab;
VarDeclaration vthis; /// 'this' parameter (member and nested)
- bool isThis2; /// has a dual-context 'this' parameter
VarDeclaration v_arguments; /// '_arguments' parameter
VarDeclaration v_argptr; /// '_argptr' variable
@@ -278,31 +288,21 @@ extern (C++) class FuncDeclaration : Declaration
FuncDeclaration overnext0; /// next in overload list (only used during IFTI)
Loc endloc; /// location of closing curly bracket
int vtblIndex = -1; /// for member functions, index into vtbl[]
- bool naked; /// true if naked
- bool generated; /// true if function was generated by the compiler rather than
- /// supplied by the user
- bool hasAlwaysInlines; /// contains references to functions that must be inlined
- ubyte isCrtCtorDtor; /// has attribute pragma(crt_constructor(1)/crt_destructor(2))
- /// not set before the glue layer
ILS inlineStatusStmt = ILS.uninitialized;
ILS inlineStatusExp = ILS.uninitialized;
PINLINE inlining = PINLINE.default_;
int inlineNest; /// !=0 if nested inline
- bool eh_none; /// true if no exception unwinding is needed
- bool semantic3Errors; /// true if errors in semantic3 this function's frame ptr
ForeachStatement fes; /// if foreach body, this is the foreach
BaseClass* interfaceVirtual; /// if virtual, but only appears in base interface vtbl[]
- bool introducing; /// true if 'introducing' function
/** if !=NULL, then this is the type
of the 'introducing' function
this one is overriding
*/
Type tintro;
- bool inferRetType; /// true if return type is to be inferred
StorageClass storage_class2; /// storage class for template onemember's
// Things that should really go into Scope
@@ -314,8 +314,6 @@ extern (C++) class FuncDeclaration : Declaration
/// 16 if there are multiple return statements
int hasReturnExp;
- // Support for NRVO (named return value optimization)
- bool nrvo_can = true; /// true means we can do NRVO
VarDeclaration nrvo_var; /// variable to replace with shidden
Symbol* shidden; /// hidden pointer passed to function
@@ -346,7 +344,9 @@ extern (C++) class FuncDeclaration : Declaration
FuncDeclarations *inlinedNestedCallees;
- uint flags; /// FUNCFLAG.xxxxx
+ /// Function flags: A collection of boolean packed for memory efficiency
+ /// See the `FUNCFLAG` enum
+ uint flags = FUNCFLAG.NRVO;
/**
* Data for a function declaration that is needed for the Objective-C
@@ -374,7 +374,8 @@ extern (C++) class FuncDeclaration : Declaration
/* The type given for "infer the return type" is a TypeFunction with
* NULL for the return type.
*/
- inferRetType = (type && type.nextOf() is null);
+ if (type && type.nextOf() is null)
+ this.flags |= FUNCFLAG.inferRetType;
}
static FuncDeclaration create(const ref Loc loc, const ref Loc endloc, Identifier id, StorageClass storage_class, Type type, bool noreturn = false)
@@ -480,7 +481,7 @@ extern (C++) class FuncDeclaration : Declaration
return false;
}
- return !errors && !semantic3Errors;
+ return !errors && !this.hasSemantic3Errors();
}
/****************************************************
@@ -515,9 +516,11 @@ extern (C++) class FuncDeclaration : Declaration
*/
extern (D) final void declareThis(Scope* sc)
{
- isThis2 = toParent2() != toParentLocal();
+ const bool dualCtx = (toParent2() != toParentLocal());
+ if (dualCtx)
+ this.flags |= FUNCFLAG.dualContext;
auto ad = isThis();
- if (!isThis2 && !ad && !isNested())
+ if (!dualCtx && !ad && !isNested())
{
vthis = null;
objc.selectorParameter = null;
@@ -529,16 +532,16 @@ extern (C++) class FuncDeclaration : Declaration
return t.addMod(type.mod).addStorageClass(storage_class);
}
- if (isThis2 || isNested())
+ if (dualCtx || isNested())
{
/* The 'this' for a nested function is the link to the
* enclosing function's stack frame.
* Note that nested functions and member functions are disjoint.
*/
- Type tthis = addModStc(isThis2 ?
+ Type tthis = addModStc(dualCtx ?
Type.tvoidptr.sarrayOf(2).pointerTo() :
Type.tvoid.pointerTo());
- vthis = new VarDeclaration(loc, tthis, isThis2 ? Id.this2 : Id.capture, null);
+ vthis = new VarDeclaration(loc, tthis, dualCtx ? Id.this2 : Id.capture, null);
vthis.storage_class |= STC.parameter | STC.nodtor;
}
else if (ad)
@@ -549,22 +552,6 @@ extern (C++) class FuncDeclaration : Declaration
if (thandle.ty == Tstruct)
{
vthis.storage_class |= STC.ref_;
-
- /* if member function is marked 'inout', then 'this' is 'return ref'
- * The same thing is done for `ref inout` parameters in TypeFunction's semantic routine.
- */
- if (auto tf = type.isTypeFunction())
- {
- /* This feature was a mistake, but existing code relies on it.
- * So only disable it in @safe code and DIP1000 code
- */
- if (!(global.params.useDIP1000 == FeatureState.enabled &&
- tf.trust == TRUST.safe))
- {
- if (tf.isInOutQual())
- vthis.storage_class |= STC.return_;
- }
- }
}
}
@@ -574,19 +561,8 @@ extern (C++) class FuncDeclaration : Declaration
vthis.storage_class |= STC.return_;
if (tf.isScopeQual)
vthis.storage_class |= STC.scope_;
-
- /* Add STC.returnScope like typesem.d does for TypeFunction parameters,
- * at least it should be the same. At the moment, we'll just
- * do existing practice. But we should examine how TypeFunction does
- * it, for consistency.
- */
- if (global.params.useDIP1000 != FeatureState.enabled &&
- !tf.isref && isRefReturnScope(vthis.storage_class))
- {
- /* if `ref return scope`, evaluate to `ref` `return scope`
- */
+ if (tf.isreturnscope)
vthis.storage_class |= STC.returnScope;
- }
}
if (flags & FUNCFLAG.inferScope && !(vthis.storage_class & STC.scope_))
vthis.storage_class |= STC.maybescope;
@@ -1369,7 +1345,7 @@ extern (C++) class FuncDeclaration : Declaration
if (!tf.isnogc)
flags |= FUNCFLAG.nogcInprocess;
- if (!isVirtual() || introducing)
+ if (!isVirtual() || this.isIntroducing())
flags |= FUNCFLAG.returnInprocess;
// Initialize for inferring STC.scope_
@@ -1482,6 +1458,73 @@ extern (C++) class FuncDeclaration : Declaration
return !(flags & FUNCFLAG.nogcInprocess) && isNogc();
}
+ final bool isNRVO() const scope @safe pure nothrow @nogc
+ {
+ return !!(this.flags & FUNCFLAG.NRVO);
+ }
+
+ final void isNRVO(bool v) pure nothrow @safe @nogc
+ {
+ if (v) this.flags |= FUNCFLAG.NRVO;
+ else this.flags &= ~FUNCFLAG.NRVO;
+ }
+
+ final bool isNaked() const scope @safe pure nothrow @nogc
+ {
+ return !!(this.flags & FUNCFLAG.naked);
+ }
+
+ final bool isGenerated() const scope @safe pure nothrow @nogc
+ {
+ return !!(this.flags & FUNCFLAG.generated);
+ }
+
+ final void isGenerated(bool v) pure nothrow @safe @nogc
+ {
+ if (v) this.flags |= FUNCFLAG.generated;
+ else this.flags &= ~FUNCFLAG.generated;
+ }
+
+ final bool isIntroducing() const scope @safe pure nothrow @nogc
+ {
+ return !!(this.flags & FUNCFLAG.introducing);
+ }
+
+ final bool hasSemantic3Errors() const scope @safe pure nothrow @nogc
+ {
+ return !!(this.flags & FUNCFLAG.semantic3Errors);
+ }
+
+ final bool hasNoEH() const scope @safe pure nothrow @nogc
+ {
+ return !!(this.flags & FUNCFLAG.noEH);
+ }
+
+ final bool inferRetType() const scope @safe pure nothrow @nogc
+ {
+ return !!(this.flags & FUNCFLAG.inferRetType);
+ }
+
+ final bool hasDualContext() const scope @safe pure nothrow @nogc
+ {
+ return !!(this.flags & FUNCFLAG.dualContext);
+ }
+
+ final bool hasAlwaysInlines() const scope @safe pure nothrow @nogc
+ {
+ return !!(this.flags & FUNCFLAG.hasAlwaysInline);
+ }
+
+ final bool isCrtCtor() const scope @safe pure nothrow @nogc
+ {
+ return !!(this.flags & FUNCFLAG.CRTCtor);
+ }
+
+ final bool isCrtDtor() const scope @safe pure nothrow @nogc
+ {
+ return !!(this.flags & FUNCFLAG.CRTDtor);
+ }
+
/**************************************
* The function is doing something that may allocate with the GC,
* so mark it as not nogc (not no-how).
@@ -1809,19 +1852,19 @@ extern (C++) class FuncDeclaration : Declaration
{
auto ad = isThis();
ClassDeclaration cd = ad ? ad.isClassDeclaration() : null;
- return (ad && !(cd && cd.isCPPclass()) && global.params.useInvariants == CHECKENABLE.on && (visibility.kind == Visibility.Kind.protected_ || visibility.kind == Visibility.Kind.public_ || visibility.kind == Visibility.Kind.export_) && !naked);
+ return (ad && !(cd && cd.isCPPclass()) && global.params.useInvariants == CHECKENABLE.on && (visibility.kind == Visibility.Kind.protected_ || visibility.kind == Visibility.Kind.public_ || visibility.kind == Visibility.Kind.export_) && !this.isNaked());
}
bool addPostInvariant()
{
auto ad = isThis();
ClassDeclaration cd = ad ? ad.isClassDeclaration() : null;
- return (ad && !(cd && cd.isCPPclass()) && ad.inv && global.params.useInvariants == CHECKENABLE.on && (visibility.kind == Visibility.Kind.protected_ || visibility.kind == Visibility.Kind.public_ || visibility.kind == Visibility.Kind.export_) && !naked);
+ return (ad && !(cd && cd.isCPPclass()) && ad.inv && global.params.useInvariants == CHECKENABLE.on && (visibility.kind == Visibility.Kind.protected_ || visibility.kind == Visibility.Kind.public_ || visibility.kind == Visibility.Kind.export_) && !this.isNaked());
}
override const(char)* kind() const
{
- return generated ? "generated function" : "function";
+ return this.isGenerated() ? "generated function" : "function";
}
/********************************************
@@ -2163,7 +2206,7 @@ extern (C++) class FuncDeclaration : Declaration
vresult.parent = this;
}
- if (sc && vresult.semanticRun == PASS.init)
+ if (sc && vresult.semanticRun == PASS.initial)
{
TypeFunction tf = type.toTypeFunction();
if (tf.isref)
@@ -2609,35 +2652,124 @@ extern (C++) class FuncDeclaration : Declaration
return fd;
}
- /******************
- * Check parameters and return type of D main() function.
- * Issue error messages.
- */
- extern (D) final void checkDmain()
- {
+ /+
+ + Checks the parameter and return types iff this is a `main` function.
+ +
+ + The following signatures are allowed for a `D main`:
+ + - Either no or a single parameter of type `string[]`
+ + - Return type is either `void`, `int` or `noreturn`
+ +
+ + The following signatures are standard C:
+ + - `int main()`
+ + - `int main(int, char**)`
+ +
+ + This function accepts the following non-standard extensions:
+ + - `char** envp` as a third parameter
+ + - `void` / `noreturn` as return type
+ +
+ + This function will issue errors for unexpected arguments / return types.
+ +/
+ extern (D) final void checkMain()
+ {
+ if (ident != Id.main || isMember() || isNested())
+ return; // Not a main function
+
TypeFunction tf = type.toTypeFunction();
+
+ Type retType = tf.nextOf();
+ if (!retType)
+ {
+ // auto main(), check after semantic
+ assert(this.inferRetType);
+ return;
+ }
+
+ /// Checks whether `t` is equivalent to `char**`
+ /// Ignores qualifiers and treats enums according to their base type
+ static bool isCharPtrPtr(Type t)
+ {
+ auto tp = t.toBasetype().isTypePointer();
+ if (!tp)
+ return false;
+
+ tp = tp.next.toBasetype().isTypePointer();
+ if (!tp)
+ return false;
+
+ return tp.next.toBasetype().ty == Tchar;
+ }
+
+ // Neither of these qualifiers is allowed because they affect the ABI
+ enum invalidSTC = STC.out_ | STC.ref_ | STC.lazy_;
+
const nparams = tf.parameterList.length;
bool argerr;
- if (nparams == 1)
+
+ if (linkage == LINK.d)
{
- auto fparam0 = tf.parameterList[0];
- auto t = fparam0.type.toBasetype();
- if (t.ty != Tarray ||
- t.nextOf().ty != Tarray ||
- t.nextOf().nextOf().ty != Tchar ||
- fparam0.storageClass & (STC.out_ | STC.ref_ | STC.lazy_))
+ if (nparams == 1)
{
- argerr = true;
+ auto fparam0 = tf.parameterList[0];
+ auto t = fparam0.type.toBasetype();
+ if (t.ty != Tarray ||
+ t.nextOf().ty != Tarray ||
+ t.nextOf().nextOf().ty != Tchar ||
+ fparam0.storageClass & invalidSTC)
+ {
+ argerr = true;
+ }
}
+
+ if (tf.parameterList.varargs || nparams >= 2 || argerr)
+ error("parameter list must be empty or accept one parameter of type `string[]`");
}
- if (!tf.nextOf())
- // auto main(), check after semantic
- assert(this.inferRetType);
- else if (tf.nextOf().ty != Tint32 && tf.nextOf().ty != Tvoid && tf.nextOf().ty != Tnoreturn)
+ else if (linkage == LINK.c)
+ {
+ if (nparams == 2 || nparams == 3)
+ {
+ // Argument count must be int
+ auto argCount = tf.parameterList[0];
+ argerr |= !!(argCount.storageClass & invalidSTC);
+ argerr |= argCount.type.toBasetype().ty != Tint32;
+
+ // Argument pointer must be char**
+ auto argPtr = tf.parameterList[1];
+ argerr |= !!(argPtr.storageClass & invalidSTC);
+ argerr |= !isCharPtrPtr(argPtr.type);
+
+ // `char** environ` is a common extension, see J.5.1 of the C standard
+ if (nparams == 3)
+ {
+ auto envPtr = tf.parameterList[2];
+ argerr |= !!(envPtr.storageClass & invalidSTC);
+ argerr |= !isCharPtrPtr(envPtr.type);
+ }
+ }
+ else
+ argerr = nparams != 0;
+
+ // Disallow variadic main() - except for K&R declarations in C files.
+ // E.g. int main(), int main(argc, argv) int argc, char** argc { ... }
+ if (tf.parameterList.varargs && (!this.isCsymbol() || (!tf.parameterList.hasIdentifierList && nparams)))
+ argerr |= true;
+
+ if (argerr)
+ {
+ error("parameters must match one of the following signatures");
+ loc.errorSupplemental("`main()`");
+ loc.errorSupplemental("`main(int argc, char** argv)`");
+ loc.errorSupplemental("`main(int argc, char** argv, char** environ)` [POSIX extension]");
+ }
+ }
+ else
+ return; // Neither C nor D main, ignore (should probably be an error)
+
+ // Allow enums with appropriate base types (same ABI)
+ retType = retType.toBasetype();
+
+ if (retType.ty != Tint32 && retType.ty != Tvoid && retType.ty != Tnoreturn)
error("must return `int`, `void` or `noreturn`, not `%s`", tf.nextOf().toChars());
- else if (tf.parameterList.varargs || nparams >= 2 || argerr)
- error("parameters must be `main()` or `main(string[] args)`");
}
/***********************************************
@@ -2649,7 +2781,7 @@ extern (C++) class FuncDeclaration : Declaration
*/
final bool checkNRVO()
{
- if (!nrvo_can || returns is null)
+ if (!isNRVO() || returns is null)
return false;
auto tf = type.toTypeFunction();
@@ -2661,7 +2793,7 @@ extern (C++) class FuncDeclaration : Declaration
if (auto ve = rs.exp.isVarExp())
{
auto v = ve.var.isVarDeclaration();
- if (!v || v.isOut() || v.isRef())
+ if (!v || v.isReference())
return false;
else if (nrvo_var is null)
{
@@ -2669,6 +2801,8 @@ extern (C++) class FuncDeclaration : Declaration
// parameters and closure variables cannot be NRVOed.
if (v.isDataseg() || v.isParameter() || v.toParent2() != this)
return false;
+ if (v.nestedrefs.length && needsClosure())
+ return false;
// The variable type needs to be equivalent to the return type.
if (!v.type.equivalent(tf.next))
return false;
diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d
index 6697a05..6b6655c 100644
--- a/gcc/d/dmd/globals.d
+++ b/gcc/d/dmd/globals.d
@@ -15,6 +15,7 @@ import core.stdc.stdint;
import dmd.root.array;
import dmd.root.filename;
import dmd.common.outbuffer;
+import dmd.file_manager;
import dmd.identifier;
/// Defines a setting for how compiler warnings and deprecations are handled
@@ -329,6 +330,9 @@ extern (C++) struct Global
bool hasMainFunction; /// Whether a main function has already been compiled in (for -main switch)
uint varSequenceNumber = 1; /// Relative lifetime of `VarDeclaration` within a function, used for `scope` checks
+ /// Cache files read from disk
+ FileManager fileManager;
+
enum recursionLimit = 500; /// number of recursive template expansions before abort
nothrow:
@@ -383,6 +387,7 @@ extern (C++) struct Global
extern (C++) void _init()
{
+ this.fileManager = new FileManager();
version (MARS)
{
vendor = "Digital Mars D";
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index 9bbe0c9..2a33692 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -19,6 +19,8 @@
// Can't include arraytypes.h here, need to declare these directly.
template <typename TYPE> struct Array;
+class FileManager;
+
typedef unsigned char Diagnostic;
enum
{
@@ -292,6 +294,8 @@ struct Global
bool hasMainFunction;
unsigned varSequenceNumber;
+ FileManager* fileManager;
+
/* Start gagging. Return the current number of gagged errors
*/
unsigned startGagging();
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index f2552d4..a3afbe5 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -1836,25 +1836,12 @@ public:
t = te.sym.memtype;
goto L1;
}
+ case Tchar:
case Twchar:
- // BUG: need to cast(wchar)
case Tdchar:
- // BUG: need to cast(dchar)
- if (cast(uinteger_t)v > 0xFF)
- {
- buf.printf("'\\U%08llx'", cast(long)v);
- break;
- }
- goto case;
- case Tchar:
{
- size_t o = buf.length;
- if (v == '\'')
- buf.writestring("'\\''");
- else if (isprint(cast(int)v) && v != '\\')
- buf.printf("'%c'", cast(int)v);
- else
- buf.printf("'\\x%02x'", cast(int)v);
+ const o = buf.length;
+ writeSingleCharLiteral(*buf, cast(dchar) v);
if (hgs.ddoc)
escapeDdocString(buf, o);
break;
@@ -2761,9 +2748,15 @@ bool stcToBuffer(OutBuffer* buf, StorageClass stc)
bool result = false;
if (stc & STC.scopeinferred)
+ {
+ //buf.writestring("scope-inferred ");
stc &= ~(STC.scope_ | STC.scopeinferred);
+ }
if (stc & STC.returninferred)
+ {
+ //buf.writestring("return-inferred ");
stc &= ~(STC.return_ | STC.returninferred);
+ }
/* Put scope ref return into a standard order
*/
diff --git a/gcc/d/dmd/importc.d b/gcc/d/dmd/importc.d
index ec44ee0..bcfbd9a 100644
--- a/gcc/d/dmd/importc.d
+++ b/gcc/d/dmd/importc.d
@@ -285,7 +285,7 @@ bool cFuncEquivalence(TypeFunction tf1, TypeFunction tf2)
if (tf1.parameterList.length == 0 && tf2.parameterList.length == 0)
return true;
- if (!tf1.nextOf().equals(tf2.nextOf()))
+ if (!cTypeEquivalence(tf1.next, tf2.next))
return false; // function return types don't match
if (tf1.parameterList.length != tf2.parameterList.length)
@@ -318,3 +318,40 @@ bool cFuncEquivalence(TypeFunction tf1, TypeFunction tf2)
//printf("t2: %s\n", tf2.toChars());
return true;
}
+
+/*******************************
+ * Types haven't been merged yet, because we haven't done
+ * semantic() yet.
+ * But we still need to see if t1 and t2 are the same type.
+ * Params:
+ * t1 = first type
+ * t2 = second type
+ * Returns:
+ * true if they are equivalent types
+ */
+bool cTypeEquivalence(Type t1, Type t2)
+{
+ if (t1.equals(t2))
+ return true; // that was easy
+
+ if (t1.ty != t2.ty || t1.mod != t2.mod)
+ return false;
+
+ if (auto tp = t1.isTypePointer())
+ return cTypeEquivalence(tp.next, t2.nextOf());
+
+ if (auto ta = t1.isTypeSArray())
+ // Bug: should check array dimension
+ return cTypeEquivalence(ta.next, t2.nextOf());
+
+ if (auto ts = t1.isTypeStruct())
+ return ts.sym is t2.isTypeStruct().sym;
+
+ if (auto te = t1.isTypeEnum())
+ return te.sym is t2.isTypeEnum().sym;
+
+ if (auto tf = t1.isTypeFunction())
+ return cFuncEquivalence(tf, tf.isTypeFunction());
+
+ return false;
+}
diff --git a/gcc/d/dmd/init.h b/gcc/d/dmd/init.h
index c6c8c62..73dc4bb 100644
--- a/gcc/d/dmd/init.h
+++ b/gcc/d/dmd/init.h
@@ -114,4 +114,4 @@ public:
void accept(Visitor *v) { v->visit(this); }
};
-Expression *initializerToExpression(Initializer *init, Type *t = NULL);
+Expression *initializerToExpression(Initializer *init, Type *t = NULL, const bool isCfile = false);
diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index bc02bf9..649d88e 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/dmd/initsem.d
@@ -1080,10 +1080,11 @@ Initializer inferType(Initializer init, Scope* sc)
* Params:
* init = `Initializer` AST node
* itype = if not `null`, type to coerce expression to
+ * isCfile = default initializers are different with C
* Returns:
* `Expression` created, `null` if cannot, `ErrorExp` for other errors
*/
-extern (C++) Expression initializerToExpression(Initializer init, Type itype = null)
+extern (C++) Expression initializerToExpression(Initializer init, Type itype = null, const bool isCfile = false)
{
Expression visitVoid(VoidInitializer)
{
@@ -1204,7 +1205,7 @@ extern (C++) Expression initializerToExpression(Initializer init, Type itype = n
if (!init.type) // don't know what type to use
return null;
if (!defaultInit)
- defaultInit = (cast(TypeNext)t).next.defaultInit(Loc.initial);
+ defaultInit = (cast(TypeNext)t).next.defaultInit(Loc.initial, isCfile);
element = defaultInit;
}
}
diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d
index 3ff2eae..7cd4bfd 100644
--- a/gcc/d/dmd/lexer.d
+++ b/gcc/d/dmd/lexer.d
@@ -77,6 +77,7 @@ class Lexer
bool doDocComment; // collect doc comment information
bool anyToken; // seen at least one token
bool commentToken; // comments are TOK.comment's
+ bool tokenizeNewlines; // newlines are turned into TOK.endOfLine's
version (DMDLIB)
{
@@ -116,6 +117,7 @@ class Lexer
line = p;
this.doDocComment = doDocComment;
this.commentToken = commentToken;
+ this.tokenizeNewlines = false;
this.inTokenStringConstant = 0;
this.lastDocLine = 0;
//initKeywords();
@@ -227,6 +229,8 @@ class Lexer
/****************************
* Turn next token in buffer into a token.
+ * Params:
+ * t = the token to set the resulting Token to
*/
final void scan(Token* t)
{
@@ -286,7 +290,15 @@ class Lexer
case '\r':
p++;
if (*p != '\n') // if CR stands by itself
+ {
endOfLine();
+ if (tokenizeNewlines)
+ {
+ t.value = TOK.endOfLine;
+ tokenizeNewlines = false;
+ return;
+ }
+ }
version (DMDLIB)
{
if (whitespaceToken)
@@ -299,6 +311,12 @@ class Lexer
case '\n':
p++;
endOfLine();
+ if (tokenizeNewlines)
+ {
+ t.value = TOK.endOfLine;
+ tokenizeNewlines = false;
+ return;
+ }
version (DMDLIB)
{
if (whitespaceToken)
@@ -1045,6 +1063,10 @@ class Lexer
return;
case '#':
{
+ // https://issues.dlang.org/show_bug.cgi?id=22825
+ // Special token sequences are terminated by newlines,
+ // and should not be skipped over.
+ this.tokenizeNewlines = true;
p++;
if (parseSpecialTokenSequence())
continue;
@@ -1064,6 +1086,12 @@ class Lexer
{
endOfLine();
p++;
+ if (tokenizeNewlines)
+ {
+ t.value = TOK.endOfLine;
+ tokenizeNewlines = false;
+ return;
+ }
continue;
}
}
@@ -2607,16 +2635,19 @@ class Lexer
{
auto linnum = this.scanloc.linnum;
const(char)* filespec = null;
- const loc = this.loc();
bool flags;
if (!linemarker)
scan(&tok);
if (tok.value == TOK.int32Literal || tok.value == TOK.int64Literal)
{
- const lin = cast(int)(tok.unsvalue - 1);
- if (lin != tok.unsvalue - 1)
- error("line number `%lld` out of range", cast(ulong)tok.unsvalue);
+ const lin = cast(int)(tok.unsvalue);
+ if (lin != tok.unsvalue)
+ {
+ error(tok.loc, "line number `%lld` out of range", cast(ulong)tok.unsvalue);
+ skipToNextLine();
+ return;
+ }
else
linnum = lin;
}
@@ -2624,15 +2655,19 @@ class Lexer
{
}
else
- goto Lerr;
+ {
+ error(tok.loc, "positive integer argument expected following `#line`");
+ if (tok.value != TOK.endOfLine)
+ skipToNextLine();
+ return;
+ }
while (1)
{
- switch (*p)
+ scan(&tok);
+ switch (tok.value)
{
- case 0:
- case 0x1A:
- case '\n':
- Lnewline:
+ case TOK.endOfFile:
+ case TOK.endOfLine:
if (!inTokenStringConstant)
{
this.scanloc.linnum = linnum;
@@ -2640,93 +2675,40 @@ class Lexer
this.scanloc.filename = filespec;
}
return;
- case '\r':
- p++;
- if (*p != '\n')
- {
- p--;
- goto Lnewline;
- }
- continue;
- case ' ':
- case '\t':
- case '\v':
- case '\f':
- p++;
- continue; // skip white space
- case '_':
+ case TOK.file:
if (filespec || flags)
goto Lerr;
- if (memcmp(p, "__FILE__".ptr, 8) == 0)
- {
- p += 8;
- filespec = mem.xstrdup(scanloc.filename);
- continue;
- }
- goto Lerr;
- case '"':
+ filespec = mem.xstrdup(scanloc.filename);
+ continue;
+ case TOK.string_:
if (filespec || flags)
goto Lerr;
- stringbuffer.setsize(0);
- p++;
- while (1)
- {
- uint c;
- c = *p;
- switch (c)
- {
- case '\n':
- case '\r':
- case 0:
- case 0x1A:
- goto Lerr;
- case '"':
- stringbuffer.writeByte(0);
- filespec = mem.xstrdup(cast(const(char)*)stringbuffer[].ptr);
- p++;
- break;
- default:
- if (c & 0x80)
- {
- uint u = decodeUTF();
- if (u == PS || u == LS)
- goto Lerr;
- }
- stringbuffer.writeByte(c);
- p++;
- continue;
- }
- break;
- }
- continue;
-
- case '1':
- case '2':
- case '3':
- case '4':
- if (!linemarker)
+ if (tok.ptr[0] != '"' || tok.postfix != 0)
goto Lerr;
- flags = true; // linemarker flags seen
- ++p;
- if ('0' <= *p && *p <= '9')
- goto Lerr; // only one digit allowed
+ filespec = tok.ustring;
continue;
-
- default:
- if (*p & 0x80)
+ case TOK.int32Literal:
+ if (!filespec)
+ goto Lerr;
+ if (linemarker && tok.unsvalue >= 1 && tok.unsvalue <= 4)
{
- uint u = decodeUTF();
- if (u == PS || u == LS)
- goto Lnewline;
+ flags = true; // linemarker flags seen
+ continue;
}
goto Lerr;
+ default:
+ goto Lerr;
}
}
Lerr:
- if (linemarker)
- error(loc, "# integer [\"filespec\"] { 1 | 2 | 3 | 4 }\\n expected");
- else
- error(loc, "#line integer [\"filespec\"]\\n expected");
+ if (filespec is null)
+ error(tok.loc, "invalid filename for `#line` directive");
+ else if (linemarker)
+ error(tok.loc, "invalid flag for line marker directive");
+ else if (!Ccompile)
+ error(tok.loc, "found `%s` when expecting new line following `#line` directive", tok.toChars());
+ if (tok.value != TOK.endOfLine)
+ skipToNextLine();
}
/***************************************
@@ -2768,6 +2750,7 @@ class Lexer
break;
}
endOfLine();
+ tokenizeNewlines = false;
}
/********************************************
@@ -3004,7 +2987,7 @@ private struct TimeStampInfo
if (auto p = getenv("SOURCE_DATE_EPOCH"))
{
if (!ct.parseDigits(p.toDString()))
- error(loc, "Value of environment variable `SOURCE_DATE_EPOCH` should be a valid UNIX timestamp, not: `%s`", p);
+ error(loc, "value of environment variable `SOURCE_DATE_EPOCH` should be a valid UNIX timestamp, not: `%s`", p);
}
else
.time(&ct);
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 1494044..b2c7aa4 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -4198,6 +4198,8 @@ extern (C++) final class TypeFunction : TypeNext
ParameterList parameterList; // function parameters
+ // These flags can be accessed like `bool` properties,
+ // getters and setters are generated for them
private enum FunctionFlag : uint
{
none = 0,
@@ -4206,13 +4208,13 @@ extern (C++) final class TypeFunction : TypeNext
isproperty = 0x0004, // can be called without parentheses
isref = 0x0008, // returns a reference
isreturn = 0x0010, // 'this' is returned by ref
- isscope = 0x0020, // 'this' is scope
+ isScopeQual = 0x0020, // 'this' is scope
isreturninferred= 0x0040, // 'this' is return from inference
isscopeinferred = 0x0080, // 'this' is scope from inference
islive = 0x0100, // is @live
incomplete = 0x0200, // return type or default arguments removed
- inoutParam = 0x0400, // inout on the parameters
- inoutQual = 0x0800, // inout on the qualifier
+ isInOutParam = 0x0400, // inout on the parameters
+ isInOutQual = 0x0800, // inout on the qualifier
isctor = 0x1000, // the function is a constructor
isreturnscope = 0x2000, // `this` is returned by value
}
@@ -4480,7 +4482,7 @@ extern (C++) final class TypeFunction : TypeNext
{
// Check escaping through return value
Type tret = nextOf().toBasetype();
- if (isref || tret.hasPointers())
+ if (isref || tret.hasPointers() || !isnothrow())
{
return stc;
}
@@ -5084,177 +5086,29 @@ extern (C++) final class TypeFunction : TypeNext
return false;
}
- /// set or get if the function has the `nothrow` attribute
- bool isnothrow() const pure nothrow @safe @nogc
- {
- return (funcFlags & FunctionFlag.isnothrow) != 0;
- }
- /// ditto
- void isnothrow(bool v) pure nothrow @safe @nogc
- {
- if (v) funcFlags |= FunctionFlag.isnothrow;
- else funcFlags &= ~FunctionFlag.isnothrow;
- }
-
- /// set or get if the function has the `@nogc` attribute
- bool isnogc() const pure nothrow @safe @nogc
- {
- return (funcFlags & FunctionFlag.isnogc) != 0;
- }
- /// ditto
- void isnogc(bool v) pure nothrow @safe @nogc
- {
- if (v) funcFlags |= FunctionFlag.isnogc;
- else funcFlags &= ~FunctionFlag.isnogc;
- }
-
- /// set or get if the function has the `@property` attribute
- bool isproperty() const pure nothrow @safe @nogc
- {
- return (funcFlags & FunctionFlag.isproperty) != 0;
- }
- /// ditto
- void isproperty(bool v) pure nothrow @safe @nogc
- {
- if (v) funcFlags |= FunctionFlag.isproperty;
- else funcFlags &= ~FunctionFlag.isproperty;
- }
-
- /// set or get if the function has the `ref` attribute
- bool isref() const pure nothrow @safe @nogc
- {
- return (funcFlags & FunctionFlag.isref) != 0;
- }
- /// ditto
- void isref(bool v) pure nothrow @safe @nogc
- {
- if (v) funcFlags |= FunctionFlag.isref;
- else funcFlags &= ~FunctionFlag.isref;
- }
-
- /// set or get if the function has the `return` attribute
- bool isreturn() const pure nothrow @safe @nogc
- {
- return (funcFlags & FunctionFlag.isreturn) != 0;
- }
- /// ditto
- void isreturn(bool v) pure nothrow @safe @nogc
- {
- if (v) funcFlags |= FunctionFlag.isreturn;
- else funcFlags &= ~FunctionFlag.isreturn;
- }
-
- /// set or get if the function has the `returnscope` attribute
- bool isreturnscope() const pure nothrow @safe @nogc
- {
- return (funcFlags & FunctionFlag.isreturnscope) != 0;
- }
- /// ditto
- void isreturnscope(bool v) pure nothrow @safe @nogc
- {
- if (v) funcFlags |= FunctionFlag.isreturnscope;
- else funcFlags &= ~FunctionFlag.isreturnscope;
- }
-
- /// set or get if the function has the `scope` attribute
- bool isScopeQual() const pure nothrow @safe @nogc
- {
- return (funcFlags & FunctionFlag.isscope) != 0;
- }
- /// ditto
- void isScopeQual(bool v) pure nothrow @safe @nogc
- {
- if (v) funcFlags |= FunctionFlag.isscope;
- else funcFlags &= ~FunctionFlag.isscope;
- }
-
- /// set or get if the function has the `return` attribute inferred
- bool isreturninferred() const pure nothrow @safe @nogc
- {
- return (funcFlags & FunctionFlag.isreturninferred) != 0;
- }
- /// ditto
- void isreturninferred(bool v) pure nothrow @safe @nogc
- {
- if (v) funcFlags |= FunctionFlag.isreturninferred;
- else funcFlags &= ~FunctionFlag.isreturninferred;
- }
-
- /// set or get if the function has the `scope` attribute inferred
- bool isscopeinferred() const pure nothrow @safe @nogc
- {
- return (funcFlags & FunctionFlag.isscopeinferred) != 0;
- }
- /// ditoo
- void isscopeinferred(bool v) pure nothrow @safe @nogc
- {
- if (v) funcFlags |= FunctionFlag.isscopeinferred;
- else funcFlags &= ~FunctionFlag.isscopeinferred;
- }
-
- /// set or get if the function has the `@live` attribute
- bool islive() const pure nothrow @safe @nogc
- {
- return (funcFlags & FunctionFlag.islive) != 0;
- }
- /// ditto
- void islive(bool v) pure nothrow @safe @nogc
- {
- if (v) funcFlags |= FunctionFlag.islive;
- else funcFlags &= ~FunctionFlag.islive;
- }
-
- /// set or get if the return type or the default arguments are removed
- bool incomplete() const pure nothrow @safe @nogc
- {
- return (funcFlags & FunctionFlag.incomplete) != 0;
- }
- /// ditto
- void incomplete(bool v) pure nothrow @safe @nogc
- {
- if (v) funcFlags |= FunctionFlag.incomplete;
- else funcFlags &= ~FunctionFlag.incomplete;
- }
-
- /// set or get if the function has the `inout` on the parameters
- bool isInOutParam() const pure nothrow @safe @nogc
- {
- return (funcFlags & FunctionFlag.inoutParam) != 0;
- }
- /// ditto
- void isInOutParam(bool v) pure nothrow @safe @nogc
- {
- if (v) funcFlags |= FunctionFlag.inoutParam;
- else funcFlags &= ~FunctionFlag.inoutParam;
- }
+ // Generate getter / setter functions for `FunctionFlag` members so they can be
+ // treated like regular `bool` fields, instead of requiring bit twiddling to read/write
+ extern (D) mixin(() {
+ string result = "extern(C++) pure nothrow @safe @nogc {";
+ foreach (string mem; __traits(allMembers, FunctionFlag))
+ {
+ result ~= "
+ /// set or get if the function has the FunctionFlag attribute of the same name
+ bool "~mem~"() const { return (funcFlags & FunctionFlag."~mem~") != 0; }
+ /// ditto
+ void "~mem~"(bool v)
+ {
+ if (v) funcFlags |= FunctionFlag."~mem~";
+ else funcFlags &= ~FunctionFlag."~mem~";
+ }";
+ }
+ return result ~ "}\n";
+ }());
- /// set or get if the function has the `inout` on the parameters
- bool isInOutQual() const pure nothrow @safe @nogc
- {
- return (funcFlags & FunctionFlag.inoutQual) != 0;
- }
- /// ditto
- void isInOutQual(bool v) pure nothrow @safe @nogc
- {
- if (v) funcFlags |= FunctionFlag.inoutQual;
- else funcFlags &= ~FunctionFlag.inoutQual;
- }
/// Returns: `true` the function is `isInOutQual` or `isInOutParam` ,`false` otherwise.
bool iswild() const pure nothrow @safe @nogc
{
- return (funcFlags & (FunctionFlag.inoutParam | FunctionFlag.inoutQual)) != 0;
- }
-
- /// set or get if the function is a constructor
- bool isctor() const pure nothrow @safe @nogc
- {
- return (funcFlags & FunctionFlag.isctor) != 0;
- }
- /// ditto
- void isctor(bool v) pure nothrow @safe @nogc
- {
- if (v) funcFlags |= FunctionFlag.isctor;
- else funcFlags &= ~FunctionFlag.isctor;
+ return (funcFlags & (FunctionFlag.isInOutParam | FunctionFlag.isInOutQual)) != 0;
}
/// Returns: whether `this` function type has the same attributes (`@safe`,...) as `other`
@@ -6418,9 +6272,6 @@ extern (C++) final class TypeClass : Type
override MOD deduceWild(Type t, bool isRef)
{
- // If sym is forward referenced:
- if (sym.semanticRun < PASS.semanticdone && !sym.isBaseInfoComplete())
- sym.dsymbolSemantic(null);
ClassDeclaration cd = t.isClassHandle();
if (cd && (sym == cd || cd.isBaseOf(sym, null)))
return Type.deduceWild(t, isRef);
@@ -7176,6 +7027,17 @@ extern (C++) final class Parameter : ASTNode
extern (D) private static bool isCovariantScope(bool returnByRef, StorageClass from, StorageClass to) pure nothrow @nogc @safe
{
+ // Workaround for failing covariance when finding a common type of delegates,
+ // some of which have parameters with inferred scope
+ // https://issues.dlang.org/show_bug.cgi?id=21285
+ // The root cause is that scopeinferred is not part of the mangle, and mangle
+ // is used for type equality checks
+ if (to & STC.returninferred)
+ to &= ~STC.return_;
+ // note: f(return int* x) currently 'infers' scope without inferring `return`, in that case keep STC.scope
+ if (to & STC.scopeinferred && !(to & STC.return_))
+ to &= ~STC.scope_;
+
if (from == to)
return true;
diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d
index d6735d4..2957b3a 100644
--- a/gcc/d/dmd/nogc.d
+++ b/gcc/d/dmd/nogc.d
@@ -137,9 +137,9 @@ public:
override void visit(DeleteExp e)
{
- if (e.e1.op == EXP.variable)
+ if (VarExp ve = e.e1.isVarExp())
{
- VarDeclaration v = (cast(VarExp)e.e1).var.isVarDeclaration();
+ VarDeclaration v = ve.var.isVarDeclaration();
if (v && v.onstack)
return; // delete for scope allocated class object
}
diff --git a/gcc/d/dmd/ob.d b/gcc/d/dmd/ob.d
index c2594fe..121a266 100644
--- a/gcc/d/dmd/ob.d
+++ b/gcc/d/dmd/ob.d
@@ -1747,7 +1747,7 @@ PtrState toPtrState(VarDeclaration v)
*/
auto t = v.type;
- if (v.isRef())
+ if (v.isReference())
{
return t.hasMutableFields() ? PtrState.Borrowed : PtrState.Readonly;
}
@@ -1775,7 +1775,7 @@ bool hasPointersToMutableFields(Type t)
{
foreach (v; ts.sym.fields)
{
- if (v.isRef())
+ if (v.isReference())
{
if (v.type.hasMutableFields())
return true;
@@ -1977,7 +1977,12 @@ void checkObErrors(ref ObState obstate)
else if (isReadonlyPtr(v))
pvs.state = PtrState.Readonly;
else
+ {
+ if (pvs.state == PtrState.Owner && v.type.hasPointersToMutableFields())
+ v.error(e.loc, "assigning to Owner without disposing of owned value");
+
pvs.state = PtrState.Owner;
+ }
pvs.deps.zero();
EscapeByResults er;
diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d
index fc64377..dbd761f 100644
--- a/gcc/d/dmd/opover.d
+++ b/gcc/d/dmd/opover.d
@@ -711,7 +711,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if (s)
{
functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2);
- if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
+ if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
{
return ErrorExp.get();
}
@@ -720,7 +720,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if (s_r)
{
functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, &args1);
- if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
+ if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
{
return ErrorExp.get();
}
@@ -793,7 +793,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if (s_r)
{
functionResolve(m, s_r, e.loc, sc, tiargs, e.e1.type, &args2);
- if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
+ if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
{
return ErrorExp.get();
}
@@ -802,7 +802,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if (s)
{
functionResolve(m, s, e.loc, sc, tiargs, e.e2.type, &args1);
- if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
+ if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
{
return ErrorExp.get();
}
@@ -1250,7 +1250,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
if (s)
{
functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2);
- if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
+ if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
{
return ErrorExp.get();
}
@@ -1344,7 +1344,7 @@ private Expression compare_overload(BinExp e, Scope* sc, Identifier id, EXP* pop
if (s)
{
functionResolve(m, s, e.loc, sc, tiargs, e.e1.type, &args2);
- if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
+ if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
return ErrorExp.get();
}
FuncDeclaration lastf = m.lastf;
@@ -1352,7 +1352,7 @@ private Expression compare_overload(BinExp e, Scope* sc, Identifier id, EXP* pop
if (s_r)
{
functionResolve(m, s_r, e.loc, sc, tiargs, e.e2.type, &args1);
- if (m.lastf && (m.lastf.errors || m.lastf.semantic3Errors))
+ if (m.lastf && (m.lastf.errors || m.lastf.hasSemantic3Errors()))
return ErrorExp.get();
}
if (m.count > 1)
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index 5a86931..3745a15d 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -504,6 +504,16 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
{
eint = ei;
}
+ else if (auto se = ep.e1.isSymOffExp())
+ {
+ if (!se.var.isReference() &&
+ !se.var.isImportedSymbol() &&
+ se.var.isDataseg())
+ {
+ var = se.var.isVarDeclaration();
+ offset += se.offset;
+ }
+ }
}
return false;
}
@@ -531,7 +541,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
if (auto ae = e.e1.isIndexExp())
{
// Convert &array[n] to &array+n
- if (ae.e2.op == EXP.int64 && ae.e1.isVarExp())
+ if (ae.e2.isIntegerExp() && ae.e1.isVarExp())
{
sinteger_t index = ae.e2.toInteger();
VarExp ve = ae.e1.isVarExp();
@@ -541,8 +551,13 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
sinteger_t dim = ts.dim.toInteger();
if (index < 0 || index >= dim)
{
- e.error("array index %lld is out of bounds `[0..%lld]`", index, dim);
- return error();
+ /* 0 for C static arrays means size is unknown, no need to check
+ */
+ if (!(dim == 0 && ve.var.isCsymbol()))
+ {
+ e.error("array index %lld is out of bounds `[0..%lld]`", index, dim);
+ return error();
+ }
}
import core.checkedint : mulu;
@@ -559,6 +574,33 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
return;
}
}
+ // Convert &((a.b)[n]) to (&a.b)+n
+ else if (ae.e2.isIntegerExp() && ae.e1.isDotVarExp())
+ {
+ sinteger_t index = ae.e2.toInteger();
+ DotVarExp ve = ae.e1.isDotVarExp();
+ if (ve.type.isTypeSArray() && ve.var.isField() && ve.e1.isPtrExp())
+ {
+ TypeSArray ts = ve.type.isTypeSArray();
+ sinteger_t dim = ts.dim.toInteger();
+ if (index < 0 || index >= dim)
+ {
+ /* 0 for C static arrays means size is unknown, no need to check
+ */
+ if (!(dim == 0 && ve.var.isCsymbol()))
+ {
+ e.error("array index %lld is out of bounds `[0..%lld]`", index, dim);
+ return error();
+ }
+ }
+
+ auto pe = new AddrExp(e.loc, ve);
+ pe.type = e.type;
+ ret = new AddExp(e.loc, pe, ae.e2);
+ ret.type = e.type;
+ return;
+ }
+ }
}
}
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index f6472bf..7b1b63c 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -3651,7 +3651,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.traits:
if (AST.TraitsExp te = cast(AST.TraitsExp) parsePrimaryExp())
- if (te.ident && te.args)
+ if (te.ident)
{
t = new AST.TypeTraits(token.loc, te);
break;
diff --git a/gcc/d/dmd/printast.d b/gcc/d/dmd/printast.d
index 571c3fc..bba3481 100644
--- a/gcc/d/dmd/printast.d
+++ b/gcc/d/dmd/printast.d
@@ -209,5 +209,3 @@ extern (C++) final class PrintASTVisitor : Visitor
putc(' ', stdout);
}
}
-
-
diff --git a/gcc/d/dmd/root/aav.d b/gcc/d/dmd/root/aav.d
index 5b8cc82..ba5d331 100644
--- a/gcc/d/dmd/root/aav.d
+++ b/gcc/d/dmd/root/aav.d
@@ -20,7 +20,7 @@ private size_t hash(size_t a) pure nothrow @nogc @safe
return a ^ (a >> 7) ^ (a >> 4);
}
-struct KeyValueTemplate(K,V)
+private struct KeyValueTemplate(K,V)
{
K key;
V value;
@@ -31,15 +31,17 @@ alias Value = void*;
alias KeyValue = KeyValueTemplate!(Key, Value);
-struct aaA
+private struct aaA
{
+private:
aaA* next;
KeyValue keyValue;
alias keyValue this;
}
-struct AA
+private struct AA
{
+private:
aaA** b;
size_t b_length;
size_t nodes; // total number of aaA nodes
diff --git a/gcc/d/dmd/root/array.h b/gcc/d/dmd/root/array.h
index 866b952..52bed5e 100644
--- a/gcc/d/dmd/root/array.h
+++ b/gcc/d/dmd/root/array.h
@@ -205,4 +205,3 @@ struct Array
return data.ptr[--length];
}
};
-
diff --git a/gcc/d/dmd/root/bitarray.d b/gcc/d/dmd/root/bitarray.d
index 42c09fa..90cbaed 100644
--- a/gcc/d/dmd/root/bitarray.d
+++ b/gcc/d/dmd/root/bitarray.d
@@ -187,6 +187,3 @@ nothrow pure unittest
a = b;
assert(a == b);
}
-
-
-
diff --git a/gcc/d/dmd/root/file.d b/gcc/d/dmd/root/file.d
index 1f33c18..a01cfdc 100644
--- a/gcc/d/dmd/root/file.d
+++ b/gcc/d/dmd/root/file.d
@@ -45,11 +45,6 @@ struct FileBuffer
data = null;
return result;
}
-
- extern (C++) static FileBuffer* create() pure nothrow @safe
- {
- return new FileBuffer();
- }
}
///
@@ -78,12 +73,6 @@ struct File
nothrow:
/// Read the full content of a file.
- extern (C++) static ReadResult read(const(char)* name)
- {
- return read(name.toDString());
- }
-
- /// Ditto
static ReadResult read(const(char)[] name)
{
ReadResult result;
@@ -179,24 +168,18 @@ nothrow:
}
/// Write a file, returning `true` on success.
- extern (D) static bool write(const(char)* name, const void[] data)
+ static bool write(const(char)* name, const void[] data)
{
import dmd.common.file : writeFile;
return writeFile(name, data);
}
///ditto
- extern(D) static bool write(const(char)[] name, const void[] data)
+ static bool write(const(char)[] name, const void[] data)
{
return name.toCStringThen!((fname) => write(fname.ptr, data));
}
- /// ditto
- extern (C++) static bool write(const(char)* name, const(void)* data, size_t size)
- {
- return write(name, data[0 .. size]);
- }
-
/// Delete a file.
extern (C++) static void remove(const(char)* name)
{
@@ -229,7 +212,7 @@ nothrow:
* Returns:
* `true` on success
*/
- extern (D) static bool update(const(char)* namez, const void[] data)
+ static bool update(const(char)* namez, const void[] data)
{
enum log = false;
if (log) printf("update %s\n", namez);
@@ -252,17 +235,11 @@ nothrow:
}
///ditto
- extern(D) static bool update(const(char)[] name, const void[] data)
+ static bool update(const(char)[] name, const void[] data)
{
return name.toCStringThen!(fname => update(fname.ptr, data));
}
- /// ditto
- extern (C++) static bool update(const(char)* name, const(void)* data, size_t size)
- {
- return update(name, data[0 .. size]);
- }
-
/// Size of a file in bytes.
/// Params: namez = null-terminated filename
/// Returns: `ulong.max` on any error, the length otherwise.
diff --git a/gcc/d/dmd/root/stringtable.d b/gcc/d/dmd/root/stringtable.d
index 884a9f1..20316fa 100644
--- a/gcc/d/dmd/root/stringtable.d
+++ b/gcc/d/dmd/root/stringtable.d
@@ -224,7 +224,7 @@ public:
}
/// ditto
- extern(D) int opApply(scope int delegate(const(StringValue!T)*) nothrow dg) nothrow
+ int opApply(scope int delegate(const(StringValue!T)*) nothrow dg) nothrow
{
foreach (const se; table)
{
diff --git a/gcc/d/dmd/sapply.d b/gcc/d/dmd/sapply.d
index 7314d5b..26fba8f 100644
--- a/gcc/d/dmd/sapply.d
+++ b/gcc/d/dmd/sapply.d
@@ -177,4 +177,3 @@ public:
doCond(s.statement) || applyTo(s);
}
}
-
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index d237caf..5119576 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -275,7 +275,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
// Disable generated opAssign, because some members forbid identity assignment.
funcdecl.storage_class |= STC.disable;
funcdecl.fbody = null; // remove fbody which contains the error
- funcdecl.semantic3Errors = false;
+ funcdecl.flags &= ~FUNCFLAG.semantic3Errors;
}
return;
}
@@ -285,7 +285,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
if (funcdecl.semanticRun >= PASS.semantic3)
return;
funcdecl.semanticRun = PASS.semantic3;
- funcdecl.semantic3Errors = false;
+ funcdecl.flags &= ~FUNCFLAG.semantic3Errors;
if (!funcdecl.type || funcdecl.type.ty != Tfunction)
return;
@@ -386,7 +386,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
// functions may be widely used by dmd-compiled projects.
// It also gives more time for the implementation of dual-context
// functions to be reworked as a frontend-only feature.
- if (funcdecl.isThis2)
+ if (funcdecl.hasDualContext())
{
funcdecl.deprecation("function requires a dual-context, which is deprecated");
if (auto ti = sc2.parent ? sc2.parent.isInstantiated() : null)
@@ -603,7 +603,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
if (!funcdecl.fbody)
funcdecl.fbody = new CompoundStatement(Loc.initial, new Statements());
- if (funcdecl.naked)
+ if (funcdecl.isNaked())
{
fpreinv = null; // can't accommodate with no stack frame
fpostinv = null;
@@ -619,8 +619,8 @@ private extern(C++) final class Semantic3Visitor : Visitor
f.next = Type.tvoid;
if (f.checkRetType(funcdecl.loc))
funcdecl.fbody = new ErrorStatement();
- else if (funcdecl.isMain())
- funcdecl.checkDmain(); // Check main() parameters and return type
+ else
+ funcdecl.checkMain(); // Check main() parameters and return type
}
if (f.next !is null)
@@ -654,7 +654,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
// handle NRVO
if (!target.isReturnOnStack(f, funcdecl.needThis()) || !funcdecl.checkNRVO())
- funcdecl.nrvo_can = 0;
+ funcdecl.flags &= ~FUNCFLAG.NRVO;
if (funcdecl.fbody.isErrorStatement())
{
@@ -762,7 +762,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
/* Don't generate unwind tables for this function
* https://issues.dlang.org/show_bug.cgi?id=17997
*/
- funcdecl.eh_none = true;
+ funcdecl.flags |= FUNCFLAG.noEH;
}
if (funcdecl.flags & FUNCFLAG.nothrowInprocess)
@@ -927,7 +927,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
/* https://issues.dlang.org/show_bug.cgi?id=10789
* If NRVO is not possible, all returned lvalues should call their postblits.
*/
- if (!funcdecl.nrvo_can)
+ if (!funcdecl.isNRVO())
exp = doCopyOrMove(sc2, exp, f.next);
if (tret.hasPointers())
@@ -996,7 +996,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
freq = freq.statementSemantic(sc2);
freq.blockExit(funcdecl, false);
- funcdecl.eh_none = false;
+ funcdecl.flags &= ~FUNCFLAG.noEH;
sc2 = sc2.pop();
@@ -1030,7 +1030,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
fens = fens.statementSemantic(sc2);
fens.blockExit(funcdecl, false);
- funcdecl.eh_none = false;
+ funcdecl.flags &= ~FUNCFLAG.noEH;
sc2 = sc2.pop();
@@ -1159,7 +1159,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
const blockexit = s.blockExit(funcdecl, isnothrow);
if (blockexit & BE.throw_)
{
- funcdecl.eh_none = false;
+ funcdecl.flags &= ~FUNCFLAG.noEH;
if (isnothrow)
error(funcdecl.loc, "%s `%s` may throw but is marked as `nothrow`", funcdecl.kind(), funcdecl.toPrettyChars());
else if (funcdecl.flags & FUNCFLAG.nothrowInprocess)
@@ -1195,7 +1195,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
{
// 'this' is the monitor
vsync = new VarExp(funcdecl.loc, funcdecl.vthis);
- if (funcdecl.isThis2)
+ if (funcdecl.hasDualContext())
{
vsync = new PtrExp(funcdecl.loc, vsync);
vsync = new IndexExp(funcdecl.loc, vsync, IntegerExp.literal!0);
@@ -1230,7 +1230,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
}
// Fix up forward-referenced gotos
- if (funcdecl.gotos)
+ if (funcdecl.gotos && !funcdecl.isCsymbol())
{
for (size_t i = 0; i < funcdecl.gotos.dim; ++i)
{
@@ -1238,7 +1238,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
}
}
- if (funcdecl.naked && (funcdecl.fensures || funcdecl.frequires))
+ if (funcdecl.isNaked() && (funcdecl.fensures || funcdecl.frequires))
funcdecl.error("naked assembly functions with contracts are not supported");
sc2.ctorflow.callSuper = CSX.none;
@@ -1370,7 +1370,10 @@ private extern(C++) final class Semantic3Visitor : Visitor
* Otherwise, error gagging should be temporarily ungagged by functionSemantic3.
*/
funcdecl.semanticRun = PASS.semantic3done;
- funcdecl.semantic3Errors = (global.errors != oldErrors) || (funcdecl.fbody && funcdecl.fbody.isErrorStatement());
+ if ((global.errors != oldErrors) || (funcdecl.fbody && funcdecl.fbody.isErrorStatement()))
+ funcdecl.flags |= FUNCFLAG.semantic3Errors;
+ else
+ funcdecl.flags &= ~FUNCFLAG.semantic3Errors;
if (funcdecl.type.ty == Terror)
funcdecl.errors = true;
//printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent.toChars(), toChars(), sc, loc.toChars());
diff --git a/gcc/d/dmd/statement.d b/gcc/d/dmd/statement.d
index 8b271f8..ae03b8a 100644
--- a/gcc/d/dmd/statement.d
+++ b/gcc/d/dmd/statement.d
@@ -1761,6 +1761,9 @@ extern (C++) final class GotoStatement : Statement
return new GotoStatement(loc, ident);
}
+ /**************
+ * Returns: true for error
+ */
extern (D) bool checkLabel()
{
if (!label.statement)
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index 6ffba68..c2967d6 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -211,7 +211,8 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
if (f.checkForwardRef(s.exp.loc))
s.exp = ErrorExp.get();
}
- if (discardValue(s.exp))
+
+ if (!(sc.flags & SCOPE.Cfile) && discardValue(s.exp))
s.exp = ErrorExp.get();
s.exp = s.exp.optimize(WANTvalue);
@@ -728,12 +729,12 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
Dsymbol sapply = null; // the inferred opApply() or front() function
if (!inferForeachAggregate(sc, fs.op == TOK.foreach_, fs.aggr, sapply))
{
- const(char)* msg = "";
- if (fs.aggr.type && isAggregate(fs.aggr.type))
- {
- msg = ", define `opApply()`, range primitives, or use `.tupleof`";
- }
- fs.error("invalid `foreach` aggregate `%s`%s", oaggr.toChars(), msg);
+ assert(oaggr.type);
+
+ fs.error("invalid `foreach` aggregate `%s` of type `%s`", oaggr.toChars(), oaggr.type.toPrettyChars());
+ if (isAggregate(fs.aggr.type))
+ fs.loc.errorSupplemental("maybe define `opApply()`, range primitives, or use `.tupleof`");
+
return setError();
}
@@ -2310,12 +2311,12 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
needswitcherror = true;
}
- if (!sc.sw.sdefault && !(sc.flags & SCOPE.Cfile) &&
+ if (!sc.sw.sdefault &&
(!ss.isFinal || needswitcherror || global.params.useAssert == CHECKENABLE.on))
{
ss.hasNoDefault = 1;
- if (!ss.isFinal && (!ss._body || !ss._body.isErrorStatement()))
+ if (!ss.isFinal && (!ss._body || !ss._body.isErrorStatement()) && !(sc.flags & SCOPE.Cfile))
ss.error("`switch` statement without a `default`; use `final switch` or add `default: assert(0);` or add `default: break;`");
// Generate runtime error if the default is hit
@@ -2323,7 +2324,11 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
CompoundStatement cs;
Statement s;
- if (global.params.useSwitchError == CHECKENABLE.on &&
+ if (sc.flags & SCOPE.Cfile)
+ {
+ s = new BreakStatement(ss.loc, null); // default for C is `default: break;`
+ }
+ else if (global.params.useSwitchError == CHECKENABLE.on &&
global.params.checkAction != CHECKACTION.halt)
{
if (global.params.checkAction == CHECKACTION.C)
@@ -2365,7 +2370,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
ss._body = cs;
}
- if (ss.checkLabel())
+ if (!(sc.flags & SCOPE.Cfile) && ss.checkLabel())
{
sc.pop();
return setError();
@@ -3840,7 +3845,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
fd.gotos = new GotoStatements();
fd.gotos.push(gs);
}
- else if (gs.checkLabel())
+ else if (!(sc.flags & SCOPE.Cfile) && gs.checkLabel())
return setError();
result = gs;
@@ -3916,12 +3921,10 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
}
assert(sc.func);
- // use setImpure/setGC when the deprecation cycle is over
- PURE purity;
- if (!(cas.stc & STC.pure_) && (purity = sc.func.isPureBypassingInference()) != PURE.impure && purity != PURE.fwdref)
- cas.deprecation("`asm` statement is assumed to be impure - mark it with `pure` if it is not");
- if (!(cas.stc & STC.nogc) && sc.func.isNogcBypassingInference())
- cas.deprecation("`asm` statement is assumed to use the GC - mark it with `@nogc` if it does not");
+ if (!(cas.stc & STC.pure_) && sc.func.setImpure())
+ cas.error("`asm` statement is assumed to be impure - mark it with `pure` if it is not");
+ if (!(cas.stc & STC.nogc) && sc.func.setGC())
+ cas.error("`asm` statement is assumed to use the GC - mark it with `@nogc` if it does not");
if (!(cas.stc & (STC.trusted | STC.safe)) && sc.func.setUnsafe())
cas.error("`asm` statement is assumed to be `@system` - mark it with `@trusted` if it is not");
diff --git a/gcc/d/dmd/tokens.d b/gcc/d/dmd/tokens.d
index 1790996..43feab1 100644
--- a/gcc/d/dmd/tokens.d
+++ b/gcc/d/dmd/tokens.d
@@ -245,6 +245,7 @@ enum TOK : ubyte
arrow, // ->
colonColon, // ::
wchar_tLiteral,
+ endOfLine, // \n, \r, \u2028, \u2029
whitespace,
// C only keywords
@@ -851,6 +852,7 @@ extern (C++) struct Token
TOK.wcharLiteral: "wcharv",
TOK.dcharLiteral: "dcharv",
TOK.wchar_tLiteral: "wchar_tv",
+ TOK.endOfLine: "\\n",
TOK.whitespace: "whitespace",
// C only keywords
@@ -945,20 +947,19 @@ nothrow:
sprintf(&buffer[0], "%d", cast(int)intvalue);
break;
case TOK.uns32Literal:
- case TOK.wcharLiteral:
- case TOK.dcharLiteral:
case TOK.wchar_tLiteral:
sprintf(&buffer[0], "%uU", cast(uint)unsvalue);
break;
+ case TOK.wcharLiteral:
+ case TOK.dcharLiteral:
case TOK.charLiteral:
- {
- const v = cast(int)intvalue;
- if (v >= ' ' && v <= '~')
- sprintf(&buffer[0], "'%c'", v);
- else
- sprintf(&buffer[0], "'\\x%02x'", v);
+ {
+ OutBuffer buf;
+ buf.writeSingleCharLiteral(cast(dchar) intvalue);
+ buf.writeByte('\0');
+ p = buf.extractSlice().ptr;
+ }
break;
- }
case TOK.int64Literal:
sprintf(&buffer[0], "%lldL", cast(long)intvalue);
break;
@@ -1090,7 +1091,7 @@ void writeCharLiteral(ref OutBuffer buf, dchar c)
buf.writeByte('\\');
goto default;
default:
- if (c <= 0x7F)
+ if (c <= 0xFF)
{
if (isprint(c))
buf.writeByte(c);
@@ -1114,3 +1115,40 @@ unittest
}
assert(buf.extractSlice() == `a\n\r\t\b\f\0\x11\u7233\U00017233`);
}
+
+/**
+ * Write a single-quoted character literal
+ *
+ * Useful for printing '' char literals in e.g. error messages, ddoc, or the `.stringof` property
+ *
+ * Params:
+ * buf = buffer to append character in
+ * c = code point to write
+ */
+nothrow
+void writeSingleCharLiteral(ref OutBuffer buf, dchar c)
+{
+ buf.writeByte('\'');
+ if (c == '\'')
+ buf.writeByte('\\');
+
+ if (c == '"')
+ buf.writeByte('"');
+ else
+ writeCharLiteral(buf, c);
+
+ buf.writeByte('\'');
+}
+
+unittest
+{
+ OutBuffer buf;
+ writeSingleCharLiteral(buf, '\'');
+ assert(buf.extractSlice() == `'\''`);
+ buf.reset();
+ writeSingleCharLiteral(buf, '"');
+ assert(buf.extractSlice() == `'"'`);
+ buf.reset();
+ writeSingleCharLiteral(buf, '\n');
+ assert(buf.extractSlice() == `'\n'`);
+}
diff --git a/gcc/d/dmd/tokens.h b/gcc/d/dmd/tokens.h
index c404cab..f9b6062 100644
--- a/gcc/d/dmd/tokens.h
+++ b/gcc/d/dmd/tokens.h
@@ -254,6 +254,7 @@ enum class TOK : unsigned char
arrow, // ->
colonColon, // ::
wchar_tLiteral,
+ endOfLine, // \n, \r, \u2028, \u2029
whitespace,
// C only keywords
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index dbdcfd4..4b15e8c 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -80,10 +80,10 @@ private Dsymbol getDsymbolWithoutExpCtx(RootObject oarg)
{
if (auto e = isExpression(oarg))
{
- if (e.op == EXP.dotVariable)
- return (cast(DotVarExp)e).var;
- if (e.op == EXP.dotTemplateDeclaration)
- return (cast(DotTemplateExp)e).td;
+ if (auto dve = e.isDotVarExp())
+ return dve.var;
+ if (auto dte = e.isDotTemplateExp())
+ return dte.td;
}
return getDsymbol(oarg);
}
@@ -833,7 +833,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
e.error("argument `%s` has no visibility", o.toChars());
return ErrorExp.get();
}
- if (s.semanticRun == PASS.init)
+ if (s.semanticRun == PASS.initial)
s.dsymbolSemantic(null);
auto protName = visibilityToString(s.visible().kind); // TODO: How about package(names)
@@ -1053,9 +1053,9 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
}
else if (e.ident == Id.getMember)
{
- if (ex.op == EXP.dotIdentifier)
+ if (auto die = ex.isDotIdExp())
// Prevent semantic() from replacing Symbol with its initializer
- (cast(DotIdExp)ex).wantsym = true;
+ die.wantsym = true;
ex = ex.expressionSemantic(scx);
return ex;
}
@@ -2101,13 +2101,14 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
return ErrorExp.get();
}
- if (sc.func is null)
+ auto fd = sc.getEnclosingFunction();
+ if (!fd)
{
e.error("`__traits(parameters)` may only be used inside a function");
return ErrorExp.get();
}
- assert(sc.func && sc.parent.isFuncDeclaration());
- auto tf = sc.parent.isFuncDeclaration.type.isTypeFunction();
+
+ auto tf = fd.type.isTypeFunction();
assert(tf);
auto exps = new Expressions(0);
int addParameterDG(size_t idx, Parameter x)
@@ -2162,7 +2163,7 @@ private bool isSame(RootObject o1, RootObject o2, Scope* sc)
{
if (ea.op == EXP.function_)
{
- if (auto fe = cast(FuncExp)ea)
+ if (auto fe = ea.isFuncExp())
return fe.fd;
}
}
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index e5f839b..bcdbec5 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -978,7 +978,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
// duplicate a part of StructDeclaration::semanticTypeInfoMembers
//printf("AA = %s, key: xeq = %p, xerreq = %p xhash = %p\n", toChars(), sd.xeq, sd.xerreq, sd.xhash);
- if (sd.xeq && sd.xeq.generated && sd.xeq._scope && sd.xeq.semanticRun < PASS.semantic3done)
+ if (sd.xeq && sd.xeq.isGenerated() && sd.xeq._scope && sd.xeq.semanticRun < PASS.semantic3done)
{
uint errors = global.startGagging();
sd.xeq.semantic3(sd.xeq._scope);
@@ -1431,12 +1431,6 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
errors = true;
}
- if ((fparam.storageClass & (STC.ref_ | STC.wild)) == (STC.ref_ | STC.wild))
- {
- // 'ref inout' implies 'return'
- fparam.storageClass |= STC.return_;
- }
-
if (fparam.storageClass & STC.return_)
{
if (fparam.isReference())
@@ -1799,6 +1793,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
mtype.exp.ident != Id.derivedMembers &&
mtype.exp.ident != Id.getMember &&
mtype.exp.ident != Id.parent &&
+ mtype.exp.ident != Id.parameters &&
mtype.exp.ident != Id.child &&
mtype.exp.ident != Id.toType &&
mtype.exp.ident != Id.getOverloads &&
@@ -3088,7 +3083,7 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type
//static int nest; if (++nest == 50) *(char*)0=0;
if (sc is null)
{
- error(loc, "Invalid scope.");
+ error(loc, "invalid scope");
return returnError();
}
if (mt.inuse)
@@ -4076,7 +4071,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
return e.expressionSemantic(sc);
}
}
- if (d.semanticRun == PASS.init)
+ if (d.semanticRun == PASS.initial)
d.dsymbolSemantic(null);
checkAccess(e.loc, sc, e, d);
auto ve = new VarExp(e.loc, d);
@@ -4307,7 +4302,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
if (ident == Id.outer && mt.sym.vthis)
{
- if (mt.sym.vthis.semanticRun == PASS.init)
+ if (mt.sym.vthis.semanticRun == PASS.initial)
mt.sym.vthis.dsymbolSemantic(null);
if (auto cdp = mt.sym.toParentLocal().isClassDeclaration())
@@ -4503,7 +4498,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
Expression e1;
Type t;
/* returns: true to continue, false to return */
- if (f.isThis2)
+ if (f.hasDualContext())
{
if (f.followInstantiationContext(ad))
{
@@ -4560,7 +4555,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
}
}
//printf("e = %s, d = %s\n", e.toChars(), d.toChars());
- if (d.semanticRun == PASS.init)
+ if (d.semanticRun == PASS.initial)
d.dsymbolSemantic(null);
// If static function, get the most visible overload.
diff --git a/gcc/d/dmd/utils.d b/gcc/d/dmd/utils.d
index f8e7e48..67e4d86 100644
--- a/gcc/d/dmd/utils.d
+++ b/gcc/d/dmd/utils.d
@@ -63,7 +63,7 @@ FileBuffer readFile(Loc loc, const(char)[] filename)
auto result = File.read(filename);
if (!result.success)
{
- error(loc, "Error reading file `%.*s`", cast(int)filename.length, filename.ptr);
+ error(loc, "error reading file `%.*s`", cast(int)filename.length, filename.ptr);
fatal();
}
return FileBuffer(result.extractSlice());
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 2a7fb69..61a2b50 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -1441,7 +1441,7 @@ public:
gcc_assert (e->e1->op == EXP::variable);
VarDeclaration *v = e->e1->isVarExp ()->var->isVarDeclaration ();
- gcc_assert (v && v->onstack);
+ gcc_assert (v && v->onstack ());
libcall_fn libcall = tb1->isClassHandle ()->isInterfaceDeclaration ()
? LIBCALL_CALLINTERFACEFINALIZER : LIBCALL_CALLFINALIZER;
diff --git a/gcc/d/modules.cc b/gcc/d/modules.cc
index 899648f..edc7912 100644
--- a/gcc/d/modules.cc
+++ b/gcc/d/modules.cc
@@ -141,7 +141,7 @@ get_internal_fn (tree ident, const Visibility &visibility)
FuncDeclaration *fd = FuncDeclaration::genCfunc (NULL, Type::tvoid,
Identifier::idPool (name));
- fd->generated = true;
+ fd->isGenerated (true);
fd->loc = Loc (mod->srcfile.toChars (), 1, 0);
fd->parent = mod;
fd->visibility = visibility;
diff --git a/gcc/d/toir.cc b/gcc/d/toir.cc
index a25f7a5..d20c5c3 100644
--- a/gcc/d/toir.cc
+++ b/gcc/d/toir.cc
@@ -958,7 +958,7 @@ public:
/* If returning via NRVO, just refer to the DECL_RESULT; this differs
from using NULL_TREE in that it indicates that we care about the
value of the DECL_RESULT. */
- if (this->func_->nrvo_can && this->func_->nrvo_var)
+ if (this->func_->isNRVO () && this->func_->nrvo_var)
{
add_stmt (return_expr (decl));
return;