public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/ibuclaw/heads/gdc)] Import dmd v2.097.1: dmd 50bdf003a, druntime f8df5552, phobos 4ea930b6c
@ 2021-07-30 8:44 Iain Buclaw
0 siblings, 0 replies; only message in thread
From: Iain Buclaw @ 2021-07-30 8:44 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:9ad4b07f274d805fed51561046352725c418e5cb
commit 9ad4b07f274d805fed51561046352725c418e5cb
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date: Sat Jul 24 03:53:04 2021 +0200
Import dmd v2.097.1: dmd 50bdf003a, druntime f8df5552, phobos 4ea930b6c
Diff:
---
gcc/d/d-codegen.cc | 4 +-
gcc/d/d-convert.cc | 2 +-
gcc/d/d-lang.cc | 1 +
gcc/d/dmd/VERSION | 2 +-
gcc/d/dmd/access.d | 8 +-
gcc/d/dmd/aggregate.d | 94 +---
gcc/d/dmd/aggregate.h | 11 +-
gcc/d/dmd/attrib.d | 2 +-
gcc/d/dmd/blockexit.d | 3 +-
gcc/d/dmd/canthrow.d | 4 -
gcc/d/dmd/clone.d | 24 +-
gcc/d/dmd/cond.d | 2 +-
gcc/d/dmd/cparse.d | 129 ++++-
gcc/d/dmd/dcast.d | 105 ++--
gcc/d/dmd/dclass.d | 587 +++++++++++----------
gcc/d/dmd/declaration.d | 17 +-
gcc/d/dmd/declaration.h | 1 +
gcc/d/dmd/denum.d | 133 -----
gcc/d/dmd/dinterpret.d | 13 +-
gcc/d/dmd/dmodule.d | 19 +-
gcc/d/dmd/dstruct.d | 169 +-----
gcc/d/dmd/dsymbolsem.d | 212 ++++++--
gcc/d/dmd/dtemplate.d | 2 +-
gcc/d/dmd/dtoh.d | 369 +++++--------
gcc/d/dmd/enum.h | 2 -
gcc/d/dmd/escape.d | 108 ++--
gcc/d/dmd/expression.d | 117 +---
gcc/d/dmd/expression.h | 9 +-
gcc/d/dmd/expressionsem.d | 479 +++++++++++++----
gcc/d/dmd/func.d | 22 +-
gcc/d/dmd/globals.d | 1 +
gcc/d/dmd/gluelayer.d | 25 -
gcc/d/dmd/hdrgen.d | 4 +-
gcc/d/dmd/iasmgcc.d | 12 +-
gcc/d/dmd/identifier.h | 2 +-
gcc/d/dmd/init.d | 12 +-
gcc/d/dmd/mtype.d | 115 ++--
gcc/d/dmd/nogc.d | 2 -
gcc/d/dmd/optimize.d | 2 +-
gcc/d/dmd/parse.d | 45 +-
gcc/d/dmd/semantic3.d | 54 +-
gcc/d/dmd/statement.d | 527 +-----------------
gcc/d/dmd/statement.h | 20 +-
gcc/d/dmd/statementsem.d | 530 ++++++++++++++++++-
gcc/d/dmd/transitivevisitor.d | 2 -
gcc/d/dmd/typesem.d | 134 ++++-
gcc/d/expr.cc | 36 +-
gcc/d/lang-specs.h | 3 +-
gcc/testsuite/gdc.test/compilable/b17111.d | 11 +-
.../gdc.test/compilable/ddoc_markdown_breaks.d | 3 +-
.../compilable/ddoc_markdown_breaks_verbose.d | 12 +-
.../gdc.test/compilable/ddoc_markdown_code.d | 9 +-
.../compilable/ddoc_markdown_code_verbose.d | 10 +-
.../gdc.test/compilable/ddoc_markdown_emphasis.d | 3 +-
.../compilable/ddoc_markdown_emphasis_verbose.d | 11 +-
.../gdc.test/compilable/ddoc_markdown_escapes.d | 3 +-
.../gdc.test/compilable/ddoc_markdown_headings.d | 3 +-
.../compilable/ddoc_markdown_headings_verbose.d | 10 +-
.../gdc.test/compilable/ddoc_markdown_links.d | 3 +-
.../compilable/ddoc_markdown_links_verbose.d | 15 +-
.../gdc.test/compilable/ddoc_markdown_lists.d | 3 +-
.../compilable/ddoc_markdown_lists_verbose.d | 10 +-
.../gdc.test/compilable/ddoc_markdown_quote.d | 9 +-
.../compilable/ddoc_markdown_quote_verbose.d | 10 +-
.../gdc.test/compilable/ddoc_markdown_tables.d | 9 +-
.../compilable/ddoc_markdown_tables_verbose.d | 10 +-
.../gdc.test/compilable/dtoh_AnonDeclaration.d | 21 +
.../gdc.test/compilable/dtoh_forwarding.d | 38 +-
| 20 +-
| 25 +-
.../gdc.test/compilable/imports/imp22122.d | 5 +
gcc/testsuite/gdc.test/compilable/interpret3.d | 11 +-
gcc/testsuite/gdc.test/compilable/test17143.d | 14 +-
gcc/testsuite/gdc.test/compilable/test20367.d | 2 -
gcc/testsuite/gdc.test/compilable/test22122.d | 53 ++
gcc/testsuite/gdc.test/compilable/testcstuff1.c | 499 ------------------
gcc/testsuite/gdc.test/compilable/testcstuff2.c | 313 -----------
| 13 +-
| 16 +-
| 16 +-
| 13 +-
| 11 +-
| 11 +-
| 31 +-
| 22 +-
gcc/testsuite/gdc.test/compilable/vcg-ast.d | 10 +-
gcc/testsuite/gdc.test/fail_compilation/cconst1.c | 21 -
.../gdc.test/fail_compilation/diag_class_alloc.d | 4 +-
.../gdc.test/fail_compilation/disable_new.d | 4 +-
.../gdc.test/fail_compilation/fail11038.d | 6 +-
.../gdc.test/fail_compilation/fail20033.d | 22 +-
.../gdc.test/fail_compilation/fail21868b.d | 22 +
.../gdc.test/fail_compilation/fail22054.d | 23 +
.../gdc.test/fail_compilation/fail22075.d | 30 ++
.../gdc.test/fail_compilation/fail22121.d | 11 +
.../fail22121/imports/test22121/package.d | 1 +
gcc/testsuite/gdc.test/fail_compilation/fail4517.d | 21 -
gcc/testsuite/gdc.test/fail_compilation/fail4923.d | 3 +-
gcc/testsuite/gdc.test/fail_compilation/fail9368.d | 48 --
.../gdc.test/fail_compilation/failcstuff1.c | 103 ----
.../gdc.test/fail_compilation/failcstuff2.c | 86 ---
gcc/testsuite/gdc.test/fail_compilation/ice17831.d | 16 +-
.../gdc.test/fail_compilation/test16523.d | 3 +-
.../gdc.test/fail_compilation/trait_loc_err.d | 6 +-
gcc/testsuite/gdc.test/runnable/builtin.d | 10 -
gcc/testsuite/gdc.test/runnable/cstuff2.c | 254 ---------
gcc/testsuite/gdc.test/runnable/fix22115.d | 70 +++
gcc/testsuite/gdc.test/runnable/ice21727.d | 46 ++
gcc/testsuite/gdc.test/runnable/test15.d | 58 +-
gcc/testsuite/gdc.test/runnable/ufcs.d | 69 ++-
libphobos/libdruntime/core/exception.d | 201 ++++++-
libphobos/libdruntime/core/internal/atomic.d | 7 +-
.../libdruntime/core/internal/backtrace/dwarf.d | 417 ++++++---------
libphobos/libdruntime/core/internal/dassert.d | 55 +-
libphobos/libdruntime/core/internal/hash.d | 77 ++-
libphobos/libdruntime/core/lifetime.d | 6 +-
libphobos/libdruntime/core/runtime.d | 2 +-
libphobos/libdruntime/core/sys/posix/fcntl.d | 8 +-
libphobos/libdruntime/core/sys/windows/sqlext.d | 2 +-
libphobos/libdruntime/object.d | 27 +-
libphobos/src/std/algorithm/comparison.d | 23 +-
libphobos/src/std/algorithm/mutation.d | 18 +-
libphobos/src/std/array.d | 335 ++++++------
libphobos/src/std/container/array.d | 22 +-
libphobos/src/std/datetime/date.d | 6 +-
libphobos/src/std/datetime/systime.d | 216 ++++----
libphobos/src/std/datetime/timezone.d | 2 +-
libphobos/src/std/file.d | 2 +-
libphobos/src/std/internal/math/biguintcore.d | 4 +-
libphobos/src/std/math/operations.d | 46 +-
libphobos/src/std/path.d | 12 +-
libphobos/src/std/process.d | 27 +-
libphobos/src/std/random.d | 4 +-
libphobos/src/std/range/package.d | 4 +-
libphobos/src/std/regex/internal/ir.d | 4 +-
libphobos/src/std/signals.d | 9 +-
libphobos/src/std/stdio.d | 8 +-
libphobos/src/std/string.d | 59 ++-
libphobos/src/std/sumtype.d | 1 +
libphobos/src/std/traits.d | 79 ++-
libphobos/src/std/typecons.d | 58 +-
libphobos/src/std/utf.d | 49 ++
libphobos/src/std/uuid.d | 2 +-
.../testsuite/libphobos.exceptions/assert_fail.d | 79 +++
libphobos/testsuite/libphobos.hash/test_hash.d | 67 +++
145 files changed, 4017 insertions(+), 4322 deletions(-)
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 18f8b75a616..b7dbda937e7 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -2322,7 +2322,7 @@ get_frame_for_symbol (Dsymbol *sym)
gcc_assert (cdo && cd);
int offset;
- if (cdo->isBaseOf (cd, &offset) && offset != 0)
+ if (isBaseOf (cdo, cd, &offset) && offset != 0)
{
/* Generate a new frame to pass to the overriden function that
has the `this' pointer adjusted. */
@@ -2393,7 +2393,7 @@ find_this_tree (ClassDeclaration *ocd)
{
if (ocd == cd)
return get_decl_tree (fd->vthis);
- else if (ocd->isBaseOf (cd, NULL))
+ else if (isBaseOf (ocd, cd, NULL))
return convert_expr (get_decl_tree (fd->vthis),
cd->type, ocd->type);
diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc
index 0e030eca541..f822ee2ccd9 100644
--- a/gcc/d/d-convert.cc
+++ b/gcc/d/d-convert.cc
@@ -407,7 +407,7 @@ convert_expr (tree exp, Type *etype, Type *totype)
ClassDeclaration *cdto = tbtype->isClassHandle ();
int offset;
- if (cdto->isBaseOf (cdfrom, &offset) && offset != OFFSET_RUNTIME)
+ if (isBaseOf (cdto, cdfrom, &offset) && offset != OFFSET_RUNTIME)
{
/* Casting up the inheritance tree: Don't do anything special.
Cast to an implemented interface: Handle at compile-time. */
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index c8f9935da30..4f9d4205cd1 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
#include "dmd/mangle.h"
#include "dmd/module.h"
#include "dmd/mtype.h"
+#include "dmd/root/file.h"
#include "dmd/target.h"
#include "opts.h"
diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION
index 6945fd11783..53632cade2f 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@
-v2.097.0
+v2.097.1
diff --git a/gcc/d/dmd/access.d b/gcc/d/dmd/access.d
index 20c162c7fa1..a97e43310e2 100644
--- a/gcc/d/dmd/access.d
+++ b/gcc/d/dmd/access.d
@@ -197,10 +197,10 @@ bool checkAccess(Loc loc, Scope* sc, Expression e, Dsymbol d)
if (!e)
return false;
- if (e.type.ty == Tclass)
+ if (auto tc = e.type.isTypeClass())
{
// Do access check
- ClassDeclaration cd = (cast(TypeClass)e.type).sym;
+ ClassDeclaration cd = tc.sym;
if (e.op == TOK.super_)
{
if (ClassDeclaration cd2 = sc.func.toParent().isClassDeclaration())
@@ -208,10 +208,10 @@ bool checkAccess(Loc loc, Scope* sc, Expression e, Dsymbol d)
}
return checkAccess(cd, loc, sc, d);
}
- else if (e.type.ty == Tstruct)
+ else if (auto ts = e.type.isTypeStruct())
{
// Do access check
- StructDeclaration cd = (cast(TypeStruct)e.type).sym;
+ StructDeclaration cd = ts.sym;
return checkAccess(cd, loc, sc, d);
}
return false;
diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d
index da54ba2bf9f..88b7fbf7ef6 100644
--- a/gcc/d/dmd/aggregate.d
+++ b/gcc/d/dmd/aggregate.d
@@ -103,7 +103,6 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
// Special member functions
FuncDeclarations invs; /// Array of invariants
FuncDeclaration inv; /// Merged invariant calling all members of invs
- NewDeclaration aggNew; /// allocator
/// CtorDeclaration or TemplateDeclaration
Dsymbol ctor;
@@ -125,6 +124,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
///
Visibility visibility;
bool noDefaultCtor; /// no default construction
+ bool disableNew; /// disallow allocations using `new`
Sizeok sizeok = Sizeok.none; /// set when structsize contains valid data
final extern (D) this(const ref Loc loc, Identifier id)
@@ -161,91 +161,6 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
ScopeDsymbol.setScope(sc);
}
- /***************************************
- * Find all instance fields, then push them into `fields`.
- *
- * Runs semantic() for all instance field variables, but also
- * the field types can remain yet not resolved forward references,
- * except direct recursive definitions.
- * After the process sizeok is set to Sizeok.fwd.
- *
- * Returns:
- * false if any errors occur.
- */
- final bool determineFields()
- {
- if (_scope)
- dsymbolSemantic(this, null);
- if (sizeok != Sizeok.none)
- return true;
-
- //printf("determineFields() %s, fields.dim = %d\n", toChars(), fields.dim);
- // determineFields can be called recursively from one of the fields's v.semantic
- fields.setDim(0);
-
- static int func(Dsymbol s, AggregateDeclaration ad)
- {
- auto v = s.isVarDeclaration();
- if (!v)
- return 0;
- if (v.storage_class & STC.manifest)
- return 0;
-
- if (v.semanticRun < PASS.semanticdone)
- v.dsymbolSemantic(null);
- // Return in case a recursive determineFields triggered by v.semantic already finished
- if (ad.sizeok != Sizeok.none)
- return 1;
-
- if (v.aliassym)
- return 0; // If this variable was really a tuple, skip it.
-
- if (v.storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared | STC.manifest | STC.ctfe | STC.templateparameter))
- return 0;
- if (!v.isField() || v.semanticRun < PASS.semanticdone)
- return 1; // unresolvable forward reference
-
- ad.fields.push(v);
-
- if (v.storage_class & STC.ref_)
- return 0;
- auto tv = v.type.baseElemOf();
- if (tv.ty != Tstruct)
- return 0;
- if (ad == (cast(TypeStruct)tv).sym)
- {
- const(char)* psz = (v.type.toBasetype().ty == Tsarray) ? "static array of " : "";
- ad.error("cannot have field `%s` with %ssame struct type", v.toChars(), psz);
- ad.type = Type.terror;
- ad.errors = true;
- return 1;
- }
- return 0;
- }
-
- if (members)
- {
- for (size_t i = 0; i < members.dim; i++)
- {
- auto s = (*members)[i];
- if (s.apply(&func, this))
- {
- if (sizeok != Sizeok.none)
- {
- // recursive determineFields already finished
- return true;
- }
- return false;
- }
- }
- }
-
- if (sizeok != Sizeok.done)
- sizeok = Sizeok.fwd;
-
- return true;
- }
-
/***************************************
* Returns:
* The total number of fields minus the number of hidden fields.
@@ -288,7 +203,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
}
// Determine instance fields when sizeok == Sizeok.none
- if (!determineFields())
+ if (!this.determineFields())
goto Lfail;
if (sizeok != Sizeok.done)
finalizeSize();
@@ -538,8 +453,9 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
* will return the base of the enum, and its default initializer
* would be different from the enum's.
*/
- while (telem.toBasetype().ty == Tsarray)
- telem = (cast(TypeSArray)telem.toBasetype()).next;
+ TypeSArray tsa;
+ while ((tsa = telem.toBasetype().isTypeSArray()) !is null)
+ telem = tsa.next;
if (telem.ty == Tvoid)
telem = Type.tuns8.addMod(telem.mod);
}
diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h
index 41572a82bdb..571f3aebd09 100644
--- a/gcc/d/dmd/aggregate.h
+++ b/gcc/d/dmd/aggregate.h
@@ -21,7 +21,6 @@ class Expression;
class FuncDeclaration;
class CtorDeclaration;
class DtorDeclaration;
-class NewDeclaration;
class InterfaceDeclaration;
class TypeInfoClassDeclaration;
class VarDeclaration;
@@ -102,7 +101,6 @@ public:
// Special member functions
FuncDeclarations invs; // Array of invariants
FuncDeclaration *inv; // invariant
- NewDeclaration *aggNew; // allocator
Dsymbol *ctor; // CtorDeclaration or TemplateDeclaration
@@ -122,11 +120,11 @@ public:
Visibility visibility;
bool noDefaultCtor; // no default construction
+ bool disableNew; // disallow allocations using `new`
Sizeok sizeok; // set when structsize contains valid data
virtual Scope *newScope(Scope *sc);
void setScope(Scope *sc);
- bool determineFields();
size_t nonHiddenFields();
bool determineSize(Loc loc);
virtual void finalizeSize() = 0;
@@ -193,11 +191,9 @@ public:
static StructDeclaration *create(Loc loc, Identifier *id, bool inObject);
StructDeclaration *syntaxCopy(Dsymbol *s);
- void semanticTypeInfoMembers();
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
const char *kind() const;
void finalizeSize();
- bool fit(const Loc &loc, Scope *sc, Expressions *elements, Type *stype);
bool isPOD();
StructDeclaration *isStructDeclaration() { return this; }
@@ -294,7 +290,6 @@ public:
#define OFFSET_RUNTIME 0x76543210
#define OFFSET_FWDREF 0x76543211
- virtual bool isBaseOf(ClassDeclaration *cd, int *poffset);
bool isBaseInfoComplete();
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
@@ -327,8 +322,6 @@ class InterfaceDeclaration : public ClassDeclaration
public:
InterfaceDeclaration *syntaxCopy(Dsymbol *s);
Scope *newScope(Scope *sc);
- bool isBaseOf(ClassDeclaration *cd, int *poffset);
- bool isBaseOf(BaseClass *bc, int *poffset);
const char *kind() const;
int vtblOffset() const;
bool isCPPinterface() const;
@@ -337,3 +330,5 @@ public:
InterfaceDeclaration *isInterfaceDeclaration() { return this; }
void accept(Visitor *v) { v->visit(this); }
};
+
+bool isBaseOf(ClassDeclaration* derived, ClassDeclaration* cd, int* poffset);
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index 646dd3c7a40..bb104250ebb 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -206,7 +206,7 @@ extern (C++) abstract class AttribDeclaration : Dsymbol
objc.addSymbols(this, classes, categories);
}
- override final inout(AttribDeclaration) isAttribDeclaration() inout
+ override final inout(AttribDeclaration) isAttribDeclaration() inout pure @safe
{
return this;
}
diff --git a/gcc/d/dmd/blockexit.d b/gcc/d/dmd/blockexit.d
index efeb3fac748..1fd90051830 100644
--- a/gcc/d/dmd/blockexit.d
+++ b/gcc/d/dmd/blockexit.d
@@ -156,7 +156,8 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
if (!(result & BE.fallthru) && !s.comeFrom())
{
- if (blockExit(s, func, mustNotThrow) != BE.halt && s.hasCode())
+ if (blockExit(s, func, mustNotThrow) != BE.halt && s.hasCode() &&
+ s.loc != Loc.initial) // don't emit warning for generated code
s.warning("statement is not reachable");
}
else
diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d
index fcb884df72d..ed05af6ac7c 100644
--- a/gcc/d/dmd/canthrow.d
+++ b/gcc/d/dmd/canthrow.d
@@ -115,10 +115,6 @@ extern (C++) bool canThrow(Expression e, FuncDeclaration func, bool mustNotThrow
{
if (ne.member)
{
- if (ne.allocator)
- // https://issues.dlang.org/show_bug.cgi?id=14407
- checkFuncThrows(ne, ne.allocator);
-
// See if constructor call can throw
checkFuncThrows(ne, ne.member);
}
diff --git a/gcc/d/dmd/clone.d b/gcc/d/dmd/clone.d
index 094ce0051a0..d3006170be7 100644
--- a/gcc/d/dmd/clone.d
+++ b/gcc/d/dmd/clone.d
@@ -410,9 +410,8 @@ bool needOpEquals(StructDeclaration sd)
/* If any of the fields has an opEquals, then we
* need it too.
*/
- for (size_t i = 0; i < sd.fields.dim; i++)
+ foreach (VarDeclaration v; sd.fields)
{
- VarDeclaration v = sd.fields[i];
if (v.storage_class & STC.ref_)
continue;
if (v.overlapped)
@@ -426,8 +425,6 @@ bool needOpEquals(StructDeclaration sd)
continue;
if (needOpEquals(ts.sym))
goto Lneed;
- if (ts.sym.aliasthis) // https://issues.dlang.org/show_bug.cgi?id=14806
- goto Lneed;
}
if (tvbase.isfloating())
{
@@ -731,12 +728,11 @@ private bool needToHash(StructDeclaration sd)
if (sd.xhash)
goto Lneed;
- /* If any of the fields has an opEquals, then we
+ /* If any of the fields has an toHash, then we
* need it too.
*/
- for (size_t i = 0; i < sd.fields.dim; i++)
+ foreach (VarDeclaration v; sd.fields)
{
- VarDeclaration v = sd.fields[i];
if (v.storage_class & STC.ref_)
continue;
if (v.overlapped)
@@ -750,8 +746,6 @@ private bool needToHash(StructDeclaration sd)
continue;
if (needToHash(ts.sym))
goto Lneed;
- if (ts.sym.aliasthis) // https://issues.dlang.org/show_bug.cgi?id=14948
- goto Lneed;
}
if (tvbase.isfloating())
{
@@ -1001,9 +995,8 @@ DtorDeclaration buildDtor(AggregateDeclaration ad, Scope* sc)
Expression e = null;
e = null;
stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
- for (size_t i = 0; i < ad.dtors.dim; i++)
+ foreach (FuncDeclaration fd; ad.dtors)
{
- FuncDeclaration fd = ad.dtors[i];
stc = mergeFuncAttrs(stc, fd);
if (stc & STC.disable)
{
@@ -1228,10 +1221,8 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
// if any of the postblits are disabled, then the generated postblit
// will be disabled
- for (size_t i = 0; i < sd.postblits.dim; i++)
- {
- stc |= sd.postblits[i].storage_class & STC.disable;
- }
+ foreach (postblit; sd.postblits)
+ stc |= postblit.storage_class & STC.disable;
VarDeclaration[] fieldsToDestroy;
auto postblitCalls = new Statements();
@@ -1434,9 +1425,8 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
default:
Expression e = null;
stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
- for (size_t i = 0; i < sd.postblits.dim; i++)
+ foreach (fd; sd.postblits)
{
- auto fd = sd.postblits[i];
stc = mergeFuncAttrs(stc, fd);
if (stc & STC.disable)
{
diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d
index cf12ee4e530..d4a8b136d43 100644
--- a/gcc/d/dmd/cond.d
+++ b/gcc/d/dmd/cond.d
@@ -118,7 +118,7 @@ extern (C++) final class StaticForeach : RootObject
*/
bool needExpansion = false;
- extern (D) this(const ref Loc loc,ForeachStatement aggrfe,ForeachRangeStatement rangefe)
+ extern (D) this(const ref Loc loc, ForeachStatement aggrfe, ForeachRangeStatement rangefe)
{
assert(!!aggrfe ^ !!rangefe);
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index f64813d613f..063746116a3 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -163,6 +163,18 @@ final class CParser(AST) : Parser!AST
case TOK.rightShiftAssign:
goto Lexp;
+ case TOK.leftParenthesis:
+ {
+ /* If tokens look like a function call, assume it is one,
+ * As any type-name won't be resolved until semantic, this
+ * could be rewritten later.
+ */
+ auto tk = &token;
+ if (isFunctionCall(tk))
+ goto Lexp;
+ goto default;
+ }
+
default:
{
/* If tokens look like a declaration, assume it is one
@@ -1738,7 +1750,7 @@ final class CParser(AST) : Parser!AST
auto body = cparseStatement(ParseStatementFlags.curly); // don't start a new scope; continue with parameter scope
Specifier specifier;
specifier.scw = scw;
- auto fd = new AST.FuncDeclaration(token.loc, Loc.initial, id, specifiersToSTC(LVL.global, specifier), ft);
+ auto fd = new AST.FuncDeclaration(locFunc, prevloc, id, specifiersToSTC(LVL.global, specifier), ft);
if (addFuncName)
{
@@ -2281,35 +2293,44 @@ final class CParser(AST) : Parser!AST
{
case TOK.leftBracket:
{
- // post [] syntax.
+ // post [] syntax, pick up any leading type qualifiers, `static` and `*`
AST.Type ta;
nextToken();
- // pick up any leading type qualifiers, `static` and `*`
+ auto mod = cparseTypeQualifierList(); // const/volatile/restrict/_Atomic
+
bool isStatic;
+ bool isVLA;
if (token.value == TOK.static_)
{
- isStatic = true;
+ isStatic = true; // `static`
nextToken();
+ if (!mod) // type qualifiers after `static`
+ mod = cparseTypeQualifierList();
}
-
- bool isVLA;
- if (!isStatic)
+ else if (token.value == TOK.mul)
{
- if (token.value == TOK.static_)
+ if (peekNext() == TOK.rightBracket)
{
- isStatic = true;
+ isVLA = true; // `*`
nextToken();
}
- else if (token.value == TOK.mul)
- {
- if (peekNext() == TOK.rightBracket)
- {
- isVLA = true;
- nextToken();
- }
- }
}
+
+ if (isStatic || token.value != TOK.rightBracket)
+ {
+ //printf("It's a static array\n");
+ AST.Expression e = cparseAssignExp(); // [ expression ]
+ ta = new AST.TypeSArray(t, e);
+ }
+ else
+ {
+ // An array of unknown size, fake it with a DArray
+ ta = new AST.TypeDArray(t); // []
+ }
+ check(TOK.rightBracket);
+
+ // Issue errors for unsupported types.
if (isVLA) // C11 6.7.6.2
{
error("variable length arrays are not supported");
@@ -2318,25 +2339,35 @@ final class CParser(AST) : Parser!AST
{
error("static array parameters are not supported");
}
-
- if (token.value == TOK.rightBracket)
+ if (declarator != DTR.xparameter)
{
- // An array of unknown size, fake it with a DArray
- ta = new AST.TypeDArray(t); // []
- nextToken();
+ /* C11 6.7.6.2-4: '*' can only be used with function prototype scope.
+ */
+ if (isVLA)
+ error("variable length array used outside of function prototype");
+ /* C11 6.7.6.2-1: type qualifiers and 'static' shall only appear
+ * in a declaration of a function parameter with an array type.
+ */
+ if (isStatic || mod)
+ error("static or type qualifier used outside of function prototype");
}
- else
+ if (ts.isTypeSArray() || ts.isTypeDArray())
{
- //printf("It's a static array\n");
- AST.Expression e = cparseAssignExp(); // [ expression ]
- ta = new AST.TypeSArray(t, e);
- check(TOK.rightBracket);
+ /* C11 6.7.6.2-1: type qualifiers and 'static' shall only appear
+ * in the outermost array type derivation.
+ */
+ if (isStatic || mod)
+ error("static or type qualifier used in non-outermost array type derivation");
+ /* C11 6.7.6.2-1: the element type shall not be an incomplete or
+ * function type.
+ */
+ if (ta.isTypeDArray() && !isVLA)
+ error("array type has incomplete element type `%s`", ta.toChars());
}
- const mod = cparseTypeQualifierList(); // const/volatile/restrict/_Atomic
+ // Apply type qualifiers to the constructed type.
if (mod & MOD.xconst) // ignore the other bits
ta = toConst(ta);
-
insertTx(ts, ta, t); // ts -> ... -> ta -> t
continue;
}
@@ -3189,6 +3220,46 @@ final class CParser(AST) : Parser!AST
return true;
}
+ /********************************
+ * See if match for:
+ * postfix-expression ( argument-expression-list(opt) )
+ * Params:
+ * pt = starting token, updated to one past end of initializer if true
+ * Returns:
+ * true if function call
+ */
+ private bool isFunctionCall(ref Token* pt)
+ {
+ //printf("isFunctionCall()\n");
+ auto t = pt;
+
+ if (!isPrimaryExpression(t))
+ return false;
+ if (t.value != TOK.leftParenthesis)
+ return false;
+ t = peek(t);
+ while (1)
+ {
+ if (!isAssignmentExpression(t))
+ return false;
+ if (t.value == TOK.comma)
+ {
+ t = peek(t);
+ continue;
+ }
+ if (t.value == TOK.rightParenthesis)
+ {
+ t = peek(t);
+ break;
+ }
+ return false;
+ }
+ if (t.value != TOK.semicolon)
+ return false;
+ pt = t;
+ return true;
+ }
+
/********************************
* See if match for assignment-expression.
* Params:
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index cd360e93cad..69b49fc59d5 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -574,7 +574,7 @@ MATCH implicitConvTo(Expression e, Type t)
visit(cast(Expression)e);
if (result != MATCH.nomatch)
return;
- if (e.type.ty == t.ty && e.type.ty == Tstruct && (cast(TypeStruct)e.type).sym == (cast(TypeStruct)t).sym)
+ if (e.type.ty == t.ty && e.type.isTypeStruct() && e.type.isTypeStruct().sym == t.isTypeStruct().sym)
{
result = MATCH.constant;
foreach (i, el; (*e.elements)[])
@@ -615,7 +615,7 @@ MATCH implicitConvTo(Expression e, Type t)
TY tynto = t.nextOf().ty;
if (tynto == tyn)
{
- if ((cast(TypeSArray)e.type).dim.toInteger() == (cast(TypeSArray)t).dim.toInteger())
+ if (e.type.isTypeSArray().dim.toInteger() == t.isTypeSArray().dim.toInteger())
{
result = MATCH.exact;
}
@@ -626,7 +626,7 @@ MATCH implicitConvTo(Expression e, Type t)
if (e.committed && tynto != tyn)
return;
size_t fromlen = e.numberOfCodeUnits(tynto);
- size_t tolen = cast(size_t)(cast(TypeSArray)t).dim.toInteger();
+ size_t tolen = cast(size_t)t.isTypeSArray().dim.toInteger();
if (tolen < fromlen)
return;
if (tolen != fromlen)
@@ -650,7 +650,7 @@ MATCH implicitConvTo(Expression e, Type t)
if (e.committed && tynto != tyn)
return;
size_t fromlen = e.numberOfCodeUnits(tynto);
- size_t tolen = cast(size_t)(cast(TypeSArray)t).dim.toInteger();
+ size_t tolen = cast(size_t)t.isTypeSArray().dim.toInteger();
if (tolen < fromlen)
return;
if (tolen != fromlen)
@@ -703,7 +703,7 @@ MATCH implicitConvTo(Expression e, Type t)
result = m;
return;
case Tenum:
- if ((cast(TypeEnum)tn).sym.isSpecial())
+ if (tn.isTypeEnum().sym.isSpecial())
{
/* Allow string literal -> const(wchar_t)[]
*/
@@ -1185,7 +1185,7 @@ MATCH implicitConvTo(Expression e, Type t)
* newargs
* arguments
* .init
- * 'member' and 'allocator' need to be pure.
+ * 'member' need to be pure.
*/
/* See if fail only because of mod bits
@@ -1219,30 +1219,25 @@ MATCH implicitConvTo(Expression e, Type t)
return;
}
- /* Check call to 'allocator', then 'member'
+ /* Check call to 'member'
*/
- FuncDeclaration fd = e.allocator;
- for (int count = 0; count < 2; ++count, (fd = e.member))
+ if (e.member)
{
- if (!fd)
- continue;
+ FuncDeclaration fd = e.member;
if (fd.errors || fd.type.ty != Tfunction)
return; // error
- TypeFunction tf = cast(TypeFunction)fd.type;
+ TypeFunction tf = fd.type.isTypeFunction();
if (tf.purity == PURE.impure)
return; // impure
- if (fd == e.member)
+ if (e.type.immutableOf().implicitConvTo(t) < MATCH.constant && e.type.addMod(MODFlags.shared_).implicitConvTo(t) < MATCH.constant && e.type.implicitConvTo(t.addMod(MODFlags.shared_)) < MATCH.constant)
{
- if (e.type.immutableOf().implicitConvTo(t) < MATCH.constant && e.type.addMod(MODFlags.shared_).implicitConvTo(t) < MATCH.constant && e.type.implicitConvTo(t.addMod(MODFlags.shared_)) < MATCH.constant)
- {
- return;
- }
- // Allow a conversion to immutable type, or
- // conversions of mutable types between thread-local and shared.
+ return;
}
+ // Allow a conversion to immutable type, or
+ // conversions of mutable types between thread-local and shared.
- Expressions* args = (fd == e.allocator) ? e.newargs : e.arguments;
+ Expressions* args = e.arguments;
size_t nparams = tf.parameterList.length;
// if TypeInfoArray was prepended
@@ -1306,10 +1301,10 @@ MATCH implicitConvTo(Expression e, Type t)
Type ntb = e.newtype.toBasetype();
if (ntb.ty == Tarray)
ntb = ntb.nextOf().toBasetype();
- if (ntb.ty == Tstruct)
+ if (auto ts = ntb.isTypeStruct())
{
// Don't allow nested structs - uplevel reference may not be convertible
- StructDeclaration sd = (cast(TypeStruct)ntb).sym;
+ StructDeclaration sd = ts.sym;
sd.size(e.loc); // resolve any forward references
if (sd.isNested())
return;
@@ -1318,11 +1313,11 @@ MATCH implicitConvTo(Expression e, Type t)
{
/* Zeros are implicitly convertible, except for special cases.
*/
- if (ntb.ty == Tclass)
+ if (auto tc = ntb.isTypeClass())
{
/* With new() must look at the class instance initializer.
*/
- ClassDeclaration cd = (cast(TypeClass)ntb).sym;
+ ClassDeclaration cd = tc.sym;
cd.size(e.loc); // resolve any forward references
@@ -1632,7 +1627,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
else if (tob.ty == Tvector && t1b.ty != Tvector)
{
//printf("test1 e = %s, e.type = %s, tob = %s\n", e.toChars(), e.type.toChars(), tob.toChars());
- TypeVector tv = cast(TypeVector)tob;
+ TypeVector tv = tob.isTypeVector();
result = new CastExp(e.loc, e, tv.elementType());
result = new VectorExp(e.loc, result, tob);
result = result.expressionSemantic(sc);
@@ -1704,7 +1699,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
// cast(U[])sa; // ==> cast(U[])sa[];
d_uns64 fsize = t1b.nextOf().size();
d_uns64 tsize = tob.nextOf().size();
- if (((cast(TypeSArray)t1b).dim.toInteger() * fsize) % tsize != 0)
+ if ((t1b.isTypeSArray().dim.toInteger() * fsize) % tsize != 0)
{
// copied from sarray_toDarray() in e2ir.c
e.error("cannot cast expression `%s` of type `%s` to `%s` since sizes don't line up", e.toChars(), e.type.toChars(), t.toChars());
@@ -1887,7 +1882,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
d_uns64 szx = tb.nextOf().size();
assert(szx <= 255);
se.sz = cast(ubyte)szx;
- se.len = cast(size_t)(cast(TypeSArray)tb).dim.toInteger();
+ se.len = cast(size_t)tb.isTypeSArray().dim.toInteger();
se.committed = 1;
se.type = t;
@@ -2061,9 +2056,9 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
assert(copied);
// See if need to truncate or extend the literal
- if (tb.ty == Tsarray)
+ if (auto tsa = tb.isTypeSArray())
{
- size_t dim2 = cast(size_t)(cast(TypeSArray)tb).dim.toInteger();
+ size_t dim2 = cast(size_t)tsa.dim.toInteger();
//printf("dim from = %d, to = %d\n", (int)se.len, (int)dim2);
// Changing dimensions
@@ -2181,7 +2176,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
return;
}
- TupleExp te = cast(TupleExp)e.copy();
+ TupleExp te = e.copy().isTupleExp();
te.e0 = e.e0 ? e.e0.copy() : null;
te.exps = e.exps.copy();
for (size_t i = 0; i < te.exps.dim; i++)
@@ -2243,9 +2238,8 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
}
else
{
- if (tb.ty == Tsarray)
+ if (auto tsa = tb.isTypeSArray())
{
- TypeSArray tsa = cast(TypeSArray)tb;
if (e.elements.dim != tsa.dim.toInteger())
goto L1;
}
@@ -2279,15 +2273,15 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray))
{
// Convert array literal to vector type
- TypeVector tv = cast(TypeVector)tb;
- TypeSArray tbase = cast(TypeSArray)tv.basetype;
+ TypeVector tv = tb.isTypeVector();
+ TypeSArray tbase = tv.basetype.isTypeSArray();
assert(tbase.ty == Tsarray);
const edim = e.elements.dim;
const tbasedim = tbase.dim.toInteger();
if (edim > tbasedim)
goto L1;
- ae = cast(ArrayLiteralExp)e.copy();
+ ae = e.copy().isArrayLiteralExp();
ae.type = tbase; // https://issues.dlang.org/show_bug.cgi?id=12642
ae.elements = e.elements.copy();
Type telement = tv.elementType();
@@ -2340,7 +2334,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
(*ae.values)[i] = ex;
ex = (*e.keys)[i];
- ex = ex.castTo(sc, (cast(TypeAArray)tb).index);
+ ex = ex.castTo(sc, tb.isTypeAArray().index);
(*ae.keys)[i] = ex;
}
ae.type = t;
@@ -2555,7 +2549,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
// Handle the cast from Tarray to Tsarray with CT-known slicing
- TypeSArray tsa = cast(TypeSArray)toStaticArrayType(e);
+ TypeSArray tsa = toStaticArrayType(e).isTypeSArray();
if (tsa && tsa.size(e.loc) == tb.size(e.loc))
{
/* Match if the sarray sizes are equal:
@@ -2569,7 +2563,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
result.type = t;
return;
}
- if (tsa && tsa.dim.equals((cast(TypeSArray)tb).dim))
+ if (tsa && tsa.dim.equals(tb.isTypeSArray().dim))
{
/* Match if the dimensions are equal
* with the implicit conversion of e.e1:
@@ -2577,7 +2571,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
*/
Type t1b = e.e1.type.toBasetype();
if (t1b.ty == Tsarray)
- t1b = tb.nextOf().sarrayOf((cast(TypeSArray)t1b).dim.toInteger());
+ t1b = tb.nextOf().sarrayOf(t1b.isTypeSArray().dim.toInteger());
else if (t1b.ty == Tarray)
t1b = tb.nextOf().arrayOf();
else if (t1b.ty == Tpointer)
@@ -2654,9 +2648,8 @@ Expression inferType(Expression e, Type t, int flag = 0)
Expression visitAar(AssocArrayLiteralExp aale)
{
Type tb = t.toBasetype();
- if (tb.ty == Taarray)
+ if (auto taa = tb.isTypeAArray())
{
- TypeAArray taa = cast(TypeAArray)tb;
Type ti = taa.index;
Type tv = taa.nextOf();
for (size_t i = 0; i < aale.keys.dim; i++)
@@ -2880,7 +2873,7 @@ Type typeMerge(Scope* sc, TOK op, ref Expression pe1, ref Expression pe2)
if (t1.mod != t2.mod &&
t1.ty == Tenum && t2.ty == Tenum &&
- (cast(TypeEnum)t1).sym == (cast(TypeEnum)t2).sym)
+ t1.isTypeEnum().sym == t2.isTypeEnum().sym)
{
ubyte mod = MODmerge(t1.mod, t2.mod);
t1 = t1.castMod(mod);
@@ -2950,8 +2943,8 @@ Lagain:
if (t1n.ty == Tfunction && t2n.ty == Tfunction)
{
- TypeFunction tf1 = cast(TypeFunction)t1n;
- TypeFunction tf2 = cast(TypeFunction)t2n;
+ TypeFunction tf1 = t1n.isTypeFunction();
+ TypeFunction tf2 = t2n.isTypeFunction();
tf1.purityLevel();
tf2.purityLevel();
@@ -3021,7 +3014,7 @@ Lagain:
return null;
}
- if ((t1.ty == Tsarray || t1.ty == Tarray) && (e2.op == TOK.null_ && t2.ty == Tpointer && t2.nextOf().ty == Tvoid || e2.op == TOK.arrayLiteral && t2.ty == Tsarray && t2.nextOf().ty == Tvoid && (cast(TypeSArray)t2).dim.toInteger() == 0 || isVoidArrayLiteral(e2, t1)))
+ if ((t1.ty == Tsarray || t1.ty == Tarray) && (e2.op == TOK.null_ && t2.ty == Tpointer && t2.nextOf().ty == Tvoid || e2.op == TOK.arrayLiteral && t2.ty == Tsarray && t2.nextOf().ty == Tvoid && t2.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e2, t1)))
{
/* (T[n] op void*) => T[]
* (T[] op void*) => T[]
@@ -3033,7 +3026,7 @@ Lagain:
return coerce(t1.nextOf().arrayOf());
}
- if ((t2.ty == Tsarray || t2.ty == Tarray) && (e1.op == TOK.null_ && t1.ty == Tpointer && t1.nextOf().ty == Tvoid || e1.op == TOK.arrayLiteral && t1.ty == Tsarray && t1.nextOf().ty == Tvoid && (cast(TypeSArray)t1).dim.toInteger() == 0 || isVoidArrayLiteral(e1, t2)))
+ if ((t2.ty == Tsarray || t2.ty == Tarray) && (e1.op == TOK.null_ && t1.ty == Tpointer && t1.nextOf().ty == Tvoid || e1.op == TOK.arrayLiteral && t1.ty == Tsarray && t1.nextOf().ty == Tvoid && t1.isTypeSArray().dim.toInteger() == 0 || isVoidArrayLiteral(e1, t2)))
{
/* (void* op T[n]) => T[]
* (void* op T[]) => T[]
@@ -3145,8 +3138,8 @@ Lagain:
if (t1.ty == Tclass && t2.ty == Tclass)
{
- TypeClass tc1 = cast(TypeClass)t1;
- TypeClass tc2 = cast(TypeClass)t2;
+ TypeClass tc1 = t1.isTypeClass();
+ TypeClass tc2 = t2.isTypeClass();
/* Pick 'tightest' type
*/
@@ -3164,7 +3157,7 @@ Lagain:
else
return null;
}
- else if (t1.ty == Tstruct && (cast(TypeStruct)t1).sym.aliasthis)
+ else if (t1.ty == Tstruct && t1.isTypeStruct().sym.aliasthis)
{
if (isRecursiveAliasThis(att1, e1.type))
return null;
@@ -3173,7 +3166,7 @@ Lagain:
t1 = e1.type;
continue;
}
- else if (t2.ty == Tstruct && (cast(TypeStruct)t2).sym.aliasthis)
+ else if (t2.ty == Tstruct && t2.isTypeStruct().sym.aliasthis)
{
if (isRecursiveAliasThis(att2, e2.type))
return null;
@@ -3200,8 +3193,8 @@ Lagain:
goto Lagain;
}
- TypeStruct ts1 = cast(TypeStruct)t1;
- TypeStruct ts2 = cast(TypeStruct)t2;
+ TypeStruct ts1 = t1.isTypeStruct();
+ TypeStruct ts2 = t2.isTypeStruct();
if (ts1.sym != ts2.sym)
{
if (!ts1.sym.aliasthis && !ts2.sym.aliasthis)
@@ -3253,7 +3246,7 @@ Lagain:
if (t1.ty == Tstruct || t2.ty == Tstruct)
{
- if (t1.ty == Tstruct && (cast(TypeStruct)t1).sym.aliasthis)
+ if (t1.ty == Tstruct && t1.isTypeStruct().sym.aliasthis)
{
if (isRecursiveAliasThis(att1, e1.type))
return null;
@@ -3263,7 +3256,7 @@ Lagain:
t = t1;
goto Lagain;
}
- if (t2.ty == Tstruct && (cast(TypeStruct)t2).sym.aliasthis)
+ if (t2.ty == Tstruct && t2.isTypeStruct().sym.aliasthis)
{
if (isRecursiveAliasThis(att2, e2.type))
return null;
@@ -3290,8 +3283,8 @@ Lagain:
// https://issues.dlang.org/show_bug.cgi?id=13841
// all vector types should have no common types between
// different vectors, even though their sizes are same.
- auto tv1 = cast(TypeVector)t1;
- auto tv2 = cast(TypeVector)t2;
+ auto tv1 = t1.isTypeVector();
+ auto tv2 = t2.isTypeVector();
if (!tv1.basetype.equals(tv2.basetype))
return null;
diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d
index 9c5f0da2f97..fb0e4fb53eb 100644
--- a/gcc/d/dmd/dclass.d
+++ b/gcc/d/dmd/dclass.d
@@ -228,151 +228,149 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
// For forward references
type = new TypeClass(this);
- if (id)
- {
- // Look for special class names
- if (id == Id.__sizeof || id == Id.__xalignof || id == Id._mangleof)
- error("illegal class name");
+ // Look for special class names
+ if (id == Id.__sizeof || id == Id.__xalignof || id == Id._mangleof)
+ error("illegal class name");
- // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
- if (id.toChars()[0] == 'T')
+ // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
+ if (id.toChars()[0] == 'T')
+ {
+ if (id == Id.TypeInfo)
{
- if (id == Id.TypeInfo)
- {
- if (!inObject)
- error("%s", msg);
- Type.dtypeinfo = this;
- }
- if (id == Id.TypeInfo_Class)
- {
- if (!inObject)
- error("%s", msg);
- Type.typeinfoclass = this;
- }
- if (id == Id.TypeInfo_Interface)
- {
- if (!inObject)
- error("%s", msg);
- Type.typeinfointerface = this;
- }
- if (id == Id.TypeInfo_Struct)
- {
- if (!inObject)
- error("%s", msg);
- Type.typeinfostruct = this;
- }
- if (id == Id.TypeInfo_Pointer)
- {
- if (!inObject)
- error("%s", msg);
- Type.typeinfopointer = this;
- }
- if (id == Id.TypeInfo_Array)
- {
- if (!inObject)
- error("%s", msg);
- Type.typeinfoarray = this;
- }
- if (id == Id.TypeInfo_StaticArray)
- {
- //if (!inObject)
- // Type.typeinfostaticarray.error("%s", msg);
- Type.typeinfostaticarray = this;
- }
- if (id == Id.TypeInfo_AssociativeArray)
- {
- if (!inObject)
- error("%s", msg);
- Type.typeinfoassociativearray = this;
- }
- if (id == Id.TypeInfo_Enum)
- {
- if (!inObject)
- error("%s", msg);
- Type.typeinfoenum = this;
- }
- if (id == Id.TypeInfo_Function)
- {
- if (!inObject)
- error("%s", msg);
- Type.typeinfofunction = this;
- }
- if (id == Id.TypeInfo_Delegate)
- {
- if (!inObject)
- error("%s", msg);
- Type.typeinfodelegate = this;
- }
- if (id == Id.TypeInfo_Tuple)
- {
- if (!inObject)
- error("%s", msg);
- Type.typeinfotypelist = this;
- }
- if (id == Id.TypeInfo_Const)
- {
- if (!inObject)
- error("%s", msg);
- Type.typeinfoconst = this;
- }
- if (id == Id.TypeInfo_Invariant)
- {
- if (!inObject)
- error("%s", msg);
- Type.typeinfoinvariant = this;
- }
- if (id == Id.TypeInfo_Shared)
- {
- if (!inObject)
- error("%s", msg);
- Type.typeinfoshared = this;
- }
- if (id == Id.TypeInfo_Wild)
- {
- if (!inObject)
- error("%s", msg);
- Type.typeinfowild = this;
- }
- if (id == Id.TypeInfo_Vector)
- {
- if (!inObject)
- error("%s", msg);
- Type.typeinfovector = this;
- }
+ if (!inObject)
+ error("%s", msg);
+ Type.dtypeinfo = this;
}
-
- if (id == Id.Object)
+ if (id == Id.TypeInfo_Class)
{
if (!inObject)
error("%s", msg);
- object = this;
+ Type.typeinfoclass = this;
}
-
- if (id == Id.Throwable)
+ if (id == Id.TypeInfo_Interface)
+ {
+ if (!inObject)
+ error("%s", msg);
+ Type.typeinfointerface = this;
+ }
+ if (id == Id.TypeInfo_Struct)
+ {
+ if (!inObject)
+ error("%s", msg);
+ Type.typeinfostruct = this;
+ }
+ if (id == Id.TypeInfo_Pointer)
+ {
+ if (!inObject)
+ error("%s", msg);
+ Type.typeinfopointer = this;
+ }
+ if (id == Id.TypeInfo_Array)
+ {
+ if (!inObject)
+ error("%s", msg);
+ Type.typeinfoarray = this;
+ }
+ if (id == Id.TypeInfo_StaticArray)
+ {
+ //if (!inObject)
+ // Type.typeinfostaticarray.error("%s", msg);
+ Type.typeinfostaticarray = this;
+ }
+ if (id == Id.TypeInfo_AssociativeArray)
+ {
+ if (!inObject)
+ error("%s", msg);
+ Type.typeinfoassociativearray = this;
+ }
+ if (id == Id.TypeInfo_Enum)
+ {
+ if (!inObject)
+ error("%s", msg);
+ Type.typeinfoenum = this;
+ }
+ if (id == Id.TypeInfo_Function)
{
if (!inObject)
error("%s", msg);
- throwable = this;
+ Type.typeinfofunction = this;
}
- if (id == Id.Exception)
+ if (id == Id.TypeInfo_Delegate)
{
if (!inObject)
error("%s", msg);
- exception = this;
+ Type.typeinfodelegate = this;
}
- if (id == Id.Error)
+ if (id == Id.TypeInfo_Tuple)
{
if (!inObject)
error("%s", msg);
- errorException = this;
+ Type.typeinfotypelist = this;
}
- if (id == Id.cpp_type_info_ptr)
+ if (id == Id.TypeInfo_Const)
{
if (!inObject)
error("%s", msg);
- cpp_type_info_ptr = this;
+ Type.typeinfoconst = this;
+ }
+ if (id == Id.TypeInfo_Invariant)
+ {
+ if (!inObject)
+ error("%s", msg);
+ Type.typeinfoinvariant = this;
+ }
+ if (id == Id.TypeInfo_Shared)
+ {
+ if (!inObject)
+ error("%s", msg);
+ Type.typeinfoshared = this;
+ }
+ if (id == Id.TypeInfo_Wild)
+ {
+ if (!inObject)
+ error("%s", msg);
+ Type.typeinfowild = this;
+ }
+ if (id == Id.TypeInfo_Vector)
+ {
+ if (!inObject)
+ error("%s", msg);
+ Type.typeinfovector = this;
}
}
+
+ if (id == Id.Object)
+ {
+ if (!inObject)
+ error("%s", msg);
+ object = this;
+ }
+
+ if (id == Id.Throwable)
+ {
+ if (!inObject)
+ error("%s", msg);
+ throwable = this;
+ }
+ if (id == Id.Exception)
+ {
+ if (!inObject)
+ error("%s", msg);
+ exception = this;
+ }
+ if (id == Id.Error)
+ {
+ if (!inObject)
+ error("%s", msg);
+ errorException = this;
+ }
+ if (id == Id.cpp_type_info_ptr)
+ {
+ if (!inObject)
+ error("%s", msg);
+ cpp_type_info_ptr = this;
+ }
+
baseok = Baseok.none;
}
@@ -444,32 +442,6 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
enum OFFSET_RUNTIME = 0x76543210;
enum OFFSET_FWDREF = 0x76543211;
- /*******************************************
- * Determine if 'this' is a base class of cd.
- */
- bool isBaseOf(ClassDeclaration cd, int* poffset)
- {
- //printf("ClassDeclaration.isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd.toChars());
- if (poffset)
- *poffset = 0;
- while (cd)
- {
- /* cd.baseClass might not be set if cd is forward referenced.
- */
- if (!cd.baseClass && cd.semanticRun < PASS.semanticdone && !cd.isInterfaceDeclaration())
- {
- cd.dsymbolSemantic(null);
- if (!cd.baseClass && cd.semanticRun < PASS.semanticdone)
- cd.error("base class is forward referenced by `%s`", toChars());
- }
-
- if (this == cd.baseClass)
- return true;
-
- cd = cd.baseClass;
- }
- return false;
- }
/*********************************************
* Determine if 'this' has complete base class information.
@@ -498,7 +470,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
if (!members || !symtab) // opaque or addMember is not yet done
{
// .stringof is always defined (but may be hidden by some other symbol)
- if (ident != Id.stringof && !(flags & IgnoreErrors))
+ if (ident != Id.stringof && !(flags & IgnoreErrors) && semanticRun < PASS.semanticdone)
error("is forward referenced when looking for `%s`", ident.toChars());
//*(char*)0=0;
return null;
@@ -510,33 +482,34 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
if (flags & SearchImportsOnly)
return s;
- if (!s)
+ if (s)
+ return s;
+
+ // Search bases classes in depth-first, left to right order
+ foreach (b; (*baseclasses)[])
{
- // Search bases classes in depth-first, left to right order
- for (size_t i = 0; i < baseclasses.dim; i++)
+ if (!b.sym)
+ continue;
+
+ if (!b.sym.symtab)
{
- BaseClass* b = (*baseclasses)[i];
- if (b.sym)
- {
- if (!b.sym.symtab)
- error("base `%s` is forward referenced", b.sym.ident.toChars());
- else
- {
- import dmd.access : symbolIsVisible;
-
- s = b.sym.search(loc, ident, flags);
- if (!s)
- continue;
- else if (s == this) // happens if s is nested in this and derives from this
- s = null;
- else if (!(flags & IgnoreSymbolVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(this, s))
- s = null;
- else
- break;
- }
- }
+ error("base `%s` is forward referenced", b.sym.ident.toChars());
+ continue;
}
+
+ import dmd.access : symbolIsVisible;
+
+ s = b.sym.search(loc, ident, flags);
+ if (!s)
+ continue;
+ else if (s == this) // happens if s is nested in this and derives from this
+ s = null;
+ else if (!(flags & IgnoreSymbolVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(this, s))
+ s = null;
+ else
+ break;
}
+
return s;
}
@@ -749,57 +722,59 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
// the first entry might be a ClassInfo
//printf("\t[%d] = %s\n", i, fd.toChars());
- if (ident == fd.ident && fd.type.covariant(tf) == 1)
+ if (ident != fd.ident || fd.type.covariant(tf) != 1)
{
- //printf("fd.parent.isClassDeclaration() = %p\n", fd.parent.isClassDeclaration());
- if (!fdmatch)
- {
- updateBestMatch(fd);
- continue;
- }
- if (fd == fdmatch)
- continue;
+ //printf("\t\t%d\n", fd.type.covariant(tf));
+ continue;
+ }
- {
- // Function type matching: exact > covariant
- MATCH m1 = tf.equals(fd.type) ? MATCH.exact : MATCH.nomatch;
- MATCH m2 = tf.equals(fdmatch.type) ? MATCH.exact : MATCH.nomatch;
- if (m1 > m2)
- {
- updateBestMatch(fd);
- continue;
- }
- else if (m1 < m2)
- continue;
- }
- {
- MATCH m1 = (tf.mod == fd.type.mod) ? MATCH.exact : MATCH.nomatch;
- MATCH m2 = (tf.mod == fdmatch.type.mod) ? MATCH.exact : MATCH.nomatch;
- if (m1 > m2)
- {
- updateBestMatch(fd);
- continue;
- }
- else if (m1 < m2)
- continue;
- }
- {
- // The way of definition: non-mixin > mixin
- MATCH m1 = fd.parent.isClassDeclaration() ? MATCH.exact : MATCH.nomatch;
- MATCH m2 = fdmatch.parent.isClassDeclaration() ? MATCH.exact : MATCH.nomatch;
- if (m1 > m2)
- {
- updateBestMatch(fd);
- continue;
- }
- else if (m1 < m2)
- continue;
- }
+ //printf("fd.parent.isClassDeclaration() = %p\n", fd.parent.isClassDeclaration());
+ if (!fdmatch)
+ {
+ updateBestMatch(fd);
+ continue;
+ }
+ if (fd == fdmatch)
+ continue;
- fdambig = fd;
- //printf("Lambig fdambig = %s %s [%s]\n", fdambig.toChars(), fdambig.type.toChars(), fdambig.loc.toChars());
+ {
+ // Function type matching: exact > covariant
+ MATCH m1 = tf.equals(fd.type) ? MATCH.exact : MATCH.nomatch;
+ MATCH m2 = tf.equals(fdmatch.type) ? MATCH.exact : MATCH.nomatch;
+ if (m1 > m2)
+ {
+ updateBestMatch(fd);
+ continue;
+ }
+ else if (m1 < m2)
+ continue;
}
- //else printf("\t\t%d\n", fd.type.covariant(tf));
+ {
+ MATCH m1 = (tf.mod == fd.type.mod) ? MATCH.exact : MATCH.nomatch;
+ MATCH m2 = (tf.mod == fdmatch.type.mod) ? MATCH.exact : MATCH.nomatch;
+ if (m1 > m2)
+ {
+ updateBestMatch(fd);
+ continue;
+ }
+ else if (m1 < m2)
+ continue;
+ }
+ {
+ // The way of definition: non-mixin > mixin
+ MATCH m1 = fd.parent.isClassDeclaration() ? MATCH.exact : MATCH.nomatch;
+ MATCH m2 = fdmatch.parent.isClassDeclaration() ? MATCH.exact : MATCH.nomatch;
+ if (m1 > m2)
+ {
+ updateBestMatch(fd);
+ continue;
+ }
+ else if (m1 < m2)
+ continue;
+ }
+
+ fdambig = fd;
+ //printf("Lambig fdambig = %s %s [%s]\n", fdambig.toChars(), fdambig.type.toChars(), fdambig.loc.toChars());
}
}
@@ -985,7 +960,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
return vtblsym;
}
- override final inout(ClassDeclaration) isClassDeclaration() inout
+ override final inout(ClassDeclaration) isClassDeclaration() inout @nogc nothrow pure @safe
{
return this;
}
@@ -1032,73 +1007,6 @@ extern (C++) final class InterfaceDeclaration : ClassDeclaration
return sc2;
}
- /*******************************************
- * Determine if 'this' is a base class of cd.
- * (Actually, if it is an interface supported by cd)
- * Output:
- * *poffset offset to start of class
- * OFFSET_RUNTIME must determine offset at runtime
- * Returns:
- * false not a base
- * true is a base
- */
- override bool isBaseOf(ClassDeclaration cd, int* poffset)
- {
- //printf("%s.InterfaceDeclaration.isBaseOf(cd = '%s')\n", toChars(), cd.toChars());
- assert(!baseClass);
- foreach (b; cd.interfaces)
- {
- //printf("\tX base %s\n", b.sym.toChars());
- if (this == b.sym)
- {
- //printf("\tfound at offset %d\n", b.offset);
- if (poffset)
- {
- // don't return incorrect offsets
- // https://issues.dlang.org/show_bug.cgi?id=16980
- *poffset = cd.sizeok == Sizeok.done ? b.offset : OFFSET_FWDREF;
- }
- // printf("\tfound at offset %d\n", b.offset);
- return true;
- }
- if (isBaseOf(b, poffset))
- return true;
- }
- if (cd.baseClass && isBaseOf(cd.baseClass, poffset))
- return true;
-
- if (poffset)
- *poffset = 0;
- return false;
- }
-
- bool isBaseOf(BaseClass* bc, int* poffset)
- {
- //printf("%s.InterfaceDeclaration.isBaseOf(bc = '%s')\n", toChars(), bc.sym.toChars());
- for (size_t j = 0; j < bc.baseInterfaces.length; j++)
- {
- BaseClass* b = &bc.baseInterfaces[j];
- //printf("\tY base %s\n", b.sym.toChars());
- if (this == b.sym)
- {
- //printf("\tfound at offset %d\n", b.offset);
- if (poffset)
- {
- *poffset = b.offset;
- }
- return true;
- }
- if (isBaseOf(b, poffset))
- {
- return true;
- }
- }
-
- if (poffset)
- *poffset = 0;
- return false;
- }
-
/*******************************************
*/
override const(char)* kind() const
@@ -1139,3 +1047,110 @@ extern (C++) final class InterfaceDeclaration : ClassDeclaration
v.visit(this);
}
}
+
+
+/**
+ * Returns whether `bc` implements `id`, including indirectly (`bc` implements an interfaces
+ * that inherits from `id`)
+ *
+ * Params:
+ * id = the interface
+ * bc = the base class
+ * poffset = out parameter, offset of the interface in an object
+ *
+ * Returns:
+ * true if the `bc` implements `id`, false otherwise
+ **/
+private bool baseClassImplementsInterface(InterfaceDeclaration id, BaseClass* bc, int* poffset)
+{
+ //printf("%s.InterfaceDeclaration.isBaseOf(bc = '%s')\n", toChars(), bc.sym.toChars());
+ for (size_t j = 0; j < bc.baseInterfaces.length; j++)
+ {
+ BaseClass* b = &bc.baseInterfaces[j];
+ //printf("\tY base %s\n", b.sym.toChars());
+ if (id == b.sym)
+ {
+ //printf("\tfound at offset %d\n", b.offset);
+ if (poffset)
+ {
+ *poffset = b.offset;
+ }
+ return true;
+ }
+ if (baseClassImplementsInterface(id, b, poffset))
+ {
+ return true;
+ }
+ }
+
+ if (poffset)
+ *poffset = 0;
+ return false;
+}
+
+/*******************************************
+ * Determine if `derived` is a base class of cd.
+ * Or, if `derived` is an interface, is it implemented by `cd`
+ * Params:
+ * derived = Potentially derived ClassDeclaration
+ * cd = Potential base class
+ * poffset = out parameter, offset to start of class. OFFSET_RUNTIME must determine offset at runtime
+ * Returns:
+ * false not a base
+ * true is a base
+ */
+extern(C++) bool isBaseOf(ClassDeclaration derived, ClassDeclaration cd, int* poffset)
+{
+ if (auto id = derived.isInterfaceDeclaration())
+ {
+ //printf("%s.InterfaceDeclaration.isBaseOf(cd = '%s')\n", toChars(), cd.toChars());
+ assert(!id.baseClass);
+ foreach (b; cd.interfaces)
+ {
+ //printf("\tX base %s\n", b.sym.toChars());
+ if (id == b.sym)
+ {
+ //printf("\tfound at offset %d\n", b.offset);
+ if (poffset)
+ {
+ // don't return incorrect offsets
+ // https://issues.dlang.org/show_bug.cgi?id=16980
+ *poffset = cd.sizeok == Sizeok.done ? b.offset : ClassDeclaration.OFFSET_FWDREF;
+ }
+ // printf("\tfound at offset %d\n", b.offset);
+ return true;
+ }
+ if (baseClassImplementsInterface(id, b, poffset))
+ return true;
+ }
+ if (cd.baseClass && id.isBaseOf(cd.baseClass, poffset))
+ return true;
+
+ if (poffset)
+ *poffset = 0;
+ return false;
+ }
+
+ //normal Class decl
+ //printf("ClassDeclaration.isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd.toChars());
+ if (poffset)
+ *poffset = 0;
+ while (cd)
+ {
+ /* cd.baseClass might not be set if cd is forward referenced.
+ */
+ if (!cd.baseClass && cd.semanticRun < PASS.semanticdone && !cd.isInterfaceDeclaration())
+ {
+ cd.dsymbolSemantic(null);
+ if (!cd.baseClass && cd.semanticRun < PASS.semanticdone)
+ cd.error("base class is forward referenced by `%s`", derived.toChars());
+ }
+
+ if (derived == cd.baseClass)
+ return true;
+
+ cd = cd.baseClass;
+ }
+ return false;
+
+}
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index 2135ef039dd..9426cf2343a 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -171,6 +171,13 @@ bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
MODtoChars(var.type.mod), p, var.toChars(), sc.func.toChars());
}
}
+ else if (fd.isStaticCtorDeclaration() && !fd.isSharedStaticCtorDeclaration() &&
+ var.type.isImmutable())
+ {
+ .error(loc, "%s %s `%s` initialization is not allowed in `static this`",
+ MODtoChars(var.type.mod), var.kind(), var.toChars());
+ errorSupplemental(loc, "Use `shared static this` instead.");
+ }
return result;
}
else
@@ -526,6 +533,12 @@ extern (C++) abstract class Declaration : Dsymbol
return (storage_class & STC.ref_) != 0;
}
+ /// Returns: Whether the variable is a reference, annotated with `out` or `ref`
+ final bool isReference() const pure nothrow @nogc @safe
+ {
+ return (storage_class & (STC.ref_ | STC.out_)) != 0;
+ }
+
final bool isFuture() const pure nothrow @nogc @safe
{
return (storage_class & STC.future) != 0;
@@ -536,7 +549,7 @@ extern (C++) abstract class Declaration : Dsymbol
return visibility;
}
- override final inout(Declaration) isDeclaration() inout
+ override final inout(Declaration) isDeclaration() inout pure nothrow @nogc @safe
{
return this;
}
@@ -1727,7 +1740,7 @@ extern (C++) class TypeInfoDeclaration : VarDeclaration
return buf.extractChars();
}
- override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout
+ override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout @nogc nothrow pure @safe
{
return this;
}
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 58f72c6e7a0..b44b6e14a55 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -134,6 +134,7 @@ public:
bool isIn() const { return (storage_class & STCin) != 0; }
bool isOut() const { return (storage_class & STCout) != 0; }
bool isRef() const { return (storage_class & STCref) != 0; }
+ bool isReference() const { return (storage_class & (STCref | STCout)) != 0; }
bool isFuture() const { return (storage_class & STCfuture) != 0; }
diff --git a/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d
index 2d449af9f7d..54467d8efd4 100644
--- a/gcc/d/dmd/denum.d
+++ b/gcc/d/dmd/denum.d
@@ -23,7 +23,6 @@ import dmd.dscope;
import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.expression;
-import dmd.expressionsem;
import dmd.globals;
import dmd.id;
import dmd.identifier;
@@ -142,121 +141,6 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
return visibility;
}
- /******************************
- * Get the value of the .max/.min property as an Expression.
- * Lazily computes the value and caches it in maxval/minval.
- * Reports any errors.
- * Params:
- * loc = location to use for error messages
- * id = Id::max or Id::min
- * Returns:
- * corresponding value of .max/.min
- */
- Expression getMaxMinValue(const ref Loc loc, Identifier id)
- {
- //printf("EnumDeclaration::getMaxValue()\n");
-
- static Expression pvalToResult(Expression e, const ref Loc loc)
- {
- if (e.op != TOK.error)
- {
- e = e.copy();
- e.loc = loc;
- }
- return e;
- }
-
- Expression* pval = (id == Id.max) ? &maxval : &minval;
-
- Expression errorReturn()
- {
- *pval = ErrorExp.get();
- return *pval;
- }
-
- if (inuse)
- {
- error(loc, "recursive definition of `.%s` property", id.toChars());
- return errorReturn();
- }
- if (*pval)
- return pvalToResult(*pval, loc);
-
- if (_scope)
- dsymbolSemantic(this, _scope);
- if (errors)
- return errorReturn();
- if (!members)
- {
- if (isSpecial())
- {
- /* Allow these special enums to not need a member list
- */
- return memtype.getProperty(_scope, loc, id, 0);
- }
-
- error(loc, "is opaque and has no `.%s`", id.toChars());
- return errorReturn();
- }
- if (!(memtype && memtype.isintegral()))
- {
- error(loc, "has no `.%s` property because base type `%s` is not an integral type", id.toChars(), memtype ? memtype.toChars() : "");
- return errorReturn();
- }
-
- bool first = true;
- for (size_t i = 0; i < members.dim; i++)
- {
- EnumMember em = (*members)[i].isEnumMember();
- if (!em)
- continue;
- if (em.errors)
- {
- errors = true;
- continue;
- }
-
- if (em.semanticRun < PASS.semanticdone)
- {
- em.error("is forward referenced looking for `.%s`", id.toChars());
- errors = true;
- continue;
- }
-
- if (first)
- {
- *pval = em.value;
- first = false;
- }
- else
- {
- /* In order to work successfully with UDTs,
- * build expressions to do the comparisons,
- * and let the semantic analyzer and constant
- * folder give us the result.
- */
-
- /* Compute:
- * if (e > maxval)
- * maxval = e;
- */
- Expression e = em.value;
- Expression ec = new CmpExp(id == Id.max ? TOK.greaterThan : TOK.lessThan, em.loc, e, *pval);
- inuse++;
- ec = ec.expressionSemantic(em._scope);
- inuse--;
- ec = ec.ctfeInterpret();
- if (ec.op == TOK.error)
- {
- errors = true;
- continue;
- }
- if (ec.toInteger())
- *pval = e;
- }
- }
- return errors ? errorReturn() : pvalToResult(*pval, loc);
- }
/****************
* Determine if enum is a special one.
@@ -414,23 +298,6 @@ extern (C++) final class EnumMember : VarDeclaration
return "enum member";
}
- Expression getVarExp(const ref Loc loc, Scope* sc)
- {
- dsymbolSemantic(this, sc);
- if (errors)
- return ErrorExp.get();
- checkDisabled(loc, sc);
-
- if (depdecl && !depdecl._scope)
- depdecl._scope = sc;
- checkDeprecated(loc, sc);
-
- if (errors)
- return ErrorExp.get();
- Expression e = new VarExp(loc, this);
- return e.expressionSemantic(sc);
- }
-
override inout(EnumMember) isEnumMember() inout
{
return this;
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 853758a7197..541fac7dfb4 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -351,7 +351,7 @@ public:
extern (C++) void pop(VarDeclaration v)
{
assert(!v.isDataseg() || v.isCTFE());
- assert(!(v.storage_class & (STC.ref_ | STC.out_)));
+ assert(!v.isReference());
const oldid = v.ctfeAdrOnStack;
v.ctfeAdrOnStack = cast(uint)cast(size_t)savedId[oldid];
if (v.ctfeAdrOnStack == values.dim - 1)
@@ -2132,7 +2132,7 @@ public:
errorSupplemental(vie.var.loc, "`%s` was uninitialized and used before set", vie.var.toChars());
return CTFEExp.cantexp;
}
- if (goal != CTFEGoal.LValue && (v.isRef() || v.isOut()))
+ if (goal != CTFEGoal.LValue && v.isReference())
e = interpret(e, istate, goal);
}
if (!e)
@@ -2742,12 +2742,6 @@ public:
{
printf("%s NewExp::interpret() %s\n", e.loc.toChars(), e.toChars());
}
- if (e.allocator)
- {
- e.error("member allocators not supported by CTFE");
- result = CTFEExp.cantexp;
- return;
- }
Expression epre = interpret(pue, e.argprefix, istate, CTFEGoal.Nothing);
if (exceptionOrCant(epre))
@@ -6139,6 +6133,9 @@ public:
return;
}
+ if (result.isStringExp())
+ return;
+
if (result.op != TOK.address)
{
if (result.op == TOK.null_)
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 841fff6c485..768eaa05a08 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -67,7 +67,7 @@ enum package_di = "package." ~ hdr_ext;
private const(char)[] lookForSourceFile(const char[] filename, const char*[] path)
{
//printf("lookForSourceFile(`%.*s`)\n", cast(int)filename.length, filename.ptr);
- /* Search along path[] for .di file, then .d file.
+ /* Search along path[] for .di file, then .d file, then .i file, then .c file.
*/
const sdi = FileName.forceExt(filename, hdr_ext);
if (FileName.exists(sdi) == 1)
@@ -79,6 +79,11 @@ private const(char)[] lookForSourceFile(const char[] filename, const char*[] pat
return sd;
scope(exit) FileName.free(sd.ptr);
+ const si = FileName.forceExt(filename, i_ext);
+ if (FileName.exists(si) == 1)
+ return si;
+ scope(exit) FileName.free(si.ptr);
+
const sc = FileName.forceExt(filename, c_ext);
if (FileName.exists(sc) == 1)
return sc;
@@ -120,6 +125,12 @@ private const(char)[] lookForSourceFile(const char[] filename, const char*[] pat
}
FileName.free(n.ptr);
+ n = FileName.combine(p, si);
+ if (FileName.exists(n) == 1) {
+ return n;
+ }
+ FileName.free(n.ptr);
+
n = FileName.combine(p, sc);
if (FileName.exists(n) == 1) {
return n;
@@ -554,6 +565,7 @@ extern (C++) final class Module : Package
else if (!FileName.equalsExt(srcfilename, mars_ext) &&
!FileName.equalsExt(srcfilename, hdr_ext) &&
!FileName.equalsExt(srcfilename, c_ext) &&
+ !FileName.equalsExt(srcfilename, i_ext) &&
!FileName.equalsExt(srcfilename, dd_ext))
{
@@ -1041,8 +1053,9 @@ extern (C++) final class Module : Package
}
/* If it has the extension ".c", it is a "C" file.
+ * If it has the extension ".i", it is a preprocessed "C" file.
*/
- if (FileName.equalsExt(arg, c_ext))
+ if (FileName.equalsExt(arg, c_ext) || FileName.equalsExt(arg, i_ext))
{
isCFile = true;
@@ -1086,6 +1099,8 @@ extern (C++) final class Module : Package
foreach (id; md.packages[1 .. $]) // [b, c]
{
p = cast(Package) p.symtab.lookup(id);
+ if (p is null)
+ break;
addAccessiblePackage(p, Visibility(Visibility.Kind.private_));
}
}
diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d
index 10ea91188e4..cddd08b4bab 100644
--- a/gcc/d/dmd/dstruct.d
+++ b/gcc/d/dmd/dstruct.d
@@ -24,14 +24,12 @@ import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.errors;
import dmd.expression;
-import dmd.expressionsem;
import dmd.func;
import dmd.globals;
import dmd.id;
import dmd.identifier;
import dmd.mtype;
import dmd.opover;
-import dmd.semantic3;
import dmd.target;
import dmd.tokens;
import dmd.typesem;
@@ -248,58 +246,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration
return sd;
}
- final void semanticTypeInfoMembers()
- {
- if (xeq &&
- xeq._scope &&
- xeq.semanticRun < PASS.semantic3done)
- {
- uint errors = global.startGagging();
- xeq.semantic3(xeq._scope);
- if (global.endGagging(errors))
- xeq = xerreq;
- }
-
- if (xcmp &&
- xcmp._scope &&
- xcmp.semanticRun < PASS.semantic3done)
- {
- uint errors = global.startGagging();
- xcmp.semantic3(xcmp._scope);
- if (global.endGagging(errors))
- xcmp = xerrcmp;
- }
-
- FuncDeclaration ftostr = search_toString(this);
- if (ftostr &&
- ftostr._scope &&
- ftostr.semanticRun < PASS.semantic3done)
- {
- ftostr.semantic3(ftostr._scope);
- }
-
- if (xhash &&
- xhash._scope &&
- xhash.semanticRun < PASS.semantic3done)
- {
- xhash.semantic3(xhash._scope);
- }
-
- if (postblit &&
- postblit._scope &&
- postblit.semanticRun < PASS.semantic3done)
- {
- postblit.semantic3(postblit._scope);
- }
-
- if (dtor &&
- dtor._scope &&
- dtor.semanticRun < PASS.semantic3done)
- {
- dtor.semantic3(dtor._scope);
- }
- }
-
override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
{
//printf("%s.StructDeclaration::search('%s', flags = x%x)\n", toChars(), ident.toChars(), flags);
@@ -309,7 +255,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration
if (!members || !symtab) // opaque or semantic() is not yet called
{
// .stringof is always defined (but may be hidden by some other symbol)
- if(ident != Id.stringof && !(flags & IgnoreErrors))
+ if(ident != Id.stringof && !(flags & IgnoreErrors) && semanticRun < PASS.semanticdone)
error("is forward referenced when looking for `%s`", ident.toChars());
return null;
}
@@ -415,117 +361,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration
argTypes = target.toArgTypes(type);
}
- /***************************************
- * Fit elements[] to the corresponding types of the struct's fields.
- *
- * Params:
- * loc = location to use for error messages
- * sc = context
- * elements = explicit arguments used to construct object
- * stype = the constructed object type.
- * Returns:
- * false if any errors occur,
- * otherwise true and elements[] are rewritten for the output.
- */
- final bool fit(const ref Loc loc, Scope* sc, Expressions* elements, Type stype)
- {
- if (!elements)
- return true;
-
- const nfields = nonHiddenFields();
- size_t offset = 0;
- for (size_t i = 0; i < elements.dim; i++)
- {
- Expression e = (*elements)[i];
- if (!e)
- continue;
-
- e = resolveProperties(sc, e);
- if (i >= nfields)
- {
- if (i <= fields.dim && e.op == TOK.null_)
- {
- // CTFE sometimes creates null as hidden pointer; we'll allow this.
- continue;
- }
- .error(loc, "more initializers than fields (%zu) of `%s`", nfields, toChars());
- return false;
- }
- VarDeclaration v = fields[i];
- if (v.offset < offset)
- {
- .error(loc, "overlapping initialization for `%s`", v.toChars());
- if (!isUnionDeclaration())
- {
- enum errorMsg = "`struct` initializers that contain anonymous unions" ~
- " must initialize only the first member of a `union`. All subsequent" ~
- " non-overlapping fields are default initialized";
- .errorSupplemental(loc, errorMsg);
- }
- return false;
- }
- offset = cast(uint)(v.offset + v.type.size());
-
- Type t = v.type;
- if (stype)
- t = t.addMod(stype.mod);
- Type origType = t;
- Type tb = t.toBasetype();
-
- const hasPointers = tb.hasPointers();
- if (hasPointers)
- {
- if ((stype.alignment() < target.ptrsize ||
- (v.offset & (target.ptrsize - 1))) &&
- (sc.func && sc.func.setUnsafe()))
- {
- .error(loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code",
- toChars(), v.toChars());
- return false;
- }
- }
-
- /* Look for case of initializing a static array with a too-short
- * string literal, such as:
- * char[5] foo = "abc";
- * Allow this by doing an explicit cast, which will lengthen the string
- * literal.
- */
- if (e.op == TOK.string_ && tb.ty == Tsarray)
- {
- StringExp se = cast(StringExp)e;
- Type typeb = se.type.toBasetype();
- TY tynto = tb.nextOf().ty;
- if (!se.committed &&
- (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
- se.numberOfCodeUnits(tynto) < (cast(TypeSArray)tb).dim.toInteger())
- {
- e = se.castTo(sc, t);
- goto L1;
- }
- }
-
- while (!e.implicitConvTo(t) && tb.ty == Tsarray)
- {
- /* Static array initialization, as in:
- * T[3][5] = e;
- */
- t = tb.nextOf();
- tb = t.toBasetype();
- }
- if (!e.implicitConvTo(t))
- t = origType; // restore type for better diagnostic
-
- e = e.implicitCastTo(sc, t);
- L1:
- if (e.op == TOK.error)
- return false;
-
- (*elements)[i] = doCopyOrMove(sc, e);
- }
- return true;
- }
-
/***************************************
* Determine if struct is POD (Plain Old Data).
*
@@ -580,7 +415,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration
return (ispod == StructPOD.yes);
}
- override final inout(StructDeclaration) isStructDeclaration() inout
+ override final inout(StructDeclaration) isStructDeclaration() inout @nogc nothrow pure @safe
{
return this;
}
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index 09d8dc67e8b..a90ed019a5b 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -17,6 +17,7 @@ import core.stdc.string;
import dmd.aggregate;
import dmd.aliasthis;
+import dmd.apply;
import dmd.arraytypes;
import dmd.astcodegen;
import dmd.astenums;
@@ -1977,18 +1978,23 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}
}
- ed.semanticRun = PASS.semanticdone;
-
if (!ed.members) // enum ident : memtype;
+ {
+ ed.semanticRun = PASS.semanticdone;
return;
+ }
if (ed.members.dim == 0)
{
ed.error("enum `%s` must have at least one member", ed.toChars());
ed.errors = true;
+ ed.semanticRun = PASS.semanticdone;
return;
}
+ if (!(sc.flags & SCOPE.Cfile)) // C enum remains incomplete until members are done
+ ed.semanticRun = PASS.semanticdone;
+
Module.dprogress++;
Scope* sce;
@@ -2017,6 +2023,69 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
*/
addEnumMembers(ed, sc, sc.getScopesym());
+ if (sc.flags & SCOPE.Cfile)
+ {
+ /* C11 6.7.2.2
+ */
+ ed.memtype = Type.tint32; // C11 6.7.2.2-4 implementation defined
+ int nextValue = 0; // C11 6.7.2.2-3 first member value defaults to 0
+
+ void emSemantic(EnumMember em, ref int nextValue)
+ {
+ static void errorReturn(EnumMember em)
+ {
+ em.errors = true;
+ em.semanticRun = PASS.semanticdone;
+ }
+
+ em.semanticRun = PASS.semantic;
+ em.type = Type.tint32;
+ em.linkage = LINK.c;
+ em.storage_class |= STC.manifest;
+ if (em.value)
+ {
+ Expression e = em.value;
+ assert(e.dyncast() == DYNCAST.expression);
+ e = e.expressionSemantic(sc);
+ e = resolveProperties(sc, e);
+ e = e.integralPromotions(sc);
+ e = e.ctfeInterpret();
+ if (e.op == TOK.error)
+ return errorReturn(em);
+ auto ie = e.isIntegerExp();
+ if (!ie)
+ {
+ // C11 6.7.2.2-2
+ em.error("enum member must be an integral constant expression, not `%s` of type `%s`", e.toChars(), e.type.toChars());
+ return errorReturn(em);
+ }
+ const sinteger_t v = ie.toInteger();
+ if (v < int.min || v > uint.max)
+ {
+ // C11 6.7.2.2-2
+ em.error("enum member value `%s` does not fit in an `int`", e.toChars());
+ return errorReturn(em);
+ }
+ em.value = new IntegerExp(em.loc, cast(int)v, Type.tint32);
+ nextValue = cast(int)v;
+ }
+ else
+ {
+ em.value = new IntegerExp(em.loc, nextValue, Type.tint32);
+ }
+ ++nextValue; // C11 6.7.2.2-3 add 1 to value of previous enumeration constant
+ em.semanticRun = PASS.semanticdone;
+ }
+
+ ed.members.foreachDsymbol( (s)
+ {
+ if (EnumMember em = s.isEnumMember())
+ emSemantic(em, nextValue);
+ });
+ ed.semanticRun = PASS.semanticdone;
+ return;
+ }
+
ed.members.foreachDsymbol( (s)
{
if (EnumMember em = s.isEnumMember())
@@ -4146,55 +4215,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
override void visit(NewDeclaration nd)
{
//printf("NewDeclaration::semantic()\n");
-
- // `@disable new();` should not be deprecated
- if (!nd.isDisabled())
- {
- // @@@DEPRECATED_2.091@@@
- // Made an error in 2.087.
- // Should be removed in 2.091
- error(nd.loc, "class allocators are obsolete, consider moving the allocation strategy outside of the class");
- }
-
if (nd.semanticRun >= PASS.semanticdone)
return;
- if (nd._scope)
- {
- sc = nd._scope;
- nd._scope = null;
- }
-
- nd.parent = sc.parent;
- Dsymbol p = nd.parent.pastMixin();
- if (!p.isAggregateDeclaration())
- {
- error(nd.loc, "allocator can only be a member of aggregate, not %s `%s`", p.kind(), p.toChars());
- nd.type = Type.terror;
- nd.errors = true;
- return;
- }
- Type tret = Type.tvoid.pointerTo();
if (!nd.type)
- nd.type = new TypeFunction(nd.parameterList, tret, LINK.d, nd.storage_class);
-
- nd.type = nd.type.typeSemantic(nd.loc, sc);
-
- // allow for `@disable new();` to force users of a type to use an external allocation strategy
- if (!nd.isDisabled())
- {
- // Check that there is at least one argument of type size_t
- TypeFunction tf = nd.type.toTypeFunction();
- if (tf.parameterList.length < 1)
- {
- nd.error("at least one argument of type `size_t` expected");
- }
- else
- {
- Parameter fparam = tf.parameterList[0];
- if (!fparam.type.equals(Type.tsize_t))
- nd.error("first argument must be type `size_t`, not `%s`", fparam.type.toChars());
- }
- }
+ nd.type = new TypeFunction(ParameterList(), Type.tvoid.pointerTo(), LINK.d, nd.storage_class);
funcDeclarationSemantic(nd);
}
@@ -4323,7 +4347,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
/* Look for special member functions.
*/
- sd.aggNew = cast(NewDeclaration)sd.search(Loc.initial, Id.classNew);
+ sd.disableNew = sd.search(Loc.initial, Id.classNew) !is null;
// Look for the constructor
sd.ctor = sd.searchCtor();
@@ -4916,7 +4940,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
* They must be in this class, not in a base class.
*/
// Can be in base class
- cldec.aggNew = cast(NewDeclaration)cldec.search(Loc.initial, Id.classNew);
+ cldec.disableNew = cldec.search(Loc.initial, Id.classNew) !is null;
// Look for the constructor
cldec.ctor = cldec.searchCtor();
@@ -6475,3 +6499,91 @@ private void aliasAssignSemantic(AliasAssign ds, Scope* sc)
ds.semanticRun = PASS.semanticdone;
}
+
+/***************************************
+ * Find all instance fields in `ad`, then push them into `fields`.
+ *
+ * Runs semantic() for all instance field variables, but also
+ * the field types can remain yet not resolved forward references,
+ * except direct recursive definitions.
+ * After the process sizeok is set to Sizeok.fwd.
+ *
+ * Params:
+ * ad = the AggregateDeclaration to examine
+ * Returns:
+ * false if any errors occur.
+ */
+bool determineFields(AggregateDeclaration ad)
+{
+ if (ad._scope)
+ dsymbolSemantic(ad, null);
+ if (ad.sizeok != Sizeok.none)
+ return true;
+
+ //printf("determineFields() %s, fields.dim = %d\n", toChars(), fields.dim);
+ // determineFields can be called recursively from one of the fields's v.semantic
+ ad.fields.setDim(0);
+
+ static int func(Dsymbol s, AggregateDeclaration ad)
+ {
+ auto v = s.isVarDeclaration();
+ if (!v)
+ return 0;
+ if (v.storage_class & STC.manifest)
+ return 0;
+
+ if (v.semanticRun < PASS.semanticdone)
+ v.dsymbolSemantic(null);
+ // Return in case a recursive determineFields triggered by v.semantic already finished
+ if (ad.sizeok != Sizeok.none)
+ return 1;
+
+ if (v.aliassym)
+ return 0; // If this variable was really a tuple, skip it.
+
+ if (v.storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared | STC.manifest | STC.ctfe | STC.templateparameter))
+ return 0;
+ if (!v.isField() || v.semanticRun < PASS.semanticdone)
+ return 1; // unresolvable forward reference
+
+ ad.fields.push(v);
+
+ if (v.storage_class & STC.ref_)
+ return 0;
+ auto tv = v.type.baseElemOf();
+ if (auto tvs = tv.isTypeStruct())
+ {
+ if (ad == tvs.sym)
+ {
+ const(char)* psz = (v.type.toBasetype().ty == Tsarray) ? "static array of " : "";
+ ad.error("cannot have field `%s` with %ssame struct type", v.toChars(), psz);
+ ad.type = Type.terror;
+ ad.errors = true;
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ if (ad.members)
+ {
+ for (size_t i = 0; i < ad.members.dim; i++)
+ {
+ auto s = (*ad.members)[i];
+ if (s.apply(&func, ad))
+ {
+ if (ad.sizeok != Sizeok.none)
+ {
+ // recursive determineFields already finished
+ return true;
+ }
+ return false;
+ }
+ }
+ }
+
+ if (ad.sizeok != Sizeok.done)
+ ad.sizeok = Sizeok.fwd;
+
+ return true;
+}
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index 524f62484a9..60058977701 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -1842,7 +1842,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
// https://issues.dlang.org/show_bug.cgi?id=12876
// Optimize argument to allow CT-known length matching
- farg = farg.optimize(WANTvalue, (fparam.storageClass & (STC.ref_ | STC.out_)) != 0);
+ farg = farg.optimize(WANTvalue, fparam.isReference());
//printf("farg = %s %s\n", farg.type.toChars(), farg.toChars());
RootObject oarg = farg;
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index 00f8a0e61b1..867e7802913 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -271,6 +271,9 @@ public:
/// Processing a type that can be forward referenced
bool forwarding;
+
+ /// Inside of an anonymous struct/union (AnonDeclaration)
+ bool inAnonymousDecl;
}
/// Informations about the current context in the AST
@@ -378,7 +381,7 @@ public:
private void writeProtection(const AST.Visibility.Kind kind)
{
// Don't write visibility for global declarations
- if (!adparent)
+ if (!adparent || inAnonymousDecl)
return;
string token;
@@ -518,20 +521,15 @@ public:
{
debug (Debug_DtoH)
{
- printf("[AST.Dsymbol enter] %s\n", s.toChars());
+ mixin(traceVisit!s);
import dmd.asttypename;
printf("[AST.Dsymbol enter] %s\n", s.astTypeName().ptr);
- scope(exit) printf("[AST.Dsymbol exit] %s\n", s.toChars());
}
}
override void visit(AST.Import i)
{
- debug (Debug_DtoH)
- {
- printf("[AST.Import enter] %s\n", i.toChars());
- scope(exit) printf("[AST.Import exit] %s\n", i.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!i);
/// Writes `using <alias_> = <sym.ident>` into `buf`
const(char*) writeImport(AST.Dsymbol sym, const Identifier alias_)
@@ -644,11 +642,8 @@ public:
override void visit(AST.AttribDeclaration pd)
{
- debug (Debug_DtoH)
- {
- printf("[AST.AttribDeclaration enter] %s\n", pd.toChars());
- scope(exit) printf("[AST.AttribDeclaration exit] %s\n", pd.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!pd);
+
Dsymbols* decl = pd.include(null);
if (!decl)
return;
@@ -662,11 +657,8 @@ public:
override void visit(AST.StorageClassDeclaration scd)
{
- debug (Debug_DtoH)
- {
- printf("[AST.StorageClassDeclaration enter] %s\n", scd.toChars());
- scope(exit) printf("[AST.StorageClassDeclaration exit] %s\n", scd.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!scd);
+
const stcStash = this.storageClass;
this.storageClass |= scd.stc;
visit(cast(AST.AttribDeclaration) scd);
@@ -675,11 +667,8 @@ public:
override void visit(AST.LinkDeclaration ld)
{
- debug (Debug_DtoH)
- {
- printf("[AST.LinkDeclaration enter] %s\n", ld.toChars());
- scope(exit) printf("[AST.LinkDeclaration exit] %s\n", ld.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!ld);
+
auto save = linkage;
linkage = ld.linkage;
visit(cast(AST.AttribDeclaration)ld);
@@ -688,6 +677,8 @@ public:
override void visit(AST.CPPMangleDeclaration md)
{
+ debug (Debug_DtoH) mixin(traceVisit!md);
+
const oldLinkage = this.linkage;
this.linkage = LINK.cpp;
visit(cast(AST.AttribDeclaration) md);
@@ -696,11 +687,8 @@ public:
override void visit(AST.Module m)
{
- debug (Debug_DtoH)
- {
- printf("[AST.Module enter] %s\n", m.toChars());
- scope(exit) printf("[AST.Module exit] %s\n", m.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!m);
+
foreach (s; *m.members)
{
if (s.visible().kind < AST.Visibility.Kind.public_)
@@ -711,11 +699,8 @@ public:
override void visit(AST.FuncDeclaration fd)
{
- debug (Debug_DtoH)
- {
- printf("[AST.FuncDeclaration enter] %s\n", fd.toChars());
- scope(exit) printf("[AST.FuncDeclaration exit] %s\n", fd.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!fd);
+
if (cast(void*)fd in visited)
return;
// printf("FuncDeclaration %s %s\n", fd.toPrettyChars(), fd.type.toChars());
@@ -840,20 +825,13 @@ public:
override void visit(AST.UnitTestDeclaration utd)
{
- debug (Debug_DtoH)
- {
- printf("[AST.UnitTestDeclaration enter] %s\n", utd.toChars());
- scope(exit) printf("[AST.UnitTestDeclaration exit] %s\n", utd.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!utd);
}
override void visit(AST.VarDeclaration vd)
{
- debug (Debug_DtoH)
- {
- printf("[AST.VarDeclaration enter] %s\n", vd.toChars());
- scope(exit) printf("[AST.VarDeclaration exit] %s\n", vd.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!vd);
+
if (!shouldEmit(vd))
return;
@@ -1006,20 +984,12 @@ public:
override void visit(AST.TypeInfoDeclaration tid)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TypeInfoDeclaration enter] %s\n", tid.toChars());
- scope(exit) printf("[AST.TypeInfoDeclaration exit] %s\n", tid.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!tid);
}
override void visit(AST.AliasDeclaration ad)
{
- debug (Debug_DtoH)
- {
- printf("[AST.AliasDeclaration enter] %s\n", ad.toChars());
- scope(exit) printf("[AST.AliasDeclaration exit] %s\n", ad.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!ad);
if (!shouldEmit(ad))
return;
@@ -1141,11 +1111,13 @@ public:
override void visit(AST.Nspace ns)
{
+ debug (Debug_DtoH) mixin(traceVisit!ns);
handleNspace(ns, ns.members);
}
override void visit(AST.CPPNamespaceDeclaration ns)
{
+ debug (Debug_DtoH) mixin(traceVisit!ns);
handleNspace(ns, ns.decl);
}
@@ -1169,11 +1141,11 @@ public:
override void visit(AST.AnonDeclaration ad)
{
- debug (Debug_DtoH)
- {
- printf("[AST.AnonDeclaration enter] %s\n", ad.toChars());
- scope(exit) printf("[AST.AnonDeclaration exit] %s\n", ad.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!ad);
+
+ const anonStash = inAnonymousDecl;
+ inAnonymousDecl = true;
+ scope (exit) inAnonymousDecl = anonStash;
buf.writestringln(ad.isunion ? "union" : "struct");
buf.writestringln("{");
@@ -1201,11 +1173,7 @@ public:
override void visit(AST.StructDeclaration sd)
{
- debug (Debug_DtoH)
- {
- printf("[AST.StructDeclaration enter] %s\n", sd.toChars());
- scope(exit) printf("[AST.StructDeclaration exit] %s\n", sd.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!sd);
if (!shouldEmit(sd))
return;
@@ -1407,11 +1375,7 @@ public:
override void visit(AST.ClassDeclaration cd)
{
- debug (Debug_DtoH)
- {
- printf("[AST.ClassDeclaration enter] %s\n", cd.toChars());
- scope(exit) printf("[AST.ClassDeclaration exit] %s\n", cd.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!cd);
if (!shouldEmit(cd))
return;
@@ -1475,11 +1439,8 @@ public:
override void visit(AST.EnumDeclaration ed)
{
- debug (Debug_DtoH)
- {
- printf("[AST.EnumDeclaration enter] %s\n", ed.toChars());
- scope(exit) printf("[AST.EnumDeclaration exit] %s\n", ed.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!ed);
+
if (!shouldEmit(ed))
return;
@@ -1749,32 +1710,21 @@ public:
override void visit(AST.Type t)
{
- debug (Debug_DtoH)
- {
- printf("[AST.Type enter] %s\n", t.toChars());
- scope(exit) printf("[AST.Type exit] %s\n", t.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!t);
printf("Invalid type: %s\n", t.toPrettyChars());
assert(0);
}
override void visit(AST.TypeNoreturn t)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TypeNoreturn enter] %s\n", t.toChars());
- scope(exit) printf("[AST.TypeNoreturn exit] %s\n", t.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!t);
+
buf.writestring("/* noreturn */ char");
}
override void visit(AST.TypeIdentifier t)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TypeIdentifier enter] %s\n", t.toChars());
- scope(exit) printf("[AST.TypeIdentifier exit] %s\n", t.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!t);
// Try to resolve the referenced symbol
if (auto sym = findSymbol(t.ident))
@@ -1802,11 +1752,8 @@ public:
override void visit(AST.TypeNull t)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TypeNull enter] %s\n", t.toChars());
- scope(exit) printf("[AST.TypeNull exit] %s\n", t.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!t);
+
if (global.params.cplusplus >= CppStdRevision.cpp11)
buf.writestring("nullptr_t");
else
@@ -1816,11 +1763,8 @@ public:
override void visit(AST.TypeTypeof t)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TypeInstance enter] %s\n", t.toChars());
- scope(exit) printf("[AST.TypeInstance exit] %s\n", t.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!t);
+
assert(t.exp);
if (t.exp.type)
@@ -1845,11 +1789,8 @@ public:
override void visit(AST.TypeBasic t)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TypeBasic enter] %s\n", t.toChars());
- scope(exit) printf("[AST.TypeBasic exit] %s\n", t.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!t);
+
if (t.isConst() || t.isImmutable())
buf.writestring("const ");
string typeName;
@@ -1897,11 +1838,8 @@ public:
override void visit(AST.TypePointer t)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TypePointer enter] %s\n", t.toChars());
- scope(exit) printf("[AST.TypePointer exit] %s\n", t.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!t);
+
auto ts = t.next.isTypeStruct();
if (ts && !strcmp(ts.sym.ident.toChars(), "__va_list_tag"))
{
@@ -1923,31 +1861,20 @@ public:
override void visit(AST.TypeSArray t)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TypeSArray enter] %s\n", t.toChars());
- scope(exit) printf("[AST.TypeSArray exit] %s\n", t.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!t);
t.next.accept(this);
}
override void visit(AST.TypeAArray t)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TypeAArray enter] %s\n", t.toChars());
- scope(exit) printf("[AST.TypeAArray exit] %s\n", t.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!t);
AST.Type.tvoidptr.accept(this);
}
override void visit(AST.TypeFunction tf)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TypeFunction enter] %s\n", tf.toChars());
- scope(exit) printf("[AST.TypeFunction exit] %s\n", tf.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!tf);
+
tf.next.accept(this);
buf.writeByte('(');
buf.writeByte('*');
@@ -1975,11 +1902,8 @@ public:
/// (Might not be `ed` for special enums or enums that were emitted as namespaces)
private void enumToBuffer(AST.EnumDeclaration ed)
{
- debug (Debug_DtoH)
- {
- printf("[enumToBuffer(AST.EnumDeclaration) enter] %s\n", ed.toChars());
- scope(exit) printf("[enumToBuffer(AST.EnumDeclaration) exit] %s\n", ed.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!ed);
+
if (ed.isSpecial())
{
if (ed.ident == DMDType.c_long)
@@ -2025,11 +1949,7 @@ public:
override void visit(AST.TypeEnum t)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TypeEnum enter] %s\n", t.toChars());
- scope(exit) printf("[AST.TypeEnum exit] %s\n", t.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!t);
if (t.isConst() || t.isImmutable())
buf.writestring("const ");
@@ -2038,11 +1958,7 @@ public:
override void visit(AST.TypeStruct t)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TypeStruct enter] %s\n", t.toChars());
- scope(exit) printf("[AST.TypeStruct exit] %s\n", t.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!t);
if (t.isConst() || t.isImmutable())
buf.writestring("const ");
@@ -2051,11 +1967,8 @@ public:
override void visit(AST.TypeDArray t)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TypeDArray enter] %s\n", t.toChars());
- scope(exit) printf("[AST.TypeDArray exit] %s\n", t.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!t);
+
if (t.isConst() || t.isImmutable())
buf.writestring("const ");
buf.writestring("_d_dynamicArray< ");
@@ -2065,21 +1978,12 @@ public:
override void visit(AST.TypeInstance t)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TypeInstance enter] %s\n", t.toChars());
- scope(exit) printf("[AST.TypeInstance exit] %s\n", t.toChars());
- }
visitTi(t.tempinst);
}
private void visitTi(AST.TemplateInstance ti)
{
- debug (Debug_DtoH)
- {
- printf("[visitTi(AST.TemplateInstance) enter] %s\n", ti.toChars());
- scope(exit) printf("[visitTi(AST.TemplateInstance) exit] %s\n", ti.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!ti);
// Ensure that the TD appears before the instance
if (auto td = findTemplateDeclaration(ti))
@@ -2112,11 +2016,8 @@ public:
override void visit(AST.TemplateDeclaration td)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TemplateDeclaration enter] %s\n", td.toChars());
- scope(exit) printf("[AST.TemplateDeclaration exit] %s\n", td.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!td);
+
if (!shouldEmit(td))
return;
@@ -2171,11 +2072,7 @@ public:
/// Emit declarations of the TemplateMixin in the current scope
override void visit(AST.TemplateMixin tm)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TemplateMixin enter] %s\n", tm.toChars());
- scope(exit) printf("[AST.TemplateMixin exit] %s\n", tm.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!tm);
auto members = tm.members;
@@ -2256,11 +2153,7 @@ public:
override void visit(AST.TypeClass t)
{
- debug (Debug_DtoH)
- {
- printf("[AST.TypeClass enter] %s\n", t.toChars());
- scope(exit) printf("[AST.TypeClass exit] %s\n", t.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!t);
// Classes are emitted as pointer and hence can be forwarded
const fwdSave = forwarding;
@@ -2340,13 +2233,18 @@ public:
override void visit(AST.Parameter p)
{
- debug (Debug_DtoH)
+ debug (Debug_DtoH) mixin(traceVisit!p);
+
+ ident = p.ident;
+
{
- printf("[AST.Parameter enter] %s\n", p.toChars());
- scope(exit) printf("[AST.Parameter exit] %s\n", p.toChars());
+ // Reference parameters can be forwarded
+ const fwdStash = this.forwarding;
+ this.forwarding = !!(p.storageClass & AST.STC.ref_);
+ p.type.accept(this);
+ this.forwarding = fwdStash;
}
- ident = p.ident;
- p.type.accept(this);
+
if (p.storageClass & AST.STC.ref_)
buf.writeByte('&');
buf.writeByte(' ');
@@ -2479,11 +2377,8 @@ public:
override void visit(AST.Expression e)
{
- debug (Debug_DtoH)
- {
- printf("[AST.Expression enter] %s\n", e.toChars());
- scope(exit) printf("[AST.Expression exit] %s\n", e.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!e);
+
// Valid in most cases, others should be overriden below
// to use the appropriate operators (:: and ->)
buf.writestring(e.toString());
@@ -2491,11 +2386,7 @@ public:
override void visit(AST.UnaExp e)
{
- debug (Debug_DtoH)
- {
- printf("[AST.UnaExp enter] %s\n", e.toChars());
- scope(exit) printf("[AST.UnaExp exit] %s\n", e.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!e);
buf.writestring(tokToString(e.op));
e.e1.accept(this);
@@ -2503,11 +2394,7 @@ public:
override void visit(AST.BinExp e)
{
- debug (Debug_DtoH)
- {
- printf("[AST.BinExp enter] %s\n", e.toChars());
- scope(exit) printf("[AST.BinExp exit] %s\n", e.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!e);
e.e1.accept(this);
buf.writeByte(' ');
@@ -2530,11 +2417,7 @@ public:
override void visit(AST.VarExp e)
{
- debug (Debug_DtoH)
- {
- printf("[AST.VarExp enter] %s\n", e.toChars());
- scope(exit) printf("[AST.VarExp exit] %s\n", e.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!e);
// Local members don't need another prefix and might've been renamed
if (e.var.isThis())
@@ -2558,11 +2441,7 @@ public:
override void visit(AST.CallExp e)
{
- debug (Debug_DtoH)
- {
- printf("[AST.CallExp enter] %s\n", e.toChars());
- scope(exit) printf("[AST.CallExp exit] %s\n", e.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!e);
// Dereferencing function pointers requires additional braces: (*f)(args)
const isFp = e.e1.isPtrExp();
@@ -2588,11 +2467,7 @@ public:
override void visit(AST.DotVarExp e)
{
- debug (Debug_DtoH)
- {
- printf("[AST.DotVarExp enter] %s\n", e.toChars());
- scope(exit) printf("[AST.DotVarExp exit] %s\n", e.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!e);
if (auto sym = symbolFromType(e.e1.type))
includeSymbol(outermostSymbol(sym));
@@ -2617,11 +2492,7 @@ public:
override void visit(AST.DotIdExp e)
{
- debug (Debug_DtoH)
- {
- printf("[AST.DotIdExp enter] %s\n", e.toChars());
- scope(exit) printf("[AST.DotIdExp exit] %s\n", e.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!e);
e.e1.accept(this);
buf.writestring("::");
@@ -2630,11 +2501,7 @@ public:
override void visit(AST.ScopeExp e)
{
- debug (Debug_DtoH)
- {
- printf("[AST.ScopeExp enter] %s\n", e.toChars());
- scope(exit) printf("[AST.ScopeExp exit] %s\n", e.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!e);
// Usually a template instance in a TemplateDeclaration
if (auto ti = e.sds.isTemplateInstance())
@@ -2645,11 +2512,8 @@ public:
override void visit(AST.NullExp e)
{
- debug (Debug_DtoH)
- {
- printf("[AST.NullExp enter] %s\n", e.toChars());
- scope(exit) printf("[AST.NullExp exit] %s\n", e.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!e);
+
if (global.params.cplusplus >= CppStdRevision.cpp11)
buf.writestring("nullptr");
else
@@ -2658,21 +2522,13 @@ public:
override void visit(AST.ArrayLiteralExp e)
{
- debug (Debug_DtoH)
- {
- printf("[AST.ArrayLiteralExp enter] %s\n", e.toChars());
- scope(exit) printf("[AST.ArrayLiteralExp exit] %s\n", e.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!e);
buf.writestring("arrayliteral");
}
override void visit(AST.StringExp e)
{
- debug (Debug_DtoH)
- {
- printf("[AST.StringExp enter] %s\n", e.toChars());
- scope(exit) printf("[AST.StringExp exit] %s\n", e.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!e);
if (e.sz == 2)
buf.writeByte('u');
@@ -2709,11 +2565,7 @@ public:
override void visit(AST.RealExp e)
{
- debug (Debug_DtoH)
- {
- printf("[AST.RealExp enter] %s\n", e.toChars());
- scope(exit) printf("[AST.RealExp exit] %s\n", e.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!e);
import dmd.root.ctfloat : CTFloat;
@@ -2740,22 +2592,15 @@ public:
override void visit(AST.IntegerExp e)
{
- debug (Debug_DtoH)
- {
- printf("[AST.IntegerExp enter] %s\n", e.toChars());
- scope(exit) printf("[AST.IntegerExp exit] %s\n", e.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!e);
visitInteger(e.toInteger, e.type);
}
/// Writes `v` as type `t` into `buf`
private void visitInteger(dinteger_t v, AST.Type t)
{
- debug (Debug_DtoH)
- {
- printf("[visitInteger(AST.Type) enter] %s\n", t.toChars());
- scope(exit) printf("[visitInteger(AST.Type) exit] %s\n", t.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!t);
+
switch (t.ty)
{
case AST.Tenum:
@@ -2808,11 +2653,8 @@ public:
override void visit(AST.StructLiteralExp sle)
{
- debug (Debug_DtoH)
- {
- printf("[AST.StructLiteralExp enter] %s\n", sle.toChars());
- scope(exit) printf("[AST.StructLiteralExp exit] %s\n", sle.toChars());
- }
+ debug (Debug_DtoH) mixin(traceVisit!sle);
+
const isUnion = sle.sd.isUnionDeclaration();
sle.sd.type.accept(this);
buf.writeByte('(');
@@ -3014,8 +2856,12 @@ public:
/**
* Writes the qualified name of `sym` into `buf` including parent
* symbols and template parameters.
+ *
+ * Params:
+ * sym = the symbol
+ * mustInclude = whether sym may not be forward declared
*/
- private void writeFullName(AST.Dsymbol sym)
+ private void writeFullName(AST.Dsymbol sym, const bool mustInclude = false)
in
{
assert(sym);
@@ -3059,13 +2905,20 @@ public:
nested = !par.isModule();
if (nested && !isNestedIn(par, adparent))
{
- writeFullName(par);
+ writeFullName(par, true);
buf.writestring("::");
}
}
if (!nested)
- ensureDeclared(sym);
+ {
+ // Cannot forward the symbol when called recursively
+ // for a nested symbol
+ if (mustInclude)
+ includeSymbol(sym);
+ else
+ ensureDeclared(sym);
+ }
if (ti)
visitTi(ti);
@@ -3316,3 +3169,17 @@ ASTCodegen.Dsymbol findMember(ASTCodegen.Dsymbol sym, Identifier name)
return search(sds.members, name);
}
+
+debug (Debug_DtoH)
+{
+ /// Generates code to trace the entry and exit of the enclosing `visit` function
+ string traceVisit(alias node)()
+ {
+ const type = typeof(node).stringof;
+ const method = __traits(hasMember, node, "toPrettyChars") ? "toPrettyChars" : "toChars";
+ const arg = __traits(identifier, node) ~ '.' ~ method;
+
+ return `printf("[` ~ type ~ ` enter] %s\n", ` ~ arg ~ `());
+ scope(exit) printf("[` ~ type ~ ` exit] %s\n", ` ~ arg ~ `());`;
+ }
+}
diff --git a/gcc/d/dmd/enum.h b/gcc/d/dmd/enum.h
index eb3e2bc183f..76c1235715b 100644
--- a/gcc/d/dmd/enum.h
+++ b/gcc/d/dmd/enum.h
@@ -49,7 +49,6 @@ public:
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
bool isDeprecated() const; // is Dsymbol deprecated?
Visibility visible();
- Expression *getMaxMinValue(const Loc &loc, Identifier *id);
bool isSpecial() const;
Expression *getDefaultValue(const Loc &loc);
Type *getMemtype(const Loc &loc);
@@ -81,7 +80,6 @@ public:
EnumMember *syntaxCopy(Dsymbol *s);
const char *kind() const;
- Expression *getVarExp(const Loc &loc, Scope *sc);
EnumMember *isEnumMember() { return this; }
void accept(Visitor *v) { v->visit(this); }
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index 8d5857461e9..2b0b242a90e 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -374,7 +374,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, Exp
notMaybeScope(v);
- if ((v.storage_class & (STC.ref_ | STC.out_)) == 0 && p == sc.func)
+ if (!v.isReference() && p == sc.func)
{
if (par && (par.storageClass & (STC.scope_ | STC.return_)) == STC.scope_)
continue;
@@ -399,7 +399,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, Exp
notMaybeScope(v);
- if ((v.storage_class & (STC.ref_ | STC.out_ | STC.scope_)) && p == sc.func)
+ if ((v.isReference() || v.isScope()) && p == sc.func)
{
unsafeAssign(v, "reference to local");
continue;
@@ -471,12 +471,9 @@ bool checkConstructorEscape(Scope* sc, CallExp ce, bool gag)
if (!ce.arguments && ce.arguments.dim)
return false;
- assert(ce.e1.op == TOK.dotVariable);
- DotVarExp dve = cast(DotVarExp)ce.e1;
+ DotVarExp dve = ce.e1.isDotVarExp();
CtorDeclaration ctor = dve.var.isCtorDeclaration();
- assert(ctor);
- assert(ctor.type.ty == Tfunction);
- TypeFunction tf = cast(TypeFunction)ctor.type;
+ TypeFunction tf = ctor.type.isTypeFunction();
const nparams = tf.parameterList.length;
const n = ce.arguments.dim;
@@ -590,12 +587,12 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
// Try to infer 'scope' for va if in a function not marked @system
bool inferScope = false;
if (va && sc.func && sc.func.type && sc.func.type.ty == Tfunction)
- inferScope = (cast(TypeFunction)sc.func.type).trust != TRUST.system;
+ inferScope = sc.func.type.isTypeFunction().trust != TRUST.system;
//printf("inferScope = %d, %d\n", inferScope, (va.storage_class & STCmaybescope) != 0);
// Determine if va is a parameter that is an indirect reference
const bool vaIsRef = va && va.storage_class & STC.parameter &&
- (va.storage_class & (STC.ref_ | STC.out_) || va.type.toBasetype().ty == Tclass);
+ (va.isReference() || va.type.toBasetype().ty == Tclass);
if (log && vaIsRef) printf("va is ref `%s`\n", va.toChars());
/* Determine if va is the first parameter, through which other 'return' parameters
@@ -609,7 +606,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
FuncDeclaration fd = sc.func;
if (p == fd && fd.type && fd.type.ty == Tfunction)
{
- TypeFunction tf = cast(TypeFunction)fd.type;
+ TypeFunction tf = fd.type.isTypeFunction();
if (!tf.nextOf() || (tf.nextOf().ty != Tvoid && !fd.isCtorDeclaration()))
return false;
if (va == fd.vthis)
@@ -688,7 +685,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
// va is class reference
ae.e1.op == TOK.dotVariable && va.type.toBasetype().ty == Tclass && (va.enclosesLifetimeOf(v) || !va.isScope()) ||
vaIsRef ||
- va.storage_class & (STC.ref_ | STC.out_) && !(v.storage_class & (STC.parameter | STC.temp))) &&
+ va.isReference() && !(v.storage_class & (STC.parameter | STC.temp))) &&
sc.func.setUnsafe())
{
if (!gag)
@@ -757,7 +754,7 @@ ByRef:
if (global.params.useDIP1000 == FeatureState.enabled)
{
- if (va && va.isScope() && (v.storage_class & (STC.ref_ | STC.out_)) == 0)
+ if (va && va.isScope() && !v.isReference())
{
if (!(va.storage_class & STC.return_))
{
@@ -787,7 +784,7 @@ ByRef:
continue;
}
- if (va && v.storage_class & (STC.ref_ | STC.out_))
+ if (va && v.isReference())
{
Dsymbol pva = va.toParent2();
for (Dsymbol pv = p; pv; )
@@ -810,7 +807,7 @@ ByRef:
if (!(va && va.isScope()))
notMaybeScope(v);
- if ((v.storage_class & (STC.ref_ | STC.out_)) || p != sc.func)
+ if (v.isReference() || p != sc.func)
continue;
if (va && !va.isDataseg() && !va.doNotInferScope)
@@ -855,7 +852,7 @@ ByRef:
if (!(va && va.isScope()))
notMaybeScope(v);
- if (!(v.storage_class & (STC.ref_ | STC.out_ | STC.scope_)) || p != sc.func)
+ if (!(v.isReference() || v.isScope()) || p != sc.func)
continue;
if (va && !va.isDataseg() && !va.doNotInferScope)
@@ -1086,7 +1083,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
Dsymbol p = v.toParent2();
- if ((v.storage_class & (STC.ref_ | STC.out_)) == 0)
+ if (!v.isReference())
{
if (p == sc.func)
{
@@ -1098,7 +1095,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
/* Check for returning a ref variable by 'ref', but should be 'return ref'
* Infer the addition of 'return', or set result to be the offending expression.
*/
- if (!(v.storage_class & (STC.ref_ | STC.out_)))
+ if (!v.isReference())
continue;
if (!sc._module || !sc._module.isRoot())
@@ -1285,11 +1282,18 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
foreach (VarDeclaration v; er.byref)
{
- if (log) printf("byref `%s`\n", v.toChars());
+ if (log)
+ {
+ printf("byref `%s`\n", v.toChars());
+ if (v.storage_class & STC.return_) printf(" return");
+ if (v.storage_class & STC.ref_) printf(" ref");
+ if (v.storage_class & STC.scope_) printf(" scope");
+ printf("\n");
+ }
// 'featureState' tells us whether to emit an error or a deprecation,
// depending on the flag passed to the CLI for DIP25
- void escapingRef(VarDeclaration v, FeatureState featureState = FeatureState.enabled)
+ void escapingRef(VarDeclaration v, ScopeRef vsr, FeatureState featureState = FeatureState.enabled)
{
if (!gag)
{
@@ -1298,7 +1302,9 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
(v.type.hasPointers() || v.storage_class & STC.ref_))
{
msg = "returning `%s` escapes a reference to parameter `%s`";
- supplemental = "perhaps annotate the parameter with `return`";
+ supplemental = vsr == ScopeRef.Ref_ReturnScope
+ ? "perhaps remove `scope` parameter annotation so `return` applies to `ref`"
+ : "perhaps annotate the parameter with `return`";
}
else
{
@@ -1317,17 +1323,23 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
if (v.isDataseg())
continue;
+ auto stc = v.storage_class;
+ if (stc & STC.out_)
+ stc |= STC.ref_; // temporary hack until we adjust buildScopeRef()
+
+ const vsr = buildScopeRef(refs, stc);
+
Dsymbol p = v.toParent2();
// https://issues.dlang.org/show_bug.cgi?id=19965
if (!refs && sc.func.vthis == v)
notMaybeScope(v);
- if ((v.storage_class & (STC.ref_ | STC.out_)) == 0)
+ if (!v.isReference())
{
if (p == sc.func)
{
- escapingRef(v);
+ escapingRef(v, vsr, FeatureState.enabled);
continue;
}
FuncDeclaration fd = p.isFuncDeclaration();
@@ -1345,16 +1357,18 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
sc.func.storage_class |= STC.return_ | STC.returninferred;
}
}
-
}
/* Check for returning a ref variable by 'ref', but should be 'return ref'
* Infer the addition of 'return', or set result to be the offending expression.
*/
- if ( (v.storage_class & (STC.ref_ | STC.out_)) &&
- !(v.storage_class & (STC.return_ | STC.foreach_)))
+ if ((vsr == ScopeRef.Ref ||
+ vsr == ScopeRef.RefScope ||
+ vsr == ScopeRef.Ref_ReturnScope) &&
+ !(v.storage_class & STC.foreach_))
{
- if (sc.func.flags & FUNCFLAG.returnInprocess && p == sc.func)
+ if (sc.func.flags & FUNCFLAG.returnInprocess && p == sc.func &&
+ (vsr == ScopeRef.Ref || vsr == ScopeRef.RefScope))
{
inferReturn(sc.func, v); // infer addition of 'return'
}
@@ -1366,14 +1380,14 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
{
//printf("escaping reference to local ref variable %s\n", v.toChars());
//printf("storage class = x%llx\n", v.storage_class);
- escapingRef(v, global.params.useDIP25);
+ escapingRef(v, vsr, global.params.useDIP25);
continue;
}
// Don't need to be concerned if v's parent does not return a ref
FuncDeclaration fd = p.isFuncDeclaration();
if (fd && fd.type && fd.type.ty == Tfunction)
{
- TypeFunction tf = cast(TypeFunction)fd.type;
+ TypeFunction tf = fd.type.isTypeFunction();
if (tf.isref)
{
const(char)* msg = "escaping reference to outer local variable `%s`";
@@ -1414,13 +1428,12 @@ private void inferReturn(FuncDeclaration fd, VarDeclaration v)
//printf("for function '%s' inferring 'return' for variable '%s'\n", fd.toChars(), v.toChars());
v.storage_class |= STC.return_ | STC.returninferred;
- TypeFunction tf = cast(TypeFunction)fd.type;
if (v == fd.vthis)
{
/* v is the 'this' reference, so mark the function
*/
fd.storage_class |= STC.return_ | STC.returninferred;
- if (tf.ty == Tfunction)
+ if (auto tf = fd.type.isTypeFunction())
{
//printf("'this' too %p %s\n", tf, sc.func.toChars());
tf.isreturn = true;
@@ -1430,7 +1443,7 @@ private void inferReturn(FuncDeclaration fd, VarDeclaration v)
else
{
// Perform 'return' inference on parameter
- if (tf.ty == Tfunction)
+ if (auto tf = fd.type.isTypeFunction())
{
foreach (i, p; tf.parameterList)
{
@@ -1607,9 +1620,9 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false)
override void visit(SliceExp e)
{
- if (e.e1.op == TOK.variable)
+ if (auto ve = e.e1.isVarExp())
{
- VarDeclaration v = (cast(VarExp)e.e1).var.isVarDeclaration();
+ VarDeclaration v = ve.var.isVarDeclaration();
Type tb = e.type.toBasetype();
if (v)
{
@@ -1684,11 +1697,11 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false)
TypeDelegate dg;
if (t1.ty == Tdelegate)
{
- dg = cast(TypeDelegate)t1;
- tf = cast(TypeFunction)(cast(TypeDelegate)t1).next;
+ dg = t1.isTypeDelegate();
+ tf = dg.next.isTypeFunction();
}
else if (t1.ty == Tfunction)
- tf = cast(TypeFunction)t1;
+ tf = t1.isTypeFunction();
else
return;
@@ -1731,7 +1744,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false)
// If 'this' is returned, check it too
if (e.e1.op == TOK.dotVariable && t1.ty == Tfunction)
{
- DotVarExp dve = cast(DotVarExp)e.e1;
+ DotVarExp dve = e.e1.isDotVarExp();
FuncDeclaration fd = dve.var.isFuncDeclaration();
AggregateDeclaration ad;
if (global.params.useDIP1000 == FeatureState.enabled && tf.isreturn && fd && (ad = fd.isThis()) !is null)
@@ -1779,9 +1792,8 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false)
/* If it's a nested function that is 'return scope'
*/
- if (e.e1.op == TOK.variable)
+ if (auto ve = e.e1.isVarExp())
{
- VarExp ve = cast(VarExp)e.e1;
FuncDeclaration fd = ve.var.isFuncDeclaration();
if (fd && fd.isNested())
{
@@ -1875,9 +1887,9 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false)
override void visit(IndexExp e)
{
Type tb = e.e1.type.toBasetype();
- if (e.e1.op == TOK.variable)
+ if (auto ve = e.e1.isVarExp())
{
- VarDeclaration v = (cast(VarExp)e.e1).var.isVarDeclaration();
+ VarDeclaration v = ve.var.isVarDeclaration();
if (tb.ty == Tarray || tb.ty == Tsarray)
{
if (v && v.storage_class & STC.variadic)
@@ -1949,9 +1961,9 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false)
Type t1 = e.e1.type.toBasetype();
TypeFunction tf;
if (t1.ty == Tdelegate)
- tf = cast(TypeFunction)(cast(TypeDelegate)t1).next;
+ tf = t1.isTypeDelegate().next.isTypeFunction();
else if (t1.ty == Tfunction)
- tf = cast(TypeFunction)t1;
+ tf = t1.isTypeFunction();
else
return;
if (tf.isref)
@@ -1974,9 +1986,8 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false)
arg.accept(this);
else if ((stc & STC.scope_) && (stc & STC.return_))
{
- if (arg.op == TOK.delegate_)
+ if (auto de = arg.isDelegateExp())
{
- DelegateExp de = cast(DelegateExp)arg;
if (de.func.isNested())
er.byexp.push(de);
}
@@ -1989,7 +2000,7 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false)
// If 'this' is returned by ref, check it too
if (e.e1.op == TOK.dotVariable && t1.ty == Tfunction)
{
- DotVarExp dve = cast(DotVarExp)e.e1;
+ DotVarExp dve = e.e1.isDotVarExp();
// https://issues.dlang.org/show_bug.cgi?id=20149#c10
if (dve.var.isCtorDeclaration())
@@ -2021,9 +2032,8 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false)
/* If it's a nested function that is 'return ref'
*/
- if (e.e1.op == TOK.variable)
+ if (auto ve = e.e1.isVarExp())
{
- VarExp ve = cast(VarExp)e.e1;
FuncDeclaration fd = ve.var.isFuncDeclaration();
if (fd && fd.isNested())
{
@@ -2161,7 +2171,7 @@ public void eliminateMaybeScopes(VarDeclaration[] array)
{
// v cannot be scope since it is assigned to a non-scope va
notMaybeScope(v);
- if (!(v.storage_class & (STC.ref_ | STC.out_)))
+ if (!v.isReference())
v.storage_class &= ~(STC.return_ | STC.returninferred);
changes = true;
}
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 9545642af6e..51034867e5c 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -1546,57 +1546,7 @@ extern (C++) abstract class Expression : ASTNode
return type ? Modifiable.yes : Modifiable.no; // default modifiable
}
- /*****************************
- * If expression can be tested for true or false,
- * returns the modified expression.
- * Otherwise returns ErrorExp.
- */
- Expression toBoolean(Scope* sc)
- {
- // Default is 'yes' - do nothing
- Expression e = this;
- Type t = type;
- Type tb = type.toBasetype();
- Type att = null;
-
- while (1)
- {
- // Structs can be converted to bool using opCast(bool)()
- if (auto ts = tb.isTypeStruct())
- {
- AggregateDeclaration ad = ts.sym;
- /* Don't really need to check for opCast first, but by doing so we
- * get better error messages if it isn't there.
- */
- if (Dsymbol fd = search_function(ad, Id._cast))
- {
- e = new CastExp(loc, e, Type.tbool);
- e = e.expressionSemantic(sc);
- return e;
- }
-
- // Forward to aliasthis.
- if (ad.aliasthis && !isRecursiveAliasThis(att, tb))
- {
- e = resolveAliasThis(sc, e);
- t = e.type;
- tb = e.type.toBasetype();
- continue;
- }
- }
- break;
- }
-
- if (!t.isBoolean())
- {
- if (tb != Type.terror)
- error("expression `%s` of type `%s` does not have a boolean value", toChars(), t.toChars());
- return ErrorExp.get();
- }
- return e;
- }
-
- /************************************************
+ /************************************************
* Destructors are attached to VarDeclarations.
* Hence, if expression returns a temp that needs a destructor,
* make sure and create a VarDeclaration for that temp.
@@ -1666,7 +1616,7 @@ extern (C++) abstract class Expression : ASTNode
return true;
}
- final pure inout nothrow @nogc
+ final pure inout nothrow @nogc @safe
{
inout(IntegerExp) isIntegerExp() { return op == TOK.int64 ? cast(typeof(return))this : null; }
inout(ErrorExp) isErrorExp() { return op == TOK.error ? cast(typeof(return))this : null; }
@@ -3379,6 +3329,14 @@ extern (C++) final class StructLiteralExp : Expression
return this;
}
+ override Expression toLvalue(Scope* sc, Expression e)
+ {
+ if (sc.flags & SCOPE.Cfile)
+ return this; // C struct literals are lvalues
+ else
+ return Expression.toLvalue(sc, e);
+ }
+
override void accept(Visitor v)
{
v.visit(this);
@@ -3561,7 +3519,6 @@ extern (C++) final class NewExp : Expression
Expression argprefix; // expression to be evaluated just before arguments[]
CtorDeclaration member; // constructor function
- NewDeclaration allocator; // allocator function
bool onstack; // allocate on stack
bool thrownew; // this NewExp is the expression of a ThrowStatement
@@ -4634,7 +4591,7 @@ extern (C++) class BinAssignExp : BinExp
return toLvalue(sc, this);
}
- override inout(BinAssignExp) isBinAssignExp() pure inout nothrow @nogc
+ override inout(BinAssignExp) isBinAssignExp() pure inout nothrow @nogc @safe
{
return this;
}
@@ -5373,12 +5330,6 @@ extern (C++) final class DeleteExp : UnaExp
this.isRAII = isRAII;
}
- override Expression toBoolean(Scope* sc)
- {
- error("`delete` does not give a boolean result");
- return ErrorExp.get();
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -5722,16 +5673,6 @@ extern (C++) final class CommaExp : BinExp
return e2.isBool(result);
}
- override Expression toBoolean(Scope* sc)
- {
- auto ex2 = e2.toBoolean(sc);
- if (ex2.op == TOK.error)
- return ex2;
- e2 = ex2;
- type = e2.type;
- return this;
- }
-
override Expression addDtorHook(Scope* sc)
{
e2 = e2.addDtorHook(sc);
@@ -6037,16 +5978,6 @@ extern (C++) class AssignExp : BinExp
return this;
}
- override final Expression toBoolean(Scope* sc)
- {
- // Things like:
- // if (a = b) ...
- // are usually mistakes.
-
- error("assignment cannot be used as a condition, perhaps `==` was meant?");
- return ErrorExp.get();
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -6071,7 +6002,7 @@ extern (C++) final class ConstructExp : AssignExp
super(loc, TOK.construct, ve, e2);
- if (v.storage_class & (STC.ref_ | STC.out_))
+ if (v.isReference())
memset = MemorySet.referenceInit;
}
@@ -6099,7 +6030,7 @@ extern (C++) final class BlitExp : AssignExp
super(loc, TOK.blit, ve, e2);
- if (v.storage_class & (STC.ref_ | STC.out_))
+ if (v.isReference())
memset = MemorySet.referenceInit;
}
@@ -6567,15 +6498,6 @@ extern (C++) final class LogicalExp : BinExp
assert(op == TOK.andAnd || op == TOK.orOr);
}
- override Expression toBoolean(Scope* sc)
- {
- auto ex2 = e2.toBoolean(sc);
- if (ex2.op == TOK.error)
- return ex2;
- e2 = ex2;
- return this;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -6731,19 +6653,6 @@ extern (C++) final class CondExp : BinExp
return toLvalue(sc, this);
}
- override Expression toBoolean(Scope* sc)
- {
- auto ex1 = e1.toBoolean(sc);
- auto ex2 = e2.toBoolean(sc);
- if (ex1.op == TOK.error)
- return ex1;
- if (ex2.op == TOK.error)
- return ex2;
- e1 = ex1;
- e2 = ex2;
- return this;
- }
-
void hookDtors(Scope* sc)
{
extern (C++) final class DtorVisitor : StoppableVisitor
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index 855c82bfacc..5e60917e804 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -27,7 +27,6 @@ class VarDeclaration;
class FuncDeclaration;
class FuncLiteralDeclaration;
class CtorDeclaration;
-class NewDeclaration;
class Dsymbol;
class ScopeDsymbol;
class Expression;
@@ -97,7 +96,6 @@ public:
virtual bool checkValue();
bool checkDeprecated(Scope *sc, Dsymbol *s);
virtual int checkModifiable(Scope *sc, int flag = 0);
- virtual Expression *toBoolean(Scope *sc);
virtual Expression *addDtorHook(Scope *sc);
Expression *addressOf();
Expression *deref();
@@ -463,6 +461,7 @@ public:
Expression *getField(Type *type, unsigned offset);
int getFieldIndex(Type *type, unsigned offset);
Expression *addDtorHook(Scope *sc);
+ Expression *toLvalue(Scope *sc, Expression *e);
void accept(Visitor *v) { v->visit(this); }
};
@@ -513,7 +512,6 @@ public:
Expression *argprefix; // expression to be evaluated just before arguments[]
CtorDeclaration *member; // constructor function
- NewDeclaration *allocator; // allocator function
bool onstack; // allocate on stack
bool thrownew; // this NewExp is the expression of a ThrowStatement
@@ -861,7 +859,6 @@ class DeleteExp : public UnaExp
{
public:
bool isRAII;
- Expression *toBoolean(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
};
@@ -988,7 +985,6 @@ public:
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
bool isBool(bool result);
- Expression *toBoolean(Scope *sc);
Expression *addDtorHook(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
};
@@ -1039,7 +1035,6 @@ public:
bool isLvalue();
Expression *toLvalue(Scope *sc, Expression *ex);
- Expression *toBoolean(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
};
@@ -1215,7 +1210,6 @@ public:
class LogicalExp : public BinExp
{
public:
- Expression *toBoolean(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
};
@@ -1265,7 +1259,6 @@ public:
bool isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
- Expression *toBoolean(Scope *sc);
void hookDtors(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 36e657a62af..5069e8f51a0 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -190,9 +190,8 @@ private Expression extractOpDollarSideEffect(Scope* sc, UnaExp ue)
* (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
*/
e1 = extractSideEffect(sc, "__dop", e0, e1, false);
- assert(e1.op == TOK.variable);
- VarExp ve = cast(VarExp)e1;
- ve.var.storage_class |= STC.exptemp; // lifetime limited to expression
+ assert(e1.isVarExp());
+ e1.isVarExp().var.storage_class |= STC.exptemp; // lifetime limited to expression
}
ue.e1 = e1;
return e0;
@@ -243,10 +242,8 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
}
sc = sc.pop();
- if (e.op == TOK.interval)
+ if (auto ie = e.isIntervalExp())
{
- IntervalExp ie = cast(IntervalExp)e;
-
auto tiargs = new Objects();
Expression edim = new IntegerExp(ae.loc, i, Type.tsize_t);
edim = edim.expressionSemantic(sc);
@@ -372,7 +369,7 @@ private bool checkPropertyCall(Expression e)
if (!tf.deco && ce.f.semanticRun < PASS.semanticdone)
{
ce.f.dsymbolSemantic(null);
- tf = cast(TypeFunction)ce.f.type;
+ tf = ce.f.type.isTypeFunction();
}
}
else if (!ce.e1.type.isFunction_Delegate_PtrToFunction())
@@ -454,9 +451,8 @@ private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident)
}
}
- if (ue.op == TOK.dotTemplateInstance)
+ if (auto dti = ue.isDotTemplateInstanceExp())
{
- DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)ue;
auto ti = new TemplateInstance(loc, s.ident, dti.ti.tiargs);
if (!ti.updateTempDecl(sc, s))
return ErrorExp.get();
@@ -478,9 +474,8 @@ private Expression resolveUFCS(Scope* sc, CallExp ce)
Expression eleft;
Expression e;
- if (ce.e1.op == TOK.dotIdentifier)
+ if (auto die = ce.e1.isDotIdExp())
{
- DotIdExp die = cast(DotIdExp)ce.e1;
Identifier ident = die.ident;
Expression ex = die.semanticX(sc);
@@ -519,7 +514,7 @@ private Expression resolveUFCS(Scope* sc, CallExp ce)
key = key.expressionSemantic(sc);
key = resolveProperties(sc, key);
- TypeAArray taa = cast(TypeAArray)t;
+ TypeAArray taa = t.isTypeAArray();
key = key.implicitCastTo(sc, taa.index);
if (key.checkValue() || key.checkSharedAccess(sc))
@@ -592,7 +587,7 @@ private Expression resolveUFCS(Scope* sc, CallExp ce)
die.e1 = alias_e;
CallExp ce2 = ce.syntaxCopy();
ce2.e1 = die;
- e = cast(CallExp)ce2.trySemantic(sc);
+ e = ce2.isCallExp().trySemantic(sc);
if (e)
return e;
}
@@ -601,9 +596,8 @@ private Expression resolveUFCS(Scope* sc, CallExp ce)
searchUFCS(sc, die, ident);
}
}
- else if (ce.e1.op == TOK.dotTemplateInstance)
+ else if (auto dti = ce.e1.isDotTemplateInstanceExp())
{
- DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)ce.e1;
if (Expression ey = dti.semanticY(sc, 1))
{
ce.e1 = ey;
@@ -633,16 +627,13 @@ private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2
Expression eleft;
Expression e;
- if (e1.op == TOK.dotIdentifier)
+ if (auto die = e1.isDotIdExp())
{
- DotIdExp die = cast(DotIdExp)e1;
eleft = die.e1;
e = searchUFCS(sc, die, die.ident);
}
- else if (e1.op == TOK.dotTemplateInstance)
+ else if (auto dti = e1.isDotTemplateInstanceExp())
{
- DotTemplateInstanceExp dti;
- dti = cast(DotTemplateInstanceExp)e1;
eleft = dti.e1;
e = searchUFCS(sc, dti, dti.ti.name);
}
@@ -728,12 +719,12 @@ Expression resolvePropertiesOnly(Scope* sc, Expression e1)
auto td = s.isTemplateDeclaration();
if (fd)
{
- if ((cast(TypeFunction)fd.type).isproperty)
+ if (fd.type.isTypeFunction().isproperty)
return resolveProperties(sc, e1);
}
else if (td && td.onemember && (fd = td.onemember.isFuncDeclaration()) !is null)
{
- if ((cast(TypeFunction)fd.type).isproperty ||
+ if (fd.type.isTypeFunction().isproperty ||
(fd.storage_class2 & STC.property) ||
(td._scope.stc & STC.property))
return resolveProperties(sc, e1);
@@ -749,7 +740,7 @@ Expression resolvePropertiesOnly(Scope* sc, Expression e1)
{
if (auto fd = td.onemember.isFuncDeclaration())
{
- if ((cast(TypeFunction)fd.type).isproperty ||
+ if (fd.type.isTypeFunction().isproperty ||
(fd.storage_class2 & STC.property) ||
(td._scope.stc & STC.property))
return resolveProperties(sc, e1);
@@ -761,7 +752,7 @@ Expression resolvePropertiesOnly(Scope* sc, Expression e1)
Expression handleFuncDecl(FuncDeclaration fd)
{
assert(fd);
- if ((cast(TypeFunction)fd.type).isproperty)
+ if (fd.type.isTypeFunction().isproperty)
return resolveProperties(sc, e1);
return e1;
}
@@ -781,23 +772,23 @@ Expression resolvePropertiesOnly(Scope* sc, Expression e1)
}
else if (auto dte = e1.isDotTemplateExp())
return handleTemplateDecl(dte.td);
- else if (e1.op == TOK.scope_)
+ else if (auto se = e1.isScopeExp())
{
- Dsymbol s = (cast(ScopeExp)e1).sds;
+ Dsymbol s = se.sds;
TemplateInstance ti = s.isTemplateInstance();
if (ti && !ti.semanticRun && ti.tempdecl)
if (auto td = ti.tempdecl.isTemplateDeclaration())
return handleTemplateDecl(td);
}
- else if (e1.op == TOK.template_)
- return handleTemplateDecl((cast(TemplateExp)e1).td);
- else if (e1.op == TOK.dotVariable && e1.type.ty == Tfunction)
+ else if (auto et = e1.isTemplateExp())
+ return handleTemplateDecl(et.td);
+ else if (e1.isDotVarExp() && e1.type.isTypeFunction())
{
- DotVarExp dve = cast(DotVarExp)e1;
+ DotVarExp dve = e1.isDotVarExp();
return handleFuncDecl(dve.var.isFuncDeclaration());
}
- else if (e1.op == TOK.variable && e1.type && e1.type.ty == Tfunction && (sc.intypeof || !(cast(VarExp)e1).var.needThis()))
- return handleFuncDecl((cast(VarExp)e1).var.isFuncDeclaration());
+ else if (e1.isVarExp() && e1.type && e1.type.isTypeFunction() && (sc.intypeof || !e1.isVarExp().var.needThis()))
+ return handleFuncDecl(e1.isVarExp().var.isFuncDeclaration());
return e1;
}
@@ -1040,7 +1031,7 @@ L1:
var.isFuncDeclaration && var.isFuncDeclaration.isStatic &&
var.isFuncDeclaration.objc.selector)
{
- return new ObjcClassReferenceExp(e1.loc, cast(ClassDeclaration) ad);
+ return new ObjcClassReferenceExp(e1.loc, ad.isClassDeclaration());
}
/* Access of a member which is a template parameter in dual-scope scenario
@@ -1068,8 +1059,8 @@ L1:
/* If e1 is not the 'this' pointer for ad
*/
if (ad &&
- !(t.ty == Tpointer && t.nextOf().ty == Tstruct && (cast(TypeStruct)t.nextOf()).sym == ad) &&
- !(t.ty == Tstruct && (cast(TypeStruct)t).sym == ad))
+ !(t.isTypePointer() && t.nextOf().isTypeStruct() && t.nextOf().isTypeStruct().sym == ad) &&
+ !(t.isTypeStruct() && t.isTypeStruct().sym == ad))
{
ClassDeclaration cd = ad.isClassDeclaration();
ClassDeclaration tcd = t.isClassHandle();
@@ -1124,22 +1115,21 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
Dsymbol s;
Objects* tiargs;
Type tthis;
- if (e1.op == TOK.dot)
+ if (auto de = e1.isDotExp())
{
- DotExp de = cast(DotExp)e1;
- if (de.e2.op == TOK.overloadSet)
+ if (auto oe = de.e2.isOverExp())
{
tiargs = null;
tthis = de.e1.type;
- os = (cast(OverExp)de.e2).vars;
+ os = oe.vars;
goto Los;
}
}
- else if (e1.op == TOK.overloadSet)
+ else if (e1.isOverExp())
{
tiargs = null;
tthis = null;
- os = (cast(OverExp)e1).vars;
+ os = e1.isOverExp().vars;
Los:
assert(os);
FuncDeclaration fd = null;
@@ -1178,7 +1168,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
return ErrorExp.get();
fd = f;
assert(fd.type.ty == Tfunction);
- TypeFunction tf = cast(TypeFunction)fd.type;
+ auto tf = fd.type.isTypeFunction();
if (!tf.isref && e2)
{
error(loc, "%s is not an lvalue", e1.toChars());
@@ -1197,9 +1187,8 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
if (e2)
goto Leprop;
}
- else if (e1.op == TOK.dotTemplateInstance)
+ else if (auto dti = e1.isDotTemplateInstanceExp())
{
- DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)e1;
if (!dti.findTempDecl(sc))
goto Leprop;
if (!dti.ti.semanticTiargs(sc))
@@ -1211,17 +1200,16 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
if ((s = dti.ti.tempdecl) !is null)
goto Lfd;
}
- else if (e1.op == TOK.dotTemplateDeclaration)
+ else if (auto dte = e1.isDotTemplateExp())
{
- DotTemplateExp dte = cast(DotTemplateExp)e1;
s = dte.td;
tiargs = null;
tthis = dte.e1.type;
goto Lfd;
}
- else if (e1.op == TOK.scope_)
+ else if (auto se = e1.isScopeExp())
{
- s = (cast(ScopeExp)e1).sds;
+ s = se.sds;
TemplateInstance ti = s.isTemplateInstance();
if (ti && !ti.semanticRun && ti.tempdecl)
{
@@ -1236,9 +1224,9 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 =
goto Lfd;
}
}
- else if (e1.op == TOK.template_)
+ else if (auto te = e1.isTemplateExp())
{
- s = (cast(TemplateExp)e1).td;
+ s = te.td;
tiargs = null;
tthis = null;
goto Lfd;
@@ -1872,8 +1860,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
L1:
if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
{
- const isRef = (p.storageClass & (STC.ref_ | STC.out_)) != 0;
- if (ubyte wm = arg.type.deduceWild(p.type, isRef))
+ if (ubyte wm = arg.type.deduceWild(p.type, p.isReference()))
{
wildmatch = wildmatch ? MODmerge(wildmatch, wm) : wm;
//printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p.type.toChars(), arg.type.toChars(), wm, wildmatch);
@@ -3684,28 +3671,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
}
- if (cd.aggNew)
+ if (cd.disableNew)
{
- // Prepend the size argument to newargs[]
- Expression e = new IntegerExp(exp.loc, cd.size(exp.loc), Type.tsize_t);
- if (!exp.newargs)
- exp.newargs = new Expressions();
- exp.newargs.shift(e);
-
- FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.aggNew, null, tb, exp.newargs, FuncResolveFlag.standard);
- if (!f || f.errors)
- return setError();
-
- checkFunctionAttributes(exp, sc, f);
- checkAccess(cd, exp.loc, sc, f);
-
- TypeFunction tf = cast(TypeFunction)f.type;
- Type rettype;
- if (functionParameters(exp.loc, sc, tf, null, null, exp.newargs, f, &rettype, &newprefix))
- return setError();
-
- exp.allocator = f.isNewDeclaration();
- assert(exp.allocator);
+ exp.error("cannot allocate `class %s` with `new` because it is annotated with `@disable new()`",
+ originalNewtype.toChars());
+ return setError();
}
else
{
@@ -3774,28 +3744,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
// checkDeprecated() is already done in newtype.typeSemantic().
- if (sd.aggNew)
+ if (sd.disableNew)
{
- // Prepend the uint size argument to newargs[]
- Expression e = new IntegerExp(exp.loc, sd.size(exp.loc), Type.tsize_t);
- if (!exp.newargs)
- exp.newargs = new Expressions();
- exp.newargs.shift(e);
-
- FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.aggNew, null, tb, exp.newargs, FuncResolveFlag.standard);
- if (!f || f.errors)
- return setError();
-
- checkFunctionAttributes(exp, sc, f);
- checkAccess(sd, exp.loc, sc, f);
-
- TypeFunction tf = cast(TypeFunction)f.type;
- Type rettype;
- if (functionParameters(exp.loc, sc, tf, null, null, exp.newargs, f, &rettype, &newprefix))
- return setError();
-
- exp.allocator = f.isNewDeclaration();
- assert(exp.allocator);
+ exp.error("cannot allocate `struct %s` with `new` because it is annotated with `@disable new()`",
+ originalNewtype.toChars());
+ return setError();
}
else
{
@@ -4464,6 +4417,40 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// Rewrite (*fp)(arguments) to fp(arguments)
exp.e1 = (cast(PtrExp)exp.e1).e1;
}
+ else if (exp.e1.op == TOK.type && (sc && sc.flags & SCOPE.Cfile))
+ {
+ /* Ambiguous cases arise from CParser where there is not enough
+ * information to determine if we have a function call or declaration.
+ * type-name ( identifier ) ;
+ * identifier ( identifier ) ;
+ * If exp.e1 is a type-name, then this is a declaration. C11 does not
+ * have type construction syntax, so don't convert this to a cast().
+ */
+ if (exp.arguments && exp.arguments.dim == 1)
+ {
+ Expression arg = (*exp.arguments)[0];
+ if (auto ie = (*exp.arguments)[0].isIdentifierExp())
+ {
+ TypeExp te = cast(TypeExp)exp.e1;
+ auto initializer = new VoidInitializer(ie.loc);
+ Dsymbol s = new VarDeclaration(ie.loc, te.type, ie.ident, initializer);
+ auto decls = new Dsymbols(1);
+ (*decls)[0] = s;
+ s = new LinkDeclaration(s.loc, LINK.c, decls);
+ result = new DeclarationExp(exp.loc, s);
+ result = result.expressionSemantic(sc);
+ }
+ else
+ {
+ arg.error("identifier or `(` expected");
+ result = ErrorExp.get();
+ }
+ return;
+ }
+ exp.error("identifier or `(` expected before `)`");
+ result = ErrorExp.get();
+ return;
+ }
}
Type t1 = exp.e1.type ? exp.e1.type.toBasetype() : null;
@@ -6700,6 +6687,25 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
+ if (sc.flags & SCOPE.Cfile)
+ {
+ /* Special handling for &"string"
+ * since C regards a string literal as an lvalue
+ */
+ if (auto se = exp.e1.isStringExp())
+ {
+ if (auto tp = se.type.toBasetype().isTypePointer())
+ {
+ /* Switch from pointer-to-char to pointer-to-static-array-of-char
+ */
+ auto ts = new TypeSArray(tp.nextOf(), new IntegerExp(Loc.initial, se.len + 1, Type.tsize_t));
+ se.type = typeSemantic(ts, Loc.initial, sc).pointerTo();
+ result = se;
+ return;
+ }
+ }
+ }
+
int wasCond = exp.e1.op == TOK.question;
if (exp.e1.op == TOK.dotTemplateInstance)
@@ -7297,6 +7303,39 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
+ if ((sc && sc.flags & SCOPE.Cfile) &&
+ exp.to && exp.to.ty == Tident &&
+ (exp.e1.op == TOK.address || exp.e1.op == TOK.star ||
+ exp.e1.op == TOK.uadd || exp.e1.op == TOK.negate))
+ {
+ /* Ambiguous cases arise from CParser if type-name is just an identifier.
+ * ( identifier ) cast-expression
+ * If we determine that `identifier` is a variable, and cast-expression
+ * is one of the unary operators (& * + -), then rewrite this cast
+ * as a binary expression.
+ */
+ Loc loc = exp.loc;
+ Type t;
+ Expression e;
+ Dsymbol s;
+ exp.to.resolve(loc, sc, e, t, s);
+ if (e !is null)
+ {
+ if (auto ex = exp.e1.isAddrExp()) // (ident) &exp -> (ident & exp)
+ result = new AndExp(loc, e, ex.e1);
+ else if (auto ex = exp.e1.isPtrExp()) // (ident) *exp -> (ident * exp)
+ result = new MulExp(loc, e, ex.e1);
+ else if (auto ex = exp.e1.isUAddExp()) // (ident) +exp -> (ident + exp)
+ result = new AddExp(loc, e, ex.e1);
+ else if (auto ex = exp.e1.isNegExp()) // (ident) -exp -> (ident - exp)
+ result = new MinExp(loc, e, ex.e1);
+
+ assert(result);
+ result = result.expressionSemantic(sc);
+ return;
+ }
+ }
+
if (exp.to)
{
exp.to = exp.to.typeSemantic(exp.loc, sc);
@@ -8770,15 +8809,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp = new ConstructExp(exp.loc, exp.e1, exp.e2);
exp.type = t;
- // @@@DEPRECATED_2020-06@@@
- // When removing, alter `checkModifiable` to return the correct value.
- if (sc.func.isStaticCtorDeclaration() && !sc.func.isSharedStaticCtorDeclaration() &&
- exp.e1.type.isImmutable())
- {
- deprecation(exp.loc, "initialization of `immutable` variable from `static this` is deprecated.");
- deprecationSupplemental(exp.loc, "Use `shared static this` instead.");
- }
-
// https://issues.dlang.org/show_bug.cgi?id=13515
// set Index::modifiable flag for complex AA element initialization
if (auto ie1 = exp.e1.isIndexExp())
@@ -12658,3 +12688,246 @@ bool verifyHookExist(const ref Loc loc, ref Scope sc, Identifier id, string desc
error(loc, "`%s.%s` not found. The current runtime does not support %.*s, or the runtime is corrupt.", module_.toChars(), id.toChars(), cast(int)description.length, description.ptr);
return false;
}
+
+/***************************************
+ * Fit elements[] to the corresponding types of the `sd`'s fields.
+ *
+ * Params:
+ * sd = the struct declaration
+ * loc = location to use for error messages
+ * sc = context
+ * elements = explicit arguments used to construct object
+ * stype = the constructed object type.
+ * Returns:
+ * false if any errors occur,
+ * otherwise true and elements[] are rewritten for the output.
+ */
+private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions* elements, Type stype)
+{
+ if (!elements)
+ return true;
+
+ const nfields = sd.nonHiddenFields();
+ size_t offset = 0;
+ for (size_t i = 0; i < elements.dim; i++)
+ {
+ Expression e = (*elements)[i];
+ if (!e)
+ continue;
+
+ e = resolveProperties(sc, e);
+ if (i >= nfields)
+ {
+ if (i <= sd.fields.dim && e.op == TOK.null_)
+ {
+ // CTFE sometimes creates null as hidden pointer; we'll allow this.
+ continue;
+ }
+ .error(loc, "more initializers than fields (%zu) of `%s`", nfields, sd.toChars());
+ return false;
+ }
+ VarDeclaration v = sd.fields[i];
+ if (v.offset < offset)
+ {
+ .error(loc, "overlapping initialization for `%s`", v.toChars());
+ if (!sd.isUnionDeclaration())
+ {
+ enum errorMsg = "`struct` initializers that contain anonymous unions" ~
+ " must initialize only the first member of a `union`. All subsequent" ~
+ " non-overlapping fields are default initialized";
+ .errorSupplemental(loc, errorMsg);
+ }
+ return false;
+ }
+ offset = cast(uint)(v.offset + v.type.size());
+
+ Type t = v.type;
+ if (stype)
+ t = t.addMod(stype.mod);
+ Type origType = t;
+ Type tb = t.toBasetype();
+
+ const hasPointers = tb.hasPointers();
+ if (hasPointers)
+ {
+ if ((stype.alignment() < target.ptrsize ||
+ (v.offset & (target.ptrsize - 1))) &&
+ (sc.func && sc.func.setUnsafe()))
+ {
+ .error(loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code",
+ sd.toChars(), v.toChars());
+ return false;
+ }
+ }
+
+ /* Look for case of initializing a static array with a too-short
+ * string literal, such as:
+ * char[5] foo = "abc";
+ * Allow this by doing an explicit cast, which will lengthen the string
+ * literal.
+ */
+ if (e.op == TOK.string_ && tb.ty == Tsarray)
+ {
+ StringExp se = cast(StringExp)e;
+ Type typeb = se.type.toBasetype();
+ TY tynto = tb.nextOf().ty;
+ if (!se.committed &&
+ (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
+ se.numberOfCodeUnits(tynto) < (cast(TypeSArray)tb).dim.toInteger())
+ {
+ e = se.castTo(sc, t);
+ goto L1;
+ }
+ }
+
+ while (!e.implicitConvTo(t) && tb.ty == Tsarray)
+ {
+ /* Static array initialization, as in:
+ * T[3][5] = e;
+ */
+ t = tb.nextOf();
+ tb = t.toBasetype();
+ }
+ if (!e.implicitConvTo(t))
+ t = origType; // restore type for better diagnostic
+
+ e = e.implicitCastTo(sc, t);
+ L1:
+ if (e.op == TOK.error)
+ return false;
+
+ (*elements)[i] = doCopyOrMove(sc, e);
+ }
+ return true;
+}
+
+
+/**
+ * Returns `em` as a VariableExp
+ * Params:
+ * em = the EnumMember to wrap
+ * loc = location of use of em
+ * sc = scope of use of em
+ * Returns:
+ * VarExp referenceing `em` or ErrorExp if `em` if disabled/deprecated
+ */
+Expression getVarExp(EnumMember em, const ref Loc loc, Scope* sc)
+{
+ dsymbolSemantic(em, sc);
+ if (em.errors)
+ return ErrorExp.get();
+ em.checkDisabled(loc, sc);
+
+ if (em.depdecl && !em.depdecl._scope)
+ em.depdecl._scope = sc;
+ em.checkDeprecated(loc, sc);
+
+ if (em.errors)
+ return ErrorExp.get();
+ Expression e = new VarExp(loc, em);
+ return e.expressionSemantic(sc);
+}
+
+
+/*****************************
+ * Try to treat `exp` as a boolean,
+ * Params:
+ * exp = the expression
+ * sc = scope to evalute `exp` in
+ * Returns:
+ * Modified expression on success, ErrorExp on error
+ */
+Expression toBoolean(Expression exp, Scope* sc)
+{
+ switch(exp.op)
+ {
+ case TOK.delete_:
+ exp.error("`delete` does not give a boolean result");
+ return ErrorExp.get();
+
+ case TOK.comma:
+ auto ce = exp.isCommaExp();
+ auto ex2 = ce.e2.toBoolean(sc);
+ if (ex2.op == TOK.error)
+ return ex2;
+ ce.e2 = ex2;
+ ce.type = ce.e2.type;
+ return ce;
+
+ case TOK.assign:
+ case TOK.construct:
+ case TOK.blit:
+ // Things like:
+ // if (a = b) ...
+ // are usually mistakes.
+ exp.error("assignment cannot be used as a condition, perhaps `==` was meant?");
+ return ErrorExp.get();
+
+ //LogicalExp
+ case TOK.andAnd:
+ case TOK.orOr:
+ auto le = exp.isLogicalExp();
+ auto ex2 = le.e2.toBoolean(sc);
+ if (ex2.op == TOK.error)
+ return ex2;
+ le.e2 = ex2;
+ return le;
+
+ case TOK.question:
+ auto ce = exp.isCondExp();
+ auto ex1 = ce.e1.toBoolean(sc);
+ auto ex2 = ce.e2.toBoolean(sc);
+ if (ex1.op == TOK.error)
+ return ex1;
+ if (ex2.op == TOK.error)
+ return ex2;
+ ce.e1 = ex1;
+ ce.e2 = ex2;
+ return ce;
+
+
+ default:
+ // Default is 'yes' - do nothing
+ Expression e = exp;
+ Type t = exp.type;
+ Type tb = t.toBasetype();
+ Type att = null;
+
+ while (1)
+ {
+ // Structs can be converted to bool using opCast(bool)()
+ if (auto ts = tb.isTypeStruct())
+ {
+ AggregateDeclaration ad = ts.sym;
+ /* Don't really need to check for opCast first, but by doing so we
+ * get better error messages if it isn't there.
+ */
+ if (Dsymbol fd = search_function(ad, Id._cast))
+ {
+ e = new CastExp(exp.loc, e, Type.tbool);
+ e = e.expressionSemantic(sc);
+ return e;
+ }
+
+ // Forward to aliasthis.
+ if (ad.aliasthis && !isRecursiveAliasThis(att, tb))
+ {
+ e = resolveAliasThis(sc, e);
+ t = e.type;
+ tb = e.type.toBasetype();
+ continue;
+ }
+ }
+ break;
+ }
+
+ if (!t.isBoolean())
+ {
+ if (tb != Type.terror)
+ exp.error("expression `%s` of type `%s` does not have a boolean value",
+ exp.toChars(), t.toChars());
+ return ErrorExp.get();
+ }
+ return e;
+ }
+}
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index eff9bc63da4..b73bf62d455 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -3760,32 +3760,32 @@ extern (C++) class StaticCtorDeclaration : FuncDeclaration
return scd;
}
- override final inout(AggregateDeclaration) isThis() inout
+ override final inout(AggregateDeclaration) isThis() inout @nogc nothrow pure @safe
{
return null;
}
- override final bool isVirtual() const
+ override final bool isVirtual() const @nogc nothrow pure @safe
{
return false;
}
- override final bool addPreInvariant()
+ override final bool addPreInvariant() @nogc nothrow pure @safe
{
return false;
}
- override final bool addPostInvariant()
+ override final bool addPostInvariant() @nogc nothrow pure @safe
{
return false;
}
- override final bool hasStaticCtorOrDtor()
+ override final bool hasStaticCtorOrDtor() @nogc nothrow pure @safe
{
return true;
}
- override final inout(StaticCtorDeclaration) isStaticCtorDeclaration() inout
+ override final inout(StaticCtorDeclaration) isStaticCtorDeclaration() inout @nogc nothrow pure @safe
{
return this;
}
@@ -4015,19 +4015,15 @@ extern (C++) final class UnitTestDeclaration : FuncDeclaration
*/
extern (C++) final class NewDeclaration : FuncDeclaration
{
- ParameterList parameterList;
-
- extern (D) this(const ref Loc loc, const ref Loc endloc, StorageClass stc, ref ParameterList parameterList)
+ extern (D) this(const ref Loc loc, StorageClass stc)
{
- super(loc, endloc, Id.classNew, STC.static_ | stc, null);
- this.parameterList = parameterList;
+ super(loc, Loc.initial, Id.classNew, STC.static_ | stc, null);
}
override NewDeclaration syntaxCopy(Dsymbol s)
{
assert(!s);
- auto parameterList = parameterList.syntaxCopy();
- auto f = new NewDeclaration(loc, endloc, storage_class, parameterList);
+ auto f = new NewDeclaration(loc, storage_class);
FuncDeclaration.syntaxCopy(f);
return f;
}
diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d
index 2a355581af6..9b65d024b97 100644
--- a/gcc/d/dmd/globals.d
+++ b/gcc/d/dmd/globals.d
@@ -275,6 +275,7 @@ enum hdr_ext = "di"; // for D 'header' import files
enum json_ext = "json"; // for JSON files
enum map_ext = "map"; // for .map files
enum c_ext = "c"; // for C source files
+enum i_ext = "i"; // for preprocessed C source file
/**
* Collection of global compiler settings and global state used by the frontend
diff --git a/gcc/d/dmd/gluelayer.d b/gcc/d/dmd/gluelayer.d
index 2b733063244..debb9ca62d4 100644
--- a/gcc/d/dmd/gluelayer.d
+++ b/gcc/d/dmd/gluelayer.d
@@ -32,21 +32,6 @@ version (NoBackend)
extern (C++)
{
- version (NoMain) {} else
- {
- import dmd.lib : Library;
-
- // glue
- void obj_write_deferred(Library library) {}
- void obj_start(const(char)* srcfile) {}
- void obj_end(Library library, const(char)* objfilename) {}
- void genObjFile(Module m, bool multiobj) {}
-
- // msc
- void backend_init() {}
- void backend_term() {}
- }
-
// iasm
Statement asmSemantic(AsmStatement s, Scope* sc)
{
@@ -65,8 +50,6 @@ version (NoBackend)
}
else version (MARS)
{
- import dmd.lib : Library;
-
public import dmd.backend.cc : block, Blockx, Symbol;
public import dmd.backend.type : type;
public import dmd.backend.el : elem;
@@ -74,14 +57,6 @@ else version (MARS)
extern (C++)
{
- void obj_write_deferred(Library library);
- void obj_start(const(char)* srcfile);
- void obj_end(Library library, const(char)* objfilename);
- void genObjFile(Module m, bool multiobj);
-
- void backend_init();
- void backend_term();
-
Statement asmSemantic(AsmStatement s, Scope* sc);
void toObjFile(Dsymbol ds, bool multiobj);
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 685acae8dc0..e870612ba7d 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -1765,9 +1765,7 @@ public:
{
if (stcToBuffer(buf, d.storage_class & ~STC.static_))
buf.writeByte(' ');
- buf.writestring("new");
- parametersToBuffer(d.parameterList, buf, hgs);
- bodyToBuffer(d);
+ buf.writestring("new();");
}
override void visit(Module m)
diff --git a/gcc/d/dmd/iasmgcc.d b/gcc/d/dmd/iasmgcc.d
index 2ba9a005a86..e61fb23eb5d 100644
--- a/gcc/d/dmd/iasmgcc.d
+++ b/gcc/d/dmd/iasmgcc.d
@@ -240,13 +240,13 @@ Lerror:
* | GotoAsmInstruction
* |
* | BasicAsmInstruction:
- * | Expression
+ * | AssignExpression
* |
* | ExtAsmInstruction:
- * | Expression : Operands(opt) : Operands(opt) : Clobbers(opt)
+ * | AssignExpression : Operands(opt) : Operands(opt) : Clobbers(opt)
* |
* | GotoAsmInstruction:
- * | Expression : : Operands(opt) : Clobbers(opt) : GotoLabels(opt)
+ * | AssignExpression : : Operands(opt) : Clobbers(opt) : GotoLabels(opt)
* Params:
* p = parser state
* s = asm statement to parse
@@ -255,7 +255,7 @@ Lerror:
*/
GccAsmStatement parseGccAsm(Parser)(Parser p, GccAsmStatement s)
{
- s.insn = p.parseExpression();
+ s.insn = p.parseAssignExp();
if (p.token.value == TOK.semicolon || p.token.value == TOK.endOfFile)
goto Ldone;
@@ -523,6 +523,10 @@ unittest
:
: "g" (a ? b : : c);
} },
+
+ // Found ',' when expecting ':'
+ q{ asm { "", "";
+ } },
];
foreach (test; passAsmTests)
diff --git a/gcc/d/dmd/identifier.h b/gcc/d/dmd/identifier.h
index 986f479f497..790d5a036d4 100644
--- a/gcc/d/dmd/identifier.h
+++ b/gcc/d/dmd/identifier.h
@@ -11,7 +11,7 @@
#pragma once
#include "root/dcompat.h"
-#include "root/root.h"
+#include "root/object.h"
class Identifier : public RootObject
{
diff --git a/gcc/d/dmd/init.d b/gcc/d/dmd/init.d
index 1df109af99f..45e101b903a 100644
--- a/gcc/d/dmd/init.d
+++ b/gcc/d/dmd/init.d
@@ -64,33 +64,33 @@ extern (C++) class Initializer : ASTNode
return buf.extractChars();
}
- final inout(ErrorInitializer) isErrorInitializer() inout pure
+ final inout(ErrorInitializer) isErrorInitializer() inout @nogc nothrow pure
{
// Use void* cast to skip dynamic casting call
return kind == InitKind.error ? cast(inout ErrorInitializer)cast(void*)this : null;
}
- final inout(VoidInitializer) isVoidInitializer() inout pure
+ final inout(VoidInitializer) isVoidInitializer() inout @nogc nothrow pure
{
return kind == InitKind.void_ ? cast(inout VoidInitializer)cast(void*)this : null;
}
- final inout(StructInitializer) isStructInitializer() inout pure
+ final inout(StructInitializer) isStructInitializer() inout @nogc nothrow pure
{
return kind == InitKind.struct_ ? cast(inout StructInitializer)cast(void*)this : null;
}
- final inout(ArrayInitializer) isArrayInitializer() inout pure
+ final inout(ArrayInitializer) isArrayInitializer() inout @nogc nothrow pure
{
return kind == InitKind.array ? cast(inout ArrayInitializer)cast(void*)this : null;
}
- final inout(ExpInitializer) isExpInitializer() inout pure
+ final inout(ExpInitializer) isExpInitializer() inout @nogc nothrow pure
{
return kind == InitKind.exp ? cast(inout ExpInitializer)cast(void*)this : null;
}
- final inout(CInitializer) isCInitializer() inout pure
+ final inout(CInitializer) isCInitializer() inout @nogc nothrow pure
{
return kind == InitKind.C_ ? cast(inout CInitializer)cast(void*)this : null;
}
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 1554fc722a1..c7f4be1bb25 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -2593,7 +2593,7 @@ extern (C++) abstract class Type : ASTNode
}
}
- final pure inout nothrow @nogc
+ final pure inout nothrow @nogc @safe
{
inout(TypeError) isTypeError() { return ty == Terror ? cast(typeof(return))this : null; }
inout(TypeVector) isTypeVector() { return ty == Tvector ? cast(typeof(return))this : null; }
@@ -7025,53 +7025,16 @@ extern (C++) final class Parameter : ASTNode
if (from == to)
return true;
- /* Shrinking the representation is necessary because StorageClass is so wide
- * Params:
- * returnByRef = true if the function returns by ref
- * stc = storage class of parameter
- */
- static uint buildSR(bool returnByRef, StorageClass stc) pure nothrow @nogc @safe
- {
- uint result;
- final switch (stc & (STC.ref_ | STC.scope_ | STC.return_))
- {
- case 0: result = SR.None; break;
- case STC.ref_: result = SR.Ref; break;
- case STC.scope_: result = SR.Scope; break;
- case STC.return_ | STC.ref_: result = SR.ReturnRef; break;
- case STC.return_ | STC.scope_: result = SR.ReturnScope; break;
- case STC.ref_ | STC.scope_: result = SR.RefScope; break;
- case STC.return_ | STC.ref_ | STC.scope_:
- result = returnByRef ? SR.ReturnRef_Scope : SR.Ref_ReturnScope;
- break;
- }
- return result;
- }
-
/* result is true if the 'from' can be used as a 'to'
*/
if ((from ^ to) & STC.ref_) // differing in 'ref' means no covariance
return false;
- return covariant[buildSR(returnByRef, from)][buildSR(returnByRef, to)];
+ return covariant[buildScopeRef(returnByRef, from)][buildScopeRef(returnByRef, to)];
}
- /* Classification of 'scope-return-ref' possibilities
- */
- private enum SR
- {
- None,
- Scope,
- ReturnScope,
- Ref,
- ReturnRef,
- RefScope,
- ReturnRef_Scope,
- Ref_ReturnScope,
- }
-
- extern (D) private static bool[SR.max + 1][SR.max + 1] covariantInit() pure nothrow @nogc @safe
+ extern (D) private static bool[ScopeRef.max + 1][ScopeRef.max + 1] covariantInit() pure nothrow @nogc @safe
{
/* Initialize covariant[][] with this:
@@ -7087,26 +7050,26 @@ extern (C++) final class Parameter : ASTNode
ReturnRef-Scope X X
Ref-ReturnScope X X X
*/
- bool[SR.max + 1][SR.max + 1] covariant;
+ bool[ScopeRef.max + 1][ScopeRef.max + 1] covariant;
- foreach (i; 0 .. SR.max + 1)
+ foreach (i; 0 .. ScopeRef.max + 1)
{
covariant[i][i] = true;
- covariant[SR.RefScope][i] = true;
+ covariant[ScopeRef.RefScope][i] = true;
}
- covariant[SR.ReturnScope][SR.None] = true;
- covariant[SR.Scope ][SR.None] = true;
- covariant[SR.Scope ][SR.ReturnScope] = true;
+ covariant[ScopeRef.ReturnScope][ScopeRef.None] = true;
+ covariant[ScopeRef.Scope ][ScopeRef.None] = true;
+ covariant[ScopeRef.Scope ][ScopeRef.ReturnScope] = true;
- covariant[SR.Ref ][SR.ReturnRef] = true;
- covariant[SR.ReturnRef_Scope][SR.ReturnRef] = true;
- covariant[SR.Ref_ReturnScope][SR.Ref ] = true;
- covariant[SR.Ref_ReturnScope][SR.ReturnRef] = true;
+ covariant[ScopeRef.Ref ][ScopeRef.ReturnRef] = true;
+ covariant[ScopeRef.ReturnRef_Scope][ScopeRef.ReturnRef] = true;
+ covariant[ScopeRef.Ref_ReturnScope][ScopeRef.Ref ] = true;
+ covariant[ScopeRef.Ref_ReturnScope][ScopeRef.ReturnRef] = true;
return covariant;
}
- extern (D) private static immutable bool[SR.max + 1][SR.max + 1] covariant = covariantInit();
+ extern (D) private static immutable bool[ScopeRef.max + 1][ScopeRef.max + 1] covariant = covariantInit();
extern (D) bool opEquals(const Parameter other) const
{
@@ -7252,3 +7215,53 @@ bool isCopyable(Type t)
}
return true;
}
+
+/***************************************
+ * Computes how a parameter may be returned.
+ * Shrinking the representation is necessary because StorageClass is so wide
+ * Params:
+ * returnByRef = true if the function returns by ref
+ * stc = storage class of parameter
+ * Returns:
+ * value from enum ScopeRef
+ */
+ScopeRef buildScopeRef(bool returnByRef, StorageClass stc) pure nothrow @nogc @safe
+{
+ if (stc & STC.out_)
+ stc |= STC.ref_; // treat `out` and `ref` the same
+
+ ScopeRef result;
+ final switch (stc & (STC.ref_ | STC.scope_ | STC.return_))
+ {
+ case STC.return_:
+ case 0: result = ScopeRef.None; break;
+ case STC.ref_: result = ScopeRef.Ref; break;
+ case STC.scope_: result = ScopeRef.Scope; break;
+ case STC.return_ | STC.ref_: result = ScopeRef.ReturnRef; break;
+ case STC.return_ | STC.scope_: result = ScopeRef.ReturnScope; break;
+ case STC.ref_ | STC.scope_: result = ScopeRef.RefScope; break;
+
+ case STC.return_ | STC.ref_ | STC.scope_:
+ result = returnByRef ? ScopeRef.ReturnRef_Scope
+ : ScopeRef.Ref_ReturnScope;
+ break;
+ }
+ return result;
+}
+
+/**
+ * Classification of 'scope-return-ref' possibilities
+ */
+enum ScopeRef
+{
+ None,
+ Scope,
+ ReturnScope,
+ Ref,
+ ReturnRef,
+ RefScope,
+ ReturnRef_Scope,
+ Ref_ReturnScope,
+}
+
+
diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d
index 7d134a966ca..4bb2907c9ba 100644
--- a/gcc/d/dmd/nogc.d
+++ b/gcc/d/dmd/nogc.d
@@ -122,8 +122,6 @@ public:
}
if (e.onstack)
return;
- if (e.allocator)
- return;
if (global.params.ehnogc && e.thrownew)
return; // separate allocator is called for this, not the GC
if (f.setGC())
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index 5a5fb0b73ed..3ae30619a20 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -461,7 +461,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
if (e.e1.op == TOK.variable)
{
VarExp ve = cast(VarExp)e.e1;
- if (!ve.var.isOut() && !ve.var.isRef() && !ve.var.isImportedSymbol())
+ if (!ve.var.isReference() && !ve.var.isImportedSymbol())
{
ret = new SymOffExp(e.loc, ve.var, 0, ve.hasOverloads);
ret.type = e.type;
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 572f1782cea..34635eac7e4 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -1482,7 +1482,11 @@ class Parser(AST) : Lexer
return 0;
}
- error("`@identifier` or `@(ArgumentList)` expected, not `@%s`", token.toChars());
+ if (token.isKeyword())
+ error("`%s` is a keyword, not an `@` attribute", token.toChars());
+ else
+ error("`@identifier` or `@(ArgumentList)` expected, not `@%s`", token.toChars());
+
return 0;
}
@@ -2818,20 +2822,47 @@ class Parser(AST) : Lexer
/*****************************************
* Parse a new definition:
- * new(parameters) { body }
+ * @disable new();
* Current token is 'new'.
*/
private AST.Dsymbol parseNew(PrefixAttributes!AST* pAttrs)
{
const loc = token.loc;
StorageClass stc = getStorageClass!AST(pAttrs);
-
+ if (!(stc & STC.disable))
+ {
+ error("`new` allocator must be annotated with `@disabled`");
+ }
nextToken();
- auto parameterList = parseParameterList(null);
- auto f = new AST.NewDeclaration(loc, Loc.initial, stc, parameterList);
- AST.Dsymbol s = parseContracts(f);
- return s;
+ /* @@@DEPRECATED_2.098@@@
+ * After deprecation period (2.108), remove all code in the version(all) block.
+ */
+ version (all)
+ {
+ auto parameterList = parseParameterList(null); // parameterList ignored
+ if (parameterList.parameters.length > 0 || parameterList.varargs != VarArg.none)
+ deprecation("`new` allocator with non-empty parameter list is deprecated");
+ auto f = new AST.NewDeclaration(loc, stc);
+ if (token.value != TOK.semicolon)
+ {
+ deprecation("`new` allocator with function definition is deprecated");
+ parseContracts(f); // body ignored
+ f.fbody = null;
+ f.fensures = null;
+ f.frequires = null;
+ }
+ else
+ nextToken();
+ return f;
+ }
+ else
+ {
+ check(TOK.leftParenthesis);
+ check(TOK.rightParenthesis);
+ check(TOK.semicolon);
+ return new AST.NewDeclaration(loc, stc);
+ }
}
/**********************************************
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index 79c3272870f..728b1df790f 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -1112,7 +1112,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
foreach (v; *funcdecl.parameters)
{
- if (v.storage_class & (STC.ref_ | STC.out_ | STC.lazy_))
+ if (v.isReference() || (v.storage_class & STC.lazy_))
continue;
if (v.needsScopeDtor())
{
@@ -1570,3 +1570,55 @@ private struct FuncDeclSem3
}
}
}
+
+private void semanticTypeInfoMembers(StructDeclaration sd)
+{
+ if (sd.xeq &&
+ sd.xeq._scope &&
+ sd.xeq.semanticRun < PASS.semantic3done)
+ {
+ uint errors = global.startGagging();
+ sd.xeq.semantic3(sd.xeq._scope);
+ if (global.endGagging(errors))
+ sd.xeq = sd.xerreq;
+ }
+
+ if (sd.xcmp &&
+ sd.xcmp._scope &&
+ sd.xcmp.semanticRun < PASS.semantic3done)
+ {
+ uint errors = global.startGagging();
+ sd.xcmp.semantic3(sd.xcmp._scope);
+ if (global.endGagging(errors))
+ sd.xcmp = sd.xerrcmp;
+ }
+
+ FuncDeclaration ftostr = search_toString(sd);
+ if (ftostr &&
+ ftostr._scope &&
+ ftostr.semanticRun < PASS.semantic3done)
+ {
+ ftostr.semantic3(ftostr._scope);
+ }
+
+ if (sd.xhash &&
+ sd.xhash._scope &&
+ sd.xhash.semanticRun < PASS.semantic3done)
+ {
+ sd.xhash.semantic3(sd.xhash._scope);
+ }
+
+ if (sd.postblit &&
+ sd.postblit._scope &&
+ sd.postblit.semanticRun < PASS.semantic3done)
+ {
+ sd.postblit.semantic3(sd.postblit._scope);
+ }
+
+ if (sd.dtor &&
+ sd.dtor._scope &&
+ sd.dtor.semanticRun < PASS.semantic3done)
+ {
+ sd.dtor.semantic3(sd.dtor._scope);
+ }
+}
diff --git a/gcc/d/dmd/statement.d b/gcc/d/dmd/statement.d
index f76f37edceb..b49c9035d3f 100644
--- a/gcc/d/dmd/statement.d
+++ b/gcc/d/dmd/statement.d
@@ -18,8 +18,6 @@ import core.stdc.stdio;
import dmd.aggregate;
import dmd.arraytypes;
-import dmd.attrib;
-import dmd.astcodegen;
import dmd.astenums;
import dmd.ast_node;
import dmd.gluelayer;
@@ -31,11 +29,9 @@ import dmd.denum;
import dmd.dimport;
import dmd.dscope;
import dmd.dsymbol;
-import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.errors;
import dmd.expression;
-import dmd.expressionsem;
import dmd.func;
import dmd.globals;
import dmd.hdrgen;
@@ -43,7 +39,6 @@ import dmd.id;
import dmd.identifier;
import dmd.dinterpret;
import dmd.mtype;
-import dmd.parse;
import dmd.root.outbuffer;
import dmd.root.rootobject;
import dmd.sapply;
@@ -327,40 +322,6 @@ extern (C++) abstract class Statement : ASTNode
return walkPostorder(this, hc);
}
- /****************************************
- * If this statement has code that needs to run in a finally clause
- * at the end of the current scope, return that code in the form of
- * a Statement.
- * Params:
- * sc = context
- * sentry = set to code executed upon entry to the scope
- * sexception = set to code executed upon exit from the scope via exception
- * sfinally = set to code executed in finally block
- * Returns:
- * code to be run in the finally clause
- */
- Statement scopeCode(Scope* sc, Statement* sentry, Statement* sexception, Statement* sfinally)
- {
- //printf("Statement::scopeCode()\n");
- *sentry = null;
- *sexception = null;
- *sfinally = null;
- return this;
- }
-
- /*********************************
- * Flatten out the scope by presenting the statement
- * as an array of statements.
- * Params:
- * sc = context
- * Returns:
- * The array of `Statements`, or `null` if no flattening necessary
- */
- Statements* flatten(Scope* sc)
- {
- return null;
- }
-
/*******************************
* Find last statement in a sequence of statements.
* Returns:
@@ -392,7 +353,7 @@ extern (C++) abstract class Statement : ASTNode
pure nothrow @nogc
inout(ReturnStatement) endsWithReturnStatement() inout { return null; }
- final pure inout nothrow @nogc:
+ final pure inout nothrow @nogc @safe:
/********************
* A cheaper method of doing downcasting of Statements.
@@ -405,6 +366,8 @@ extern (C++) abstract class Statement : ASTNode
inout(CompoundStatement) isCompoundStatement() { return stmt == STMT.Compound ? cast(typeof(return))this : null; }
inout(ReturnStatement) isReturnStatement() { return stmt == STMT.Return ? cast(typeof(return))this : null; }
inout(IfStatement) isIfStatement() { return stmt == STMT.If ? cast(typeof(return))this : null; }
+ inout(ConditionalStatement) isConditionalStatement() { return stmt == STMT.Conditional ? cast(typeof(return))this : null; }
+ inout(StaticForeachStatement) isStaticForeachStatement() { return stmt == STMT.StaticForeach ? cast(typeof(return))this : null; }
inout(CaseStatement) isCaseStatement() { return stmt == STMT.Case ? cast(typeof(return))this : null; }
inout(DefaultStatement) isDefaultStatement() { return stmt == STMT.Default ? cast(typeof(return))this : null; }
inout(LabelStatement) isLabelStatement() { return stmt == STMT.Label ? cast(typeof(return))this : null; }
@@ -413,6 +376,7 @@ extern (C++) abstract class Statement : ASTNode
inout(GotoCaseStatement) isGotoCaseStatement() { return stmt == STMT.GotoCase ? cast(typeof(return))this : null; }
inout(BreakStatement) isBreakStatement() { return stmt == STMT.Break ? cast(typeof(return))this : null; }
inout(DtorExpStatement) isDtorExpStatement() { return stmt == STMT.DtorExp ? cast(typeof(return))this : null; }
+ inout(CompileStatement) isCompileStatement() { return stmt == STMT.Compile ? cast(typeof(return))this : null; }
inout(ForwardingStatement) isForwardingStatement() { return stmt == STMT.Forwarding ? cast(typeof(return))this : null; }
inout(DoStatement) isDoStatement() { return stmt == STMT.Do ? cast(typeof(return))this : null; }
inout(WhileStatement) isWhileStatement() { return stmt == STMT.While ? cast(typeof(return))this : null; }
@@ -423,7 +387,9 @@ extern (C++) abstract class Statement : ASTNode
inout(WithStatement) isWithStatement() { return stmt == STMT.With ? cast(typeof(return))this : null; }
inout(TryCatchStatement) isTryCatchStatement() { return stmt == STMT.TryCatch ? cast(typeof(return))this : null; }
inout(ThrowStatement) isThrowStatement() { return stmt == STMT.Throw ? cast(typeof(return))this : null; }
+ inout(DebugStatement) isDebugStatement() { return stmt == STMT.Debug ? cast(typeof(return))this : null; }
inout(TryFinallyStatement) isTryFinallyStatement() { return stmt == STMT.TryFinally ? cast(typeof(return))this : null; }
+ inout(ScopeGuardStatement) isScopeGuardStatement() { return stmt == STMT.ScopeGuard ? cast(typeof(return))this : null; }
inout(SwitchErrorStatement) isSwitchErrorStatement() { return stmt == STMT.SwitchError ? cast(typeof(return))this : null; }
inout(UnrolledLoopStatement) isUnrolledLoopStatement() { return stmt == STMT.UnrolledLoop ? cast(typeof(return))this : null; }
inout(ForeachRangeStatement) isForeachRangeStatement() { return stmt == STMT.ForeachRange ? cast(typeof(return))this : null; }
@@ -471,163 +437,6 @@ extern (C++) final class PeelStatement : Statement
}
}
-/***********************************************************
- * Convert TemplateMixin members (== Dsymbols) to Statements.
- */
-private Statement toStatement(Dsymbol s)
-{
- extern (C++) final class ToStmt : Visitor
- {
- alias visit = Visitor.visit;
- public:
- Statement result;
-
- Statement visitMembers(Loc loc, Dsymbols* a)
- {
- if (!a)
- return null;
-
- auto statements = new Statements();
- foreach (s; *a)
- {
- statements.push(toStatement(s));
- }
- return new CompoundStatement(loc, statements);
- }
-
- override void visit(Dsymbol s)
- {
- .error(Loc.initial, "Internal Compiler Error: cannot mixin %s `%s`\n", s.kind(), s.toChars());
- result = new ErrorStatement();
- }
-
- override void visit(TemplateMixin tm)
- {
- auto a = new Statements();
- foreach (m; *tm.members)
- {
- Statement s = toStatement(m);
- if (s)
- a.push(s);
- }
- result = new CompoundStatement(tm.loc, a);
- }
-
- /* An actual declaration symbol will be converted to DeclarationExp
- * with ExpStatement.
- */
- Statement declStmt(Dsymbol s)
- {
- auto de = new DeclarationExp(s.loc, s);
- de.type = Type.tvoid; // avoid repeated semantic
- return new ExpStatement(s.loc, de);
- }
-
- override void visit(VarDeclaration d)
- {
- result = declStmt(d);
- }
-
- override void visit(AggregateDeclaration d)
- {
- result = declStmt(d);
- }
-
- override void visit(FuncDeclaration d)
- {
- result = declStmt(d);
- }
-
- override void visit(EnumDeclaration d)
- {
- result = declStmt(d);
- }
-
- override void visit(AliasDeclaration d)
- {
- result = declStmt(d);
- }
-
- override void visit(TemplateDeclaration d)
- {
- result = declStmt(d);
- }
-
- /* All attributes have been already picked by the semantic analysis of
- * 'bottom' declarations (function, struct, class, etc).
- * So we don't have to copy them.
- */
- override void visit(StorageClassDeclaration d)
- {
- result = visitMembers(d.loc, d.decl);
- }
-
- override void visit(DeprecatedDeclaration d)
- {
- result = visitMembers(d.loc, d.decl);
- }
-
- override void visit(LinkDeclaration d)
- {
- result = visitMembers(d.loc, d.decl);
- }
-
- override void visit(VisibilityDeclaration d)
- {
- result = visitMembers(d.loc, d.decl);
- }
-
- override void visit(AlignDeclaration d)
- {
- result = visitMembers(d.loc, d.decl);
- }
-
- override void visit(UserAttributeDeclaration d)
- {
- result = visitMembers(d.loc, d.decl);
- }
-
- override void visit(ForwardingAttribDeclaration d)
- {
- result = visitMembers(d.loc, d.decl);
- }
-
- override void visit(StaticAssert s)
- {
- }
-
- override void visit(Import s)
- {
- }
-
- override void visit(PragmaDeclaration d)
- {
- }
-
- override void visit(ConditionalDeclaration d)
- {
- result = visitMembers(d.loc, d.include(null));
- }
-
- override void visit(StaticForeachDeclaration d)
- {
- assert(d.sfe && !!d.sfe.aggrfe ^ !!d.sfe.rangefe);
- result = visitMembers(d.loc, d.include(null));
- }
-
- override void visit(CompileDeclaration d)
- {
- result = visitMembers(d.loc, d.include(null));
- }
- }
-
- if (!s)
- return null;
-
- scope ToStmt v = new ToStmt();
- s.accept(v);
- return v.result;
-}
/***********************************************************
* https://dlang.org/spec/statement.html#ExpressionStatement
@@ -664,68 +473,6 @@ extern (C++) class ExpStatement : Statement
return new ExpStatement(loc, exp ? exp.syntaxCopy() : null);
}
- override final Statement scopeCode(Scope* sc, Statement* sentry, Statement* sexception, Statement* sfinally)
- {
- //printf("ExpStatement::scopeCode()\n");
-
- *sentry = null;
- *sexception = null;
- *sfinally = null;
-
- if (exp && exp.op == TOK.declaration)
- {
- auto de = cast(DeclarationExp)exp;
- auto v = de.declaration.isVarDeclaration();
- if (v && !v.isDataseg())
- {
- if (v.needsScopeDtor())
- {
- *sfinally = new DtorExpStatement(loc, v.edtor, v);
- v.storage_class |= STC.nodtor; // don't add in dtor again
- }
- }
- }
- return this;
- }
-
- override final Statements* flatten(Scope* sc)
- {
- /* https://issues.dlang.org/show_bug.cgi?id=14243
- * expand template mixin in statement scope
- * to handle variable destructors.
- */
- if (exp && exp.op == TOK.declaration)
- {
- Dsymbol d = (cast(DeclarationExp)exp).declaration;
- if (TemplateMixin tm = d.isTemplateMixin())
- {
- Expression e = exp.expressionSemantic(sc);
- if (e.op == TOK.error || tm.errors)
- {
- auto a = new Statements();
- a.push(new ErrorStatement());
- return a;
- }
- assert(tm.members);
-
- Statement s = toStatement(tm);
- version (none)
- {
- OutBuffer buf;
- buf.doindent = 1;
- HdrGenState hgs;
- hgs.hdrgen = true;
- toCBuffer(s, &buf, &hgs);
- printf("tm ==> s = %s\n", buf.peekChars());
- }
- auto a = new Statements();
- a.push(s);
- return a;
- }
- }
- return null;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -781,46 +528,6 @@ extern (C++) final class CompileStatement : Statement
return new CompileStatement(loc, Expression.arraySyntaxCopy(exps));
}
- private Statements* compileIt(Scope* sc)
- {
- //printf("CompileStatement::compileIt() %s\n", exp.toChars());
-
- auto errorStatements()
- {
- auto a = new Statements();
- a.push(new ErrorStatement());
- return a;
- }
-
-
- OutBuffer buf;
- if (expressionsToString(buf, sc, exps))
- return errorStatements();
-
- const errors = global.errors;
- const len = buf.length;
- buf.writeByte(0);
- const str = buf.extractSlice()[0 .. len];
- scope p = new Parser!ASTCodegen(loc, sc._module, str, false);
- p.nextToken();
-
- auto a = new Statements();
- while (p.token.value != TOK.endOfFile)
- {
- Statement s = p.parseStatement(ParseStatementFlags.semi | ParseStatementFlags.curlyScope);
- if (!s || global.errors != errors)
- return errorStatements();
- a.push(s);
- }
- return a;
- }
-
- override Statements* flatten(Scope* sc)
- {
- //printf("CompileStatement::flatten() %s\n", exp.toChars());
- return compileIt(sc);
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -880,11 +587,6 @@ extern (C++) class CompoundStatement : Statement
return new CompoundStatement(loc, Statement.arraySyntaxCopy(statements));
}
- override Statements* flatten(Scope* sc)
- {
- return statements;
- }
-
override final inout(ReturnStatement) endsWithReturnStatement() inout nothrow pure
{
foreach (s; *statements)
@@ -1062,39 +764,6 @@ extern (C++) final class ForwardingStatement : Statement
return new ForwardingStatement(loc, statement.syntaxCopy());
}
- /***********************
- * ForwardingStatements are distributed over the flattened
- * sequence of statements. This prevents flattening to be
- * "blocked" by a ForwardingStatement and is necessary, for
- * example, to support generating scope guards with `static
- * foreach`:
- *
- * static foreach(i; 0 .. 10) scope(exit) writeln(i);
- * writeln("this is printed first");
- * // then, it prints 10, 9, 8, 7, ...
- */
-
- override Statements* flatten(Scope* sc)
- {
- if (!statement)
- {
- return null;
- }
- sc = sc.push(sym);
- auto a = statement.flatten(sc);
- sc = sc.pop();
- if (!a)
- {
- return a;
- }
- auto b = new Statements(a.dim);
- foreach (i, s; *a)
- {
- (*b)[i] = s ? new ForwardingStatement(s.loc, sym, s) : null;
- }
- return b;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -1222,13 +891,6 @@ extern (C++) final class ForStatement : Statement
endloc);
}
- override Statement scopeCode(Scope* sc, Statement* sentry, Statement* sexception, Statement* sfinally)
- {
- //printf("ForStatement::scopeCode()\n");
- Statement.scopeCode(sc, sentry, sexception, sfinally);
- return this;
- }
-
override Statement getRelatedLabeled()
{
return relatedLabeled ? relatedLabeled : this;
@@ -1411,66 +1073,12 @@ extern (C++) final class ConditionalStatement : Statement
return new ConditionalStatement(loc, condition.syntaxCopy(), ifbody.syntaxCopy(), elsebody ? elsebody.syntaxCopy() : null);
}
- override Statements* flatten(Scope* sc)
- {
- Statement s;
-
- //printf("ConditionalStatement::flatten()\n");
- if (condition.include(sc))
- {
- DebugCondition dc = condition.isDebugCondition();
- if (dc)
- {
- s = new DebugStatement(loc, ifbody);
- debugThrowWalker(ifbody);
- }
- else
- s = ifbody;
- }
- else
- s = elsebody;
-
- auto a = new Statements();
- a.push(s);
- return a;
- }
-
override void accept(Visitor v)
{
v.visit(this);
}
}
-/**
-Marks all occurring ThrowStatements as internalThrows.
-This is intended to be called from a DebugStatement as it allows
-to mark all its nodes as nothrow.
-
-Params:
- s = AST Node to traverse
-*/
-private void debugThrowWalker(Statement s)
-{
-
- extern(C++) final class DebugWalker : SemanticTimeTransitiveVisitor
- {
- alias visit = SemanticTimeTransitiveVisitor.visit;
- public:
-
- override void visit(ThrowStatement s)
- {
- s.internalThrow = true;
- }
-
- override void visit(CallExp s)
- {
- s.inDebugStatement = true;
- }
- }
-
- scope walker = new DebugWalker();
- s.accept(walker);
-}
/***********************************************************
* https://dlang.org/spec/version.html#StaticForeachStatement
@@ -1498,30 +1106,6 @@ extern (C++) final class StaticForeachStatement : Statement
return new StaticForeachStatement(loc, sfe.syntaxCopy());
}
- override Statements* flatten(Scope* sc)
- {
- sfe.prepare(sc);
- if (sfe.ready())
- {
- import dmd.statementsem;
- auto s = makeTupleForeach!(true, false)(sc, sfe.aggrfe, sfe.needExpansion);
- auto result = s.flatten(sc);
- if (result)
- {
- return result;
- }
- result = new Statements();
- result.push(s);
- return result;
- }
- else
- {
- auto result = new Statements();
- result.push(new ErrorStatement());
- return result;
- }
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -2097,52 +1681,6 @@ extern (C++) final class ScopeGuardStatement : Statement
return new ScopeGuardStatement(loc, tok, statement.syntaxCopy());
}
- override Statement scopeCode(Scope* sc, Statement* sentry, Statement* sexception, Statement* sfinally)
- {
- //printf("ScopeGuardStatement::scopeCode()\n");
- *sentry = null;
- *sexception = null;
- *sfinally = null;
-
- Statement s = new PeelStatement(statement);
-
- switch (tok)
- {
- case TOK.onScopeExit:
- *sfinally = s;
- break;
-
- case TOK.onScopeFailure:
- *sexception = s;
- break;
-
- case TOK.onScopeSuccess:
- {
- /* Create:
- * sentry: bool x = false;
- * sexception: x = true;
- * sfinally: if (!x) statement;
- */
- auto v = copyToTemp(0, "__os", IntegerExp.createBool(false));
- v.dsymbolSemantic(sc);
- *sentry = new ExpStatement(loc, v);
-
- Expression e = IntegerExp.createBool(true);
- e = new AssignExp(Loc.initial, new VarExp(Loc.initial, v), e);
- *sexception = new ExpStatement(Loc.initial, e);
-
- e = new VarExp(Loc.initial, v);
- e = new NotExp(Loc.initial, e);
- *sfinally = new IfStatement(Loc.initial, null, e, s, null, Loc.initial);
-
- break;
- }
- default:
- assert(0);
- }
- return null;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -2195,19 +1733,6 @@ extern (C++) final class DebugStatement : Statement
return new DebugStatement(loc, statement ? statement.syntaxCopy() : null);
}
- override Statements* flatten(Scope* sc)
- {
- Statements* a = statement ? statement.flatten(sc) : null;
- if (a)
- {
- foreach (ref s; *a)
- {
- s = new DebugStatement(loc, s);
- }
- }
- return a;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -2343,41 +1868,6 @@ extern (C++) final class LabelStatement : Statement
return new LabelStatement(loc, ident, statement ? statement.syntaxCopy() : null);
}
- override Statements* flatten(Scope* sc)
- {
- Statements* a = null;
- if (statement)
- {
- a = statement.flatten(sc);
- if (a)
- {
- if (!a.dim)
- {
- a.push(new ExpStatement(loc, cast(Expression)null));
- }
-
- // reuse 'this' LabelStatement
- this.statement = (*a)[0];
- (*a)[0] = this;
- }
- }
- return a;
- }
-
- override Statement scopeCode(Scope* sc, Statement* sentry, Statement* sexit, Statement* sfinally)
- {
- //printf("LabelStatement::scopeCode()\n");
- if (statement)
- statement = statement.scopeCode(sc, sentry, sexit, sfinally);
- else
- {
- *sentry = null;
- *sexit = null;
- *sfinally = null;
- }
- return this;
- }
-
override void accept(Visitor v)
{
v.visit(this);
@@ -2527,11 +2017,6 @@ extern (C++) final class CompoundAsmStatement : CompoundStatement
return new CompoundAsmStatement(loc, a, stc);
}
- override Statements* flatten(Scope* sc)
- {
- return null;
- }
-
override void accept(Visitor v)
{
v.visit(this);
diff --git a/gcc/d/dmd/statement.h b/gcc/d/dmd/statement.h
index 58937724f53..7825762db9e 100644
--- a/gcc/d/dmd/statement.h
+++ b/gcc/d/dmd/statement.h
@@ -122,8 +122,6 @@ public:
bool usesEH();
bool comeFrom();
bool hasCode();
- virtual Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
- virtual Statements *flatten(Scope *sc);
virtual Statement *last();
virtual ReturnStatement *endsWithReturnStatement() { return NULL; }
@@ -134,6 +132,8 @@ public:
CompoundStatement *isCompoundStatement() { return stmt == STMTcompound ? (CompoundStatement*)this : NULL; }
ReturnStatement *isReturnStatement() { return stmt == STMTreturn ? (ReturnStatement*)this : NULL; }
IfStatement *isIfStatement() { return stmt == STMTif ? (IfStatement*)this : NULL; }
+ ConditionalStatement *isConditionalStatement() { return stmt == STMTconditional ? (ConditionalStatement*)this : NULL; }
+ StaticForeachStatement *isStaticForeachStatement() { return stmt == STMTstaticForeach ? (StaticForeachStatement*)this : NULL; }
CaseStatement *isCaseStatement() { return stmt == STMTcase ? (CaseStatement*)this : NULL; }
DefaultStatement *isDefaultStatement() { return stmt == STMTdefault ? (DefaultStatement*)this : NULL; }
LabelStatement *isLabelStatement() { return stmt == STMTlabel ? (LabelStatement*)this : NULL; }
@@ -141,6 +141,7 @@ public:
GotoCaseStatement *isGotoCaseStatement() { return stmt == STMTgotoCase ? (GotoCaseStatement*)this : NULL; }
BreakStatement *isBreakStatement() { return stmt == STMTbreak ? (BreakStatement*)this : NULL; }
DtorExpStatement *isDtorExpStatement() { return stmt == STMTdtorExp ? (DtorExpStatement*)this : NULL; }
+ CompileStatement *isCompileStatement() { return stmt == STMTcompile ? (CompileStatement*)this : NULL; }
ForwardingStatement *isForwardingStatement() { return stmt == STMTforwarding ? (ForwardingStatement*)this : NULL; }
DoStatement *isDoStatement() { return stmt == STMTdo ? (DoStatement*)this : NULL; }
ForStatement *isForStatement() { return stmt == STMTfor ? (ForStatement*)this : NULL; }
@@ -150,7 +151,9 @@ public:
WithStatement *isWithStatement() { return stmt == STMTwith ? (WithStatement*)this : NULL; }
TryCatchStatement *isTryCatchStatement() { return stmt == STMTtryCatch ? (TryCatchStatement*)this : NULL; }
ThrowStatement *isThrowStatement() { return stmt == STMTthrow ? (ThrowStatement*)this : NULL; }
+ DebugStatement *isDebugStatement() { return stmt == STMTdebug ? (DebugStatement*)this : NULL; }
TryFinallyStatement *isTryFinallyStatement() { return stmt == STMTtryFinally ? (TryFinallyStatement*)this : NULL; }
+ ScopeGuardStatement *isScopeGuardStatement() { return stmt == STMTscopeGuard ? (ScopeGuardStatement*)this : NULL; }
SwitchErrorStatement *isSwitchErrorStatement() { return stmt == STMTswitchError ? (SwitchErrorStatement*)this : NULL; }
UnrolledLoopStatement *isUnrolledLoopStatement() { return stmt == STMTunrolledLoop ? (UnrolledLoopStatement*)this : NULL; }
ForeachRangeStatement *isForeachRangeStatement() { return stmt == STMTforeachRange ? (ForeachRangeStatement*)this : NULL; }
@@ -185,8 +188,6 @@ public:
static ExpStatement *create(Loc loc, Expression *exp);
ExpStatement *syntaxCopy();
- Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
- Statements *flatten(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
};
@@ -209,7 +210,6 @@ public:
Expressions *exps;
CompileStatement *syntaxCopy();
- Statements *flatten(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
};
@@ -220,7 +220,6 @@ public:
static CompoundStatement *create(Loc loc, Statement *s1, Statement *s2);
CompoundStatement *syntaxCopy();
- Statements *flatten(Scope *sc);
ReturnStatement *endsWithReturnStatement();
Statement *last();
@@ -270,7 +269,6 @@ public:
Statement *statement;
ForwardingStatement *syntaxCopy();
- Statements *flatten(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
};
@@ -318,7 +316,6 @@ public:
Statement *relatedLabeled;
ForStatement *syntaxCopy();
- Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
Statement *getRelatedLabeled() { return relatedLabeled ? relatedLabeled : this; }
bool hasBreak() const;
bool hasContinue() const;
@@ -392,7 +389,6 @@ public:
Statement *elsebody;
ConditionalStatement *syntaxCopy();
- Statements *flatten(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
};
@@ -403,7 +399,6 @@ public:
StaticForeach *sfe;
StaticForeachStatement *syntaxCopy();
- Statements *flatten(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
};
@@ -635,7 +630,6 @@ public:
Statement *statement;
ScopeGuardStatement *syntaxCopy();
- Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
void accept(Visitor *v) { v->visit(this); }
};
@@ -659,7 +653,6 @@ public:
Statement *statement;
DebugStatement *syntaxCopy();
- Statements *flatten(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
};
@@ -692,8 +685,6 @@ public:
bool breaks; // someone did a 'break ident'
LabelStatement *syntaxCopy();
- Statements *flatten(Scope *sc);
- Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
void accept(Visitor *v) { v->visit(this); }
};
@@ -760,7 +751,6 @@ public:
StorageClass stc; // postfix attributes like nothrow/pure/@trusted
CompoundAsmStatement *syntaxCopy();
- Statements *flatten(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
};
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index b391b05603c..cd9ad8fdd09 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -19,7 +19,10 @@ import dmd.aggregate;
import dmd.aliasthis;
import dmd.arrayop;
import dmd.arraytypes;
+import dmd.astcodegen;
import dmd.astenums;
+import dmd.ast_node;
+import dmd.attrib;
import dmd.blockexit;
import dmd.clone;
import dmd.cond;
@@ -49,12 +52,14 @@ import dmd.intrange;
import dmd.mtype;
import dmd.nogc;
import dmd.opover;
+import dmd.parse;
import dmd.printast;
import dmd.root.outbuffer;
import dmd.root.string;
import dmd.semantic2;
import dmd.sideeffect;
import dmd.statement;
+import dmd.staticassert;
import dmd.target;
import dmd.tokens;
import dmd.typesem;
@@ -273,7 +278,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
Statement sexception;
Statement sfinally;
- (*cs.statements)[i] = s.scopeCode(sc, &sentry, &sexception, &sfinally);
+ (*cs.statements)[i] = s.scopeCode(sc, sentry, sexception, sfinally);
if (sentry)
{
sentry = sentry.statementSemantic(sc);
@@ -474,7 +479,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
Statement sentry;
Statement sexception;
Statement sfinally;
- ss.statement = ss.statement.scopeCode(sc, &sentry, &sexception, &sfinally);
+ ss.statement = ss.statement.scopeCode(sc, sentry, sexception, sfinally);
assert(!sentry);
assert(!sexception);
if (sfinally)
@@ -538,7 +543,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
const inLoopSave = sc.inLoop;
sc.inLoop = true;
if (ds._body)
- ds._body = ds._body.semanticScope(sc, ds, ds);
+ ds._body = ds._body.semanticScope(sc, ds, ds, null);
sc.inLoop = inLoopSave;
if (ds.condition.op == TOK.dotIdentifier)
@@ -1433,7 +1438,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
auto var = new VarDeclaration(loc, p.type, p.ident, null);
var.storage_class |= STC.foreach_;
var.storage_class |= p.storageClass & (STC.IOR | STC.TYPECTOR);
- if (var.storage_class & (STC.ref_ | STC.out_))
+ if (var.isReference())
var.storage_class |= STC.nodtor;
fs.value = var;
@@ -2349,7 +2354,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
CtorFlow ctorflow_then = sc.ctorflow; // move flow results
sc.ctorflow = ctorflow_root; // reset flow analysis back to root
if (ifs.elsebody)
- ifs.elsebody = ifs.elsebody.semanticScope(sc, null, null);
+ ifs.elsebody = ifs.elsebody.semanticScope(sc, null, null, null);
// Merge 'then' results into 'else' results
sc.merge(ifs.loc, ctorflow_then);
@@ -2686,9 +2691,11 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
ed = ds.isEnumDeclaration(); // typedef'ed enum
if (!ed && te && ((ds = te.toDsymbol(sc)) !is null))
ed = ds.isEnumDeclaration();
- if (ed)
+ if (ed && ss.cases.length < ed.members.length)
{
- Lmembers:
+ int missingMembers = 0;
+ const maxShown = !global.params.verbose ? 6 : int.max;
+ Lmembers:
foreach (es; *ed.members)
{
EnumMember em = es.isEnumMember();
@@ -2696,14 +2703,25 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
{
foreach (cs; *ss.cases)
{
- if (cs.exp.equals(em.value) || (!cs.exp.type.isString() && !em.value.type.isString() && cs.exp.toInteger() == em.value.toInteger()))
+ if (cs.exp.equals(em.value) || (!cs.exp.type.isString() &&
+ !em.value.type.isString() && cs.exp.toInteger() == em.value.toInteger()))
continue Lmembers;
}
- ss.error("`enum` member `%s` not represented in `final switch`", em.toChars());
- sc.pop();
- return setError();
+ if (missingMembers == 0)
+ ss.error("missing cases for `enum` members in `final switch`:");
+
+ if (missingMembers < maxShown)
+ errorSupplemental(ss.loc, "`%s`", em.toChars());
+ missingMembers++;
}
}
+ if (missingMembers > 0)
+ {
+ if (missingMembers > maxShown)
+ errorSupplemental(ss.loc, "... (%d more, -v to show) ...", missingMembers - maxShown);
+ sc.pop();
+ return setError();
+ }
}
else
needswitcherror = true;
@@ -2895,7 +2913,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
*/
if (!v.isConst() && !v.isImmutable())
{
- cs.deprecation("`case` variables have to be `const` or `immutable`");
+ cs.error("`case` variables have to be `const` or `immutable`");
}
if (sw.isFinal)
@@ -3933,13 +3951,9 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
enum FLAGcpp = 1;
enum FLAGd = 2;
- tcs.tryBody = sc.tryBody;
-
- scope sc2 = sc.push();
- sc2.tryBody = tcs;
- tcs._body = tcs._body.semanticScope(sc2, null, null);
+ tcs.tryBody = sc.tryBody; // chain on the in-flight tryBody
+ tcs._body = tcs._body.semanticScope(sc, null, null, tcs);
assert(tcs._body);
- sc2.pop();
/* Even if body is empty, still do semantic analysis on catches
*/
@@ -4020,12 +4034,8 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
override void visit(TryFinallyStatement tfs)
{
//printf("TryFinallyStatement::semantic()\n");
- tfs.tryBody = sc.tryBody;
-
- auto sc2 = sc.push();
- sc2.tryBody = tfs;
- tfs._body = tfs._body.statementSemantic(sc2);
- sc2.pop();
+ tfs.tryBody = sc.tryBody; // chain on in-flight tryBody
+ tfs._body = tfs._body.semanticScope(sc, null, null, tfs);
sc = sc.push();
sc.tf = tfs;
@@ -4458,7 +4468,7 @@ Statement semanticNoScope(Statement s, Scope* sc)
}
// Same as semanticNoScope(), but do create a new scope
-Statement semanticScope(Statement s, Scope* sc, Statement sbreak, Statement scontinue)
+private Statement semanticScope(Statement s, Scope* sc, Statement sbreak, Statement scontinue, Statement tryBody)
{
auto sym = new ScopeDsymbol();
sym.parent = sc.scopesym;
@@ -4467,12 +4477,98 @@ Statement semanticScope(Statement s, Scope* sc, Statement sbreak, Statement scon
scd.sbreak = sbreak;
if (scontinue)
scd.scontinue = scontinue;
+ if (tryBody)
+ scd.tryBody = tryBody;
s = s.semanticNoScope(scd);
scd.pop();
return s;
}
+/****************************************
+ * If `statement` has code that needs to run in a finally clause
+ * at the end of the current scope, return that code in the form of
+ * a Statement.
+ * Params:
+ * statement = the statement
+ * sc = context
+ * sentry = set to code executed upon entry to the scope
+ * sexception = set to code executed upon exit from the scope via exception
+ * sfinally = set to code executed in finally block
+ * Returns:
+ * code to be run in the finally clause
+ */
+Statement scopeCode(Statement statement, Scope* sc, out Statement sentry, out Statement sexception, out Statement sfinally)
+{
+ if (auto es = statement.isExpStatement())
+ {
+ if (es.exp && es.exp.op == TOK.declaration)
+ {
+ auto de = cast(DeclarationExp)es.exp;
+ auto v = de.declaration.isVarDeclaration();
+ if (v && !v.isDataseg())
+ {
+ if (v.needsScopeDtor())
+ {
+ sfinally = new DtorExpStatement(es.loc, v.edtor, v);
+ v.storage_class |= STC.nodtor; // don't add in dtor again
+ }
+ }
+ }
+ return es;
+
+ }
+ else if (auto sgs = statement.isScopeGuardStatement())
+ {
+ Statement s = new PeelStatement(sgs.statement);
+
+ switch (sgs.tok)
+ {
+ case TOK.onScopeExit:
+ sfinally = s;
+ break;
+
+ case TOK.onScopeFailure:
+ sexception = s;
+ break;
+
+ case TOK.onScopeSuccess:
+ {
+ /* Create:
+ * sentry: bool x = false;
+ * sexception: x = true;
+ * sfinally: if (!x) statement;
+ */
+ auto v = copyToTemp(0, "__os", IntegerExp.createBool(false));
+ v.dsymbolSemantic(sc);
+ sentry = new ExpStatement(statement.loc, v);
+
+ Expression e = IntegerExp.createBool(true);
+ e = new AssignExp(Loc.initial, new VarExp(Loc.initial, v), e);
+ sexception = new ExpStatement(Loc.initial, e);
+
+ e = new VarExp(Loc.initial, v);
+ e = new NotExp(Loc.initial, e);
+ sfinally = new IfStatement(Loc.initial, null, e, s, null, Loc.initial);
+
+ break;
+ }
+ default:
+ assert(0);
+ }
+ return null;
+ }
+ else if (auto ls = statement.isLabelStatement())
+ {
+ if (ls.statement)
+ ls.statement = ls.statement.scopeCode(sc, sentry, sexception, sfinally);
+ return ls;
+ }
+
+ return statement;
+}
+
+
/*******************
* Determines additional argument types for makeTupleForeach.
*/
@@ -4513,3 +4609,387 @@ TupleForeachRet!(isStatic, isDecl) makeTupleForeach(bool isStatic, bool isDecl)(
return v.makeTupleForeach!(isStatic, isDecl)(fs, args);
}
}
+
+/*********************************
+ * Flatten out the scope by presenting `statement`
+ * as an array of statements.
+ * Params:
+ * statement = the statement to flatten
+ * sc = context
+ * Returns:
+ * The array of `Statements`, or `null` if no flattening necessary
+ */
+private Statements* flatten(Statement statement, Scope* sc)
+{
+ static auto errorStatements()
+ {
+ auto a = new Statements();
+ a.push(new ErrorStatement());
+ return a;
+ }
+
+
+ /*compound and expression statements have classes that inherit from them with the same
+ *flattening behavior, so the isXXX methods won't work
+ */
+ switch(statement.stmt)
+ {
+ case STMT.Compound:
+ case STMT.CompoundDeclaration:
+ return (cast(CompoundStatement)statement).statements;
+
+ case STMT.Exp:
+ case STMT.DtorExp:
+ auto es = cast(ExpStatement)statement;
+ /* https://issues.dlang.org/show_bug.cgi?id=14243
+ * expand template mixin in statement scope
+ * to handle variable destructors.
+ */
+ if (!es.exp || es.exp.op != TOK.declaration)
+ return null;
+
+ Dsymbol d = (cast(DeclarationExp)es.exp).declaration;
+ auto tm = d.isTemplateMixin();
+ if (!tm)
+ return null;
+
+ Expression e = es.exp.expressionSemantic(sc);
+ if (e.op == TOK.error || tm.errors)
+ return errorStatements();
+ assert(tm.members);
+
+ Statement s = toStatement(tm);
+ version (none)
+ {
+ OutBuffer buf;
+ buf.doindent = 1;
+ HdrGenState hgs;
+ hgs.hdrgen = true;
+ toCBuffer(s, &buf, &hgs);
+ printf("tm ==> s = %s\n", buf.peekChars());
+ }
+ auto a = new Statements();
+ a.push(s);
+ return a;
+
+ case STMT.Forwarding:
+ /***********************
+ * ForwardingStatements are distributed over the flattened
+ * sequence of statements. This prevents flattening to be
+ * "blocked" by a ForwardingStatement and is necessary, for
+ * example, to support generating scope guards with `static
+ * foreach`:
+ *
+ * static foreach(i; 0 .. 10) scope(exit) writeln(i);
+ * writeln("this is printed first");
+ * // then, it prints 10, 9, 8, 7, ...
+ */
+ auto fs = statement.isForwardingStatement();
+ if (!fs.statement)
+ {
+ return null;
+ }
+ sc = sc.push(fs.sym);
+ auto a = fs.statement.flatten(sc);
+ sc = sc.pop();
+ if (!a)
+ {
+ return a;
+ }
+ auto b = new Statements(a.dim);
+ foreach (i, s; *a)
+ {
+ (*b)[i] = s ? new ForwardingStatement(s.loc, fs.sym, s) : null;
+ }
+ return b;
+
+ case STMT.Conditional:
+ auto cs = statement.isConditionalStatement();
+ Statement s;
+
+ //printf("ConditionalStatement::flatten()\n");
+ if (cs.condition.include(sc))
+ {
+ DebugCondition dc = cs.condition.isDebugCondition();
+ if (dc)
+ {
+ s = new DebugStatement(cs.loc, cs.ifbody);
+ debugThrowWalker(cs.ifbody);
+ }
+ else
+ s = cs.ifbody;
+ }
+ else
+ s = cs.elsebody;
+
+ auto a = new Statements();
+ a.push(s);
+ return a;
+
+ case STMT.StaticForeach:
+ auto sfs = statement.isStaticForeachStatement();
+ sfs.sfe.prepare(sc);
+ if (sfs.sfe.ready())
+ {
+ auto s = makeTupleForeach!(true, false)(sc, sfs.sfe.aggrfe, sfs.sfe.needExpansion);
+ auto result = s.flatten(sc);
+ if (result)
+ {
+ return result;
+ }
+ result = new Statements();
+ result.push(s);
+ return result;
+ }
+ else
+ return errorStatements();
+
+ case STMT.Debug:
+ auto ds = statement.isDebugStatement();
+ Statements* a = ds.statement ? ds.statement.flatten(sc) : null;
+ if (!a)
+ return null;
+
+ foreach (ref s; *a)
+ {
+ s = new DebugStatement(ds.loc, s);
+ }
+ return a;
+
+ case STMT.Label:
+ auto ls = statement.isLabelStatement();
+ if (!ls.statement)
+ return null;
+
+ Statements* a = null;
+ a = ls.statement.flatten(sc);
+ if (!a)
+ return null;
+
+ if (!a.dim)
+ {
+ a.push(new ExpStatement(ls.loc, cast(Expression)null));
+ }
+
+ // reuse 'this' LabelStatement
+ ls.statement = (*a)[0];
+ (*a)[0] = ls;
+ return a;
+
+ case STMT.Compile:
+ auto cs = statement.isCompileStatement();
+
+
+ OutBuffer buf;
+ if (expressionsToString(buf, sc, cs.exps))
+ return errorStatements();
+
+ const errors = global.errors;
+ const len = buf.length;
+ buf.writeByte(0);
+ const str = buf.extractSlice()[0 .. len];
+ scope p = new Parser!ASTCodegen(cs.loc, sc._module, str, false);
+ p.nextToken();
+
+ auto a = new Statements();
+ while (p.token.value != TOK.endOfFile)
+ {
+ Statement s = p.parseStatement(ParseStatementFlags.semi | ParseStatementFlags.curlyScope);
+ if (!s || global.errors != errors)
+ return errorStatements();
+ a.push(s);
+ }
+ return a;
+ default:
+ return null;
+ }
+}
+
+/***********************************************************
+ * Convert TemplateMixin members (== Dsymbols) to Statements.
+ */
+private Statement toStatement(Dsymbol s)
+{
+ extern (C++) final class ToStmt : Visitor
+ {
+ alias visit = Visitor.visit;
+ public:
+ Statement result;
+
+ Statement visitMembers(Loc loc, Dsymbols* a)
+ {
+ if (!a)
+ return null;
+
+ auto statements = new Statements();
+ foreach (s; *a)
+ {
+ statements.push(toStatement(s));
+ }
+ return new CompoundStatement(loc, statements);
+ }
+
+ override void visit(Dsymbol s)
+ {
+ .error(Loc.initial, "Internal Compiler Error: cannot mixin %s `%s`\n", s.kind(), s.toChars());
+ result = new ErrorStatement();
+ }
+
+ override void visit(TemplateMixin tm)
+ {
+ auto a = new Statements();
+ foreach (m; *tm.members)
+ {
+ Statement s = toStatement(m);
+ if (s)
+ a.push(s);
+ }
+ result = new CompoundStatement(tm.loc, a);
+ }
+
+ /* An actual declaration symbol will be converted to DeclarationExp
+ * with ExpStatement.
+ */
+ Statement declStmt(Dsymbol s)
+ {
+ auto de = new DeclarationExp(s.loc, s);
+ de.type = Type.tvoid; // avoid repeated semantic
+ return new ExpStatement(s.loc, de);
+ }
+
+ override void visit(VarDeclaration d)
+ {
+ result = declStmt(d);
+ }
+
+ override void visit(AggregateDeclaration d)
+ {
+ result = declStmt(d);
+ }
+
+ override void visit(FuncDeclaration d)
+ {
+ result = declStmt(d);
+ }
+
+ override void visit(EnumDeclaration d)
+ {
+ result = declStmt(d);
+ }
+
+ override void visit(AliasDeclaration d)
+ {
+ result = declStmt(d);
+ }
+
+ override void visit(TemplateDeclaration d)
+ {
+ result = declStmt(d);
+ }
+
+ /* All attributes have been already picked by the semantic analysis of
+ * 'bottom' declarations (function, struct, class, etc).
+ * So we don't have to copy them.
+ */
+ override void visit(StorageClassDeclaration d)
+ {
+ result = visitMembers(d.loc, d.decl);
+ }
+
+ override void visit(DeprecatedDeclaration d)
+ {
+ result = visitMembers(d.loc, d.decl);
+ }
+
+ override void visit(LinkDeclaration d)
+ {
+ result = visitMembers(d.loc, d.decl);
+ }
+
+ override void visit(VisibilityDeclaration d)
+ {
+ result = visitMembers(d.loc, d.decl);
+ }
+
+ override void visit(AlignDeclaration d)
+ {
+ result = visitMembers(d.loc, d.decl);
+ }
+
+ override void visit(UserAttributeDeclaration d)
+ {
+ result = visitMembers(d.loc, d.decl);
+ }
+
+ override void visit(ForwardingAttribDeclaration d)
+ {
+ result = visitMembers(d.loc, d.decl);
+ }
+
+ override void visit(StaticAssert s)
+ {
+ }
+
+ override void visit(Import s)
+ {
+ }
+
+ override void visit(PragmaDeclaration d)
+ {
+ }
+
+ override void visit(ConditionalDeclaration d)
+ {
+ result = visitMembers(d.loc, d.include(null));
+ }
+
+ override void visit(StaticForeachDeclaration d)
+ {
+ assert(d.sfe && !!d.sfe.aggrfe ^ !!d.sfe.rangefe);
+ result = visitMembers(d.loc, d.include(null));
+ }
+
+ override void visit(CompileDeclaration d)
+ {
+ result = visitMembers(d.loc, d.include(null));
+ }
+ }
+
+ if (!s)
+ return null;
+
+ scope ToStmt v = new ToStmt();
+ s.accept(v);
+ return v.result;
+}
+
+/**
+Marks all occurring ThrowStatements as internalThrows.
+This is intended to be called from a DebugStatement as it allows
+to mark all its nodes as nothrow.
+
+Params:
+ s = AST Node to traverse
+*/
+private void debugThrowWalker(Statement s)
+{
+
+ extern(C++) final class DebugWalker : SemanticTimeTransitiveVisitor
+ {
+ alias visit = SemanticTimeTransitiveVisitor.visit;
+ public:
+
+ override void visit(ThrowStatement s)
+ {
+ s.internalThrow = true;
+ }
+
+ override void visit(CallExp s)
+ {
+ s.inDebugStatement = true;
+ }
+ }
+
+ scope walker = new DebugWalker();
+ s.accept(walker);
+}
diff --git a/gcc/d/dmd/transitivevisitor.d b/gcc/d/dmd/transitivevisitor.d
index 1170fee2392..5e57d1f466d 100644
--- a/gcc/d/dmd/transitivevisitor.d
+++ b/gcc/d/dmd/transitivevisitor.d
@@ -879,8 +879,6 @@ package mixin template ParseVisitMethods(AST)
override void visit(AST.NewDeclaration d)
{
//printf("Visiting NewDeclaration\n");
- visitParameters(d.parameterList.parameters);
- visitFuncBody(d);
}
// Initializers
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index ab1f3d17861..cd1eee38250 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -2007,6 +2007,11 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
auto scopesym = sc.inner().scopesym;
if (scopesym.members)
scopesym.members.push(sd);
+ if (scopesym.symtab && !scopesym.symtabInsert(sd))
+ {
+ Dsymbol s2 = scopesym.symtabLookup(sd, mtype.id);
+ handleTagSymbols(*sc, sd, s2, scopesym);
+ }
sd.parent = sc.parent;
sd.dsymbolSemantic(sc);
}
@@ -2387,8 +2392,12 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden
error(loc, "no property `%s` for type `%s`", ident.toChars(), mt.toPrettyChars(true));
if (auto dsym = mt.toDsymbol(scope_))
if (auto sym = dsym.isAggregateDeclaration())
+ {
if (auto fd = search_function(sym, Id.opDispatch))
errorSupplemental(loc, "potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message");
+ else if (!sym.members)
+ errorSupplemental(sym.loc, "`%s %s` is opaque and has no members.", sym.kind, mt.toPrettyChars(true));
+ }
}
}
e = ErrorExp.get();
@@ -3730,7 +3739,11 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
assert(mt.ty == Tstruct || mt.ty == Tclass);
auto sym = mt.toDsymbol(sc).isAggregateDeclaration();
assert(sym);
- if (ident != Id.__sizeof &&
+ if (// https://issues.dlang.org/show_bug.cgi?id=22054
+ // if a class or struct does not have a body
+ // there is no point in searching for its members
+ sym.members &&
+ ident != Id.__sizeof &&
ident != Id.__xalignof &&
ident != Id._init &&
ident != Id._mangleof &&
@@ -4738,3 +4751,122 @@ Expression defaultInit(Type mt, const ref Loc loc)
null;
}
}
+
+
+/******************************
+ * Get the value of the .max/.min property of `ed` as an Expression.
+ * Lazily computes the value and caches it in maxval/minval.
+ * Reports any errors.
+ * Params:
+ * ed = the EnumDeclaration being examined
+ * loc = location to use for error messages
+ * id = Id::max or Id::min
+ * Returns:
+ * corresponding value of .max/.min
+ */
+private Expression getMaxMinValue(EnumDeclaration ed, const ref Loc loc, Identifier id)
+{
+ //printf("EnumDeclaration::getMaxValue()\n");
+
+ static Expression pvalToResult(Expression e, const ref Loc loc)
+ {
+ if (e.op != TOK.error)
+ {
+ e = e.copy();
+ e.loc = loc;
+ }
+ return e;
+ }
+
+ Expression* pval = (id == Id.max) ? &ed.maxval : &ed.minval;
+
+ Expression errorReturn()
+ {
+ *pval = ErrorExp.get();
+ return *pval;
+ }
+
+ if (ed.inuse)
+ {
+ ed.error(loc, "recursive definition of `.%s` property", id.toChars());
+ return errorReturn();
+ }
+ if (*pval)
+ return pvalToResult(*pval, loc);
+
+ if (ed._scope)
+ dsymbolSemantic(ed, ed._scope);
+ if (ed.errors)
+ return errorReturn();
+ if (!ed.members)
+ {
+ if (ed.isSpecial())
+ {
+ /* Allow these special enums to not need a member list
+ */
+ return ed.memtype.getProperty(ed._scope, loc, id, 0);
+ }
+
+ ed.error(loc, "is opaque and has no `.%s`", id.toChars());
+ return errorReturn();
+ }
+ if (!(ed.memtype && ed.memtype.isintegral()))
+ {
+ ed.error(loc, "has no `.%s` property because base type `%s` is not an integral type",
+ id.toChars(), ed.memtype ? ed.memtype.toChars() : "");
+ return errorReturn();
+ }
+
+ bool first = true;
+ for (size_t i = 0; i < ed.members.dim; i++)
+ {
+ EnumMember em = (*ed.members)[i].isEnumMember();
+ if (!em)
+ continue;
+ if (em.errors)
+ {
+ ed.errors = true;
+ continue;
+ }
+
+ if (em.semanticRun < PASS.semanticdone)
+ {
+ em.error("is forward referenced looking for `.%s`", id.toChars());
+ ed.errors = true;
+ continue;
+ }
+
+ if (first)
+ {
+ *pval = em.value;
+ first = false;
+ }
+ else
+ {
+ /* In order to work successfully with UDTs,
+ * build expressions to do the comparisons,
+ * and let the semantic analyzer and constant
+ * folder give us the result.
+ */
+
+ /* Compute:
+ * if (e > maxval)
+ * maxval = e;
+ */
+ Expression e = em.value;
+ Expression ec = new CmpExp(id == Id.max ? TOK.greaterThan : TOK.lessThan, em.loc, e, *pval);
+ ed.inuse++;
+ ec = ec.expressionSemantic(em._scope);
+ ed.inuse--;
+ ec = ec.ctfeInterpret();
+ if (ec.op == TOK.error)
+ {
+ ed.errors = true;
+ continue;
+ }
+ if (ec.toInteger())
+ *pval = e;
+ }
+ }
+ return ed.errors ? errorReturn() : pvalToResult(*pval, loc);
+}
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 6b44bebd6c1..86578aa8c5f 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -2318,9 +2318,6 @@ public:
Type *tb = e->type->toBasetype ();
tree result;
- if (e->allocator)
- gcc_assert (e->newargs);
-
if (tb->ty == TY::Tclass)
{
/* Allocating a new class. */
@@ -2340,15 +2337,6 @@ public:
new_call = build_nop (type, build_address (var));
setup_exp = modify_expr (var, aggregate_initializer_decl (cd));
}
- else if (e->allocator)
- {
- /* Call class allocator, and copy the initializer into memory. */
- new_call = d_build_call_expr (e->allocator, NULL_TREE, e->newargs);
- new_call = d_save_expr (new_call);
- new_call = build_nop (type, new_call);
- setup_exp = modify_expr (build_deref (new_call),
- aggregate_initializer_decl (cd));
- }
else
{
/* Generate: _d_newclass() */
@@ -2376,7 +2364,7 @@ public:
{
ClassDeclaration *ocd = outer->isClassDeclaration ();
int offset = 0;
- gcc_assert (ocd->isBaseOf (tcd, &offset));
+ gcc_assert (isBaseOf (ocd, tcd, &offset));
/* Could just add offset... */
value = convert_expr (value, e->thisexp->type, ocd->type);
}
@@ -2423,20 +2411,11 @@ public:
return;
}
- if (e->allocator)
- {
- /* Call struct allocator. */
- new_call = d_build_call_expr (e->allocator, NULL_TREE, e->newargs);
- new_call = build_nop (build_ctype (tb), new_call);
- }
- else
- {
- /* Generate: _d_newitemT() */
- libcall_fn libcall = htype->isZeroInit ()
- ? LIBCALL_NEWITEMT : LIBCALL_NEWITEMIT;
- tree arg = build_typeinfo (e->loc, e->newtype);
- new_call = build_libcall (libcall, tb, 1, arg);
- }
+ /* Generate: _d_newitemT() */
+ libcall_fn libcall = htype->isZeroInit ()
+ ? LIBCALL_NEWITEMT : LIBCALL_NEWITEMIT;
+ tree arg = build_typeinfo (e->loc, e->newtype);
+ new_call = build_libcall (libcall, tb, 1, arg);
if (e->member || !e->arguments)
{
@@ -2485,7 +2464,6 @@ public:
tb = e->newtype->toBasetype ();
TypeDArray *tarray = tb->isTypeDArray ();
- gcc_assert (!e->allocator);
gcc_assert (e->arguments && e->arguments->length >= 1);
if (e->arguments->length == 1)
@@ -3073,7 +3051,7 @@ public:
ClassDeclaration *from = e->originalClass ();
int offset = 0;
- gcc_assert (to->isBaseOf (from, &offset) != 0);
+ gcc_assert (isBaseOf (to, from, &offset) != 0);
if (offset != 0)
var = build_offset (var, size_int (offset));
diff --git a/gcc/d/lang-specs.h b/gcc/d/lang-specs.h
index 266e2a98265..2225677dafb 100644
--- a/gcc/d/lang-specs.h
+++ b/gcc/d/lang-specs.h
@@ -23,8 +23,7 @@ along with GCC; see the file COPYING3. If not see
{".di", "@d", 0, 1, 0 },
{"@d",
"%{!E:d21 %i %(cc1_options) %I %{nostdinc*} %{i*} %{I*} %{J*} \
- %{H} %{Hd*} %{Hf*} %{HC} %{HCd*} %{HCf*} \
- %{MD:-MD %b.deps} %{MMD:-MMD %b.deps} \
+ %{H} %{Hd*} %{Hf*} %{MD:-MD %b.deps} %{MMD:-MMD %b.deps} \
%{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*} \
%{X:-Xf %b.json} %{Xf*} \
%{v} %{!fsyntax-only:%(invoke_as)}}", 0, 1, 0 },
diff --git a/gcc/testsuite/gdc.test/compilable/b17111.d b/gcc/testsuite/gdc.test/compilable/b17111.d
index 6bf5da9f3e2..9e79a20780c 100644
--- a/gcc/testsuite/gdc.test/compilable/b17111.d
+++ b/gcc/testsuite/gdc.test/compilable/b17111.d
@@ -1,16 +1,7 @@
-/*
-TEST_OUTPUT:
----
-compilable/b17111.d(16): Deprecation: `case` variables have to be `const` or `immutable`
-compilable/b17111.d(17): Deprecation: `case` variables have to be `const` or `immutable`
----
-*/
alias TestType = ubyte;
-void test()
+void test(immutable TestType a, immutable TestType b, TestType c)
{
- TestType a,b,c;
-
switch(c)
{
case a: break;
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_breaks.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_breaks.d
index efb83ce4799..8242b98e89a 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_breaks.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_breaks.d
@@ -1,6 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o-
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_breaks.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_breaks.html
/++
# Thematic Breaks
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_breaks_verbose.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_breaks_verbose.d
index 3a83223459d..1ff26b07499 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_breaks_verbose.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_breaks_verbose.d
@@ -1,15 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -wi -o- -transition=vmarkdown
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
-
-/*
-TEST_OUTPUT:
-----
-compilable/ddoc_markdown_breaks_verbose.d(21): Ddoc: converted '___' to a thematic break
-compilable/ddoc_markdown_breaks_verbose.d(21): Ddoc: converted '- - -' to a thematic break
-compilable/ddoc_markdown_breaks_verbose.d(21): Ddoc: converted '***' to a thematic break
-----
-*/
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_breaks_verbose.html
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_breaks_verbose.html
/++
Thematic Breaks
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_code.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_code.d
index 7fed9ed0f84..56e6be36538 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_code.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_code.d
@@ -1,12 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o-
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
-
-/*
-TEST_OUTPUT:
-----
-----
-*/
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_code.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_code.html
/++
# Code Blocks
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_code_verbose.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_code_verbose.d
index d2be2d274a7..eb64c04363d 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_code_verbose.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_code_verbose.d
@@ -1,13 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o- -transition=vmarkdown
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
-
-/*
-TEST_OUTPUT:
-----
-compilable/ddoc_markdown_code_verbose.d(19): Ddoc: adding code block for language 'ruby'
-----
-*/
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_code_verbose.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_code_verbose.html
/++
Code:
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_emphasis.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_emphasis.d
index bef13c9d4c4..8bbcbdf91a3 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_emphasis.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_emphasis.d
@@ -1,6 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o-
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_emphasis.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_emphasis.html
/++
Markdown Emphasis:
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_emphasis_verbose.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_emphasis_verbose.d
index 68e936492a2..07904c1e42f 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_emphasis_verbose.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_emphasis_verbose.d
@@ -1,14 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -wi -o- -transition=vmarkdown
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
-
-/*
-TEST_OUTPUT:
-----
-compilable/ddoc_markdown_emphasis_verbose.d(20): Ddoc: emphasized text 'emphasized text'
-compilable/ddoc_markdown_emphasis_verbose.d(20): Ddoc: emphasized text 'strongly emphasized text'
-----
-*/
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_emphasis_verbose.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_emphasis_verbose.html
/++
Markdown Emphasis:
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_escapes.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_escapes.d
index 1fbe1c78042..4d8c8aeb945 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_escapes.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_escapes.d
@@ -1,6 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o-
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_escapes.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_escapes.html
/++
Backslash Escapes:
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_headings.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_headings.d
index 733a1b8cdfe..e7191f89769 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_headings.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_headings.d
@@ -1,6 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o-
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_headings.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_headings.html
/++
# ATX-Style Headings
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_headings_verbose.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_headings_verbose.d
index 0717b7ba017..64484632b4e 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_headings_verbose.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_headings_verbose.d
@@ -1,13 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o- -transition=vmarkdown
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
-
-/*
-TEST_OUTPUT:
-----
-compilable/ddoc_markdown_headings_verbose.d(15): Ddoc: added heading 'Heading'
-----
-*/
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_headings_verbose.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_headings_verbose.html
/++
# Heading
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_links.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_links.d
index 0e3a99c57a2..349175b0484 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_links.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_links.d
@@ -1,6 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o-
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_links.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_links.html
/++
# Links
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_links_verbose.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_links_verbose.d
index 5d8cffd388d..435b426e03e 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_links_verbose.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_links_verbose.d
@@ -1,18 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o- -transition=vmarkdown
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
-
-/*
-TEST_OUTPUT:
-----
-compilable/ddoc_markdown_links_verbose.d(28): Ddoc: found link reference 'dub' to 'https://code.dlang.org'
-compilable/ddoc_markdown_links_verbose.d(28): Ddoc: linking '[Object]' to '$(DOC_ROOT_object)object$(DOC_EXTENSION)#.Object'
-compilable/ddoc_markdown_links_verbose.d(28): Ddoc: linking '[the D homepage](https://dlang.org)' to 'https://dlang.org'
-compilable/ddoc_markdown_links_verbose.d(28): Ddoc: linking '[dub]' to 'https://code.dlang.org'
-compilable/ddoc_markdown_links_verbose.d(28): Ddoc: linking '[dub][]' to 'https://code.dlang.org'
-compilable/ddoc_markdown_links_verbose.d(28): Ddoc: linking '![D-Man](https://dlang.org/images/d3.png)' to 'https://dlang.org/images/d3.png'
-----
-*/
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_links_verbose.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_links_verbose.html
/++
Links:
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_lists.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_lists.d
index 00ef30649c5..1e5ff560d64 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_lists.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_lists.d
@@ -1,6 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o-
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_lists.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_lists.html
/++
# Lists
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_lists_verbose.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_lists_verbose.d
index f3223f34d31..4fd1a80c58b 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_lists_verbose.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_lists_verbose.d
@@ -1,13 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o- -transition=vmarkdown
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
-
-/*
-TEST_OUTPUT:
-----
-compilable/ddoc_markdown_lists_verbose.d(15): Ddoc: starting list item 'list item'
-----
-*/
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_lists_verbose.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_lists_verbose.html
/++
- list item
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_quote.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_quote.d
index be9f7866c9f..27cfc430b8d 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_quote.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_quote.d
@@ -1,12 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o-
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
-
-/*
-TEST_OUTPUT:
-----
-----
-*/
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_quote.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_quote.html
/++
# Quote Blocks
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_quote_verbose.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_quote_verbose.d
index 5490278b5f6..f16e5390ece 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_quote_verbose.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_quote_verbose.d
@@ -1,13 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o- -transition=vmarkdown
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
-
-/*
-TEST_OUTPUT:
-----
-compilable/ddoc_markdown_quote_verbose.d(17): Ddoc: starting quote block with '> Great, just what I need.. another D in programming. -- Segfault'
-----
-*/
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_quote_verbose.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_quote_verbose.html
/++
Quote Block:
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables.d
index 1cda6640629..231364acc96 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables.d
@@ -1,12 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o-
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
-
-/*
-TEST_OUTPUT:
-----
-----
-*/
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_tables.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_tables.html
/++
# Tables
diff --git a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables_verbose.d b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables_verbose.d
index d7b3c388e1d..d1aac1cedf8 100644
--- a/gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables_verbose.d
+++ b/gcc/testsuite/gdc.test/compilable/ddoc_markdown_tables_verbose.d
@@ -1,13 +1,7 @@
// PERMUTE_ARGS:
// REQUIRED_ARGS: -D -Dd${RESULTS_DIR}/compilable -o- -transition=vmarkdown
-// POST_SCRIPT: compilable/extra-files/ddocAny-postscript.sh
-
-/*
-TEST_OUTPUT:
-----
-compilable/ddoc_markdown_tables_verbose.d(19): Ddoc: formatting table '| this | that |'
-----
-*/
+// TEST_OUTPUT_FILE: extra-files/ddoc_markdown_tables_verbose.html
+// OUTPUT_FILES: ${RESULTS_DIR}/compilable/ddoc_markdown_tables_verbose.html
/++
Table:
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_AnonDeclaration.d b/gcc/testsuite/gdc.test/compilable/dtoh_AnonDeclaration.d
index 9b1157d87eb..bcf5558054d 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_AnonDeclaration.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_AnonDeclaration.d
@@ -53,6 +53,15 @@ struct S final
extern "C" void foo();
void bar();
};
+ struct
+ {
+ int32_t outerPrivate;
+ };
+ struct
+ {
+ int32_t innerPrivate;
+ int32_t innerBar;
+ };
S()
{
}
@@ -77,6 +86,18 @@ extern (C++) struct S
extern(C) void foo() {}
extern(C++) void bar() {}
}
+
+ // Private not emitted because AnonDeclaration has no protection
+ private struct
+ {
+ int outerPrivate;
+ }
+
+ public struct {
+ // Private cannot be exported to C++
+ private int innerPrivate;
+ int innerBar;
+ }
}
extern (D)
diff --git a/gcc/testsuite/gdc.test/compilable/dtoh_forwarding.d b/gcc/testsuite/gdc.test/compilable/dtoh_forwarding.d
index 76acfc117cb..483e58f6ae5 100644
--- a/gcc/testsuite/gdc.test/compilable/dtoh_forwarding.d
+++ b/gcc/testsuite/gdc.test/compilable/dtoh_forwarding.d
@@ -42,7 +42,6 @@ struct _d_dynamicArray final
struct Child;
class Struct;
enum class Enum;
-struct OuterStruct;
class ExternDClass;
struct ExternDStruct;
template <typename T>
@@ -51,12 +50,27 @@ template <typename T>
class TemplStruct;
template <typename T>
class ExternDTemplClass;
+struct OnlyByRef;
struct Parent
{
virtual void bar();
};
+struct OuterStruct final
+{
+ struct NestedStruct final
+ {
+ NestedStruct()
+ {
+ }
+ };
+
+ OuterStruct()
+ {
+ }
+};
+
struct ExternDStructRequired final
{
int32_t member;
@@ -104,20 +118,6 @@ enum class Enum
extern OuterStruct::NestedStruct* nestedStrPtr;
-struct OuterStruct final
-{
- struct NestedStruct final
- {
- NestedStruct()
- {
- }
- };
-
- OuterStruct()
- {
- }
-};
-
extern ExternDClass* externDClassPtr;
extern ExternDStruct* externDStrPtr;
@@ -148,6 +148,8 @@ extern ExternDTemplClass<int32_t >* externTemplClass;
extern ExternDTemplStruct<int32_t > externTemplStruct;
+extern void foo(OnlyByRef& obr);
+
---
*/
@@ -255,3 +257,9 @@ extern(D) struct ExternDTemplStruct(T)
{
T member;
}
+
+//******************************************************
+
+extern(D) struct OnlyByRef {}
+
+void foo(ref OnlyByRef obr) {}
--git a/gcc/testsuite/gdc.test/compilable/header18364.d b/gcc/testsuite/gdc.test/compilable/header18364.d
index 77df1d0d2ad..c7e1e67c7ae 100644
--- a/gcc/testsuite/gdc.test/compilable/header18364.d
+++ b/gcc/testsuite/gdc.test/compilable/header18364.d
@@ -1,5 +1,21 @@
-// REQUIRED_ARGS: -o- -Hf${RESULTS_DIR}/compilable/header18364.di
-// POST_SCRIPT: compilable/extra-files/header-postscript.sh
+/*
+REQUIRED_ARGS: -o- -Hf${RESULTS_DIR}/compilable/header18364.di
+PERMUTE_ARGS:
+OUTPUT_FILES: ${RESULTS_DIR}/compilable/header18364.di
+
+TEST_OUTPUT:
+---
+=== ${RESULTS_DIR}/compilable/header18364.di
+// D import file generated from 'compilable/header18364.d'
+module foo.bar.ba;
+nothrow pure @nogc @safe package(foo)
+{
+ void foo();
+ nothrow pure @nogc @safe package(foo.bar) void foo2();
+}
+---
+*/
+
module foo.bar.ba;
@safe pure nothrow @nogc package(foo):
void foo();
--git a/gcc/testsuite/gdc.test/compilable/header18365.d b/gcc/testsuite/gdc.test/compilable/header18365.d
index e01b4cdd8e5..7e51fb26cc7 100644
--- a/gcc/testsuite/gdc.test/compilable/header18365.d
+++ b/gcc/testsuite/gdc.test/compilable/header18365.d
@@ -1,5 +1,26 @@
-// REQUIRED_ARGS: -c -o- -Hf${RESULTS_DIR}/compilable/header18365.di
-// POST_SCRIPT: compilable/extra-files/header-postscript.sh
+/*
+REQUIRED_ARGS: -c -o- -Hf${RESULTS_DIR}/compilable/header18365.di
+PERMUTE_ARGS:
+OUTPUT_FILES: ${RESULTS_DIR}/compilable/header18365.di
+
+TEST_OUTPUT:
+---
+=== ${RESULTS_DIR}/compilable/header18365.di
+// D import file generated from 'compilable/header18365.d'
+struct FullCaseEntry
+{
+ dchar[3] seq;
+ ubyte n;
+ ubyte size;
+ ubyte entry_len;
+ auto const pure nothrow @nogc @property @trusted value() return
+ {
+ return seq[0..entry_len];
+ }
+}
+---
+*/
+
struct FullCaseEntry
{
dchar[3] seq;
diff --git a/gcc/testsuite/gdc.test/compilable/imports/imp22122.d b/gcc/testsuite/gdc.test/compilable/imports/imp22122.d
new file mode 100644
index 00000000000..b29bae0bb6f
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/imp22122.d
@@ -0,0 +1,5 @@
+module imports.imp22122;
+
+package struct Imp22122
+{
+}
diff --git a/gcc/testsuite/gdc.test/compilable/interpret3.d b/gcc/testsuite/gdc.test/compilable/interpret3.d
index cd355538eee..ff85856b62e 100644
--- a/gcc/testsuite/gdc.test/compilable/interpret3.d
+++ b/gcc/testsuite/gdc.test/compilable/interpret3.d
@@ -2,8 +2,7 @@
/*
TEST_OUTPUT:
---
-compilable/interpret3.d(2914): Deprecation: `case` variables have to be `const` or `immutable`
-compilable/interpret3.d(6351): Deprecation: identity comparison of static arrays implicitly coerces them to slices, which are compared by reference
+compilable/interpret3.d(6350): Deprecation: identity comparison of static arrays implicitly coerces them to slices, which are compared by reference
---
*/
@@ -2904,16 +2903,16 @@ static assert(bug4448b() == 3);
/**************************************************/
// https://issues.dlang.org/show_bug.cgi?id=6985
-// non-constant case
+// Formerly, non-constant case, but switch cases with mutable cases now error
+// Currently: run-time constant variable case
int bug6985(int z)
{
- int q = z * 2 - 6;
+ const int q = z * 2 - 6;
switch(z)
{
case q:
- q = 87;
- break;
+ return 87;
default:
}
return q;
diff --git a/gcc/testsuite/gdc.test/compilable/test17143.d b/gcc/testsuite/gdc.test/compilable/test17143.d
index 98e31f4c324..4ec029572f4 100644
--- a/gcc/testsuite/gdc.test/compilable/test17143.d
+++ b/gcc/testsuite/gdc.test/compilable/test17143.d
@@ -1,4 +1,16 @@
-import std.typecons : tuple;
+// https://issues.dlang.org/show_bug.cgi?id=17143
+
+struct Tuple(T...)
+{
+ T values;
+ alias expand = values;
+}
+
+Tuple!T tuple(T...)(T args)
+{
+ return Tuple!T(args);
+}
+
enum foo = tuple(1, 2).expand;
static assert(typeof(foo).stringof == "(int, int)");
static assert(foo.stringof == "tuple(1, 2)");
diff --git a/gcc/testsuite/gdc.test/compilable/test20367.d b/gcc/testsuite/gdc.test/compilable/test20367.d
index a6a171f4a42..ebdf9ee5b8d 100644
--- a/gcc/testsuite/gdc.test/compilable/test20367.d
+++ b/gcc/testsuite/gdc.test/compilable/test20367.d
@@ -1,7 +1,5 @@
// https://issues.dlang.org/show_bug.cgi?id=20367
-import std.stdio;
-
struct A
{
int x;
diff --git a/gcc/testsuite/gdc.test/compilable/test22122.d b/gcc/testsuite/gdc.test/compilable/test22122.d
new file mode 100644
index 00000000000..a06d06c787d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test22122.d
@@ -0,0 +1,53 @@
+// EXTRA_FILES: imports/imp22122.d
+module imports.test22122;
+
+struct S22122
+{
+ import imports.imp22122;
+ Variant!(Imp22122)[] array;
+}
+
+void test22122_catch(S22122 s)
+{
+ try
+ {
+ foreach(elem; s.array)
+ {
+ import imports.imp22122;
+ with(elem.get!Imp22122)
+ {
+ }
+ }
+ }
+ catch (Exception)
+ {
+ }
+}
+
+void test22122_finally(S22122 s)
+{
+ try
+ {
+ foreach(elem; s.array)
+ {
+ import imports.imp22122;
+ with(elem.get!Imp22122)
+ {
+ }
+ }
+ }
+ finally
+ {
+ }
+}
+
+private struct Variant(T)
+{
+ union Impl
+ {
+ }
+ auto get(E)()
+ {
+ return Impl();
+ }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/testcstuff1.c b/gcc/testsuite/gdc.test/compilable/testcstuff1.c
deleted file mode 100644
index 271edaeca0d..00000000000
--- a/gcc/testsuite/gdc.test/compilable/testcstuff1.c
+++ /dev/null
@@ -1,499 +0,0 @@
-// check the expression parser
-
-_Static_assert(0 == 0, "ok");
-_Static_assert(0 != 1, "ok");
-_Static_assert(1 + 2 == 3, "ok");
-_Static_assert(1 - 2 == -1, "ok");
-_Static_assert(3 * 4 == 12, "ok");
-_Static_assert(10 / 2 == 5, "ok");
-_Static_assert(10 % 3 == 1, "ok");
-_Static_assert(2 << 3 == 16, "ok");
-_Static_assert(16 >> 3 == 2, "ok");
-_Static_assert((2 | 1) == 3, "ok");
-_Static_assert((3 & 1) == 1, "ok");
-_Static_assert((3 ^ 1) == 2, "ok");
-_Static_assert(-(3 ^ 1) == -+2, "ok");
-_Static_assert(~1 == 0xFFFFFFFE, "ok");
-_Static_assert(!3 == 0, "ok");
-_Static_assert(!0 == 1, "ok");
-_Static_assert(6.0f == 6.0, "in");
-_Static_assert(6.0F == 6.0, "in");
-_Static_assert(6.0l == 6.0, "in");
-_Static_assert(6.0L == 6.0, "in");
-
-_Static_assert(sizeof(char) == 1, "ok");
-_Static_assert(sizeof(char signed) == 1, "ok");
-_Static_assert(sizeof(unsigned char) == 1, "ok");
-
-_Static_assert(sizeof(short) == 2, "ok");
-_Static_assert(sizeof(int short) == 2, "ok");
-_Static_assert(sizeof(signed short) == 2, "ok");
-_Static_assert(sizeof(signed short int) == 2, "ok");
-
-_Static_assert(sizeof(short unsigned) == 2, "ok");
-_Static_assert(sizeof(unsigned short int) == 2, "ok");
-
-_Static_assert(sizeof(int) == 4, "ok");
-_Static_assert(sizeof(signed) == 4, "ok");
-_Static_assert(sizeof(signed int) == 4, "ok");
-
-_Static_assert(sizeof(int unsigned) == 4, "ok");
-_Static_assert(sizeof(unsigned) == 4, "ok");
-
-_Static_assert(sizeof(long) >= 4, "ok");
-_Static_assert(sizeof(signed long) >= 4, "ok");
-_Static_assert(sizeof(int long) <= 8, "ok");
-_Static_assert(sizeof(long signed int) <= 8, "ok");
-
-_Static_assert(sizeof(int unsigned long) >= 4, "ok");
-_Static_assert(sizeof(long unsigned) <= 8, "ok");
-
-_Static_assert(sizeof(long long) == 8, "ok");
-_Static_assert(sizeof(int long long) == 8, "ok");
-_Static_assert(sizeof(long signed long) == 8, "ok");
-_Static_assert(sizeof(long long signed int) == 8, "ok");
-
-_Static_assert(sizeof(unsigned long long) == 8, "ok");
-_Static_assert(sizeof(int long unsigned long) == 8, "ok");
-
-_Static_assert(sizeof(float) == 4, "ok");
-_Static_assert(sizeof(double) == 8, "ok");
-//_Static_assert(sizeof(long double) == 8 || sizeof(long double) == 10 || sizeof(long double) == 16, "ok");
-
-_Static_assert(sizeof(const restrict volatile char volatile restrict const) == 1, "ok");
-
-_Static_assert(sizeof(int*) == 8 || 4 == sizeof(char*), "ok");
-
-_Static_assert(sizeof(int[10][20]) == 20 * (10 * 4), "ok");
-
-/**********************************************/
-
-_Static_assert(07 == 7, "ok");
-_Static_assert(071 == 57, "ok");
-_Static_assert(0 == 0, "ok");
-
-_Static_assert(1u == 1l, "ok");
-_Static_assert(1U == 1L, "ok");
-_Static_assert(1Ul == 1L, "ok");
-
-_Static_assert(1ull == 1LL, "ok");
-_Static_assert(1llu == 1ull, "ok");
-
-_Static_assert(sizeof(1) == 4, "ok");
-_Static_assert(sizeof(0x1) == 4, "ok");
-_Static_assert(sizeof(1u) == 4, "ok");
-_Static_assert(sizeof(0x1u) == 4, "ok");
-_Static_assert(sizeof(1l) == 4 || sizeof(1l) == 8, "ok");
-_Static_assert(sizeof(1ul) == 4 || sizeof(1ul) == 8, "ok");
-_Static_assert(sizeof(0x1l) == 4 || sizeof(0x1L) == 8, "ok");
-_Static_assert(sizeof(0x1ul) == 4 || sizeof(0x1UL) == 8, "ok");
-_Static_assert(sizeof(1ll) == 8, "ok");
-_Static_assert(sizeof(1ull) == 8, "ok");
-_Static_assert(sizeof(0x1ull) == 8, "ok");
-
-_Static_assert(sizeof(0x8000000000000000LL) == 8, "ok");
-_Static_assert(sizeof(0x1LL) == 8, "ok");
-_Static_assert(sizeof(0x8000000000000000) == 8, "ok");
-_Static_assert(sizeof(0x7FFFFFFF00000000) == 8, "ok");
-_Static_assert(sizeof(9223372036854775808) == 8, "ok");
-_Static_assert(sizeof(9223372032559808512) == 8, "ok");
-_Static_assert(sizeof(0xFFFFFFFF00000000U) == 8, "ok");
-
-_Static_assert(sizeof(0x8000000000000000L) == 8, "ok");
-
-/**********************************************/
-
-int f1(i, j)
-int i;
-int j;
-{
- return i + 3;
-}
-
-_Static_assert(f1(4, 2) == 7, "ok");
-
-/**********************************************/
-
-enum E1 { M1, M2, M3, M4 = 7, M5, };
-enum E2 { M6 };
-
-_Static_assert(M3 == 2, "ok");
-_Static_assert(M5 == 8, "ok");
-
-/**********************************************/
-
-int s1(int i)
-{
- while (i < 10) ++i;
- return i;
-}
-
-_Static_assert(s1(3) == 10, "s1(3) == 10");
-
-int s2(int i)
-{
- for (; i < 10; ++i);
- return i;
-}
-
-_Static_assert(s2(3) == 10, "s2(3) == 10");
-
-int s3(int i)
-{
- do
- {
- ++i;
- } while (i < 10);
- return i;
-}
-
-_Static_assert(s3(3) == 10, "s3(3) == 10");
-
-int s4(int i)
-{
- switch (i)
- {
- case 1: break;
- case 2+1: i = 10; break;
- default: i = 11; break;
- }
- return i;
-}
-
-_Static_assert(s4(1) == 1, "s4(1) == 1");
-_Static_assert(s4(3) == 10, "s4(3) == 10");
-_Static_assert(s4(5) == 11, "s4(5) == 11");
-
-int s5(int i)
-{
- if (i == 3)
- return 4;
- else
- return 5;
-}
-
-_Static_assert(s5(3) == 4, "s5(3) == 4");
-_Static_assert(s5(4) == 5, "s5(4) == 5");
-
-/********************************/
-
-void tokens()
-<%
- char c = 'c';
- unsigned short w = L'w';
- //unsigned short* ws = L"wstring";
- int LLL1[1];
- int LLL2<:1:>;
-%>
-
-/********************************/
-
-int testexpinit()
-{
- int i = 1;
- int j = { 2 };
- int k = { 3 , };
- return i + j + k;
-}
-
-_Static_assert(testexpinit() == 1 + 2 + 3, "ok");
-
-/********************************/
-
-// Character literals
-_Static_assert(sizeof('a') == 4, "ok");
-_Static_assert(sizeof(u'a') == 4, "ok");
-_Static_assert(sizeof(U'a') == 4, "ok");
-_Static_assert('a' == 0x61, "ok");
-_Static_assert('ab' == 0x6162, "ok");
-_Static_assert('abc' == 0x616263, "ok");
-_Static_assert('abcd' == 0x61626364, "ok");
-_Static_assert(u'a' == 0x61, "ok");
-_Static_assert(u'ab' == 0x610062, "ok");
-_Static_assert(U'a' == 0x61, "ok");
-_Static_assert(u'\u1234' == 0x1234, "ok");
-_Static_assert(U'\U00011234' == 0x11234, "ok");
-_Static_assert(L'\u1234' == 0x1234, "ok");
-
-/********************************/
-
-void test__func__()
-{
- _Static_assert((sizeof __func__) == 13, "ok");
-}
-
-void teststringtype()
-{
- char* p = "hello";
- unsigned short* up = u"hello";
- unsigned int* Up = U"hello";
-}
-
-/********************************/
-
-char s[] = "hello";
-_Static_assert(sizeof(s) == 6, "in");
-
-/********************************/
-
-struct SA { int a, b, *const c, d[50]; };
-
-int test1(int i)
-{
- L1:
- ++i;
- L2:
- { --i; }
- return i;
-}
-
-_Static_assert(test1(5) == 5, "ok");
-
-void test2()
-{
- int;
- int (*xi);
- int (*fp)(void);
- int (* const volatile restrict fp2)(void);
- void* pv;
- char c, d;
- short sh;
- int j;
- long l;
- signed s;
- unsigned u;
- //_Complex double co;
- _Bool b;
- typedef int TI;
- //extern int ei;
- static int si;
- _Thread_local int tli;
- auto int ai;
- register int reg;
- const int ci;
- volatile int vi;
- restrict int ri;
-
-// _Atomic(int) ai;
-// _Alignas(c) ac;
-
- void * const volatile restrict q;
-
- inline int f();
- _Noreturn void g();
-
- _Static_assert(1, "ok");
-}
-
-void test3(int i)
-{
- for (i = 0; ;)
- {
- }
- for (int j = 0; ;)
- {
- continue;
- }
- if (i == 3)
- i = 4;
- else
- i = 5;
- if (i == 4)
- i = 6;
- goto L1;
- L1: ;
- { L2: }
-}
-
-void test4(int i)
-{
- i = 4, i = 5;
- float f = 1.0f + 3;
- double d = 1.0 + 4;
- char c = 'c';
- //char* s = __func__;
- int* p = &i;
- i = *p;
- _Static_assert(sizeof 3 == 4, "ok");
- _Static_assert(sizeof(3) == 4, "ok");
- _Static_assert(_Alignof(int) == 4, "ok");
- _Static_assert((int)3 == 3, "ok");
- _Static_assert(sizeof p[0] == 4, "ok");
- _Static_assert(1 && 2, "ok");
- _Static_assert((1 ? 2 : 3) == 2, "ok");
- _Static_assert((0 ? 2 : 3) == 3, "ok");
-
- i += 2;
- i -= 2;
- i *= 2;
- i /= 2;
- i %= 2;
- i &= 2;
- i |= 2;
- i ^= 2;
- i <<= 2;
- i >>= 2;
- i++;
- i--;
- p[0]++;
- *p = 3;
- (++i);
- long long ll = 12L;
- ll = 12UL;
- long double ld = 1.0L;
- const char* s = "hello" "betty";
-}
-
-/********************************/
-
-void parenExp(int a, int b)
-{
- char* q = (char*)"hello";
- if (!(a == b))
- a = b;
- if ((int)3 == 3);
- a = b;
- if ((a) == b)
- a = b;
- a = (int) (1 << (b));
- typedef int t;
- int* p;
- a = a + (t)*p;
-}
-
-/********************************/
-
-struct SS { int a; };
-
-int tests1()
-{
- struct SS s;
- return s.a;
-}
-
-int tests2()
-{
- struct T { int a; };
- struct T t;
- return t.a;
-}
-
-void* tests3()
-{
- struct T1 *p;
- return p;
-}
-
-int tests4()
-{
- struct S { int b; } a, *p;
- a.b = 3;
- p = &a;
- return p->b;
-}
-
-int test5()
-{
- struct { int a; };
- struct S
- {
- int a;
- struct { int b, c; };
- } s;
- return s.a + s.b + s.c;
-}
-
-/********************************/
-
-int test16997()
-{
- /* Exhaustively test all signed and unsigned byte promotions for
- * - + and ~
- */
- for (int i = 0; i < 256; ++i)
- {
- unsigned char c = (unsigned char)i;
-
- int i1 = (int) (~c);
- int i2 = (int) (~(int) c);
-
- //printf("%d, %d\n", i1, i2);
- if (i1 != i2) return 0;
-
- i1 = (int) (+c);
- i2 = (int) (+(int) c);
- if (i1 != i2) return 0;
-
- i1 = (int) (-c);
- i2 = (int) (-(int) c);
- if (i1 != i2) return 0;
- }
-
- for (int i = 0; i < 256; ++i)
- {
- signed char c = (signed char)i;
-
- int i1 = (int) (~c);
- int i2 = (int) (~(int) c);
-
- //printf("%d, %d\n", i1, i2);
- if (i1 != i2) return 0;
-
- i1 = (int) (+c);
- i2 = (int) (+(int) c);
- if (i1 != i2) return 0;
-
- i1 = (int) (-c);
- i2 = (int) (-(int) c);
- if (i1 != i2) return 0;
- }
- return 1;
-}
-
-_Static_assert(test16997(), "in");
-
-/********************************/
-
-struct SH { int a; };
-int SH;
-int SJ;
-struct SJ { int a; };
-
-void testtags()
-{
- struct SH h;
- h.a = SH;
- struct SJ j;
- j.a = SJ;
-
- struct SK { int a; };
- int SK;
- struct SK k;
- k.a = SK;
-
- int SL;
- struct SL { int a; };
- struct SL l;
- l.a = SL;
-}
-
-/********************************/
-
-int printf(const char*, ...);
-
-int main()
-{
- printf("hello world\n");
-}
-
-#line 1000
-%:line 1010
-
-# 1020 "cstuff1.c" 1 2 3 4
-# 1030
-struct S21944
-{
- int var;
-#1040 "cstuff1.c" 3 4
-};
-
diff --git a/gcc/testsuite/gdc.test/compilable/testcstuff2.c b/gcc/testsuite/gdc.test/compilable/testcstuff2.c
deleted file mode 100644
index a500d4f7b88..00000000000
--- a/gcc/testsuite/gdc.test/compilable/testcstuff2.c
+++ /dev/null
@@ -1,313 +0,0 @@
-// check bugs in the expression parser
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=21931
-
-typedef long int T21931a;
-typedef T21931a T21931b;
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=21933
-
-struct S21933 { void *opaque; };
-int test21933(struct S21933 *);
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=21934
-
-typedef int T21934 asm("realtype");
-int init21934 asm("realsym") = 1;
-int var21934 asm("realvsym");
-int fun21934() asm("realfun");
-
-void test21934()
-{
- typedef int asmreg;
- register asmreg r1 asm("r1");
- // asm ignored by C compiler, should be disallowed?
- asmreg r2 asm("r2");
-
- register asmreg r3 asm("r3") = 3;
- // asm ignored by C compiler, should be disallowed?
- asmreg r4 asm("r4") = 4;
-}
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=21937
-
-__attribute__(()) int test21937a();
-int test21937b() __attribute__(( , nothrow, hot, aligned(2), ));
-int test21937c() __attribute__((nothrow , leaf)) __attribute__((noreturn));
-
-__attribute__((noinline))
-void test21937d()
-{
- typedef int attr_var_t;
- attr_var_t attr_local __attribute__((unused));
-}
-
-__attribute__((aligned)) int test21937e;
-int test21937f __attribute__((aligned));
-
-struct __attribute__((packed)) S21937a
-{
- __attribute__((deprecated("msg"))) char c;
- int i __attribute__((deprecated));
-};
-
-struct S21937b
-{
- __attribute__((deprecated("msg"))) char c;
- int i __attribute__((deprecated));
-} __attribute__((packed));
-
-enum __attribute__((aligned)) E21937a
-{
- E21937a_A,
-};
-
-enum E21937b
-{
- E21937b_A,
-} __attribute__((aligned));
-
-typedef int T21937a __attribute__((unused));
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=21945
-
-typedef struct {
- long var;
-} S21945;
-S21945 test21945a;
-
-typedef enum {
- E21945_member,
-} E21945;
-E21945 test21945b;
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=21948
-
-void test21948()
-{
- typedef int myint;
- typedef struct { int f; } mystruct;
-
- myint var1;
- myint var2 = 12;
- mystruct var3;
- // Uncomment when bug fixed https://issues.dlang.org/show_bug.cgi?id=21979
- //mystruct var4 = { 34 };
-}
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=21963
-
-union U21963
-{
- int iv;
- float fv;
-};
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=21965
-
-struct { int var; };
-typedef struct { int var; };
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=21967
-
-const int test21967a(void);
-const int *test21967b(void);
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=21968
-
-struct S21968
-{
- struct inner *data[16];
-};
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=21970
-
-extern int test21970a;
-extern char *test21970b;
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=21973
-
-struct S21973
-{
- int field;
- struct
- {
- int nested;
- };
-};
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=21977
-int test21977a;
-_Thread_local int test21977b;
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=21982
-
-struct S21982 { int field; };
-struct S21982 test21982;
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=22028
-
-struct S22028
-{
- struct nested
- {
- int field;
- };
- const int cfield;
- _Static_assert(1 == 1, "ok");
-};
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=22060
-
-struct S22060;
-typedef struct S22060 T22060a;
-struct S22060;
-typedef struct S22060 T22060b;
-struct S22060;
-struct S22060
-{
- int _flags;
-};
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=22061
-
-union S22061
-{
- int field;
-};
-typedef union S22061 S22061;
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=22063
-
-typedef struct S22063_t
-{
- int field;
-} S22063;
-
-void test22063()
-{
- // BUG: no definition of struct
- //struct S22063_t v1 = { 0 };
- // BUG: cannot implicitly cast from integer to pointer.
- struct S22063_t *v2 = (struct S22063_t *)0;
- S22063 v3 = { 0 };
- S22063 *v4 = (S22063 *)0;
-}
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=22066
-
-void test22066()
-{
- int var = 0;
- (var)++;
-}
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=22067
-
-void test22067()
-{
- union U {
- int value;
- char *ptr;
- char array[4];
- } var;
- union U *pvar = &var;
- var.value = 0xabcdef;
- var.array[0]++;
- (*var.ptr)--;
- ++(*pvar).value;
- --(*pvar).array[3];
-}
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=22073
-
-struct S22073a { int field; };
-struct S22073b { const char *field; };
-
-_Static_assert((struct S22073a){6789}.field == 6789, "ok");
-_Static_assert((struct S22073b){"zxcv"}.field[2] == 'c', "ok");
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=22079
-
-struct S22079
-{
- int a, b, c;
-};
-
-_Static_assert(sizeof(struct S22079){1,2,3} == sizeof(int)*3, "ok");
-_Static_assert(sizeof(struct S22079){1,2,3}.a == sizeof(int), "ok");
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=22080
-
-int F22080(const char *);
-
-int test22080()
-{
- int (*fun)(const char *) = &F22080;
-}
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=22086
-typedef union U22086 U22086;
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=22088
-
-void test22088()
-{
- int *p;
- int i;
- p = i;
- i = p;
-
- void *pv;
- p = pv;
- pv = p;
-
- long long ll;
- ll = i;
- i = ll;
-
- char c;
- c = i;
- i = c;
-
- float f;
- f = i;
- i = f;
-
- double d;
- d = i;
- i = d;
-
- long double ld;
- ld = i;
- i = ld;
- c = ld;
-}
-
-/***************************************************/
-
--git a/gcc/testsuite/gdc.test/compilable/testheader1.d b/gcc/testsuite/gdc.test/compilable/testheader1.d
index 9d4cd483cb1..9b14f7b0d34 100644
--- a/gcc/testsuite/gdc.test/compilable/testheader1.d
+++ b/gcc/testsuite/gdc.test/compilable/testheader1.d
@@ -1,12 +1,9 @@
-// EXTRA_SOURCES: extra-files/header1.d
-// REQUIRED_ARGS: -o- -unittest -H -Hf${RESULTS_DIR}/compilable/testheader1.di -ignore
-// PERMUTE_ARGS: -d -dw
-// POST_SCRIPT: compilable/extra-files/header-postscript.sh
/*
-TEST_OUTPUT:
----
-Hello World
----
+EXTRA_SOURCES: extra-files/header1.d
+REQUIRED_ARGS: -o- -unittest -H -Hf${RESULTS_DIR}/compilable/testheader1.di -ignore
+PERMUTE_ARGS: -d -dw
+OUTPUT_FILES: ${RESULTS_DIR}/compilable/testheader1.di
+TEST_OUTPUT_FILE: extra-files/header1.di
*/
void main() {}
diff --git a/gcc/testsuite/gdc.test/compilable/testheader12567a.d b/gcc/testsuite/gdc.test/compilable/testheader12567a.d
index dcbcd37ca30..3372d871ea6 100644
--- a/gcc/testsuite/gdc.test/compilable/testheader12567a.d
+++ b/gcc/testsuite/gdc.test/compilable/testheader12567a.d
@@ -1,6 +1,16 @@
-// REQUIRED_ARGS: -o- -H -Hf${RESULTS_DIR}/compilable/testheader12567a.di
-// PERMUTE_ARGS:
-// POST_SCRIPT: compilable/extra-files/header-postscript.sh
+/*
+REQUIRED_ARGS: -o- -H -Hf${RESULTS_DIR}/compilable/testheader12567a.di
+PERMUTE_ARGS:
+OUTPUT_FILES: ${RESULTS_DIR}/compilable/testheader12567a.di
+
+TEST_OUTPUT:
+---
+=== ${RESULTS_DIR}/compilable/testheader12567a.di
+// D import file generated from 'compilable/testheader12567a.d'
+deprecated module header12567a;
+void main();
+---
+*/
deprecated module header12567a;
diff --git a/gcc/testsuite/gdc.test/compilable/testheader12567b.d b/gcc/testsuite/gdc.test/compilable/testheader12567b.d
index 873a8fad049..f17a37eeea5 100644
--- a/gcc/testsuite/gdc.test/compilable/testheader12567b.d
+++ b/gcc/testsuite/gdc.test/compilable/testheader12567b.d
@@ -1,6 +1,16 @@
-// REQUIRED_ARGS: -o- -H -Hf${RESULTS_DIR}/compilable/testheader12567b.di
-// PERMUTE_ARGS:
-// POST_SCRIPT: compilable/extra-files/header-postscript.sh
+/*
+REQUIRED_ARGS: -o- -H -Hf${RESULTS_DIR}/compilable/testheader12567b.di
+PERMUTE_ARGS:
+OUTPUT_FILES: ${RESULTS_DIR}/compilable/testheader12567b.di
+
+TEST_OUTPUT:
+---
+=== ${RESULTS_DIR}/compilable/testheader12567b.di
+// D import file generated from 'compilable/testheader12567b.d'
+deprecated("message") module header12567b;
+void main();
+---
+*/
deprecated("message") module header12567b;
--git a/gcc/testsuite/gdc.test/compilable/testheader1i.d b/gcc/testsuite/gdc.test/compilable/testheader1i.d
index 236d3f82582..f79a1af4027 100644
--- a/gcc/testsuite/gdc.test/compilable/testheader1i.d
+++ b/gcc/testsuite/gdc.test/compilable/testheader1i.d
@@ -1,12 +1,9 @@
-// EXTRA_SOURCES: extra-files/header1.d
-// REQUIRED_ARGS: -o- -H -Hf${RESULTS_DIR}/compilable/testheader1i.di -inline -ignore
-// PERMUTE_ARGS: -d -dw
-// POST_SCRIPT: compilable/extra-files/header-postscript.sh
/*
-TEST_OUTPUT:
----
-Hello World
----
+EXTRA_SOURCES: extra-files/header1.d
+REQUIRED_ARGS: -o- -H -Hf${RESULTS_DIR}/compilable/testheader1i.di -inline -ignore
+PERMUTE_ARGS: -d -dw
+OUTPUT_FILES: ${RESULTS_DIR}/compilable/testheader1i.di
+TEST_OUTPUT_FILE: extra-files/header1i.di
*/
void main() {}
--git a/gcc/testsuite/gdc.test/compilable/testheader2.d b/gcc/testsuite/gdc.test/compilable/testheader2.d
index a061530d857..25cc3c933da 100644
--- a/gcc/testsuite/gdc.test/compilable/testheader2.d
+++ b/gcc/testsuite/gdc.test/compilable/testheader2.d
@@ -1,6 +1,9 @@
-// EXTRA_SOURCES: extra-files/header2.d
-// REQUIRED_ARGS: -o- -H -Hf${RESULTS_DIR}/compilable/testheader2.di
-// PERMUTE_ARGS:
-// POST_SCRIPT: compilable/extra-files/header-postscript.sh
+/*
+EXTRA_SOURCES: extra-files/header2.d
+REQUIRED_ARGS: -o- -H -Hf${RESULTS_DIR}/compilable/testheader2.di
+PERMUTE_ARGS:
+OUTPUT_FILES: ${RESULTS_DIR}/compilable/testheader2.di
+TEST_OUTPUT_FILE: extra-files/header2.di
+*/
void main() {}
--git a/gcc/testsuite/gdc.test/compilable/testheader2i.d b/gcc/testsuite/gdc.test/compilable/testheader2i.d
index ec1f3c2c931..517fae41d53 100644
--- a/gcc/testsuite/gdc.test/compilable/testheader2i.d
+++ b/gcc/testsuite/gdc.test/compilable/testheader2i.d
@@ -1,6 +1,9 @@
-// EXTRA_SOURCES: extra-files/header2.d
-// REQUIRED_ARGS: -o- -H -Hf${RESULTS_DIR}/compilable/testheader2i.di -inline
-// PERMUTE_ARGS:
-// POST_SCRIPT: compilable/extra-files/header-postscript.sh
+/*
+EXTRA_SOURCES: extra-files/header2.d
+REQUIRED_ARGS: -o- -H -Hf${RESULTS_DIR}/compilable/testheader2i.di -inline
+PERMUTE_ARGS:
+OUTPUT_FILES: ${RESULTS_DIR}/compilable/testheader2i.di
+TEST_OUTPUT_FILE: extra-files/header2i.di
+*/
void main() {}
--git a/gcc/testsuite/gdc.test/compilable/testheader3.d b/gcc/testsuite/gdc.test/compilable/testheader3.d
index 0aac4fbc945..be38d7c76ee 100644
--- a/gcc/testsuite/gdc.test/compilable/testheader3.d
+++ b/gcc/testsuite/gdc.test/compilable/testheader3.d
@@ -1,8 +1,27 @@
-// EXTRA_SOURCES: extra-files/header3.d
-// REQUIRED_ARGS: -o- -unittest -H -Hf${RESULTS_DIR}/compilable/testheader3.di
-// PERMUTE_ARGS: -d -dw
-// POST_SCRIPT: compilable/extra-files/header-postscript.sh
-
-void main() {}
+/*
+EXTRA_SOURCES: extra-files/header3.d
+REQUIRED_ARGS: -o- -unittest -H -Hf${RESULTS_DIR}/compilable/testheader3.di
+PERMUTE_ARGS: -d -dw
+OUTPUT_FILES: ${RESULTS_DIR}/compilable/testheader3.di
+TEST_OUTPUT:
+---
+=== ${RESULTS_DIR}/compilable/testheader3.di
+// D import file generated from 'compilable/extra-files/header3.d'
+auto elseifchain()
+{
+ bool a, b, c;
+ if (a)
+ {
+ }
+ else if (b)
+ {
+ }
+ else if (c)
+ {
+ }
+}
+---
+*/
+void main() {}
diff --git a/gcc/testsuite/gdc.test/compilable/testheaderudamodule.d b/gcc/testsuite/gdc.test/compilable/testheaderudamodule.d
index b0d4515f96d..b6b0ed1a278 100644
--- a/gcc/testsuite/gdc.test/compilable/testheaderudamodule.d
+++ b/gcc/testsuite/gdc.test/compilable/testheaderudamodule.d
@@ -1,6 +1,22 @@
-// REQUIRED_ARGS: -o- -H -Hf${RESULTS_DIR}/compilable/testheaderudamodule.di
-// PERMUTE_ARGS:
-// POST_SCRIPT: compilable/extra-files/header-postscript.sh
+/*
+REQUIRED_ARGS: -o- -H -Hf${RESULTS_DIR}/compilable/testheaderudamodule.di
+PERMUTE_ARGS:
+OUTPUT_FILES: ${RESULTS_DIR}/compilable/testheaderudamodule.di
+
+TEST_OUTPUT:
+---
+=== ${RESULTS_DIR}/compilable/testheaderudamodule.di
+// D import file generated from 'compilable/testheaderudamodule.d'
+@(1, UDA(2))
+module testheaderudamodule;
+struct UDA
+{
+ int a;
+}
+void main();
+void foo(@(1) int bar, @UDA(2) string bebe);
+---
+*/
@(1, UDA(2))
module testheaderudamodule;
diff --git a/gcc/testsuite/gdc.test/compilable/vcg-ast.d b/gcc/testsuite/gdc.test/compilable/vcg-ast.d
index bfcaf83d572..61767cc60d6 100644
--- a/gcc/testsuite/gdc.test/compilable/vcg-ast.d
+++ b/gcc/testsuite/gdc.test/compilable/vcg-ast.d
@@ -1,7 +1,11 @@
+/*
+REQUIRED_ARGS: -vcg-ast -o-
+PERMUTE_ARGS:
+OUTPUT_FILES: compilable/vcg-ast.d.cg
+TEST_OUTPUT_FILE: extra-files/vcg-ast.d.cg
+*/
+
module vcg;
-// REQUIRED_ARGS: -vcg-ast -o-
-// PERMUTE_ARGS:
-// POST_SCRIPT: compilable/extra-files/vcg-ast-postscript.sh
template Seq(A...)
{
diff --git a/gcc/testsuite/gdc.test/fail_compilation/cconst1.c b/gcc/testsuite/gdc.test/fail_compilation/cconst1.c
deleted file mode 100644
index 50bf17f58bc..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/cconst1.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/* TEST_OUTPUT:
----
-fail_compilation/cconst1.c(104): Error: cannot modify `const` expression `i`
-fail_compilation/cconst1.c(106): Error: cannot modify `const` expression `j`
-fail_compilation/cconst1.c(108): Error: cannot modify `const` expression `p`
----
-*/
-
-#line 100
-
-void test100()
-{
- const int i;
- ++i;
- int const j;
- ++j;
- int *const p;
- ++p;
- int *const x, y;
- ++y; // this should pass
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag_class_alloc.d b/gcc/testsuite/gdc.test/fail_compilation/diag_class_alloc.d
index 93d3e038e46..326d82e0718 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/diag_class_alloc.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag_class_alloc.d
@@ -1,7 +1,9 @@
/*
TEST_OUTPUT:
---
-fail_compilation/diag_class_alloc.d(13): Error: class allocators are obsolete, consider moving the allocation strategy outside of the class
+fail_compilation/diag_class_alloc.d(15): Error: `new` allocator must be annotated with `@disabled`
+fail_compilation/diag_class_alloc.d(16): Deprecation: `new` allocator with non-empty parameter list is deprecated
+fail_compilation/diag_class_alloc.d(16): Deprecation: `new` allocator with function definition is deprecated
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/disable_new.d b/gcc/testsuite/gdc.test/fail_compilation/disable_new.d
index d5f1ecf074e..33ae32c2d8a 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/disable_new.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/disable_new.d
@@ -1,8 +1,8 @@
/*
TEST_OUTPUT:
---
-fail_compilation/disable_new.d(23): Error: allocator `disable_new.C.new` cannot be used because it is annotated with `@disable`
-fail_compilation/disable_new.d(24): Error: allocator `disable_new.S.new` cannot be used because it is annotated with `@disable`
+fail_compilation/disable_new.d(23): Error: cannot allocate `class C` with `new` because it is annotated with `@disable new()`
+fail_compilation/disable_new.d(24): Error: cannot allocate `struct S` with `new` because it is annotated with `@disable new()`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail11038.d b/gcc/testsuite/gdc.test/fail_compilation/fail11038.d
index 8f39ccc51eb..331c3fc5892 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail11038.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail11038.d
@@ -2,16 +2,16 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail11038.d(16): Error: `writeln` is not defined, perhaps `import std.stdio;` is needed?
+fail_compilation/fail11038.d(16): Error: `printf` is not defined, perhaps `import core.stdc.stdio;` is needed?
---
*/
static
{
- import std.stdio;
+ import core.stdc.stdio;
}
void main()
{
- writeln("foo"); // compiles
+ printf("foo"); // compiles
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail20033.d b/gcc/testsuite/gdc.test/fail_compilation/fail20033.d
index 8d8dbd5cec0..f641469c3dc 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail20033.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail20033.d
@@ -2,17 +2,22 @@
/*
TEST_OUTPUT:
---
-fail_compilation/fail20033.d(36): Deprecation: `alias byKeyValue this` is deprecated - This was a bad idea
-fail_compilation/fail20033.d(37): Deprecation: `alias byKeyValue this` is deprecated
-fail_compilation/fail20033.d(39): Deprecation: `alias byKeyValue this` is deprecated - This was a bad idea
-fail_compilation/fail20033.d(40): Deprecation: `alias byKeyValue this` is deprecated
+fail_compilation/fail20033.d(38): Deprecation: `alias byKeyValue this` is deprecated - This was a bad idea
+fail_compilation/fail20033.d(39): Deprecation: `alias byKeyValue this` is deprecated
+fail_compilation/fail20033.d(41): Deprecation: `alias byKeyValue this` is deprecated - This was a bad idea
+fail_compilation/fail20033.d(42): Deprecation: `alias byKeyValue this` is deprecated
---
*/
#line 1
-struct Test {
- import std.typecons : Tuple;
- alias KVT = Tuple!(string, "key", string, "value");
+struct Tuple(T...)
+{
+ T values;
+ alias values this;
+}
+alias KVT = Tuple!(string, string);
+
+struct Test {
struct Range {
bool empty () { return false; }
KVT front() { return KVT.init; }
@@ -26,9 +31,6 @@ struct Test {
}
struct Test2 {
- import std.typecons : Tuple;
- alias KVT = Tuple!(string, "key", string, "value");
-
struct Range {
bool empty () { return false; }
KVT front() { return KVT.init; }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21868b.d b/gcc/testsuite/gdc.test/fail_compilation/fail21868b.d
new file mode 100644
index 00000000000..6f34029db10
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail21868b.d
@@ -0,0 +1,22 @@
+/* REQUIRED_ARGS: -preview=dip1000
+TEST_OUTPUT:
+---
+fail_compilation/fail21868b.d(19): Error: returning `&s.x` escapes a reference to parameter `s`
+fail_compilation/fail21868b.d(19): perhaps remove `scope` parameter annotation so `return` applies to `ref`
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=21868
+
+struct S
+{
+ int x;
+ int* y;
+}
+
+int* test(ref return scope S s)
+{
+ return &s.x;
+}
+
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22054.d b/gcc/testsuite/gdc.test/fail_compilation/fail22054.d
new file mode 100644
index 00000000000..c172f089d9c
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22054.d
@@ -0,0 +1,23 @@
+// https://issues.dlang.org/show_bug.cgi?id=22054
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail22054.d(21): Error: no property `what` for type `fail22054.exception`
+fail_compilation/fail22054.d(16): `class fail22054.exception` is opaque and has no members.
+fail_compilation/fail22054.d(22): Error: no property `what` for type `fail22054.exception2`
+fail_compilation/fail22054.d(17): `struct fail22054.exception2` is opaque and has no members.
+---
+*/
+
+
+
+
+class exception;
+struct exception2;
+
+void main ()
+{
+ assert(exception.what() == "Hello");
+ assert(exception2.what() == "Hello");
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22075.d b/gcc/testsuite/gdc.test/fail_compilation/fail22075.d
new file mode 100644
index 00000000000..9b857c2f1d5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22075.d
@@ -0,0 +1,30 @@
+// https://issues.dlang.org/show_bug.cgi?id=22075
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail22075.d(25): Error: AA key type `S` should have `extern (D) size_t toHash() const nothrow @safe` if `opEquals` defined
+fail_compilation/fail22075.d(26): Error: AA key type `S` should have `extern (D) size_t toHash() const nothrow @safe` if `opEquals` defined
+---
+*/
+
+struct HasAliasThis { int a; alias a this; }
+
+struct LacksAliasThis { int a; }
+
+struct S(T)
+{
+ private T a;
+
+ bool opEquals(const S rhs) const @nogc nothrow @safe
+ {
+ return rhs is this;
+ }
+}
+
+int[S!HasAliasThis] aa1; // Compiles but should not.
+int[S!LacksAliasThis] aa2; // Correctly fails to compile with "Error: AA key
+ // type `S` should have `extern (D) size_t toHash() const nothrow @safe`
+ // if `opEquals` defined"".
+
+void main() {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22121.d b/gcc/testsuite/gdc.test/fail_compilation/fail22121.d
new file mode 100644
index 00000000000..f45cf12e061
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22121.d
@@ -0,0 +1,11 @@
+// https://issues.dlang.org/show_bug.cgi?id=22121
+// EXTRA_FILES: fail22121/imports/test22121/package.d
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail22121/imports/test22121/package.d(1): Error: package name 'fail22121' conflicts with usage as a module name in file fail_compilation/fail22121.d
+---
+*/
+
+module fail22121;
+import fail22121.imports.test22121;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail22121/imports/test22121/package.d b/gcc/testsuite/gdc.test/fail_compilation/fail22121/imports/test22121/package.d
new file mode 100644
index 00000000000..9277fabd0c5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail22121/imports/test22121/package.d
@@ -0,0 +1 @@
+module fail22121.imports.test22121;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail4517.d b/gcc/testsuite/gdc.test/fail_compilation/fail4517.d
deleted file mode 100644
index f3fe031a147..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail4517.d
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail4517.d(16): Error: `enum` member `B` not represented in `final switch`
----
-*/
-
-enum E : ushort
-{
- A, B
-}
-
-void main()
-{
- E e;
- final switch(e)
- {
- case E.A:
- break;
- }
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail4923.d b/gcc/testsuite/gdc.test/fail_compilation/fail4923.d
index fd1e8af2d45..3239cff0cf0 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail4923.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail4923.d
@@ -1,8 +1,7 @@
/*
-REQUIRED_ARGS: -de
TEST_OUTPUT:
---
-fail_compilation/fail4923.d(4): Deprecation: initialization of `immutable` variable from `static this` is deprecated.
+fail_compilation/fail4923.d(4): Error: immutable variable `bar` initialization is not allowed in `static this`
fail_compilation/fail4923.d(4): Use `shared static this` instead.
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail9368.d b/gcc/testsuite/gdc.test/fail_compilation/fail9368.d
deleted file mode 100644
index f575a86ab0c..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/fail9368.d
+++ /dev/null
@@ -1,48 +0,0 @@
-// REQUIRED_ARGS: -d
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail9368.d(19): Error: `enum` member `b` not represented in `final switch`
----
-*/
-
-enum E
-{
- a,
- b
-}
-
-void main()
-{
- alias E F;
- F f;
- final switch (f)
- {
- case F.a:
- }
-}
-
-/*
-TEST_OUTPUT:
----
-fail_compilation/fail9368.d(40): Error: `enum` member `B` not represented in `final switch`
----
-*/
-
-enum G
-{
- A,B,C
-}
-
-void test286()
-{
- G e;
- final switch (e)
- {
- case G.A:
-// case G.B:
- case G.C:
- {}
- }
-}
-
diff --git a/gcc/testsuite/gdc.test/fail_compilation/failcstuff1.c b/gcc/testsuite/gdc.test/fail_compilation/failcstuff1.c
deleted file mode 100644
index e57a7148021..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/failcstuff1.c
+++ /dev/null
@@ -1,103 +0,0 @@
-// check the expression parser
-/* TEST_OUTPUT
----
-fail_compilation/failcstuff1.c(51): Error: attributes should be specified before the function definition
-fail_compilation/failcstuff1.c(100): Error: no members for `enum E21962`
-fail_compilation/failcstuff1.c(101): Error: no members for anonymous enum
-fail_compilation/failcstuff1.c(152): Error: `;` or `,` expected
-fail_compilation/failcstuff1.c(153): Error: `void` has no value
-fail_compilation/failcstuff1.c(153): Error: missing comma
-fail_compilation/failcstuff1.c(153): Error: `;` or `,` expected
-fail_compilation/failcstuff1.c(154): Error: empty struct-declaration-list for `struct Anonymous`
-fail_compilation/failcstuff1.c(157): Error: identifier not allowed in abstract-declarator
-fail_compilation/failcstuff1.c(203): Error: storage class not allowed in specifier-qualified-list
-fail_compilation/failcstuff1.c(204): Error: storage class not allowed in specifier-qualified-list
-fail_compilation/failcstuff1.c(205): Error: storage class not allowed in specifier-qualified-list
-fail_compilation/failcstuff1.c(206): Error: storage class not allowed in specifier-qualified-list
-fail_compilation/failcstuff1.c(207): Error: storage class not allowed in specifier-qualified-list
-fail_compilation/failcstuff1.c(208): Error: storage class not allowed in specifier-qualified-list
-fail_compilation/failcstuff1.c(251): Error: identifier or `(` expected
-fail_compilation/failcstuff1.c(252): Error: identifier or `(` expected
-fail_compilation/failcstuff1.c(253): Error: identifier or `(` expected
-fail_compilation/failcstuff1.c(258): Error: identifier or `(` expected
-fail_compilation/failcstuff1.c(259): Error: identifier or `(` expected
-fail_compilation/failcstuff1.c(260): Error: identifier or `(` expected
-fail_compilation/failcstuff1.c(301): Error: illegal type combination
-fail_compilation/failcstuff1.c(352): Error: found `2` when expecting `:`
-fail_compilation/failcstuff1.c(352): Error: found `:` instead of statement
-fail_compilation/failcstuff1.c(400): Error: `enum ENUM` has no members
----
-*/
-
-/********************************/
-// https://issues.dlang.org/show_bug.cgi?id=21937
-#line 50
-void test21962() __attribute__((noinline))
-{
-}
-
-/********************************/
-// https://issues.dlang.org/show_bug.cgi?id=21962
-#line 100
-enum E21962 { };
-enum { };
-
-/********************************/
-// https://issues.dlang.org/show_bug.cgi?id=22028
-#line 150
-struct S22028
-{
- int init = 1;
- void vfield nocomma;
- struct { };
-};
-
-int test22028 = sizeof(struct S22028 ident);
-
-/********************************/
-// https://issues.dlang.org/show_bug.cgi?id=22029
-#line 200
-struct S22029
-{
- int field;
- typedef int tfield;
- extern int efield;
- static int sfield;
- _Thread_local int lfield;
- auto int afield;
- register int rfield;
-};
-
-// https://issues.dlang.org/show_bug.cgi?id=22030
-#line 250
-int;
-int *;
-int &;
-int , int;
-
-struct S22030
-{
- int;
- int *;
- int &;
- int, int;
- int _;
-};
-
-void test22030(struct S22030, struct S22030*, struct S22030[4]);
-
-// https://issues.dlang.org/show_bug.cgi?id=22032
-#line 300
-struct S22032 { int field; }
-int test22032;
-
-// https://issues.dlang.org/show_bug.cgi?id=22035
-#line 350
-void test22035()
-{
- case 1 2:
-}
-
-// https://issues.dlang.org/show_bug.cgi?id=21932
-#line 400
-enum ENUM;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/failcstuff2.c b/gcc/testsuite/gdc.test/fail_compilation/failcstuff2.c
deleted file mode 100644
index 385b5bce47a..00000000000
--- a/gcc/testsuite/gdc.test/fail_compilation/failcstuff2.c
+++ /dev/null
@@ -1,86 +0,0 @@
-// check semantic analysis of C files
-/* TEST_OUTPUT:
----
-fail_compilation/failcstuff2.c(54): Error: `& var` has no effect
-fail_compilation/failcstuff2.c(55): Error: `*ptr` has no effect
-fail_compilation/failcstuff2.c(56): Error: `var` has no effect
-fail_compilation/failcstuff2.c(57): Error: `-var` has no effect
-fail_compilation/failcstuff2.c(58): Error: `~var` has no effect
-fail_compilation/failcstuff2.c(59): Error: `!var` has no effect
-fail_compilation/failcstuff2.c(113): Error: `cast(int)var` is not an lvalue and cannot be modified
-fail_compilation/failcstuff2.c(114): Error: cannot modify constant `var.sizeof`
-fail_compilation/failcstuff2.c(115): Error: `cast(short)3` is not an lvalue and cannot be modified
-fail_compilation/failcstuff2.c(116): Error: cannot modify constant `4`
-fail_compilation/failcstuff2.c(117): Error: cannot modify constant `5`
-fail_compilation/failcstuff2.c(118): Error: cannot modify constant `6`
-fail_compilation/failcstuff2.c(119): Error: `cast(int)var` is not an lvalue and cannot be modified
-fail_compilation/failcstuff2.c(120): Error: `cast(int)var` is not an lvalue and cannot be modified
-fail_compilation/failcstuff2.c(121): Error: `cast(int)var` is not an lvalue and cannot be modified
-fail_compilation/failcstuff2.c(122): Error: `cast(int)var` is not an lvalue and cannot be modified
-fail_compilation/failcstuff2.c(123): Error: `cast(int)var` is not an lvalue and cannot be modified
-fail_compilation/failcstuff2.c(124): Error: `makeS22067().field` is not an lvalue and cannot be modified
-fail_compilation/failcstuff2.c(125): Error: `makeS22067().field` is not an lvalue and cannot be modified
-fail_compilation/failcstuff2.c(126): Error: `makeS22067().field` is not an lvalue and cannot be modified
-fail_compilation/failcstuff2.c(127): Error: `makeS22067().field` is not an lvalue and cannot be modified
-fail_compilation/failcstuff2.c(153): Error: `cast(short)var` is not an lvalue and cannot be modified
-fail_compilation/failcstuff2.c(154): Error: `cast(long)var` is not an lvalue and cannot be modified
----
-*/
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=22069
-#line 50
-void test22069()
-{
- int var;
- int *ptr;
- &var;
- *ptr;
- +var;
- -var;
- ~var;
- !var;
-}
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=22067
-#line 100
-struct S22067
-{
- int field;
-};
-
-struct S22067 makeS22067()
-{
- return (struct S22067) { 42 };
-}
-
-void test22067()
-{
- int var;
- (int) var = 1;
- sizeof(var) = 2;
- ++(short)3;
- --4;
- (5)++;
- (&6);
- ((int)var)++;
- ((int)var)--;
- ++(int)var;
- --(int)var;
- &(int)var;
- &makeS22067().field;
- makeS22067().field = 1;
- makeS22067().field++;
- --makeS22067().field;
-}
-
-/***************************************************/
-// https://issues.dlang.org/show_bug.cgi?id=22068
-#line 150
-void test22068()
-{
- int var;
- ++(short) var;
- --(long long) var;
-}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice17831.d b/gcc/testsuite/gdc.test/fail_compilation/ice17831.d
index 4312d5b1ddf..41abbf77a82 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/ice17831.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/ice17831.d
@@ -1,12 +1,16 @@
-// REQUIRED_ARGS: -d
/*
TEST_OUTPUT:
---
-fail_compilation/ice17831.d(19): Error: `case` variable `i` declared at fail_compilation/ice17831.d(17) cannot be declared in `switch` body
-fail_compilation/ice17831.d(33): Error: `case` variable `i` declared at fail_compilation/ice17831.d(31) cannot be declared in `switch` body
-fail_compilation/ice17831.d(48): Error: `case` variable `i` declared at fail_compilation/ice17831.d(45) cannot be declared in `switch` body
-fail_compilation/ice17831.d(61): Error: `case` variable `i` declared at fail_compilation/ice17831.d(60) cannot be declared in `switch` body
-fail_compilation/ice17831.d(73): Error: `case` variable `i` declared at fail_compilation/ice17831.d(72) cannot be declared in `switch` body
+fail_compilation/ice17831.d(23): Error: `case` variables have to be `const` or `immutable`
+fail_compilation/ice17831.d(23): Error: `case` variable `i` declared at fail_compilation/ice17831.d(21) cannot be declared in `switch` body
+fail_compilation/ice17831.d(37): Error: `case` variables have to be `const` or `immutable`
+fail_compilation/ice17831.d(37): Error: `case` variable `i` declared at fail_compilation/ice17831.d(35) cannot be declared in `switch` body
+fail_compilation/ice17831.d(52): Error: `case` variables have to be `const` or `immutable`
+fail_compilation/ice17831.d(52): Error: `case` variable `i` declared at fail_compilation/ice17831.d(49) cannot be declared in `switch` body
+fail_compilation/ice17831.d(65): Error: `case` variables have to be `const` or `immutable`
+fail_compilation/ice17831.d(65): Error: `case` variable `i` declared at fail_compilation/ice17831.d(64) cannot be declared in `switch` body
+fail_compilation/ice17831.d(77): Error: `case` variables have to be `const` or `immutable`
+fail_compilation/ice17831.d(77): Error: `case` variable `i` declared at fail_compilation/ice17831.d(76) cannot be declared in `switch` body
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16523.d b/gcc/testsuite/gdc.test/fail_compilation/test16523.d
index 61d17ed2b85..78563c92525 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/test16523.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/test16523.d
@@ -1,8 +1,7 @@
-// REQUIRED_ARGS: -de
/*
TEST_OUTPUT:
---
-fail_compilation/test16523.d(13): Deprecation: `case` variables have to be `const` or `immutable`
+fail_compilation/test16523.d(12): Error: `case` variables have to be `const` or `immutable`
---
*/
diff --git a/gcc/testsuite/gdc.test/fail_compilation/trait_loc_err.d b/gcc/testsuite/gdc.test/fail_compilation/trait_loc_err.d
index 8d5d480174e..c5d0579f4a0 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/trait_loc_err.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/trait_loc_err.d
@@ -2,14 +2,14 @@
TEST_OUTPUT:
---
fail_compilation/trait_loc_err.d(13): Error: can only get the location of a symbol, not `trait_loc_err`
-fail_compilation/trait_loc_err.d(14): Error: can only get the location of a symbol, not `std`
+fail_compilation/trait_loc_err.d(14): Error: can only get the location of a symbol, not `stdc`
---
*/
module trait_loc_err;
-import std.stdio;
+import core.stdc.stdio;
void main()
{
__traits(getLocation, __traits(parent, main));
- __traits(getLocation, __traits(parent, std.stdio));
+ __traits(getLocation, __traits(parent, core.stdc.stdio));
}
diff --git a/gcc/testsuite/gdc.test/runnable/builtin.d b/gcc/testsuite/gdc.test/runnable/builtin.d
index cc3c8c1ee93..39ab12a3386 100644
--- a/gcc/testsuite/gdc.test/runnable/builtin.d
+++ b/gcc/testsuite/gdc.test/runnable/builtin.d
@@ -1,6 +1,4 @@
// RUNNABLE_PHOBOS_TEST
-
-import std.stdio;
import std.math;
import core.bitop;
@@ -16,21 +14,15 @@ version (DigitalMars)
void test1()
{
- writefln("%a", sin(6.8L));
auto f = 6.8L;
- writefln("%a", sin(f));
assert(sin(f) == sin(6.8L));
static assert(isClose(sin(6.8L), 0x1.f9f8d9aea10fdf1cp-2));
- writefln("%a", cos(6.8L));
f = 6.8L;
- writefln("%a", cos(f));
assert(cos(f) == cos(6.8L));
static assert(isClose(cos(6.8L), 0x1.bd21aaf88dcfa13ap-1));
- writefln("%a", tan(6.8L));
f = 6.8L;
- writefln("%a", tan(f));
version (Win64)
{ }
else
@@ -113,7 +105,5 @@ int main()
test1();
test2();
test3();
-
- printf("Success\n");
return 0;
}
diff --git a/gcc/testsuite/gdc.test/runnable/cstuff2.c b/gcc/testsuite/gdc.test/runnable/cstuff2.c
deleted file mode 100644
index 3c28348e63f..00000000000
--- a/gcc/testsuite/gdc.test/runnable/cstuff2.c
+++ /dev/null
@@ -1,254 +0,0 @@
-
-int printf(const char *, ...);
-void exit(int);
-
-/*********************************/
-
-void test1()
-{
- static int a[3] = {1, 2, 3};
- if (a[0] != 1 ||
- a[1] != 2 ||
- a[2] != 3)
- {
- printf("error 1\n");
- exit(1);
- }
-}
-
-/*********************************/
-
-void test2()
-{
- static int a[4] = {1, 2, 3};
- if (a[0] != 1 ||
- a[1] != 2 ||
- a[2] != 3 ||
- a[3] != 0)
- {
- printf("error 2\n");
- exit(1);
- }
-}
-
-/*********************************/
-
-void test3()
-{
- static int a[] = {1, 2, 3};
- if (sizeof(a) != 3 * sizeof(int) ||
- a[0] != 1 ||
- a[1] != 2 ||
- a[2] != 3)
- {
- printf("error 3\n");
- exit(1);
- }
-}
-
-/*********************************/
-
-void test4()
-{
- static int a[3] = {1, 2, 3};
- int i;
- for (i = 0; i < 3; ++i)
- {
- if (a[i] != i + 1)
- {
- printf("error 4\n");
- exit(1);
- }
- }
-}
-
-/*********************************/
-
-void test5()
-{
- static int b[3][2] = { 1,2,3,4,5,6 };
- int i;
- for (i = 0; i < 3; ++i)
- {
- int j;
- for (j = 0; j < 2; ++j)
- {
- if (b[i][j] != i * 2 + j + 1)
- {
- printf("error 5\n");
- exit(1);
- }
- }
- }
-}
-
-/*********************************/
-
-void test6()
-{
- static int c[3][2] = { {1,2},{3,4},{5,6} };
- int i;
- for (i = 0; i < 3; ++i)
- {
- int j;
- for (j = 0; j < 2; ++j)
- {
- if (c[i][j] != i * 2 + j + 1)
- {
- printf("error 6\n");
- exit(1);
- }
- }
- }
-}
-
-/*********************************/
-
-void test7()
-{
- static int d[3][2] = { {1,2},3,4,{5,6} };
- int i;
- for (i = 0; i < 3; ++i)
- {
- int j;
- for (j = 0; j < 2; ++j)
- {
- if (d[i][j] != i * 2 + j + 1)
- {
- printf("error 7\n");
- exit(1);
- }
- }
- }
-}
-
-/*********************************/
-
-void test8()
-{
- static int d[3][2] = { {1,2} };
- int i;
- for (i = 0; i < 3; ++i)
- {
- int j;
- for (j = 0; j < 2; ++j)
- {
- if (i == 0)
- {
- if (d[i][j] != j + 1)
- {
- printf("error 8a\n");
- exit(1);
- }
- }
- else if (d[i][j] != 0)
- {
- printf("error 8b\n");
- exit(1);
- }
- }
- }
-}
-
-/*********************************/
-
-void test8a()
-{
- int i;
- static int a[3] = { 1,2,3 };
- // Casting to an array type is not allowed by C11, but
- // CompoundLiterals are not there yet to test this
- // grammar
- i = ((int[3])a)[2];
- if (i != 3) { printf("test8a\n"); exit(1); }
-}
-
-/*********************************/
-
-void test8b()
-{
- struct S { int a, b; };
- static struct S ax[3] = { 0x11,0x22,0x33,0 };
- //printf("%x %x %x %x\n", ax[0].a, ax[0].b, ax[1].a, ax[1].b);
- if (ax[0].a != 0x11 ||
- ax[0].b != 0x22 ||
- ax[1].a != 0x33 ||
- ax[1].b != 0) { printf("test8b\n"); exit(1); }
-}
-
-/*********************************/
-
-void test9()
-{
- int i = 1; if (i != 1) { printf("error 9i\n"); exit(1); }
- int j = { 2 }; if (j != 2) { printf("error 9j\n"); exit(1); }
- int k = { 3,}; if (k != 3) { printf("error 9k\n"); exit(1); }
-
- static int l = 4; if (l != 4) { printf("error 9l\n"); exit(1); }
- static int m = { 5 }; if (m != 5) { printf("error 9m\n"); exit(1); }
- static int n = { 6,}; if (n != 6) { printf("error 9n\n"); exit(1); }
-}
-
-/*********************************/
-
-void test10()
-{
- char s[6] = { "s" }; if (s[0] != 's') { printf("error 10s\n"); exit(1); }
- char t[7] = { "t" }; if (t[0] != 't' && t[1] != 0) { printf("error 10t\n"); exit(1); }
- static char u[6] = { "u" }; if (u[0] != 'u') { printf("error 10u\n"); exit(1); }
- static char v[7] = { "v" }; if (v[0] != 'v' && v[1] != 0) { printf("error 10v\n"); exit(1); }
-}
-
-/*********************************/
-
-void test11()
-{
- struct S { int a, b; };
- struct S s = { 1, 2 };
- if (s.a != 1 || s.b != 2) { printf("xx\n"); exit(1); }
- static struct S s2 = { 1, };
- if (s2.a != 1 || s2.b != 0) { printf("xx\n"); exit(1); }
-
- struct T { int a; struct { int b, c; }; };
- struct T t = { 1, 2, 3 };
- if (t.a != 1 || t.b != 2 || t.c != 3) { printf("xx\n"); exit(1); }
-
- struct U { int a; union { int b, c; }; int d; };
- struct U u = { 1, 2, 3 };
- if (u.a != 1 ||
- u.b != 2 ||
- u.c != 2 ||
- u.d != 3) { printf("%d %d %d %d\n", u.a, u.b, u.c, u.d); exit(1); }
-}
-
-/*********************************/
-
-void test12()
-{
- int i;
- i = (int) { 3 };
- if (i != 3) { printf("test12\n"); exit(1); }
-}
-
-/*********************************/
-
-int main()
-{
- test1();
- test2();
- test3();
- test4();
- test5();
- test6();
- test7();
- test8();
- test8a();
- test8b();
- test9();
- test10();
- test11();
- test12();
-
- return 0;
-}
-
diff --git a/gcc/testsuite/gdc.test/runnable/fix22115.d b/gcc/testsuite/gdc.test/runnable/fix22115.d
new file mode 100644
index 00000000000..2344bcc1a0c
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/fix22115.d
@@ -0,0 +1,70 @@
+/* PERMUTE_ARGS: -O -inline
+ */
+// https://issues.dlang.org/show_bug.cgi?id=22115
+
+
+int sx;
+void sss() { ++sx; }
+
+static if (1)
+{
+ struct S { int a; }
+
+ void test1(S* s)
+ {
+ if (s.a == 3 ? s : null)
+ sss();
+ }
+}
+
+static if (1)
+{
+ extern (C++) class Exp
+ {
+ int a;
+
+ void func() { }
+ final inout(AddExp) isAddExp() inout { return a == 3 ? cast(typeof(return))this : null; }
+ }
+
+ extern (C++) class AddExp : Exp
+ {
+ }
+
+ void test2(Exp e)
+ {
+ if (e.isAddExp())
+ sss();
+ }
+}
+
+
+int main()
+{
+ static if (1)
+ {
+ S s;
+ s.a = 3;
+ test1(&s);
+ assert(sx == 1);
+ s.a = 2;
+ test1(&s);
+ assert(sx == 1);
+ }
+ sx = 1;
+
+ static if (1)
+ {
+ auto c = new AddExp();
+ c.a = 3;
+ test2(c);
+ assert(sx == 2);
+ auto ae = c.isAddExp();
+ assert(ae && ae.a == 3);
+ c.a = 2;
+ test2(c);
+ assert(sx == 2);
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/gdc.test/runnable/ice21727.d b/gcc/testsuite/gdc.test/runnable/ice21727.d
new file mode 100644
index 00000000000..5b5745f9df0
--- /dev/null
+++ b/gcc/testsuite/gdc.test/runnable/ice21727.d
@@ -0,0 +1,46 @@
+// REQUIRED_ARGS: -m64 -O -inline
+// DISABLED: win32 linux32 freebsd32 osx32 netbsd32 dragonflybsd32
+// https://issues.dlang.org/show_bug.cgi?id=21727
+
+import core.simd;
+
+@nogc nothrow pure @safe:
+
+struct Float4
+{
+ float4 mVector;
+
+ pragma(inline, false) ref typeof(this) doubleInPlace() return
+ @nogc nothrow pure @safe
+ {
+ mVector = mVector + mVector;
+ return this;
+ }
+}
+
+pragma(inline, false) Float4 identity(Float4 a)
+{
+ return a;
+}
+
+pragma(inline, true) Float4 twoTimes(const ref Float4 a)
+{
+ version (D_SIMD)
+ return Float4(cast(float4) __simd(XMM.ADDPS, a.mVector, a.mVector));
+ else // Allow non-DMD compilers to compile this test.
+ return Float4(a.mVector + a.mVector);
+}
+
+pragma(inline, false) Float4 fourTimes(const Float4 a)
+{
+ auto x = identity(a);
+ auto y = x.doubleInPlace(); // This crashed in dmd.backend.cgxmm.xmmload.
+ auto z = twoTimes(y);
+ return z;
+}
+
+void main()
+{
+ const c = fourTimes(Float4([5,7,11,13]));
+ assert(c.mVector.array == [20, 28, 44, 52]);
+}
diff --git a/gcc/testsuite/gdc.test/runnable/test15.d b/gcc/testsuite/gdc.test/runnable/test15.d
index ad888a5fb25..222742c4080 100644
--- a/gcc/testsuite/gdc.test/runnable/test15.d
+++ b/gcc/testsuite/gdc.test/runnable/test15.d
@@ -1,14 +1,10 @@
-// RUNNABLE_PHOBOS_TEST
/*
-REQUIRED_ARGS:
+REQUIRED_ARGS: -Jrunnable/extra-files
EXTRA_FILES: extra-files/test15.txt
*/
-import std.array;
import core.math;
import core.vararg;
-import std.string;
-import std.stdio : File;
extern (C)
{
@@ -281,10 +277,47 @@ void test20()
void test21()
{
+ // Minimalistic byLine implementation
+ static struct Lines
+ {
+ private string text, line;
+ this(string text)
+ {
+ this.text = text;
+ popFront();
+ }
+
+ bool empty() const { return text == ""; }
+
+ string front() const
+ {
+ assert(!empty);
+ return line;
+ }
+
+ void popFront()
+ {
+ assert(!empty);
+ foreach (const idx; 0 .. text.length)
+ {
+ if (text[idx] == '\n')
+ {
+ line = text[0..idx];
+ text = text[idx + 1..$];
+ return;
+ }
+ }
+
+ line = text;
+ text = null;
+ }
+ }
+
+ static immutable string file = import(`test15.txt`);
+
int[string] esdom;
- auto f = File("runnable/extra-files/test15.txt", "r");
- foreach(it; f.byLine())
+ foreach(it; Lines(file))
esdom[it.idup] = 0;
esdom.rehash;
@@ -363,11 +396,11 @@ void test25()
void test26()
{
- string[] instructions = std.array.split("a;b;c", ";");
+ string[] instructions =[ "a", "b", "c" ];
foreach(ref string instr; instructions)
{
- std.string.strip(instr);
+ instr = instr[];
}
foreach(string instr; instructions)
@@ -1117,16 +1150,13 @@ void test60()
class StdString
{
- alias std.string.format toString;
+ alias nearest = core.math.rint;
}
void test61()
{
- int i = 123;
StdString g = new StdString();
- string s = g.toString("%s", i);
- printf("%.*s\n", cast(int)s.length, s.ptr);
- assert(s == "123");
+ assert(g.nearest(123.1) == 123);
}
diff --git a/gcc/testsuite/gdc.test/runnable/ufcs.d b/gcc/testsuite/gdc.test/runnable/ufcs.d
index fb9039b8df2..2d9bf155983 100644
--- a/gcc/testsuite/gdc.test/runnable/ufcs.d
+++ b/gcc/testsuite/gdc.test/runnable/ufcs.d
@@ -1,4 +1,3 @@
-// RUNNABLE_PHOBOS_TEST
// EXTRA_SOURCES: imports/ufcs5a.d imports/ufcs5b.d imports/ufcs5c.d imports/ufcs5d.d imports/ufcs5e.d
module ufcs;
@@ -422,8 +421,6 @@ class C5 : B5
/*******************************************/
// https://issues.dlang.org/show_bug.cgi?id=662
-import std.string, std.conv;
-
enum Etest
{
a,b,c,d
@@ -448,6 +445,10 @@ int test(Etest test)
//{
// return cast(int)i;
//}
+string to(T)(int i) {
+ assert(i == 22);
+ return "22";
+}
void test682()
{
@@ -465,13 +466,54 @@ void test682()
/*******************************************/
// https://issues.dlang.org/show_bug.cgi?id=3382
-import std.range, std.algorithm;
-
@property T twice(T)(T x){ return x * x; }
char toupper(char c){ return ('a'<=c && c<='z') ? cast(char)(c - 'a' + 'A') : c; }
@property ref T setter(T)(ref T x, T v){ x = v; return x; }
+auto iota(T)(T min, T max)
+{
+ static struct Result
+ {
+ T cur, end;
+
+ T front() { return cur; }
+ bool empty() { return front == end; }
+ void popFront() { cur++; }
+ }
+ return Result(min, max);
+}
+
+auto map(string s, R)(R range)
+{
+ static struct Result
+ {
+ R source;
+ auto front() { auto a = source.front; return mixin(s); }
+ alias source this;
+ }
+ return Result(range);
+}
+
+auto filter(string s, R)(R range)
+{
+ static struct Result
+ {
+ R source;
+ alias source this;
+ void popFront()
+ {
+ while (true)
+ {
+ auto a = source.front;
+ if (mixin(s)) break;
+ source.popFront();
+ }
+ }
+ }
+ return Result(range);
+}
+
void test3382()
{
auto r = iota(0, 10).map!"a*3"().filter!"a%2 != 0"();
@@ -486,10 +528,23 @@ void test3382()
/*******************************************/
// https://issues.dlang.org/show_bug.cgi?id=6185
-void test6185()
+ref T front(T)(T[] array) { return array[0]; }
+bool empty(T)(T[] array) { return array.length == 0; }
+void popFront(T)(ref T[] array) { array = array[1..$]; }
+
+bool equal(T, U)(T t, U u)
{
- import std.algorithm;
+ while (true)
+ {
+ if (t.empty) return u.empty;
+ if (u.empty || t.front != u.front) return false;
+ t.popFront();
+ u.popFront();
+ }
+}
+void test6185()
+{
auto r1 = [1,2,3].map!"a*2";
assert(equal(r1, [2,4,6]));
diff --git a/libphobos/libdruntime/core/exception.d b/libphobos/libdruntime/core/exception.d
index 252e33da8b0..734fbcf9bae 100644
--- a/libphobos/libdruntime/core/exception.d
+++ b/libphobos/libdruntime/core/exception.d
@@ -51,6 +51,11 @@ class RangeError : Error
{
super( "Range violation", file, line, next );
}
+
+ protected this( string msg, string file, size_t line, Throwable next = null ) @nogc nothrow pure @safe
+ {
+ super( msg, file, line, next );
+ }
}
unittest
@@ -72,6 +77,142 @@ unittest
}
}
+/**
+ * Thrown when an out of bounds array index is accessed.
+ */
+class ArrayIndexError : RangeError
+{
+ /// Index into array
+ const size_t index;
+ /// Length of indexed array
+ const size_t length;
+
+ // Buffer to avoid GC allocations
+ private immutable char[100] msgBuf = '\0';
+
+ this(size_t index, size_t length, string file = __FILE__,
+ size_t line = __LINE__, Throwable next = null) @nogc nothrow pure @safe
+ {
+ this.index = index;
+ this.length = length;
+
+ // Constructing the message is a bit clumsy:
+ // It's essentially `printf("index [%zu] exceeds array of length [%zu]", index, length)`,
+ // but even `snprintf` isn't `pure`.
+ // Also string concatenation isn't `@nogc`, and casting to/from immutable isn't `@safe`
+ import core.internal.string : unsignedToTempString;
+ char[msgBuf.length] buf = void;
+ char[20] tmpBuf = void;
+ char[] sink = buf[];
+ sink.rangeMsgPut("index [");
+ sink.rangeMsgPut(unsignedToTempString!10(index, tmpBuf));
+ sink.rangeMsgPut("]");
+ sink.rangeMsgPut(" exceeds array of length ");
+ sink.rangeMsgPut(unsignedToTempString!10(length, tmpBuf));
+ this.msgBuf = buf;
+ super(msgBuf[0..$-sink.length], file, line, next);
+ }
+}
+
+@safe pure unittest
+{
+ assert(new ArrayIndexError(900, 700).msg == "index [900] exceeds array of length 700");
+ // Ensure msg buffer doesn't overflow on large numbers
+ assert(new ArrayIndexError(size_t.max, size_t.max-1).msg);
+}
+
+unittest
+{
+ try
+ {
+ _d_arraybounds_indexp("test", 400, 9, 3);
+ assert(0, "no ArrayIndexError thrown");
+ }
+ catch (ArrayIndexError re)
+ {
+ assert(re.file == "test");
+ assert(re.line == 400);
+ assert(re.index == 9);
+ assert(re.length == 3);
+ }
+}
+
+/**
+ * Thrown when an out of bounds array slice is created
+ */
+class ArraySliceError : RangeError
+{
+ /// Lower/upper bound passed to slice: `array[lower .. upper]`
+ const size_t lower, upper;
+ /// Length of sliced array
+ const size_t length;
+
+ private immutable char[120] msgBuf = '\0';
+
+ this(size_t lower, size_t upper, size_t length, string file = __FILE__,
+ size_t line = __LINE__, Throwable next = null) @nogc nothrow pure @safe
+ {
+ this.lower = lower;
+ this.upper = upper;
+ this.length = length;
+
+ // Constructing the message is a bit clumsy for the same reasons as ArrayIndexError
+ import core.internal.string : unsignedToTempString;
+ char[msgBuf.length] buf = void;
+ char[20] tmpBuf = void;
+ char[] sink = buf;
+ sink.rangeMsgPut("slice [");
+ sink.rangeMsgPut(unsignedToTempString!10(lower, tmpBuf));
+ sink.rangeMsgPut(" .. ");
+ sink.rangeMsgPut(unsignedToTempString!10(upper, tmpBuf));
+ sink.rangeMsgPut("] ");
+ if (lower > upper)
+ {
+ sink.rangeMsgPut("has a larger lower index than upper index");
+ }
+ else
+ {
+ sink.rangeMsgPut("extends past source array of length ");
+ sink.rangeMsgPut(unsignedToTempString!10(length, tmpBuf));
+ }
+
+ this.msgBuf = buf;
+ super(msgBuf[0..$-sink.length], file, line, next);
+ }
+}
+
+@safe pure unittest
+{
+ assert(new ArraySliceError(40, 80, 20).msg == "slice [40 .. 80] extends past source array of length 20");
+ assert(new ArraySliceError(90, 70, 20).msg == "slice [90 .. 70] has a larger lower index than upper index");
+ // Ensure msg buffer doesn't overflow on large numbers
+ assert(new ArraySliceError(size_t.max, size_t.max, size_t.max-1).msg);
+}
+
+unittest
+{
+ try
+ {
+ _d_arraybounds_slicep("test", 400, 1, 7, 3);
+ assert(0, "no ArraySliceError thrown");
+ }
+ catch (ArraySliceError re)
+ {
+ assert(re.file == "test");
+ assert(re.line == 400);
+ assert(re.lower == 1);
+ assert(re.upper == 7);
+ assert(re.length == 3);
+ }
+}
+
+/// Mini `std.range.primitives: put` for constructor of ArraySliceError / ArrayIndexError
+private void rangeMsgPut(ref char[] r, scope const(char)[] e) @nogc nothrow pure @safe
+{
+ assert(r.length >= e.length); // don't throw ArraySliceError inside ArrayIndexError ctor
+ r[0 .. e.length] = e[];
+ r = r[e.length .. $];
+}
/**
* Thrown on an assert error.
@@ -470,7 +611,7 @@ extern (C) void onUnittestErrorMsg( string file, size_t line, string msg ) nothr
///////////////////////////////////////////////////////////////////////////////
/**
- * A callback for array bounds errors in D. A $(LREF RangeError) will be thrown.
+ * A callback for general array bounds errors in D. A $(LREF RangeError) will be thrown.
*
* Params:
* file = The name of the file that signaled this error.
@@ -481,9 +622,45 @@ extern (C) void onUnittestErrorMsg( string file, size_t line, string msg ) nothr
*/
extern (C) void onRangeError( string file = __FILE__, size_t line = __LINE__ ) @trusted pure nothrow @nogc
{
- throw staticError!RangeError( file, line, null );
+ throw staticError!RangeError(file, line, null);
}
+/**
+ * A callback for array slice out of bounds errors in D.
+ *
+ * Params:
+ * lower = the lower bound of the index passed of a slice
+ * upper = the upper bound of the index passed of a slice or the index if not a slice
+ * length = length of the array
+ * file = The name of the file that signaled this error.
+ * line = The line number on which this error occurred.
+ *
+ * Throws:
+ * $(LREF ArraySliceError).
+ */
+extern (C) void onArraySliceError( size_t lower = 0, size_t upper = 0, size_t length = 0,
+ string file = __FILE__, size_t line = __LINE__ ) @trusted pure nothrow @nogc
+{
+ throw staticError!ArraySliceError(lower, upper, length, file, line, null);
+}
+
+/**
+ * A callback for array index out of bounds errors in D.
+ *
+ * Params:
+ * index = index in the array
+ * length = length of the array
+ * file = The name of the file that signaled this error.
+ * line = The line number on which this error occurred.
+ *
+ * Throws:
+ * $(LREF ArrayIndexError).
+ */
+extern (C) void onArrayIndexError( size_t index = 0, size_t length = 0,
+ string file = __FILE__, size_t line = __LINE__ ) @trusted pure nothrow @nogc
+{
+ throw staticError!ArrayIndexError(index, length, file, line, null);
+}
/**
* A callback for finalize errors in D. A $(LREF FinalizeError) will be thrown.
@@ -613,22 +790,36 @@ extern (C)
_d_unittest_msg("unittest failure", file, line);
}
- /* Called when an array index is out of bounds
- */
+ /// Called when an invalid array index/slice or associative array key is accessed
void _d_arrayboundsp(immutable(char*) file, uint line)
{
import core.stdc.string : strlen;
onRangeError(file[0 .. strlen(file)], line);
}
+ /// ditto
void _d_arraybounds(string file, uint line)
{
onRangeError(file, line);
}
+
+ /// Called when an out of range slice of an array is created
+ void _d_arraybounds_slicep(immutable(char*) file, uint line, size_t lower, size_t upper, size_t length)
+ {
+ import core.stdc.string : strlen;
+ onArraySliceError(lower, upper, length, file[0 .. strlen(file)], line);
+ }
+
+ /// Called when an out of range array index is accessed
+ void _d_arraybounds_indexp(immutable(char*) file, uint line, size_t index, size_t length)
+ {
+ import core.stdc.string : strlen;
+ onArrayIndexError(index, length, file[0 .. strlen(file)], line);
+ }
}
// TLS storage shared for all errors, chaining might create circular reference
-private align(2 * size_t.sizeof) void[128] _store;
+private align(2 * size_t.sizeof) void[256] _store;
// only Errors for now as those are rarely chained
private T staticError(T, Args...)(auto ref Args args)
diff --git a/libphobos/libdruntime/core/internal/atomic.d b/libphobos/libdruntime/core/internal/atomic.d
index 0d9f903b100..3036ea72d15 100644
--- a/libphobos/libdruntime/core/internal/atomic.d
+++ b/libphobos/libdruntime/core/internal/atomic.d
@@ -10,7 +10,7 @@
module core.internal.atomic;
-import core.atomic : MemoryOrder;
+import core.atomic : MemoryOrder, has128BitCAS;
version (DigitalMars)
{
@@ -1065,8 +1065,9 @@ enum CanCAS(T) = is(T : ulong) ||
is(T : U[], U) ||
is(T : R delegate(A), R, A...) ||
(is(T == struct) && __traits(isPOD, T) &&
- T.sizeof <= size_t.sizeof*2 && // no more than 2 words
- (T.sizeof & (T.sizeof - 1)) == 0 // is power of 2
+ (T.sizeof <= size_t.sizeof*2 || // no more than 2 words
+ (T.sizeof == 16 && has128BitCAS)) && // or supports 128-bit CAS
+ (T.sizeof & (T.sizeof - 1)) == 0 // is power of 2
);
template IntOrLong(T)
diff --git a/libphobos/libdruntime/core/internal/backtrace/dwarf.d b/libphobos/libdruntime/core/internal/backtrace/dwarf.d
index 9e1b39d167a..f17658b1cf9 100644
--- a/libphobos/libdruntime/core/internal/backtrace/dwarf.d
+++ b/libphobos/libdruntime/core/internal/backtrace/dwarf.d
@@ -317,7 +317,9 @@ void resolveAddresses(const(ubyte)[] debugLineSectionData, Location[] locations,
// Can be called with either `locInfo` or `lastLoc`
void update(const ref LocationInfo match)
{
- const sourceFile = lp.sourceFiles[match.file - 1];
+ // File indices are 1-based for DWARF < 5
+ const fileIndex = match.file - (lp.dwarfVersion < 5 ? 1 : 0);
+ const sourceFile = lp.sourceFiles[fileIndex];
debug (DwarfDebugMachine)
{
printf("-- found for [%p]:\n", loc.address);
@@ -325,7 +327,7 @@ void resolveAddresses(const(ubyte)[] debugLineSectionData, Location[] locations,
cast(int) sourceFile.file.length, sourceFile.file.ptr);
printf("-- line: %d\n", match.line);
}
- // DMD emits entries with FQN, but other implmentations
+ // DMD emits entries with FQN, but other implementations
// (e.g. LDC) make use of directories
// See https://github.com/dlang/druntime/pull/2945
if (sourceFile.dirIndex != 0)
@@ -592,76 +594,13 @@ T read(T)(ref const(ubyte)[] buffer) @nogc nothrow
return result;
}
-/**
- * Reads an ULEB128 length and then reads the followings bytes specified by the
- * length.
- *
- * Params:
- * buffer = buffer where the data is read from
- * Returns:
- * Value contained in the block.
- */
-ulong readBlock(ref const(ubyte)[] buffer) @nogc nothrow
+// Reads a null-terminated string from `buffer`.
+const(char)[] readStringz(ref const(ubyte)[] buffer) @nogc nothrow
{
- ulong length = buffer.readULEB128();
- assert(length <= ulong.sizeof);
-
- ulong block;
- foreach (i; 0 .. length)
- {
- ubyte b = buffer.read!ubyte;
- block <<= 8 * i;
- block |= b;
- }
-
- return block;
-}
-
-/**
- * Reads a MD5 hash from the `buffer`.
- *
- * Params:
- * buffer = buffer where the data is read from
- * Returns:
- * A MD5 hash
- */
-char[16] readMD5(ref const(ubyte)[] buffer) @nogc nothrow
-{
- assert(buffer.length >= 16);
-
- ubyte[16] bytes;
- foreach (h; 0 .. 16)
- bytes[h] = buffer.read!ubyte;
-
- return cast(char[16])bytes;
-}
-
-/**
- * Reads a null-terminated string from `buffer`.
- * The string is not removed from buffer and doesn't contain the last null byte.
- *
- * Params:
- * buffer = buffer where the data is read from
- *
- * Returns:
- * A string
- */
-const(char)[] readString(ref const(ubyte)[] buffer) @nogc nothrow
-{
- import core.sys.posix.string : strnlen;
-
- return cast(const(char)[])buffer[0 .. strnlen(cast(char*)buffer.ptr, buffer.length)];
-}
-
-unittest
-{
- const(ubyte)[] data = [0x48, 0x61, 0x76, 0x65, 0x20, 0x61, 0x20, 0x67, 0x6f,
- 0x6f, 0x64, 0x20, 0x64, 0x61, 0x79, 0x20, 0x21, 0x00];
- const(char)[] result = data.readString();
- assert(result == "Have a good day !");
-
- data = [0x00];
- assert(data.readString == null);
+ const p = cast(char*) buffer.ptr;
+ const str = p[0 .. strlen(p)];
+ buffer = buffer[str.length+1 .. $];
+ return str;
}
ulong readULEB128(ref const(ubyte)[] buffer) @nogc nothrow
@@ -710,102 +649,18 @@ long readSLEB128(ref const(ubyte)[] buffer) @nogc nothrow
return val;
}
-Array!EntryFormatData readEntryFormat(ref const(ubyte)[] buffer, ref Array!ulong entryFormat) @nogc nothrow
+enum DW_LNCT : ushort
{
- // The count needs to be pair, as the specification says
- assert(entryFormat.length % 2 == 0);
- Array!EntryFormatData result;
-
- for (uint i = 0; i < entryFormat.length; i += 2)
- {
- EntryFormatData efdata;
- ulong form = entryFormat[i + 1];
-
- switch (entryFormat[i])
- {
- case StandardContentDescription.path:
- if (form == FormEncoding._string)
- efdata.path = buffer.readString();
- else
- {
- size_t offset = buffer.read!size_t;
-
- // TODO: set filename.path to the string at offset
- static if (0)
- {
- if (form == FormEncoding.line_strp) // Offset in debug_line_str
- {
-
- }
- else if (form == FormEncoding.strp) // Offset in debug_str
- {
-
- }
- else if (form == FormEncoding.strp_sup) // Offset of debug_str in debug_info
- {
-
- }
- else
- assert(0);
- }
- else
- assert(0);
- }
- break;
-
- case StandardContentDescription.directoryIndex:
- if (form == FormEncoding.data1)
- efdata.directoryIndex = cast(ulong)buffer.read!ubyte;
- else if (form == FormEncoding.data2)
- efdata.directoryIndex = cast(ulong)buffer.read!ushort;
- else if (form == FormEncoding.udata)
- efdata.directoryIndex = buffer.readULEB128();
- else
- assert(0);
- break;
-
- case StandardContentDescription.timeStamp:
- if (form == FormEncoding.udata)
- efdata.timeStamp = buffer.readULEB128();
- else if (form == FormEncoding.data4)
- efdata.timeStamp = cast(ulong)buffer.read!uint;
- else if (form == FormEncoding.data8)
- efdata.timeStamp = buffer.read!ulong;
- else if (form == FormEncoding.block)
- efdata.timeStamp = buffer.readBlock();
- else
- assert(0);
- break;
-
- case StandardContentDescription.size:
- if (form == FormEncoding.data1)
- efdata.size = cast(ulong)buffer.read!ubyte;
- else if (form == FormEncoding.data2)
- efdata.size = cast(ulong)buffer.read!ushort;
- else if (form == FormEncoding.data4)
- efdata.size = cast(ulong)buffer.read!uint;
- else if (form == FormEncoding.data8)
- efdata.size = buffer.read!ulong;
- else
- assert(0);
- break;
-
- case StandardContentDescription.md5:
- if (form == FormEncoding.data16)
- efdata.md5 = buffer.readMD5();
- else
- assert(0);
- break;
-
- default:
- assert(0);
- }
- result.insertBack(efdata);
- }
- return result;
+ path = 1,
+ directoryIndex = 2,
+ timestamp = 3,
+ size = 4,
+ md5 = 5,
+ loUser = 0x2000,
+ hiUser = 0x3fff,
}
-enum FormEncoding : ubyte
+enum DW_FORM : ubyte
{
addr = 1,
block2 = 3,
@@ -813,7 +668,7 @@ enum FormEncoding : ubyte
data2 = 5,
data4 = 6,
data8 = 7,
- _string = 8,
+ string_ = 8,
block = 9,
block1 = 10,
data1 = 11,
@@ -852,6 +707,36 @@ enum FormEncoding : ubyte
addrx4 = 44,
}
+struct EntryFormatPair
+{
+ DW_LNCT type;
+ DW_FORM form;
+}
+
+/// Reads a DWARF v5 directory/file name entry format.
+Array!EntryFormatPair readEntryFormat(ref const(ubyte)[] buffer) @nogc nothrow
+{
+ const numPairs = buffer.read!ubyte();
+
+ Array!EntryFormatPair pairs;
+ pairs.length = numPairs;
+
+ foreach (ref pair; pairs)
+ {
+ pair.type = cast(DW_LNCT) buffer.readULEB128();
+ pair.form = cast(DW_FORM) buffer.readULEB128();
+ }
+
+ debug (DwarfDebugMachine)
+ {
+ printf("entryFormat: (%d)\n", cast(int) pairs.length);
+ foreach (ref pair; pairs)
+ printf("\t- type: %d, form: %d\n", cast(int) pair.type, cast(int) pair.form);
+ }
+
+ return pairs;
+}
+
enum StandardOpcode : ubyte
{
extendedOp = 0,
@@ -877,24 +762,6 @@ enum ExtendedOpcode : ubyte
setDiscriminator = 4,
}
-enum StandardContentDescription : ubyte
-{
- path = 1,
- directoryIndex = 2,
- timeStamp = 3,
- size = 4,
- md5 = 5,
-}
-
-struct EntryFormatData
-{
- const(char)[] path;
- ulong directoryIndex;
- ulong timeStamp;
- ulong size;
- char[16] md5;
-}
-
struct StateMachine
{
const(void)* address;
@@ -931,17 +798,6 @@ struct LineNumberProgram
ubyte lineRange;
ubyte opcodeBase;
const(ubyte)[] standardOpcodeLengths;
-
- ubyte directoryEntryFormatCount;
- Array!ulong directoryEntryFormat;
- ulong directoriesCount;
- Array!EntryFormatData directories;
-
- ubyte fileNameEntryFormatCount;
- Array!ulong fileNameEntryFormat;
- ulong fileNamesCount;
- Array!EntryFormatData fileNames;
-
Array!(const(char)[]) includeDirectories;
Array!SourceFile sourceFiles;
const(ubyte)[] program;
@@ -950,7 +806,7 @@ struct LineNumberProgram
struct SourceFile
{
const(char)[] file;
- size_t dirIndex;
+ size_t dirIndex; // 1-based
}
LineNumberProgram readLineNumberProgram(ref const(ubyte)[] data) @nogc nothrow
@@ -993,78 +849,135 @@ LineNumberProgram readLineNumberProgram(ref const(ubyte)[] data) @nogc nothrow
if (lp.dwarfVersion >= 5)
{
- lp.directoryEntryFormatCount = data.read!ubyte();
- foreach (c; 0 .. lp.directoryEntryFormatCount)
- lp.directoryEntryFormat.insertBack(data.readULEB128());
-
- lp.directoriesCount = data.readULEB128();
- lp.directories = data.readEntryFormat(lp.directoryEntryFormat);
-
-
- lp.fileNameEntryFormatCount = data.read!ubyte;
- foreach (c; 0 .. lp.fileNameEntryFormatCount)
- lp.fileNameEntryFormat.insertBack(data.readULEB128());
-
- lp.fileNamesCount = data.readULEB128();
- lp.fileNames = data.readEntryFormat(lp.fileNameEntryFormat);
- }
-
- // A sequence ends with a null-byte.
- static auto readSequence(alias ReadEntry)(ref const(ubyte)[] data)
- {
- alias ResultType = typeof(ReadEntry(data));
-
- static size_t count(const(ubyte)[] data)
+ static void consumeGenericForm(ref const(ubyte)[] data, DW_FORM form, bool is64bitDwarf)
{
- size_t count = 0;
- while (data.length && data[0] != 0)
+ with (DW_FORM) switch (form)
{
- ReadEntry(data);
- ++count;
+ case strp, strp_sup, line_strp:
+ data = data[is64bitDwarf ? 8 : 4 .. $]; break;
+ case data1, strx1:
+ data = data[1 .. $]; break;
+ case data2, strx2:
+ data = data[2 .. $]; break;
+ case strx3:
+ data = data[3 .. $]; break;
+ case data4, strx4:
+ data = data[4 .. $]; break;
+ case data8:
+ data = data[8 .. $]; break;
+ case data16:
+ data = data[16 .. $]; break;
+ case udata, strx:
+ data.readULEB128(); break;
+ case block:
+ const length = cast(size_t) data.readULEB128();
+ data = data[length .. $];
+ break;
+ default:
+ assert(0); // TODO: support other forms for vendor extensions
}
- return count;
}
- const numEntries = count(data);
+ const dirFormat = data.readEntryFormat();
+ lp.includeDirectories.length = cast(size_t) data.readULEB128();
+ foreach (ref dir; lp.includeDirectories)
+ {
+ dir = "<unknown dir>"; // fallback
+ foreach (ref pair; dirFormat)
+ {
+ if (pair.type == DW_LNCT.path &&
+ // TODO: support other forms too (offsets in other sections)
+ pair.form == DW_FORM.string_)
+ {
+ dir = data.readStringz();
+ }
+ else // uninteresting type
+ consumeGenericForm(data, pair.form, is64bitDwarf);
+ }
+ }
- Array!ResultType result;
- result.length = numEntries;
+ const fileFormat = data.readEntryFormat();
+ lp.sourceFiles.length = cast(size_t) data.readULEB128();
+ foreach (ref sf; lp.sourceFiles)
+ {
+ sf.file = "<unknown file>"; // fallback
+ foreach (ref pair; fileFormat)
+ {
+ if (pair.type == DW_LNCT.path &&
+ // TODO: support other forms too (offsets in other sections)
+ pair.form == DW_FORM.string_)
+ {
+ sf.file = data.readStringz();
+ }
+ else if (pair.type == DW_LNCT.directoryIndex)
+ {
+ if (pair.form == DW_FORM.data1)
+ sf.dirIndex = data.read!ubyte();
+ else if (pair.form == DW_FORM.data2)
+ sf.dirIndex = data.read!ushort();
+ else if (pair.form == DW_FORM.udata)
+ sf.dirIndex = cast(size_t) data.readULEB128();
+ else
+ assert(0); // not allowed by DWARF 5 spec
+ sf.dirIndex++; // DWARF v5 indices are 0-based
+ }
+ else // uninteresting type
+ consumeGenericForm(data, pair.form, is64bitDwarf);
+ }
+ }
+ }
+ else
+ {
+ // A sequence ends with a null-byte.
+ static auto readSequence(alias ReadEntry)(ref const(ubyte)[] data)
+ {
+ alias ResultType = typeof(ReadEntry(data));
- foreach (i; 0 .. numEntries)
- result[i] = ReadEntry(data);
+ static size_t count(const(ubyte)[] data)
+ {
+ size_t count = 0;
+ while (data.length && data[0] != 0)
+ {
+ ReadEntry(data);
+ ++count;
+ }
+ return count;
+ }
- data = data[1 .. $]; // skip over sequence-terminating null
+ const numEntries = count(data);
- return result;
- }
+ Array!ResultType result;
+ result.length = numEntries;
- /// Directories are simply a sequence of NUL-terminated strings
- static const(char)[] readIncludeDirectoryEntry(ref const(ubyte)[] data)
- {
- const ptr = cast(const(char)*) data.ptr;
- const dir = ptr[0 .. strlen(ptr)];
- data = data[dir.length + "\0".length .. $];
- return dir;
- }
- lp.includeDirectories = readSequence!readIncludeDirectoryEntry(data);
+ foreach (i; 0 .. numEntries)
+ result[i] = ReadEntry(data);
- static SourceFile readFileNameEntry(ref const(ubyte)[] data)
- {
- const ptr = cast(const(char)*) data.ptr;
- const file = ptr[0 .. strlen(ptr)];
- data = data[file.length + "\0".length .. $];
+ data = data[1 .. $]; // skip over sequence-terminating null
- auto dirIndex = cast(size_t) data.readULEB128();
+ return result;
+ }
- data.readULEB128(); // last mod
- data.readULEB128(); // file len
+ /// Directories are simply a sequence of NUL-terminated strings
+ static const(char)[] readIncludeDirectoryEntry(ref const(ubyte)[] data)
+ {
+ return data.readStringz();
+ }
+ lp.includeDirectories = readSequence!readIncludeDirectoryEntry(data);
- return SourceFile(
- file,
- dirIndex,
- );
+ static SourceFile readFileNameEntry(ref const(ubyte)[] data)
+ {
+ const file = data.readStringz();
+ const dirIndex = cast(size_t) data.readULEB128();
+ data.readULEB128(); // last mod
+ data.readULEB128(); // file len
+
+ return SourceFile(
+ file,
+ dirIndex,
+ );
+ }
+ lp.sourceFiles = readSequence!readFileNameEntry(data);
}
- lp.sourceFiles = readSequence!readFileNameEntry(data);
debug (DwarfDebugMachine)
{
diff --git a/libphobos/libdruntime/core/internal/dassert.d b/libphobos/libdruntime/core/internal/dassert.d
index c2701fa7af6..6aaef53f066 100644
--- a/libphobos/libdruntime/core/internal/dassert.d
+++ b/libphobos/libdruntime/core/internal/dassert.d
@@ -37,6 +37,10 @@ module core.internal.dassert;
*/
string _d_assert_fail(A)(const scope string op, auto ref const scope A a)
{
+ // Prevent InvalidMemoryOperationError when triggered from a finalizer
+ if (inFinalizer())
+ return "Assertion failed (rich formatting is disabled in finalizers)";
+
string[2] vals = [ miniFormatFakeAttributes(a), "true" ];
immutable token = op == "!" ? "==" : "!=";
return combine(vals[0 .. 1], token, vals[1 .. $]);
@@ -62,6 +66,10 @@ template _d_assert_fail(A...)
const scope string comp, auto ref const scope A a, auto ref const scope B b)
if (B.length != 0 || A.length != 1) // Resolve ambiguity with unary overload
{
+ // Prevent InvalidMemoryOperationError when triggered from a finalizer
+ if (inFinalizer())
+ return "Assertion failed (rich formatting is disabled in finalizers)";
+
string[A.length + B.length] vals;
static foreach (idx; 0 .. A.length)
vals[idx] = miniFormatFakeAttributes(a[idx]);
@@ -401,22 +409,53 @@ private string miniFormat(V)(const scope ref V v)
private string formatMembers(V)(const scope ref V v)
{
enum ctxPtr = __traits(isNested, V);
+ enum isOverlapped = calcFieldOverlap([ v.tupleof.offsetof ]);
+
string msg = V.stringof ~ "(";
foreach (i, ref field; v.tupleof)
{
if (i > 0)
msg ~= ", ";
- // Mark context pointer
- static if (ctxPtr && i == v.tupleof.length - 1)
- msg ~= "<context>: ";
+ static if (isOverlapped[i])
+ {
+ msg ~= "<overlapped field>";
+ }
+ else
+ {
+ // Mark context pointer
+ static if (ctxPtr && i == v.tupleof.length - 1)
+ msg ~= "<context>: ";
- msg ~= miniFormat(field);
+ msg ~= miniFormat(field);
+ }
}
msg ~= ")";
return msg;
}
+/**
+ * Calculates whether fields are overlapped based on the passed offsets.
+ *
+ * Params:
+ * offsets = offsets of all fields matching the order of `.tupleof`
+ *
+ * Returns: an array such that arr[n] = true indicates that the n'th field
+ * overlaps with an adjacent field
+ **/
+private bool[] calcFieldOverlap(const scope size_t[] offsets)
+{
+ bool[] overlaps = new bool[](offsets.length);
+
+ foreach (const idx; 1 .. overlaps.length)
+ {
+ if (offsets[idx - 1] == offsets[idx])
+ overlaps[idx - 1] = overlaps[idx] = true;
+ }
+
+ return overlaps;
+}
+
// This should be a local import in miniFormat but fails with a cyclic dependency error
// core.thread.osthread -> core.time -> object -> core.internal.array.capacity
// -> core.atomic -> core.thread -> core.thread.osthread
@@ -476,6 +515,14 @@ private auto pureAlloc(size_t t)
return assumeFakeAttributes(&alloc)(t);
}
+/// Wrapper for GC.inFinalizer that fakes purity
+private bool inFinalizer()() pure nothrow @nogc @safe
+{
+ // CTFE doesn't trigger InvalidMemoryErrors
+ import core.memory : GC;
+ return !__ctfe && assumeFakeAttributes(&GC.inFinalizer)();
+}
+
// https://issues.dlang.org/show_bug.cgi?id=21544
unittest
{
diff --git a/libphobos/libdruntime/core/internal/hash.d b/libphobos/libdruntime/core/internal/hash.d
index 668fc4d8e28..e999f0cada9 100644
--- a/libphobos/libdruntime/core/internal/hash.d
+++ b/libphobos/libdruntime/core/internal/hash.d
@@ -130,16 +130,10 @@ private template canBitwiseHash(T)
//enum hash. CTFE depends on base type
size_t hashOf(T)(auto ref T val, size_t seed = 0)
-if (is(T EType == enum) && (!__traits(isScalar, T) || is(T == __vector)))
+if (is(T == enum) && !__traits(isScalar, T))
{
- static if (is(T EType == enum)) //for EType
- {
- return hashOf(cast(EType) val, seed);
- }
- else
- {
- static assert(0);
- }
+ static if (is(T EType == enum)) {} //for EType
+ return hashOf(cast(EType) val, seed);
}
//CTFE ready (depends on base type).
@@ -261,6 +255,11 @@ size_t hashOf(T)(scope const T val) if (__traits(isScalar, T) && !is(T == __vect
size_t result = cast(size_t) val;
return result ^ (result >> 4);
}
+ else static if (is(T EType == enum) && is(typeof(val[0])))
+ {
+ // Enum type whose base type is vector.
+ return hashOf(cast(EType) val);
+ }
else static if (__traits(isIntegral, T))
{
static if (T.sizeof <= size_t.sizeof)
@@ -301,6 +300,11 @@ size_t hashOf(T)(scope const T val, size_t seed) if (__traits(isScalar, T) && !i
}
return hashOf(cast(size_t) val, seed);
}
+ else static if (is(T EType == enum) && is(typeof(val[0])))
+ {
+ // Enum type whose base type is vector.
+ return hashOf(cast(EType) val, seed);
+ }
else static if (__traits(isIntegral, val) && T.sizeof <= size_t.sizeof)
{
static if (size_t.sizeof < ulong.sizeof)
@@ -357,8 +361,8 @@ size_t hashOf(T)(scope const T val, size_t seed) if (__traits(isScalar, T) && !i
}
}
-size_t hashOf(T)(scope const auto ref T val, size_t seed = 0) @safe @nogc nothrow pure
-if (is(T == __vector) && !is(T == enum))
+size_t hashOf(T)(scope const T val, size_t seed = 0) @safe @nogc nothrow pure
+if (is(T == __vector)) // excludes enum types
{
static if (__traits(isFloating, T) && (floatCoalesceZeroes || floatCoalesceNaNs))
{
@@ -400,10 +404,21 @@ q{
static if (!isChained) enum size_t seed = 0;
static if (hasCallableToHash!(typeof(val))) //CTFE depends on toHash()
{
- static if (isChained)
- return hashOf(cast(size_t) val.toHash(), seed);
+ static if (!__traits(isSame, typeof(val), __traits(parent, val.toHash))
+ && is(typeof(val is null)))
+ {
+ static if (isChained)
+ return hashOf(__traits(getMember, val, __traits(getAliasThis, typeof(val))), seed);
+ else
+ return hashOf(__traits(getMember, val, __traits(getAliasThis, typeof(val))));
+ }
else
- return val.toHash();
+ {
+ static if (isChained)
+ return hashOf(cast(size_t) val.toHash(), seed);
+ else
+ return val.toHash();
+ }
}
else
{
@@ -452,10 +467,21 @@ q{
{
static if (hasCallableToHash!F)
{
- static if (i == 0 && !isChained)
- size_t h = val.tupleof[i].toHash();
+ static if (!__traits(isSame, F, __traits(parent, val.tupleof[i].toHash))
+ && is(typeof(val.tupleof[i] is null)))
+ {
+ static if (i == 0 && !isChained)
+ size_t h = hashOf(__traits(getMember, val.tupleof[i], __traits(getAliasThis, F)));
+ else
+ h = hashOf(__traits(getMember, val.tupleof[i], __traits(getAliasThis, F)), h);
+ }
else
- h = hashOf(cast(size_t) val.tupleof[i].toHash(), h);
+ {
+ static if (i == 0 && !isChained)
+ size_t h = val.tupleof[i].toHash();
+ else
+ h = hashOf(cast(size_t) val.tupleof[i].toHash(), h);
+ }
}
else static if (F.tupleof.length == 1)
{
@@ -580,7 +606,13 @@ if (!is(T == enum) && (is(T == interface) || is(T == class))
&& !canBitwiseHash!T)
{
static if (__traits(compiles, {size_t h = val.toHash();}))
- return val ? val.toHash() : 0;
+ {
+ static if (is(__traits(parent, val.toHash) P) && !is(immutable T* : immutable P*)
+ && is(typeof((ref P p) => p is null)))
+ return val ? hashOf(__traits(getMember, val, __traits(getAliasThis, T))) : 0;
+ else
+ return val ? val.toHash() : 0;
+ }
else
return val ? (cast(Object)val).toHash() : 0;
}
@@ -591,7 +623,14 @@ if (!is(T == enum) && (is(T == interface) || is(T == class))
&& !canBitwiseHash!T)
{
static if (__traits(compiles, {size_t h = val.toHash();}))
- return hashOf(val ? cast(size_t) val.toHash() : size_t(0), seed);
+ {
+ static if (is(__traits(parent, val.toHash) P) && !is(immutable T* : immutable P*)
+ && is(typeof((ref P p) => p is null)))
+ return hashOf(val ? hashOf(__traits(getMember, val, __traits(getAliasThis, T)))
+ : size_t(0), seed);
+ else
+ return hashOf(val ? cast(size_t) val.toHash() : size_t(0), seed);
+ }
else
return hashOf(val ? (cast(Object)val).toHash() : 0, seed);
}
diff --git a/libphobos/libdruntime/core/lifetime.d b/libphobos/libdruntime/core/lifetime.d
index 7836812e16b..fc47b1d9394 100644
--- a/libphobos/libdruntime/core/lifetime.d
+++ b/libphobos/libdruntime/core/lifetime.d
@@ -1915,7 +1915,7 @@ pure nothrow @safe @nogc unittest
static assert(is(typeof({ S s; move(s, s); }) == T));
}
-private void moveImpl(T)(scope ref T target, return ref T source)
+private void moveImpl(T)(scope ref T target, return scope ref T source)
{
import core.internal.traits : hasElaborateDestructor;
@@ -1930,7 +1930,7 @@ private void moveImpl(T)(scope ref T target, return ref T source)
moveEmplaceImpl(target, source);
}
-private T moveImpl(T)(ref T source)
+private T moveImpl(T)(return scope ref T source)
{
// Properly infer safety from moveEmplaceImpl as the implementation below
// might void-initialize pointers in result and hence needs to be @trusted
@@ -1939,7 +1939,7 @@ private T moveImpl(T)(ref T source)
return trustedMoveImpl(source);
}
-private T trustedMoveImpl(T)(ref T source) @trusted
+private T trustedMoveImpl(T)(return scope ref T source) @trusted
{
T result = void;
moveEmplaceImpl(result, source);
diff --git a/libphobos/libdruntime/core/runtime.d b/libphobos/libdruntime/core/runtime.d
index 7669c20645d..bfb72e07b05 100644
--- a/libphobos/libdruntime/core/runtime.d
+++ b/libphobos/libdruntime/core/runtime.d
@@ -785,7 +785,7 @@ version (DRuntime_Use_Libunwind)
alias DefaultTraceInfo = LibunwindHandler;
}
/// Default implementation for most POSIX systems
-static if (hasExecinfo) private class DefaultTraceInfo : Throwable.TraceInfo
+else static if (hasExecinfo) private class DefaultTraceInfo : Throwable.TraceInfo
{
import core.demangle;
import core.stdc.stdlib : free;
diff --git a/libphobos/libdruntime/core/sys/posix/fcntl.d b/libphobos/libdruntime/core/sys/posix/fcntl.d
index 59df921ba41..6d9eb7846d6 100644
--- a/libphobos/libdruntime/core/sys/posix/fcntl.d
+++ b/libphobos/libdruntime/core/sys/posix/fcntl.d
@@ -895,10 +895,10 @@ else version (CRuntime_Musl)
O_SEARCH = O_PATH,
O_EXEC = O_PATH,
- O_ACCMODE = (03|O_SEARCH),
- O_RDONLY = 00,
- O_WRONLY = 01,
- O_RDWR = 02,
+ O_ACCMODE = (3|O_SEARCH),
+ O_RDONLY = 0,
+ O_WRONLY = 1,
+ O_RDWR = 2,
}
enum
{
diff --git a/libphobos/libdruntime/core/sys/windows/sqlext.d b/libphobos/libdruntime/core/sys/windows/sqlext.d
index 3acfc5aa70c..1f891056a82 100644
--- a/libphobos/libdruntime/core/sys/windows/sqlext.d
+++ b/libphobos/libdruntime/core/sys/windows/sqlext.d
@@ -535,7 +535,7 @@ enum SQL_U_UNION_ALL = 2;
enum SQL_UB_OFF = 0UL;
enum SQL_UB_DEFAULT = SQL_UB_OFF;
-enum SQL_UB_ON = 01UL;
+enum SQL_UB_ON = 1UL;
enum SQL_UNION = 96;
enum SQL_UNSEARCHABLE = 0;
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index cec2ef561f4..a8dd832eeed 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -2194,7 +2194,7 @@ const:
* Returns:
* array of pointers to the ModuleInfo's of modules imported by this one
*/
- @property immutable(ModuleInfo*)[] importedModules() nothrow pure @nogc
+ @property immutable(ModuleInfo*)[] importedModules() return nothrow pure @nogc
{
if (flags & MIimportedModules)
{
@@ -2208,7 +2208,7 @@ const:
* Returns:
* array of TypeInfo_Class references for classes defined in this module
*/
- @property TypeInfo_Class[] localClasses() nothrow pure @nogc
+ @property TypeInfo_Class[] localClasses() return nothrow pure @nogc
{
if (flags & MIlocalClasses)
{
@@ -2222,7 +2222,7 @@ const:
* Returns:
* name of module, `null` if no name
*/
- @property string name() nothrow pure @nogc
+ @property string name() return nothrow pure @nogc
{
import core.stdc.string : strlen;
@@ -3505,7 +3505,7 @@ private U[] _dup(T, U)(scope T[] a) pure nothrow @trusted if (__traits(isPOD, T)
return *cast(U[]*) &arr;
}
-private U[] _dupCtfe(T, U)(T[] a)
+private U[] _dupCtfe(T, U)(scope T[] a)
{
static if (is(T : void))
assert(0, "Cannot dup a void[] array at compile time.");
@@ -3546,6 +3546,21 @@ private U[] _dup(T, U)(T[] a) if (!__traits(isPOD, T))
return res;
}
+// https://issues.dlang.org/show_bug.cgi?id=22107
+@safe unittest
+{
+ static int i;
+ @safe struct S
+ {
+ this(this) { i++; }
+ }
+
+ void fun(scope S[] values...) @safe
+ {
+ values.dup;
+ }
+}
+
// HACK: This is a lie. `_d_arraysetcapacity` is neither `nothrow` nor `pure`, but this lie is
// necessary for now to prevent breaking code.
private extern (C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void[]* arrptr) pure nothrow;
@@ -3820,7 +3835,7 @@ private void _doPostblit(T)(T[] arr)
[].dup!Sunpure;
[].dup!Sthrow;
- [].dup!Sunsafe;
+ cast(void) [].dup!Sunsafe;
static assert(!__traits(compiles, () pure { [].dup!Sunpure; }));
static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
static assert(!__traits(compiles, () @safe { [].dup!Sunsafe; }));
@@ -3871,7 +3886,7 @@ private void _doPostblit(T)(T[] arr)
static struct Sunsafe { this(ref const typeof(this)) @system pure nothrow {} }
[].dup!Sunpure;
[].dup!Sthrow;
- [].dup!Sunsafe;
+ cast(void) [].dup!Sunsafe;
static assert(!__traits(compiles, () pure { [].dup!Sunpure; }));
static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
static assert(!__traits(compiles, () @safe { [].dup!Sunsafe; }));
diff --git a/libphobos/src/std/algorithm/comparison.d b/libphobos/src/std/algorithm/comparison.d
index dd42bff7e9c..c9525445ceb 100644
--- a/libphobos/src/std/algorithm/comparison.d
+++ b/libphobos/src/std/algorithm/comparison.d
@@ -1516,7 +1516,7 @@ Iterates the passed arguments and returns the maximum value.
Params:
args = The values to select the maximum from. At least two arguments must
- be passed, and they must be comparable with `>`.
+ be passed, and they must be comparable with `<`.
Returns:
The maximum of the passed-in values. The type of the returned value is
@@ -1564,6 +1564,16 @@ if (T.length >= 2 && !is(CommonType!T == void))
return cast(Result) (chooseB ? b : a);
}
+/// ditto
+T max(T, U)(T a, U b)
+if (is(T == U) && is(typeof(a < b)))
+{
+ /* Handle the common case without all the template expansions
+ * of the general case
+ */
+ return a < b ? b : a;
+}
+
///
@safe @betterC @nogc unittest
{
@@ -1664,6 +1674,17 @@ if (T.length >= 2 && !is(CommonType!T == void))
return cast(Result) (chooseB ? b : a);
}
+/// ditto
+T min(T, U)(T a, U b)
+if (is(T == U) && is(typeof(a < b)))
+{
+ /* Handle the common case without all the template expansions
+ * of the general case
+ */
+ return b < a ? b : a;
+}
+
+
///
@safe @nogc @betterC unittest
{
diff --git a/libphobos/src/std/algorithm/mutation.d b/libphobos/src/std/algorithm/mutation.d
index 6d1e2313bb6..88191bbf3f7 100644
--- a/libphobos/src/std/algorithm/mutation.d
+++ b/libphobos/src/std/algorithm/mutation.d
@@ -1074,7 +1074,7 @@ Params:
*/
void move(T)(ref T source, ref T target)
{
- moveImpl(source, target);
+ moveImpl(target, source);
}
/// For non-struct types, `move` just performs `target = source`:
@@ -1244,7 +1244,7 @@ pure nothrow @safe @nogc unittest
static assert(is(typeof({ S s; move(s, s); }) == T));
}
-private void moveImpl(T)(ref T source, ref T target)
+private void moveImpl(T)(ref scope T target, ref return scope T source)
{
import std.traits : hasElaborateDestructor;
@@ -1257,10 +1257,10 @@ private void moveImpl(T)(ref T source, ref T target)
static if (hasElaborateDestructor!T) target.__xdtor();
}
// move and emplace source into target
- moveEmplaceImpl(source, target);
+ moveEmplaceImpl(target, source);
}
-private T moveImpl(T)(ref T source)
+private T moveImpl(T)(ref return scope T source)
{
// Properly infer safety from moveEmplaceImpl as the implementation below
// might void-initialize pointers in result and hence needs to be @trusted
@@ -1269,10 +1269,10 @@ private T moveImpl(T)(ref T source)
return trustedMoveImpl(source);
}
-private T trustedMoveImpl(T)(ref T source) @trusted
+private T trustedMoveImpl(T)(ref return scope T source) @trusted
{
T result = void;
- moveEmplaceImpl(source, result);
+ moveEmplaceImpl(result, source);
return result;
}
@@ -1415,7 +1415,7 @@ private T trustedMoveImpl(T)(ref T source) @trusted
move(x, x);
}
-private void moveEmplaceImpl(T)(ref T source, ref T target)
+private void moveEmplaceImpl(T)(ref scope T target, ref return scope T source)
{
import core.stdc.string : memcpy, memset;
import std.traits : hasAliasing, hasElaborateAssign,
@@ -1486,7 +1486,7 @@ private void moveEmplaceImpl(T)(ref T source, ref T target)
*/
void moveEmplace(T)(ref T source, ref T target) pure @system
{
- moveEmplaceImpl(source, target);
+ moveEmplaceImpl(target, source);
}
///
@@ -2388,7 +2388,7 @@ Range remove(alias pred, SwapStrategy s = SwapStrategy.stable, Range)(Range rang
@nogc @safe unittest
{
// @nogc test
- int[10] arr = [0,1,2,3,4,5,6,7,8,9];
+ static int[] arr = [0,1,2,3,4,5,6,7,8,9];
alias pred = e => e < 5;
auto r = arr[].remove!(SwapStrategy.unstable)(0);
diff --git a/libphobos/src/std/array.d b/libphobos/src/std/array.d
index bca137dbf58..0466c08ce7a 100644
--- a/libphobos/src/std/array.d
+++ b/libphobos/src/std/array.d
@@ -1953,7 +1953,7 @@ private enum bool hasCheapIteration(R) = isArray!R;
See_Also:
For a lazy version, see $(REF joiner, std,algorithm,iteration)
+/
-ElementEncodingType!(ElementType!RoR)[] join(RoR, R)(RoR ror, scope R sep)
+ElementEncodingType!(ElementType!RoR)[] join(RoR, R)(RoR ror, R sep)
if (isInputRange!RoR &&
isInputRange!(Unqual!(ElementType!RoR)) &&
isInputRange!R &&
@@ -3265,7 +3265,7 @@ if (isDynamicArray!A)
{
size_t capacity;
Unqual!T[] arr;
- bool canExtend = false;
+ bool tryExtendBlock = false;
}
private Data* _data;
@@ -3276,7 +3276,7 @@ if (isDynamicArray!A)
* it will be used by the appender. After initializing an appender on an array,
* appending to the original array will reallocate.
*/
- this(A arr) @trusted pure nothrow
+ this(A arr) @trusted
{
// initialize to a given array.
_data = new Data;
@@ -3325,7 +3325,7 @@ if (isDynamicArray!A)
* managed array can accommodate before triggering a reallocation). If any
* appending will reallocate, `0` will be returned.
*/
- @property size_t capacity() const @safe pure nothrow
+ @property size_t capacity() const
{
return _data ? _data.capacity : 0;
}
@@ -3334,7 +3334,7 @@ if (isDynamicArray!A)
* Use opSlice() from now on.
* Returns: The managed array.
*/
- @property inout(ElementEncodingType!A)[] data() inout @trusted pure nothrow
+ @property inout(T)[] data() inout @trusted
{
return this[];
}
@@ -3342,7 +3342,7 @@ if (isDynamicArray!A)
/**
* Returns: The managed array.
*/
- @property inout(ElementEncodingType!A)[] opSlice() inout @trusted pure nothrow
+ @property inout(T)[] opSlice() inout @trusted
{
/* @trusted operation:
* casting Unqual!T[] to inout(T)[]
@@ -3385,7 +3385,7 @@ if (isDynamicArray!A)
// have better access to the capacity field.
auto newlen = appenderNewCapacity!(T.sizeof)(_data.capacity, reqlen);
// first, try extending the current block
- if (_data.canExtend)
+ if (_data.tryExtendBlock)
{
immutable u = (() @trusted => GC.extend(_data.arr.ptr, nelems * T.sizeof, (newlen - len) * T.sizeof))();
if (u)
@@ -3410,7 +3410,7 @@ if (isDynamicArray!A)
if (len)
() @trusted { memcpy(bi.base, _data.arr.ptr, len * T.sizeof); }();
_data.arr = (() @trusted => (cast(Unqual!T*) bi.base)[0 .. len])();
- _data.canExtend = true;
+ _data.tryExtendBlock = true;
// leave the old data, for safety reasons
}
}
@@ -3653,7 +3653,7 @@ if (isDynamicArray!A)
}
///
-@safe unittest
+@safe pure nothrow unittest
{
auto app = appender!string();
string b = "abcdefg";
@@ -3691,7 +3691,7 @@ if (isDynamicArray!A)
}
// https://issues.dlang.org/show_bug.cgi?id=17251
-@safe unittest
+@safe pure nothrow unittest
{
static struct R
{
@@ -3707,7 +3707,7 @@ if (isDynamicArray!A)
}
// https://issues.dlang.org/show_bug.cgi?id=13300
-@safe unittest
+@safe pure nothrow unittest
{
static test(bool isPurePostblit)()
{
@@ -3743,7 +3743,7 @@ if (isDynamicArray!A)
}
// https://issues.dlang.org/show_bug.cgi?id=19572
-@system unittest
+@safe pure nothrow unittest
{
static struct Struct
{
@@ -3763,7 +3763,7 @@ if (isDynamicArray!A)
assert(result.value != 23);
}
-@safe unittest
+@safe pure unittest
{
import std.conv : to;
import std.utf : byCodeUnit;
@@ -3774,7 +3774,7 @@ if (isDynamicArray!A)
}
// https://issues.dlang.org/show_bug.cgi?id=21256
-@safe unittest
+@safe pure unittest
{
Appender!string app1;
app1.toString();
@@ -3788,7 +3788,7 @@ if (isDynamicArray!A)
//arg curLen: The current length
//arg reqLen: The length as requested by the user
//ret sugLen: A suggested growth.
-private size_t appenderNewCapacity(size_t TSizeOf)(size_t curLen, size_t reqLen) @safe pure nothrow
+private size_t appenderNewCapacity(size_t TSizeOf)(size_t curLen, size_t reqLen)
{
import core.bitop : bsr;
import std.algorithm.comparison : max;
@@ -3816,6 +3816,8 @@ private size_t appenderNewCapacity(size_t TSizeOf)(size_t curLen, size_t reqLen)
struct RefAppender(A)
if (isDynamicArray!A)
{
+ private alias T = ElementEncodingType!A;
+
private
{
Appender!A impl;
@@ -3878,7 +3880,7 @@ if (isDynamicArray!A)
/* Use opSlice() instead.
* Returns: the managed array.
*/
- @property inout(ElementEncodingType!A)[] data() inout
+ @property inout(T)[] data() inout
{
return impl[];
}
@@ -3893,7 +3895,7 @@ if (isDynamicArray!A)
}
///
-@system pure nothrow
+@safe pure nothrow
unittest
{
int[] a = [1, 2];
@@ -3929,63 +3931,48 @@ Appender!(E[]) appender(A : E[], E)(auto ref A array)
@safe pure nothrow unittest
{
- import std.exception;
- {
- auto app = appender!(char[])();
- string b = "abcdefg";
- foreach (char c; b) app.put(c);
- assert(app[] == "abcdefg");
- }
- {
- auto app = appender!(char[])();
- string b = "abcdefg";
- foreach (char c; b) app ~= c;
- assert(app[] == "abcdefg");
- }
- {
- int[] a = [ 1, 2 ];
- auto app2 = appender(a);
- assert(app2[] == [ 1, 2 ]);
- app2.put(3);
- app2.put([ 4, 5, 6 ][]);
- assert(app2[] == [ 1, 2, 3, 4, 5, 6 ]);
- app2.put([ 7 ]);
- assert(app2[] == [ 1, 2, 3, 4, 5, 6, 7 ]);
- }
+ auto app = appender!(char[])();
+ string b = "abcdefg";
+ foreach (char c; b) app.put(c);
+ assert(app[] == "abcdefg");
+}
+@safe pure nothrow unittest
+{
+ auto app = appender!(char[])();
+ string b = "abcdefg";
+ foreach (char c; b) app ~= c;
+ assert(app[] == "abcdefg");
+}
+
+@safe pure nothrow unittest
+{
int[] a = [ 1, 2 ];
auto app2 = appender(a);
assert(app2[] == [ 1, 2 ]);
- app2 ~= 3;
- app2 ~= [ 4, 5, 6 ][];
+ app2.put(3);
+ app2.put([ 4, 5, 6 ][]);
assert(app2[] == [ 1, 2, 3, 4, 5, 6 ]);
- app2 ~= [ 7 ];
+ app2.put([ 7 ]);
assert(app2[] == [ 1, 2, 3, 4, 5, 6, 7 ]);
+}
- app2.reserve(5);
- assert(app2.capacity >= 5);
-
- try // shrinkTo may throw
- {
- app2.shrinkTo(3);
- }
- catch (Exception) assert(0);
- assert(app2[] == [ 1, 2, 3 ]);
- assertThrown(app2.shrinkTo(5));
-
- const app3 = app2;
- assert(app3.capacity >= 3);
- assert(app3[] == [1, 2, 3]);
-
+@safe pure nothrow unittest
+{
auto app4 = appender([]);
try // shrinkTo may throw
{
app4.shrinkTo(0);
}
catch (Exception) assert(0);
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=5663
+// https://issues.dlang.org/show_bug.cgi?id=9725
+@safe pure nothrow unittest
+{
+ import std.exception : assertNotThrown;
- // https://issues.dlang.org/show_bug.cgi?id=5663
- // https://issues.dlang.org/show_bug.cgi?id=9725
static foreach (S; AliasSeq!(char[], const(char)[], string))
{
{
@@ -4016,6 +4003,12 @@ Appender!(E[]) appender(A : E[], E)(auto ref A array)
assert(app5663m[] == "\xE3");
}
}
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=10122
+@safe pure nothrow unittest
+{
+ import std.exception : assertCTFEable;
static struct S10122
{
@@ -4032,6 +4025,35 @@ Appender!(E[]) appender(A : E[], E)(auto ref A array)
});
}
+@safe pure nothrow unittest
+{
+ import std.exception : assertThrown;
+
+ int[] a = [ 1, 2 ];
+ auto app2 = appender(a);
+ assert(app2[] == [ 1, 2 ]);
+ app2 ~= 3;
+ app2 ~= [ 4, 5, 6 ][];
+ assert(app2[] == [ 1, 2, 3, 4, 5, 6 ]);
+ app2 ~= [ 7 ];
+ assert(app2[] == [ 1, 2, 3, 4, 5, 6, 7 ]);
+
+ app2.reserve(5);
+ assert(app2.capacity >= 5);
+
+ try // shrinkTo may throw
+ {
+ app2.shrinkTo(3);
+ }
+ catch (Exception) assert(0);
+ assert(app2[] == [ 1, 2, 3 ]);
+ assertThrown(app2.shrinkTo(5));
+
+ const app3 = app2;
+ assert(app3.capacity >= 3);
+ assert(app3[] == [1, 2, 3]);
+}
+
///
@safe pure nothrow
unittest
@@ -4053,63 +4075,63 @@ unittest
@safe pure nothrow unittest
{
+ auto w = appender!string();
+ w.reserve(4);
+ cast(void) w.capacity;
+ cast(void) w[];
+ try
{
- auto w = appender!string();
- w.reserve(4);
- cast(void) w.capacity;
- cast(void) w[];
- try
- {
- wchar wc = 'a';
- dchar dc = 'a';
- w.put(wc); // decoding may throw
- w.put(dc); // decoding may throw
- }
- catch (Exception) assert(0);
+ wchar wc = 'a';
+ dchar dc = 'a';
+ w.put(wc); // decoding may throw
+ w.put(dc); // decoding may throw
}
+ catch (Exception) assert(0);
+}
+
+@safe pure nothrow unittest
+{
+ auto w = appender!(int[])();
+ w.reserve(4);
+ cast(void) w.capacity;
+ cast(void) w[];
+ w.put(10);
+ w.put([10]);
+ w.clear();
+ try
{
- auto w = appender!(int[])();
- w.reserve(4);
- cast(void) w.capacity;
- cast(void) w[];
- w.put(10);
- w.put([10]);
- w.clear();
- try
- {
- w.shrinkTo(0);
- }
- catch (Exception) assert(0);
+ w.shrinkTo(0);
+ }
+ catch (Exception) assert(0);
- struct N
- {
- int payload;
- alias payload this;
- }
- w.put(N(1));
- w.put([N(2)]);
+ struct N
+ {
+ int payload;
+ alias payload this;
+ }
+ w.put(N(1));
+ w.put([N(2)]);
- struct S(T)
- {
- @property bool empty() { return true; }
- @property T front() { return T.init; }
- void popFront() {}
- }
- S!int r;
- w.put(r);
+ struct S(T)
+ {
+ @property bool empty() { return true; }
+ @property T front() { return T.init; }
+ void popFront() {}
}
+ S!int r;
+ w.put(r);
}
// https://issues.dlang.org/show_bug.cgi?id=10690
-@safe unittest
+@safe pure nothrow unittest
{
- import std.algorithm;
- import std.typecons;
+ import std.algorithm.iteration : filter;
+ import std.typecons : tuple;
[tuple(1)].filter!(t => true).array; // No error
[tuple("A")].filter!(t => true).array; // error
}
-@safe unittest
+@safe pure nothrow unittest
{
import std.range;
//Coverage for put(Range)
@@ -4129,7 +4151,7 @@ unittest
au1.put(sc1.repeat().take(10));
}
-@system unittest
+@system pure unittest
{
import std.range;
struct S2
@@ -4141,7 +4163,7 @@ unittest
au2.put(sc2.repeat().take(10));
}
-@system unittest
+@system pure nothrow unittest
{
struct S
{
@@ -4175,7 +4197,7 @@ unittest
}
// https://issues.dlang.org/show_bug.cgi?id=9528
-@safe unittest
+@safe pure nothrow unittest
{
const(E)[] fastCopy(E)(E[] src) {
auto app = appender!(const(E)[])();
@@ -4193,7 +4215,7 @@ unittest
}
// https://issues.dlang.org/show_bug.cgi?id=10753
-@safe unittest
+@safe pure unittest
{
import std.algorithm.iteration : map;
struct Foo {
@@ -4206,7 +4228,7 @@ unittest
[1, 2].map!Bar.array;
}
-@safe unittest
+@safe pure nothrow unittest
{
import std.algorithm.comparison : equal;
@@ -4255,7 +4277,7 @@ unittest
assert(app8[] == null);
}
-@safe unittest //Test large allocations (for GC.extend)
+@safe pure nothrow unittest //Test large allocations (for GC.extend)
{
import std.algorithm.comparison : equal;
import std.range;
@@ -4266,7 +4288,7 @@ unittest
assert(equal(app[], 'a'.repeat(100_000)));
}
-@safe unittest
+@safe pure nothrow unittest
{
auto reference = new ubyte[](2048 + 1); //a number big enough to have a full page (EG: the GC extends)
auto arr = reference.dup;
@@ -4276,7 +4298,7 @@ unittest
assert(reference[] == arr[]);
}
-@safe unittest // clear method is supported only for mutable element types
+@safe pure nothrow unittest // clear method is supported only for mutable element types
{
Appender!string app;
app.put("foo");
@@ -4284,7 +4306,7 @@ unittest
assert(app[] == "foo");
}
-@safe unittest
+@safe pure nothrow unittest
{
static struct D//dynamic
{
@@ -4343,7 +4365,7 @@ RefAppender!(E[]) appender(P : E[]*, E)(P arrayPtr)
}
///
-@system pure nothrow
+@safe pure nothrow
unittest
{
int[] a = [1, 2];
@@ -4359,35 +4381,41 @@ unittest
assert(app2.capacity >= 5);
}
-@system unittest
+@safe pure nothrow unittest
{
- import std.exception;
- {
- auto arr = new char[0];
- auto app = appender(&arr);
- string b = "abcdefg";
- foreach (char c; b) app.put(c);
- assert(app[] == "abcdefg");
- assert(arr == "abcdefg");
- }
- {
- auto arr = new char[0];
- auto app = appender(&arr);
- string b = "abcdefg";
- foreach (char c; b) app ~= c;
- assert(app[] == "abcdefg");
- assert(arr == "abcdefg");
- }
- {
- int[] a = [ 1, 2 ];
- auto app2 = appender(&a);
- assert(app2[] == [ 1, 2 ]);
- assert(a == [ 1, 2 ]);
- app2.put(3);
- app2.put([ 4, 5, 6 ][]);
- assert(app2[] == [ 1, 2, 3, 4, 5, 6 ]);
- assert(a == [ 1, 2, 3, 4, 5, 6 ]);
- }
+ auto arr = new char[0];
+ auto app = appender(&arr);
+ string b = "abcdefg";
+ foreach (char c; b) app.put(c);
+ assert(app[] == "abcdefg");
+ assert(arr == "abcdefg");
+}
+
+@safe pure nothrow unittest
+{
+ auto arr = new char[0];
+ auto app = appender(&arr);
+ string b = "abcdefg";
+ foreach (char c; b) app ~= c;
+ assert(app[] == "abcdefg");
+ assert(arr == "abcdefg");
+}
+
+@safe pure nothrow unittest
+{
+ int[] a = [ 1, 2 ];
+ auto app2 = appender(&a);
+ assert(app2[] == [ 1, 2 ]);
+ assert(a == [ 1, 2 ]);
+ app2.put(3);
+ app2.put([ 4, 5, 6 ][]);
+ assert(app2[] == [ 1, 2, 3, 4, 5, 6 ]);
+ assert(a == [ 1, 2, 3, 4, 5, 6 ]);
+}
+
+@safe pure nothrow unittest
+{
+ import std.exception : assertThrown;
int[] a = [ 1, 2 ];
auto app2 = appender(&a);
@@ -4415,13 +4443,13 @@ unittest
}
// https://issues.dlang.org/show_bug.cgi?id=14605
-@safe unittest
+@safe pure nothrow unittest
{
static assert(isOutputRange!(Appender!(int[]), int));
static assert(isOutputRange!(RefAppender!(int[]), int));
}
-@safe unittest
+@safe pure nothrow unittest
{
Appender!(int[]) app;
short[] range = [1, 2, 3];
@@ -4429,7 +4457,7 @@ unittest
assert(app[] == [1, 2, 3]);
}
-@safe unittest
+@safe pure nothrow unittest
{
string s = "hello".idup;
char[] a = "hello".dup;
@@ -4471,7 +4499,7 @@ pragma(inline, true) T[n] staticArray(T, size_t n)(auto ref T[n] a)
}
/// static array from array literal
-nothrow pure @safe unittest
+nothrow pure @safe @nogc unittest
{
auto a = [0, 1].staticArray;
static assert(is(typeof(a) == int[2]));
@@ -4485,14 +4513,14 @@ if (!is(T == U) && is(T : U))
}
/// static array from array with implicit casting of elements
-nothrow pure @safe unittest
+nothrow pure @safe @nogc unittest
{
auto b = [0, 1].staticArray!long;
static assert(is(typeof(b) == long[2]));
assert(b == [0, 1]);
}
-nothrow pure @safe unittest
+nothrow pure @safe @nogc unittest
{
int val = 3;
static immutable gold = [1, 2, 3];
@@ -4589,7 +4617,7 @@ if (isInputRange!T && is(ElementType!T : U))
}
/// static array from range + size
-nothrow pure @safe unittest
+nothrow pure @safe @nogc unittest
{
import std.range : iota;
@@ -4605,8 +4633,7 @@ nothrow pure @safe unittest
// Tests that code compiles when there is an elaborate destructor and exceptions
// are thrown. Unfortunately can't test that memory is initialized
// before having a destructor called on it.
-// @system required because of https://issues.dlang.org/show_bug.cgi?id=18872.
-@system nothrow unittest
+@safe nothrow unittest
{
// exists only to allow doing something in the destructor. Not tested
// at the end because value appears to depend on implementation of the.
@@ -4644,7 +4671,7 @@ nothrow pure @safe unittest
}
-nothrow pure @safe unittest
+nothrow pure @safe @nogc unittest
{
auto a = [1, 2].staticArray;
assert(is(typeof(a) == int[2]) && a == [1, 2]);
@@ -4656,7 +4683,7 @@ nothrow pure @safe unittest
2.iota.staticArray!(long[2]).checkStaticArray!long([0, 1]);
}
-nothrow pure @system unittest
+nothrow pure @safe @nogc unittest
{
import std.range : iota;
size_t copiedAmount;
@@ -4681,7 +4708,7 @@ if (isInputRange!(typeof(a)))
}
/// static array from CT range
-nothrow pure @safe unittest
+nothrow pure @safe @nogc unittest
{
import std.range : iota;
@@ -4694,7 +4721,7 @@ nothrow pure @safe unittest
assert(b == [0, 1]);
}
-nothrow pure @safe unittest
+nothrow pure @safe @nogc unittest
{
import std.range : iota;
diff --git a/libphobos/src/std/container/array.d b/libphobos/src/std/container/array.d
index 780b985e587..89ca4b24534 100644
--- a/libphobos/src/std/container/array.d
+++ b/libphobos/src/std/container/array.d
@@ -544,6 +544,17 @@ if (!is(immutable T == immutable bool))
return _data.refCountedStore.isInitialized ? _data._capacity : 0;
}
+ /**
+ * Returns: the internal representation of the array.
+ *
+ * Complexity: $(BIGOH 1).
+ */
+
+ T[] data() @system
+ {
+ return _data._payload;
+ }
+
/**
* Ensures sufficient capacity to accommodate `e` _elements.
* If `e < capacity`, this method does nothing.
@@ -1559,7 +1570,7 @@ if (!is(immutable T == immutable bool))
ai.insertBack(arr);
}
-/**
+/*
* typeof may give wrong result in case of classes defining `opCall` operator
* https://issues.dlang.org/show_bug.cgi?id=20589
*
@@ -2601,3 +2612,12 @@ if (is(immutable T == immutable bool))
GC.collect();
arr[1].func();
}
+
+@system unittest
+{
+ Array!int arr = [1, 2, 4, 5];
+ int[] data = arr.data();
+
+ data[0] = 0;
+ assert(arr[0] == 0);
+}
diff --git a/libphobos/src/std/datetime/date.d b/libphobos/src/std/datetime/date.d
index fa78abe197d..ebdaba42a9d 100644
--- a/libphobos/src/std/datetime/date.d
+++ b/libphobos/src/std/datetime/date.d
@@ -3216,7 +3216,7 @@ public:
assertThrown!DateTimeException(DateTime.fromISOString("2010-12-22T172201"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-Dec-22 17:22:01"));
- assert(DateTime.fromISOString("20101222T172201") == DateTime(Date(2010, 12, 22), TimeOfDay(17, 22, 01)));
+ assert(DateTime.fromISOString("20101222T172201") == DateTime(Date(2010, 12, 22), TimeOfDay(17, 22, 1)));
assert(DateTime.fromISOString("19990706T123033") == DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assert(DateTime.fromISOString("-19990706T123033") == DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
assert(DateTime.fromISOString("+019990706T123033") == DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
@@ -3316,7 +3316,7 @@ public:
assertThrown!DateTimeException(DateTime.fromISOExtString("20101222T172201"));
assertThrown!DateTimeException(DateTime.fromISOExtString("2010-Dec-22 17:22:01"));
- assert(DateTime.fromISOExtString("2010-12-22T17:22:01") == DateTime(Date(2010, 12, 22), TimeOfDay(17, 22, 01)));
+ assert(DateTime.fromISOExtString("2010-12-22T17:22:01") == DateTime(Date(2010, 12, 22), TimeOfDay(17, 22, 1)));
assert(DateTime.fromISOExtString("1999-07-06T12:30:33") == DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assert(DateTime.fromISOExtString("-1999-07-06T12:30:33") == DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
assert(DateTime.fromISOExtString("+01999-07-06T12:30:33") == DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
@@ -3414,7 +3414,7 @@ public:
assertThrown!DateTimeException(DateTime.fromSimpleString("2010-12-22T172201"));
assert(DateTime.fromSimpleString("2010-Dec-22 17:22:01") ==
- DateTime(Date(2010, 12, 22), TimeOfDay(17, 22, 01)));
+ DateTime(Date(2010, 12, 22), TimeOfDay(17, 22, 1)));
assert(DateTime.fromSimpleString("1999-Jul-06 12:30:33") ==
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assert(DateTime.fromSimpleString("-1999-Jul-06 12:30:33") ==
diff --git a/libphobos/src/std/datetime/systime.d b/libphobos/src/std/datetime/systime.d
index 1e2d120fe03..9c051b452f7 100644
--- a/libphobos/src/std/datetime/systime.d
+++ b/libphobos/src/std/datetime/systime.d
@@ -8901,7 +8901,7 @@ public:
throw new AssertError("unittest failure", __FILE__, line);
}
- test("20101222T172201", SysTime(DateTime(2010, 12, 22, 17, 22, 01)));
+ test("20101222T172201", SysTime(DateTime(2010, 12, 22, 17, 22, 1)));
test("19990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
test("-19990706T123033", SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
test("+019990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
@@ -8909,16 +8909,16 @@ public:
test(" 19990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
test(" 19990706T123033 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
- test("19070707T121212.0", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
- test("19070707T121212.0000000", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
- test("19070707T121212.0000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), hnsecs(1)));
- test("20100704T000000.00000000", SysTime(Date(2010, 07, 04)));
- test("20100704T000000.00000009", SysTime(Date(2010, 07, 04)));
- test("20100704T000000.00000019", SysTime(DateTime(2010, 07, 04), hnsecs(1)));
- test("19070707T121212.000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
- test("19070707T121212.0000010", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
- test("19070707T121212.001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
- test("19070707T121212.0010000", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
+ test("19070707T121212.0", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
+ test("19070707T121212.0000000", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
+ test("19070707T121212.0000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), hnsecs(1)));
+ test("20100704T000000.00000000", SysTime(Date(2010, 7, 4)));
+ test("20100704T000000.00000009", SysTime(Date(2010, 7, 4)));
+ test("20100704T000000.00000019", SysTime(DateTime(2010, 7, 4), hnsecs(1)));
+ test("19070707T121212.000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
+ test("19070707T121212.0000010", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
+ test("19070707T121212.001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
+ test("19070707T121212.0010000", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
auto west60 = new immutable SimpleTimeZone(hours(-1));
auto west90 = new immutable SimpleTimeZone(minutes(-90));
@@ -8927,32 +8927,32 @@ public:
auto east90 = new immutable SimpleTimeZone(minutes(90));
auto east480 = new immutable SimpleTimeZone(hours(8));
- test("20101222T172201Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC()));
- test("20101222T172201-0100", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
- test("20101222T172201-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
- test("20101222T172201-0130", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west90));
- test("20101222T172201-0800", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west480));
- test("20101222T172201+0100", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
- test("20101222T172201+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
- test("20101222T172201+0130", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
- test("20101222T172201+0800", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east480));
+ test("20101222T172201Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), UTC()));
+ test("20101222T172201-0100", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
+ test("20101222T172201-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
+ test("20101222T172201-0130", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west90));
+ test("20101222T172201-0800", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west480));
+ test("20101222T172201+0100", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
+ test("20101222T172201+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
+ test("20101222T172201+0130", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
+ test("20101222T172201+0800", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east480));
test("20101103T065106.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC()));
- test("20101222T172201.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_341_200), UTC()));
- test("20101222T172201.23112-0100", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60));
- test("20101222T172201.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), west60));
- test("20101222T172201.1-0130", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_000_000), west90));
- test("20101222T172201.55-0800", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(5_500_000), west480));
- test("20101222T172201.1234567+0100", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_234_567), east60));
- test("20101222T172201.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
- test("20101222T172201.0000000+0130", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
- test("20101222T172201.45+0800", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), east480));
+ test("20101222T172201.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_341_200), UTC()));
+ test("20101222T172201.23112-0100", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_311_200), west60));
+ test("20101222T172201.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), west60));
+ test("20101222T172201.1-0130", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_000_000), west90));
+ test("20101222T172201.55-0800", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(5_500_000), west480));
+ test("20101222T172201.1234567+0100", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_234_567), east60));
+ test("20101222T172201.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
+ test("20101222T172201.0000000+0130", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
+ test("20101222T172201.45+0800", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), east480));
// for dstring coverage
assert(SysTime.fromISOString("20101222T172201.23112-0100"d) == SysTime(
- DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60));
+ DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_311_200), west60));
assert(SysTime.fromISOString("19070707T121212.0010000"d) == SysTime(
- DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
+ DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
// @@@DEPRECATED_2019-07@@@
// This isn't deprecated per se, but that text will make it so that it
@@ -8964,19 +8964,19 @@ public:
// These tests will then start failing will need to be updated accordingly.
// Also, the notes about this issue in toISOString and fromISOString's
// documentation will need to be removed.
- test("20101222T172201-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
- test("20101222T172201-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west90));
- test("20101222T172201-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west480));
- test("20101222T172201+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
- test("20101222T172201+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
- test("20101222T172201+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east480));
-
- test("20101222T172201.23112-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60));
- test("20101222T172201.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_000_000), west90));
- test("20101222T172201.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(5_500_000), west480));
- test("20101222T172201.1234567+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_234_567), east60));
- test("20101222T172201.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
- test("20101222T172201.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), east480));
+ test("20101222T172201-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
+ test("20101222T172201-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west90));
+ test("20101222T172201-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west480));
+ test("20101222T172201+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
+ test("20101222T172201+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
+ test("20101222T172201+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east480));
+
+ test("20101222T172201.23112-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_311_200), west60));
+ test("20101222T172201.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_000_000), west90));
+ test("20101222T172201.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(5_500_000), west480));
+ test("20101222T172201.1234567+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_234_567), east60));
+ test("20101222T172201.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
+ test("20101222T172201.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), east480));
static void testScope(scope ref string str) @safe
{
@@ -9177,7 +9177,7 @@ public:
throw new AssertError("unittest failure", __FILE__, line);
}
- test("2010-12-22T17:22:01", SysTime(DateTime(2010, 12, 22, 17, 22, 01)));
+ test("2010-12-22T17:22:01", SysTime(DateTime(2010, 12, 22, 17, 22, 1)));
test("1999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
test("-1999-07-06T12:30:33", SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
test("+01999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
@@ -9185,16 +9185,16 @@ public:
test(" 1999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
test(" 1999-07-06T12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
- test("1907-07-07T12:12:12.0", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
- test("1907-07-07T12:12:12.0000000", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
- test("1907-07-07T12:12:12.0000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), hnsecs(1)));
- test("2010-07-04T00:00:00.00000000", SysTime(Date(2010, 07, 04)));
- test("2010-07-04T00:00:00.00000009", SysTime(Date(2010, 07, 04)));
- test("2010-07-04T00:00:00.00000019", SysTime(DateTime(2010, 07, 04), hnsecs(1)));
- test("1907-07-07T12:12:12.000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
- test("1907-07-07T12:12:12.0000010", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
- test("1907-07-07T12:12:12.001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
- test("1907-07-07T12:12:12.0010000", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
+ test("1907-07-07T12:12:12.0", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
+ test("1907-07-07T12:12:12.0000000", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
+ test("1907-07-07T12:12:12.0000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), hnsecs(1)));
+ test("2010-07-04T00:00:00.00000000", SysTime(Date(2010, 7, 4)));
+ test("2010-07-04T00:00:00.00000009", SysTime(Date(2010, 7, 4)));
+ test("2010-07-04T00:00:00.00000019", SysTime(DateTime(2010, 7, 4), hnsecs(1)));
+ test("1907-07-07T12:12:12.000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
+ test("1907-07-07T12:12:12.0000010", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
+ test("1907-07-07T12:12:12.001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
+ test("1907-07-07T12:12:12.0010000", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
auto west60 = new immutable SimpleTimeZone(hours(-1));
auto west90 = new immutable SimpleTimeZone(minutes(-90));
@@ -9203,28 +9203,28 @@ public:
auto east90 = new immutable SimpleTimeZone(minutes(90));
auto east480 = new immutable SimpleTimeZone(hours(8));
- test("2010-12-22T17:22:01Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC()));
- test("2010-12-22T17:22:01-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
- test("2010-12-22T17:22:01-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
- test("2010-12-22T17:22:01-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west90));
- test("2010-12-22T17:22:01-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west480));
- test("2010-12-22T17:22:01+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
- test("2010-12-22T17:22:01+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
- test("2010-12-22T17:22:01+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
- test("2010-12-22T17:22:01+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east480));
+ test("2010-12-22T17:22:01Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), UTC()));
+ test("2010-12-22T17:22:01-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
+ test("2010-12-22T17:22:01-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
+ test("2010-12-22T17:22:01-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west90));
+ test("2010-12-22T17:22:01-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west480));
+ test("2010-12-22T17:22:01+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
+ test("2010-12-22T17:22:01+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
+ test("2010-12-22T17:22:01+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
+ test("2010-12-22T17:22:01+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east480));
test("2010-11-03T06:51:06.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC()));
- test("2010-12-22T17:22:01.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_341_200), UTC()));
+ test("2010-12-22T17:22:01.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_341_200), UTC()));
test("2010-12-22T17:22:01.23112-01:00",
- SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60));
- test("2010-12-22T17:22:01.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), west60));
- test("2010-12-22T17:22:01.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_000_000), west90));
- test("2010-12-22T17:22:01.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(5_500_000), west480));
+ SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_311_200), west60));
+ test("2010-12-22T17:22:01.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), west60));
+ test("2010-12-22T17:22:01.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_000_000), west90));
+ test("2010-12-22T17:22:01.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(5_500_000), west480));
test("2010-12-22T17:22:01.1234567+01:00",
- SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_234_567), east60));
- test("2010-12-22T17:22:01.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
- test("2010-12-22T17:22:01.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
- test("2010-12-22T17:22:01.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), east480));
+ SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_234_567), east60));
+ test("2010-12-22T17:22:01.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
+ test("2010-12-22T17:22:01.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
+ test("2010-12-22T17:22:01.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), east480));
static void testScope(scope ref string str) @safe
{
@@ -9429,7 +9429,7 @@ public:
throw new AssertError("unittest failure", __FILE__, line);
}
- test("2010-Dec-22 17:22:01", SysTime(DateTime(2010, 12, 22, 17, 22, 01)));
+ test("2010-Dec-22 17:22:01", SysTime(DateTime(2010, 12, 22, 17, 22, 1)));
test("1999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
test("-1999-Jul-06 12:30:33", SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
test("+01999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
@@ -9437,16 +9437,16 @@ public:
test(" 1999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
test(" 1999-Jul-06 12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
- test("1907-Jul-07 12:12:12.0", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
- test("1907-Jul-07 12:12:12.0000000", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
- test("2010-Jul-04 00:00:00.00000000", SysTime(Date(2010, 07, 04)));
- test("2010-Jul-04 00:00:00.00000009", SysTime(Date(2010, 07, 04)));
- test("2010-Jul-04 00:00:00.00000019", SysTime(DateTime(2010, 07, 04), hnsecs(1)));
- test("1907-Jul-07 12:12:12.0000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), hnsecs(1)));
- test("1907-Jul-07 12:12:12.000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
- test("1907-Jul-07 12:12:12.0000010", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
- test("1907-Jul-07 12:12:12.001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
- test("1907-Jul-07 12:12:12.0010000", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
+ test("1907-Jul-07 12:12:12.0", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
+ test("1907-Jul-07 12:12:12.0000000", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
+ test("2010-Jul-04 00:00:00.00000000", SysTime(Date(2010, 7, 4)));
+ test("2010-Jul-04 00:00:00.00000009", SysTime(Date(2010, 7, 4)));
+ test("2010-Jul-04 00:00:00.00000019", SysTime(DateTime(2010, 7, 4), hnsecs(1)));
+ test("1907-Jul-07 12:12:12.0000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), hnsecs(1)));
+ test("1907-Jul-07 12:12:12.000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
+ test("1907-Jul-07 12:12:12.0000010", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
+ test("1907-Jul-07 12:12:12.001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
+ test("1907-Jul-07 12:12:12.0010000", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
auto west60 = new immutable SimpleTimeZone(hours(-1));
auto west90 = new immutable SimpleTimeZone(minutes(-90));
@@ -9455,28 +9455,28 @@ public:
auto east90 = new immutable SimpleTimeZone(minutes(90));
auto east480 = new immutable SimpleTimeZone(hours(8));
- test("2010-Dec-22 17:22:01Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC()));
- test("2010-Dec-22 17:22:01-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
- test("2010-Dec-22 17:22:01-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
- test("2010-Dec-22 17:22:01-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west90));
- test("2010-Dec-22 17:22:01-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west480));
- test("2010-Dec-22 17:22:01+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
- test("2010-Dec-22 17:22:01+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
- test("2010-Dec-22 17:22:01+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
- test("2010-Dec-22 17:22:01+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east480));
+ test("2010-Dec-22 17:22:01Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), UTC()));
+ test("2010-Dec-22 17:22:01-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
+ test("2010-Dec-22 17:22:01-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
+ test("2010-Dec-22 17:22:01-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west90));
+ test("2010-Dec-22 17:22:01-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west480));
+ test("2010-Dec-22 17:22:01+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
+ test("2010-Dec-22 17:22:01+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
+ test("2010-Dec-22 17:22:01+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
+ test("2010-Dec-22 17:22:01+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east480));
test("2010-Nov-03 06:51:06.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC()));
- test("2010-Dec-22 17:22:01.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_341_200), UTC()));
+ test("2010-Dec-22 17:22:01.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_341_200), UTC()));
test("2010-Dec-22 17:22:01.23112-01:00",
- SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60));
- test("2010-Dec-22 17:22:01.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), west60));
- test("2010-Dec-22 17:22:01.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_000_000), west90));
- test("2010-Dec-22 17:22:01.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(5_500_000), west480));
+ SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_311_200), west60));
+ test("2010-Dec-22 17:22:01.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), west60));
+ test("2010-Dec-22 17:22:01.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_000_000), west90));
+ test("2010-Dec-22 17:22:01.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(5_500_000), west480));
test("2010-Dec-22 17:22:01.1234567+01:00",
- SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_234_567), east60));
- test("2010-Dec-22 17:22:01.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
- test("2010-Dec-22 17:22:01.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
- test("2010-Dec-22 17:22:01.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), east480));
+ SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_234_567), east60));
+ test("2010-Dec-22 17:22:01.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
+ test("2010-Dec-22 17:22:01.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
+ test("2010-Dec-22 17:22:01.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), east480));
static void testScope(scope ref string str) @safe
{
@@ -9688,7 +9688,7 @@ long unixTimeToStdTime(long unixTime) @safe pure nothrow @nogc
assert(unixTimeToStdTime(int.max) == 642_830_804_470_000_000L);
assert(SysTime(unixTimeToStdTime(int.max)) ==
- SysTime(DateTime(2038, 1, 19, 3, 14, 07), UTC()));
+ SysTime(DateTime(2038, 1, 19, 3, 14, 7), UTC()));
assert(unixTimeToStdTime(-127_127) == 621_354_696_730_000_000L);
assert(SysTime(unixTimeToStdTime(-127_127)) ==
@@ -10934,7 +10934,7 @@ version (StdUnittest) private void testBadParse822(alias cr)(string str, size_t
// test time zones
{
- auto dt = DateTime(1982, 05, 03, 12, 22, 04);
+ auto dt = DateTime(1982, 5, 3, 12, 22, 4);
test("Wed, 03 May 1982 12:22:04 UT", SysTime(dt, UTC()));
test("Wed, 03 May 1982 12:22:04 GMT", SysTime(dt, UTC()));
test("Wed, 03 May 1982 12:22:04 EST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-5))));
@@ -10995,13 +10995,13 @@ version (StdUnittest) private void testBadParse822(alias cr)(string str, size_t
// test that the checks for minimum length work correctly and avoid
// any RangeErrors.
- test("7Dec1200:00A", SysTime(DateTime(2012, 12, 7, 00, 00, 00),
+ test("7Dec1200:00A", SysTime(DateTime(2012, 12, 7, 0, 0, 0),
new immutable SimpleTimeZone(Duration.zero)));
- test("Fri,7Dec1200:00A", SysTime(DateTime(2012, 12, 7, 00, 00, 00),
+ test("Fri,7Dec1200:00A", SysTime(DateTime(2012, 12, 7, 0, 0, 0),
new immutable SimpleTimeZone(Duration.zero)));
- test("7Dec1200:00:00A", SysTime(DateTime(2012, 12, 7, 00, 00, 00),
+ test("7Dec1200:00:00A", SysTime(DateTime(2012, 12, 7, 0, 0, 0),
new immutable SimpleTimeZone(Duration.zero)));
- test("Fri,7Dec1200:00:00A", SysTime(DateTime(2012, 12, 7, 00, 00, 00),
+ test("Fri,7Dec1200:00:00A", SysTime(DateTime(2012, 12, 7, 0, 0, 0),
new immutable SimpleTimeZone(Duration.zero)));
auto tooShortMsg = collectExceptionMsg!DateTimeException(parseRFC822DateTime(""));
diff --git a/libphobos/src/std/datetime/timezone.d b/libphobos/src/std/datetime/timezone.d
index 108360a33ff..5df42e728c3 100644
--- a/libphobos/src/std/datetime/timezone.d
+++ b/libphobos/src/std/datetime/timezone.d
@@ -1702,7 +1702,7 @@ package:
Params:
isoExtString = A string which represents a time zone in the ISO format.
+/
- static immutable(SimpleTimeZone) fromISOExtString(S)(S isoExtString) @safe pure
+ static immutable(SimpleTimeZone) fromISOExtString(S)(scope S isoExtString) @safe pure
if (isSomeString!S)
{
import std.algorithm.searching : startsWith;
diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d
index 9f26ebb53d1..6bcb231d717 100644
--- a/libphobos/src/std/file.d
+++ b/libphobos/src/std/file.d
@@ -1846,7 +1846,7 @@ else version (Posix)
stat_t statbuf;
// check that both lvalues and rvalues work
timeLastAccessed(statbuf);
- timeLastAccessed(stat_t.init);
+ cast(void) timeLastAccessed(stat_t.init);
}
}
diff --git a/libphobos/src/std/internal/math/biguintcore.d b/libphobos/src/std/internal/math/biguintcore.d
index 486be66e5a9..59d784265c1 100644
--- a/libphobos/src/std/internal/math/biguintcore.d
+++ b/libphobos/src/std/internal/math/biguintcore.d
@@ -761,7 +761,7 @@ public:
// If wantSub is false, return x + y, leaving sign unchanged
// If wantSub is true, return abs(x - y), negating sign if x < y
- static BigUint addOrSubInt(Tulong)(const BigUint x, Tulong y,
+ static BigUint addOrSubInt(Tulong)(const scope BigUint x, Tulong y,
bool wantSub, ref bool sign) pure nothrow @safe if (is(Tulong == ulong))
{
BigUint r;
@@ -1380,7 +1380,7 @@ pure nothrow @safe
}
// Encode BigInt as BigDigit array (sign and 2's complement)
-BigDigit[] includeSign(const(BigDigit) [] x, size_t minSize, bool sign)
+BigDigit[] includeSign(scope const(BigDigit) [] x, size_t minSize, bool sign)
pure nothrow @safe
{
size_t length = (x.length > minSize) ? x.length : minSize;
diff --git a/libphobos/src/std/math/operations.d b/libphobos/src/std/math/operations.d
index ec8966d4951..dfb1aeea587 100644
--- a/libphobos/src/std/math/operations.d
+++ b/libphobos/src/std/math/operations.d
@@ -1717,7 +1717,7 @@ if (isFloatingPoint!T)
bool negative;
}
-FloatingPointBitpattern!T extractBitpattern(T)(T val)
+FloatingPointBitpattern!T extractBitpattern(T)(T val) @trusted
if (isFloatingPoint!T)
{
import std.math : floatTraits, RealFormat;
@@ -1729,9 +1729,9 @@ if (isFloatingPoint!T)
{
if (__ctfe)
{
- import core.math : fabs;
+ import core.math : fabs, ldexp;
import std.math.rounding : floor;
- import std.math.traits : isInfinity, isNaN;
+ import std.math.traits : isInfinity, isNaN, signbit;
import std.math.exponential : log2;
if (isNaN(val) || isInfinity(val))
@@ -1750,19 +1750,9 @@ if (isFloatingPoint!T)
}
else
{
- if (ret.exponent > 16382 + 64) // bias + bits of ulong
- val /= 2.0L ^^ (ret.exponent - (16382 + 64));
- else
- {
- auto delta = 16382 + 64 - (ret.exponent == 0 ? 1 : ret.exponent); // -1 in case of subnormals
- if (delta > 16383)
- {
- // need two steps to avoid overflow
- val *= 2.0L ^^ 16383;
- delta -= 16383;
- }
- val *= 2.0L ^^ delta;
- }
+ auto delta = 16382 + 64 // bias + bits of ulong
+ - (ret.exponent == 0 ? 1 : ret.exponent); // -1 in case of subnormals
+ val = ldexp(val, delta); // val *= 2^^delta
ulong tmp = cast(ulong) fabs(val);
if (ret.exponent != 32767 && ret.exponent > 0 && tmp <= ulong.max / 2)
@@ -1773,30 +1763,28 @@ if (isFloatingPoint!T)
tmp = cast(ulong) fabs(val);
}
- ret.mantissa = tmp & ((1L << 63) - 1);
+ ret.mantissa = tmp & long.max;
}
- double d = cast(double) val;
- ulong ival = () @trusted { return *cast(ulong*) &d; }();
- if ((ival >> 63) & 1) ret.negative = true;
+ ret.negative = (signbit(val) == 1);
}
else
{
- ulong[2] ival = () @trusted { return *cast(ulong[2]*) &val; }();
- ret.mantissa = ival[0] & ((1L << 63) - 1);
- ret.exponent = ival[1] & 32767;
- if ((ival[1] >> 15) & 1) ret.negative = true;
+ ushort* vs = cast(ushort*) &val;
+ ret.mantissa = (cast(ulong*) vs)[0] & long.max;
+ ret.exponent = vs[4] & short.max;
+ ret.negative = (vs[4] >> 15) & 1;
}
}
else
{
static if (F.realFormat == RealFormat.ieeeSingle)
{
- ulong ival = () @trusted { return *cast(uint*) &val; }();
+ ulong ival = *cast(uint*) &val;
}
else static if (F.realFormat == RealFormat.ieeeDouble)
{
- ulong ival = () @trusted { return *cast(ulong*) &val; }();
+ ulong ival = *cast(ulong*) &val;
}
else
{
@@ -2003,8 +1991,8 @@ if (isFloatingPoint!T)
enum r7 = nextDown(0x1p+16383L);
enum bp7 = extractBitpattern(r7);
- static assert(bp2.mantissa == 0xffff_ffff_ffff_ffffL);
- static assert(bp2.exponent == 16383);
- static assert(bp2.negative == false);
+ static assert(bp7.mantissa == 0xffff_ffff_ffff_ffffL);
+ static assert(bp7.exponent == 16382);
+ static assert(bp7.negative == false);
}
}
diff --git a/libphobos/src/std/path.d b/libphobos/src/std/path.d
index 78679bb400f..e862e654a0e 100644
--- a/libphobos/src/std/path.d
+++ b/libphobos/src/std/path.d
@@ -558,14 +558,14 @@ if (isRandomAccessRange!R && hasSlicing!R && isSomeChar!(ElementType!R) || isNar
the POSIX requirements for the 'dirname' shell utility)
(with suitable adaptations for Windows paths).
*/
-auto dirName(R)(R path)
+auto dirName(R)(return scope R path)
if (isRandomAccessRange!R && hasSlicing!R && hasLength!R && isSomeChar!(ElementType!R) && !isSomeString!R)
{
return _dirName(path);
}
/// ditto
-auto dirName(C)(C[] path)
+auto dirName(C)(return scope C[] path)
if (isSomeChar!C)
{
return _dirName(path);
@@ -662,7 +662,7 @@ if (isSomeChar!C)
//static assert(dirName("dir/file".byChar).array == "dir");
}
-private auto _dirName(R)(R path)
+private auto _dirName(R)(return scope R path)
{
static auto result(bool dot, typeof(path[0 .. 1]) p)
{
@@ -1448,7 +1448,7 @@ private auto _withDefaultExtension(R, C)(R path, C[] ext)
Returns: The assembled path.
*/
immutable(ElementEncodingType!(ElementType!Range))[]
- buildPath(Range)(Range segments)
+ buildPath(Range)(scope Range segments)
if (isInputRange!Range && !isInfinite!Range && isSomeString!(ElementType!Range))
{
if (segments.empty) return null;
@@ -2747,7 +2747,7 @@ else version (Posix)
See_Also:
$(LREF asAbsolutePath) which does not allocate
*/
-string absolutePath(return scope string path, lazy string base = getcwd())
+string absolutePath(string path, lazy string base = getcwd())
@safe pure
{
import std.array : array;
@@ -2893,7 +2893,7 @@ if (isConvertibleToString!R)
`Exception` if the specified _base directory is not absolute.
*/
string relativePath(CaseSensitive cs = CaseSensitive.osDefault)
- (scope return string path, lazy string base = getcwd())
+ (string path, lazy string base = getcwd())
{
if (!isAbsolute(path))
return path;
diff --git a/libphobos/src/std/process.d b/libphobos/src/std/process.d
index f3d294ed460..68cc65cfa46 100644
--- a/libphobos/src/std/process.d
+++ b/libphobos/src/std/process.d
@@ -276,7 +276,7 @@ static:
multi-threaded programs. See e.g.
$(LINK2 https://www.gnu.org/software/libc/manual/html_node/Environment-Access.html#Environment-Access, glibc).
*/
- inout(char)[] opIndexAssign(inout char[] value, scope const(char)[] name) @trusted
+ inout(char)[] opIndexAssign(return inout char[] value, scope const(char)[] name) @trusted
{
version (Posix)
{
@@ -2138,9 +2138,20 @@ struct Config
enum Config inheritFDs = Config(Flags.inheritFDs); /// ditto
enum Config detached = Config(Flags.detached); /// ditto
enum Config stderrPassThrough = Config(Flags.stderrPassThrough); /// ditto
- Config opBinary(string op : "|")(Config other)
+ Config opUnary(string op)()
+ if (is(typeof(mixin(op ~ q{flags}))))
{
- return Config(flags | other.flags);
+ return Config(mixin(op ~ q{flags}));
+ } /// ditto
+ Config opBinary(string op)(Config other)
+ if (is(typeof(mixin(q{flags} ~ op ~ q{other.flags}))))
+ {
+ return Config(mixin(q{flags} ~ op ~ q{other.flags}));
+ } /// ditto
+ Config opOpAssign(string op)(Config other)
+ if (is(typeof(mixin(q{flags} ~ op ~ q{=other.flags}))))
+ {
+ return Config(mixin(q{flags} ~ op ~ q{=other.flags}));
} /// ditto
version (StdDdoc)
@@ -2158,6 +2169,16 @@ struct Config
}
}
+// https://issues.dlang.org/show_bug.cgi?id=22125
+@safe unittest
+{
+ Config c = Config.retainStdin;
+ c |= Config.retainStdout;
+ c |= Config.retainStderr;
+ c &= ~Config.retainStderr;
+ assert(c == (Config.retainStdin | Config.retainStdout));
+}
+
/// A handle that corresponds to a spawned process.
final class Pid
{
diff --git a/libphobos/src/std/random.d b/libphobos/src/std/random.d
index 887fc66c4f6..f91eb0df6bb 100644
--- a/libphobos/src/std/random.d
+++ b/libphobos/src/std/random.d
@@ -3362,8 +3362,8 @@ if (isRandomAccessRange!Range)
// Optionally @nogc std.random.randomCover
// https://issues.dlang.org/show_bug.cgi?id=14001
auto rng = Xorshift(123_456_789);
- int[5] sa = [1, 2, 3, 4, 5];
- auto r = randomCover(sa[], rng);
+ static immutable int[] sa = [1, 2, 3, 4, 5];
+ auto r = randomCover(sa, rng);
assert(!r.empty);
const x = r.front;
r.popFront();
diff --git a/libphobos/src/std/range/package.d b/libphobos/src/std/range/package.d
index 4161b4f89e3..86bd4a1dd19 100644
--- a/libphobos/src/std/range/package.d
+++ b/libphobos/src/std/range/package.d
@@ -7708,7 +7708,7 @@ if (isForwardRange!RangeOfRanges &&
@safe unittest
{
import std.algorithm.comparison : equal;
- ulong[1] t0 = [ 123 ];
+ ulong[] t0 = [ 123 ];
assert(!hasAssignableElements!(typeof(t0[].chunks(1))));
assert(!is(typeof(transposed(t0[].chunks(1)))));
@@ -10850,7 +10850,7 @@ if (isInputRange!Range && !isInstanceOf!(SortedRange, Range))
into a `SortedRange`, it extracts the original range back out of the `SortedRange`
using $(REF, move, std,algorithm,mutation).
*/
- auto release()
+ auto release() return scope
{
import std.algorithm.mutation : move;
return move(_input);
diff --git a/libphobos/src/std/regex/internal/ir.d b/libphobos/src/std/regex/internal/ir.d
index 4d1b6006564..ec0cb66631e 100644
--- a/libphobos/src/std/regex/internal/ir.d
+++ b/libphobos/src/std/regex/internal/ir.d
@@ -629,7 +629,9 @@ struct Regex(Char)
@safe @property bool empty() const nothrow { return ir is null; }
-
+ /++
+ `namedCaptures` returns a range of all named captures in a given regular expression.
+ +/
@safe @property auto namedCaptures()
{
static struct NamedGroupRange
diff --git a/libphobos/src/std/signals.d b/libphobos/src/std/signals.d
index 23639eb7692..e5dc67eb83d 100644
--- a/libphobos/src/std/signals.d
+++ b/libphobos/src/std/signals.d
@@ -37,10 +37,10 @@
* $(LINK2 http://www.digitalmars.com/d/archives/16368.html, signals and slots)$(BR)
*
* Bugs:
- * $(RED Slots can only be delegates formed from class objects or
- * interfaces to class objects. If a delegate to something else
+ * $(RED Slots can only be delegates referring directly to
+ * class or interface member functions. If a delegate to something else
* is passed to connect(), such as a struct member function,
- * a nested function, a COM interface or a closure, undefined behavior
+ * a nested function, a COM interface, a closure, undefined behavior
* will result.)
*
* Not safe for multiple threads operating on the same signals
@@ -93,7 +93,8 @@ mixin template Signal(T1...)
* The delegate must be to an instance of a class or an interface
* to a class instance.
* Delegates to struct instances or nested functions must not be
- * used as slots.
+ * used as slots. This applies even if the nested function does not access
+ * it's parent function variables.
*/
alias slot_t = void delegate(T1);
diff --git a/libphobos/src/std/stdio.d b/libphobos/src/std/stdio.d
index a2597b658ad..6e903fcf6ef 100644
--- a/libphobos/src/std/stdio.d
+++ b/libphobos/src/std/stdio.d
@@ -2121,6 +2121,9 @@ is recommended if you want to process a complete file.
* When passed as a compile-time argument, the string will be statically checked
* against the argument types passed.
* data = Items to be read.
+ * Returns:
+ * Same as `formattedRead`: The number of variables filled. If the input range `r` ends early,
+ * this number will be less than the number of variables provided.
* Example:
----
// test.d
@@ -3150,7 +3153,7 @@ is empty, throws an `Exception`. In case of an I/O error throws
/// Range primitive implementations.
void put(A)(scope A writeme)
- if ((isSomeChar!(Unqual!(ElementType!A)) ||
+ if ((isSomeChar!(ElementType!A) ||
is(ElementType!A : const(ubyte))) &&
isInputRange!A &&
!isInfinite!A)
@@ -4488,6 +4491,9 @@ void writefln(Char, A...)(in Char[] fmt, A args)
* When passed as a compile-time argument, the string will be statically checked
* against the argument types passed.
* args = Items to be read.
+ * Returns:
+ * Same as `formattedRead`: The number of variables filled. If the input range `r` ends early,
+ * this number will be less than the number of variables provided.
* Example:
----
// test.d
diff --git a/libphobos/src/std/string.d b/libphobos/src/std/string.d
index 5abcc4c26ed..420b68abe6a 100644
--- a/libphobos/src/std/string.d
+++ b/libphobos/src/std/string.d
@@ -154,7 +154,7 @@ private:
string _s;
}
- bool testAliasedString(alias func, Args...)(scope string s, scope Args args)
+ bool testAliasedString(alias func, Args...)(string s, Args args)
{
import std.algorithm.comparison : equal;
auto a = func(TestAliasedString(s), args);
@@ -240,6 +240,17 @@ if (isSomeChar!Char)
return cString ? cString[0 .. cstrlen(cString)] : null;
}
+/// ditto
+inout(Char)[] fromStringz(Char)(return scope inout(Char)[] cString) @nogc @safe pure nothrow
+if (isSomeChar!Char)
+{
+ foreach (i; 0 .. cString.length)
+ if (cString[i] == '\0')
+ return cString[0 .. i];
+
+ return cString;
+}
+
///
@system pure unittest
{
@@ -252,6 +263,44 @@ if (isSomeChar!Char)
assert(fromStringz("福\0"d.ptr) == "福"d);
}
+///
+@nogc @safe pure nothrow unittest
+{
+ struct C
+ {
+ char[32] name;
+ }
+ assert(C("foo\0"c).name.fromStringz() == "foo"c);
+
+ struct W
+ {
+ wchar[32] name;
+ }
+ assert(W("foo\0"w).name.fromStringz() == "foo"w);
+
+ struct D
+ {
+ dchar[32] name;
+ }
+ assert(D("foo\0"d).name.fromStringz() == "foo"d);
+}
+
+@nogc @safe pure nothrow unittest
+{
+ assert( string.init.fromStringz() == ""c);
+ assert(wstring.init.fromStringz() == ""w);
+ assert(dstring.init.fromStringz() == ""d);
+
+ immutable char[3] a = "foo"c;
+ assert(a.fromStringz() == "foo"c);
+
+ immutable wchar[3] b = "foo"w;
+ assert(b.fromStringz() == "foo"w);
+
+ immutable dchar[3] c = "foo"d;
+ assert(c.fromStringz() == "foo"d);
+}
+
@system pure unittest
{
char* a = null;
@@ -2632,8 +2681,12 @@ if (isSomeChar!C)
enum S : string { a = "hello\nworld" }
assert(S.a.splitLines() == ["hello", "world"]);
+}
- char[S.a.length] sa = S.a[];
+@system pure nothrow unittest
+{
+ // dip1000 cannot express an array of scope arrays, so this is not @safe
+ char[11] sa = "hello\nworld";
assert(sa.splitLines() == ["hello", "world"]);
}
@@ -6654,7 +6707,7 @@ string[string] abbrev(string[] values) @safe pure
*/
size_t column(Range)(Range str, in size_t tabsize = 8)
-if ((isInputRange!Range && isSomeChar!(Unqual!(ElementEncodingType!Range)) ||
+if ((isInputRange!Range && isSomeChar!(ElementEncodingType!Range) ||
isNarrowString!Range) &&
!isConvertibleToString!Range)
{
diff --git a/libphobos/src/std/sumtype.d b/libphobos/src/std/sumtype.d
index c94896e4c95..278647ecb83 100644
--- a/libphobos/src/std/sumtype.d
+++ b/libphobos/src/std/sumtype.d
@@ -993,6 +993,7 @@ version (D_BetterC) {} else
}
// const SumTypes
+version (D_BetterC) {} else // not @nogc, https://issues.dlang.org/show_bug.cgi?id=22117
@safe unittest
{
auto _ = const(SumType!(int[]))([1, 2, 3]);
diff --git a/libphobos/src/std/traits.d b/libphobos/src/std/traits.d
index 59be04c85b2..0a04ac5d945 100644
--- a/libphobos/src/std/traits.d
+++ b/libphobos/src/std/traits.d
@@ -6348,7 +6348,7 @@ template isIntegral(T)
/**
* Detect whether `T` is a built-in floating point type.
*/
-enum bool isFloatingPoint(T) = __traits(isFloating, T) && !is(T : ireal) && !is(T : creal);
+enum bool isFloatingPoint(T) = __traits(isFloating, T) && is(T : real);
///
@safe unittest
@@ -6392,16 +6392,28 @@ enum bool isFloatingPoint(T) = __traits(isFloating, T) && !is(T : ireal) && !is(
static assert(!isFloatingPoint!(Q!T));
}
}
+ static if (is(__vector(float[4])))
+ {
+ static assert(!isFloatingPoint!(__vector(float[4])));
+ }
}
/**
* Detect whether `T` is a built-in numeric type (integral or floating
* point).
*/
-enum bool isNumeric(T) = __traits(isArithmetic, T) && !(is(immutable T == immutable bool) ||
- is(immutable T == immutable char) ||
- is(immutable T == immutable wchar) ||
- is(immutable T == immutable dchar));
+template isNumeric(T)
+{
+ static if (!__traits(isArithmetic, T))
+ enum isNumeric = false;
+ else static if (__traits(isFloating, T))
+ enum isNumeric = is(T : real); // Not __vector, imaginary, or complex.
+ else static if (is(T U == enum))
+ enum isNumeric = isNumeric!U;
+ else
+ enum isNumeric = __traits(isZeroInit, T) // Not char, wchar, or dchar.
+ && !is(immutable T == immutable bool) && !is(T == __vector);
+}
///
@safe unittest
@@ -6453,6 +6465,21 @@ enum bool isNumeric(T) = __traits(isArithmetic, T) && !(is(immutable T == immuta
alias t this;
}
static assert(!isNumeric!(S!int));
+
+ enum EChar : char { a = 0, }
+ static assert(!isNumeric!EChar);
+
+ static if (is(__vector(float[4])))
+ {
+ static assert(!isNumeric!(__vector(float[4])));
+ }
+ static if (is(__vector(int[4])))
+ {
+ static assert(!isNumeric!(__vector(int[4])));
+ }
+
+ static assert(!isNumeric!ifloat);
+ static assert(!isNumeric!cfloat);
}
/**
@@ -6514,10 +6541,16 @@ enum bool isBasicType(T) = isScalarType!T || is(immutable T == immutable void);
/**
* Detect whether `T` is a built-in unsigned numeric type.
*/
-enum bool isUnsigned(T) = __traits(isUnsigned, T) && !(is(immutable T == immutable char) ||
- is(immutable T == immutable wchar) ||
- is(immutable T == immutable dchar) ||
- is(immutable T == immutable bool));
+template isUnsigned(T)
+{
+ static if (!__traits(isUnsigned, T))
+ enum isUnsigned = false;
+ else static if (is(T U == enum))
+ enum isUnsigned = isUnsigned!U;
+ else
+ enum isUnsigned = __traits(isZeroInit, T) // Not char, wchar, or dchar.
+ && !is(immutable T == immutable bool) && !is(T == __vector);
+}
///
@safe unittest
@@ -6554,12 +6587,21 @@ enum bool isUnsigned(T) = __traits(isUnsigned, T) && !(is(immutable T == immutab
alias t this;
}
static assert(!isUnsigned!(S!uint));
+
+ enum EChar : char { a = 0, }
+ static assert(!isUnsigned!EChar);
+
+ static if (is(__vector(uint[4])))
+ {
+ static assert(!isUnsigned!(__vector(uint[4])));
+ }
}
/**
* Detect whether `T` is a built-in signed numeric type.
*/
-enum bool isSigned(T) = __traits(isArithmetic, T) && !__traits(isUnsigned, T);
+enum bool isSigned(T) = __traits(isArithmetic, T) && !__traits(isUnsigned, T)
+ && is(T : real);
///
@safe unittest
@@ -6598,6 +6640,14 @@ enum bool isSigned(T) = __traits(isArithmetic, T) && !__traits(isUnsigned, T);
alias t this;
}
static assert(!isSigned!(S!uint));
+
+ static if (is(__vector(int[4])))
+ {
+ static assert(!isSigned!(__vector(int[4])));
+ }
+
+ static assert(!isSigned!ifloat);
+ static assert(!isSigned!cfloat);
}
// https://issues.dlang.org/show_bug.cgi?id=17196
@@ -7563,6 +7613,11 @@ template isCallable(alias callable)
else static if (is(typeof(&callable.opCall) V : V*) && is(V == function))
// T is a type which has a static member function opCall().
enum bool isCallable = true;
+ else static if (is(typeof(&callable.opCall!())))
+ {
+ alias TemplateInstanceType = typeof(&callable.opCall!());
+ enum bool isCallable = isCallable!TemplateInstanceType;
+ }
else static if (is(typeof(&callable!())))
{
alias TemplateInstanceType = typeof(&callable!());
@@ -7602,9 +7657,13 @@ template isCallable(alias callable)
{
void f()() { }
T g(T = int)(T x) { return x; }
+ struct S1 { static void opCall()() { } }
+ struct S2 { static T opCall(T = int)(T x) {return x; } }
static assert( isCallable!f);
static assert( isCallable!g);
+ static assert( isCallable!S1);
+ static assert( isCallable!S2);
}
/// Overloaded functions and function templates.
diff --git a/libphobos/src/std/typecons.d b/libphobos/src/std/typecons.d
index e54622d8c30..b49b989ef65 100644
--- a/libphobos/src/std/typecons.d
+++ b/libphobos/src/std/typecons.d
@@ -3010,7 +3010,7 @@ struct Nullable(T)
* Params:
* value = A value of type `T` to assign to this `Nullable`.
*/
- void opAssign()(T value)
+ Nullable opAssign()(T value)
{
import std.algorithm.mutation : moveEmplace, move;
@@ -3028,6 +3028,7 @@ struct Nullable(T)
move(copy.payload, _value.payload);
}
_isNull = false;
+ return this;
}
/**
@@ -3038,12 +3039,13 @@ struct Nullable(T)
* Params:
* value = A value of type `Nullable!T` to assign to this `Nullable`.
*/
- void opAssign()(Nullable!T value)
+ Nullable opAssign()(Nullable!T value)
{
if (value._isNull)
nullify();
else
opAssign(value.get());
+ return this;
}
/**
@@ -3088,13 +3090,13 @@ struct Nullable(T)
}
/// ditto
- @property inout(T) get()(inout(T) fallback) inout @safe pure nothrow
+ @property inout(T) get()(inout(T) fallback) inout
{
return isNull ? fallback : _value.payload;
}
/// ditto
- @property auto get(U)(inout(U) fallback) inout @safe pure nothrow
+ @property auto get(U)(inout(U) fallback) inout
{
return isNull ? fallback : _value.payload;
}
@@ -3605,6 +3607,28 @@ auto nullable(T)(T t)
assert(test1 == test2);
}
+// https://issues.dlang.org/show_bug.cgi?id=22101
+@safe unittest
+{
+ static int impure;
+
+ struct S
+ {
+ ~this() { impure++; }
+ }
+
+ Nullable!S s;
+ s.get(S());
+}
+
+// https://issues.dlang.org/show_bug.cgi?id=22100
+@safe unittest
+{
+ Nullable!int a, b, c;
+ a = b = c = 5;
+ a = b = c = nullable(5);
+}
+
/**
Just like `Nullable!T`, except that the null state is defined as a
particular value. For example, $(D Nullable!(uint, uint.max)) is an
@@ -6635,7 +6659,16 @@ assert(refCountedStore.isInitialized)).
string toString(this This)()
{
import std.conv : to;
- return to!string(refCountedPayload);
+
+ static if (autoInit)
+ return to!string(refCountedPayload);
+ else
+ {
+ if (!_refCounted.isInitialized)
+ return This.stringof ~ "(RefCountedStore(null))";
+ else
+ return to!string(_refCounted._store._payload);
+ }
}
}
}
@@ -6773,16 +6806,23 @@ pure @system unittest
import std.conv : to;
// Check that string conversion is transparent for refcounted
// structs that do not have either toString or alias this.
- struct A { Object a; }
+ static struct A { Object a; }
auto a = A(new Object());
auto r = refCounted(a);
assert(to!string(r) == to!string(a));
assert(to!string(cast(const) r) == to!string(cast(const) a));
// Check that string conversion is still transparent for refcounted
// structs that have alias this.
- struct B { int b; alias b this; }
- struct C { B b; alias b this; }
+ static struct B { int b; alias b this; }
+ static struct C { B b; alias b this; }
assert(to!string(refCounted(C(B(123)))) == to!string(C(B(123))));
+ // https://issues.dlang.org/show_bug.cgi?id=22093
+ // Check that uninitialized refcounted structs that previously could be
+ // converted to strings still can be.
+ alias R = typeof(r);
+ R r2;
+ cast(void) (((const ref R a) => to!string(a))(r2));
+ cast(void) to!string(RefCounted!(A, RefCountedAutoInitialize.no).init);
}
/**
@@ -8211,7 +8251,7 @@ if (alignment > 0 && !((alignment - 1) & alignment))
void test(size_t size)
{
import core.stdc.stdlib;
- alloca(size);
+ cast(void) alloca(size);
alignmentTest();
}
foreach (i; 0 .. 10)
diff --git a/libphobos/src/std/utf.d b/libphobos/src/std/utf.d
index 7059e8215e7..41f5a09a9cf 100644
--- a/libphobos/src/std/utf.d
+++ b/libphobos/src/std/utf.d
@@ -41,6 +41,7 @@ $(TR $(TD Index) $(TD
))
$(TR $(TD Validation) $(TD
$(LREF isValidDchar)
+ $(LREF isValidCodepoint)
$(LREF validate)
))
$(TR $(TD Miscellaneous) $(TD
@@ -306,6 +307,54 @@ pure nothrow @safe @nogc unittest
});
}
+/**
+Checks if a single character forms a valid code point.
+
+When standing alone, some characters are invalid code points. For
+example the `wchar` `0xD800` is a so called high surrogate, which can
+only be interpreted together with a low surrogate following it. As a
+standalone character it is considered invalid.
+
+See $(LINK2 http://www.unicode.org/versions/Unicode13.0.0/,
+Unicode Standard, D90, D91 and D92) for more details.
+
+Params:
+ c = character to test
+ Char = character type of `c`
+
+Returns:
+ `true`, if `c` forms a valid code point.
+ */
+bool isValidCodepoint(Char)(Char c)
+if (isSomeChar!Char)
+{
+ alias UChar = Unqual!Char;
+ static if (is(UChar == char))
+ {
+ return c <= 0x7F;
+ }
+ else static if (is(UChar == wchar))
+ {
+ return c <= 0xD7FF || c >= 0xE000;
+ }
+ else static if (is(UChar == dchar))
+ {
+ return isValidDchar(c);
+ }
+ else
+ static assert(false, "unknown character type: `" ~ Char.stringof ~ "`");
+}
+
+///
+@safe pure nothrow unittest
+{
+ assert( isValidCodepoint(cast(char) 0x40));
+ assert(!isValidCodepoint(cast(char) 0x80));
+ assert( isValidCodepoint(cast(wchar) 0x1234));
+ assert(!isValidCodepoint(cast(wchar) 0xD800));
+ assert( isValidCodepoint(cast(dchar) 0x0010FFFF));
+ assert(!isValidCodepoint(cast(dchar) 0x12345678));
+}
/++
Calculate the length of the UTF sequence starting at `index`
diff --git a/libphobos/src/std/uuid.d b/libphobos/src/std/uuid.d
index 1347bca5c25..dec2a1c276d 100644
--- a/libphobos/src/std/uuid.d
+++ b/libphobos/src/std/uuid.d
@@ -331,7 +331,7 @@ public struct UUID
*
* For a less strict parser, see $(LREF parseUUID)
*/
- this(T)(in T[] uuid) if (isSomeChar!(Unqual!T))
+ this(T)(in T[] uuid) if (isSomeChar!T)
{
import std.conv : to, parse;
if (uuid.length < 36)
diff --git a/libphobos/testsuite/libphobos.exceptions/assert_fail.d b/libphobos/testsuite/libphobos.exceptions/assert_fail.d
index d5b41508bab..79b3cb8139e 100644
--- a/libphobos/testsuite/libphobos.exceptions/assert_fail.d
+++ b/libphobos/testsuite/libphobos.exceptions/assert_fail.d
@@ -444,6 +444,82 @@ void testException()
test(MayThrow(0), MayThrow(1), `Some message != <toString() failed: "Error", called on MayThrow(1)>`);
}
+void testOverlappingFields()
+{
+ static struct S
+ {
+ union
+ {
+ double num;
+ immutable(char)[] name;
+ }
+ }
+
+ test(S(1.0), S(2.0), "S(<overlapped field>, <overlapped field>) != S(<overlapped field>, <overlapped field>)");
+
+ static struct S2
+ {
+ int valid;
+ union
+ {
+ double num;
+ immutable(char)[] name;
+ }
+ }
+
+ test(S2(4, 1.0), S2(5, 2.0), "S2(4, <overlapped field>, <overlapped field>) != S2(5, <overlapped field>, <overlapped field>)");
+
+ static struct S3
+ {
+ union
+ {
+ double num;
+ immutable(char)[] name;
+ }
+ int valid;
+ }
+ S3 a = {
+ num: 1.0,
+ valid: 8
+ };
+
+ S3 b = {
+ num: 1.0,
+ valid: 8
+ };
+ test(a, b, "S3(<overlapped field>, <overlapped field>, 8) != S3(<overlapped field>, <overlapped field>, 8)");
+}
+
+void testDestruction()
+{
+ static class Test
+ {
+ __gshared string unary, binary;
+ __gshared bool run;
+
+ ~this()
+ {
+ run = true;
+ unary = _d_assert_fail!int("", 1);
+ binary = _d_assert_fail!int("==", 1, 2);
+ }
+ }
+
+ static void createGarbage()
+ {
+ new Test();
+ new long[100];
+ }
+
+ import core.memory : GC;
+ createGarbage();
+ GC.collect();
+
+ assert(Test.run);
+ assert(Test.unary == "Assertion failed (rich formatting is disabled in finalizers)");
+ assert(Test.binary == "Assertion failed (rich formatting is disabled in finalizers)");
+}
+
int main()
{
testIntegers();
@@ -476,6 +552,9 @@ int main()
testExternClasses();
testShared();
testException();
+ testOverlappingFields();
+ if (!__ctfe)
+ testDestruction();
if (!__ctfe)
fprintf(stderr, "success.\n");
diff --git a/libphobos/testsuite/libphobos.hash/test_hash.d b/libphobos/testsuite/libphobos.hash/test_hash.d
index c6ef3ed668e..d0a8e5fb809 100644
--- a/libphobos/testsuite/libphobos.hash/test_hash.d
+++ b/libphobos/testsuite/libphobos.hash/test_hash.d
@@ -16,6 +16,8 @@ void main()
issue19582();
issue20034();
issue21642();
+ issue22024();
+ issue22076();
testTypeInfoArrayGetHash1();
testTypeInfoArrayGetHash2();
pr2243();
@@ -247,6 +249,71 @@ void issue21642() @safe nothrow pure
assert(toUbyte(c) == [ubyte(1)]);
}
+/// Accept enum type whose ultimate base type is a SIMD vector.
+void issue22024() @nogc nothrow pure @safe
+{
+ static if (is(__vector(float[2])))
+ {
+ enum E2 : __vector(float[2]) { a = __vector(float[2]).init, }
+ enum F2 : E2 { a = E2.init, }
+ assert(hashOf(E2.init) == hashOf(F2.init));
+ assert(hashOf(E2.init, 1) == hashOf(F2.init, 1));
+ }
+ static if (is(__vector(float[4])))
+ {
+ enum E4 : __vector(float[4]) { a = __vector(float[4]).init, }
+ enum F4 : E4 { a = E4.init, }
+ assert(hashOf(E4.init) == hashOf(F4.init));
+ assert(hashOf(E4.init, 1) == hashOf(F4.init, 1));
+ }
+}
+
+/// hashOf(S) can segfault if S.toHash is forwarded via `alias this` to a
+/// receiver which may be null.
+void issue22076()
+{
+ static struct S0 { Object a; alias a this; }
+
+ static struct S1
+ {
+ S0 a;
+ inout(S0)* b() inout nothrow { return &a; }
+ alias b this;
+ }
+
+ static struct S2
+ {
+ S0 a;
+ S1 b;
+ }
+
+ extern(C++) static class C0
+ {
+ int foo() { return 0; } // Need at least one function in vtable.
+ S0 a; alias a this;
+ }
+
+ extern(C++) static class C1
+ {
+ S1 a;
+ inout(S1)* b() inout nothrow { return &a; }
+ alias b this;
+ }
+
+ cast(void) hashOf(S0.init);
+ cast(void) hashOf(S0.init, 0);
+ cast(void) hashOf(S1.init);
+ cast(void) hashOf(S1.init, 0);
+ cast(void) hashOf(S2.init);
+ cast(void) hashOf(S2.init, 0);
+ auto c0 = new C0();
+ cast(void) hashOf(c0);
+ cast(void) hashOf(c0, 0);
+ auto c1 = new C1();
+ cast(void) hashOf(c1);
+ cast(void) hashOf(c1, 0);
+}
+
/// Tests ensure TypeInfo_Array.getHash uses element hash functions instead
/// of hashing array data.
void testTypeInfoArrayGetHash1()
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-07-30 8:44 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-30 8:44 [gcc(refs/users/ibuclaw/heads/gdc)] Import dmd v2.097.1: dmd 50bdf003a, druntime f8df5552, phobos 4ea930b6c Iain Buclaw
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).