aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/dmd
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@symmetryinvestments.com>2024-12-29 06:40:04 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2025-01-05 13:30:24 +0100
commit332cf038fda109ea0612eeba7a85441293ba6984 (patch)
treeca5c381d189ace8afa4cf40369cd7d2063bc00a4 /gcc/d/dmd
parent31f1bec65ba257adc346f952fd79a1ec3165a2e6 (diff)
downloadgcc-332cf038fda109ea0612eeba7a85441293ba6984.zip
gcc-332cf038fda109ea0612eeba7a85441293ba6984.tar.gz
gcc-332cf038fda109ea0612eeba7a85441293ba6984.tar.bz2
d: Merge upstream dmd c11e1d1708, druntime e60bfd11bd, phobos 8729740e3
Synchronizing the compiler with the upstream release of v2.108.1. D front-end changes: - Import dmd v2.108.1. - Add experimental support for language editions, enabled by adding the UDA `@__edition_latest_do_not_use' before module declarations. - [Next Edition] Aliasing a member of a type instance is now an error. - Added `__ctfeWrite' to write messages from CTFE. - `-fdump-c++-spec' generates signatures for `extern(Windows)' and `extern(System)' functions. - `foreach_reverse' on a delegate is now an error. - ImportC has improved Unicode support. D runtime changes: - Mark unsafe unittest @trusted. Phobos changes: - Mark unsafe functions @trusted. gcc/d/ChangeLog: * Make-lang.in (D_FRONTEND_OBJS): Add d/attribsem.o, d/common-charactertables.o, d/common-identifiertables.o. * d-attribs.cc (apply_user_attributes): Update for new front-end interface. * d-builtins.cc (d_init_versions): Predefine CppRuntime_GNU. * d-incpath.cc (add_globalpaths): Update for new front-end interface. (add_filepaths): Likewise. (add_import_paths): Likewise. * d-lang.cc (d_post_options): Likewise. * dmd/MERGE: Merge upstream dmd c11e1d1708. * dmd/VERSION: Bump version to v2.108.1. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime e60bfd11bd. * src/MERGE: Merge upstream phobos 8729740e3. gcc/testsuite/ChangeLog: * gdc.dg/torture/pr96435.d: Add dg-warning.
Diffstat (limited to 'gcc/d/dmd')
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/README.md1
-rw-r--r--gcc/d/dmd/VERSION2
-rw-r--r--gcc/d/dmd/arrayop.d5
-rw-r--r--gcc/d/dmd/astenums.d27
-rw-r--r--gcc/d/dmd/attrib.d53
-rw-r--r--gcc/d/dmd/attrib.h6
-rw-r--r--gcc/d/dmd/attribsem.d87
-rw-r--r--gcc/d/dmd/common/charactertables.d267
-rw-r--r--gcc/d/dmd/common/charactertables.h29
-rw-r--r--gcc/d/dmd/common/file.d171
-rw-r--r--gcc/d/dmd/common/identifiertables.d4241
-rw-r--r--gcc/d/dmd/common/outbuffer.d7
-rw-r--r--gcc/d/dmd/cond.h4
-rw-r--r--gcc/d/dmd/cparse.d77
-rw-r--r--gcc/d/dmd/cppmangle.d58
-rw-r--r--gcc/d/dmd/cxxfrontend.d10
-rw-r--r--gcc/d/dmd/dcast.d4
-rw-r--r--gcc/d/dmd/dclass.d1
-rw-r--r--gcc/d/dmd/declaration.d54
-rw-r--r--gcc/d/dmd/dmangle.d5
-rw-r--r--gcc/d/dmd/dmodule.d35
-rw-r--r--gcc/d/dmd/doc.d50
-rw-r--r--gcc/d/dmd/dscope.d10
-rw-r--r--gcc/d/dmd/dstruct.d10
-rw-r--r--gcc/d/dmd/dsymbol.d6
-rw-r--r--gcc/d/dmd/dsymbol.h114
-rw-r--r--gcc/d/dmd/dsymbolsem.d36
-rw-r--r--gcc/d/dmd/dtemplate.d2
-rw-r--r--gcc/d/dmd/dtoh.d49
-rw-r--r--gcc/d/dmd/errors.h2
-rw-r--r--gcc/d/dmd/escape.d514
-rw-r--r--gcc/d/dmd/expression.d1
-rw-r--r--gcc/d/dmd/expression.h2
-rw-r--r--gcc/d/dmd/expressionsem.d59
-rw-r--r--gcc/d/dmd/file_manager.d268
-rw-r--r--gcc/d/dmd/func.d868
-rw-r--r--gcc/d/dmd/funcsem.d812
-rw-r--r--gcc/d/dmd/globals.d32
-rw-r--r--gcc/d/dmd/globals.h18
-rw-r--r--gcc/d/dmd/id.d7
-rw-r--r--gcc/d/dmd/identifier.d75
-rw-r--r--gcc/d/dmd/init.d14
-rw-r--r--gcc/d/dmd/init.h2
-rw-r--r--gcc/d/dmd/initsem.d17
-rw-r--r--gcc/d/dmd/lexer.d335
-rw-r--r--gcc/d/dmd/module.h9
-rw-r--r--gcc/d/dmd/mtype.d126
-rw-r--r--gcc/d/dmd/mtype.h10
-rw-r--r--gcc/d/dmd/mustuse.d2
-rw-r--r--gcc/d/dmd/ob.d150
-rw-r--r--gcc/d/dmd/objc.d1
-rw-r--r--gcc/d/dmd/opover.d1
-rw-r--r--gcc/d/dmd/parse.d25
-rw-r--r--gcc/d/dmd/pragmasem.d4
-rw-r--r--gcc/d/dmd/root/array.h4
-rw-r--r--gcc/d/dmd/root/bitarray.h2
-rw-r--r--gcc/d/dmd/root/dcompat.h2
-rw-r--r--gcc/d/dmd/root/file.d88
-rw-r--r--gcc/d/dmd/root/filename.d22
-rw-r--r--gcc/d/dmd/root/filename.h4
-rw-r--r--gcc/d/dmd/root/rmem.d2
-rw-r--r--gcc/d/dmd/root/string.d196
-rw-r--r--gcc/d/dmd/root/utf.d275
-rw-r--r--gcc/d/dmd/safe.d15
-rw-r--r--gcc/d/dmd/semantic2.d1
-rw-r--r--gcc/d/dmd/semantic3.d27
-rw-r--r--gcc/d/dmd/statement.h68
-rw-r--r--gcc/d/dmd/statementsem.d25
-rw-r--r--gcc/d/dmd/target.d3
-rw-r--r--gcc/d/dmd/target.h2
-rw-r--r--gcc/d/dmd/tokens.h2
-rw-r--r--gcc/d/dmd/traits.d3
-rw-r--r--gcc/d/dmd/typesem.d2
-rw-r--r--gcc/d/dmd/utils.d12
75 files changed, 7242 insertions, 2290 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index dc47db8..46d435e 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-b65767825f365dbc153457fc86e1054b03196c6d
+c11e1d1708646c9ac81ac2aafb57fa1ef5d289ad
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/README.md b/gcc/d/dmd/README.md
index 282e818..d784d07 100644
--- a/gcc/d/dmd/README.md
+++ b/gcc/d/dmd/README.md
@@ -109,6 +109,7 @@ Note that these groups have no strict meaning, the category assignments are a bi
| File | Purpose |
|-------------------------------------------------------------------------------------------|-------------------------------------------------------------------|
+| [attribsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/attribsem.d) | Attribute semantics |
| [dsymbolsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dsymbolsem.d) | Do semantic 1 pass (symbol identifiers/types) |
| [enumsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/enumsem.d) | Enum semantics |
| [funcsem.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/funcsem.d) | Function semantics |
diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION
index 5868b87..99582f5 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@
-v2.108.0
+v2.108.1
diff --git a/gcc/d/dmd/arrayop.d b/gcc/d/dmd/arrayop.d
index af3875e..d0ec5eb 100644
--- a/gcc/d/dmd/arrayop.d
+++ b/gcc/d/dmd/arrayop.d
@@ -145,7 +145,10 @@ Expression arrayOp(BinExp e, Scope* sc)
if (auto te = id.isTemplateExp())
arrayOp = te.td;
else
- ObjectNotFound(idArrayOp); // fatal error
+ {
+ ObjectNotFound(e.loc, idArrayOp); // fatal error
+ return ErrorExp.get();
+ }
}
auto fd = resolveFuncCall(e.loc, sc, arrayOp, tiargs, null, ArgumentList(args), FuncResolveFlag.standard);
diff --git a/gcc/d/dmd/astenums.d b/gcc/d/dmd/astenums.d
index 4fc1514..1e30b9f 100644
--- a/gcc/d/dmd/astenums.d
+++ b/gcc/d/dmd/astenums.d
@@ -18,6 +18,15 @@ enum Sizeok : ubyte
done, /// size of aggregate is set correctly
}
+/// D Language version
+enum Edition : ubyte
+{
+ none,
+ legacy, /// Before the introduction of editions
+ v2024, /// Experimental first new edition
+ latest = v2024 /// Newest edition that this compiler knows of
+}
+
enum Baseok : ubyte
{
none, /// base classes not computed yet
@@ -441,6 +450,24 @@ enum FileType : ubyte
c, /// C source file
}
+/// In which context checks for assertions, contracts, bounds checks etc. are enabled
+enum CHECKENABLE : ubyte
+{
+ _default, /// initial value
+ off, /// never do checking
+ on, /// always do checking
+ safeonly, /// do checking only in @safe functions
+}
+
+/// What should happend when an assertion fails
+enum CHECKACTION : ubyte
+{
+ D, /// call D assert on failure
+ C, /// call C assert on failure
+ halt, /// cause program halt on failure
+ context, /// call D assert with the error context on failure
+}
+
extern (C++) struct structalign_t
{
private:
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index d7d3eca6..1c8eb57 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -35,7 +35,6 @@ import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.errors;
import dmd.expression;
-import dmd.expressionsem;
import dmd.func;
import dmd.globals;
import dmd.hdrgen : visibilityToBuffer;
@@ -1121,21 +1120,6 @@ extern (C++) final class UserAttributeDeclaration : AttribDeclaration
return udas;
}
- Expressions* getAttributes()
- {
- if (auto sc = _scope)
- {
- _scope = null;
- arrayExpressionSemantic(atts.peekSlice(), sc);
- }
- auto exps = new Expressions();
- if (userAttribDecl && userAttribDecl !is this)
- exps.push(new TupleExp(Loc.initial, userAttribDecl.getAttributes()));
- if (atts && atts.length)
- exps.push(new TupleExp(Loc.initial, atts));
- return exps;
- }
-
override const(char)* kind() const
{
return "UserAttribute";
@@ -1232,43 +1216,6 @@ bool isCoreUda(Dsymbol sym, Identifier ident)
}
/**
- * Iterates the UDAs attached to the given symbol.
- *
- * Params:
- * sym = the symbol to get the UDAs from
- * sc = scope to use for semantic analysis of UDAs
- * dg = called once for each UDA
- *
- * Returns:
- * If `dg` returns `!= 0`, stops the iteration and returns that value.
- * Otherwise, returns 0.
- */
-int foreachUda(Dsymbol sym, Scope* sc, int delegate(Expression) dg)
-{
- if (!sym.userAttribDecl)
- return 0;
-
- auto udas = sym.userAttribDecl.getAttributes();
- arrayExpressionSemantic(udas.peekSlice(), sc, true);
-
- return udas.each!((uda) {
- if (!uda.isTupleExp())
- return 0;
-
- auto exps = uda.isTupleExp().exps;
-
- return exps.each!((e) {
- assert(e);
-
- if (auto result = dg(e))
- return result;
-
- return 0;
- });
- });
-}
-
-/**
* Iterates the UDAs attached to the given symbol, without performing semantic
* analysis.
*
diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h
index 344a7e9..d4c41ec 100644
--- a/gcc/d/dmd/attrib.h
+++ b/gcc/d/dmd/attrib.h
@@ -17,6 +17,11 @@ class Expression;
class Condition;
class StaticForeach;
+namespace dmd
+{
+ Expressions *getAttributes(UserAttributeDeclaration *a);
+}
+
/**************************************************************/
class AttribDeclaration : public Dsymbol
@@ -226,7 +231,6 @@ public:
UserAttributeDeclaration *syntaxCopy(Dsymbol *s) override;
Scope *newScope(Scope *sc) override;
- Expressions *getAttributes();
const char *kind() const override;
void accept(Visitor *v) override { v->visit(this); }
};
diff --git a/gcc/d/dmd/attribsem.d b/gcc/d/dmd/attribsem.d
new file mode 100644
index 0000000..44647ee
--- /dev/null
+++ b/gcc/d/dmd/attribsem.d
@@ -0,0 +1,87 @@
+/**
+ * Does semantic analysis for attributes.
+ *
+ * The term 'attribute' refers to things that can apply to a larger scope than a single declaration.
+ * Among them are:
+ * - Alignment (`align(8)`)
+ * - User defined attributes (`@UDA`)
+ * - Function Attributes (`@safe`)
+ * - Storage classes (`static`, `__gshared`)
+ * - Mixin declarations (`mixin("int x;")`)
+ * - Conditional compilation (`static if`, `static foreach`)
+ * - Linkage (`extern(C)`)
+ * - Anonymous structs / unions
+ * - Protection (`private`, `public`)
+ * - Deprecated declarations (`@deprecated`)
+ *
+ * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
+ * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
+ * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/attribsem.d, _attrib.d)
+ * Documentation: https://dlang.org/phobos/dmd_attribsem.html
+ * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/attribsem.d
+ */
+
+module dmd.attribsem;
+
+import dmd.arraytypes;
+import dmd.attrib;
+import dmd.dscope;
+import dmd.dsymbol;
+import dmd.expression;
+import dmd.expressionsem;
+import dmd.location;
+import dmd.root.array; // for each
+
+
+Expressions* getAttributes(UserAttributeDeclaration a)
+{
+ if (auto sc = a._scope)
+ {
+ a._scope = null;
+ arrayExpressionSemantic(a.atts.peekSlice(), sc);
+ }
+ auto exps = new Expressions();
+ if (a.userAttribDecl && a.userAttribDecl !is a)
+ exps.push(new TupleExp(Loc.initial, a.userAttribDecl.getAttributes()));
+ if (a.atts && a.atts.length)
+ exps.push(new TupleExp(Loc.initial, a.atts));
+ return exps;
+}
+
+/**
+ * Iterates the UDAs attached to the given symbol.
+ *
+ * Params:
+ * sym = the symbol to get the UDAs from
+ * sc = scope to use for semantic analysis of UDAs
+ * dg = called once for each UDA
+ *
+ * Returns:
+ * If `dg` returns `!= 0`, stops the iteration and returns that value.
+ * Otherwise, returns 0.
+ */
+int foreachUda(Dsymbol sym, Scope* sc, int delegate(Expression) dg)
+{
+ if (!sym.userAttribDecl)
+ return 0;
+
+ auto udas = sym.userAttribDecl.getAttributes();
+ arrayExpressionSemantic(udas.peekSlice(), sc, true);
+
+ return udas.each!((uda) {
+ if (!uda.isTupleExp())
+ return 0;
+
+ auto exps = uda.isTupleExp().exps;
+
+ return exps.each!((e) {
+ assert(e);
+
+ if (auto result = dg(e))
+ return result;
+
+ return 0;
+ });
+ });
+}
diff --git a/gcc/d/dmd/common/charactertables.d b/gcc/d/dmd/common/charactertables.d
new file mode 100644
index 0000000..ac89807
--- /dev/null
+++ b/gcc/d/dmd/common/charactertables.d
@@ -0,0 +1,267 @@
+/**
+ * Character tables related to identifiers.
+ *
+ * Supports UAX31, C99, C11 and least restrictive (All).
+ *
+ * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
+ * Authors: $(LINK2 https://cattermole.co.nz, Richard (Rikki) Andrew Cattermole)
+ * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/charactertables.d, common/charactertables.d)
+ * Documentation: https://dlang.org/phobos/dmd_common_charactertables.html
+ * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/charactertables.d
+ */
+module dmd.common.charactertables;
+
+@safe nothrow @nogc pure:
+
+extern(C++):
+
+///
+enum IdentifierTable {
+ UAX31, ///
+ C99, ///
+ C11, ///
+ LR, /// Least Restrictive aka All
+}
+
+///
+struct IdentifierCharLookup
+{
+ @safe nothrow @nogc pure:
+
+ ///
+ extern(C++) bool function(dchar) isStart;
+ ///
+ extern(C++) bool function(dchar) isContinue;
+
+ /// Lookup the table given the table name
+ extern(C++) static IdentifierCharLookup forTable(IdentifierTable table)
+ {
+ import dmd.common.identifiertables;
+
+ // Awful solution to require these lambdas.
+ // However without them the extern(C++) ABI issues crop up for isInRange,
+ // and then it can't access the tables.
+ final switch(table) {
+ case IdentifierTable.UAX31:
+ return IdentifierCharLookup(
+ (c) => isInRange!UAX31_Start(c),
+ (c) => isInRange!UAX31_Continue(c));
+ case IdentifierTable.C99:
+ return IdentifierCharLookup(
+ (c) => isInRange!FixedTable_C99_Start(c),
+ (c) => isInRange!FixedTable_C99_Continue(c));
+ case IdentifierTable.C11:
+ return IdentifierCharLookup(
+ (c) => isInRange!FixedTable_C11_Start(c),
+ (c) => isInRange!FixedTable_C11_Continue(c));
+ case IdentifierTable.LR:
+ return IdentifierCharLookup(
+ (c) => isInRange!LeastRestrictive_Start(c),
+ (c) => isInRange!LeastRestrictive_Continue(c));
+ }
+ }
+}
+
+/**
+Convenience function for use in places where we just don't care,
+what the identifier ranges are, or if it is start/continue.
+
+Returns: is character a member of least restrictive of all.
+*/
+bool isAnyIdentifierCharacter(dchar c)
+{
+ import dmd.common.identifiertables;
+ return isInRange!LeastRestrictive_OfAll(c);
+}
+
+///
+unittest
+{
+ assert(isAnyIdentifierCharacter('ÄŸ'));
+}
+
+/**
+Convenience function for use in places where we just don't care,
+what the identifier ranges are.
+
+Returns: is character a member of restrictive Start
+*/
+bool isAnyStart(dchar c)
+{
+ import dmd.common.identifiertables;
+ return isInRange!LeastRestrictive_Start(c);
+}
+
+///
+unittest
+{
+ assert(isAnyStart('ÄŸ'));
+}
+
+/**
+Convenience function for use in places where we just don't care,
+what the identifier ranges are.
+
+Returns: is character a member of least restrictive Continue
+*/
+bool isAnyContinue(dchar c)
+{
+ import dmd.common.identifiertables;
+ return isInRange!LeastRestrictive_Continue(c);
+}
+
+///
+unittest
+{
+ assert(isAnyContinue('ÄŸ'));
+}
+
+/// UTF line separator
+enum LS = 0x2028;
+/// UTF paragraph separator
+enum PS = 0x2029;
+
+private
+{
+ enum CMoctal = 0x1;
+ enum CMhex = 0x2;
+ enum CMidchar = 0x4;
+ enum CMzerosecond = 0x8;
+ enum CMdigitsecond = 0x10;
+ enum CMsinglechar = 0x20;
+}
+
+///
+bool isoctal(const char c)
+{
+ return (cmtable[c] & CMoctal) != 0;
+}
+
+///
+bool ishex(const char c)
+{
+ return (cmtable[c] & CMhex) != 0;
+}
+
+///
+bool isidchar(const char c)
+{
+ return (cmtable[c] & CMidchar) != 0;
+}
+
+///
+bool isZeroSecond(const char c)
+{
+ return (cmtable[c] & CMzerosecond) != 0;
+}
+
+///
+bool isDigitSecond(const char c)
+{
+ return (cmtable[c] & CMdigitsecond) != 0;
+}
+
+///
+bool issinglechar(const char c)
+{
+ return (cmtable[c] & CMsinglechar) != 0;
+}
+
+///
+bool c_isxdigit(const int c)
+{
+ return (( c >= '0' && c <= '9') ||
+ ( c >= 'a' && c <= 'f') ||
+ ( c >= 'A' && c <= 'F'));
+}
+
+///
+bool c_isalnum(const int c)
+{
+ return (( c >= '0' && c <= '9') ||
+ ( c >= 'a' && c <= 'z') ||
+ ( c >= 'A' && c <= 'Z'));
+}
+
+extern(D) private:
+
+// originally from dmd.root.utf
+bool isInRange(alias Ranges)(dchar c)
+{
+ size_t high = Ranges.length - 1;
+ // Shortcut search if c is out of range
+ size_t low = (c < Ranges[0][0] || Ranges[high][1] < c) ? high + 1 : 0;
+ // Binary search
+ while (low <= high)
+ {
+ const size_t mid = low + ((high - low) >> 1);
+ if (c < Ranges[mid][0])
+ high = mid - 1;
+ else if (Ranges[mid][1] < c)
+ low = mid + 1;
+ else
+ {
+ assert(Ranges[mid][0] <= c && c <= Ranges[mid][1]);
+ return true;
+ }
+ }
+ return false;
+}
+
+/********************************************
+ * Do our own char maps
+ */
+// originally from dmd.lexer (was private)
+static immutable cmtable = ()
+{
+ ubyte[256] table;
+ foreach (const c; 0 .. table.length)
+ {
+ if ('0' <= c && c <= '7')
+ table[c] |= CMoctal;
+ if (c_isxdigit(c))
+ table[c] |= CMhex;
+ if (c_isalnum(c) || c == '_')
+ table[c] |= CMidchar;
+
+ switch (c)
+ {
+ case 'x': case 'X':
+ case 'b': case 'B':
+ table[c] |= CMzerosecond;
+ break;
+
+ case '0': .. case '9':
+ case 'e': case 'E':
+ case 'f': case 'F':
+ case 'l': case 'L':
+ case 'p': case 'P':
+ case 'u': case 'U':
+ case 'i':
+ case '.':
+ case '_':
+ table[c] |= CMzerosecond | CMdigitsecond;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (c)
+ {
+ case '\\':
+ case '\n':
+ case '\r':
+ case 0:
+ case 0x1A:
+ case '\'':
+ break;
+ default:
+ if (!(c & 0x80))
+ table[c] |= CMsinglechar;
+ break;
+ }
+ }
+ return table;
+}();
diff --git a/gcc/d/dmd/common/charactertables.h b/gcc/d/dmd/common/charactertables.h
new file mode 100644
index 0000000..10a81d3
--- /dev/null
+++ b/gcc/d/dmd/common/charactertables.h
@@ -0,0 +1,29 @@
+/**
+ * Character tables related to identifiers.
+ *
+ * Supports UAX31, C99, C11 and least restrictive (All).
+ *
+ * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
+ * Authors: $(LINK2 https://cattermole.co.nz, Richard (Rikki) Andrew Cattermole)
+ * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/charactertables.d, common/charactertables.d)
+ */
+
+#pragma once
+
+enum class IdentifierTable
+{
+ UAX31,
+ C99,
+ C11,
+ LR, // Least Restrictive aka All
+};
+
+struct IdentifierCharLookup final
+{
+ bool(*isStart)(char32_t);
+ bool(*isContinue)(char32_t);
+
+ // constructor not provided here.
+ static IdentifierCharLookup forTable(IdentifierTable table);
+};
diff --git a/gcc/d/dmd/common/file.d b/gcc/d/dmd/common/file.d
index 80677f6..52da6ee 100644
--- a/gcc/d/dmd/common/file.d
+++ b/gcc/d/dmd/common/file.d
@@ -14,15 +14,23 @@
module dmd.common.file;
+import core.stdc.stdio;
+import core.stdc.stdlib;
+import core.stdc.string;
+import core.stdc.limits;
+
import core.stdc.errno : errno;
import core.stdc.stdio : fprintf, remove, rename, stderr;
import core.stdc.stdlib;
import core.stdc.string : strerror, strlen, memcpy;
import dmd.common.smallbuffer;
+import dmd.root.filename;
+import dmd.root.rmem;
version (Windows)
{
+ import core.stdc.wchar_;
import core.sys.windows.winbase;
import core.sys.windows.winnls : CP_ACP;
import core.sys.windows.winnt;
@@ -32,6 +40,7 @@ version (Windows)
}
else version (Posix)
{
+ import core.sys.posix.dirent;
import core.sys.posix.fcntl;
import core.sys.posix.sys.mman;
import core.sys.posix.sys.stat;
@@ -566,7 +575,7 @@ else version (Windows)
private ulong fileSize(HANDLE fd)
{
ulong result;
- if (GetFileSizeEx(fd, cast(LARGE_INTEGER*) &result) == 0)
+ if (GetFileSizeEx(fd, cast(LARGE_INTEGER*) &result))
return result;
return ulong.max;
}
@@ -587,3 +596,163 @@ private auto ref fakePure(F)(scope F fun) pure
mixin("alias PureFun = " ~ F.stringof ~ " pure;");
return (cast(PureFun) fun)();
}
+
+/***********************************
+ * Recursively search all the directories and files under dir_path
+ * for files that match one of the extensions in exts[].
+ * Pass the matches to sink.
+ * Params:
+ * dir_path = root of directories to search
+ * exts = array of filename extensions to match
+ * recurse = go into subdirectories
+ * filenameSink = accepts the resulting matches
+ * Returns:
+ * true for failed to open the directory
+ */
+bool findFiles(const char* dir_path, const char[][] exts, bool recurse, void delegate(const(char)[]) nothrow filenameSink)
+{
+ enum log = false;
+ if (log) printf("findFiles() dir_path: %s\n", dir_path);
+ version (Windows)
+ {
+ debug
+ enum BufLength = 10; // trigger any reallocation bugs
+ else
+ enum BufLength = 100;
+ char[BufLength + 1] buf = void;
+ char* fullPath = buf.ptr;
+ size_t fullPathLength = BufLength;
+
+ // fullPath = dir_path \ *.*
+ const dir_pathLength = strlen(dir_path);
+ auto count = dir_pathLength + 1 + 3;
+ if (count > fullPathLength)
+ {
+ fullPathLength = count;
+ fullPath = cast(char*)Mem.xrealloc_noscan(fullPath == buf.ptr ? null : fullPath, fullPathLength + 1);
+ }
+ memcpy(fullPath, dir_path, dir_pathLength);
+ strcpy(fullPath + dir_pathLength, "\\*.*".ptr);
+
+ if (log) printf("fullPath: %s\n", fullPath);
+
+ WIN32_FIND_DATAW ffd = void;
+ HANDLE hFind = fullPath[0 .. strlen(fullPath)].extendedPathThen!(p => FindFirstFileW(p.ptr, &ffd));
+ if (hFind == INVALID_HANDLE_VALUE)
+ return true;
+
+ do
+ {
+ if (log) wprintf("ffd.cFileName: %s\n", ffd.cFileName.ptr);
+ if (ffd.cFileName[0] == 0)
+ continue; // ignore
+
+ if (ffd.cFileName[0] == '.')
+ continue; // ignore files that start with a ., also ignore . and .. directories
+
+ const(char)[] name = toNarrowStringz(ffd.cFileName[0 .. wcslen(ffd.cFileName.ptr)], null);
+ if (log) printf("name: %s\n", name.ptr);
+
+ // fullPath = dir_path \ name.ptr
+ count = dir_pathLength + 1 + name.length;
+ if (count > fullPathLength)
+ {
+ fullPathLength = count;
+ fullPath = cast(char*)Mem.xrealloc_noscan(fullPath == buf.ptr ? null : fullPath, fullPathLength + 1);
+ }
+ strcpy(fullPath + dir_pathLength + 1, name.ptr);
+
+ if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ if (recurse)
+ findFiles(fullPath, exts, recurse, filenameSink);
+ }
+ else
+ {
+ const(char)[] nameExt = FileName.ext(name);
+ foreach (ext; exts[])
+ {
+ if (nameExt == ext)
+ {
+ if (log) printf("adding %s\n", fullPath);
+ filenameSink(fullPath[0 .. count]);
+ }
+ }
+ }
+ mem.xfree(cast(void*)name.ptr);
+
+ } while (FindNextFileW(hFind, &ffd) != 0);
+
+ if (fullPath != buf.ptr)
+ mem.xfree(fullPath);
+ FindClose(hFind);
+ if (log) printf("findFiles() exit\n");
+ return false;
+ }
+ else version (Posix)
+ {
+ DIR* dir = opendir(dir_path);
+ if (!dir)
+ return true;
+
+ debug
+ enum BufLength = 10; // trigger any reallocation bugs
+ else
+ enum BufLength = 100;
+ char[BufLength + 1] buf = void;
+ char* fullPath = buf.ptr;
+ size_t fullPathLength = BufLength;
+
+ dirent* entry;
+ while ((entry = readdir(dir)) != null)
+ {
+ //printf("entry: %s\n", entry.d_name.ptr);
+ if (entry.d_name[0] == '.')
+ continue; // ignore files that start with a .
+
+ // fullPath = dir_path / entry.d_name.ptr
+ const dir_pathLength = strlen(dir_path);
+ const count = dir_pathLength + 1 + strlen(entry.d_name.ptr);
+ if (count > fullPathLength)
+ {
+ fullPathLength = count;
+ fullPath = cast(char*)Mem.xrealloc_noscan(fullPath == buf.ptr ? null : fullPath, fullPathLength + 1);
+ }
+ memcpy(fullPath, dir_path, dir_pathLength);
+ fullPath[dir_pathLength] = '/';
+ strcpy(fullPath + dir_pathLength + 1, entry.d_name.ptr);
+
+ stat_t statbuf;
+ if (lstat(fullPath, &statbuf) == -1)
+ continue;
+
+ const(char)[] name = entry.d_name.ptr[0 .. strlen(entry.d_name.ptr)]; // convert to D string
+ if (!name.length)
+ continue; // ignore
+
+ if (S_ISDIR(statbuf.st_mode))
+ {
+ if (recurse && !(name == "." || name == ".."))
+ findFiles(fullPath, exts, recurse, filenameSink);
+ }
+ else if (S_ISREG(statbuf.st_mode))
+ {
+ foreach (ext; exts)
+ {
+ if (FileName.ext(name) == ext)
+ {
+ //printf("%s\n", fullPath);
+ filenameSink(fullPath[0 .. count]);
+ }
+ }
+ }
+ }
+
+ if (fullPath != buf.ptr)
+ mem.xfree(fullPath);
+ closedir(dir);
+ return false;
+ }
+ else
+ static assert(0);
+}
diff --git a/gcc/d/dmd/common/identifiertables.d b/gcc/d/dmd/common/identifiertables.d
new file mode 100644
index 0000000..b87e9fa
--- /dev/null
+++ b/gcc/d/dmd/common/identifiertables.d
@@ -0,0 +1,4241 @@
+// Generated by compiler/tools/unicode_tables.d DO NOT MODIFY!!!
+module dmd.common.identifiertables;
+
+/**
+UAX31 profile Start
+Entries: 136892
+*/
+static immutable dchar[2][] UAX31_Start = [
+ [0xAA, 0xAA],
+ [0xB5, 0xB5],
+ [0xBA, 0xBA],
+ [0xC0, 0xD6],
+ [0xD8, 0xF6],
+ [0xF8, 0x2C1],
+ [0x2C6, 0x2D1],
+ [0x2E0, 0x2E4],
+ [0x2EC, 0x2EC],
+ [0x2EE, 0x2EE],
+ [0x370, 0x374],
+ [0x376, 0x377],
+ [0x37B, 0x37D],
+ [0x37F, 0x37F],
+ [0x386, 0x386],
+ [0x388, 0x38A],
+ [0x38C, 0x38C],
+ [0x38E, 0x3A1],
+ [0x3A3, 0x3F5],
+ [0x3F7, 0x481],
+ [0x48A, 0x52F],
+ [0x531, 0x556],
+ [0x559, 0x559],
+ [0x560, 0x588],
+ [0x5D0, 0x5EA],
+ [0x5EF, 0x5F2],
+ [0x620, 0x64A],
+ [0x66E, 0x66F],
+ [0x671, 0x6D3],
+ [0x6D5, 0x6D5],
+ [0x6E5, 0x6E6],
+ [0x6EE, 0x6EF],
+ [0x6FA, 0x6FC],
+ [0x6FF, 0x6FF],
+ [0x710, 0x710],
+ [0x712, 0x72F],
+ [0x74D, 0x7A5],
+ [0x7B1, 0x7B1],
+ [0x7CA, 0x7EA],
+ [0x7F4, 0x7F5],
+ [0x7FA, 0x7FA],
+ [0x800, 0x815],
+ [0x81A, 0x81A],
+ [0x824, 0x824],
+ [0x828, 0x828],
+ [0x840, 0x858],
+ [0x860, 0x86A],
+ [0x870, 0x887],
+ [0x889, 0x88E],
+ [0x8A0, 0x8C9],
+ [0x904, 0x939],
+ [0x93D, 0x93D],
+ [0x950, 0x950],
+ [0x958, 0x961],
+ [0x971, 0x980],
+ [0x985, 0x98C],
+ [0x98F, 0x990],
+ [0x993, 0x9A8],
+ [0x9AA, 0x9B0],
+ [0x9B2, 0x9B2],
+ [0x9B6, 0x9B9],
+ [0x9BD, 0x9BD],
+ [0x9CE, 0x9CE],
+ [0x9DC, 0x9DD],
+ [0x9DF, 0x9E1],
+ [0x9F0, 0x9F1],
+ [0x9FC, 0x9FC],
+ [0xA05, 0xA0A],
+ [0xA0F, 0xA10],
+ [0xA13, 0xA28],
+ [0xA2A, 0xA30],
+ [0xA32, 0xA33],
+ [0xA35, 0xA36],
+ [0xA38, 0xA39],
+ [0xA59, 0xA5C],
+ [0xA5E, 0xA5E],
+ [0xA72, 0xA74],
+ [0xA85, 0xA8D],
+ [0xA8F, 0xA91],
+ [0xA93, 0xAA8],
+ [0xAAA, 0xAB0],
+ [0xAB2, 0xAB3],
+ [0xAB5, 0xAB9],
+ [0xABD, 0xABD],
+ [0xAD0, 0xAD0],
+ [0xAE0, 0xAE1],
+ [0xAF9, 0xAF9],
+ [0xB05, 0xB0C],
+ [0xB0F, 0xB10],
+ [0xB13, 0xB28],
+ [0xB2A, 0xB30],
+ [0xB32, 0xB33],
+ [0xB35, 0xB39],
+ [0xB3D, 0xB3D],
+ [0xB5C, 0xB5D],
+ [0xB5F, 0xB61],
+ [0xB71, 0xB71],
+ [0xB83, 0xB83],
+ [0xB85, 0xB8A],
+ [0xB8E, 0xB90],
+ [0xB92, 0xB95],
+ [0xB99, 0xB9A],
+ [0xB9C, 0xB9C],
+ [0xB9E, 0xB9F],
+ [0xBA3, 0xBA4],
+ [0xBA8, 0xBAA],
+ [0xBAE, 0xBB9],
+ [0xBD0, 0xBD0],
+ [0xC05, 0xC0C],
+ [0xC0E, 0xC10],
+ [0xC12, 0xC28],
+ [0xC2A, 0xC39],
+ [0xC3D, 0xC3D],
+ [0xC58, 0xC5A],
+ [0xC5D, 0xC5D],
+ [0xC60, 0xC61],
+ [0xC80, 0xC80],
+ [0xC85, 0xC8C],
+ [0xC8E, 0xC90],
+ [0xC92, 0xCA8],
+ [0xCAA, 0xCB3],
+ [0xCB5, 0xCB9],
+ [0xCBD, 0xCBD],
+ [0xCDD, 0xCDE],
+ [0xCE0, 0xCE1],
+ [0xCF1, 0xCF2],
+ [0xD04, 0xD0C],
+ [0xD0E, 0xD10],
+ [0xD12, 0xD3A],
+ [0xD3D, 0xD3D],
+ [0xD4E, 0xD4E],
+ [0xD54, 0xD56],
+ [0xD5F, 0xD61],
+ [0xD7A, 0xD7F],
+ [0xD85, 0xD96],
+ [0xD9A, 0xDB1],
+ [0xDB3, 0xDBB],
+ [0xDBD, 0xDBD],
+ [0xDC0, 0xDC6],
+ [0xE01, 0xE30],
+ [0xE32, 0xE32],
+ [0xE40, 0xE46],
+ [0xE81, 0xE82],
+ [0xE84, 0xE84],
+ [0xE86, 0xE8A],
+ [0xE8C, 0xEA3],
+ [0xEA5, 0xEA5],
+ [0xEA7, 0xEB0],
+ [0xEB2, 0xEB2],
+ [0xEBD, 0xEBD],
+ [0xEC0, 0xEC4],
+ [0xEC6, 0xEC6],
+ [0xEDC, 0xEDF],
+ [0xF00, 0xF00],
+ [0xF40, 0xF47],
+ [0xF49, 0xF6C],
+ [0xF88, 0xF8C],
+ [0x1000, 0x102A],
+ [0x103F, 0x103F],
+ [0x1050, 0x1055],
+ [0x105A, 0x105D],
+ [0x1061, 0x1061],
+ [0x1065, 0x1066],
+ [0x106E, 0x1070],
+ [0x1075, 0x1081],
+ [0x108E, 0x108E],
+ [0x10A0, 0x10C5],
+ [0x10C7, 0x10C7],
+ [0x10CD, 0x10CD],
+ [0x10D0, 0x10FA],
+ [0x10FC, 0x1248],
+ [0x124A, 0x124D],
+ [0x1250, 0x1256],
+ [0x1258, 0x1258],
+ [0x125A, 0x125D],
+ [0x1260, 0x1288],
+ [0x128A, 0x128D],
+ [0x1290, 0x12B0],
+ [0x12B2, 0x12B5],
+ [0x12B8, 0x12BE],
+ [0x12C0, 0x12C0],
+ [0x12C2, 0x12C5],
+ [0x12C8, 0x12D6],
+ [0x12D8, 0x1310],
+ [0x1312, 0x1315],
+ [0x1318, 0x135A],
+ [0x1380, 0x138F],
+ [0x13A0, 0x13F5],
+ [0x13F8, 0x13FD],
+ [0x1401, 0x166C],
+ [0x166F, 0x167F],
+ [0x1681, 0x169A],
+ [0x16A0, 0x16EA],
+ [0x16EE, 0x16F8],
+ [0x1700, 0x1711],
+ [0x171F, 0x1731],
+ [0x1740, 0x1751],
+ [0x1760, 0x176C],
+ [0x176E, 0x1770],
+ [0x1780, 0x17B3],
+ [0x17D7, 0x17D7],
+ [0x17DC, 0x17DC],
+ [0x1820, 0x1878],
+ [0x1880, 0x18A8],
+ [0x18AA, 0x18AA],
+ [0x18B0, 0x18F5],
+ [0x1900, 0x191E],
+ [0x1950, 0x196D],
+ [0x1970, 0x1974],
+ [0x1980, 0x19AB],
+ [0x19B0, 0x19C9],
+ [0x1A00, 0x1A16],
+ [0x1A20, 0x1A54],
+ [0x1AA7, 0x1AA7],
+ [0x1B05, 0x1B33],
+ [0x1B45, 0x1B4C],
+ [0x1B83, 0x1BA0],
+ [0x1BAE, 0x1BAF],
+ [0x1BBA, 0x1BE5],
+ [0x1C00, 0x1C23],
+ [0x1C4D, 0x1C4F],
+ [0x1C5A, 0x1C7D],
+ [0x1C80, 0x1C88],
+ [0x1C90, 0x1CBA],
+ [0x1CBD, 0x1CBF],
+ [0x1CE9, 0x1CEC],
+ [0x1CEE, 0x1CF3],
+ [0x1CF5, 0x1CF6],
+ [0x1CFA, 0x1CFA],
+ [0x1D00, 0x1DBF],
+ [0x1E00, 0x1F15],
+ [0x1F18, 0x1F1D],
+ [0x1F20, 0x1F45],
+ [0x1F48, 0x1F4D],
+ [0x1F50, 0x1F57],
+ [0x1F59, 0x1F59],
+ [0x1F5B, 0x1F5B],
+ [0x1F5D, 0x1F5D],
+ [0x1F5F, 0x1F7D],
+ [0x1F80, 0x1FB4],
+ [0x1FB6, 0x1FBC],
+ [0x1FBE, 0x1FBE],
+ [0x1FC2, 0x1FC4],
+ [0x1FC6, 0x1FCC],
+ [0x1FD0, 0x1FD3],
+ [0x1FD6, 0x1FDB],
+ [0x1FE0, 0x1FEC],
+ [0x1FF2, 0x1FF4],
+ [0x1FF6, 0x1FFC],
+ [0x2071, 0x2071],
+ [0x207F, 0x207F],
+ [0x2090, 0x209C],
+ [0x2102, 0x2102],
+ [0x2107, 0x2107],
+ [0x210A, 0x2113],
+ [0x2115, 0x2115],
+ [0x2118, 0x211D],
+ [0x2124, 0x2124],
+ [0x2126, 0x2126],
+ [0x2128, 0x2128],
+ [0x212A, 0x2139],
+ [0x213C, 0x213F],
+ [0x2145, 0x2149],
+ [0x214E, 0x214E],
+ [0x2160, 0x2188],
+ [0x2C00, 0x2CE4],
+ [0x2CEB, 0x2CEE],
+ [0x2CF2, 0x2CF3],
+ [0x2D00, 0x2D25],
+ [0x2D27, 0x2D27],
+ [0x2D2D, 0x2D2D],
+ [0x2D30, 0x2D67],
+ [0x2D6F, 0x2D6F],
+ [0x2D80, 0x2D96],
+ [0x2DA0, 0x2DA6],
+ [0x2DA8, 0x2DAE],
+ [0x2DB0, 0x2DB6],
+ [0x2DB8, 0x2DBE],
+ [0x2DC0, 0x2DC6],
+ [0x2DC8, 0x2DCE],
+ [0x2DD0, 0x2DD6],
+ [0x2DD8, 0x2DDE],
+ [0x3005, 0x3007],
+ [0x3021, 0x3029],
+ [0x3031, 0x3035],
+ [0x3038, 0x303C],
+ [0x3041, 0x3096],
+ [0x309D, 0x309F],
+ [0x30A1, 0x30FA],
+ [0x30FC, 0x30FF],
+ [0x3105, 0x312F],
+ [0x3131, 0x318E],
+ [0x31A0, 0x31BF],
+ [0x31F0, 0x31FF],
+ [0x3400, 0x4DBF],
+ [0x4E00, 0xA48C],
+ [0xA4D0, 0xA4FD],
+ [0xA500, 0xA60C],
+ [0xA610, 0xA61F],
+ [0xA62A, 0xA62B],
+ [0xA640, 0xA66E],
+ [0xA67F, 0xA69D],
+ [0xA6A0, 0xA6EF],
+ [0xA717, 0xA71F],
+ [0xA722, 0xA788],
+ [0xA78B, 0xA7CA],
+ [0xA7D0, 0xA7D1],
+ [0xA7D3, 0xA7D3],
+ [0xA7D5, 0xA7D9],
+ [0xA7F2, 0xA801],
+ [0xA803, 0xA805],
+ [0xA807, 0xA80A],
+ [0xA80C, 0xA822],
+ [0xA840, 0xA873],
+ [0xA882, 0xA8B3],
+ [0xA8F2, 0xA8F7],
+ [0xA8FB, 0xA8FB],
+ [0xA8FD, 0xA8FE],
+ [0xA90A, 0xA925],
+ [0xA930, 0xA946],
+ [0xA960, 0xA97C],
+ [0xA984, 0xA9B2],
+ [0xA9CF, 0xA9CF],
+ [0xA9E0, 0xA9E4],
+ [0xA9E6, 0xA9EF],
+ [0xA9FA, 0xA9FE],
+ [0xAA00, 0xAA28],
+ [0xAA40, 0xAA42],
+ [0xAA44, 0xAA4B],
+ [0xAA60, 0xAA76],
+ [0xAA7A, 0xAA7A],
+ [0xAA7E, 0xAAAF],
+ [0xAAB1, 0xAAB1],
+ [0xAAB5, 0xAAB6],
+ [0xAAB9, 0xAABD],
+ [0xAAC0, 0xAAC0],
+ [0xAAC2, 0xAAC2],
+ [0xAADB, 0xAADD],
+ [0xAAE0, 0xAAEA],
+ [0xAAF2, 0xAAF4],
+ [0xAB01, 0xAB06],
+ [0xAB09, 0xAB0E],
+ [0xAB11, 0xAB16],
+ [0xAB20, 0xAB26],
+ [0xAB28, 0xAB2E],
+ [0xAB30, 0xAB5A],
+ [0xAB5C, 0xAB69],
+ [0xAB70, 0xABE2],
+ [0xAC00, 0xD7A3],
+ [0xD7B0, 0xD7C6],
+ [0xD7CB, 0xD7FB],
+ [0xF900, 0xFA6D],
+ [0xFA70, 0xFAD9],
+ [0xFB00, 0xFB06],
+ [0xFB13, 0xFB17],
+ [0xFB1D, 0xFB1D],
+ [0xFB1F, 0xFB28],
+ [0xFB2A, 0xFB36],
+ [0xFB38, 0xFB3C],
+ [0xFB3E, 0xFB3E],
+ [0xFB40, 0xFB41],
+ [0xFB43, 0xFB44],
+ [0xFB46, 0xFBB1],
+ [0xFBD3, 0xFC5D],
+ [0xFC64, 0xFD3D],
+ [0xFD50, 0xFD8F],
+ [0xFD92, 0xFDC7],
+ [0xFDF0, 0xFDF9],
+ [0xFE71, 0xFE71],
+ [0xFE73, 0xFE73],
+ [0xFE77, 0xFE77],
+ [0xFE79, 0xFE79],
+ [0xFE7B, 0xFE7B],
+ [0xFE7D, 0xFE7D],
+ [0xFE7F, 0xFEFC],
+ [0xFF21, 0xFF3A],
+ [0xFF41, 0xFF5A],
+ [0xFF66, 0xFF9D],
+ [0xFFA0, 0xFFBE],
+ [0xFFC2, 0xFFC7],
+ [0xFFCA, 0xFFCF],
+ [0xFFD2, 0xFFD7],
+ [0xFFDA, 0xFFDC],
+ [0x10000, 0x1000B],
+ [0x1000D, 0x10026],
+ [0x10028, 0x1003A],
+ [0x1003C, 0x1003D],
+ [0x1003F, 0x1004D],
+ [0x10050, 0x1005D],
+ [0x10080, 0x100FA],
+ [0x10140, 0x10174],
+ [0x10280, 0x1029C],
+ [0x102A0, 0x102D0],
+ [0x10300, 0x1031F],
+ [0x1032D, 0x1034A],
+ [0x10350, 0x10375],
+ [0x10380, 0x1039D],
+ [0x103A0, 0x103C3],
+ [0x103C8, 0x103CF],
+ [0x103D1, 0x103D5],
+ [0x10400, 0x1049D],
+ [0x104B0, 0x104D3],
+ [0x104D8, 0x104FB],
+ [0x10500, 0x10527],
+ [0x10530, 0x10563],
+ [0x10570, 0x1057A],
+ [0x1057C, 0x1058A],
+ [0x1058C, 0x10592],
+ [0x10594, 0x10595],
+ [0x10597, 0x105A1],
+ [0x105A3, 0x105B1],
+ [0x105B3, 0x105B9],
+ [0x105BB, 0x105BC],
+ [0x10600, 0x10736],
+ [0x10740, 0x10755],
+ [0x10760, 0x10767],
+ [0x10780, 0x10785],
+ [0x10787, 0x107B0],
+ [0x107B2, 0x107BA],
+ [0x10800, 0x10805],
+ [0x10808, 0x10808],
+ [0x1080A, 0x10835],
+ [0x10837, 0x10838],
+ [0x1083C, 0x1083C],
+ [0x1083F, 0x10855],
+ [0x10860, 0x10876],
+ [0x10880, 0x1089E],
+ [0x108E0, 0x108F2],
+ [0x108F4, 0x108F5],
+ [0x10900, 0x10915],
+ [0x10920, 0x10939],
+ [0x10980, 0x109B7],
+ [0x109BE, 0x109BF],
+ [0x10A00, 0x10A00],
+ [0x10A10, 0x10A13],
+ [0x10A15, 0x10A17],
+ [0x10A19, 0x10A35],
+ [0x10A60, 0x10A7C],
+ [0x10A80, 0x10A9C],
+ [0x10AC0, 0x10AC7],
+ [0x10AC9, 0x10AE4],
+ [0x10B00, 0x10B35],
+ [0x10B40, 0x10B55],
+ [0x10B60, 0x10B72],
+ [0x10B80, 0x10B91],
+ [0x10C00, 0x10C48],
+ [0x10C80, 0x10CB2],
+ [0x10CC0, 0x10CF2],
+ [0x10D00, 0x10D23],
+ [0x10E80, 0x10EA9],
+ [0x10EB0, 0x10EB1],
+ [0x10F00, 0x10F1C],
+ [0x10F27, 0x10F27],
+ [0x10F30, 0x10F45],
+ [0x10F70, 0x10F81],
+ [0x10FB0, 0x10FC4],
+ [0x10FE0, 0x10FF6],
+ [0x11003, 0x11037],
+ [0x11071, 0x11072],
+ [0x11075, 0x11075],
+ [0x11083, 0x110AF],
+ [0x110D0, 0x110E8],
+ [0x11103, 0x11126],
+ [0x11144, 0x11144],
+ [0x11147, 0x11147],
+ [0x11150, 0x11172],
+ [0x11176, 0x11176],
+ [0x11183, 0x111B2],
+ [0x111C1, 0x111C4],
+ [0x111DA, 0x111DA],
+ [0x111DC, 0x111DC],
+ [0x11200, 0x11211],
+ [0x11213, 0x1122B],
+ [0x1123F, 0x11240],
+ [0x11280, 0x11286],
+ [0x11288, 0x11288],
+ [0x1128A, 0x1128D],
+ [0x1128F, 0x1129D],
+ [0x1129F, 0x112A8],
+ [0x112B0, 0x112DE],
+ [0x11305, 0x1130C],
+ [0x1130F, 0x11310],
+ [0x11313, 0x11328],
+ [0x1132A, 0x11330],
+ [0x11332, 0x11333],
+ [0x11335, 0x11339],
+ [0x1133D, 0x1133D],
+ [0x11350, 0x11350],
+ [0x1135D, 0x11361],
+ [0x11400, 0x11434],
+ [0x11447, 0x1144A],
+ [0x1145F, 0x11461],
+ [0x11480, 0x114AF],
+ [0x114C4, 0x114C5],
+ [0x114C7, 0x114C7],
+ [0x11580, 0x115AE],
+ [0x115D8, 0x115DB],
+ [0x11600, 0x1162F],
+ [0x11644, 0x11644],
+ [0x11680, 0x116AA],
+ [0x116B8, 0x116B8],
+ [0x11700, 0x1171A],
+ [0x11740, 0x11746],
+ [0x11800, 0x1182B],
+ [0x118A0, 0x118DF],
+ [0x118FF, 0x11906],
+ [0x11909, 0x11909],
+ [0x1190C, 0x11913],
+ [0x11915, 0x11916],
+ [0x11918, 0x1192F],
+ [0x1193F, 0x1193F],
+ [0x11941, 0x11941],
+ [0x119A0, 0x119A7],
+ [0x119AA, 0x119D0],
+ [0x119E1, 0x119E1],
+ [0x119E3, 0x119E3],
+ [0x11A00, 0x11A00],
+ [0x11A0B, 0x11A32],
+ [0x11A3A, 0x11A3A],
+ [0x11A50, 0x11A50],
+ [0x11A5C, 0x11A89],
+ [0x11A9D, 0x11A9D],
+ [0x11AB0, 0x11AF8],
+ [0x11C00, 0x11C08],
+ [0x11C0A, 0x11C2E],
+ [0x11C40, 0x11C40],
+ [0x11C72, 0x11C8F],
+ [0x11D00, 0x11D06],
+ [0x11D08, 0x11D09],
+ [0x11D0B, 0x11D30],
+ [0x11D46, 0x11D46],
+ [0x11D60, 0x11D65],
+ [0x11D67, 0x11D68],
+ [0x11D6A, 0x11D89],
+ [0x11D98, 0x11D98],
+ [0x11EE0, 0x11EF2],
+ [0x11F02, 0x11F02],
+ [0x11F04, 0x11F10],
+ [0x11F12, 0x11F33],
+ [0x11FB0, 0x11FB0],
+ [0x12000, 0x12399],
+ [0x12400, 0x1246E],
+ [0x12480, 0x12543],
+ [0x12F90, 0x12FF0],
+ [0x13000, 0x1342F],
+ [0x13441, 0x13446],
+ [0x14400, 0x14646],
+ [0x16800, 0x16A38],
+ [0x16A40, 0x16A5E],
+ [0x16A70, 0x16ABE],
+ [0x16AD0, 0x16AED],
+ [0x16B00, 0x16B2F],
+ [0x16B40, 0x16B43],
+ [0x16B63, 0x16B77],
+ [0x16B7D, 0x16B8F],
+ [0x16E40, 0x16E7F],
+ [0x16F00, 0x16F4A],
+ [0x16F50, 0x16F50],
+ [0x16F93, 0x16F9F],
+ [0x16FE0, 0x16FE1],
+ [0x16FE3, 0x16FE3],
+ [0x17000, 0x187F7],
+ [0x18800, 0x18CD5],
+ [0x18D00, 0x18D08],
+ [0x1AFF0, 0x1AFF3],
+ [0x1AFF5, 0x1AFFB],
+ [0x1AFFD, 0x1AFFE],
+ [0x1B000, 0x1B122],
+ [0x1B132, 0x1B132],
+ [0x1B150, 0x1B152],
+ [0x1B155, 0x1B155],
+ [0x1B164, 0x1B167],
+ [0x1B170, 0x1B2FB],
+ [0x1BC00, 0x1BC6A],
+ [0x1BC70, 0x1BC7C],
+ [0x1BC80, 0x1BC88],
+ [0x1BC90, 0x1BC99],
+ [0x1D400, 0x1D454],
+ [0x1D456, 0x1D49C],
+ [0x1D49E, 0x1D49F],
+ [0x1D4A2, 0x1D4A2],
+ [0x1D4A5, 0x1D4A6],
+ [0x1D4A9, 0x1D4AC],
+ [0x1D4AE, 0x1D4B9],
+ [0x1D4BB, 0x1D4BB],
+ [0x1D4BD, 0x1D4C3],
+ [0x1D4C5, 0x1D505],
+ [0x1D507, 0x1D50A],
+ [0x1D50D, 0x1D514],
+ [0x1D516, 0x1D51C],
+ [0x1D51E, 0x1D539],
+ [0x1D53B, 0x1D53E],
+ [0x1D540, 0x1D544],
+ [0x1D546, 0x1D546],
+ [0x1D54A, 0x1D550],
+ [0x1D552, 0x1D6A5],
+ [0x1D6A8, 0x1D6C0],
+ [0x1D6C2, 0x1D6DA],
+ [0x1D6DC, 0x1D6FA],
+ [0x1D6FC, 0x1D714],
+ [0x1D716, 0x1D734],
+ [0x1D736, 0x1D74E],
+ [0x1D750, 0x1D76E],
+ [0x1D770, 0x1D788],
+ [0x1D78A, 0x1D7A8],
+ [0x1D7AA, 0x1D7C2],
+ [0x1D7C4, 0x1D7CB],
+ [0x1DF00, 0x1DF1E],
+ [0x1DF25, 0x1DF2A],
+ [0x1E030, 0x1E06D],
+ [0x1E100, 0x1E12C],
+ [0x1E137, 0x1E13D],
+ [0x1E14E, 0x1E14E],
+ [0x1E290, 0x1E2AD],
+ [0x1E2C0, 0x1E2EB],
+ [0x1E4D0, 0x1E4EB],
+ [0x1E7E0, 0x1E7E6],
+ [0x1E7E8, 0x1E7EB],
+ [0x1E7ED, 0x1E7EE],
+ [0x1E7F0, 0x1E7FE],
+ [0x1E800, 0x1E8C4],
+ [0x1E900, 0x1E943],
+ [0x1E94B, 0x1E94B],
+ [0x1EE00, 0x1EE03],
+ [0x1EE05, 0x1EE1F],
+ [0x1EE21, 0x1EE22],
+ [0x1EE24, 0x1EE24],
+ [0x1EE27, 0x1EE27],
+ [0x1EE29, 0x1EE32],
+ [0x1EE34, 0x1EE37],
+ [0x1EE39, 0x1EE39],
+ [0x1EE3B, 0x1EE3B],
+ [0x1EE42, 0x1EE42],
+ [0x1EE47, 0x1EE47],
+ [0x1EE49, 0x1EE49],
+ [0x1EE4B, 0x1EE4B],
+ [0x1EE4D, 0x1EE4F],
+ [0x1EE51, 0x1EE52],
+ [0x1EE54, 0x1EE54],
+ [0x1EE57, 0x1EE57],
+ [0x1EE59, 0x1EE59],
+ [0x1EE5B, 0x1EE5B],
+ [0x1EE5D, 0x1EE5D],
+ [0x1EE5F, 0x1EE5F],
+ [0x1EE61, 0x1EE62],
+ [0x1EE64, 0x1EE64],
+ [0x1EE67, 0x1EE6A],
+ [0x1EE6C, 0x1EE72],
+ [0x1EE74, 0x1EE77],
+ [0x1EE79, 0x1EE7C],
+ [0x1EE7E, 0x1EE7E],
+ [0x1EE80, 0x1EE89],
+ [0x1EE8B, 0x1EE9B],
+ [0x1EEA1, 0x1EEA3],
+ [0x1EEA5, 0x1EEA9],
+ [0x1EEAB, 0x1EEBB],
+ [0x20000, 0x2A6DF],
+ [0x2A700, 0x2B739],
+ [0x2B740, 0x2B81D],
+ [0x2B820, 0x2CEA1],
+ [0x2CEB0, 0x2EBE0],
+ [0x2EBF0, 0x2EE5D],
+ [0x2F800, 0x2FA1D],
+ [0x30000, 0x3134A],
+ [0x31350, 0x323AF],
+];
+
+/**
+UAX31 profile Continue
+Entries: 140026
+*/
+static immutable dchar[2][] UAX31_Continue = [
+ [0xAA, 0xAA],
+ [0xB5, 0xB5],
+ [0xB7, 0xB7],
+ [0xBA, 0xBA],
+ [0xC0, 0xD6],
+ [0xD8, 0xF6],
+ [0xF8, 0x2C1],
+ [0x2C6, 0x2D1],
+ [0x2E0, 0x2E4],
+ [0x2EC, 0x2EC],
+ [0x2EE, 0x2EE],
+ [0x300, 0x374],
+ [0x376, 0x377],
+ [0x37B, 0x37D],
+ [0x37F, 0x37F],
+ [0x386, 0x38A],
+ [0x38C, 0x38C],
+ [0x38E, 0x3A1],
+ [0x3A3, 0x3F5],
+ [0x3F7, 0x481],
+ [0x483, 0x487],
+ [0x48A, 0x52F],
+ [0x531, 0x556],
+ [0x559, 0x559],
+ [0x560, 0x588],
+ [0x591, 0x5BD],
+ [0x5BF, 0x5BF],
+ [0x5C1, 0x5C2],
+ [0x5C4, 0x5C5],
+ [0x5C7, 0x5C7],
+ [0x5D0, 0x5EA],
+ [0x5EF, 0x5F2],
+ [0x610, 0x61A],
+ [0x620, 0x669],
+ [0x66E, 0x6D3],
+ [0x6D5, 0x6DC],
+ [0x6DF, 0x6E8],
+ [0x6EA, 0x6FC],
+ [0x6FF, 0x6FF],
+ [0x710, 0x74A],
+ [0x74D, 0x7B1],
+ [0x7C0, 0x7F5],
+ [0x7FA, 0x7FA],
+ [0x7FD, 0x7FD],
+ [0x800, 0x82D],
+ [0x840, 0x85B],
+ [0x860, 0x86A],
+ [0x870, 0x887],
+ [0x889, 0x88E],
+ [0x898, 0x8E1],
+ [0x8E3, 0x963],
+ [0x966, 0x96F],
+ [0x971, 0x983],
+ [0x985, 0x98C],
+ [0x98F, 0x990],
+ [0x993, 0x9A8],
+ [0x9AA, 0x9B0],
+ [0x9B2, 0x9B2],
+ [0x9B6, 0x9B9],
+ [0x9BC, 0x9C4],
+ [0x9C7, 0x9C8],
+ [0x9CB, 0x9CE],
+ [0x9D7, 0x9D7],
+ [0x9DC, 0x9DD],
+ [0x9DF, 0x9E3],
+ [0x9E6, 0x9F1],
+ [0x9FC, 0x9FC],
+ [0x9FE, 0x9FE],
+ [0xA01, 0xA03],
+ [0xA05, 0xA0A],
+ [0xA0F, 0xA10],
+ [0xA13, 0xA28],
+ [0xA2A, 0xA30],
+ [0xA32, 0xA33],
+ [0xA35, 0xA36],
+ [0xA38, 0xA39],
+ [0xA3C, 0xA3C],
+ [0xA3E, 0xA42],
+ [0xA47, 0xA48],
+ [0xA4B, 0xA4D],
+ [0xA51, 0xA51],
+ [0xA59, 0xA5C],
+ [0xA5E, 0xA5E],
+ [0xA66, 0xA75],
+ [0xA81, 0xA83],
+ [0xA85, 0xA8D],
+ [0xA8F, 0xA91],
+ [0xA93, 0xAA8],
+ [0xAAA, 0xAB0],
+ [0xAB2, 0xAB3],
+ [0xAB5, 0xAB9],
+ [0xABC, 0xAC5],
+ [0xAC7, 0xAC9],
+ [0xACB, 0xACD],
+ [0xAD0, 0xAD0],
+ [0xAE0, 0xAE3],
+ [0xAE6, 0xAEF],
+ [0xAF9, 0xAFF],
+ [0xB01, 0xB03],
+ [0xB05, 0xB0C],
+ [0xB0F, 0xB10],
+ [0xB13, 0xB28],
+ [0xB2A, 0xB30],
+ [0xB32, 0xB33],
+ [0xB35, 0xB39],
+ [0xB3C, 0xB44],
+ [0xB47, 0xB48],
+ [0xB4B, 0xB4D],
+ [0xB55, 0xB57],
+ [0xB5C, 0xB5D],
+ [0xB5F, 0xB63],
+ [0xB66, 0xB6F],
+ [0xB71, 0xB71],
+ [0xB82, 0xB83],
+ [0xB85, 0xB8A],
+ [0xB8E, 0xB90],
+ [0xB92, 0xB95],
+ [0xB99, 0xB9A],
+ [0xB9C, 0xB9C],
+ [0xB9E, 0xB9F],
+ [0xBA3, 0xBA4],
+ [0xBA8, 0xBAA],
+ [0xBAE, 0xBB9],
+ [0xBBE, 0xBC2],
+ [0xBC6, 0xBC8],
+ [0xBCA, 0xBCD],
+ [0xBD0, 0xBD0],
+ [0xBD7, 0xBD7],
+ [0xBE6, 0xBEF],
+ [0xC00, 0xC0C],
+ [0xC0E, 0xC10],
+ [0xC12, 0xC28],
+ [0xC2A, 0xC39],
+ [0xC3C, 0xC44],
+ [0xC46, 0xC48],
+ [0xC4A, 0xC4D],
+ [0xC55, 0xC56],
+ [0xC58, 0xC5A],
+ [0xC5D, 0xC5D],
+ [0xC60, 0xC63],
+ [0xC66, 0xC6F],
+ [0xC80, 0xC83],
+ [0xC85, 0xC8C],
+ [0xC8E, 0xC90],
+ [0xC92, 0xCA8],
+ [0xCAA, 0xCB3],
+ [0xCB5, 0xCB9],
+ [0xCBC, 0xCC4],
+ [0xCC6, 0xCC8],
+ [0xCCA, 0xCCD],
+ [0xCD5, 0xCD6],
+ [0xCDD, 0xCDE],
+ [0xCE0, 0xCE3],
+ [0xCE6, 0xCEF],
+ [0xCF1, 0xCF3],
+ [0xD00, 0xD0C],
+ [0xD0E, 0xD10],
+ [0xD12, 0xD44],
+ [0xD46, 0xD48],
+ [0xD4A, 0xD4E],
+ [0xD54, 0xD57],
+ [0xD5F, 0xD63],
+ [0xD66, 0xD6F],
+ [0xD7A, 0xD7F],
+ [0xD81, 0xD83],
+ [0xD85, 0xD96],
+ [0xD9A, 0xDB1],
+ [0xDB3, 0xDBB],
+ [0xDBD, 0xDBD],
+ [0xDC0, 0xDC6],
+ [0xDCA, 0xDCA],
+ [0xDCF, 0xDD4],
+ [0xDD6, 0xDD6],
+ [0xDD8, 0xDDF],
+ [0xDE6, 0xDEF],
+ [0xDF2, 0xDF3],
+ [0xE01, 0xE3A],
+ [0xE40, 0xE4E],
+ [0xE50, 0xE59],
+ [0xE81, 0xE82],
+ [0xE84, 0xE84],
+ [0xE86, 0xE8A],
+ [0xE8C, 0xEA3],
+ [0xEA5, 0xEA5],
+ [0xEA7, 0xEBD],
+ [0xEC0, 0xEC4],
+ [0xEC6, 0xEC6],
+ [0xEC8, 0xECE],
+ [0xED0, 0xED9],
+ [0xEDC, 0xEDF],
+ [0xF00, 0xF00],
+ [0xF18, 0xF19],
+ [0xF20, 0xF29],
+ [0xF35, 0xF35],
+ [0xF37, 0xF37],
+ [0xF39, 0xF39],
+ [0xF3E, 0xF47],
+ [0xF49, 0xF6C],
+ [0xF71, 0xF84],
+ [0xF86, 0xF97],
+ [0xF99, 0xFBC],
+ [0xFC6, 0xFC6],
+ [0x1000, 0x1049],
+ [0x1050, 0x109D],
+ [0x10A0, 0x10C5],
+ [0x10C7, 0x10C7],
+ [0x10CD, 0x10CD],
+ [0x10D0, 0x10FA],
+ [0x10FC, 0x1248],
+ [0x124A, 0x124D],
+ [0x1250, 0x1256],
+ [0x1258, 0x1258],
+ [0x125A, 0x125D],
+ [0x1260, 0x1288],
+ [0x128A, 0x128D],
+ [0x1290, 0x12B0],
+ [0x12B2, 0x12B5],
+ [0x12B8, 0x12BE],
+ [0x12C0, 0x12C0],
+ [0x12C2, 0x12C5],
+ [0x12C8, 0x12D6],
+ [0x12D8, 0x1310],
+ [0x1312, 0x1315],
+ [0x1318, 0x135A],
+ [0x135D, 0x135F],
+ [0x1369, 0x1371],
+ [0x1380, 0x138F],
+ [0x13A0, 0x13F5],
+ [0x13F8, 0x13FD],
+ [0x1401, 0x166C],
+ [0x166F, 0x167F],
+ [0x1681, 0x169A],
+ [0x16A0, 0x16EA],
+ [0x16EE, 0x16F8],
+ [0x1700, 0x1715],
+ [0x171F, 0x1734],
+ [0x1740, 0x1753],
+ [0x1760, 0x176C],
+ [0x176E, 0x1770],
+ [0x1772, 0x1773],
+ [0x1780, 0x17D3],
+ [0x17D7, 0x17D7],
+ [0x17DC, 0x17DD],
+ [0x17E0, 0x17E9],
+ [0x180B, 0x180D],
+ [0x180F, 0x1819],
+ [0x1820, 0x1878],
+ [0x1880, 0x18AA],
+ [0x18B0, 0x18F5],
+ [0x1900, 0x191E],
+ [0x1920, 0x192B],
+ [0x1930, 0x193B],
+ [0x1946, 0x196D],
+ [0x1970, 0x1974],
+ [0x1980, 0x19AB],
+ [0x19B0, 0x19C9],
+ [0x19D0, 0x19DA],
+ [0x1A00, 0x1A1B],
+ [0x1A20, 0x1A5E],
+ [0x1A60, 0x1A7C],
+ [0x1A7F, 0x1A89],
+ [0x1A90, 0x1A99],
+ [0x1AA7, 0x1AA7],
+ [0x1AB0, 0x1ABD],
+ [0x1ABF, 0x1ACE],
+ [0x1B00, 0x1B4C],
+ [0x1B50, 0x1B59],
+ [0x1B6B, 0x1B73],
+ [0x1B80, 0x1BF3],
+ [0x1C00, 0x1C37],
+ [0x1C40, 0x1C49],
+ [0x1C4D, 0x1C7D],
+ [0x1C80, 0x1C88],
+ [0x1C90, 0x1CBA],
+ [0x1CBD, 0x1CBF],
+ [0x1CD0, 0x1CD2],
+ [0x1CD4, 0x1CFA],
+ [0x1D00, 0x1F15],
+ [0x1F18, 0x1F1D],
+ [0x1F20, 0x1F45],
+ [0x1F48, 0x1F4D],
+ [0x1F50, 0x1F57],
+ [0x1F59, 0x1F59],
+ [0x1F5B, 0x1F5B],
+ [0x1F5D, 0x1F5D],
+ [0x1F5F, 0x1F7D],
+ [0x1F80, 0x1FB4],
+ [0x1FB6, 0x1FBC],
+ [0x1FBE, 0x1FBE],
+ [0x1FC2, 0x1FC4],
+ [0x1FC6, 0x1FCC],
+ [0x1FD0, 0x1FD3],
+ [0x1FD6, 0x1FDB],
+ [0x1FE0, 0x1FEC],
+ [0x1FF2, 0x1FF4],
+ [0x1FF6, 0x1FFC],
+ [0x200C, 0x200D],
+ [0x203F, 0x2040],
+ [0x2054, 0x2054],
+ [0x2071, 0x2071],
+ [0x207F, 0x207F],
+ [0x2090, 0x209C],
+ [0x20D0, 0x20DC],
+ [0x20E1, 0x20E1],
+ [0x20E5, 0x20F0],
+ [0x2102, 0x2102],
+ [0x2107, 0x2107],
+ [0x210A, 0x2113],
+ [0x2115, 0x2115],
+ [0x2118, 0x211D],
+ [0x2124, 0x2124],
+ [0x2126, 0x2126],
+ [0x2128, 0x2128],
+ [0x212A, 0x2139],
+ [0x213C, 0x213F],
+ [0x2145, 0x2149],
+ [0x214E, 0x214E],
+ [0x2160, 0x2188],
+ [0x2C00, 0x2CE4],
+ [0x2CEB, 0x2CF3],
+ [0x2D00, 0x2D25],
+ [0x2D27, 0x2D27],
+ [0x2D2D, 0x2D2D],
+ [0x2D30, 0x2D67],
+ [0x2D6F, 0x2D6F],
+ [0x2D7F, 0x2D96],
+ [0x2DA0, 0x2DA6],
+ [0x2DA8, 0x2DAE],
+ [0x2DB0, 0x2DB6],
+ [0x2DB8, 0x2DBE],
+ [0x2DC0, 0x2DC6],
+ [0x2DC8, 0x2DCE],
+ [0x2DD0, 0x2DD6],
+ [0x2DD8, 0x2DDE],
+ [0x2DE0, 0x2DFF],
+ [0x3005, 0x3007],
+ [0x3021, 0x302F],
+ [0x3031, 0x3035],
+ [0x3038, 0x303C],
+ [0x3041, 0x3096],
+ [0x3099, 0x309A],
+ [0x309D, 0x309F],
+ [0x30A1, 0x30FF],
+ [0x3105, 0x312F],
+ [0x3131, 0x318E],
+ [0x31A0, 0x31BF],
+ [0x31F0, 0x31FF],
+ [0x3400, 0x4DBF],
+ [0x4E00, 0xA48C],
+ [0xA4D0, 0xA4FD],
+ [0xA500, 0xA60C],
+ [0xA610, 0xA62B],
+ [0xA640, 0xA66F],
+ [0xA674, 0xA67D],
+ [0xA67F, 0xA6F1],
+ [0xA717, 0xA71F],
+ [0xA722, 0xA788],
+ [0xA78B, 0xA7CA],
+ [0xA7D0, 0xA7D1],
+ [0xA7D3, 0xA7D3],
+ [0xA7D5, 0xA7D9],
+ [0xA7F2, 0xA827],
+ [0xA82C, 0xA82C],
+ [0xA840, 0xA873],
+ [0xA880, 0xA8C5],
+ [0xA8D0, 0xA8D9],
+ [0xA8E0, 0xA8F7],
+ [0xA8FB, 0xA8FB],
+ [0xA8FD, 0xA92D],
+ [0xA930, 0xA953],
+ [0xA960, 0xA97C],
+ [0xA980, 0xA9C0],
+ [0xA9CF, 0xA9D9],
+ [0xA9E0, 0xA9FE],
+ [0xAA00, 0xAA36],
+ [0xAA40, 0xAA4D],
+ [0xAA50, 0xAA59],
+ [0xAA60, 0xAA76],
+ [0xAA7A, 0xAAC2],
+ [0xAADB, 0xAADD],
+ [0xAAE0, 0xAAEF],
+ [0xAAF2, 0xAAF6],
+ [0xAB01, 0xAB06],
+ [0xAB09, 0xAB0E],
+ [0xAB11, 0xAB16],
+ [0xAB20, 0xAB26],
+ [0xAB28, 0xAB2E],
+ [0xAB30, 0xAB5A],
+ [0xAB5C, 0xAB69],
+ [0xAB70, 0xABEA],
+ [0xABEC, 0xABED],
+ [0xABF0, 0xABF9],
+ [0xAC00, 0xD7A3],
+ [0xD7B0, 0xD7C6],
+ [0xD7CB, 0xD7FB],
+ [0xF900, 0xFA6D],
+ [0xFA70, 0xFAD9],
+ [0xFB00, 0xFB06],
+ [0xFB13, 0xFB17],
+ [0xFB1D, 0xFB28],
+ [0xFB2A, 0xFB36],
+ [0xFB38, 0xFB3C],
+ [0xFB3E, 0xFB3E],
+ [0xFB40, 0xFB41],
+ [0xFB43, 0xFB44],
+ [0xFB46, 0xFBB1],
+ [0xFBD3, 0xFC5D],
+ [0xFC64, 0xFD3D],
+ [0xFD50, 0xFD8F],
+ [0xFD92, 0xFDC7],
+ [0xFDF0, 0xFDF9],
+ [0xFE00, 0xFE0F],
+ [0xFE20, 0xFE2F],
+ [0xFE33, 0xFE34],
+ [0xFE4D, 0xFE4F],
+ [0xFE71, 0xFE71],
+ [0xFE73, 0xFE73],
+ [0xFE77, 0xFE77],
+ [0xFE79, 0xFE79],
+ [0xFE7B, 0xFE7B],
+ [0xFE7D, 0xFE7D],
+ [0xFE7F, 0xFEFC],
+ [0xFF10, 0xFF19],
+ [0xFF21, 0xFF3A],
+ [0xFF3F, 0xFF3F],
+ [0xFF41, 0xFF5A],
+ [0xFF65, 0xFFBE],
+ [0xFFC2, 0xFFC7],
+ [0xFFCA, 0xFFCF],
+ [0xFFD2, 0xFFD7],
+ [0xFFDA, 0xFFDC],
+ [0x10000, 0x1000B],
+ [0x1000D, 0x10026],
+ [0x10028, 0x1003A],
+ [0x1003C, 0x1003D],
+ [0x1003F, 0x1004D],
+ [0x10050, 0x1005D],
+ [0x10080, 0x100FA],
+ [0x10140, 0x10174],
+ [0x101FD, 0x101FD],
+ [0x10280, 0x1029C],
+ [0x102A0, 0x102D0],
+ [0x102E0, 0x102E0],
+ [0x10300, 0x1031F],
+ [0x1032D, 0x1034A],
+ [0x10350, 0x1037A],
+ [0x10380, 0x1039D],
+ [0x103A0, 0x103C3],
+ [0x103C8, 0x103CF],
+ [0x103D1, 0x103D5],
+ [0x10400, 0x1049D],
+ [0x104A0, 0x104A9],
+ [0x104B0, 0x104D3],
+ [0x104D8, 0x104FB],
+ [0x10500, 0x10527],
+ [0x10530, 0x10563],
+ [0x10570, 0x1057A],
+ [0x1057C, 0x1058A],
+ [0x1058C, 0x10592],
+ [0x10594, 0x10595],
+ [0x10597, 0x105A1],
+ [0x105A3, 0x105B1],
+ [0x105B3, 0x105B9],
+ [0x105BB, 0x105BC],
+ [0x10600, 0x10736],
+ [0x10740, 0x10755],
+ [0x10760, 0x10767],
+ [0x10780, 0x10785],
+ [0x10787, 0x107B0],
+ [0x107B2, 0x107BA],
+ [0x10800, 0x10805],
+ [0x10808, 0x10808],
+ [0x1080A, 0x10835],
+ [0x10837, 0x10838],
+ [0x1083C, 0x1083C],
+ [0x1083F, 0x10855],
+ [0x10860, 0x10876],
+ [0x10880, 0x1089E],
+ [0x108E0, 0x108F2],
+ [0x108F4, 0x108F5],
+ [0x10900, 0x10915],
+ [0x10920, 0x10939],
+ [0x10980, 0x109B7],
+ [0x109BE, 0x109BF],
+ [0x10A00, 0x10A03],
+ [0x10A05, 0x10A06],
+ [0x10A0C, 0x10A13],
+ [0x10A15, 0x10A17],
+ [0x10A19, 0x10A35],
+ [0x10A38, 0x10A3A],
+ [0x10A3F, 0x10A3F],
+ [0x10A60, 0x10A7C],
+ [0x10A80, 0x10A9C],
+ [0x10AC0, 0x10AC7],
+ [0x10AC9, 0x10AE6],
+ [0x10B00, 0x10B35],
+ [0x10B40, 0x10B55],
+ [0x10B60, 0x10B72],
+ [0x10B80, 0x10B91],
+ [0x10C00, 0x10C48],
+ [0x10C80, 0x10CB2],
+ [0x10CC0, 0x10CF2],
+ [0x10D00, 0x10D27],
+ [0x10D30, 0x10D39],
+ [0x10E80, 0x10EA9],
+ [0x10EAB, 0x10EAC],
+ [0x10EB0, 0x10EB1],
+ [0x10EFD, 0x10F1C],
+ [0x10F27, 0x10F27],
+ [0x10F30, 0x10F50],
+ [0x10F70, 0x10F85],
+ [0x10FB0, 0x10FC4],
+ [0x10FE0, 0x10FF6],
+ [0x11000, 0x11046],
+ [0x11066, 0x11075],
+ [0x1107F, 0x110BA],
+ [0x110C2, 0x110C2],
+ [0x110D0, 0x110E8],
+ [0x110F0, 0x110F9],
+ [0x11100, 0x11134],
+ [0x11136, 0x1113F],
+ [0x11144, 0x11147],
+ [0x11150, 0x11173],
+ [0x11176, 0x11176],
+ [0x11180, 0x111C4],
+ [0x111C9, 0x111CC],
+ [0x111CE, 0x111DA],
+ [0x111DC, 0x111DC],
+ [0x11200, 0x11211],
+ [0x11213, 0x11237],
+ [0x1123E, 0x11241],
+ [0x11280, 0x11286],
+ [0x11288, 0x11288],
+ [0x1128A, 0x1128D],
+ [0x1128F, 0x1129D],
+ [0x1129F, 0x112A8],
+ [0x112B0, 0x112EA],
+ [0x112F0, 0x112F9],
+ [0x11300, 0x11303],
+ [0x11305, 0x1130C],
+ [0x1130F, 0x11310],
+ [0x11313, 0x11328],
+ [0x1132A, 0x11330],
+ [0x11332, 0x11333],
+ [0x11335, 0x11339],
+ [0x1133B, 0x11344],
+ [0x11347, 0x11348],
+ [0x1134B, 0x1134D],
+ [0x11350, 0x11350],
+ [0x11357, 0x11357],
+ [0x1135D, 0x11363],
+ [0x11366, 0x1136C],
+ [0x11370, 0x11374],
+ [0x11400, 0x1144A],
+ [0x11450, 0x11459],
+ [0x1145E, 0x11461],
+ [0x11480, 0x114C5],
+ [0x114C7, 0x114C7],
+ [0x114D0, 0x114D9],
+ [0x11580, 0x115B5],
+ [0x115B8, 0x115C0],
+ [0x115D8, 0x115DD],
+ [0x11600, 0x11640],
+ [0x11644, 0x11644],
+ [0x11650, 0x11659],
+ [0x11680, 0x116B8],
+ [0x116C0, 0x116C9],
+ [0x11700, 0x1171A],
+ [0x1171D, 0x1172B],
+ [0x11730, 0x11739],
+ [0x11740, 0x11746],
+ [0x11800, 0x1183A],
+ [0x118A0, 0x118E9],
+ [0x118FF, 0x11906],
+ [0x11909, 0x11909],
+ [0x1190C, 0x11913],
+ [0x11915, 0x11916],
+ [0x11918, 0x11935],
+ [0x11937, 0x11938],
+ [0x1193B, 0x11943],
+ [0x11950, 0x11959],
+ [0x119A0, 0x119A7],
+ [0x119AA, 0x119D7],
+ [0x119DA, 0x119E1],
+ [0x119E3, 0x119E4],
+ [0x11A00, 0x11A3E],
+ [0x11A47, 0x11A47],
+ [0x11A50, 0x11A99],
+ [0x11A9D, 0x11A9D],
+ [0x11AB0, 0x11AF8],
+ [0x11C00, 0x11C08],
+ [0x11C0A, 0x11C36],
+ [0x11C38, 0x11C40],
+ [0x11C50, 0x11C59],
+ [0x11C72, 0x11C8F],
+ [0x11C92, 0x11CA7],
+ [0x11CA9, 0x11CB6],
+ [0x11D00, 0x11D06],
+ [0x11D08, 0x11D09],
+ [0x11D0B, 0x11D36],
+ [0x11D3A, 0x11D3A],
+ [0x11D3C, 0x11D3D],
+ [0x11D3F, 0x11D47],
+ [0x11D50, 0x11D59],
+ [0x11D60, 0x11D65],
+ [0x11D67, 0x11D68],
+ [0x11D6A, 0x11D8E],
+ [0x11D90, 0x11D91],
+ [0x11D93, 0x11D98],
+ [0x11DA0, 0x11DA9],
+ [0x11EE0, 0x11EF6],
+ [0x11F00, 0x11F10],
+ [0x11F12, 0x11F3A],
+ [0x11F3E, 0x11F42],
+ [0x11F50, 0x11F59],
+ [0x11FB0, 0x11FB0],
+ [0x12000, 0x12399],
+ [0x12400, 0x1246E],
+ [0x12480, 0x12543],
+ [0x12F90, 0x12FF0],
+ [0x13000, 0x1342F],
+ [0x13440, 0x13455],
+ [0x14400, 0x14646],
+ [0x16800, 0x16A38],
+ [0x16A40, 0x16A5E],
+ [0x16A60, 0x16A69],
+ [0x16A70, 0x16ABE],
+ [0x16AC0, 0x16AC9],
+ [0x16AD0, 0x16AED],
+ [0x16AF0, 0x16AF4],
+ [0x16B00, 0x16B36],
+ [0x16B40, 0x16B43],
+ [0x16B50, 0x16B59],
+ [0x16B63, 0x16B77],
+ [0x16B7D, 0x16B8F],
+ [0x16E40, 0x16E7F],
+ [0x16F00, 0x16F4A],
+ [0x16F4F, 0x16F87],
+ [0x16F8F, 0x16F9F],
+ [0x16FE0, 0x16FE1],
+ [0x16FE3, 0x16FE4],
+ [0x16FF0, 0x16FF1],
+ [0x17000, 0x187F7],
+ [0x18800, 0x18CD5],
+ [0x18D00, 0x18D08],
+ [0x1AFF0, 0x1AFF3],
+ [0x1AFF5, 0x1AFFB],
+ [0x1AFFD, 0x1AFFE],
+ [0x1B000, 0x1B122],
+ [0x1B132, 0x1B132],
+ [0x1B150, 0x1B152],
+ [0x1B155, 0x1B155],
+ [0x1B164, 0x1B167],
+ [0x1B170, 0x1B2FB],
+ [0x1BC00, 0x1BC6A],
+ [0x1BC70, 0x1BC7C],
+ [0x1BC80, 0x1BC88],
+ [0x1BC90, 0x1BC99],
+ [0x1BC9D, 0x1BC9E],
+ [0x1CF00, 0x1CF2D],
+ [0x1CF30, 0x1CF46],
+ [0x1D165, 0x1D169],
+ [0x1D16D, 0x1D172],
+ [0x1D17B, 0x1D182],
+ [0x1D185, 0x1D18B],
+ [0x1D1AA, 0x1D1AD],
+ [0x1D242, 0x1D244],
+ [0x1D400, 0x1D454],
+ [0x1D456, 0x1D49C],
+ [0x1D49E, 0x1D49F],
+ [0x1D4A2, 0x1D4A2],
+ [0x1D4A5, 0x1D4A6],
+ [0x1D4A9, 0x1D4AC],
+ [0x1D4AE, 0x1D4B9],
+ [0x1D4BB, 0x1D4BB],
+ [0x1D4BD, 0x1D4C3],
+ [0x1D4C5, 0x1D505],
+ [0x1D507, 0x1D50A],
+ [0x1D50D, 0x1D514],
+ [0x1D516, 0x1D51C],
+ [0x1D51E, 0x1D539],
+ [0x1D53B, 0x1D53E],
+ [0x1D540, 0x1D544],
+ [0x1D546, 0x1D546],
+ [0x1D54A, 0x1D550],
+ [0x1D552, 0x1D6A5],
+ [0x1D6A8, 0x1D6C0],
+ [0x1D6C2, 0x1D6DA],
+ [0x1D6DC, 0x1D6FA],
+ [0x1D6FC, 0x1D714],
+ [0x1D716, 0x1D734],
+ [0x1D736, 0x1D74E],
+ [0x1D750, 0x1D76E],
+ [0x1D770, 0x1D788],
+ [0x1D78A, 0x1D7A8],
+ [0x1D7AA, 0x1D7C2],
+ [0x1D7C4, 0x1D7CB],
+ [0x1D7CE, 0x1D7FF],
+ [0x1DA00, 0x1DA36],
+ [0x1DA3B, 0x1DA6C],
+ [0x1DA75, 0x1DA75],
+ [0x1DA84, 0x1DA84],
+ [0x1DA9B, 0x1DA9F],
+ [0x1DAA1, 0x1DAAF],
+ [0x1DF00, 0x1DF1E],
+ [0x1DF25, 0x1DF2A],
+ [0x1E000, 0x1E006],
+ [0x1E008, 0x1E018],
+ [0x1E01B, 0x1E021],
+ [0x1E023, 0x1E024],
+ [0x1E026, 0x1E02A],
+ [0x1E030, 0x1E06D],
+ [0x1E08F, 0x1E08F],
+ [0x1E100, 0x1E12C],
+ [0x1E130, 0x1E13D],
+ [0x1E140, 0x1E149],
+ [0x1E14E, 0x1E14E],
+ [0x1E290, 0x1E2AE],
+ [0x1E2C0, 0x1E2F9],
+ [0x1E4D0, 0x1E4F9],
+ [0x1E7E0, 0x1E7E6],
+ [0x1E7E8, 0x1E7EB],
+ [0x1E7ED, 0x1E7EE],
+ [0x1E7F0, 0x1E7FE],
+ [0x1E800, 0x1E8C4],
+ [0x1E8D0, 0x1E8D6],
+ [0x1E900, 0x1E94B],
+ [0x1E950, 0x1E959],
+ [0x1EE00, 0x1EE03],
+ [0x1EE05, 0x1EE1F],
+ [0x1EE21, 0x1EE22],
+ [0x1EE24, 0x1EE24],
+ [0x1EE27, 0x1EE27],
+ [0x1EE29, 0x1EE32],
+ [0x1EE34, 0x1EE37],
+ [0x1EE39, 0x1EE39],
+ [0x1EE3B, 0x1EE3B],
+ [0x1EE42, 0x1EE42],
+ [0x1EE47, 0x1EE47],
+ [0x1EE49, 0x1EE49],
+ [0x1EE4B, 0x1EE4B],
+ [0x1EE4D, 0x1EE4F],
+ [0x1EE51, 0x1EE52],
+ [0x1EE54, 0x1EE54],
+ [0x1EE57, 0x1EE57],
+ [0x1EE59, 0x1EE59],
+ [0x1EE5B, 0x1EE5B],
+ [0x1EE5D, 0x1EE5D],
+ [0x1EE5F, 0x1EE5F],
+ [0x1EE61, 0x1EE62],
+ [0x1EE64, 0x1EE64],
+ [0x1EE67, 0x1EE6A],
+ [0x1EE6C, 0x1EE72],
+ [0x1EE74, 0x1EE77],
+ [0x1EE79, 0x1EE7C],
+ [0x1EE7E, 0x1EE7E],
+ [0x1EE80, 0x1EE89],
+ [0x1EE8B, 0x1EE9B],
+ [0x1EEA1, 0x1EEA3],
+ [0x1EEA5, 0x1EEA9],
+ [0x1EEAB, 0x1EEBB],
+ [0x1FBF0, 0x1FBF9],
+ [0x20000, 0x2A6DF],
+ [0x2A700, 0x2B739],
+ [0x2B740, 0x2B81D],
+ [0x2B820, 0x2CEA1],
+ [0x2CEB0, 0x2EBE0],
+ [0x2EBF0, 0x2EE5D],
+ [0x2F800, 0x2FA1D],
+ [0x30000, 0x3134A],
+ [0x31350, 0x323AF],
+ [0xE0100, 0xE01EF],
+];
+
+/**
+C99 Start
+Entries: 34958
+*/
+alias FixedTable_C99_Start = FixedTable_C99_Continue;
+
+/**
+C99 Continue
+Entries: 34958
+*/
+static immutable dchar[2][] FixedTable_C99_Continue = [
+ [0xAA, 0xAA],
+ [0xB5, 0xB5],
+ [0xB7, 0xB7],
+ [0xBA, 0xBA],
+ [0xC0, 0xD6],
+ [0xD8, 0xF6],
+ [0xF8, 0x1F5],
+ [0x1FA, 0x217],
+ [0x250, 0x2A8],
+ [0x2B0, 0x2B8],
+ [0x2BB, 0x2BB],
+ [0x2BD, 0x2C1],
+ [0x2D0, 0x2D1],
+ [0x2E0, 0x2E4],
+ [0x37A, 0x37A],
+ [0x386, 0x386],
+ [0x388, 0x38A],
+ [0x38C, 0x38C],
+ [0x38E, 0x3A1],
+ [0x3A3, 0x3CE],
+ [0x3D0, 0x3D6],
+ [0x3DA, 0x3DA],
+ [0x3DC, 0x3DC],
+ [0x3DE, 0x3DE],
+ [0x3E0, 0x3E0],
+ [0x3E2, 0x3F3],
+ [0x401, 0x40C],
+ [0x40E, 0x44F],
+ [0x451, 0x45C],
+ [0x45E, 0x481],
+ [0x490, 0x4C4],
+ [0x4C7, 0x4C8],
+ [0x4CB, 0x4CC],
+ [0x4D0, 0x4EB],
+ [0x4EE, 0x4F5],
+ [0x4F8, 0x4F9],
+ [0x531, 0x556],
+ [0x559, 0x559],
+ [0x561, 0x587],
+ [0x5B0, 0x5B9],
+ [0x5BB, 0x5BD],
+ [0x5BF, 0x5BF],
+ [0x5C1, 0x5C2],
+ [0x5D0, 0x5EA],
+ [0x5F0, 0x5F2],
+ [0x621, 0x63A],
+ [0x640, 0x652],
+ [0x660, 0x669],
+ [0x670, 0x6B7],
+ [0x6BA, 0x6BE],
+ [0x6C0, 0x6CE],
+ [0x6D0, 0x6DC],
+ [0x6E5, 0x6E8],
+ [0x6EA, 0x6ED],
+ [0x6F0, 0x6F9],
+ [0x901, 0x903],
+ [0x905, 0x939],
+ [0x93D, 0x94D],
+ [0x950, 0x952],
+ [0x958, 0x963],
+ [0x966, 0x96F],
+ [0x981, 0x983],
+ [0x985, 0x98C],
+ [0x98F, 0x990],
+ [0x993, 0x9A8],
+ [0x9AA, 0x9B0],
+ [0x9B2, 0x9B2],
+ [0x9B6, 0x9B9],
+ [0x9BE, 0x9C4],
+ [0x9C7, 0x9C8],
+ [0x9CB, 0x9CD],
+ [0x9DC, 0x9DD],
+ [0x9DF, 0x9E3],
+ [0x9E6, 0x9F1],
+ [0xA02, 0xA02],
+ [0xA05, 0xA0A],
+ [0xA0F, 0xA10],
+ [0xA13, 0xA28],
+ [0xA2A, 0xA30],
+ [0xA32, 0xA33],
+ [0xA35, 0xA36],
+ [0xA38, 0xA39],
+ [0xA3E, 0xA42],
+ [0xA47, 0xA48],
+ [0xA4B, 0xA4D],
+ [0xA59, 0xA5C],
+ [0xA5E, 0xA5E],
+ [0xA66, 0xA6F],
+ [0xA74, 0xA74],
+ [0xA81, 0xA83],
+ [0xA85, 0xA8B],
+ [0xA8D, 0xA8D],
+ [0xA8F, 0xA91],
+ [0xA93, 0xAA8],
+ [0xAAA, 0xAB0],
+ [0xAB2, 0xAB3],
+ [0xAB5, 0xAB9],
+ [0xABD, 0xAC5],
+ [0xAC7, 0xAC9],
+ [0xACB, 0xACD],
+ [0xAD0, 0xAD0],
+ [0xAE0, 0xAE0],
+ [0xAE6, 0xAEF],
+ [0xB01, 0xB03],
+ [0xB05, 0xB0C],
+ [0xB0F, 0xB10],
+ [0xB13, 0xB28],
+ [0xB2A, 0xB30],
+ [0xB32, 0xB33],
+ [0xB36, 0xB39],
+ [0xB3D, 0xB43],
+ [0xB47, 0xB48],
+ [0xB4B, 0xB4D],
+ [0xB5C, 0xB5D],
+ [0xB5F, 0xB61],
+ [0xB66, 0xB6F],
+ [0xB82, 0xB83],
+ [0xB85, 0xB8A],
+ [0xB8E, 0xB90],
+ [0xB92, 0xB95],
+ [0xB99, 0xB9A],
+ [0xB9C, 0xB9C],
+ [0xB9E, 0xB9F],
+ [0xBA3, 0xBA4],
+ [0xBA8, 0xBAA],
+ [0xBAE, 0xBB5],
+ [0xBB7, 0xBB9],
+ [0xBBE, 0xBC2],
+ [0xBC6, 0xBC8],
+ [0xBCA, 0xBCD],
+ [0xBE7, 0xBEF],
+ [0xC01, 0xC03],
+ [0xC05, 0xC0C],
+ [0xC0E, 0xC10],
+ [0xC12, 0xC28],
+ [0xC2A, 0xC33],
+ [0xC35, 0xC39],
+ [0xC3E, 0xC44],
+ [0xC46, 0xC48],
+ [0xC4A, 0xC4D],
+ [0xC60, 0xC61],
+ [0xC66, 0xC6F],
+ [0xC82, 0xC83],
+ [0xC85, 0xC8C],
+ [0xC8E, 0xC90],
+ [0xC92, 0xCA8],
+ [0xCAA, 0xCB3],
+ [0xCB5, 0xCB9],
+ [0xCBE, 0xCC4],
+ [0xCC6, 0xCC8],
+ [0xCCA, 0xCCD],
+ [0xCDE, 0xCDE],
+ [0xCE0, 0xCE1],
+ [0xCE6, 0xCEF],
+ [0xD02, 0xD03],
+ [0xD05, 0xD0C],
+ [0xD0E, 0xD10],
+ [0xD12, 0xD28],
+ [0xD2A, 0xD39],
+ [0xD3E, 0xD43],
+ [0xD46, 0xD48],
+ [0xD4A, 0xD4D],
+ [0xD60, 0xD61],
+ [0xD66, 0xD6F],
+ [0xE01, 0xE3A],
+ [0xE40, 0xE5B],
+ [0xE81, 0xE82],
+ [0xE84, 0xE84],
+ [0xE87, 0xE88],
+ [0xE8A, 0xE8A],
+ [0xE8D, 0xE8D],
+ [0xE94, 0xE97],
+ [0xE99, 0xE9F],
+ [0xEA1, 0xEA3],
+ [0xEA5, 0xEA5],
+ [0xEA7, 0xEA7],
+ [0xEAA, 0xEAB],
+ [0xEAD, 0xEAE],
+ [0xEB0, 0xEB9],
+ [0xEBB, 0xEBD],
+ [0xEC0, 0xEC4],
+ [0xEC6, 0xEC6],
+ [0xEC8, 0xECD],
+ [0xED0, 0xED9],
+ [0xEDC, 0xEDD],
+ [0xF00, 0xF00],
+ [0xF18, 0xF19],
+ [0xF20, 0xF33],
+ [0xF35, 0xF35],
+ [0xF37, 0xF37],
+ [0xF39, 0xF39],
+ [0xF3E, 0xF47],
+ [0xF49, 0xF69],
+ [0xF71, 0xF84],
+ [0xF86, 0xF8B],
+ [0xF90, 0xF95],
+ [0xF97, 0xF97],
+ [0xF99, 0xFAD],
+ [0xFB1, 0xFB7],
+ [0xFB9, 0xFB9],
+ [0x10A0, 0x10C5],
+ [0x10D0, 0x10F6],
+ [0x1E00, 0x1E9B],
+ [0x1EA0, 0x1EF9],
+ [0x1F00, 0x1F15],
+ [0x1F18, 0x1F1D],
+ [0x1F20, 0x1F45],
+ [0x1F48, 0x1F4D],
+ [0x1F50, 0x1F57],
+ [0x1F59, 0x1F59],
+ [0x1F5B, 0x1F5B],
+ [0x1F5D, 0x1F5D],
+ [0x1F5F, 0x1F7D],
+ [0x1F80, 0x1FB4],
+ [0x1FB6, 0x1FBC],
+ [0x1FBE, 0x1FBE],
+ [0x1FC2, 0x1FC4],
+ [0x1FC6, 0x1FCC],
+ [0x1FD0, 0x1FD3],
+ [0x1FD6, 0x1FDB],
+ [0x1FE0, 0x1FEC],
+ [0x1FF2, 0x1FF4],
+ [0x1FF6, 0x1FFC],
+ [0x203F, 0x2040],
+ [0x207F, 0x207F],
+ [0x2102, 0x2102],
+ [0x2107, 0x2107],
+ [0x210A, 0x2113],
+ [0x2115, 0x2115],
+ [0x2118, 0x211D],
+ [0x2124, 0x2124],
+ [0x2126, 0x2126],
+ [0x2128, 0x2128],
+ [0x212A, 0x2131],
+ [0x2133, 0x2138],
+ [0x2160, 0x2182],
+ [0x3005, 0x3007],
+ [0x3021, 0x3029],
+ [0x3041, 0x3093],
+ [0x309B, 0x309C],
+ [0x30A1, 0x30F6],
+ [0x30FB, 0x30FC],
+ [0x3105, 0x312C],
+ [0x4E00, 0x9FA5],
+ [0xAC00, 0xD7A3],
+];
+
+/**
+C11 Start
+Entries: 971620
+*/
+alias FixedTable_C11_Start = FixedTable_C11_Continue;
+
+/**
+C11 Continue
+Entries: 971620
+*/
+static immutable dchar[2][] FixedTable_C11_Continue = [
+ [0xA8, 0xA8],
+ [0xAA, 0xAA],
+ [0xAD, 0xAD],
+ [0xAF, 0xAF],
+ [0xB2, 0xB5],
+ [0xB7, 0xBA],
+ [0xBC, 0xBE],
+ [0xC0, 0xD6],
+ [0xD8, 0xF6],
+ [0xF8, 0xFF],
+ [0x100, 0x167F],
+ [0x1681, 0x180D],
+ [0x180F, 0x1FFF],
+ [0x200B, 0x200D],
+ [0x202A, 0x202E],
+ [0x203F, 0x2040],
+ [0x2054, 0x2054],
+ [0x2060, 0x206F],
+ [0x2070, 0x218F],
+ [0x2460, 0x24FF],
+ [0x2776, 0x2793],
+ [0x2C00, 0x2DFF],
+ [0x2E80, 0x2FFF],
+ [0x3004, 0x3007],
+ [0x3021, 0x302F],
+ [0x3031, 0x303F],
+ [0x3040, 0xD7FF],
+ [0xF900, 0xFD3D],
+ [0xFD40, 0xFDCF],
+ [0xFDF0, 0xFE44],
+ [0xFE47, 0xFFFD],
+ [0x10000, 0x1FFFD],
+ [0x20000, 0x2FFFD],
+ [0x30000, 0x3FFFD],
+ [0x40000, 0x4FFFD],
+ [0x50000, 0x5FFFD],
+ [0x60000, 0x6FFFD],
+ [0x70000, 0x7FFFD],
+ [0x80000, 0x8FFFD],
+ [0x90000, 0x9FFFD],
+ [0xA0000, 0xAFFFD],
+ [0xB0000, 0xBFFFD],
+ [0xC0000, 0xCFFFD],
+ [0xD0000, 0xDFFFD],
+ [0xE0000, 0xEFFFD],
+];
+
+/**
+Least restrictive with both Start and Continue
+Entries: 860486
+*/
+static immutable dchar[2][] LeastRestrictive_OfAll = [
+ [0xA8, 0xA8],
+ [0xAA, 0xAA],
+ [0xAD, 0xAD],
+ [0xAF, 0xAF],
+ [0xB2, 0xB5],
+ [0xB7, 0xBA],
+ [0xBC, 0xBE],
+ [0xC0, 0xD6],
+ [0xD8, 0xF6],
+ [0xF8, 0x217],
+ [0x250, 0x2A8],
+ [0x2B0, 0x2B8],
+ [0x2BB, 0x2BB],
+ [0x2BD, 0x2C1],
+ [0x2C6, 0x2D1],
+ [0x2E0, 0x2E4],
+ [0x2EC, 0x2EC],
+ [0x2EE, 0x2EE],
+ [0x300, 0x374],
+ [0x376, 0x377],
+ [0x37A, 0x37D],
+ [0x37F, 0x37F],
+ [0x386, 0x386],
+ [0x388, 0x38A],
+ [0x38C, 0x38C],
+ [0x38E, 0x3A1],
+ [0x3A3, 0x3D6],
+ [0x3DA, 0x3DA],
+ [0x3DC, 0x3DC],
+ [0x3DE, 0x3DE],
+ [0x3E0, 0x3E0],
+ [0x3E2, 0x3F3],
+ [0x3F7, 0x40C],
+ [0x40E, 0x44F],
+ [0x451, 0x45C],
+ [0x45E, 0x481],
+ [0x483, 0x487],
+ [0x48A, 0x4C4],
+ [0x4C7, 0x4C8],
+ [0x4CB, 0x4CC],
+ [0x4D0, 0x4EB],
+ [0x4EE, 0x4F5],
+ [0x4F8, 0x4F9],
+ [0x531, 0x556],
+ [0x559, 0x559],
+ [0x560, 0x587],
+ [0x591, 0x5B9],
+ [0x5BB, 0x5BD],
+ [0x5BF, 0x5BF],
+ [0x5C1, 0x5C2],
+ [0x5C4, 0x5C5],
+ [0x5C7, 0x5C7],
+ [0x5D0, 0x5EA],
+ [0x5EF, 0x5F2],
+ [0x610, 0x61A],
+ [0x620, 0x63A],
+ [0x640, 0x652],
+ [0x660, 0x669],
+ [0x66E, 0x6BE],
+ [0x6C0, 0x6CE],
+ [0x6D0, 0x6D5],
+ [0x6DF, 0x6E8],
+ [0x6EA, 0x6F9],
+ [0x6FF, 0x6FF],
+ [0x710, 0x710],
+ [0x712, 0x72F],
+ [0x74D, 0x7A5],
+ [0x7B1, 0x7B1],
+ [0x7C0, 0x7EA],
+ [0x7F4, 0x7F5],
+ [0x7FA, 0x7FA],
+ [0x7FD, 0x7FD],
+ [0x800, 0x815],
+ [0x81A, 0x81A],
+ [0x824, 0x824],
+ [0x828, 0x828],
+ [0x840, 0x858],
+ [0x860, 0x86A],
+ [0x870, 0x887],
+ [0x889, 0x88E],
+ [0x898, 0x8C9],
+ [0x8E3, 0x939],
+ [0x93D, 0x94D],
+ [0x950, 0x952],
+ [0x958, 0x963],
+ [0x966, 0x96F],
+ [0x971, 0x983],
+ [0x985, 0x98C],
+ [0x98F, 0x990],
+ [0x993, 0x9A8],
+ [0x9AA, 0x9B0],
+ [0x9B2, 0x9B2],
+ [0x9B6, 0x9B9],
+ [0x9BC, 0x9C4],
+ [0x9C7, 0x9C8],
+ [0x9CB, 0x9CE],
+ [0x9D7, 0x9D7],
+ [0x9DC, 0x9DD],
+ [0x9DF, 0x9E3],
+ [0x9E6, 0x9F1],
+ [0x9FC, 0x9FC],
+ [0x9FE, 0x9FE],
+ [0xA01, 0xA02],
+ [0xA05, 0xA0A],
+ [0xA0F, 0xA10],
+ [0xA13, 0xA28],
+ [0xA2A, 0xA30],
+ [0xA32, 0xA33],
+ [0xA35, 0xA36],
+ [0xA38, 0xA39],
+ [0xA3C, 0xA3C],
+ [0xA3E, 0xA42],
+ [0xA47, 0xA48],
+ [0xA4B, 0xA4D],
+ [0xA51, 0xA51],
+ [0xA59, 0xA5C],
+ [0xA5E, 0xA5E],
+ [0xA66, 0xA6F],
+ [0xA72, 0xA74],
+ [0xA81, 0xA83],
+ [0xA85, 0xA8B],
+ [0xA8D, 0xA8D],
+ [0xA8F, 0xA91],
+ [0xA93, 0xAA8],
+ [0xAAA, 0xAB0],
+ [0xAB2, 0xAB3],
+ [0xAB5, 0xAB9],
+ [0xABC, 0xABD],
+ [0xAC7, 0xAC9],
+ [0xACB, 0xACD],
+ [0xAD0, 0xAD0],
+ [0xAE0, 0xAE0],
+ [0xAE6, 0xAEF],
+ [0xAF9, 0xAFF],
+ [0xB01, 0xB03],
+ [0xB05, 0xB0C],
+ [0xB0F, 0xB10],
+ [0xB13, 0xB28],
+ [0xB2A, 0xB30],
+ [0xB32, 0xB33],
+ [0xB35, 0xB39],
+ [0xB3C, 0xB43],
+ [0xB47, 0xB48],
+ [0xB4B, 0xB4D],
+ [0xB55, 0xB57],
+ [0xB5C, 0xB5D],
+ [0xB5F, 0xB61],
+ [0xB66, 0xB6F],
+ [0xB71, 0xB71],
+ [0xB82, 0xB83],
+ [0xB85, 0xB8A],
+ [0xB8E, 0xB90],
+ [0xB92, 0xB95],
+ [0xB99, 0xB9A],
+ [0xB9C, 0xB9C],
+ [0xB9E, 0xB9F],
+ [0xBA3, 0xBA4],
+ [0xBA8, 0xBAA],
+ [0xBAE, 0xBB5],
+ [0xBB7, 0xBB9],
+ [0xBBE, 0xBC2],
+ [0xBC6, 0xBC8],
+ [0xBCA, 0xBCD],
+ [0xBD0, 0xBD0],
+ [0xBD7, 0xBD7],
+ [0xBE6, 0xBEF],
+ [0xC00, 0xC03],
+ [0xC05, 0xC0C],
+ [0xC0E, 0xC10],
+ [0xC12, 0xC28],
+ [0xC2A, 0xC33],
+ [0xC35, 0xC39],
+ [0xC3C, 0xC44],
+ [0xC46, 0xC48],
+ [0xC4A, 0xC4D],
+ [0xC55, 0xC56],
+ [0xC58, 0xC5A],
+ [0xC5D, 0xC5D],
+ [0xC60, 0xC61],
+ [0xC66, 0xC6F],
+ [0xC80, 0xC83],
+ [0xC85, 0xC8C],
+ [0xC8E, 0xC90],
+ [0xC92, 0xCA8],
+ [0xCAA, 0xCB3],
+ [0xCB5, 0xCB9],
+ [0xCBC, 0xCC4],
+ [0xCC6, 0xCC8],
+ [0xCCA, 0xCCD],
+ [0xCD5, 0xCD6],
+ [0xCDD, 0xCDE],
+ [0xCE0, 0xCE1],
+ [0xCE6, 0xCEF],
+ [0xCF1, 0xCF2],
+ [0xD00, 0xD0C],
+ [0xD0E, 0xD10],
+ [0xD12, 0xD39],
+ [0xD3D, 0xD43],
+ [0xD46, 0xD48],
+ [0xD4A, 0xD4E],
+ [0xD54, 0xD57],
+ [0xD5F, 0xD61],
+ [0xD66, 0xD6F],
+ [0xD7A, 0xD7F],
+ [0xD81, 0xD83],
+ [0xD85, 0xD96],
+ [0xD9A, 0xDB1],
+ [0xDB3, 0xDBB],
+ [0xDBD, 0xDBD],
+ [0xDC0, 0xDC6],
+ [0xDCA, 0xDCA],
+ [0xDCF, 0xDD4],
+ [0xDD6, 0xDD6],
+ [0xDD8, 0xDDF],
+ [0xDE6, 0xDEF],
+ [0xDF2, 0xDF3],
+ [0xE01, 0xE32],
+ [0xE40, 0xE4E],
+ [0xE50, 0xE59],
+ [0xE81, 0xE82],
+ [0xE84, 0xE84],
+ [0xE86, 0xE88],
+ [0xE8A, 0xE8A],
+ [0xE8C, 0xE8D],
+ [0xE94, 0xE97],
+ [0xE99, 0xE9F],
+ [0xEA1, 0xEA3],
+ [0xEA5, 0xEA5],
+ [0xEA7, 0xEAB],
+ [0xEAD, 0xEAE],
+ [0xEB0, 0xEB9],
+ [0xEBB, 0xEBD],
+ [0xEC0, 0xEC4],
+ [0xEC6, 0xEC6],
+ [0xEC8, 0xECE],
+ [0xED0, 0xED9],
+ [0xEDC, 0xEDF],
+ [0xF00, 0xF00],
+ [0xF18, 0xF19],
+ [0xF20, 0xF29],
+ [0xF35, 0xF35],
+ [0xF37, 0xF37],
+ [0xF39, 0xF39],
+ [0xF3E, 0xF47],
+ [0xF49, 0xF6C],
+ [0xF71, 0xF84],
+ [0xF86, 0xF95],
+ [0xF97, 0xF97],
+ [0xF99, 0xFB7],
+ [0xFB9, 0xFB9],
+ [0xFC6, 0xFC6],
+ [0x1000, 0x103F],
+ [0x1050, 0x105D],
+ [0x1061, 0x1061],
+ [0x1065, 0x1066],
+ [0x106E, 0x1070],
+ [0x1075, 0x1081],
+ [0x108E, 0x108E],
+ [0x10A0, 0x10C5],
+ [0x10C7, 0x10C7],
+ [0x10CD, 0x10CD],
+ [0x10D0, 0x10FA],
+ [0x10FC, 0x1248],
+ [0x124A, 0x124D],
+ [0x1250, 0x1256],
+ [0x1258, 0x1258],
+ [0x125A, 0x125D],
+ [0x1260, 0x1288],
+ [0x128A, 0x128D],
+ [0x1290, 0x12B0],
+ [0x12B2, 0x12B5],
+ [0x12B8, 0x12BE],
+ [0x12C0, 0x12C0],
+ [0x12C2, 0x12C5],
+ [0x12C8, 0x12D6],
+ [0x12D8, 0x1310],
+ [0x1312, 0x1315],
+ [0x1318, 0x135A],
+ [0x135D, 0x135F],
+ [0x1369, 0x1371],
+ [0x1380, 0x138F],
+ [0x13A0, 0x13F5],
+ [0x13F8, 0x13FD],
+ [0x1401, 0x166C],
+ [0x166F, 0x167F],
+ [0x1681, 0x169A],
+ [0x16A0, 0x16EA],
+ [0x16EE, 0x16F8],
+ [0x1700, 0x1711],
+ [0x171F, 0x1731],
+ [0x1740, 0x1751],
+ [0x1760, 0x176C],
+ [0x176E, 0x1770],
+ [0x1772, 0x1773],
+ [0x1780, 0x17B3],
+ [0x17D7, 0x17D7],
+ [0x17DC, 0x17DC],
+ [0x17E0, 0x17E9],
+ [0x180B, 0x180D],
+ [0x180F, 0x1878],
+ [0x1880, 0x18A8],
+ [0x18AA, 0x18AA],
+ [0x18B0, 0x18F5],
+ [0x1900, 0x191E],
+ [0x1920, 0x192B],
+ [0x1930, 0x193B],
+ [0x1946, 0x196D],
+ [0x1970, 0x1974],
+ [0x1980, 0x19AB],
+ [0x19B0, 0x19C9],
+ [0x19D0, 0x19DA],
+ [0x1A00, 0x1A16],
+ [0x1A20, 0x1A54],
+ [0x1A60, 0x1A7C],
+ [0x1A7F, 0x1A89],
+ [0x1A90, 0x1A99],
+ [0x1AA7, 0x1AA7],
+ [0x1AB0, 0x1ABD],
+ [0x1ABF, 0x1ACE],
+ [0x1B00, 0x1B33],
+ [0x1B45, 0x1B4C],
+ [0x1B50, 0x1B59],
+ [0x1B6B, 0x1B73],
+ [0x1B80, 0x1BA0],
+ [0x1BAE, 0x1BAF],
+ [0x1BBA, 0x1BE5],
+ [0x1C00, 0x1C37],
+ [0x1C40, 0x1C49],
+ [0x1C4D, 0x1C7D],
+ [0x1C80, 0x1C88],
+ [0x1C90, 0x1CBA],
+ [0x1CBD, 0x1CBF],
+ [0x1CD0, 0x1CD2],
+ [0x1CD4, 0x1CEC],
+ [0x1CEE, 0x1CF3],
+ [0x1CF5, 0x1CF6],
+ [0x1CFA, 0x1CFA],
+ [0x1D00, 0x1EF9],
+ [0x1F00, 0x1F15],
+ [0x1F18, 0x1F1D],
+ [0x1F20, 0x1F45],
+ [0x1F48, 0x1F4D],
+ [0x1F50, 0x1F57],
+ [0x1F59, 0x1F59],
+ [0x1F5B, 0x1F5B],
+ [0x1F5D, 0x1F5D],
+ [0x1F5F, 0x1F7D],
+ [0x1F80, 0x1FB4],
+ [0x1FB6, 0x1FBC],
+ [0x1FBE, 0x1FBE],
+ [0x1FC2, 0x1FC4],
+ [0x1FC6, 0x1FCC],
+ [0x1FD0, 0x1FD3],
+ [0x1FD6, 0x1FDB],
+ [0x1FE0, 0x1FEC],
+ [0x1FF2, 0x1FF4],
+ [0x1FF6, 0x1FFC],
+ [0x200B, 0x200D],
+ [0x202A, 0x202E],
+ [0x203F, 0x2040],
+ [0x2054, 0x2054],
+ [0x2060, 0x2071],
+ [0x207F, 0x207F],
+ [0x2090, 0x209C],
+ [0x20D0, 0x20DC],
+ [0x20E1, 0x20E1],
+ [0x20E5, 0x20F0],
+ [0x2102, 0x2102],
+ [0x2107, 0x2107],
+ [0x210A, 0x2113],
+ [0x2115, 0x2115],
+ [0x2118, 0x211D],
+ [0x2124, 0x2124],
+ [0x2126, 0x2126],
+ [0x2128, 0x2128],
+ [0x212A, 0x2138],
+ [0x213C, 0x213F],
+ [0x2145, 0x2149],
+ [0x214E, 0x214E],
+ [0x2160, 0x2188],
+ [0x2460, 0x24FF],
+ [0x2776, 0x2793],
+ [0x2C00, 0x2CE4],
+ [0x2CEB, 0x2CF3],
+ [0x2D00, 0x2D25],
+ [0x2D27, 0x2D27],
+ [0x2D2D, 0x2D2D],
+ [0x2D30, 0x2D67],
+ [0x2D6F, 0x2D6F],
+ [0x2D7F, 0x2D96],
+ [0x2DA0, 0x2DA6],
+ [0x2DA8, 0x2DAE],
+ [0x2DB0, 0x2DB6],
+ [0x2DB8, 0x2DBE],
+ [0x2DC0, 0x2DC6],
+ [0x2DC8, 0x2DCE],
+ [0x2DD0, 0x2DD6],
+ [0x2DD8, 0x2DDE],
+ [0x2DE0, 0x2DFF],
+ [0x2E80, 0x2FFF],
+ [0x3004, 0x3007],
+ [0x3021, 0x302F],
+ [0x3031, 0x303C],
+ [0x3041, 0x3096],
+ [0x3099, 0x309F],
+ [0x30A1, 0x30FC],
+ [0x3105, 0x312F],
+ [0x3131, 0x318E],
+ [0x31A0, 0x31BF],
+ [0x31F0, 0x31FF],
+ [0x3400, 0x4DBF],
+ [0x4E00, 0xA48C],
+ [0xA4D0, 0xA4FD],
+ [0xA500, 0xA60C],
+ [0xA610, 0xA61F],
+ [0xA62A, 0xA62B],
+ [0xA640, 0xA66F],
+ [0xA674, 0xA67D],
+ [0xA67F, 0xA6EF],
+ [0xA717, 0xA71F],
+ [0xA722, 0xA788],
+ [0xA78B, 0xA7CA],
+ [0xA7D0, 0xA7D1],
+ [0xA7D3, 0xA7D3],
+ [0xA7D5, 0xA7D9],
+ [0xA7F2, 0xA805],
+ [0xA807, 0xA80A],
+ [0xA80C, 0xA822],
+ [0xA82C, 0xA82C],
+ [0xA840, 0xA873],
+ [0xA880, 0xA8B3],
+ [0xA8D0, 0xA8D9],
+ [0xA8E0, 0xA8F7],
+ [0xA8FB, 0xA8FB],
+ [0xA8FD, 0xA8FE],
+ [0xA90A, 0xA925],
+ [0xA930, 0xA946],
+ [0xA960, 0xA97C],
+ [0xA980, 0xA9B2],
+ [0xA9CF, 0xA9CF],
+ [0xA9E0, 0xA9E4],
+ [0xA9E6, 0xA9EF],
+ [0xA9FA, 0xA9FE],
+ [0xAA00, 0xAA28],
+ [0xAA40, 0xAA42],
+ [0xAA44, 0xAA4B],
+ [0xAA50, 0xAA59],
+ [0xAA60, 0xAA76],
+ [0xAA7A, 0xAA7A],
+ [0xAA7E, 0xAAAF],
+ [0xAAB1, 0xAAB1],
+ [0xAAB5, 0xAAB6],
+ [0xAAB9, 0xAABD],
+ [0xAAC0, 0xAAC0],
+ [0xAAC2, 0xAAC2],
+ [0xAADB, 0xAADD],
+ [0xAAE0, 0xAAEA],
+ [0xAAF2, 0xAAF4],
+ [0xAB01, 0xAB06],
+ [0xAB09, 0xAB0E],
+ [0xAB11, 0xAB16],
+ [0xAB20, 0xAB26],
+ [0xAB28, 0xAB2E],
+ [0xAB30, 0xAB5A],
+ [0xAB5C, 0xAB69],
+ [0xAB70, 0xABE2],
+ [0xABEC, 0xABED],
+ [0xABF0, 0xABF9],
+ [0xAC00, 0xD7A3],
+ [0xD7B0, 0xD7C6],
+ [0xD7CB, 0xD7FB],
+ [0xF900, 0xFA6D],
+ [0xFA70, 0xFAD9],
+ [0xFB00, 0xFB06],
+ [0xFB13, 0xFB17],
+ [0xFB1D, 0xFB1D],
+ [0xFB1F, 0xFB28],
+ [0xFB2A, 0xFB36],
+ [0xFB38, 0xFB3C],
+ [0xFB3E, 0xFB3E],
+ [0xFB40, 0xFB41],
+ [0xFB43, 0xFB44],
+ [0xFB46, 0xFBB1],
+ [0xFBD3, 0xFC5D],
+ [0xFC64, 0xFD3D],
+ [0xFD40, 0xFD8F],
+ [0xFD92, 0xFDC7],
+ [0xFDF0, 0xFDF9],
+ [0xFE00, 0xFE0F],
+ [0xFE20, 0xFE2F],
+ [0xFE33, 0xFE34],
+ [0xFE47, 0xFE71],
+ [0xFE73, 0xFE73],
+ [0xFE77, 0xFE77],
+ [0xFE79, 0xFE79],
+ [0xFE7B, 0xFE7B],
+ [0xFE7D, 0xFE7D],
+ [0xFE7F, 0xFEFC],
+ [0xFF10, 0xFF19],
+ [0xFF21, 0xFF3A],
+ [0xFF3F, 0xFF3F],
+ [0xFF41, 0xFF5A],
+ [0xFF65, 0xFF9D],
+ [0xFFA0, 0xFFBE],
+ [0xFFC2, 0xFFC7],
+ [0xFFCA, 0xFFCF],
+ [0xFFD2, 0xFFD7],
+ [0xFFDA, 0xFFDC],
+ [0x10000, 0x1000B],
+ [0x1000D, 0x10026],
+ [0x10028, 0x1003A],
+ [0x1003C, 0x1003D],
+ [0x1003F, 0x1004D],
+ [0x10050, 0x1005D],
+ [0x10080, 0x100FA],
+ [0x10140, 0x10174],
+ [0x101FD, 0x101FD],
+ [0x10280, 0x1029C],
+ [0x102A0, 0x102D0],
+ [0x102E0, 0x102E0],
+ [0x10300, 0x1031F],
+ [0x1032D, 0x1034A],
+ [0x10350, 0x10375],
+ [0x10380, 0x1039D],
+ [0x103A0, 0x103C3],
+ [0x103C8, 0x103CF],
+ [0x103D1, 0x103D5],
+ [0x10400, 0x1049D],
+ [0x104A0, 0x104A9],
+ [0x104B0, 0x104D3],
+ [0x104D8, 0x104FB],
+ [0x10500, 0x10527],
+ [0x10530, 0x10563],
+ [0x10570, 0x1057A],
+ [0x1057C, 0x1058A],
+ [0x1058C, 0x10592],
+ [0x10594, 0x10595],
+ [0x10597, 0x105A1],
+ [0x105A3, 0x105B1],
+ [0x105B3, 0x105B9],
+ [0x105BB, 0x105BC],
+ [0x10600, 0x10736],
+ [0x10740, 0x10755],
+ [0x10760, 0x10767],
+ [0x10780, 0x10785],
+ [0x10787, 0x107B0],
+ [0x107B2, 0x107BA],
+ [0x10800, 0x10805],
+ [0x10808, 0x10808],
+ [0x1080A, 0x10835],
+ [0x10837, 0x10838],
+ [0x1083C, 0x1083C],
+ [0x1083F, 0x10855],
+ [0x10860, 0x10876],
+ [0x10880, 0x1089E],
+ [0x108E0, 0x108F2],
+ [0x108F4, 0x108F5],
+ [0x10900, 0x10915],
+ [0x10920, 0x10939],
+ [0x10980, 0x109B7],
+ [0x109BE, 0x109BF],
+ [0x10A00, 0x10A03],
+ [0x10A05, 0x10A06],
+ [0x10A0C, 0x10A13],
+ [0x10A15, 0x10A17],
+ [0x10A19, 0x10A35],
+ [0x10A38, 0x10A3A],
+ [0x10A3F, 0x10A3F],
+ [0x10A60, 0x10A7C],
+ [0x10A80, 0x10A9C],
+ [0x10AC0, 0x10AC7],
+ [0x10AC9, 0x10AE6],
+ [0x10B00, 0x10B35],
+ [0x10B40, 0x10B55],
+ [0x10B60, 0x10B72],
+ [0x10B80, 0x10B91],
+ [0x10C00, 0x10C48],
+ [0x10C80, 0x10CB2],
+ [0x10CC0, 0x10CF2],
+ [0x10D00, 0x10D23],
+ [0x10D30, 0x10D39],
+ [0x10E80, 0x10EA9],
+ [0x10EAB, 0x10EAC],
+ [0x10EB0, 0x10EB1],
+ [0x10EFD, 0x10F1C],
+ [0x10F27, 0x10F27],
+ [0x10F30, 0x10F45],
+ [0x10F70, 0x10F81],
+ [0x10FB0, 0x10FC4],
+ [0x10FE0, 0x10FF6],
+ [0x11000, 0x11037],
+ [0x11066, 0x11072],
+ [0x11075, 0x11075],
+ [0x1107F, 0x110AF],
+ [0x110C2, 0x110C2],
+ [0x110D0, 0x110E8],
+ [0x110F0, 0x110F9],
+ [0x11100, 0x11126],
+ [0x11136, 0x1113F],
+ [0x11144, 0x11147],
+ [0x11150, 0x11173],
+ [0x11176, 0x11176],
+ [0x11180, 0x111B2],
+ [0x111C1, 0x111C4],
+ [0x111C9, 0x111CC],
+ [0x111CE, 0x111DA],
+ [0x111DC, 0x111DC],
+ [0x11200, 0x11211],
+ [0x11213, 0x11237],
+ [0x1123E, 0x11240],
+ [0x11280, 0x11286],
+ [0x11288, 0x11288],
+ [0x1128A, 0x1128D],
+ [0x1128F, 0x1129D],
+ [0x1129F, 0x112A8],
+ [0x112B0, 0x112EA],
+ [0x112F0, 0x112F9],
+ [0x11300, 0x11303],
+ [0x11305, 0x1130C],
+ [0x1130F, 0x11310],
+ [0x11313, 0x11328],
+ [0x1132A, 0x11330],
+ [0x11332, 0x11333],
+ [0x11335, 0x11339],
+ [0x1133B, 0x1133D],
+ [0x11347, 0x11348],
+ [0x1134B, 0x1134D],
+ [0x11350, 0x11350],
+ [0x11357, 0x11357],
+ [0x1135D, 0x11363],
+ [0x11366, 0x1136C],
+ [0x11370, 0x11374],
+ [0x11400, 0x1144A],
+ [0x11450, 0x11459],
+ [0x1145E, 0x11461],
+ [0x11480, 0x114C5],
+ [0x114C7, 0x114C7],
+ [0x114D0, 0x114D9],
+ [0x11580, 0x115B5],
+ [0x115B8, 0x115C0],
+ [0x115D8, 0x115DD],
+ [0x11600, 0x11640],
+ [0x11644, 0x11644],
+ [0x11650, 0x11659],
+ [0x11680, 0x116B8],
+ [0x116C0, 0x116C9],
+ [0x11700, 0x1171A],
+ [0x1171D, 0x1172B],
+ [0x11730, 0x11739],
+ [0x11740, 0x11746],
+ [0x11800, 0x1183A],
+ [0x118A0, 0x118E9],
+ [0x118FF, 0x11906],
+ [0x11909, 0x11909],
+ [0x1190C, 0x11913],
+ [0x11915, 0x11916],
+ [0x11918, 0x11935],
+ [0x11937, 0x11938],
+ [0x1193B, 0x1193F],
+ [0x11941, 0x11941],
+ [0x11950, 0x11959],
+ [0x119A0, 0x119A7],
+ [0x119AA, 0x119D7],
+ [0x119DA, 0x119E1],
+ [0x119E3, 0x119E3],
+ [0x11A00, 0x11A32],
+ [0x11A3A, 0x11A3A],
+ [0x11A47, 0x11A47],
+ [0x11A50, 0x11A89],
+ [0x11A9D, 0x11A9D],
+ [0x11AB0, 0x11AF8],
+ [0x11C00, 0x11C08],
+ [0x11C0A, 0x11C36],
+ [0x11C38, 0x11C40],
+ [0x11C50, 0x11C59],
+ [0x11C72, 0x11C8F],
+ [0x11C92, 0x11CA7],
+ [0x11CA9, 0x11CB6],
+ [0x11D00, 0x11D06],
+ [0x11D08, 0x11D09],
+ [0x11D0B, 0x11D36],
+ [0x11D3A, 0x11D3A],
+ [0x11D3C, 0x11D3D],
+ [0x11D3F, 0x11D46],
+ [0x11D50, 0x11D59],
+ [0x11D60, 0x11D65],
+ [0x11D67, 0x11D68],
+ [0x11D6A, 0x11D89],
+ [0x11D90, 0x11D91],
+ [0x11D93, 0x11D98],
+ [0x11DA0, 0x11DA9],
+ [0x11EE0, 0x11EF2],
+ [0x11F00, 0x11F02],
+ [0x11F04, 0x11F10],
+ [0x11F12, 0x11F33],
+ [0x11F3E, 0x11F42],
+ [0x11F50, 0x11F59],
+ [0x11FB0, 0x11FB0],
+ [0x12000, 0x12399],
+ [0x12400, 0x1246E],
+ [0x12480, 0x12543],
+ [0x12F90, 0x12FF0],
+ [0x13000, 0x1342F],
+ [0x13440, 0x13446],
+ [0x14400, 0x14646],
+ [0x16800, 0x16A38],
+ [0x16A40, 0x16A5E],
+ [0x16A60, 0x16A69],
+ [0x16A70, 0x16ABE],
+ [0x16AC0, 0x16AC9],
+ [0x16AD0, 0x16AED],
+ [0x16AF0, 0x16AF4],
+ [0x16B00, 0x16B2F],
+ [0x16B40, 0x16B43],
+ [0x16B50, 0x16B59],
+ [0x16B63, 0x16B77],
+ [0x16B7D, 0x16B8F],
+ [0x16E40, 0x16E7F],
+ [0x16F00, 0x16F4A],
+ [0x16F4F, 0x16F50],
+ [0x16F8F, 0x16F9F],
+ [0x16FE0, 0x16FE1],
+ [0x16FE3, 0x16FE3],
+ [0x16FF0, 0x16FF1],
+ [0x17000, 0x187F7],
+ [0x18800, 0x18CD5],
+ [0x18D00, 0x18D08],
+ [0x1AFF0, 0x1AFF3],
+ [0x1AFF5, 0x1AFFB],
+ [0x1AFFD, 0x1AFFE],
+ [0x1B000, 0x1B122],
+ [0x1B132, 0x1B132],
+ [0x1B150, 0x1B152],
+ [0x1B155, 0x1B155],
+ [0x1B164, 0x1B167],
+ [0x1B170, 0x1B2FB],
+ [0x1BC00, 0x1BC6A],
+ [0x1BC70, 0x1BC7C],
+ [0x1BC80, 0x1BC88],
+ [0x1BC90, 0x1BC99],
+ [0x1BC9D, 0x1BC9E],
+ [0x1CF00, 0x1CF2D],
+ [0x1CF30, 0x1CF46],
+ [0x1D165, 0x1D169],
+ [0x1D16D, 0x1D172],
+ [0x1D17B, 0x1D182],
+ [0x1D185, 0x1D18B],
+ [0x1D1AA, 0x1D1AD],
+ [0x1D242, 0x1D244],
+ [0x1D400, 0x1D454],
+ [0x1D456, 0x1D49C],
+ [0x1D49E, 0x1D49F],
+ [0x1D4A2, 0x1D4A2],
+ [0x1D4A5, 0x1D4A6],
+ [0x1D4A9, 0x1D4AC],
+ [0x1D4AE, 0x1D4B9],
+ [0x1D4BB, 0x1D4BB],
+ [0x1D4BD, 0x1D4C3],
+ [0x1D4C5, 0x1D505],
+ [0x1D507, 0x1D50A],
+ [0x1D50D, 0x1D514],
+ [0x1D516, 0x1D51C],
+ [0x1D51E, 0x1D539],
+ [0x1D53B, 0x1D53E],
+ [0x1D540, 0x1D544],
+ [0x1D546, 0x1D546],
+ [0x1D54A, 0x1D550],
+ [0x1D552, 0x1D6A5],
+ [0x1D6A8, 0x1D6C0],
+ [0x1D6C2, 0x1D6DA],
+ [0x1D6DC, 0x1D6FA],
+ [0x1D6FC, 0x1D714],
+ [0x1D716, 0x1D734],
+ [0x1D736, 0x1D74E],
+ [0x1D750, 0x1D76E],
+ [0x1D770, 0x1D788],
+ [0x1D78A, 0x1D7A8],
+ [0x1D7AA, 0x1D7C2],
+ [0x1D7C4, 0x1D7CB],
+ [0x1D7CE, 0x1D7FF],
+ [0x1DA00, 0x1DA36],
+ [0x1DA3B, 0x1DA6C],
+ [0x1DA75, 0x1DA75],
+ [0x1DA84, 0x1DA84],
+ [0x1DA9B, 0x1DA9F],
+ [0x1DAA1, 0x1DAAF],
+ [0x1DF00, 0x1DF1E],
+ [0x1DF25, 0x1DF2A],
+ [0x1E000, 0x1E006],
+ [0x1E008, 0x1E018],
+ [0x1E01B, 0x1E021],
+ [0x1E023, 0x1E024],
+ [0x1E026, 0x1E02A],
+ [0x1E030, 0x1E06D],
+ [0x1E08F, 0x1E08F],
+ [0x1E100, 0x1E12C],
+ [0x1E130, 0x1E13D],
+ [0x1E140, 0x1E149],
+ [0x1E14E, 0x1E14E],
+ [0x1E290, 0x1E2AE],
+ [0x1E2C0, 0x1E2F9],
+ [0x1E4D0, 0x1E4F9],
+ [0x1E7E0, 0x1E7E6],
+ [0x1E7E8, 0x1E7EB],
+ [0x1E7ED, 0x1E7EE],
+ [0x1E7F0, 0x1E7FE],
+ [0x1E800, 0x1E8C4],
+ [0x1E8D0, 0x1E8D6],
+ [0x1E900, 0x1E94B],
+ [0x1E950, 0x1E959],
+ [0x1EE00, 0x1EE03],
+ [0x1EE05, 0x1EE1F],
+ [0x1EE21, 0x1EE22],
+ [0x1EE24, 0x1EE24],
+ [0x1EE27, 0x1EE27],
+ [0x1EE29, 0x1EE32],
+ [0x1EE34, 0x1EE37],
+ [0x1EE39, 0x1EE39],
+ [0x1EE3B, 0x1EE3B],
+ [0x1EE42, 0x1EE42],
+ [0x1EE47, 0x1EE47],
+ [0x1EE49, 0x1EE49],
+ [0x1EE4B, 0x1EE4B],
+ [0x1EE4D, 0x1EE4F],
+ [0x1EE51, 0x1EE52],
+ [0x1EE54, 0x1EE54],
+ [0x1EE57, 0x1EE57],
+ [0x1EE59, 0x1EE59],
+ [0x1EE5B, 0x1EE5B],
+ [0x1EE5D, 0x1EE5D],
+ [0x1EE5F, 0x1EE5F],
+ [0x1EE61, 0x1EE62],
+ [0x1EE64, 0x1EE64],
+ [0x1EE67, 0x1EE6A],
+ [0x1EE6C, 0x1EE72],
+ [0x1EE74, 0x1EE77],
+ [0x1EE79, 0x1EE7C],
+ [0x1EE7E, 0x1EE7E],
+ [0x1EE80, 0x1EE89],
+ [0x1EE8B, 0x1EE9B],
+ [0x1EEA1, 0x1EEA3],
+ [0x1EEA5, 0x1EEA9],
+ [0x1EEAB, 0x1EEBB],
+ [0x1FBF0, 0x1FBF9],
+ [0x20000, 0x2B739],
+ [0x2B740, 0x2B81D],
+ [0x2B820, 0x2CEA1],
+ [0x2CEB0, 0x2EBE0],
+ [0x2EBF0, 0x2EE5D],
+ [0x2F800, 0x2FA1D],
+ [0x30000, 0x323AF],
+ [0x40000, 0x4FFFD],
+ [0x50000, 0x5FFFD],
+ [0x60000, 0x6FFFD],
+ [0x70000, 0x7FFFD],
+ [0x80000, 0x8FFFD],
+ [0x90000, 0x9FFFD],
+ [0xA0000, 0xAFFFD],
+ [0xB0000, 0xBFFFD],
+ [0xC0000, 0xCFFFD],
+ [0xD0000, 0xDFFFD],
+ [0xE0000, 0xEFFFD],
+];
+
+/**
+Least restrictive Start
+Entries: 858717
+*/
+static immutable dchar[2][] LeastRestrictive_Start = [
+ [0xA8, 0xA8],
+ [0xAA, 0xAA],
+ [0xAD, 0xAD],
+ [0xAF, 0xAF],
+ [0xB2, 0xB5],
+ [0xB7, 0xBA],
+ [0xBC, 0xBE],
+ [0xC0, 0xD6],
+ [0xD8, 0xF6],
+ [0xF8, 0x217],
+ [0x250, 0x2A8],
+ [0x2B0, 0x2B8],
+ [0x2BB, 0x2BB],
+ [0x2BD, 0x2C1],
+ [0x2C6, 0x2D1],
+ [0x2E0, 0x2E4],
+ [0x2EC, 0x2EC],
+ [0x2EE, 0x2EE],
+ [0x370, 0x374],
+ [0x376, 0x377],
+ [0x37A, 0x37D],
+ [0x37F, 0x37F],
+ [0x386, 0x386],
+ [0x388, 0x38A],
+ [0x38C, 0x38C],
+ [0x38E, 0x3A1],
+ [0x3A3, 0x3CE],
+ [0x3D0, 0x3D6],
+ [0x3DA, 0x3DA],
+ [0x3DC, 0x3DC],
+ [0x3DE, 0x3DE],
+ [0x3E0, 0x3E0],
+ [0x3E2, 0x3F3],
+ [0x3F7, 0x40C],
+ [0x40E, 0x44F],
+ [0x451, 0x45C],
+ [0x45E, 0x481],
+ [0x48A, 0x4C4],
+ [0x4C7, 0x4C8],
+ [0x4CB, 0x4CC],
+ [0x4D0, 0x4EB],
+ [0x4EE, 0x4F5],
+ [0x4F8, 0x4F9],
+ [0x531, 0x556],
+ [0x559, 0x559],
+ [0x560, 0x587],
+ [0x5B0, 0x5B9],
+ [0x5BB, 0x5BD],
+ [0x5BF, 0x5BF],
+ [0x5C1, 0x5C2],
+ [0x5D0, 0x5EA],
+ [0x5EF, 0x5F2],
+ [0x620, 0x63A],
+ [0x640, 0x652],
+ [0x660, 0x669],
+ [0x66E, 0x6BE],
+ [0x6C0, 0x6CE],
+ [0x6D0, 0x6D5],
+ [0x6E5, 0x6E8],
+ [0x6EA, 0x6FC],
+ [0x6FF, 0x6FF],
+ [0x710, 0x710],
+ [0x712, 0x72F],
+ [0x74D, 0x7A5],
+ [0x7B1, 0x7B1],
+ [0x7CA, 0x7EA],
+ [0x7F4, 0x7F5],
+ [0x7FA, 0x7FA],
+ [0x800, 0x815],
+ [0x81A, 0x81A],
+ [0x824, 0x824],
+ [0x828, 0x828],
+ [0x840, 0x858],
+ [0x860, 0x86A],
+ [0x870, 0x887],
+ [0x889, 0x88E],
+ [0x8A0, 0x8C9],
+ [0x901, 0x939],
+ [0x93D, 0x94D],
+ [0x950, 0x952],
+ [0x958, 0x963],
+ [0x966, 0x96F],
+ [0x971, 0x983],
+ [0x985, 0x98C],
+ [0x98F, 0x990],
+ [0x993, 0x9A8],
+ [0x9AA, 0x9B0],
+ [0x9B2, 0x9B2],
+ [0x9B6, 0x9B9],
+ [0x9BD, 0x9C4],
+ [0x9C7, 0x9C8],
+ [0x9CB, 0x9CE],
+ [0x9DC, 0x9DD],
+ [0x9DF, 0x9E3],
+ [0x9E6, 0x9F1],
+ [0x9FC, 0x9FC],
+ [0xA02, 0xA02],
+ [0xA05, 0xA0A],
+ [0xA0F, 0xA10],
+ [0xA13, 0xA28],
+ [0xA2A, 0xA30],
+ [0xA32, 0xA33],
+ [0xA35, 0xA36],
+ [0xA38, 0xA39],
+ [0xA3E, 0xA42],
+ [0xA47, 0xA48],
+ [0xA4B, 0xA4D],
+ [0xA59, 0xA5C],
+ [0xA5E, 0xA5E],
+ [0xA66, 0xA6F],
+ [0xA72, 0xA74],
+ [0xA81, 0xA83],
+ [0xA85, 0xA8B],
+ [0xA8D, 0xA8D],
+ [0xA8F, 0xA91],
+ [0xA93, 0xAA8],
+ [0xAAA, 0xAB0],
+ [0xAB2, 0xAB3],
+ [0xAB5, 0xAB9],
+ [0xABD, 0xABD],
+ [0xAC7, 0xAC9],
+ [0xACB, 0xACD],
+ [0xAD0, 0xAD0],
+ [0xAE0, 0xAE0],
+ [0xAE6, 0xAEF],
+ [0xAF9, 0xAF9],
+ [0xB01, 0xB03],
+ [0xB05, 0xB0C],
+ [0xB0F, 0xB10],
+ [0xB13, 0xB28],
+ [0xB2A, 0xB30],
+ [0xB32, 0xB33],
+ [0xB35, 0xB39],
+ [0xB3D, 0xB43],
+ [0xB47, 0xB48],
+ [0xB4B, 0xB4D],
+ [0xB5C, 0xB5D],
+ [0xB5F, 0xB61],
+ [0xB66, 0xB6F],
+ [0xB71, 0xB71],
+ [0xB82, 0xB83],
+ [0xB85, 0xB8A],
+ [0xB8E, 0xB90],
+ [0xB92, 0xB95],
+ [0xB99, 0xB9A],
+ [0xB9C, 0xB9C],
+ [0xB9E, 0xB9F],
+ [0xBA3, 0xBA4],
+ [0xBA8, 0xBAA],
+ [0xBAE, 0xBB5],
+ [0xBB7, 0xBB9],
+ [0xBBE, 0xBC2],
+ [0xBC6, 0xBC8],
+ [0xBCA, 0xBCD],
+ [0xBD0, 0xBD0],
+ [0xBE7, 0xBEF],
+ [0xC01, 0xC03],
+ [0xC05, 0xC0C],
+ [0xC0E, 0xC10],
+ [0xC12, 0xC28],
+ [0xC2A, 0xC33],
+ [0xC35, 0xC39],
+ [0xC3D, 0xC44],
+ [0xC46, 0xC48],
+ [0xC4A, 0xC4D],
+ [0xC58, 0xC5A],
+ [0xC5D, 0xC5D],
+ [0xC60, 0xC61],
+ [0xC66, 0xC6F],
+ [0xC80, 0xC80],
+ [0xC82, 0xC83],
+ [0xC85, 0xC8C],
+ [0xC8E, 0xC90],
+ [0xC92, 0xCA8],
+ [0xCAA, 0xCB3],
+ [0xCB5, 0xCB9],
+ [0xCBD, 0xCC4],
+ [0xCC6, 0xCC8],
+ [0xCCA, 0xCCD],
+ [0xCDD, 0xCDE],
+ [0xCE0, 0xCE1],
+ [0xCE6, 0xCEF],
+ [0xCF1, 0xCF2],
+ [0xD02, 0xD0C],
+ [0xD0E, 0xD10],
+ [0xD12, 0xD28],
+ [0xD2A, 0xD39],
+ [0xD3D, 0xD43],
+ [0xD46, 0xD48],
+ [0xD4A, 0xD4E],
+ [0xD54, 0xD56],
+ [0xD5F, 0xD61],
+ [0xD66, 0xD6F],
+ [0xD7A, 0xD7F],
+ [0xD85, 0xD96],
+ [0xD9A, 0xDB1],
+ [0xDB3, 0xDBB],
+ [0xDBD, 0xDBD],
+ [0xDC0, 0xDC6],
+ [0xE01, 0xE30],
+ [0xE32, 0xE32],
+ [0xE40, 0xE5B],
+ [0xE81, 0xE82],
+ [0xE84, 0xE84],
+ [0xE86, 0xE88],
+ [0xE8A, 0xE8A],
+ [0xE8C, 0xE8D],
+ [0xE94, 0xE97],
+ [0xE99, 0xE9F],
+ [0xEA1, 0xEA3],
+ [0xEA5, 0xEA5],
+ [0xEA7, 0xEAB],
+ [0xEAD, 0xEAE],
+ [0xEB0, 0xEB2],
+ [0xEBB, 0xEBD],
+ [0xEC0, 0xEC4],
+ [0xEC6, 0xEC6],
+ [0xEC8, 0xECD],
+ [0xED0, 0xED9],
+ [0xEDC, 0xEDD],
+ [0xF00, 0xF00],
+ [0xF18, 0xF19],
+ [0xF20, 0xF33],
+ [0xF35, 0xF35],
+ [0xF37, 0xF37],
+ [0xF39, 0xF39],
+ [0xF3E, 0xF47],
+ [0xF49, 0xF69],
+ [0xF71, 0xF84],
+ [0xF86, 0xF8C],
+ [0xF90, 0xF95],
+ [0xF97, 0xF97],
+ [0xF99, 0xFAD],
+ [0xFB1, 0xFB7],
+ [0xFB9, 0xFB9],
+ [0x1000, 0x102A],
+ [0x103F, 0x103F],
+ [0x1050, 0x1055],
+ [0x105A, 0x105D],
+ [0x1061, 0x1061],
+ [0x1065, 0x1066],
+ [0x106E, 0x1070],
+ [0x1075, 0x1081],
+ [0x108E, 0x108E],
+ [0x10A0, 0x10C5],
+ [0x10C7, 0x10C7],
+ [0x10CD, 0x10CD],
+ [0x10D0, 0x10FA],
+ [0x10FC, 0x1248],
+ [0x124A, 0x124D],
+ [0x1250, 0x1256],
+ [0x1258, 0x1258],
+ [0x125A, 0x125D],
+ [0x1260, 0x1288],
+ [0x128A, 0x128D],
+ [0x1290, 0x12B0],
+ [0x12B2, 0x12B5],
+ [0x12B8, 0x12BE],
+ [0x12C0, 0x12C0],
+ [0x12C2, 0x12C5],
+ [0x12C8, 0x12D6],
+ [0x12D8, 0x1310],
+ [0x1312, 0x1315],
+ [0x1318, 0x135A],
+ [0x1380, 0x138F],
+ [0x13A0, 0x13F5],
+ [0x13F8, 0x13FD],
+ [0x1401, 0x166C],
+ [0x166F, 0x167F],
+ [0x1681, 0x169A],
+ [0x16A0, 0x16EA],
+ [0x16EE, 0x16F8],
+ [0x1700, 0x1711],
+ [0x171F, 0x1731],
+ [0x1740, 0x1751],
+ [0x1760, 0x176C],
+ [0x176E, 0x1770],
+ [0x1780, 0x17B3],
+ [0x17D7, 0x17D7],
+ [0x17DC, 0x17DC],
+ [0x180F, 0x1878],
+ [0x1880, 0x18A8],
+ [0x18AA, 0x18AA],
+ [0x18B0, 0x18F5],
+ [0x1900, 0x191E],
+ [0x1950, 0x196D],
+ [0x1970, 0x1974],
+ [0x1980, 0x19AB],
+ [0x19B0, 0x19C9],
+ [0x1A00, 0x1A16],
+ [0x1A20, 0x1A54],
+ [0x1AA7, 0x1AA7],
+ [0x1B05, 0x1B33],
+ [0x1B45, 0x1B4C],
+ [0x1B83, 0x1BA0],
+ [0x1BAE, 0x1BAF],
+ [0x1BBA, 0x1BE5],
+ [0x1C00, 0x1C23],
+ [0x1C4D, 0x1C4F],
+ [0x1C5A, 0x1C7D],
+ [0x1C80, 0x1C88],
+ [0x1C90, 0x1CBA],
+ [0x1CBD, 0x1CBF],
+ [0x1CE9, 0x1CEC],
+ [0x1CEE, 0x1CF3],
+ [0x1CF5, 0x1CF6],
+ [0x1CFA, 0x1CFA],
+ [0x1D00, 0x1DBF],
+ [0x1E00, 0x1EF9],
+ [0x1F00, 0x1F15],
+ [0x1F18, 0x1F1D],
+ [0x1F20, 0x1F45],
+ [0x1F48, 0x1F4D],
+ [0x1F50, 0x1F57],
+ [0x1F59, 0x1F59],
+ [0x1F5B, 0x1F5B],
+ [0x1F5D, 0x1F5D],
+ [0x1F5F, 0x1F7D],
+ [0x1F80, 0x1FB4],
+ [0x1FB6, 0x1FBC],
+ [0x1FBE, 0x1FBE],
+ [0x1FC2, 0x1FC4],
+ [0x1FC6, 0x1FCC],
+ [0x1FD0, 0x1FD3],
+ [0x1FD6, 0x1FDB],
+ [0x1FE0, 0x1FEC],
+ [0x1FF2, 0x1FF4],
+ [0x1FF6, 0x1FFC],
+ [0x200B, 0x200D],
+ [0x202A, 0x202E],
+ [0x203F, 0x2040],
+ [0x2054, 0x2054],
+ [0x2060, 0x2071],
+ [0x207F, 0x207F],
+ [0x2090, 0x209C],
+ [0x2102, 0x2102],
+ [0x2107, 0x2107],
+ [0x210A, 0x2113],
+ [0x2115, 0x2115],
+ [0x2118, 0x211D],
+ [0x2124, 0x2124],
+ [0x2126, 0x2126],
+ [0x2128, 0x2128],
+ [0x212A, 0x2138],
+ [0x213C, 0x213F],
+ [0x2145, 0x2149],
+ [0x214E, 0x214E],
+ [0x2160, 0x2188],
+ [0x2460, 0x24FF],
+ [0x2776, 0x2793],
+ [0x2C00, 0x2CE4],
+ [0x2CEB, 0x2CEE],
+ [0x2CF2, 0x2CF3],
+ [0x2D00, 0x2D25],
+ [0x2D27, 0x2D27],
+ [0x2D2D, 0x2D2D],
+ [0x2D30, 0x2D67],
+ [0x2D6F, 0x2D6F],
+ [0x2D80, 0x2D96],
+ [0x2DA0, 0x2DA6],
+ [0x2DA8, 0x2DAE],
+ [0x2DB0, 0x2DB6],
+ [0x2DB8, 0x2DBE],
+ [0x2DC0, 0x2DC6],
+ [0x2DC8, 0x2DCE],
+ [0x2DD0, 0x2DD6],
+ [0x2DD8, 0x2DDE],
+ [0x2E80, 0x2FFF],
+ [0x3004, 0x3007],
+ [0x3021, 0x3029],
+ [0x3031, 0x3035],
+ [0x3038, 0x303C],
+ [0x3041, 0x3096],
+ [0x309B, 0x309F],
+ [0x30A1, 0x30FF],
+ [0x3105, 0x312F],
+ [0x3131, 0x318E],
+ [0x31A0, 0x31BF],
+ [0x31F0, 0x31FF],
+ [0x3400, 0x4DBF],
+ [0x4E00, 0xA48C],
+ [0xA4D0, 0xA4FD],
+ [0xA500, 0xA60C],
+ [0xA610, 0xA61F],
+ [0xA62A, 0xA62B],
+ [0xA640, 0xA66E],
+ [0xA67F, 0xA69D],
+ [0xA6A0, 0xA6EF],
+ [0xA717, 0xA71F],
+ [0xA722, 0xA788],
+ [0xA78B, 0xA7CA],
+ [0xA7D0, 0xA7D1],
+ [0xA7D3, 0xA7D3],
+ [0xA7D5, 0xA7D9],
+ [0xA7F2, 0xA801],
+ [0xA803, 0xA805],
+ [0xA807, 0xA80A],
+ [0xA80C, 0xA822],
+ [0xA840, 0xA873],
+ [0xA882, 0xA8B3],
+ [0xA8F2, 0xA8F7],
+ [0xA8FB, 0xA8FB],
+ [0xA8FD, 0xA8FE],
+ [0xA90A, 0xA925],
+ [0xA930, 0xA946],
+ [0xA960, 0xA97C],
+ [0xA984, 0xA9B2],
+ [0xA9CF, 0xA9CF],
+ [0xA9E0, 0xA9E4],
+ [0xA9E6, 0xA9EF],
+ [0xA9FA, 0xA9FE],
+ [0xAA00, 0xAA28],
+ [0xAA40, 0xAA42],
+ [0xAA44, 0xAA4B],
+ [0xAA60, 0xAA76],
+ [0xAA7A, 0xAA7A],
+ [0xAA7E, 0xAAAF],
+ [0xAAB1, 0xAAB1],
+ [0xAAB5, 0xAAB6],
+ [0xAAB9, 0xAABD],
+ [0xAAC0, 0xAAC0],
+ [0xAAC2, 0xAAC2],
+ [0xAADB, 0xAADD],
+ [0xAAE0, 0xAAEA],
+ [0xAAF2, 0xAAF4],
+ [0xAB01, 0xAB06],
+ [0xAB09, 0xAB0E],
+ [0xAB11, 0xAB16],
+ [0xAB20, 0xAB26],
+ [0xAB28, 0xAB2E],
+ [0xAB30, 0xAB5A],
+ [0xAB5C, 0xAB69],
+ [0xAB70, 0xABE2],
+ [0xAC00, 0xD7A3],
+ [0xD7B0, 0xD7C6],
+ [0xD7CB, 0xD7FB],
+ [0xF900, 0xFA6D],
+ [0xFA70, 0xFAD9],
+ [0xFB00, 0xFB06],
+ [0xFB13, 0xFB17],
+ [0xFB1D, 0xFB1D],
+ [0xFB1F, 0xFB28],
+ [0xFB2A, 0xFB36],
+ [0xFB38, 0xFB3C],
+ [0xFB3E, 0xFB3E],
+ [0xFB40, 0xFB41],
+ [0xFB43, 0xFB44],
+ [0xFB46, 0xFBB1],
+ [0xFBD3, 0xFC5D],
+ [0xFC64, 0xFD3D],
+ [0xFD40, 0xFD8F],
+ [0xFD92, 0xFDC7],
+ [0xFDF0, 0xFDF9],
+ [0xFE47, 0xFE71],
+ [0xFE73, 0xFE73],
+ [0xFE77, 0xFE77],
+ [0xFE79, 0xFE79],
+ [0xFE7B, 0xFE7B],
+ [0xFE7D, 0xFE7D],
+ [0xFE7F, 0xFEFC],
+ [0xFF21, 0xFF3A],
+ [0xFF41, 0xFF5A],
+ [0xFF66, 0xFF9D],
+ [0xFFA0, 0xFFBE],
+ [0xFFC2, 0xFFC7],
+ [0xFFCA, 0xFFCF],
+ [0xFFD2, 0xFFD7],
+ [0xFFDA, 0xFFDC],
+ [0x10000, 0x1000B],
+ [0x1000D, 0x10026],
+ [0x10028, 0x1003A],
+ [0x1003C, 0x1003D],
+ [0x1003F, 0x1004D],
+ [0x10050, 0x1005D],
+ [0x10080, 0x100FA],
+ [0x10140, 0x10174],
+ [0x10280, 0x1029C],
+ [0x102A0, 0x102D0],
+ [0x10300, 0x1031F],
+ [0x1032D, 0x1034A],
+ [0x10350, 0x10375],
+ [0x10380, 0x1039D],
+ [0x103A0, 0x103C3],
+ [0x103C8, 0x103CF],
+ [0x103D1, 0x103D5],
+ [0x10400, 0x1049D],
+ [0x104B0, 0x104D3],
+ [0x104D8, 0x104FB],
+ [0x10500, 0x10527],
+ [0x10530, 0x10563],
+ [0x10570, 0x1057A],
+ [0x1057C, 0x1058A],
+ [0x1058C, 0x10592],
+ [0x10594, 0x10595],
+ [0x10597, 0x105A1],
+ [0x105A3, 0x105B1],
+ [0x105B3, 0x105B9],
+ [0x105BB, 0x105BC],
+ [0x10600, 0x10736],
+ [0x10740, 0x10755],
+ [0x10760, 0x10767],
+ [0x10780, 0x10785],
+ [0x10787, 0x107B0],
+ [0x107B2, 0x107BA],
+ [0x10800, 0x10805],
+ [0x10808, 0x10808],
+ [0x1080A, 0x10835],
+ [0x10837, 0x10838],
+ [0x1083C, 0x1083C],
+ [0x1083F, 0x10855],
+ [0x10860, 0x10876],
+ [0x10880, 0x1089E],
+ [0x108E0, 0x108F2],
+ [0x108F4, 0x108F5],
+ [0x10900, 0x10915],
+ [0x10920, 0x10939],
+ [0x10980, 0x109B7],
+ [0x109BE, 0x109BF],
+ [0x10A00, 0x10A00],
+ [0x10A10, 0x10A13],
+ [0x10A15, 0x10A17],
+ [0x10A19, 0x10A35],
+ [0x10A60, 0x10A7C],
+ [0x10A80, 0x10A9C],
+ [0x10AC0, 0x10AC7],
+ [0x10AC9, 0x10AE4],
+ [0x10B00, 0x10B35],
+ [0x10B40, 0x10B55],
+ [0x10B60, 0x10B72],
+ [0x10B80, 0x10B91],
+ [0x10C00, 0x10C48],
+ [0x10C80, 0x10CB2],
+ [0x10CC0, 0x10CF2],
+ [0x10D00, 0x10D23],
+ [0x10E80, 0x10EA9],
+ [0x10EB0, 0x10EB1],
+ [0x10F00, 0x10F1C],
+ [0x10F27, 0x10F27],
+ [0x10F30, 0x10F45],
+ [0x10F70, 0x10F81],
+ [0x10FB0, 0x10FC4],
+ [0x10FE0, 0x10FF6],
+ [0x11003, 0x11037],
+ [0x11071, 0x11072],
+ [0x11075, 0x11075],
+ [0x11083, 0x110AF],
+ [0x110D0, 0x110E8],
+ [0x11103, 0x11126],
+ [0x11144, 0x11144],
+ [0x11147, 0x11147],
+ [0x11150, 0x11172],
+ [0x11176, 0x11176],
+ [0x11183, 0x111B2],
+ [0x111C1, 0x111C4],
+ [0x111DA, 0x111DA],
+ [0x111DC, 0x111DC],
+ [0x11200, 0x11211],
+ [0x11213, 0x1122B],
+ [0x1123F, 0x11240],
+ [0x11280, 0x11286],
+ [0x11288, 0x11288],
+ [0x1128A, 0x1128D],
+ [0x1128F, 0x1129D],
+ [0x1129F, 0x112A8],
+ [0x112B0, 0x112DE],
+ [0x11305, 0x1130C],
+ [0x1130F, 0x11310],
+ [0x11313, 0x11328],
+ [0x1132A, 0x11330],
+ [0x11332, 0x11333],
+ [0x11335, 0x11339],
+ [0x1133D, 0x1133D],
+ [0x11350, 0x11350],
+ [0x1135D, 0x11361],
+ [0x11400, 0x11434],
+ [0x11447, 0x1144A],
+ [0x1145F, 0x11461],
+ [0x11480, 0x114AF],
+ [0x114C4, 0x114C5],
+ [0x114C7, 0x114C7],
+ [0x11580, 0x115AE],
+ [0x115D8, 0x115DB],
+ [0x11600, 0x1162F],
+ [0x11644, 0x11644],
+ [0x11680, 0x116AA],
+ [0x116B8, 0x116B8],
+ [0x11700, 0x1171A],
+ [0x11740, 0x11746],
+ [0x11800, 0x1182B],
+ [0x118A0, 0x118DF],
+ [0x118FF, 0x11906],
+ [0x11909, 0x11909],
+ [0x1190C, 0x11913],
+ [0x11915, 0x11916],
+ [0x11918, 0x1192F],
+ [0x1193F, 0x1193F],
+ [0x11941, 0x11941],
+ [0x119A0, 0x119A7],
+ [0x119AA, 0x119D0],
+ [0x119E1, 0x119E1],
+ [0x119E3, 0x119E3],
+ [0x11A00, 0x11A00],
+ [0x11A0B, 0x11A32],
+ [0x11A3A, 0x11A3A],
+ [0x11A50, 0x11A50],
+ [0x11A5C, 0x11A89],
+ [0x11A9D, 0x11A9D],
+ [0x11AB0, 0x11AF8],
+ [0x11C00, 0x11C08],
+ [0x11C0A, 0x11C2E],
+ [0x11C40, 0x11C40],
+ [0x11C72, 0x11C8F],
+ [0x11D00, 0x11D06],
+ [0x11D08, 0x11D09],
+ [0x11D0B, 0x11D30],
+ [0x11D46, 0x11D46],
+ [0x11D60, 0x11D65],
+ [0x11D67, 0x11D68],
+ [0x11D6A, 0x11D89],
+ [0x11D98, 0x11D98],
+ [0x11EE0, 0x11EF2],
+ [0x11F02, 0x11F02],
+ [0x11F04, 0x11F10],
+ [0x11F12, 0x11F33],
+ [0x11FB0, 0x11FB0],
+ [0x12000, 0x12399],
+ [0x12400, 0x1246E],
+ [0x12480, 0x12543],
+ [0x12F90, 0x12FF0],
+ [0x13000, 0x1342F],
+ [0x13441, 0x13446],
+ [0x14400, 0x14646],
+ [0x16800, 0x16A38],
+ [0x16A40, 0x16A5E],
+ [0x16A70, 0x16ABE],
+ [0x16AD0, 0x16AED],
+ [0x16B00, 0x16B2F],
+ [0x16B40, 0x16B43],
+ [0x16B63, 0x16B77],
+ [0x16B7D, 0x16B8F],
+ [0x16E40, 0x16E7F],
+ [0x16F00, 0x16F4A],
+ [0x16F50, 0x16F50],
+ [0x16F93, 0x16F9F],
+ [0x16FE0, 0x16FE1],
+ [0x16FE3, 0x16FE3],
+ [0x17000, 0x187F7],
+ [0x18800, 0x18CD5],
+ [0x18D00, 0x18D08],
+ [0x1AFF0, 0x1AFF3],
+ [0x1AFF5, 0x1AFFB],
+ [0x1AFFD, 0x1AFFE],
+ [0x1B000, 0x1B122],
+ [0x1B132, 0x1B132],
+ [0x1B150, 0x1B152],
+ [0x1B155, 0x1B155],
+ [0x1B164, 0x1B167],
+ [0x1B170, 0x1B2FB],
+ [0x1BC00, 0x1BC6A],
+ [0x1BC70, 0x1BC7C],
+ [0x1BC80, 0x1BC88],
+ [0x1BC90, 0x1BC99],
+ [0x1D400, 0x1D454],
+ [0x1D456, 0x1D49C],
+ [0x1D49E, 0x1D49F],
+ [0x1D4A2, 0x1D4A2],
+ [0x1D4A5, 0x1D4A6],
+ [0x1D4A9, 0x1D4AC],
+ [0x1D4AE, 0x1D4B9],
+ [0x1D4BB, 0x1D4BB],
+ [0x1D4BD, 0x1D4C3],
+ [0x1D4C5, 0x1D505],
+ [0x1D507, 0x1D50A],
+ [0x1D50D, 0x1D514],
+ [0x1D516, 0x1D51C],
+ [0x1D51E, 0x1D539],
+ [0x1D53B, 0x1D53E],
+ [0x1D540, 0x1D544],
+ [0x1D546, 0x1D546],
+ [0x1D54A, 0x1D550],
+ [0x1D552, 0x1D6A5],
+ [0x1D6A8, 0x1D6C0],
+ [0x1D6C2, 0x1D6DA],
+ [0x1D6DC, 0x1D6FA],
+ [0x1D6FC, 0x1D714],
+ [0x1D716, 0x1D734],
+ [0x1D736, 0x1D74E],
+ [0x1D750, 0x1D76E],
+ [0x1D770, 0x1D788],
+ [0x1D78A, 0x1D7A8],
+ [0x1D7AA, 0x1D7C2],
+ [0x1D7C4, 0x1D7CB],
+ [0x1DF00, 0x1DF1E],
+ [0x1DF25, 0x1DF2A],
+ [0x1E030, 0x1E06D],
+ [0x1E100, 0x1E12C],
+ [0x1E137, 0x1E13D],
+ [0x1E14E, 0x1E14E],
+ [0x1E290, 0x1E2AD],
+ [0x1E2C0, 0x1E2EB],
+ [0x1E4D0, 0x1E4EB],
+ [0x1E7E0, 0x1E7E6],
+ [0x1E7E8, 0x1E7EB],
+ [0x1E7ED, 0x1E7EE],
+ [0x1E7F0, 0x1E7FE],
+ [0x1E800, 0x1E8C4],
+ [0x1E900, 0x1E943],
+ [0x1E94B, 0x1E94B],
+ [0x1EE00, 0x1EE03],
+ [0x1EE05, 0x1EE1F],
+ [0x1EE21, 0x1EE22],
+ [0x1EE24, 0x1EE24],
+ [0x1EE27, 0x1EE27],
+ [0x1EE29, 0x1EE32],
+ [0x1EE34, 0x1EE37],
+ [0x1EE39, 0x1EE39],
+ [0x1EE3B, 0x1EE3B],
+ [0x1EE42, 0x1EE42],
+ [0x1EE47, 0x1EE47],
+ [0x1EE49, 0x1EE49],
+ [0x1EE4B, 0x1EE4B],
+ [0x1EE4D, 0x1EE4F],
+ [0x1EE51, 0x1EE52],
+ [0x1EE54, 0x1EE54],
+ [0x1EE57, 0x1EE57],
+ [0x1EE59, 0x1EE59],
+ [0x1EE5B, 0x1EE5B],
+ [0x1EE5D, 0x1EE5D],
+ [0x1EE5F, 0x1EE5F],
+ [0x1EE61, 0x1EE62],
+ [0x1EE64, 0x1EE64],
+ [0x1EE67, 0x1EE6A],
+ [0x1EE6C, 0x1EE72],
+ [0x1EE74, 0x1EE77],
+ [0x1EE79, 0x1EE7C],
+ [0x1EE7E, 0x1EE7E],
+ [0x1EE80, 0x1EE89],
+ [0x1EE8B, 0x1EE9B],
+ [0x1EEA1, 0x1EEA3],
+ [0x1EEA5, 0x1EEA9],
+ [0x1EEAB, 0x1EEBB],
+ [0x20000, 0x2B739],
+ [0x2B740, 0x2B81D],
+ [0x2B820, 0x2CEA1],
+ [0x2CEB0, 0x2EBE0],
+ [0x2EBF0, 0x2EE5D],
+ [0x2F800, 0x2FA1D],
+ [0x30000, 0x323AF],
+ [0x40000, 0x4FFFD],
+ [0x50000, 0x5FFFD],
+ [0x60000, 0x6FFFD],
+ [0x70000, 0x7FFFD],
+ [0x80000, 0x8FFFD],
+ [0x90000, 0x9FFFD],
+ [0xA0000, 0xAFFFD],
+ [0xB0000, 0xBFFFD],
+ [0xC0000, 0xCFFFD],
+ [0xD0000, 0xDFFFD],
+ [0xE0000, 0xEFFFD],
+];
+
+/**
+Least restrictive Continue
+Entries: 796056
+*/
+static immutable dchar[2][] LeastRestrictive_Continue = [
+ [0xA8, 0xA8],
+ [0xAA, 0xAA],
+ [0xAD, 0xAD],
+ [0xAF, 0xAF],
+ [0xB2, 0xB5],
+ [0xB7, 0xBA],
+ [0xBC, 0xBE],
+ [0xC0, 0xD6],
+ [0xD8, 0xF6],
+ [0xF8, 0x217],
+ [0x250, 0x2A8],
+ [0x2B0, 0x2B8],
+ [0x2BB, 0x2BB],
+ [0x2BD, 0x2C1],
+ [0x2C6, 0x2D1],
+ [0x2E0, 0x2E4],
+ [0x2EC, 0x2EC],
+ [0x2EE, 0x2EE],
+ [0x300, 0x374],
+ [0x376, 0x377],
+ [0x37A, 0x37D],
+ [0x37F, 0x37F],
+ [0x386, 0x386],
+ [0x388, 0x38A],
+ [0x38C, 0x38C],
+ [0x38E, 0x3A1],
+ [0x3A3, 0x3D6],
+ [0x3DA, 0x3DA],
+ [0x3DC, 0x3DC],
+ [0x3DE, 0x3DE],
+ [0x3E0, 0x3E0],
+ [0x3E2, 0x3F3],
+ [0x3F7, 0x40C],
+ [0x40E, 0x44F],
+ [0x451, 0x45C],
+ [0x45E, 0x481],
+ [0x483, 0x487],
+ [0x48A, 0x4C4],
+ [0x4C7, 0x4C8],
+ [0x4CB, 0x4CC],
+ [0x4D0, 0x4EB],
+ [0x4EE, 0x4F5],
+ [0x4F8, 0x4F9],
+ [0x531, 0x556],
+ [0x559, 0x559],
+ [0x560, 0x587],
+ [0x591, 0x5B9],
+ [0x5BB, 0x5BD],
+ [0x5BF, 0x5BF],
+ [0x5C1, 0x5C2],
+ [0x5C4, 0x5C5],
+ [0x5C7, 0x5C7],
+ [0x5D0, 0x5EA],
+ [0x5EF, 0x5F2],
+ [0x610, 0x61A],
+ [0x620, 0x63A],
+ [0x640, 0x652],
+ [0x660, 0x669],
+ [0x66E, 0x6B7],
+ [0x6BA, 0x6BE],
+ [0x6C0, 0x6CE],
+ [0x6D0, 0x6DC],
+ [0x6DF, 0x6E8],
+ [0x6EA, 0x6ED],
+ [0x6F0, 0x6F9],
+ [0x6FF, 0x6FF],
+ [0x710, 0x74A],
+ [0x74D, 0x7B1],
+ [0x7C0, 0x7F5],
+ [0x7FA, 0x7FA],
+ [0x7FD, 0x7FD],
+ [0x800, 0x82D],
+ [0x840, 0x85B],
+ [0x860, 0x86A],
+ [0x870, 0x887],
+ [0x889, 0x88E],
+ [0x898, 0x8E1],
+ [0x8E3, 0x903],
+ [0x905, 0x939],
+ [0x93D, 0x94D],
+ [0x950, 0x952],
+ [0x958, 0x963],
+ [0x966, 0x96F],
+ [0x971, 0x983],
+ [0x985, 0x98C],
+ [0x98F, 0x990],
+ [0x993, 0x9A8],
+ [0x9AA, 0x9B0],
+ [0x9B2, 0x9B2],
+ [0x9B6, 0x9B9],
+ [0x9BC, 0x9C4],
+ [0x9C7, 0x9C8],
+ [0x9CB, 0x9CD],
+ [0x9D7, 0x9D7],
+ [0x9DC, 0x9DD],
+ [0x9DF, 0x9E3],
+ [0x9E6, 0x9F1],
+ [0x9FC, 0x9FC],
+ [0x9FE, 0x9FE],
+ [0xA01, 0xA02],
+ [0xA05, 0xA0A],
+ [0xA0F, 0xA10],
+ [0xA13, 0xA28],
+ [0xA2A, 0xA30],
+ [0xA32, 0xA33],
+ [0xA35, 0xA36],
+ [0xA38, 0xA39],
+ [0xA3C, 0xA3C],
+ [0xA3E, 0xA42],
+ [0xA47, 0xA48],
+ [0xA4B, 0xA4D],
+ [0xA51, 0xA51],
+ [0xA59, 0xA5C],
+ [0xA5E, 0xA5E],
+ [0xA66, 0xA6F],
+ [0xA74, 0xA74],
+ [0xA81, 0xA83],
+ [0xA85, 0xA8B],
+ [0xA8D, 0xA8D],
+ [0xA8F, 0xA91],
+ [0xA93, 0xAA8],
+ [0xAAA, 0xAB0],
+ [0xAB2, 0xAB3],
+ [0xAB5, 0xAB9],
+ [0xABC, 0xAC5],
+ [0xAC7, 0xAC9],
+ [0xACB, 0xACD],
+ [0xAD0, 0xAD0],
+ [0xAE0, 0xAE0],
+ [0xAE6, 0xAEF],
+ [0xAF9, 0xAFF],
+ [0xB01, 0xB03],
+ [0xB05, 0xB0C],
+ [0xB0F, 0xB10],
+ [0xB13, 0xB28],
+ [0xB2A, 0xB30],
+ [0xB32, 0xB33],
+ [0xB35, 0xB39],
+ [0xB3C, 0xB43],
+ [0xB47, 0xB48],
+ [0xB4B, 0xB4D],
+ [0xB55, 0xB57],
+ [0xB5C, 0xB5D],
+ [0xB5F, 0xB61],
+ [0xB66, 0xB6F],
+ [0xB71, 0xB71],
+ [0xB82, 0xB83],
+ [0xB85, 0xB8A],
+ [0xB8E, 0xB90],
+ [0xB92, 0xB95],
+ [0xB99, 0xB9A],
+ [0xB9C, 0xB9C],
+ [0xB9E, 0xB9F],
+ [0xBA3, 0xBA4],
+ [0xBA8, 0xBAA],
+ [0xBAE, 0xBB5],
+ [0xBB7, 0xBB9],
+ [0xBBE, 0xBC2],
+ [0xBC6, 0xBC8],
+ [0xBCA, 0xBCD],
+ [0xBD0, 0xBD0],
+ [0xBD7, 0xBD7],
+ [0xBE6, 0xBEF],
+ [0xC00, 0xC03],
+ [0xC05, 0xC0C],
+ [0xC0E, 0xC10],
+ [0xC12, 0xC28],
+ [0xC2A, 0xC33],
+ [0xC35, 0xC39],
+ [0xC3C, 0xC44],
+ [0xC46, 0xC48],
+ [0xC4A, 0xC4D],
+ [0xC55, 0xC56],
+ [0xC58, 0xC5A],
+ [0xC5D, 0xC5D],
+ [0xC60, 0xC61],
+ [0xC66, 0xC6F],
+ [0xC80, 0xC83],
+ [0xC85, 0xC8C],
+ [0xC8E, 0xC90],
+ [0xC92, 0xCA8],
+ [0xCAA, 0xCB3],
+ [0xCB5, 0xCB9],
+ [0xCBC, 0xCC4],
+ [0xCC6, 0xCC8],
+ [0xCCA, 0xCCD],
+ [0xCD5, 0xCD6],
+ [0xCDD, 0xCDE],
+ [0xCE0, 0xCE1],
+ [0xCE6, 0xCEF],
+ [0xCF1, 0xCF3],
+ [0xD00, 0xD03],
+ [0xD05, 0xD0C],
+ [0xD0E, 0xD10],
+ [0xD12, 0xD39],
+ [0xD3E, 0xD43],
+ [0xD46, 0xD48],
+ [0xD4A, 0xD4E],
+ [0xD54, 0xD57],
+ [0xD5F, 0xD61],
+ [0xD66, 0xD6F],
+ [0xD7A, 0xD7F],
+ [0xD81, 0xD83],
+ [0xD85, 0xD96],
+ [0xD9A, 0xDB1],
+ [0xDB3, 0xDBB],
+ [0xDBD, 0xDBD],
+ [0xDC0, 0xDC6],
+ [0xDCA, 0xDCA],
+ [0xDCF, 0xDD4],
+ [0xDD6, 0xDD6],
+ [0xDD8, 0xDDF],
+ [0xDE6, 0xDEF],
+ [0xDF2, 0xDF3],
+ [0xE01, 0xE3A],
+ [0xE40, 0xE4E],
+ [0xE50, 0xE59],
+ [0xE81, 0xE82],
+ [0xE84, 0xE84],
+ [0xE86, 0xE88],
+ [0xE8A, 0xE8A],
+ [0xE8C, 0xE8D],
+ [0xE94, 0xE97],
+ [0xE99, 0xE9F],
+ [0xEA1, 0xEA3],
+ [0xEA5, 0xEA5],
+ [0xEA7, 0xEAB],
+ [0xEAD, 0xEAE],
+ [0xEB0, 0xEB9],
+ [0xEBB, 0xEBD],
+ [0xEC0, 0xEC4],
+ [0xEC6, 0xEC6],
+ [0xEC8, 0xECE],
+ [0xED0, 0xED9],
+ [0xEDC, 0xEDF],
+ [0xF00, 0xF00],
+ [0xF18, 0xF19],
+ [0xF20, 0xF29],
+ [0xF35, 0xF35],
+ [0xF37, 0xF37],
+ [0xF39, 0xF39],
+ [0xF3E, 0xF47],
+ [0xF49, 0xF6C],
+ [0xF71, 0xF84],
+ [0xF86, 0xF95],
+ [0xF97, 0xF97],
+ [0xF99, 0xFB7],
+ [0xFB9, 0xFB9],
+ [0xFC6, 0xFC6],
+ [0x1000, 0x1049],
+ [0x1050, 0x109D],
+ [0x10A0, 0x10C5],
+ [0x10C7, 0x10C7],
+ [0x10CD, 0x10CD],
+ [0x10D0, 0x10FA],
+ [0x10FC, 0x1248],
+ [0x124A, 0x124D],
+ [0x1250, 0x1256],
+ [0x1258, 0x1258],
+ [0x125A, 0x125D],
+ [0x1260, 0x1288],
+ [0x128A, 0x128D],
+ [0x1290, 0x12B0],
+ [0x12B2, 0x12B5],
+ [0x12B8, 0x12BE],
+ [0x12C0, 0x12C0],
+ [0x12C2, 0x12C5],
+ [0x12C8, 0x12D6],
+ [0x12D8, 0x1310],
+ [0x1312, 0x1315],
+ [0x1318, 0x135A],
+ [0x135D, 0x135F],
+ [0x1369, 0x1371],
+ [0x1380, 0x138F],
+ [0x13A0, 0x13F5],
+ [0x13F8, 0x13FD],
+ [0x1401, 0x166C],
+ [0x166F, 0x167F],
+ [0x1681, 0x169A],
+ [0x16A0, 0x16EA],
+ [0x16EE, 0x16F8],
+ [0x1700, 0x1715],
+ [0x171F, 0x1734],
+ [0x1740, 0x1753],
+ [0x1760, 0x176C],
+ [0x176E, 0x1770],
+ [0x1772, 0x1773],
+ [0x1780, 0x17D3],
+ [0x17D7, 0x17D7],
+ [0x17DC, 0x17DD],
+ [0x17E0, 0x17E9],
+ [0x180B, 0x180D],
+ [0x180F, 0x1819],
+ [0x1820, 0x1878],
+ [0x1880, 0x18AA],
+ [0x18B0, 0x18F5],
+ [0x1900, 0x191E],
+ [0x1920, 0x192B],
+ [0x1930, 0x193B],
+ [0x1946, 0x196D],
+ [0x1970, 0x1974],
+ [0x1980, 0x19AB],
+ [0x19B0, 0x19C9],
+ [0x19D0, 0x19DA],
+ [0x1A00, 0x1A1B],
+ [0x1A20, 0x1A5E],
+ [0x1A60, 0x1A7C],
+ [0x1A7F, 0x1A89],
+ [0x1A90, 0x1A99],
+ [0x1AA7, 0x1AA7],
+ [0x1AB0, 0x1ABD],
+ [0x1ABF, 0x1ACE],
+ [0x1B00, 0x1B4C],
+ [0x1B50, 0x1B59],
+ [0x1B6B, 0x1B73],
+ [0x1B80, 0x1BF3],
+ [0x1C00, 0x1C37],
+ [0x1C40, 0x1C49],
+ [0x1C4D, 0x1C7D],
+ [0x1C80, 0x1C88],
+ [0x1C90, 0x1CBA],
+ [0x1CBD, 0x1CBF],
+ [0x1CD0, 0x1CD2],
+ [0x1CD4, 0x1CFA],
+ [0x1D00, 0x1EF9],
+ [0x1F00, 0x1F15],
+ [0x1F18, 0x1F1D],
+ [0x1F20, 0x1F45],
+ [0x1F48, 0x1F4D],
+ [0x1F50, 0x1F57],
+ [0x1F59, 0x1F59],
+ [0x1F5B, 0x1F5B],
+ [0x1F5D, 0x1F5D],
+ [0x1F5F, 0x1F7D],
+ [0x1F80, 0x1FB4],
+ [0x1FB6, 0x1FBC],
+ [0x1FBE, 0x1FBE],
+ [0x1FC2, 0x1FC4],
+ [0x1FC6, 0x1FCC],
+ [0x1FD0, 0x1FD3],
+ [0x1FD6, 0x1FDB],
+ [0x1FE0, 0x1FEC],
+ [0x1FF2, 0x1FF4],
+ [0x1FF6, 0x1FFC],
+ [0x200B, 0x200D],
+ [0x202A, 0x202E],
+ [0x203F, 0x2040],
+ [0x2054, 0x2054],
+ [0x2060, 0x2071],
+ [0x207F, 0x207F],
+ [0x2090, 0x209C],
+ [0x20D0, 0x20DC],
+ [0x20E1, 0x20E1],
+ [0x20E5, 0x20F0],
+ [0x2102, 0x2102],
+ [0x2107, 0x2107],
+ [0x210A, 0x2113],
+ [0x2115, 0x2115],
+ [0x2118, 0x211D],
+ [0x2124, 0x2124],
+ [0x2126, 0x2126],
+ [0x2128, 0x2128],
+ [0x212A, 0x2138],
+ [0x213C, 0x213F],
+ [0x2145, 0x2149],
+ [0x214E, 0x214E],
+ [0x2160, 0x2188],
+ [0x2460, 0x24FF],
+ [0x2776, 0x2793],
+ [0x2C00, 0x2CE4],
+ [0x2CEB, 0x2CF3],
+ [0x2D00, 0x2D25],
+ [0x2D27, 0x2D27],
+ [0x2D2D, 0x2D2D],
+ [0x2D30, 0x2D67],
+ [0x2D6F, 0x2D6F],
+ [0x2D7F, 0x2D96],
+ [0x2DA0, 0x2DA6],
+ [0x2DA8, 0x2DAE],
+ [0x2DB0, 0x2DB6],
+ [0x2DB8, 0x2DBE],
+ [0x2DC0, 0x2DC6],
+ [0x2DC8, 0x2DCE],
+ [0x2DD0, 0x2DD6],
+ [0x2DD8, 0x2DDE],
+ [0x2DE0, 0x2DFF],
+ [0x2E80, 0x2FFF],
+ [0x3004, 0x3007],
+ [0x3021, 0x302F],
+ [0x3031, 0x303C],
+ [0x3041, 0x3096],
+ [0x3099, 0x309F],
+ [0x30A1, 0x30FC],
+ [0x3105, 0x312F],
+ [0x3131, 0x318E],
+ [0x31A0, 0x31BF],
+ [0x31F0, 0x31FF],
+ [0x3400, 0x4DBF],
+ [0x4E00, 0xA48C],
+ [0xA4D0, 0xA4FD],
+ [0xA500, 0xA60C],
+ [0xA610, 0xA62B],
+ [0xA640, 0xA66F],
+ [0xA674, 0xA67D],
+ [0xA67F, 0xA6F1],
+ [0xA717, 0xA71F],
+ [0xA722, 0xA788],
+ [0xA78B, 0xA7CA],
+ [0xA7D0, 0xA7D1],
+ [0xA7D3, 0xA7D3],
+ [0xA7D5, 0xA7D9],
+ [0xA7F2, 0xA827],
+ [0xA82C, 0xA82C],
+ [0xA840, 0xA873],
+ [0xA880, 0xA8C5],
+ [0xA8D0, 0xA8D9],
+ [0xA8E0, 0xA8F7],
+ [0xA8FB, 0xA8FB],
+ [0xA8FD, 0xA92D],
+ [0xA930, 0xA953],
+ [0xA960, 0xA97C],
+ [0xA980, 0xA9C0],
+ [0xA9CF, 0xA9D9],
+ [0xA9E0, 0xA9FE],
+ [0xAA00, 0xAA36],
+ [0xAA40, 0xAA4D],
+ [0xAA50, 0xAA59],
+ [0xAA60, 0xAA76],
+ [0xAA7A, 0xAAC2],
+ [0xAADB, 0xAADD],
+ [0xAAE0, 0xAAEF],
+ [0xAAF2, 0xAAF6],
+ [0xAB01, 0xAB06],
+ [0xAB09, 0xAB0E],
+ [0xAB11, 0xAB16],
+ [0xAB20, 0xAB26],
+ [0xAB28, 0xAB2E],
+ [0xAB30, 0xAB5A],
+ [0xAB5C, 0xAB69],
+ [0xAB70, 0xABEA],
+ [0xABEC, 0xABED],
+ [0xABF0, 0xABF9],
+ [0xAC00, 0xD7A3],
+ [0xD7B0, 0xD7C6],
+ [0xD7CB, 0xD7FB],
+ [0xF900, 0xFA6D],
+ [0xFA70, 0xFAD9],
+ [0xFB00, 0xFB06],
+ [0xFB13, 0xFB17],
+ [0xFB1D, 0xFB28],
+ [0xFB2A, 0xFB36],
+ [0xFB38, 0xFB3C],
+ [0xFB3E, 0xFB3E],
+ [0xFB40, 0xFB41],
+ [0xFB43, 0xFB44],
+ [0xFB46, 0xFBB1],
+ [0xFBD3, 0xFC5D],
+ [0xFC64, 0xFD3D],
+ [0xFD40, 0xFD8F],
+ [0xFD92, 0xFDC7],
+ [0xFDF0, 0xFDF9],
+ [0xFE00, 0xFE0F],
+ [0xFE20, 0xFE2F],
+ [0xFE33, 0xFE34],
+ [0xFE47, 0xFE4F],
+ [0xFE71, 0xFE71],
+ [0xFE73, 0xFE73],
+ [0xFE77, 0xFE77],
+ [0xFE79, 0xFE79],
+ [0xFE7B, 0xFE7B],
+ [0xFE7D, 0xFE7D],
+ [0xFE7F, 0xFEFC],
+ [0xFF10, 0xFF19],
+ [0xFF21, 0xFF3A],
+ [0xFF3F, 0xFF3F],
+ [0xFF41, 0xFF5A],
+ [0xFF65, 0xFFBE],
+ [0xFFC2, 0xFFC7],
+ [0xFFCA, 0xFFCF],
+ [0xFFD2, 0xFFD7],
+ [0xFFDA, 0xFFDC],
+ [0x10000, 0x1000B],
+ [0x1000D, 0x10026],
+ [0x10028, 0x1003A],
+ [0x1003C, 0x1003D],
+ [0x1003F, 0x1004D],
+ [0x10050, 0x1005D],
+ [0x10080, 0x100FA],
+ [0x10140, 0x10174],
+ [0x101FD, 0x101FD],
+ [0x10280, 0x1029C],
+ [0x102A0, 0x102D0],
+ [0x102E0, 0x102E0],
+ [0x10300, 0x1031F],
+ [0x1032D, 0x1034A],
+ [0x10350, 0x1037A],
+ [0x10380, 0x1039D],
+ [0x103A0, 0x103C3],
+ [0x103C8, 0x103CF],
+ [0x103D1, 0x103D5],
+ [0x10400, 0x1049D],
+ [0x104A0, 0x104A9],
+ [0x104B0, 0x104D3],
+ [0x104D8, 0x104FB],
+ [0x10500, 0x10527],
+ [0x10530, 0x10563],
+ [0x10570, 0x1057A],
+ [0x1057C, 0x1058A],
+ [0x1058C, 0x10592],
+ [0x10594, 0x10595],
+ [0x10597, 0x105A1],
+ [0x105A3, 0x105B1],
+ [0x105B3, 0x105B9],
+ [0x105BB, 0x105BC],
+ [0x10600, 0x10736],
+ [0x10740, 0x10755],
+ [0x10760, 0x10767],
+ [0x10780, 0x10785],
+ [0x10787, 0x107B0],
+ [0x107B2, 0x107BA],
+ [0x10800, 0x10805],
+ [0x10808, 0x10808],
+ [0x1080A, 0x10835],
+ [0x10837, 0x10838],
+ [0x1083C, 0x1083C],
+ [0x1083F, 0x10855],
+ [0x10860, 0x10876],
+ [0x10880, 0x1089E],
+ [0x108E0, 0x108F2],
+ [0x108F4, 0x108F5],
+ [0x10900, 0x10915],
+ [0x10920, 0x10939],
+ [0x10980, 0x109B7],
+ [0x109BE, 0x109BF],
+ [0x10A00, 0x10A03],
+ [0x10A05, 0x10A06],
+ [0x10A0C, 0x10A13],
+ [0x10A15, 0x10A17],
+ [0x10A19, 0x10A35],
+ [0x10A38, 0x10A3A],
+ [0x10A3F, 0x10A3F],
+ [0x10A60, 0x10A7C],
+ [0x10A80, 0x10A9C],
+ [0x10AC0, 0x10AC7],
+ [0x10AC9, 0x10AE6],
+ [0x10B00, 0x10B35],
+ [0x10B40, 0x10B55],
+ [0x10B60, 0x10B72],
+ [0x10B80, 0x10B91],
+ [0x10C00, 0x10C48],
+ [0x10C80, 0x10CB2],
+ [0x10CC0, 0x10CF2],
+ [0x10D00, 0x10D27],
+ [0x10D30, 0x10D39],
+ [0x10E80, 0x10EA9],
+ [0x10EAB, 0x10EAC],
+ [0x10EB0, 0x10EB1],
+ [0x10EFD, 0x10F1C],
+ [0x10F27, 0x10F27],
+ [0x10F30, 0x10F50],
+ [0x10F70, 0x10F85],
+ [0x10FB0, 0x10FC4],
+ [0x10FE0, 0x10FF6],
+ [0x11000, 0x11046],
+ [0x11066, 0x11075],
+ [0x1107F, 0x110BA],
+ [0x110C2, 0x110C2],
+ [0x110D0, 0x110E8],
+ [0x110F0, 0x110F9],
+ [0x11100, 0x11134],
+ [0x11136, 0x1113F],
+ [0x11144, 0x11147],
+ [0x11150, 0x11173],
+ [0x11176, 0x11176],
+ [0x11180, 0x111C4],
+ [0x111C9, 0x111CC],
+ [0x111CE, 0x111DA],
+ [0x111DC, 0x111DC],
+ [0x11200, 0x11211],
+ [0x11213, 0x11237],
+ [0x1123E, 0x11241],
+ [0x11280, 0x11286],
+ [0x11288, 0x11288],
+ [0x1128A, 0x1128D],
+ [0x1128F, 0x1129D],
+ [0x1129F, 0x112A8],
+ [0x112B0, 0x112EA],
+ [0x112F0, 0x112F9],
+ [0x11300, 0x11303],
+ [0x11305, 0x1130C],
+ [0x1130F, 0x11310],
+ [0x11313, 0x11328],
+ [0x1132A, 0x11330],
+ [0x11332, 0x11333],
+ [0x11335, 0x11339],
+ [0x1133B, 0x11344],
+ [0x11347, 0x11348],
+ [0x1134B, 0x1134D],
+ [0x11350, 0x11350],
+ [0x11357, 0x11357],
+ [0x1135D, 0x11363],
+ [0x11366, 0x1136C],
+ [0x11370, 0x11374],
+ [0x11400, 0x1144A],
+ [0x11450, 0x11459],
+ [0x1145E, 0x11461],
+ [0x11480, 0x114C5],
+ [0x114C7, 0x114C7],
+ [0x114D0, 0x114D9],
+ [0x11580, 0x115B5],
+ [0x115B8, 0x115C0],
+ [0x115D8, 0x115DD],
+ [0x11600, 0x11640],
+ [0x11644, 0x11644],
+ [0x11650, 0x11659],
+ [0x11680, 0x116B8],
+ [0x116C0, 0x116C9],
+ [0x11700, 0x1171A],
+ [0x1171D, 0x1172B],
+ [0x11730, 0x11739],
+ [0x11740, 0x11746],
+ [0x11800, 0x1183A],
+ [0x118A0, 0x118E9],
+ [0x118FF, 0x11906],
+ [0x11909, 0x11909],
+ [0x1190C, 0x11913],
+ [0x11915, 0x11916],
+ [0x11918, 0x11935],
+ [0x11937, 0x11938],
+ [0x1193B, 0x11943],
+ [0x11950, 0x11959],
+ [0x119A0, 0x119A7],
+ [0x119AA, 0x119D7],
+ [0x119DA, 0x119E1],
+ [0x119E3, 0x119E4],
+ [0x11A00, 0x11A3E],
+ [0x11A47, 0x11A47],
+ [0x11A50, 0x11A99],
+ [0x11A9D, 0x11A9D],
+ [0x11AB0, 0x11AF8],
+ [0x11C00, 0x11C08],
+ [0x11C0A, 0x11C36],
+ [0x11C38, 0x11C40],
+ [0x11C50, 0x11C59],
+ [0x11C72, 0x11C8F],
+ [0x11C92, 0x11CA7],
+ [0x11CA9, 0x11CB6],
+ [0x11D00, 0x11D06],
+ [0x11D08, 0x11D09],
+ [0x11D0B, 0x11D36],
+ [0x11D3A, 0x11D3A],
+ [0x11D3C, 0x11D3D],
+ [0x11D3F, 0x11D47],
+ [0x11D50, 0x11D59],
+ [0x11D60, 0x11D65],
+ [0x11D67, 0x11D68],
+ [0x11D6A, 0x11D8E],
+ [0x11D90, 0x11D91],
+ [0x11D93, 0x11D98],
+ [0x11DA0, 0x11DA9],
+ [0x11EE0, 0x11EF6],
+ [0x11F00, 0x11F10],
+ [0x11F12, 0x11F3A],
+ [0x11F3E, 0x11F42],
+ [0x11F50, 0x11F59],
+ [0x11FB0, 0x11FB0],
+ [0x12000, 0x12399],
+ [0x12400, 0x1246E],
+ [0x12480, 0x12543],
+ [0x12F90, 0x12FF0],
+ [0x13000, 0x1342F],
+ [0x13440, 0x13455],
+ [0x14400, 0x14646],
+ [0x16800, 0x16A38],
+ [0x16A40, 0x16A5E],
+ [0x16A60, 0x16A69],
+ [0x16A70, 0x16ABE],
+ [0x16AC0, 0x16AC9],
+ [0x16AD0, 0x16AED],
+ [0x16AF0, 0x16AF4],
+ [0x16B00, 0x16B36],
+ [0x16B40, 0x16B43],
+ [0x16B50, 0x16B59],
+ [0x16B63, 0x16B77],
+ [0x16B7D, 0x16B8F],
+ [0x16E40, 0x16E7F],
+ [0x16F00, 0x16F4A],
+ [0x16F4F, 0x16F87],
+ [0x16F8F, 0x16F9F],
+ [0x16FE0, 0x16FE1],
+ [0x16FE3, 0x16FE4],
+ [0x16FF0, 0x16FF1],
+ [0x17000, 0x187F7],
+ [0x18800, 0x18CD5],
+ [0x18D00, 0x18D08],
+ [0x1AFF0, 0x1AFF3],
+ [0x1AFF5, 0x1AFFB],
+ [0x1AFFD, 0x1AFFE],
+ [0x1B000, 0x1B122],
+ [0x1B132, 0x1B132],
+ [0x1B150, 0x1B152],
+ [0x1B155, 0x1B155],
+ [0x1B164, 0x1B167],
+ [0x1B170, 0x1B2FB],
+ [0x1BC00, 0x1BC6A],
+ [0x1BC70, 0x1BC7C],
+ [0x1BC80, 0x1BC88],
+ [0x1BC90, 0x1BC99],
+ [0x1BC9D, 0x1BC9E],
+ [0x1CF00, 0x1CF2D],
+ [0x1CF30, 0x1CF46],
+ [0x1D165, 0x1D169],
+ [0x1D16D, 0x1D172],
+ [0x1D17B, 0x1D182],
+ [0x1D185, 0x1D18B],
+ [0x1D1AA, 0x1D1AD],
+ [0x1D242, 0x1D244],
+ [0x1D400, 0x1D454],
+ [0x1D456, 0x1D49C],
+ [0x1D49E, 0x1D49F],
+ [0x1D4A2, 0x1D4A2],
+ [0x1D4A5, 0x1D4A6],
+ [0x1D4A9, 0x1D4AC],
+ [0x1D4AE, 0x1D4B9],
+ [0x1D4BB, 0x1D4BB],
+ [0x1D4BD, 0x1D4C3],
+ [0x1D4C5, 0x1D505],
+ [0x1D507, 0x1D50A],
+ [0x1D50D, 0x1D514],
+ [0x1D516, 0x1D51C],
+ [0x1D51E, 0x1D539],
+ [0x1D53B, 0x1D53E],
+ [0x1D540, 0x1D544],
+ [0x1D546, 0x1D546],
+ [0x1D54A, 0x1D550],
+ [0x1D552, 0x1D6A5],
+ [0x1D6A8, 0x1D6C0],
+ [0x1D6C2, 0x1D6DA],
+ [0x1D6DC, 0x1D6FA],
+ [0x1D6FC, 0x1D714],
+ [0x1D716, 0x1D734],
+ [0x1D736, 0x1D74E],
+ [0x1D750, 0x1D76E],
+ [0x1D770, 0x1D788],
+ [0x1D78A, 0x1D7A8],
+ [0x1D7AA, 0x1D7C2],
+ [0x1D7C4, 0x1D7CB],
+ [0x1D7CE, 0x1D7FF],
+ [0x1DA00, 0x1DA36],
+ [0x1DA3B, 0x1DA6C],
+ [0x1DA75, 0x1DA75],
+ [0x1DA84, 0x1DA84],
+ [0x1DA9B, 0x1DA9F],
+ [0x1DAA1, 0x1DAAF],
+ [0x1DF00, 0x1DF1E],
+ [0x1DF25, 0x1DF2A],
+ [0x1E000, 0x1E006],
+ [0x1E008, 0x1E018],
+ [0x1E01B, 0x1E021],
+ [0x1E023, 0x1E024],
+ [0x1E026, 0x1E02A],
+ [0x1E030, 0x1E06D],
+ [0x1E08F, 0x1E08F],
+ [0x1E100, 0x1E12C],
+ [0x1E130, 0x1E13D],
+ [0x1E140, 0x1E149],
+ [0x1E14E, 0x1E14E],
+ [0x1E290, 0x1E2AE],
+ [0x1E2C0, 0x1E2F9],
+ [0x1E4D0, 0x1E4F9],
+ [0x1E7E0, 0x1E7E6],
+ [0x1E7E8, 0x1E7EB],
+ [0x1E7ED, 0x1E7EE],
+ [0x1E7F0, 0x1E7FE],
+ [0x1E800, 0x1E8C4],
+ [0x1E8D0, 0x1E8D6],
+ [0x1E900, 0x1E94B],
+ [0x1E950, 0x1E959],
+ [0x1EE00, 0x1EE03],
+ [0x1EE05, 0x1EE1F],
+ [0x1EE21, 0x1EE22],
+ [0x1EE24, 0x1EE24],
+ [0x1EE27, 0x1EE27],
+ [0x1EE29, 0x1EE32],
+ [0x1EE34, 0x1EE37],
+ [0x1EE39, 0x1EE39],
+ [0x1EE3B, 0x1EE3B],
+ [0x1EE42, 0x1EE42],
+ [0x1EE47, 0x1EE47],
+ [0x1EE49, 0x1EE49],
+ [0x1EE4B, 0x1EE4B],
+ [0x1EE4D, 0x1EE4F],
+ [0x1EE51, 0x1EE52],
+ [0x1EE54, 0x1EE54],
+ [0x1EE57, 0x1EE57],
+ [0x1EE59, 0x1EE59],
+ [0x1EE5B, 0x1EE5B],
+ [0x1EE5D, 0x1EE5D],
+ [0x1EE5F, 0x1EE5F],
+ [0x1EE61, 0x1EE62],
+ [0x1EE64, 0x1EE64],
+ [0x1EE67, 0x1EE6A],
+ [0x1EE6C, 0x1EE72],
+ [0x1EE74, 0x1EE77],
+ [0x1EE79, 0x1EE7C],
+ [0x1EE7E, 0x1EE7E],
+ [0x1EE80, 0x1EE89],
+ [0x1EE8B, 0x1EE9B],
+ [0x1EEA1, 0x1EEA3],
+ [0x1EEA5, 0x1EEA9],
+ [0x1EEAB, 0x1EEBB],
+ [0x1FBF0, 0x1FBF9],
+ [0x20000, 0x2B739],
+ [0x2B740, 0x2B81D],
+ [0x2B820, 0x2CEA1],
+ [0x2CEB0, 0x2EBE0],
+ [0x2EBF0, 0x2EE5D],
+ [0x2F800, 0x2FA1D],
+ [0x30000, 0x323AF],
+ [0x40000, 0x4FFFD],
+ [0x50000, 0x5FFFD],
+ [0x60000, 0x6FFFD],
+ [0x70000, 0x7FFFD],
+ [0x80000, 0x8FFFD],
+ [0x90000, 0x9FFFD],
+ [0xA0000, 0xAFFFD],
+ [0xB0000, 0xBFFFD],
+ [0xC0000, 0xCFFFD],
+ [0xD0000, 0xDFFFD],
+ [0xE0000, 0xE01EF],
+];
diff --git a/gcc/d/dmd/common/outbuffer.d b/gcc/d/dmd/common/outbuffer.d
index cb2439f..f3801cb 100644
--- a/gcc/d/dmd/common/outbuffer.d
+++ b/gcc/d/dmd/common/outbuffer.d
@@ -141,7 +141,7 @@ struct OutBuffer
memory buffer. The config variables `notlinehead`, `doindent` etc. are
not changed.
*/
- extern (C++) void destroy() pure nothrow @trusted
+ extern (C++) void destroy() pure nothrow
{
dtor();
fileMapping = null;
@@ -247,7 +247,7 @@ struct OutBuffer
/**
* Writes a 16 bit value, no reserve check.
*/
- @trusted nothrow
+ nothrow
void write16n(int v)
{
auto x = cast(ushort) v;
@@ -367,7 +367,6 @@ struct OutBuffer
}
// Position buffer to accept the specified number of bytes at offset
- @trusted
void position(size_t where, size_t nbytes) nothrow
{
if (where + nbytes > data.length)
@@ -382,7 +381,7 @@ struct OutBuffer
/**
* Writes an 8 bit byte, no reserve check.
*/
- extern (C++) @trusted nothrow
+ extern (C++) nothrow @safe
void writeByten(int b)
{
this.data[offset++] = cast(ubyte) b;
diff --git a/gcc/d/dmd/cond.h b/gcc/d/dmd/cond.h
index fe497c2d..fc3ebd4 100644
--- a/gcc/d/dmd/cond.h
+++ b/gcc/d/dmd/cond.h
@@ -39,8 +39,8 @@ public:
virtual Condition *syntaxCopy() = 0;
virtual int include(Scope *sc) = 0;
- virtual DebugCondition *isDebugCondition() { return NULL; }
- virtual VersionCondition *isVersionCondition() { return NULL; }
+ virtual DebugCondition *isDebugCondition() { return nullptr; }
+ virtual VersionCondition *isVersionCondition() { return nullptr; }
void accept(Visitor *v) override { v->visit(this); }
};
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index aeedb49..7fbcd6d 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -35,7 +35,7 @@ final class CParser(AST) : Parser!AST
AST.Dsymbols* symbols; // symbols declared in current scope
bool addFuncName; /// add declaration of __func__ to function symbol table
- bool importBuiltins; /// seen use of C compiler builtins, so import __builtins;
+ bool importBuiltins; /// seen use of C compiler builtins, so import __importc_builtins;
private
{
@@ -89,6 +89,9 @@ final class CParser(AST) : Parser!AST
this.wchar_tsize = target.wchar_tsize;
// C `char` is always unsigned in ImportC
+
+ // We know that we are parsing out C, due the parent not knowing this, we have to setup tables here.
+ charLookup = compileEnv.cCharLookupTable;
}
/********************************************
@@ -125,7 +128,7 @@ final class CParser(AST) : Parser!AST
/* Seen references to C builtin functions.
* Import their definitions
*/
- auto s = new AST.Import(Loc.initial, null, Id.builtins, null, false);
+ auto s = new AST.Import(Loc.initial, null, Id.importc_builtins, null, false);
wrap.push(s);
}
@@ -1919,6 +1922,14 @@ final class CParser(AST) : Parser!AST
auto s = cparseFunctionDefinition(id, dt.isTypeFunction(), specifier);
typedefTab.setDim(typedefTabLengthSave);
symbols = symbolsSave;
+ if (specifier.mod & MOD.x__stdcall)
+ {
+ // If this function is __stdcall, wrap it in a LinkDeclaration so that
+ // it's extern(Windows) when imported in D.
+ auto decls = new AST.Dsymbols(1);
+ (*decls)[0] = s;
+ s = new AST.LinkDeclaration(s.loc, LINK.windows, decls);
+ }
symbols.push(s);
return;
}
@@ -2071,13 +2082,14 @@ final class CParser(AST) : Parser!AST
}
}
s = applySpecifier(s, specifier);
- if (level == LVL.local)
+ if (level == LVL.local || (specifier.mod & MOD.x__stdcall))
{
- // Wrap the declaration in `extern (C) { declaration }`
+ // Wrap the declaration in `extern (C/Windows) { declaration }`
// Necessary for function pointers, but harmless to apply to all.
auto decls = new AST.Dsymbols(1);
(*decls)[0] = s;
- s = new AST.LinkDeclaration(s.loc, linkage, decls);
+ const lkg = specifier.mod & MOD.x__stdcall ? LINK.windows : linkage;
+ s = new AST.LinkDeclaration(s.loc, lkg, decls);
}
symbols.push(s);
}
@@ -5860,13 +5872,15 @@ final class CParser(AST) : Parser!AST
const(char)* endp = &slice[length - 7];
+ AST.Dsymbols newSymbols;
+
size_t[void*] defineTab; // hash table of #define's turned into Symbol's
- // indexed by Identifier, returns index into symbols[]
+ // indexed by Identifier, returns index into newSymbols[]
// The memory for this is leaked
- void addVar(AST.Dsymbol s)
+ void addSym(AST.Dsymbol s)
{
- //printf("addVar() %s\n", s.toChars());
+ //printf("addSym() %s\n", s.toChars());
if (auto v = s.isVarDeclaration())
v.isCmacro(true); // mark it as coming from a C #define
/* If it's already defined, replace the earlier
@@ -5874,13 +5888,22 @@ final class CParser(AST) : Parser!AST
*/
if (size_t* pd = cast(void*)s.ident in defineTab)
{
- //printf("replacing %s\n", v.toChars());
- (*symbols)[*pd] = s;
+ //printf("replacing %s\n", s.toChars());
+ newSymbols[*pd] = s;
return;
}
- assert(symbols, "symbols is null");
- defineTab[cast(void*)s.ident] = symbols.length;
- symbols.push(s);
+ defineTab[cast(void*)s.ident] = newSymbols.length;
+ newSymbols.push(s);
+ }
+
+ void removeSym(Identifier ident)
+ {
+ //printf("removeSym() %s\n", ident.toChars());
+ if (size_t* pd = cast(void*)ident in defineTab)
+ {
+ //printf("removing %s\n", ident.toChars());
+ newSymbols[*pd] = null;
+ }
}
while (p < endp)
@@ -5924,7 +5947,7 @@ final class CParser(AST) : Parser!AST
*/
AST.Expression e = new AST.IntegerExp(scanloc, intvalue, t);
auto v = new AST.VarDeclaration(scanloc, t, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
- addVar(v);
+ addSym(v);
++p;
continue;
}
@@ -5947,7 +5970,7 @@ final class CParser(AST) : Parser!AST
*/
AST.Expression e = new AST.RealExp(scanloc, floatvalue, t);
auto v = new AST.VarDeclaration(scanloc, t, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
- addVar(v);
+ addSym(v);
++p;
continue;
}
@@ -5965,7 +5988,7 @@ final class CParser(AST) : Parser!AST
*/
AST.Expression e = new AST.StringExp(scanloc, str[0 .. len], len, 1, postfix);
auto v = new AST.VarDeclaration(scanloc, null, id, new AST.ExpInitializer(scanloc, e), STC.manifest);
- addVar(v);
+ addSym(v);
++p;
continue;
}
@@ -6001,7 +6024,7 @@ final class CParser(AST) : Parser!AST
AST.TemplateParameters* tpl = new AST.TemplateParameters();
AST.Expression constraint = null;
auto tempdecl = new AST.TemplateDeclaration(exp.loc, id, tpl, constraint, decldefs, false);
- addVar(tempdecl);
+ addSym(tempdecl);
++p;
continue;
}
@@ -6092,7 +6115,7 @@ final class CParser(AST) : Parser!AST
AST.Dsymbols* decldefs = new AST.Dsymbols();
decldefs.push(fd);
auto tempdecl = new AST.TemplateDeclaration(exp.loc, id, tpl, null, decldefs, false);
- addVar(tempdecl);
+ addSym(tempdecl);
++p;
continue;
@@ -6103,6 +6126,14 @@ final class CParser(AST) : Parser!AST
}
}
}
+ else if (p[0 .. 6] == "#undef")
+ {
+ p += 6;
+ nextToken();
+ //printf("undef %s\n", token.toChars());
+ if (token.value == TOK.identifier)
+ removeSym(token.ident);
+ }
// scan to end of line
while (*p)
++p;
@@ -6110,6 +6141,16 @@ final class CParser(AST) : Parser!AST
scanloc.linnum = scanloc.linnum + 1;
}
+ if (newSymbols.length)
+ {
+ assert(symbols, "symbols is null");
+ symbols.reserve(newSymbols.length);
+
+ foreach (sym; newSymbols)
+ if (sym) // undefined entries are null
+ symbols.push(sym);
+ }
+
scanloc = scanlocSave;
eSink = save;
defines = buf;
diff --git a/gcc/d/dmd/cppmangle.d b/gcc/d/dmd/cppmangle.d
index 0116aa3..334088b 100644
--- a/gcc/d/dmd/cppmangle.d
+++ b/gcc/d/dmd/cppmangle.d
@@ -49,19 +49,30 @@ import dmd.typesem;
import dmd.visitor;
-// helper to check if an identifier is a C++ operator
-enum CppOperator { Cast, Assign, Eq, Index, Call, Unary, Binary, OpAssign, Unknown }
-package CppOperator isCppOperator(Identifier id)
+// C++ operators
+enum CppOperator { Unknown, Cast, Assign, Eq, Index, Call, Unary, Binary, OpAssign }
+
+/**************
+ * Check if id is a C++ operator
+ * Params:
+ * id = identifier to be checked
+ * Returns:
+ * CppOperator, or Unknown if not a C++ operator
+ */
+package CppOperator isCppOperator(const scope Identifier id)
{
- __gshared const(Identifier)[] operators = null;
- if (!operators)
- operators = [Id._cast, Id.assign, Id.eq, Id.index, Id.call, Id.opUnary, Id.opBinary, Id.opOpAssign];
- foreach (i, op; operators)
- {
- if (op == id)
- return cast(CppOperator)i;
+ with (Id) with (CppOperator)
+ {
+ return (id == _cast) ? Cast :
+ (id == assign) ? Assign :
+ (id == eq) ? Eq :
+ (id == index) ? Index :
+ (id == call) ? Call :
+ (id == opUnary) ? Unary :
+ (id == opBinary) ? Binary :
+ (id == opOpAssign) ? OpAssign :
+ Unknown ;
}
- return CppOperator.Unknown;
}
///
@@ -71,6 +82,8 @@ const(char)* toCppMangleItanium(Dsymbol s)
OutBuffer buf;
scope CppMangleVisitor v = new CppMangleVisitor(&buf, s.loc);
v.mangleOf(s);
+ if (v.errors)
+ fatal();
return buf.extractChars();
}
@@ -82,6 +95,8 @@ const(char)* cppTypeInfoMangleItanium(Dsymbol s)
buf.writestring("_ZTI"); // "TI" means typeinfo structure
scope CppMangleVisitor v = new CppMangleVisitor(&buf, s.loc);
v.cpp_mangle_name(s, false);
+ if (v.errors)
+ fatal();
return buf.extractChars();
}
@@ -93,6 +108,8 @@ const(char)* cppThunkMangleItanium(FuncDeclaration fd, int offset)
buf.printf("_ZThn%u_", offset); // "Th" means thunk, "n%u" is the call offset
scope CppMangleVisitor v = new CppMangleVisitor(&buf, fd.loc);
v.mangle_function_encoding(fd);
+ if (v.errors)
+ fatal();
return buf.extractChars();
}
@@ -163,6 +180,7 @@ private final class CppMangleVisitor : Visitor
Objects components; /// array of components available for substitution
OutBuffer* buf; /// append the mangling to buf[]
Loc loc; /// location for use in error messages
+ bool errors; /// failed to mangle properly
/**
* Constructor
@@ -484,7 +502,8 @@ private final class CppMangleVisitor : Visitor
else
{
.error(ti.loc, "%s `%s` internal compiler error: C++ `%s` template value parameter is not supported", ti.kind, ti.toPrettyChars, tv.valType.toChars());
- fatal();
+ errors = true;
+ return;
}
}
else if (tp.isTemplateAliasParameter())
@@ -519,13 +538,13 @@ private final class CppMangleVisitor : Visitor
else
{
.error(ti.loc, "%s `%s` internal compiler error: C++ `%s` template alias parameter is not supported", ti.kind, ti.toPrettyChars, o.toChars());
- fatal();
+ errors = true;
}
}
else if (tp.isTemplateThisParameter())
{
.error(ti.loc, "%s `%s` internal compiler error: C++ `%s` template this parameter is not supported", ti.kind, ti.toPrettyChars, o.toChars());
- fatal();
+ errors = true;
}
else
{
@@ -574,7 +593,8 @@ private final class CppMangleVisitor : Visitor
if (t is null)
{
.error(ti.loc, "%s `%s` internal compiler error: C++ `%s` template value parameter is not supported", ti.kind, ti.toPrettyChars, (*ti.tiargs)[j].toChars());
- fatal();
+ errors = true;
+ return false;
}
t.accept(this);
}
@@ -1012,7 +1032,8 @@ private final class CppMangleVisitor : Visitor
if (!(d.storage_class & (STC.extern_ | STC.field | STC.gshared)))
{
.error(d.loc, "%s `%s` internal compiler error: C++ static non-`__gshared` non-`extern` variables not supported", d.kind, d.toPrettyChars);
- fatal();
+ errors = true;
+ return;
}
Dsymbol p = d.toParent();
if (p && !p.isModule()) //for example: char Namespace1::beta[6] should be mangled as "_ZN10Namespace14betaE"
@@ -1348,7 +1369,8 @@ private final class CppMangleVisitor : Visitor
// Static arrays in D are passed by value; no counterpart in C++
.error(loc, "internal compiler error: unable to pass static array `%s` to extern(C++) function, use pointer instead",
t.toChars());
- fatal();
+ errors = true;
+ return;
}
auto prev = this.context.push({
TypeFunction tf;
@@ -1386,7 +1408,7 @@ private final class CppMangleVisitor : Visitor
else
p = "";
.error(loc, "internal compiler error: %stype `%s` cannot be mapped to C++\n", p, t.toChars());
- fatal(); //Fatal, because this error should be handled in frontend
+ errors = true; //Fatal, because this error should be handled in frontend
}
/****************************
diff --git a/gcc/d/dmd/cxxfrontend.d b/gcc/d/dmd/cxxfrontend.d
index a0432d2..c0805b8 100644
--- a/gcc/d/dmd/cxxfrontend.d
+++ b/gcc/d/dmd/cxxfrontend.d
@@ -13,6 +13,7 @@ module dmd.cxxfrontend;
import dmd.aggregate : AggregateDeclaration;
import dmd.arraytypes;
import dmd.astenums;
+import dmd.attrib;
import dmd.common.outbuffer : OutBuffer;
import dmd.denum : EnumDeclaration;
import dmd.dmodule /*: Module*/;
@@ -35,6 +36,15 @@ import dmd.statement : Statement, AsmStatement, GccAsmStatement;
extern (C++, "dmd"):
/***********************************************************
+ * atrtibsem.d
+ */
+Expressions* getAttributes(UserAttributeDeclaration a)
+{
+ import dmd.attribsem;
+ return dmd.attribsem.getAttributes(a);
+}
+
+/***********************************************************
* cppmangle.d
*/
const(char)* toCppMangleItanium(Dsymbol s)
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 8a713f4..78781f4 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -69,7 +69,7 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t)
{
Expression visit(Expression e)
{
- // printf("Expression.implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars());
+ //printf("Expression.implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars());
if (const match = (sc && sc.flags & SCOPE.Cfile) ? e.cimplicitConvTo(t) : e.implicitConvTo(t))
{
// no need for an extra cast when matching is exact
@@ -2257,7 +2257,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
Type tb = t.toBasetype();
if (tb.ty == Tarray)
{
- if (checkArrayLiteralEscape(sc, ae, false))
+ if (checkArrayLiteralEscape(*sc, ae, false))
{
return ErrorExp.get();
}
diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d
index 8bac1f4..2199d5d 100644
--- a/gcc/d/dmd/dclass.d
+++ b/gcc/d/dmd/dclass.d
@@ -26,6 +26,7 @@ import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.errors;
import dmd.func;
+import dmd.funcsem;
import dmd.id;
import dmd.identifier;
import dmd.location;
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index 3f9769d..a1202ed 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -27,6 +27,7 @@ import dmd.dtemplate;
import dmd.errors;
import dmd.expression;
import dmd.func;
+import dmd.funcsem;
import dmd.globals;
import dmd.gluelayer;
import dmd.id;
@@ -38,6 +39,7 @@ import dmd.location;
import dmd.mtype;
import dmd.common.outbuffer;
import dmd.rootobject;
+import dmd.root.filename;
import dmd.target;
import dmd.tokens;
import dmd.typesem;
@@ -213,9 +215,21 @@ bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
/******************************************
*/
-void ObjectNotFound(Identifier id)
+void ObjectNotFound(Loc loc, Identifier id)
{
- error(Loc.initial, "`%s` not found. object.d may be incorrectly installed or corrupt.", id.toChars());
+ error(loc, "`%s` not found. object.d may be incorrectly installed or corrupt.", id.toChars());
+ version (IN_LLVM)
+ {
+ errorSupplemental(loc, "ldc2 might not be correctly installed.");
+ errorSupplemental(loc, "Please check your ldc2.conf configuration file.");
+ errorSupplemental(loc, "Installation instructions can be found at http://wiki.dlang.org/LDC.");
+ }
+ else version (MARS)
+ {
+ errorSupplemental(loc, "dmd might not be correctly installed. Run 'dmd -man' for installation instructions.");
+ const dmdConfFile = global.inifilename.length ? FileName.canonicalName(global.inifilename) : "not found";
+ errorSupplemental(loc, "config file: %.*s", cast(int)dmdConfFile.length, dmdConfFile.ptr);
+ }
fatal();
}
@@ -1370,7 +1384,7 @@ extern (C++) class VarDeclaration : Declaration
/*************************************
* Return true if we can take the address of this variable.
*/
- final bool canTakeAddressOf()
+ final bool canTakeAddressOf() @safe
{
return !(storage_class & STC.manifest);
}
@@ -1378,7 +1392,7 @@ extern (C++) class VarDeclaration : Declaration
/******************************************
* Return true if variable needs to call the destructor.
*/
- final bool needsScopeDtor()
+ final bool needsScopeDtor() @safe
{
//printf("VarDeclaration::needsScopeDtor() %s %d\n", toChars(), edtor && !(storage_class & STC.nodtor));
return edtor && !(storage_class & STC.nodtor);
@@ -1832,7 +1846,7 @@ extern (C++) final class TypeInfoStructDeclaration : TypeInfoDeclaration
super(tinfo);
if (!Type.typeinfostruct)
{
- ObjectNotFound(Id.TypeInfo_Struct);
+ ObjectNotFound(loc, Id.TypeInfo_Struct);
}
type = Type.typeinfostruct.type;
}
@@ -1857,7 +1871,7 @@ extern (C++) final class TypeInfoClassDeclaration : TypeInfoDeclaration
super(tinfo);
if (!Type.typeinfoclass)
{
- ObjectNotFound(Id.TypeInfo_Class);
+ ObjectNotFound(loc, Id.TypeInfo_Class);
}
type = Type.typeinfoclass.type;
}
@@ -1882,7 +1896,7 @@ extern (C++) final class TypeInfoInterfaceDeclaration : TypeInfoDeclaration
super(tinfo);
if (!Type.typeinfointerface)
{
- ObjectNotFound(Id.TypeInfo_Interface);
+ ObjectNotFound(loc, Id.TypeInfo_Interface);
}
type = Type.typeinfointerface.type;
}
@@ -1907,7 +1921,7 @@ extern (C++) final class TypeInfoPointerDeclaration : TypeInfoDeclaration
super(tinfo);
if (!Type.typeinfopointer)
{
- ObjectNotFound(Id.TypeInfo_Pointer);
+ ObjectNotFound(loc, Id.TypeInfo_Pointer);
}
type = Type.typeinfopointer.type;
}
@@ -1932,7 +1946,7 @@ extern (C++) final class TypeInfoArrayDeclaration : TypeInfoDeclaration
super(tinfo);
if (!Type.typeinfoarray)
{
- ObjectNotFound(Id.TypeInfo_Array);
+ ObjectNotFound(loc, Id.TypeInfo_Array);
}
type = Type.typeinfoarray.type;
}
@@ -1957,7 +1971,7 @@ extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
super(tinfo);
if (!Type.typeinfostaticarray)
{
- ObjectNotFound(Id.TypeInfo_StaticArray);
+ ObjectNotFound(loc, Id.TypeInfo_StaticArray);
}
type = Type.typeinfostaticarray.type;
}
@@ -1982,7 +1996,7 @@ extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclarati
super(tinfo);
if (!Type.typeinfoassociativearray)
{
- ObjectNotFound(Id.TypeInfo_AssociativeArray);
+ ObjectNotFound(loc, Id.TypeInfo_AssociativeArray);
}
type = Type.typeinfoassociativearray.type;
}
@@ -2007,7 +2021,7 @@ extern (C++) final class TypeInfoEnumDeclaration : TypeInfoDeclaration
super(tinfo);
if (!Type.typeinfoenum)
{
- ObjectNotFound(Id.TypeInfo_Enum);
+ ObjectNotFound(loc, Id.TypeInfo_Enum);
}
type = Type.typeinfoenum.type;
}
@@ -2032,7 +2046,7 @@ extern (C++) final class TypeInfoFunctionDeclaration : TypeInfoDeclaration
super(tinfo);
if (!Type.typeinfofunction)
{
- ObjectNotFound(Id.TypeInfo_Function);
+ ObjectNotFound(loc, Id.TypeInfo_Function);
}
type = Type.typeinfofunction.type;
}
@@ -2057,7 +2071,7 @@ extern (C++) final class TypeInfoDelegateDeclaration : TypeInfoDeclaration
super(tinfo);
if (!Type.typeinfodelegate)
{
- ObjectNotFound(Id.TypeInfo_Delegate);
+ ObjectNotFound(loc, Id.TypeInfo_Delegate);
}
type = Type.typeinfodelegate.type;
}
@@ -2082,7 +2096,7 @@ extern (C++) final class TypeInfoTupleDeclaration : TypeInfoDeclaration
super(tinfo);
if (!Type.typeinfotypelist)
{
- ObjectNotFound(Id.TypeInfo_Tuple);
+ ObjectNotFound(loc, Id.TypeInfo_Tuple);
}
type = Type.typeinfotypelist.type;
}
@@ -2107,7 +2121,7 @@ extern (C++) final class TypeInfoConstDeclaration : TypeInfoDeclaration
super(tinfo);
if (!Type.typeinfoconst)
{
- ObjectNotFound(Id.TypeInfo_Const);
+ ObjectNotFound(loc, Id.TypeInfo_Const);
}
type = Type.typeinfoconst.type;
}
@@ -2132,7 +2146,7 @@ extern (C++) final class TypeInfoInvariantDeclaration : TypeInfoDeclaration
super(tinfo);
if (!Type.typeinfoinvariant)
{
- ObjectNotFound(Id.TypeInfo_Invariant);
+ ObjectNotFound(loc, Id.TypeInfo_Invariant);
}
type = Type.typeinfoinvariant.type;
}
@@ -2157,7 +2171,7 @@ extern (C++) final class TypeInfoSharedDeclaration : TypeInfoDeclaration
super(tinfo);
if (!Type.typeinfoshared)
{
- ObjectNotFound(Id.TypeInfo_Shared);
+ ObjectNotFound(loc, Id.TypeInfo_Shared);
}
type = Type.typeinfoshared.type;
}
@@ -2182,7 +2196,7 @@ extern (C++) final class TypeInfoWildDeclaration : TypeInfoDeclaration
super(tinfo);
if (!Type.typeinfowild)
{
- ObjectNotFound(Id.TypeInfo_Wild);
+ ObjectNotFound(loc, Id.TypeInfo_Wild);
}
type = Type.typeinfowild.type;
}
@@ -2207,7 +2221,7 @@ extern (C++) final class TypeInfoVectorDeclaration : TypeInfoDeclaration
super(tinfo);
if (!Type.typeinfovector)
{
- ObjectNotFound(Id.TypeInfo_Vector);
+ ObjectNotFound(loc, Id.TypeInfo_Vector);
}
type = Type.typeinfovector.type;
}
diff --git a/gcc/d/dmd/dmangle.d b/gcc/d/dmd/dmangle.d
index 33428de..d4eecb9 100644
--- a/gcc/d/dmd/dmangle.d
+++ b/gcc/d/dmd/dmangle.d
@@ -72,12 +72,14 @@ void mangleToBuffer(TemplateInstance ti, ref OutBuffer buf)
/// Returns: `true` if the given character is a valid mangled character
package bool isValidMangling(dchar c) nothrow
{
+ import dmd.common.charactertables;
+
return
c >= 'A' && c <= 'Z' ||
c >= 'a' && c <= 'z' ||
c >= '0' && c <= '9' ||
c != 0 && strchr("$%().:?@[]_", c) ||
- isUniAlpha(c);
+ isAnyIdentifierCharacter(c);
}
// valid mangled characters
@@ -147,6 +149,7 @@ import dmd.dtemplate;
import dmd.errors;
import dmd.expression;
import dmd.func;
+import dmd.funcsem;
import dmd.globals;
import dmd.id;
import dmd.identifier;
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 58bf3fd..a1a337b 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -24,6 +24,7 @@ import dmd.astenums;
import dmd.common.outbuffer;
import dmd.compiler;
import dmd.cparse;
+import dmd.declaration;
import dmd.dimport;
import dmd.dmacro;
import dmd.doc;
@@ -357,6 +358,7 @@ extern (C++) final class Module : Package
FileType filetype; // source file type
bool hasAlwaysInlines; // contains references to functions that must be inlined
bool isPackageFile; // if it is a package.d
+ Edition edition; // language edition that this module is compiled with
Package pkg; // if isPackageFile is true, the Package that contains this package.d
Strings contentImportedFiles; // array of files whose content was imported
int needmoduleinfo;
@@ -454,7 +456,7 @@ extern (C++) final class Module : Package
FileName.exists(filename) == 1)
{
FileName.free(srcfilename.ptr);
- srcfilename = FileName.removeExt(filename); // just does a mem.strdup(filename)
+ srcfilename = FileName.sansExt(filename);
}
else if (!FileName.equalsExt(srcfilename, mars_ext) &&
!FileName.equalsExt(srcfilename, hdr_ext) &&
@@ -476,6 +478,8 @@ extern (C++) final class Module : Package
setDocfile();
if (doHdrGen)
hdrfile = setOutfilename(global.params.dihdr.name, global.params.dihdr.dir, arg, hdr_ext);
+
+ this.edition = Edition.legacy;
}
extern (D) this(const(char)[] filename, Identifier ident, int doDocComment, int doHdrGen)
@@ -609,41 +613,30 @@ extern (C++) final class Module : Package
*/
private void onFileReadError(const ref Loc loc)
{
- if (FileName.equals(srcfile.toString(), "object.d"))
+ const name = srcfile.toString();
+ if (FileName.equals(name, "object.d"))
{
- .error(loc, "cannot find source code for runtime library file 'object.d'");
- version (IN_LLVM)
- {
- errorSupplemental(loc, "ldc2 might not be correctly installed.");
- errorSupplemental(loc, "Please check your ldc2.conf configuration file.");
- errorSupplemental(loc, "Installation instructions can be found at http://wiki.dlang.org/LDC.");
- }
- version (MARS)
- {
- errorSupplemental(loc, "dmd might not be correctly installed. Run 'dmd -man' for installation instructions.");
- const dmdConfFile = global.inifilename.length ? FileName.canonicalName(global.inifilename) : "not found";
- errorSupplemental(loc, "config file: %.*s", cast(int)dmdConfFile.length, dmdConfFile.ptr);
- }
+ ObjectNotFound(loc, ident);
}
else if (FileName.ext(this.arg) || !loc.isValid())
{
// Modules whose original argument name has an extension, or do not
// have a valid location come from the command-line.
// Error that their file cannot be found and return early.
- .error(loc, "cannot find input file `%s`", srcfile.toChars());
+ .error(loc, "cannot find input file `%.*s`", cast(int)name.length, name.ptr);
}
else
{
// if module is not named 'package' but we're trying to read 'package.d', we're looking for a package module
bool isPackageMod = (strcmp(toChars(), "package") != 0) && isPackageFileName(srcfile);
if (isPackageMod)
- .error(loc, "importing package '%s' requires a 'package.d' file which cannot be found in '%s'", toChars(), srcfile.toChars());
+ .error(loc, "importing package '%s' requires a 'package.d' file which cannot be found in '%.*s'", toChars(), cast(int)name.length, name.ptr);
else
{
.error(loc, "unable to read module `%s`", toChars());
- const pkgfile = FileName.combine(FileName.removeExt(srcfile.toString()), package_d);
- .errorSupplemental(loc, "Expected '%s' or '%s' in one of the following import paths:",
- srcfile.toChars(), pkgfile.ptr);
+ const pkgfile = FileName.combine(FileName.sansExt(name), package_d);
+ .errorSupplemental(loc, "Expected '%.*s' or '%.*s' in one of the following import paths:",
+ cast(int)name.length, name.ptr, cast(int)pkgfile.length, pkgfile.ptr);
}
}
if (!global.gag)
@@ -657,7 +650,7 @@ extern (C++) final class Module : Package
}
else
{
- fprintf(stderr, "Specify path to file '%s' with -I switch\n", srcfile.toChars());
+ fprintf(stderr, "Specify path to file '%.*s' with -I switch\n", cast(int)name.length, name.ptr);
}
removeHdrFilesAndFail(global.params, Module.amodules);
diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d
index c00c1cc..a8b43da 100644
--- a/gcc/d/dmd/doc.d
+++ b/gcc/d/dmd/doc.d
@@ -2107,42 +2107,12 @@ int getMarkdownIndent(ref OutBuffer buf, size_t from, size_t to) @safe
}
/************************************************
- * Scan forward to one of:
- * start of identifier
- * beginning of next line
- * end of buf
- */
-size_t skiptoident(ref OutBuffer buf, size_t i) @safe
-{
- const slice = buf[];
- while (i < slice.length)
- {
- dchar c;
- size_t oi = i;
- if (utf_decodeChar(slice, i, c))
- {
- /* Ignore UTF errors, but still consume input
- */
- break;
- }
- if (c >= 0x80)
- {
- if (!isUniAlpha(c))
- continue;
- }
- else if (!(isalpha(c) || c == '_' || c == '\n'))
- continue;
- i = oi;
- break;
- }
- return i;
-}
-
-/************************************************
* Scan forward past end of identifier.
*/
size_t skippastident(ref OutBuffer buf, size_t i) @safe
{
+ import dmd.common.charactertables;
+
const slice = buf[];
while (i < slice.length)
{
@@ -2156,7 +2126,8 @@ size_t skippastident(ref OutBuffer buf, size_t i) @safe
}
if (c >= 0x80)
{
- if (isUniAlpha(c))
+ // we don't care if it is start/continue here
+ if (isAnyIdentifierCharacter(c))
continue;
}
else if (isalnum(c) || c == '_')
@@ -2173,6 +2144,8 @@ size_t skippastident(ref OutBuffer buf, size_t i) @safe
*/
size_t skipPastIdentWithDots(ref OutBuffer buf, size_t i) @safe
{
+ import dmd.common.charactertables;
+
const slice = buf[];
bool lastCharWasDot;
while (i < slice.length)
@@ -2203,7 +2176,8 @@ size_t skipPastIdentWithDots(ref OutBuffer buf, size_t i) @safe
{
if (c >= 0x80)
{
- if (isUniAlpha(c))
+ // we don't care if it is start/continue here
+ if (isAnyIdentifierCharacter(c))
{
lastCharWasDot = false;
continue;
@@ -5249,6 +5223,8 @@ bool isCVariadicArg(const(char)[] p) @nogc nothrow pure @safe
@trusted
bool isIdStart(const(char)* p) @nogc nothrow pure
{
+ import dmd.common.charactertables;
+
dchar c = *p;
if (isalpha(c) || c == '_')
return true;
@@ -5257,7 +5233,7 @@ bool isIdStart(const(char)* p) @nogc nothrow pure
size_t i = 0;
if (utf_decodeChar(p[0 .. 4], i, c))
return false; // ignore errors
- if (isUniAlpha(c))
+ if (isAnyStart(c))
return true;
}
return false;
@@ -5269,6 +5245,8 @@ bool isIdStart(const(char)* p) @nogc nothrow pure
@trusted
bool isIdTail(const(char)* p) @nogc nothrow pure
{
+ import dmd.common.charactertables;
+
dchar c = *p;
if (isalnum(c) || c == '_')
return true;
@@ -5277,7 +5255,7 @@ bool isIdTail(const(char)* p) @nogc nothrow pure
size_t i = 0;
if (utf_decodeChar(p[0 .. 4], i, c))
return false; // ignore errors
- if (isUniAlpha(c))
+ if (isAnyContinue(c))
return true;
}
return false;
diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index 76a26a2..4719529 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/dmd/dscope.d
@@ -830,12 +830,18 @@ extern (C++) struct Scope
/// Returns: whether to raise DIP1000 warnings (FeatureStabe.default) or errors (FeatureState.enabled)
extern (D) FeatureState useDIP1000()
{
- return (flags & SCOPE.dip1000) ? FeatureState.enabled : FeatureState.disabled;
+ return (flags & SCOPE.dip1000 || hasEdition(Edition.v2024)) ? FeatureState.enabled : FeatureState.disabled;
}
/// Returns: whether to raise DIP25 warnings (FeatureStabe.default) or errors (FeatureState.enabled)
extern (D) FeatureState useDIP25()
{
- return (flags & SCOPE.dip25) ? FeatureState.enabled : FeatureState.disabled;
+ return (flags & SCOPE.dip25 || hasEdition(Edition.v2024)) ? FeatureState.enabled : FeatureState.disabled;
+ }
+
+ /// Returns: whether this scope compiles with `edition` or later
+ extern (D) bool hasEdition(Edition edition)
+ {
+ return _module && _module.edition >= edition;
}
}
diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d
index df4d07a..339b223 100644
--- a/gcc/d/dmd/dstruct.d
+++ b/gcc/d/dmd/dstruct.d
@@ -28,6 +28,7 @@ import dmd.dtemplate;
import dmd.errors;
import dmd.expression;
import dmd.func;
+import dmd.funcsem;
import dmd.globals;
import dmd.id;
import dmd.identifier;
@@ -222,7 +223,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration
bool hasCopyCtor; // copy constructor
bool hasPointerField; // members with indirections
bool hasVoidInitPointers; // void-initialized unsafe fields
- bool hasSystemFields; // @system members
+ bool hasUnsafeBitpatterns; // @system members, pointers, bool
bool hasFieldWithInvariant; // invariants
bool computedTypeProperties;// the above 3 fields are computed
// Even if struct is defined as non-root symbol, some built-in operations
@@ -395,13 +396,16 @@ extern (C++) class StructDeclaration : AggregateDeclaration
foreach (vd; fields)
{
if (vd.storage_class & STC.ref_ || vd.hasPointers())
+ {
hasPointerField = true;
+ hasUnsafeBitpatterns = true;
+ }
if (vd._init && vd._init.isVoidInitializer() && vd.type.hasPointers())
hasVoidInitPointers = true;
- if (vd.storage_class & STC.system || vd.type.hasSystemFields())
- hasSystemFields = true;
+ if (vd.storage_class & STC.system || vd.type.hasUnsafeBitpatterns())
+ hasUnsafeBitpatterns = true;
if (!vd._init && vd.type.hasVoidInitPointers())
hasVoidInitPointers = true;
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index b831c32..90b2d9f 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -453,7 +453,7 @@ extern (C++) class Dsymbol : ASTNode
*
* See also `parent`, `toParent` and `toParent2`.
*/
- final inout(Dsymbol) pastMixin() inout
+ final inout(Dsymbol) pastMixin() inout @safe
{
//printf("Dsymbol::pastMixin() %s\n", toChars());
if (!isTemplateMixin() && !isForwardingAttribDeclaration() && !isForwardingScopeDsymbol())
@@ -503,13 +503,13 @@ extern (C++) class Dsymbol : ASTNode
* // s.toParentLocal() == FuncDeclaration('mod.test')
* ---
*/
- final inout(Dsymbol) toParent() inout
+ final inout(Dsymbol) toParent() inout @safe
{
return parent ? parent.pastMixin() : null;
}
/// ditto
- final inout(Dsymbol) toParent2() inout
+ final inout(Dsymbol) toParent2() inout @safe
{
if (!parent || !parent.isTemplateInstance && !parent.isForwardingAttribDeclaration() && !parent.isForwardingScopeDsymbol())
return parent;
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index f845435..ce29073 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -222,9 +222,9 @@ public:
Dsymbol *toParent2();
Dsymbol *toParentDecl();
Dsymbol *toParentLocal();
- Dsymbol *toParentP(Dsymbol *p1, Dsymbol *p2 = NULL);
+ Dsymbol *toParentP(Dsymbol *p1, Dsymbol *p2 = nullptr);
TemplateInstance *isInstantiated();
- bool followInstantiationContext(Dsymbol *p1, Dsymbol *p2 = NULL);
+ bool followInstantiationContext(Dsymbol *p1, Dsymbol *p2 = nullptr);
TemplateInstance *isSpeculative();
Ungag ungagSpeculative();
@@ -269,61 +269,61 @@ public:
bool inNonRoot();
// Eliminate need for dynamic_cast
- virtual Package *isPackage() { return NULL; }
- virtual Module *isModule() { return NULL; }
- virtual EnumMember *isEnumMember() { return NULL; }
- virtual TemplateDeclaration *isTemplateDeclaration() { return NULL; }
- virtual TemplateInstance *isTemplateInstance() { return NULL; }
- virtual TemplateMixin *isTemplateMixin() { return NULL; }
- virtual ForwardingAttribDeclaration *isForwardingAttribDeclaration() { return NULL; }
- virtual Nspace *isNspace() { return NULL; }
- virtual Declaration *isDeclaration() { return NULL; }
- virtual StorageClassDeclaration *isStorageClassDeclaration(){ return NULL; }
- virtual ExpressionDsymbol *isExpressionDsymbol() { return NULL; }
- virtual AliasAssign *isAliasAssign() { return NULL; }
- virtual ThisDeclaration *isThisDeclaration() { return NULL; }
- virtual BitFieldDeclaration *isBitFieldDeclaration() { return NULL; }
- virtual TypeInfoDeclaration *isTypeInfoDeclaration() { return NULL; }
- virtual TupleDeclaration *isTupleDeclaration() { return NULL; }
- virtual AliasDeclaration *isAliasDeclaration() { return NULL; }
- virtual AggregateDeclaration *isAggregateDeclaration() { return NULL; }
- virtual FuncDeclaration *isFuncDeclaration() { return NULL; }
- virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return NULL; }
- virtual OverDeclaration *isOverDeclaration() { return NULL; }
- virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return NULL; }
- virtual CtorDeclaration *isCtorDeclaration() { return NULL; }
- virtual PostBlitDeclaration *isPostBlitDeclaration() { return NULL; }
- virtual DtorDeclaration *isDtorDeclaration() { return NULL; }
- virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return NULL; }
- virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return NULL; }
- virtual SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() { return NULL; }
- virtual SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() { return NULL; }
- virtual InvariantDeclaration *isInvariantDeclaration() { return NULL; }
- virtual UnitTestDeclaration *isUnitTestDeclaration() { return NULL; }
- virtual NewDeclaration *isNewDeclaration() { return NULL; }
- virtual VarDeclaration *isVarDeclaration() { return NULL; }
- virtual VersionSymbol *isVersionSymbol() { return NULL; }
- virtual DebugSymbol *isDebugSymbol() { return NULL; }
- virtual ClassDeclaration *isClassDeclaration() { return NULL; }
- virtual StructDeclaration *isStructDeclaration() { return NULL; }
- virtual UnionDeclaration *isUnionDeclaration() { return NULL; }
- virtual InterfaceDeclaration *isInterfaceDeclaration() { return NULL; }
- virtual ScopeDsymbol *isScopeDsymbol() { return NULL; }
- virtual ForwardingScopeDsymbol *isForwardingScopeDsymbol() { return NULL; }
- virtual WithScopeSymbol *isWithScopeSymbol() { return NULL; }
- virtual ArrayScopeSymbol *isArrayScopeSymbol() { return NULL; }
- virtual Import *isImport() { return NULL; }
- virtual EnumDeclaration *isEnumDeclaration() { return NULL; }
- virtual SymbolDeclaration *isSymbolDeclaration() { return NULL; }
- virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
- virtual AnonDeclaration *isAnonDeclaration() { return NULL; }
- virtual CPPNamespaceDeclaration *isCPPNamespaceDeclaration() { return NULL; }
- virtual VisibilityDeclaration *isVisibilityDeclaration() { return NULL; }
- virtual OverloadSet *isOverloadSet() { return NULL; }
- virtual MixinDeclaration *isMixinDeclaration() { return NULL; }
- virtual StaticAssert *isStaticAssert() { return NULL; }
- virtual StaticIfDeclaration *isStaticIfDeclaration() { return NULL; }
- virtual CAsmDeclaration *isCAsmDeclaration() { return NULL; }
+ virtual Package *isPackage() { return nullptr; }
+ virtual Module *isModule() { return nullptr; }
+ virtual EnumMember *isEnumMember() { return nullptr; }
+ virtual TemplateDeclaration *isTemplateDeclaration() { return nullptr; }
+ virtual TemplateInstance *isTemplateInstance() { return nullptr; }
+ virtual TemplateMixin *isTemplateMixin() { return nullptr; }
+ virtual ForwardingAttribDeclaration *isForwardingAttribDeclaration() { return nullptr; }
+ virtual Nspace *isNspace() { return nullptr; }
+ virtual Declaration *isDeclaration() { return nullptr; }
+ virtual StorageClassDeclaration *isStorageClassDeclaration(){ return nullptr; }
+ virtual ExpressionDsymbol *isExpressionDsymbol() { return nullptr; }
+ virtual AliasAssign *isAliasAssign() { return nullptr; }
+ virtual ThisDeclaration *isThisDeclaration() { return nullptr; }
+ virtual BitFieldDeclaration *isBitFieldDeclaration() { return nullptr; }
+ virtual TypeInfoDeclaration *isTypeInfoDeclaration() { return nullptr; }
+ virtual TupleDeclaration *isTupleDeclaration() { return nullptr; }
+ virtual AliasDeclaration *isAliasDeclaration() { return nullptr; }
+ virtual AggregateDeclaration *isAggregateDeclaration() { return nullptr; }
+ virtual FuncDeclaration *isFuncDeclaration() { return nullptr; }
+ virtual FuncAliasDeclaration *isFuncAliasDeclaration() { return nullptr; }
+ virtual OverDeclaration *isOverDeclaration() { return nullptr; }
+ virtual FuncLiteralDeclaration *isFuncLiteralDeclaration() { return nullptr; }
+ virtual CtorDeclaration *isCtorDeclaration() { return nullptr; }
+ virtual PostBlitDeclaration *isPostBlitDeclaration() { return nullptr; }
+ virtual DtorDeclaration *isDtorDeclaration() { return nullptr; }
+ virtual StaticCtorDeclaration *isStaticCtorDeclaration() { return nullptr; }
+ virtual StaticDtorDeclaration *isStaticDtorDeclaration() { return nullptr; }
+ virtual SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() { return nullptr; }
+ virtual SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() { return nullptr; }
+ virtual InvariantDeclaration *isInvariantDeclaration() { return nullptr; }
+ virtual UnitTestDeclaration *isUnitTestDeclaration() { return nullptr; }
+ virtual NewDeclaration *isNewDeclaration() { return nullptr; }
+ virtual VarDeclaration *isVarDeclaration() { return nullptr; }
+ virtual VersionSymbol *isVersionSymbol() { return nullptr; }
+ virtual DebugSymbol *isDebugSymbol() { return nullptr; }
+ virtual ClassDeclaration *isClassDeclaration() { return nullptr; }
+ virtual StructDeclaration *isStructDeclaration() { return nullptr; }
+ virtual UnionDeclaration *isUnionDeclaration() { return nullptr; }
+ virtual InterfaceDeclaration *isInterfaceDeclaration() { return nullptr; }
+ virtual ScopeDsymbol *isScopeDsymbol() { return nullptr; }
+ virtual ForwardingScopeDsymbol *isForwardingScopeDsymbol() { return nullptr; }
+ virtual WithScopeSymbol *isWithScopeSymbol() { return nullptr; }
+ virtual ArrayScopeSymbol *isArrayScopeSymbol() { return nullptr; }
+ virtual Import *isImport() { return nullptr; }
+ virtual EnumDeclaration *isEnumDeclaration() { return nullptr; }
+ virtual SymbolDeclaration *isSymbolDeclaration() { return nullptr; }
+ virtual AttribDeclaration *isAttribDeclaration() { return nullptr; }
+ virtual AnonDeclaration *isAnonDeclaration() { return nullptr; }
+ virtual CPPNamespaceDeclaration *isCPPNamespaceDeclaration() { return nullptr; }
+ virtual VisibilityDeclaration *isVisibilityDeclaration() { return nullptr; }
+ virtual OverloadSet *isOverloadSet() { return nullptr; }
+ virtual MixinDeclaration *isMixinDeclaration() { return nullptr; }
+ virtual StaticAssert *isStaticAssert() { return nullptr; }
+ virtual StaticIfDeclaration *isStaticIfDeclaration() { return nullptr; }
+ virtual CAsmDeclaration *isCAsmDeclaration() { return nullptr; }
void accept(Visitor *v) override { v->visit(this); }
};
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index b13f98a..65a1b04 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -21,6 +21,7 @@ import dmd.arraytypes;
import dmd.astcodegen;
import dmd.astenums;
import dmd.attrib;
+import dmd.attribsem;
import dmd.clone;
import dmd.cond;
import dmd.dcast;
@@ -1072,8 +1073,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// Calculate type size + safety checks
if (sc && sc.func)
{
- if (dsym._init && dsym._init.isVoidInitializer())
+ if (dsym._init && dsym._init.isVoidInitializer() && !(dsym.storage_class & STC.temp))
{
+ // Don't do these checks for STC.temp vars because the generated `opAssign`
+ // for a struct with postblit and destructor void initializes a temporary
+ // __swap variable, which can be trusted
if (dsym.type.hasPointers()) // also computes type size
sc.setUnsafe(false, dsym.loc,
@@ -1081,9 +1085,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
else if (dsym.type.hasInvariant())
sc.setUnsafe(false, dsym.loc,
"`void` initializers for structs with invariants are not allowed in safe functions");
- else if (dsym.type.hasSystemFields())
+ else if (dsym.type.toBasetype().ty == Tbool)
sc.setUnsafePreview(global.params.systemVariables, false, dsym.loc,
- "`void` initializers for `@system` variables not allowed in safe functions");
+ "a `bool` must be 0 or 1, so void intializing it is not allowed in safe functions");
+ else if (dsym.type.hasUnsafeBitpatterns())
+ sc.setUnsafePreview(global.params.systemVariables, false, dsym.loc,
+ "`void` initializers for types with unsafe bit patterns are not allowed in safe functions");
}
else if (!dsym._init &&
!(dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field | STC.parameter)) &&
@@ -1251,7 +1258,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
{
import dmd.escape : setUnsafeDIP1000;
const inSafeFunc = sc.func && sc.func.isSafeBypassingInference(); // isSafeBypassingInference may call setUnsafe().
- if (sc.setUnsafeDIP1000(false, dsym.loc, "`scope` allocation of `%s` requires that constructor be annotated with `scope`", dsym))
+ if (setUnsafeDIP1000(*sc, false, dsym.loc, "`scope` allocation of `%s` requires that constructor be annotated with `scope`", dsym))
errorSupplemental(ne.member.loc, "is the location of the constructor");
}
ne.onstack = 1;
@@ -3379,8 +3386,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
{
void badObjectDotD()
{
- .error(cldec.loc, "%s `%s` missing or corrupt object.d", cldec.kind, cldec.toPrettyChars);
- fatal();
+ ObjectNotFound(cldec.loc, cldec.ident);
}
if (!cldec.object || cldec.object.errors)
@@ -5295,6 +5301,24 @@ void aliasSemantic(AliasDeclaration ds, Scope* sc)
// Detect `alias sym = sym;` to prevent creating loops in overload overnext lists.
if (auto tident = ds.type.isTypeIdentifier())
{
+ if (sc.hasEdition(Edition.v2024) && tident.idents.length)
+ {
+ alias mt = tident;
+ Dsymbol pscopesym;
+ Dsymbol s = sc.search(ds.loc, mt.ident, pscopesym);
+ // detect `alias a = var1.member_var;` which confusingly resolves to
+ // `typeof(var1).member_var`, which can be valid inside the aggregate type
+ if (s && s.isVarDeclaration() &&
+ mt.ident != Id.This && mt.ident != Id._super)
+ {
+ s = tident.toDsymbol(sc);
+ if (s && s.isVarDeclaration()) {
+ error(mt.loc, "cannot alias member of variable `%s`", mt.ident.toChars());
+ errorSupplemental(mt.loc, "Use `typeof(%s)` instead to preserve behaviour",
+ mt.ident.toChars());
+ }
+ }
+ }
// Selective imports are allowed to alias to the same name `import mod : sym=sym`.
if (!ds._import)
{
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index d181fac..fb11821 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -5767,7 +5767,7 @@ struct TemplateInstanceBox
assert(this.ti.hash);
}
- size_t toHash() const @trusted pure nothrow
+ size_t toHash() const @safe pure nothrow
{
assert(ti.hash);
return ti.hash;
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index 2e2ced4..883091b 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -104,7 +104,8 @@ void genCppHdrFiles(ref Modules ms)
// Emit array compatibility because extern(C++) types may have slices
// as members (as opposed to function parameters)
- buf.writestring(`
+ if (v.hasDArray)
+ buf.writestring(`
#ifdef CUSTOM_D_ARRAY_TYPE
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
#else
@@ -133,6 +134,17 @@ struct _d_dynamicArray final
#endif
`);
+ if (v.hasExternSystem)
+ buf.writestring(`
+#ifndef _WIN32
+#define EXTERN_SYSTEM_AFTER __stdcall
+#define EXTERN_SYSTEM_BEFORE
+#else
+#define EXTERN_SYSTEM_AFTER
+#define EXTERN_SYSTEM_BEFORE extern "C"
+#endif
+`);
+
if (v.hasReal)
{
hashIf(buf, "!defined(_d_real)");
@@ -248,7 +260,14 @@ public:
OutBuffer* buf;
/// The generated header uses `real` emitted as `_d_real`?
- bool hasReal;
+ bool hasReal = false;
+
+ /// The generated header has extern(System) functions,
+ /// which needs support macros in the header
+ bool hasExternSystem = false;
+
+ /// There are functions taking slices, which need a compatibility struct for C++
+ bool hasDArray = false;
/// The generated header should contain comments for skipped declarations?
const bool printIgnored;
@@ -745,7 +764,7 @@ public:
// Note that tf might be null for templated (member) functions
auto tf = cast(AST.TypeFunction)fd.type;
- if ((tf && (tf.linkage != LINK.c || adparent) && tf.linkage != LINK.cpp) || (!tf && fd.isPostBlitDeclaration()))
+ if ((tf && (tf.linkage != LINK.c || adparent) && tf.linkage != LINK.cpp && tf.linkage != LINK.windows) || (!tf && fd.isPostBlitDeclaration()))
{
ignored("function %s because of linkage", fd.toPrettyChars());
return checkFunctionNeedsPlaceholder(fd);
@@ -793,8 +812,17 @@ public:
writeProtection(fd.visibility.kind);
- if (tf && tf.linkage == LINK.c)
+ if (fd._linkage == LINK.system)
+ {
+ hasExternSystem = true;
+ buf.writestring("EXTERN_SYSTEM_BEFORE ");
+ }
+ else if (tf && tf.linkage == LINK.c)
buf.writestring("extern \"C\" ");
+ else if (tf && tf.linkage == LINK.windows)
+ {
+ // __stdcall is printed after return type
+ }
else if (!adparent)
buf.writestring("extern ");
if (adparent && fd.isStatic())
@@ -2058,6 +2086,8 @@ public:
{
debug (Debug_DtoH) mixin(traceVisit!t);
+ hasDArray = true;
+
if (t.isConst() || t.isImmutable())
buf.writestring("const ");
buf.writestring("_d_dynamicArray< ");
@@ -2261,8 +2291,8 @@ public:
* Writes the function signature to `buf`.
*
* Params:
- * fd = the function to print
* tf = fd's type
+ * fd = the function to print
*/
private void funcToBuffer(AST.TypeFunction tf, AST.FuncDeclaration fd)
{
@@ -2297,6 +2327,15 @@ public:
if (tf.isref)
buf.writeByte('&');
buf.writeByte(' ');
+
+ if (fd._linkage == LINK.system)
+ {
+ buf.writestring("EXTERN_SYSTEM_AFTER ");
+ }
+ else if (tf.linkage == LINK.windows)
+ {
+ buf.writestring("__stdcall ");
+ }
writeIdentifier(fd);
}
diff --git a/gcc/d/dmd/errors.h b/gcc/d/dmd/errors.h
index a47b5aa..7a9683b 100644
--- a/gcc/d/dmd/errors.h
+++ b/gcc/d/dmd/errors.h
@@ -42,7 +42,7 @@ D_ATTRIBUTE_FORMAT(1, 2) void message(const char *format, ...);
D_ATTRIBUTE_FORMAT(2, 3) void message(const Loc& loc, const char *format, ...);
D_ATTRIBUTE_FORMAT(1, 2) void tip(const char *format, ...);
-D_ATTRIBUTE_FORMAT(2, 0) void verrorReport(const Loc& loc, const char *format, va_list ap, ErrorKind kind, const char *p1 = NULL, const char *p2 = NULL);
+D_ATTRIBUTE_FORMAT(2, 0) void verrorReport(const Loc& loc, const char *format, va_list ap, ErrorKind kind, const char *p1 = nullptr, const char *p2 = nullptr);
D_ATTRIBUTE_FORMAT(2, 0) void verrorReportSupplemental(const Loc& loc, const char* format, va_list ap, ErrorKind kind);
#if defined(__GNUC__) || defined(__clang__)
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index 3e17ff4..08bd6fd 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -25,6 +25,7 @@ import dmd.dsymbol;
import dmd.errors;
import dmd.expression;
import dmd.func;
+import dmd.funcsem;
import dmd.globals : FeatureState;
import dmd.id;
import dmd.identifier;
@@ -73,7 +74,7 @@ package(dmd) struct EscapeState
* `true` if error
*/
public
-bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf,
+bool checkMutableArguments(ref Scope sc, FuncDeclaration fd, TypeFunction tf,
Expression ethis, Expressions* arguments, bool gag)
{
enum log = false;
@@ -92,7 +93,8 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf,
struct EscapeBy
{
- EscapeByResults er;
+ VarDeclarations byref;
+ VarDeclarations byvalue;
Parameter param; // null if no Parameter for this argument
bool isMutable; // true if reference to mutable
}
@@ -150,14 +152,21 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf,
refs = true;
auto var = outerVars[i - (len - outerVars.length)];
eb.isMutable = var.type.isMutable();
- eb.er.pushRef(var, false);
+ eb.byref.push(var);
continue;
}
+ void onRef(VarDeclaration v, bool transition) { eb.byref.push(v); }
+ void onValue(VarDeclaration v) { eb.byvalue.push(v); }
+ void onFunc(FuncDeclaration fd, bool called) {}
+ void onExp(Expression e, bool transition) {}
+
+ scope EscapeByResults er = EscapeByResults(&onRef, &onValue, &onFunc, &onExp);
+
if (refs)
- escapeByRef(arg, &eb.er);
+ escapeByRef(arg, er);
else
- escapeByValue(arg, &eb.er);
+ escapeByValue(arg, er);
}
void checkOnePair(size_t i, ref EscapeBy eb, ref EscapeBy eb2,
@@ -193,7 +202,7 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf,
void escape(size_t i, ref EscapeBy eb, bool byval)
{
- foreach (VarDeclaration v; byval ? eb.er.byvalue : eb.er.byref)
+ foreach (VarDeclaration v; byval ? eb.byvalue : eb.byref)
{
if (log)
{
@@ -204,7 +213,7 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf,
continue;
foreach (ref eb2; escapeBy[i + 1 .. $])
{
- foreach (VarDeclaration v2; byval ? eb2.er.byvalue : eb2.er.byref)
+ foreach (VarDeclaration v2; byval ? eb2.byvalue : eb2.byref)
{
checkOnePair(i, eb, eb2, v, v2, byval);
}
@@ -231,7 +240,7 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf,
* `true` if any elements escaped
*/
public
-bool checkArrayLiteralEscape(Scope *sc, ArrayLiteralExp ae, bool gag)
+bool checkArrayLiteralEscape(ref Scope sc, ArrayLiteralExp ae, bool gag)
{
bool errors;
if (ae.basis)
@@ -255,7 +264,7 @@ bool checkArrayLiteralEscape(Scope *sc, ArrayLiteralExp ae, bool gag)
* `true` if any elements escaped
*/
public
-bool checkAssocArrayLiteralEscape(Scope *sc, AssocArrayLiteralExp ae, bool gag)
+bool checkAssocArrayLiteralEscape(ref Scope sc, AssocArrayLiteralExp ae, bool gag)
{
bool errors;
foreach (ex; *ae.keys)
@@ -324,7 +333,7 @@ void printScopeFailure(E)(E printFunc, VarDeclaration v, int recursionLimit)
* `true` if pointers to the stack can escape via assignment
*/
public
-bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId, VarDeclaration vPar, STC parStc, Expression arg, bool assertmsg, bool gag)
+bool checkParamArgumentEscape(ref Scope sc, FuncDeclaration fdc, Identifier parId, VarDeclaration vPar, STC parStc, Expression arg, bool assertmsg, bool gag)
{
enum log = false;
if (log) printf("checkParamArgumentEscape(arg: %s par: %s parSTC: %llx)\n",
@@ -335,22 +344,6 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId,
if (!arg.type.hasPointers())
return false;
- EscapeByResults er;
-
- escapeByValue(arg, &er);
-
- if (parStc & STC.scope_)
- {
- // These errors only apply to non-scope parameters
- // When the parameter is `scope`, only `checkScopeVarAddr` on `er.byref` is needed
- er.byfunc.setDim(0);
- er.byvalue.setDim(0);
- er.byexp.setDim(0);
- }
-
- if (!er.byref.length && !er.byvalue.length && !er.byfunc.length && !er.byexp.length)
- return false;
-
bool result = false;
/* 'v' is assigned unsafely to 'par'
@@ -382,11 +375,11 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId,
}
}
- foreach (VarDeclaration v; er.byvalue)
+ void onValue(VarDeclaration v)
{
if (log) printf("byvalue %s\n", v.toChars());
- if (v.isDataseg())
- continue;
+ if (parStc & STC.scope_ || v.isDataseg())
+ return;
Dsymbol p = v.toParent2();
@@ -402,11 +395,11 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId,
}
}
- foreach (VarDeclaration v; er.byref)
+ void onRef(VarDeclaration v, bool retRefTransition)
{
if (log) printf("byref %s\n", v.toChars());
if (v.isDataseg())
- continue;
+ return;
Dsymbol p = v.toParent2();
@@ -414,19 +407,21 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId,
if (checkScopeVarAddr(v, arg, sc, gag))
{
result = true;
- continue;
+ return;
}
if (p == sc.func && !(parStc & STC.scope_))
{
unsafeAssign!"reference to local variable"(v);
- continue;
+ return;
}
}
- foreach (FuncDeclaration fd; er.byfunc)
+ void onFunc(FuncDeclaration fd, bool called)
{
//printf("fd = %s, %d\n", fd.toChars(), fd.tookAddressOf);
+ if (parStc & STC.scope_)
+ return;
VarDeclarations vars;
findAllOuterAccessedVariables(fd, &vars);
@@ -442,16 +437,15 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId,
if ((v.isReference() || v.isScope()) && p == sc.func)
{
unsafeAssign!"reference to local"(v);
- continue;
+ return;
}
}
}
- if (!sc.func)
- return result;
-
- foreach (Expression ee; er.byexp)
+ void onExp(Expression ee, bool retRefTransition)
{
+ if (parStc & STC.scope_)
+ return;
const(char)* msg = parId ?
"reference to stack allocated value returned by `%s` assigned to non-scope parameter `%s`" :
"reference to stack allocated value returned by `%s` assigned to non-scope anonymous parameter";
@@ -459,6 +453,8 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId,
result |= sc.setUnsafeDIP1000(gag, ee.loc, msg, ee, parId);
}
+ scope EscapeByResults er = EscapeByResults(&onRef, &onValue, &onFunc, &onExp);
+ escapeByValue(arg, er);
return result;
}
@@ -476,7 +472,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId,
* `true` if assignment to `firstArg` would cause an error
*/
public
-bool checkParamArgumentReturn(Scope* sc, Expression firstArg, Expression arg, Parameter param, bool gag)
+bool checkParamArgumentReturn(ref Scope sc, Expression firstArg, Expression arg, Parameter param, bool gag)
{
enum log = false;
if (log) printf("checkParamArgumentReturn(firstArg: %s arg: %s)\n",
@@ -512,7 +508,7 @@ bool checkParamArgumentReturn(Scope* sc, Expression firstArg, Expression arg, Pa
* `true` if construction would cause an escaping reference error
*/
public
-bool checkConstructorEscape(Scope* sc, CallExp ce, bool gag)
+bool checkConstructorEscape(ref Scope sc, CallExp ce, bool gag)
{
enum log = false;
if (log) printf("checkConstructorEscape(%s, %s)\n", ce.toChars(), ce.type.toChars());
@@ -609,7 +605,7 @@ ReturnParamDest returnParamDest(TypeFunction tf, Type tthis)
* `true` if pointers to the stack can escape via assignment
*/
public
-bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
+bool checkAssignEscape(ref Scope sc, Expression e, bool gag, bool byRef)
{
enum log = false;
if (log) printf("checkAssignEscape(e: %s, byRef: %d)\n", e.toChars(), byRef);
@@ -646,16 +642,6 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
return false;
VarDeclaration va = expToVariable(e1);
- EscapeByResults er;
-
- if (byRef)
- escapeByRef(e2, &er);
- else
- escapeByValue(e2, &er);
-
- if (!er.byref.length && !er.byvalue.length && !er.byfunc.length && !er.byexp.length)
- return false;
-
if (va && e.op == EXP.concatenateElemAssign)
{
@@ -685,7 +671,6 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
FuncDeclaration fd = sc.func;
-
// Determine if va is a `ref` parameter, so it has a lifetime exceding the function scope
const bool vaIsRef = va && va.isParameter() && va.isReference();
if (log && vaIsRef) printf("va is ref `%s`\n", va.toChars());
@@ -701,7 +686,10 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
vaIsFirstRef = va == fd.vthis;
break;
case ReturnParamDest.firstArg:
- vaIsFirstRef = (*fd.parameters)[0] == va;
+ // While you'd expect fd.parameters[0] to exist in this case, the compiler-generated
+ // expression that initializes an `out int* p = null` is analyzed before fd.parameters
+ // is created, so we still do a null and length check
+ vaIsFirstRef = fd.parameters && 0 < fd.parameters.length && (*fd.parameters)[0] == va;
break;
case ReturnParamDest.returnVal:
break;
@@ -710,14 +698,14 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
if (log && vaIsFirstRef) printf("va is first ref `%s`\n", va.toChars());
bool result = false;
- foreach (VarDeclaration v; er.byvalue)
+ void onValue(VarDeclaration v)
{
if (log) printf("byvalue: %s\n", v.toChars());
if (v.isDataseg())
- continue;
+ return;
if (v == va)
- continue;
+ return;
Dsymbol p = v.toParent2();
@@ -729,7 +717,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
/* Add v to va's list of dependencies
*/
va.addMaybe(v);
- continue;
+ return;
}
if (vaIsFirstRef && p == fd)
@@ -746,7 +734,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
{
// va=v, where v is `return scope`
if (inferScope(va))
- continue;
+ return;
}
// If va's lifetime encloses v's, then error
@@ -761,7 +749,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
break;
case EnclosedBy.longerScope:
if (v.storage_class & STC.temp)
- continue;
+ return;
msg = "scope variable `%s` assigned to `%s` with longer lifetime";
break;
case EnclosedBy.refVar:
@@ -775,7 +763,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
if (sc.setUnsafeDIP1000(gag, ae.loc, msg, v, va))
{
result = true;
- continue;
+ return;
}
}
@@ -793,14 +781,14 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
if (isRefReturnScope(va.storage_class))
va.storage_class |= STC.returnScope;
}
- continue;
+ return;
}
result |= sc.setUnsafeDIP1000(gag, ae.loc, "scope variable `%s` assigned to non-scope `%s`", v, e1);
}
else if (v.isTypesafeVariadicArray && p == fd)
{
if (inferScope(va))
- continue;
+ return;
result |= sc.setUnsafeDIP1000(gag, ae.loc, "variadic variable `%s` assigned to non-scope `%s`", v, e1);
}
else
@@ -813,16 +801,16 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
}
}
- foreach (VarDeclaration v; er.byref)
+ void onRef(VarDeclaration v, bool retRefTransition)
{
if (log) printf("byref: %s\n", v.toChars());
if (v.isDataseg())
- continue;
+ return;
if (checkScopeVarAddr(v, ae, sc, gag))
{
result = true;
- continue;
+ return;
}
if (va && va.isScope() && !v.isReference())
@@ -852,7 +840,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
if (sc.setUnsafeDIP1000(gag, ae.loc, "address of variable `%s` assigned to `%s` with longer lifetime", v, va))
{
result = true;
- continue;
+ return;
}
}
@@ -860,21 +848,21 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
notMaybeScope(v, e);
if (p != sc.func)
- continue;
+ return;
if (inferScope(va))
{
if (v.isReturn() && !va.isReturn())
va.storage_class |= STC.return_ | STC.returninferred;
- continue;
+ return;
}
if (e1.op == EXP.structLiteral)
- continue;
+ return;
result |= sc.setUnsafeDIP1000(gag, ae.loc, "reference to local variable `%s` assigned to non-scope `%s`", v, e1);
}
- foreach (FuncDeclaration func; er.byfunc)
+ void onFunc(FuncDeclaration func, bool called)
{
if (log) printf("byfunc: %s, %d\n", func.toChars(), func.tookAddressOf);
VarDeclarations vars;
@@ -899,7 +887,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
notMaybeScope(v, e);
if (!(v.isReference() || v.isScope()) || p != fd)
- continue;
+ return;
if (va && !va.isDataseg() && (va.isScope() || va.maybeScope))
{
@@ -908,14 +896,14 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
*/
//if (!va.isScope())
//va.storage_class |= STC.scope_ | STC.scopeinferred;
- continue;
+ return;
}
result |= sc.setUnsafeDIP1000(gag, ae.loc,
"reference to local `%s` assigned to non-scope `%s` in @safe code", v, e1);
}
}
- foreach (Expression ee; er.byexp)
+ void onExp(Expression ee, bool retRefTransition)
{
if (log) printf("byexp: %s\n", ee.toChars());
@@ -928,7 +916,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
sc.eSink.deprecation(ee.loc, "slice of static array temporary returned by `%s` assigned to longer lived variable `%s`",
ee.toChars(), e1.toChars());
//result = true;
- continue;
+ return;
}
if (ee.op == EXP.call && ee.type.toBasetype().isTypeStruct() &&
@@ -937,7 +925,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
if (sc.setUnsafeDIP1000(gag, ee.loc, "address of struct temporary returned by `%s` assigned to longer lived variable `%s`", ee, e1))
{
result = true;
- continue;
+ return;
}
}
@@ -947,17 +935,24 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
if (sc.setUnsafeDIP1000(gag, ee.loc, "address of struct literal `%s` assigned to longer lived variable `%s`", ee, e1))
{
result = true;
- continue;
+ return;
}
}
if (inferScope(va))
- continue;
+ return;
result |= sc.setUnsafeDIP1000(gag, ee.loc,
"reference to stack allocated value returned by `%s` assigned to non-scope `%s`", ee, e1);
}
+ scope EscapeByResults er = EscapeByResults(&onRef, &onValue, &onFunc, &onExp);
+
+ if (byRef)
+ escapeByRef(e2, er);
+ else
+ escapeByValue(e2, er);
+
return result;
}
@@ -973,35 +968,35 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
* `true` if pointers to the stack can escape
*/
public
-bool checkThrowEscape(Scope* sc, Expression e, bool gag)
+bool checkThrowEscape(ref Scope sc, Expression e, bool gag)
{
//printf("[%s] checkThrowEscape, e = %s\n", e.loc.toChars(), e.toChars());
- EscapeByResults er;
-
- escapeByValue(e, &er);
-
- if (!er.byref.length && !er.byvalue.length && !er.byexp.length)
- return false;
bool result = false;
- foreach (VarDeclaration v; er.byvalue)
+ void onRef(VarDeclaration v, bool retRefTransition) {}
+ void onValue(VarDeclaration v)
{
//printf("byvalue %s\n", v.toChars());
if (v.isDataseg())
- continue;
+ return;
if (v.isScope() && !v.iscatchvar) // special case: allow catch var to be rethrown
// despite being `scope`
{
// https://issues.dlang.org/show_bug.cgi?id=17029
result |= sc.setUnsafeDIP1000(gag, e.loc, "scope variable `%s` may not be thrown", v);
- continue;
+ return;
}
else
{
notMaybeScope(v, new ThrowExp(e.loc, e));
}
}
+ void onFunc(FuncDeclaration fd, bool called) {}
+ void onExp(Expression exp, bool retRefTransition) {}
+
+ scope EscapeByResults er = EscapeByResults(&onRef, &onValue, &onFunc, &onExp);
+ escapeByValue(e, er);
return result;
}
@@ -1017,7 +1012,7 @@ bool checkThrowEscape(Scope* sc, Expression e, bool gag)
* `true` if pointers to the stack can escape
*/
public
-bool checkNewEscape(Scope* sc, Expression e, bool gag)
+bool checkNewEscape(ref Scope sc, Expression e, bool gag)
{
import dmd.globals: FeatureState;
import dmd.errors: previewErrorFunc;
@@ -1025,19 +1020,13 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
//printf("[%s] checkNewEscape, e = %s\n", e.loc.toChars(), e.toChars());
enum log = false;
if (log) printf("[%s] checkNewEscape, e: `%s`\n", e.loc.toChars(), e.toChars());
- EscapeByResults er;
-
- escapeByValue(e, &er);
-
- if (!er.byref.length && !er.byvalue.length && !er.byexp.length)
- return false;
bool result = false;
- foreach (VarDeclaration v; er.byvalue)
+ void onValue(VarDeclaration v)
{
if (log) printf("byvalue `%s`\n", v.toChars());
if (v.isDataseg())
- continue;
+ return;
Dsymbol p = v.toParent2();
@@ -1057,7 +1046,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
{
// https://issues.dlang.org/show_bug.cgi?id=20868
result |= sc.setUnsafeDIP1000(gag, e.loc, "scope variable `%s` may not be copied into allocated memory", v);
- continue;
+ return;
}
}
else if (v.isTypesafeVariadicArray && p == sc.func)
@@ -1072,7 +1061,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
}
}
- foreach (VarDeclaration v; er.byref)
+ void onRef(VarDeclaration v, bool retRefTransition)
{
if (log) printf("byref `%s`\n", v.toChars());
@@ -1083,11 +1072,11 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
const(char)* msg = v.isParameter() ?
"copying `%s` into allocated memory escapes a reference to parameter `%s`" :
"copying `%s` into allocated memory escapes a reference to local variable `%s`";
- return sc.setUnsafePreview(fs, gag, e.loc, msg, e, v);
+ return setUnsafePreview(&sc, fs, gag, e.loc, msg, e, v);
}
if (v.isDataseg())
- continue;
+ return;
Dsymbol p = v.toParent2();
@@ -1096,7 +1085,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
if (p == sc.func)
{
result |= escapingRef(v, sc.useDIP1000);
- continue;
+ return;
}
}
@@ -1104,7 +1093,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
* Infer the addition of 'return', or set result to be the offending expression.
*/
if (!v.isReference())
- continue;
+ return;
// https://dlang.org/spec/function.html#return-ref-parameters
if (p == sc.func)
@@ -1112,16 +1101,16 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
//printf("escaping reference to local ref variable %s\n", v.toChars());
//printf("storage class = x%llx\n", v.storage_class);
result |= escapingRef(v, sc.useDIP25);
- continue;
+ return;
}
// Don't need to be concerned if v's parent does not return a ref
FuncDeclaration func = p.isFuncDeclaration();
if (!func || !func.type)
- continue;
+ return;
if (auto tf = func.type.isTypeFunction())
{
if (!tf.isref)
- continue;
+ return;
const(char)* msg = "storing reference to outer local variable `%s` into allocated memory causes it to escape";
if (!gag)
@@ -1135,7 +1124,9 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
}
}
- foreach (Expression ee; er.byexp)
+ void onFunc(FuncDeclaration fd, bool called) {}
+
+ void onExp(Expression ee, bool retRefTransition)
{
if (log) printf("byexp %s\n", ee.toChars());
if (!gag)
@@ -1144,6 +1135,9 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
result = true;
}
+ scope EscapeByResults er = EscapeByResults(&onRef, &onValue, &onFunc, &onExp);
+ escapeByValue(e, er);
+
return result;
}
@@ -1160,7 +1154,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
* `true` if pointers to the stack can escape
*/
public
-bool checkReturnEscape(Scope* sc, Expression e, bool gag)
+bool checkReturnEscape(ref Scope sc, Expression e, bool gag)
{
//printf("[%s] checkReturnEscape, e: %s\n", e.loc.toChars(), e.toChars());
return checkReturnEscapeImpl(sc, e, false, gag);
@@ -1178,7 +1172,7 @@ bool checkReturnEscape(Scope* sc, Expression e, bool gag)
* `true` if references to the stack can escape
*/
public
-bool checkReturnEscapeRef(Scope* sc, Expression e, bool gag)
+bool checkReturnEscapeRef(ref Scope sc, Expression e, bool gag)
{
version (none)
{
@@ -1200,26 +1194,17 @@ bool checkReturnEscapeRef(Scope* sc, Expression e, bool gag)
* Returns:
* `true` if references to the stack can escape
*/
-private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
+private bool checkReturnEscapeImpl(ref Scope sc, Expression e, bool refs, bool gag)
{
enum log = false;
if (log) printf("[%s] checkReturnEscapeImpl, refs: %d e: `%s`\n", e.loc.toChars(), refs, e.toChars());
- EscapeByResults er;
-
- if (refs)
- escapeByRef(e, &er);
- else
- escapeByValue(e, &er);
-
- if (!er.byref.length && !er.byvalue.length && !er.byexp.length)
- return false;
bool result = false;
- foreach (VarDeclaration v; er.byvalue)
+ void onValue(VarDeclaration v)
{
if (log) printf("byvalue `%s`\n", v.toChars());
if (v.isDataseg())
- continue;
+ return;
const vsr = buildScopeRef(v.storage_class);
@@ -1227,7 +1212,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
if (p == sc.func && inferReturn(sc.func, v, /*returnScope:*/ true))
{
- continue;
+ return;
}
if (v.isScope())
@@ -1237,7 +1222,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
if (vsr == ScopeRef.ReturnScope ||
vsr == ScopeRef.Ref_ReturnScope)
{
- continue;
+ return;
}
auto pfunc = p.isFuncDeclaration();
@@ -1251,15 +1236,20 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
* return s; // s is inferred as 'scope' but incorrectly tested in foo()
* return null; }
*/
- !(!refs && p.parent == sc.func && pfunc.fes) &&
+ !(!refs && p.parent == sc.func && pfunc.fes)
+ )
+ {
/*
* auto p(scope string s) {
* string scfunc() { return s; }
* }
*/
- !(!refs && sc.func.isFuncDeclaration().getLevel(pfunc, sc.intypeof) > 0)
- )
- {
+ if (sc.func.isFuncDeclaration().getLevel(pfunc, sc.intypeof) > 0 &&
+ inferReturn(sc.func, sc.func.vthis, /*returnScope*/ !refs))
+ {
+ return;
+ }
+
if (v.isParameter() && !v.isReturn())
{
// https://issues.dlang.org/show_bug.cgi?id=23191
@@ -1269,14 +1259,14 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
"scope parameter `%s` may not be returned", v.toChars()
);
result = true;
- continue;
+ return;
}
}
else
{
// https://issues.dlang.org/show_bug.cgi?id=17029
result |= sc.setUnsafeDIP1000(gag, e.loc, "scope variable `%s` may not be returned", v);
- continue;
+ return;
}
}
}
@@ -1293,7 +1283,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
}
}
- foreach (i, VarDeclaration v; er.byref[])
+ void onRef(VarDeclaration v, bool retRefTransition)
{
if (log)
{
@@ -1310,7 +1300,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
if (v.isParameter() && v.isReference())
{
- if (sc.setUnsafePreview(featureState, gag, e.loc, msg, e, v) ||
+ if (setUnsafePreview(&sc, featureState, gag, e.loc, msg, e, v) ||
sc.func.isSafeBypassingInference())
{
result = true;
@@ -1329,7 +1319,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
}
else
{
- if (er.refRetRefTransition[i])
+ if (retRefTransition)
{
result |= sc.setUnsafeDIP1000(gag, e.loc, msg, e, v);
}
@@ -1343,7 +1333,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
}
if (v.isDataseg())
- continue;
+ return;
const vsr = buildScopeRef(v.storage_class);
@@ -1358,7 +1348,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
if (checkScopeVarAddr(v, e, sc, gag))
{
result = true;
- continue;
+ return;
}
}
@@ -1367,7 +1357,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
if (p == sc.func)
{
escapingRef(v, FeatureState.enabled);
- continue;
+ return;
}
FuncDeclaration fd = p.isFuncDeclaration();
if (fd && sc.func.returnInprocess)
@@ -1394,7 +1384,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
if (p == sc.func && (vsr == ScopeRef.Ref || vsr == ScopeRef.RefScope) &&
inferReturn(sc.func, v, /*returnScope:*/ false))
{
- continue;
+ return;
}
else
{
@@ -1405,7 +1395,7 @@ 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, sc.useDIP25);
- continue;
+ return;
}
// Don't need to be concerned if v's parent does not return a ref
FuncDeclaration fd = p.isFuncDeclaration();
@@ -1418,7 +1408,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
if (!gag)
previewErrorFunc(sc.isDeprecated(), sc.useDIP25)(e.loc, msg, v.toChars());
result = true;
- continue;
+ return;
}
}
@@ -1426,10 +1416,16 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
}
}
- foreach (i, Expression ee; er.byexp[])
+ void onFunc(FuncDeclaration fd, bool called)
+ {
+ if (called && fd.isNested())
+ result |= sc.setUnsafeDIP1000(gag, e.loc, "escaping local variable through nested function `%s`", fd);
+ }
+
+ void onExp(Expression ee, bool retRefTransition)
{
if (log) printf("byexp %s\n", ee.toChars());
- if (er.expRetRefTransition[i])
+ if (retRefTransition)
{
result |= sc.setUnsafeDIP1000(gag, ee.loc,
"escaping reference to stack allocated value returned by `%s`", ee);
@@ -1441,6 +1437,15 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
result = true;
}
}
+
+
+ scope EscapeByResults er = EscapeByResults(&onRef, &onValue, &onFunc, &onExp);
+
+ if (refs)
+ escapeByRef(e, er);
+ else
+ escapeByValue(e, er);
+
return result;
}
@@ -1541,11 +1546,10 @@ private bool inferReturn(FuncDeclaration fd, VarDeclaration v, bool returnScope)
* Params:
* e = expression to be returned by value
* er = where to place collected data
- * live = if @live semantics apply, i.e. expressions `p`, `*p`, `**p`, etc., all return `p`.
- * retRefTransition = if `e` is returned through a `return ref scope` function call
+ * retRefTransition = if `e` is returned through a `return (ref) scope` function call
*/
public
-void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool retRefTransition = false)
+void escapeByValue(Expression e, ref scope EscapeByResults er, bool retRefTransition = false)
{
//printf("[%s] escapeByValue, e: %s\n", e.loc.toChars(), e.toChars());
@@ -1560,14 +1564,14 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
* but it'll be placed in static data so no need to check it.
*/
if (e.e1.op != EXP.structLiteral)
- escapeByRef(e.e1, er, live, retRefTransition);
+ escapeByRef(e.e1, er, retRefTransition);
}
void visitSymOff(SymOffExp e)
{
VarDeclaration v = e.var.isVarDeclaration();
if (v)
- er.pushRef(v, retRefTransition);
+ er.byRef(v, retRefTransition);
}
void visitVar(VarExp e)
@@ -1576,28 +1580,28 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
{
if (v.type.hasPointers() || // not tracking non-pointers
v.storage_class & STC.lazy_) // lazy variables are actually pointers
- er.byvalue.push(v);
+ er.byValue(v);
}
}
void visitThis(ThisExp e)
{
if (e.var)
- er.byvalue.push(e.var);
+ er.byValue(e.var);
}
void visitPtr(PtrExp e)
{
- if (live && e.type.hasPointers())
- escapeByValue(e.e1, er, live, retRefTransition);
+ if (er.live && e.type.hasPointers())
+ escapeByValue(e.e1, er, retRefTransition);
}
void visitDotVar(DotVarExp e)
{
auto t = e.e1.type.toBasetype();
- if (e.type.hasPointers() && (live || t.ty == Tstruct))
+ if (e.type.hasPointers() && (er.live || t.ty == Tstruct))
{
- escapeByValue(e.e1, er, live, retRefTransition);
+ escapeByValue(e.e1, er, retRefTransition);
}
}
@@ -1605,16 +1609,16 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
{
Type t = e.e1.type.toBasetype();
if (t.ty == Tclass || t.ty == Tpointer)
- escapeByValue(e.e1, er, live, retRefTransition);
+ escapeByValue(e.e1, er, retRefTransition);
else
- escapeByRef(e.e1, er, live, retRefTransition);
- er.byfunc.push(e.func);
+ escapeByRef(e.e1, er, retRefTransition);
+ er.byFunc(e.func, false);
}
void visitFunc(FuncExp e)
{
if (e.fd.tok == TOK.delegate_)
- er.byfunc.push(e.fd);
+ er.byFunc(e.fd, false);
}
void visitTuple(TupleExp e)
@@ -1628,11 +1632,11 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
if (tb.ty == Tsarray || tb.ty == Tarray)
{
if (e.basis)
- escapeByValue(e.basis, er, live, retRefTransition);
+ escapeByValue(e.basis, er, retRefTransition);
foreach (el; *e.elements)
{
if (el)
- escapeByValue(el, er, live, retRefTransition);
+ escapeByValue(el, er, retRefTransition);
}
}
}
@@ -1644,7 +1648,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
foreach (ex; *e.elements)
{
if (ex)
- escapeByValue(ex, er, live, retRefTransition);
+ escapeByValue(ex, er, retRefTransition);
}
}
}
@@ -1657,7 +1661,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
foreach (ex; *e.arguments)
{
if (ex)
- escapeByValue(ex, er, live, retRefTransition);
+ escapeByValue(ex, er, retRefTransition);
}
}
}
@@ -1669,10 +1673,10 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
Type tb = e.type.toBasetype();
if (tb.ty == Tarray && e.e1.type.toBasetype().ty == Tsarray)
{
- escapeByRef(e.e1, er, live, retRefTransition);
+ escapeByRef(e.e1, er, retRefTransition);
}
else
- escapeByValue(e.e1, er, live, retRefTransition);
+ escapeByValue(e.e1, er, retRefTransition);
}
void visitSlice(SliceExp e)
@@ -1687,7 +1691,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
return;
if (v.isTypesafeVariadicArray)
{
- er.byvalue.push(v);
+ er.byValue(v);
return;
}
}
@@ -1697,18 +1701,18 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
{
Type tb = e.type.toBasetype();
if (tb.ty != Tsarray)
- escapeByRef(e.e1, er, live, retRefTransition);
+ escapeByRef(e.e1, er, retRefTransition);
}
else
- escapeByValue(e.e1, er, live, retRefTransition);
+ escapeByValue(e.e1, er, retRefTransition);
}
void visitIndex(IndexExp e)
{
if (e.e1.type.toBasetype().ty == Tsarray ||
- live && e.type.hasPointers())
+ er.live && e.type.hasPointers())
{
- escapeByValue(e.e1, er, live, retRefTransition);
+ escapeByValue(e.e1, er, retRefTransition);
}
}
@@ -1717,30 +1721,30 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
Type tb = e.type.toBasetype();
if (tb.ty == Tpointer)
{
- escapeByValue(e.e1, er, live, retRefTransition);
- escapeByValue(e.e2, er, live, retRefTransition);
+ escapeByValue(e.e1, er, retRefTransition);
+ escapeByValue(e.e2, er, retRefTransition);
}
}
void visitBinAssign(BinAssignExp e)
{
- escapeByValue(e.e1, er, live, retRefTransition);
+ escapeByValue(e.e1, er, retRefTransition);
}
void visitAssign(AssignExp e)
{
- escapeByValue(e.e1, er, live, retRefTransition);
+ escapeByValue(e.e1, er, retRefTransition);
}
void visitComma(CommaExp e)
{
- escapeByValue(e.e2, er, live, retRefTransition);
+ escapeByValue(e.e2, er, retRefTransition);
}
void visitCond(CondExp e)
{
- escapeByValue(e.e1, er, live, retRefTransition);
- escapeByValue(e.e2, er, live, retRefTransition);
+ escapeByValue(e.e1, er, retRefTransition);
+ escapeByValue(e.e2, er, retRefTransition);
}
void visitCall(CallExp e)
@@ -1782,11 +1786,11 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
if (auto fd = dve.var.isFuncDeclaration())
if (fd.isCtorDeclaration() && tf.next.toBasetype().isTypeStruct())
{
- escapeByValue(arg, er, live, retRefTransition);
+ escapeByValue(arg, er, retRefTransition);
}
}
else
- escapeByValue(arg, er, live, retRefTransition);
+ escapeByValue(arg, er, true);
}
else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
{
@@ -1797,10 +1801,10 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
* as:
* p;
*/
- escapeByValue(arg, er, live, retRefTransition);
+ escapeByValue(arg, er, retRefTransition);
}
else
- escapeByRef(arg, er, live, retRefTransition);
+ escapeByRef(arg, er, retRefTransition);
}
}
}
@@ -1843,7 +1847,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
{
if (!tf.isref || tf.isctor)
- escapeByValue(dve.e1, er, live, retRefTransition);
+ escapeByValue(dve.e1, er, retRefTransition);
}
else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
{
@@ -1854,10 +1858,10 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
* as:
* this;
*/
- escapeByValue(dve.e1, er, live, retRefTransition);
+ escapeByValue(dve.e1, er, retRefTransition);
}
else
- escapeByRef(dve.e1, er, live, psr == ScopeRef.ReturnRef_Scope);
+ escapeByRef(dve.e1, er, psr == ScopeRef.ReturnRef_Scope);
}
}
@@ -1865,7 +1869,12 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
if (fd && fd.isNested())
{
if (tf.isreturn && tf.isScopeQual)
- er.pushExp(e, false);
+ {
+ if (tf.isreturnscope)
+ er.byFunc(fd, true);
+ else
+ er.byExp(e, false);
+ }
}
}
@@ -1875,7 +1884,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
if (t1.isTypeDelegate())
{
if (tf.isreturn)
- escapeByValue(e.e1, er, live, retRefTransition);
+ escapeByValue(e.e1, er, retRefTransition);
}
/* If it's a nested function that is 'return scope'
@@ -1886,7 +1895,12 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
if (fd && fd.isNested())
{
if (tf.isreturn && tf.isScopeQual)
- er.pushExp(e, false);
+ {
+ if (tf.isreturnscope)
+ er.byFunc(fd, true);
+ else
+ er.byExp(e, false);
+ }
}
}
}
@@ -1940,11 +1954,10 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
* Params:
* e = expression to be returned by 'ref'
* er = where to place collected data
- * live = if @live semantics apply, i.e. expressions `p`, `*p`, `**p`, etc., all return `p`.
- * retRefTransition = if `e` is returned through a `return ref scope` function call
+ * retRefTransition = if `e` is returned through a `return (ref) scope` function call
*/
private
-void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retRefTransition = false)
+void escapeByRef(Expression e, ref scope EscapeByResults er, bool retRefTransition = false)
{
//printf("[%s] escapeByRef, e: %s, retRefTransition: %d\n", e.loc.toChars(), e.toChars(), retRefTransition);
void visit(Expression e)
@@ -1965,27 +1978,27 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retR
if (ExpInitializer ez = v._init.isExpInitializer())
{
if (auto ce = ez.exp.isConstructExp())
- escapeByRef(ce.e2, er, live, retRefTransition);
+ escapeByRef(ce.e2, er, retRefTransition);
else
- escapeByRef(ez.exp, er, live, retRefTransition);
+ escapeByRef(ez.exp, er, retRefTransition);
}
}
else
- er.pushRef(v, retRefTransition);
+ er.byRef(v, retRefTransition);
}
}
void visitThis(ThisExp e)
{
if (e.var && e.var.toParent2().isFuncDeclaration().hasDualContext())
- escapeByValue(e, er, live, retRefTransition);
+ escapeByValue(e, er, retRefTransition);
else if (e.var)
- er.pushRef(e.var, retRefTransition);
+ er.byRef(e.var, retRefTransition);
}
void visitPtr(PtrExp e)
{
- escapeByValue(e.e1, er, live, retRefTransition);
+ escapeByValue(e.e1, er, retRefTransition);
}
void visitIndex(IndexExp e)
@@ -1996,17 +2009,17 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retR
VarDeclaration v = ve.var.isVarDeclaration();
if (v && v.isTypesafeVariadicArray)
{
- er.pushRef(v, retRefTransition);
+ er.byRef(v, retRefTransition);
return;
}
}
if (tb.ty == Tsarray)
{
- escapeByRef(e.e1, er, live, retRefTransition);
+ escapeByRef(e.e1, er, retRefTransition);
}
else if (tb.ty == Tarray)
{
- escapeByValue(e.e1, er, live, retRefTransition);
+ escapeByValue(e.e1, er, retRefTransition);
}
}
@@ -2017,40 +2030,40 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retR
foreach (ex; *e.elements)
{
if (ex)
- escapeByRef(ex, er, live, retRefTransition);
+ escapeByRef(ex, er, retRefTransition);
}
}
- er.pushExp(e, retRefTransition);
+ er.byExp(e, retRefTransition);
}
void visitDotVar(DotVarExp e)
{
Type t1b = e.e1.type.toBasetype();
if (t1b.ty == Tclass)
- escapeByValue(e.e1, er, live, retRefTransition);
+ escapeByValue(e.e1, er, retRefTransition);
else
- escapeByRef(e.e1, er, live, retRefTransition);
+ escapeByRef(e.e1, er, retRefTransition);
}
void visitBinAssign(BinAssignExp e)
{
- escapeByRef(e.e1, er, live, retRefTransition);
+ escapeByRef(e.e1, er, retRefTransition);
}
void visitAssign(AssignExp e)
{
- escapeByRef(e.e1, er, live, retRefTransition);
+ escapeByRef(e.e1, er, retRefTransition);
}
void visitComma(CommaExp e)
{
- escapeByRef(e.e2, er, live, retRefTransition);
+ escapeByRef(e.e2, er, retRefTransition);
}
void visitCond(CondExp e)
{
- escapeByRef(e.e1, er, live, retRefTransition);
- escapeByRef(e.e2, er, live, retRefTransition);
+ escapeByRef(e.e1, er, retRefTransition);
+ escapeByRef(e.e2, er, retRefTransition);
}
void visitCall(CallExp e)
@@ -2080,16 +2093,16 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retR
const stc = tf.parameterStorageClass(null, p);
ScopeRef psr = buildScopeRef(stc);
if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
- escapeByRef(arg, er, live, retRefTransition);
+ escapeByRef(arg, er, retRefTransition);
else if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
{
if (auto de = arg.isDelegateExp())
{
if (de.func.isNested())
- er.pushExp(de, false);
+ er.byExp(de, false);
}
else
- escapeByValue(arg, er, live, retRefTransition);
+ escapeByValue(arg, er, retRefTransition);
}
}
}
@@ -2103,7 +2116,7 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retR
// https://issues.dlang.org/show_bug.cgi?id=20149#c10
if (dve.var.isCtorDeclaration())
{
- er.pushExp(e, false);
+ er.byExp(e, false);
return;
}
@@ -2119,23 +2132,23 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retR
const psr = buildScopeRef(stc);
if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
- escapeByRef(dve.e1, er, live, psr == ScopeRef.ReturnRef_Scope);
+ escapeByRef(dve.e1, er, psr == ScopeRef.ReturnRef_Scope);
else if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
- escapeByValue(dve.e1, er, live, retRefTransition);
+ escapeByValue(dve.e1, er, retRefTransition);
// If it's also a nested function that is 'return ref'
if (FuncDeclaration fd = dve.var.isFuncDeclaration())
{
if (fd.isNested() && tf.isreturn)
{
- er.pushExp(e, false);
+ er.byExp(e, false);
}
}
}
// If it's a delegate, check it too
if (e.e1.op == EXP.variable && t1.ty == Tdelegate)
{
- escapeByValue(e.e1, er, live, retRefTransition);
+ escapeByValue(e.e1, er, retRefTransition);
}
/* If it's a nested function that is 'return ref'
@@ -2146,12 +2159,12 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retR
if (fd && fd.isNested())
{
if (tf.isreturn)
- er.pushExp(e, false);
+ er.byExp(e, false);
}
}
}
else
- er.pushExp(e, retRefTransition);
+ er.byExp(e, retRefTransition);
}
switch (e.op)
@@ -2181,15 +2194,8 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retR
public
struct EscapeByResults
{
- VarDeclarations byref; // array into which variables being returned by ref are inserted
- VarDeclarations byvalue; // array into which variables with values containing pointers are inserted
- private FuncDeclarations byfunc; // nested functions that are turned into delegates
- private Expressions byexp; // array into which temporaries being returned by ref are inserted
-
- import dmd.root.array: Array;
-
- /**
- * Whether the variable / expression went through a `return ref scope` function call
+ /*
+ * retRefTransition = Whether the variable / expression went through a `return (ref) scope` function call
*
* This is needed for the dip1000 by default transition, since the rules for
* disambiguating `return scope ref` have changed. Therefore, functions in legacy code
@@ -2197,46 +2203,26 @@ struct EscapeByResults
* are being escaped, which is an error even in `@system` code. By keeping track of this
* information, variables escaped through `return ref` can be treated as a deprecation instead
* of error, see test/fail_compilation/dip1000_deprecation.d
+ *
+ * Additionally, return scope can be inferred wrongly instead of scope, in which
+ * case the code could give false positives even without @safe or dip1000:
+ * https://issues.dlang.org/show_bug.cgi?id=23657
*/
- private Array!bool refRetRefTransition;
- private Array!bool expRetRefTransition;
-
- /** Reset arrays so the storage can be used again
- */
- void reset()
- {
- byref.setDim(0);
- byvalue.setDim(0);
- byfunc.setDim(0);
- byexp.setDim(0);
-
- refRetRefTransition.setDim(0);
- expRetRefTransition.setDim(0);
- }
-
- /**
- * Escape variable `v` by reference
- * Params:
- * v = variable to escape
- * retRefTransition = `v` is escaped through a `return ref scope` function call
- */
- void pushRef(VarDeclaration v, bool retRefTransition)
- {
- byref.push(v);
- refRetRefTransition.push(retRefTransition);
- }
- /**
- * Escape a reference to expression `e`
- * Params:
- * e = expression to escape
- * retRefTransition = `e` is escaped through a `return ref scope` function call
- */
- void pushExp(Expression e, bool retRefTransition)
- {
- byexp.push(e);
- expRetRefTransition.push(retRefTransition);
- }
+ /// called on variables being returned by ref / address
+ void delegate(VarDeclaration, bool retRefTransition) byRef;
+ /// called on variables with values containing pointers
+ void delegate(VarDeclaration) byValue;
+ /// called on nested functions that are turned into delegates
+ /// When `called` is true, it means the delegate escapes variables
+ /// from the closure through a call to it, while `false` means the
+ /// delegate itself escapes.
+ void delegate(FuncDeclaration, bool called) byFunc;
+ /// called when expression temporaries are being returned by ref / address
+ void delegate(Expression, bool retRefTransition) byExp;
+
+ /// if @live semantics apply, i.e. expressions `p`, `*p`, `**p`, etc., all return `p`.
+ bool live = false;
}
/*************************
@@ -2586,10 +2572,10 @@ private void addMaybe(VarDeclaration va, VarDeclaration v)
// `setUnsafePreview` partially evaluated for dip1000
public
-bool setUnsafeDIP1000(Scope* sc, bool gag, Loc loc, const(char)* msg,
+bool setUnsafeDIP1000(ref Scope sc, bool gag, Loc loc, const(char)* msg,
RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
{
- return setUnsafePreview(sc, sc.useDIP1000, gag, loc, msg, arg0, arg1, arg2);
+ return setUnsafePreview(&sc, sc.useDIP1000, gag, loc, msg, arg0, arg1, arg2);
}
/***************************************
@@ -2606,7 +2592,7 @@ bool setUnsafeDIP1000(Scope* sc, bool gag, Loc loc, const(char)* msg,
* Returns:
* true if taking the address of `v` is problematic because of the lack of transitive `scope`
*/
-private bool checkScopeVarAddr(VarDeclaration v, Expression e, Scope* sc, bool gag)
+private bool checkScopeVarAddr(VarDeclaration v, Expression e, ref Scope sc, bool gag)
{
if (v.storage_class & STC.temp)
return false;
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 479ad3a..a26f3ab 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -3824,6 +3824,7 @@ extern (C++) final class CastExp : UnaExp
{
Type to; // type to cast to
ubyte mod = cast(ubyte)~0; // MODxxxxx
+ bool trusted; // assume cast is safe
extern (D) this(const ref Loc loc, Expression e, Type t) @safe
{
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index 2f6bb84..1ff6c4c 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/dmd/expression.h
@@ -474,7 +474,7 @@ public:
d_bool isOriginal; // used when moving instances to indicate `this is this.origin`
OwnedBy ownedByCtfe;
- static StructLiteralExp *create(const Loc &loc, StructDeclaration *sd, void *elements, Type *stype = NULL);
+ static StructLiteralExp *create(const Loc &loc, StructDeclaration *sd, void *elements, Type *stype = nullptr);
bool equals(const RootObject * const o) const override;
StructLiteralExp *syntaxCopy() override;
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index 7ae7f40..3502a1c 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -3222,7 +3222,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
/* Argument value can be assigned to firstArg.
* Check arg to see if it matters.
*/
- err |= checkParamArgumentReturn(sc, firstArg, arg, p, false);
+ err |= checkParamArgumentReturn(*sc, firstArg, arg, p, false);
}
// Allow 'lazy' to imply 'scope' - lazy parameters can be passed along
// as lazy parameters to the next function, but that isn't escaping.
@@ -3236,7 +3236,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
* Check arg to see if it matters.
*/
VarDeclaration vPar = fd ? (fd.parameters ? (*fd.parameters)[i] : null) : null;
- err |= checkParamArgumentEscape(sc, fd, p.ident, vPar, cast(STC) pStc, arg, false, false);
+ err |= checkParamArgumentEscape(*sc, fd, p.ident, vPar, cast(STC) pStc, arg, false, false);
}
// Turning heap allocations into stack allocations is dangerous without dip1000, since `scope` inference
@@ -3375,7 +3375,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
}
err |= arg.checkValue();
err |= arg.checkSharedAccess(sc);
- err |= checkParamArgumentEscape(sc, fd, Id.dotdotdot, null, cast(STC) tf.parameterList.stc, arg, false, false);
+ err |= checkParamArgumentEscape(*sc, fd, Id.dotdotdot, null, cast(STC) tf.parameterList.stc, arg, false, false);
arg = arg.optimize(WANTvalue);
}
(*arguments)[i] = arg;
@@ -3575,7 +3575,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
*/
if (global.params.useDIP1021 && (tf.trust == TRUST.safe || tf.trust == TRUST.default_) ||
tf.islive)
- err |= checkMutableArguments(sc, fd, tf, ethis, arguments, false);
+ err |= checkMutableArguments(*sc, fd, tf, ethis, arguments, false);
// If D linkage and variadic, add _arguments[] as first argument
if (tf.isDstyleVariadic())
@@ -4466,7 +4466,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
semanticTypeInfo(sc, e.type);
- if (checkAssocArrayLiteralEscape(sc, e, false))
+ if (checkAssocArrayLiteralEscape(*sc, e, false))
return setError();
result = e;
@@ -5206,7 +5206,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
*/
foreach (arg; *exp.arguments)
{
- if (arg && checkNewEscape(sc, arg, false))
+ if (arg && checkNewEscape(*sc, arg, false))
return setError();
}
}
@@ -5335,7 +5335,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
lowering = new DotIdExp(exp.loc, lowering, Id.object);
auto tbn = exp.type.nextOf();
- while (tbn.ty == Tarray)
+ size_t i = nargs;
+ while (tbn.ty == Tarray && --i)
tbn = tbn.nextOf();
auto unqualTbn = tbn.unqualify(MODFlags.wild | MODFlags.const_ |
MODFlags.immutable_ | MODFlags.shared_);
@@ -6316,7 +6317,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
tthis = ue.e1.type;
if (!(exp.f.type.ty == Tfunction && (cast(TypeFunction)exp.f.type).isScopeQual))
{
- if (checkParamArgumentEscape(sc, exp.f, Id.This, exp.f.vthis, STC.undefined_, ethis, false, false))
+ if (checkParamArgumentEscape(*sc, exp.f, Id.This, exp.f.vthis, STC.undefined_, ethis, false, false))
return setError();
}
}
@@ -8046,7 +8047,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.msg = resolveProperties(sc, exp.msg);
exp.msg = exp.msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf());
exp.msg = exp.msg.optimize(WANTvalue);
- checkParamArgumentEscape(sc, null, null, null, STC.undefined_, exp.msg, true, false);
+ checkParamArgumentEscape(*sc, null, null, null, STC.undefined_, exp.msg, true, false);
}
if (exp.msg && exp.msg.op == EXP.error)
@@ -10054,7 +10055,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
semanticTypeInfo(sc, taa);
- checkNewEscape(sc, exp.e2, false);
+ checkNewEscape(*sc, exp.e2, false);
exp.type = taa.next;
break;
@@ -10088,7 +10089,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (length <= index)
{
- error(exp.loc, "array index `[%llu]` is outside array bounds `[0 .. %llu]`", index, cast(ulong)length);
+ error(exp.loc, "sequence index `[%llu]` is outside bounds `[0 .. %llu]`", index, cast(ulong)length);
return setError();
}
Expression e;
@@ -10750,7 +10751,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
dvx.e1 = e1x;
auto cx = cast(CallExp)ce.copy();
cx.e1 = dvx;
- if (checkConstructorEscape(sc, cx, false))
+ if (checkConstructorEscape(*sc, cx, false))
return setError();
Expression e0;
@@ -11511,9 +11512,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* `checkAssignExp` expects only AssignExps.
*/
if (res == exp) // no `AA[k] = v` rewrite was performed
- checkAssignEscape(sc, res, false, false);
+ checkAssignEscape(*sc, res, false, false);
else
- checkNewEscape(sc, assignElem, false); // assigning to AA puts it on heap
+ checkNewEscape(*sc, assignElem, false); // assigning to AA puts it on heap
if (auto ae = res.isConstructExp())
{
@@ -11861,10 +11862,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (tb2.checkPostblit(exp.e2.loc, sc))
return setError();
- if (checkNewEscape(sc, exp.e2, false))
+ if (checkNewEscape(*sc, exp.e2, false))
return setError();
- exp = new CatElemAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, tb1next));
+ auto ecast = exp.e2.castTo(sc, tb1next);
+ if (auto ce = ecast.isCastExp())
+ ce.trusted = true;
+
+ exp = new CatElemAssignExp(exp.loc, exp.type, exp.e1, ecast);
exp.e2 = doCopyOrMove(sc, exp.e2);
}
else if (tb1.ty == Tarray &&
@@ -11938,9 +11943,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
auto assignElem = exp.e2;
auto res = exp.reorderSettingAAElem(sc);
if (res != exp) // `AA[k] = v` rewrite was performed
- checkNewEscape(sc, assignElem, false);
+ checkNewEscape(*sc, assignElem, false);
else if (exp.op == EXP.concatenateElemAssign || exp.op == EXP.concatenateDcharAssign)
- checkAssignEscape(sc, res, false, false);
+ checkAssignEscape(*sc, res, false, false);
result = res;
@@ -12511,7 +12516,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.e2 = exp.e2.implicitCastTo(sc, tb1next);
exp.type = tb1next.arrayOf();
L2elem:
- if (checkNewEscape(sc, exp.e2, false))
+ if (checkNewEscape(*sc, exp.e2, false))
return setError();
result = exp.optimize(WANTvalue);
trySetCatExpLowering(result);
@@ -12545,7 +12550,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
exp.e1 = exp.e1.implicitCastTo(sc, tb2next);
exp.type = tb2next.arrayOf();
L1elem:
- if (checkNewEscape(sc, exp.e1, false))
+ if (checkNewEscape(*sc, exp.e1, false))
return setError();
result = exp.optimize(WANTvalue);
trySetCatExpLowering(result);
@@ -15331,8 +15336,10 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc)
Expression visitSlice(SliceExp exp)
{
exp.e1 = exp.e1.resolveLoc(loc, sc);
- exp.lwr = exp.lwr.resolveLoc(loc, sc);
- exp.upr = exp.upr.resolveLoc(loc, sc);
+ if (exp.lwr)
+ exp.lwr = exp.lwr.resolveLoc(loc, sc);
+ if (exp.upr)
+ exp.upr = exp.upr.resolveLoc(loc, sc);
return exp;
}
@@ -15732,7 +15739,15 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, const(char)* action
return visit(_this);
}
if (_this.isLvalue())
+ {
+ with (_this)
+ if (!trusted && !e1.type.pointerTo().implicitConvTo(to.pointerTo()))
+ sc.setUnsafePreview(FeatureState.default_, false, loc,
+ "cast from `%s` to `%s` cannot be used as an lvalue in @safe code",
+ e1.type, to);
+
return _this;
+ }
return visit(_this);
}
diff --git a/gcc/d/dmd/file_manager.d b/gcc/d/dmd/file_manager.d
index c696a5c..6ad3d62 100644
--- a/gcc/d/dmd/file_manager.d
+++ b/gcc/d/dmd/file_manager.d
@@ -11,10 +11,12 @@
module dmd.file_manager;
import core.stdc.stdio;
+import dmd.common.outbuffer;
import dmd.root.stringtable : StringTable;
import dmd.root.file : File, Buffer;
import dmd.root.filename : FileName, isDirSeparator;
import dmd.root.string : toDString;
+import dmd.errors;
import dmd.globals;
import dmd.identifier;
import dmd.location;
@@ -70,44 +72,84 @@ private struct PathStack
}
}
-final class FileManager
+/***************************
+ * Cache path lookups so the operating system
+ * is only consulted once for each path.
+ */
+private struct PathCache
{
- private StringTable!(const(ubyte)[]) files; // contents of files indexed by file name
- private StringTable!(bool) packageStatus;
+ /* for filespec "a/b/c/d.ext"
+ * a b and c are directories, a, a/b, a/b/c are paths.
+ */
- // check if the package path of the given path exists. The input path is
- // expected to contain the full path to the module, so the parent
- // directories of that path are checked.
- private bool packageExists(const(char)[] p) nothrow
+ StringTable!(bool) pathStatus; // cached value of does a path exist or not
+
+ nothrow:
+
+ /**
+ * Determine if the path part of path/filename exists.
+ * Cache the results for the path and each left-justified subpath of the path.
+ * Params:
+ * filespec = path/filename
+ * Returns:
+ * true if path exists, false if it does not
+ */
+ bool pathExists(const(char)[] filespec) nothrow
{
- // step 1, look for the closest parent path that is cached
+ /* look for the longest leftmost parent path that is cached
+ * by starting at the right and working to the left
+ */
bool exists = true;
- auto st = PathStack(p);
+ auto st = PathStack(filespec);
while (st.up) {
- if (auto cached = packageStatus.lookup(st.cur)) {
+ if (auto cached = pathStatus.lookup(st.cur)) {
exists = cached.value;
break;
}
}
- // found a parent that is cached (or reached the end of the stack).
- // step 2, traverse back up the stack storing either false if the
- // parent doesn't exist, or the result of the `exists` call if it does.
+ /* found a parent path that is cached (or reached the left end of the path).
+ * Now move right caching the results of those directories.
+ * Once a directory is found to not exist, all the directories
+ * to the right of it do not exist
+ */
while (st.down) {
if (!exists)
- packageStatus.insert(st.cur, false);
+ pathStatus.insert(st.cur, false);
else
- exists = packageStatus.insert(st.cur, FileName.exists(st.cur) == 2).value;
+ exists = pathStatus.insert(st.cur, FileName.exists(st.cur) == 2).value;
}
- // at this point, exists should be the answer.
return exists;
}
+ /**
+ * Ask if path ends in a directory.
+ * Cache result for speed.
+ * Params:
+ * path = a path
+ * Returns:
+ * true if it's a path, false if not
+ */
+ bool isExistingPath(const char[] path)
+ {
+ auto cached = pathStatus.lookup(path);
+ if (!cached)
+ cached = pathStatus.insert(path, FileName.exists(path) == 2);
+ return cached.value;
+ }
+}
+
+final class FileManager
+{
+ private StringTable!(const(ubyte)[]) files; // contents of files indexed by file name
+
+ private PathCache pathCache;
+
///
public this () nothrow
{
this.files._init();
- this.packageStatus._init();
+ this.pathCache.pathStatus._init();
}
nothrow:
@@ -117,18 +159,18 @@ nothrow:
* Does not open the file.
* Params:
* filename = as supplied by the user
- * path = path to look for filename
+ * paths = paths to look for filename
* Returns:
* the found file name or
* `null` if it is not different from filename.
*/
- const(char)[] lookForSourceFile(const char[] filename, const char*[] path)
+ const(char)[] lookForSourceFile(const char[] filename, const char*[] paths)
{
//printf("lookForSourceFile(`%.*s`)\n", cast(int)filename.length, filename.ptr);
- /* Search along path[] for .di file, then .d file.
+ /* Search along paths[] for .di file, then .d file.
*/
// see if we should check for the module locally.
- bool checkLocal = packageExists(filename);
+ bool checkLocal = pathCache.pathExists(filename);
const sdi = FileName.forceExt(filename, hdr_ext);
if (checkLocal && FileName.exists(sdi) == 1)
return sdi;
@@ -144,12 +186,9 @@ nothrow:
if (checkLocal)
{
- auto cached = packageStatus.lookup(filename);
- if (!cached)
- cached = packageStatus.insert(filename, FileName.exists(filename) == 2);
- if (cached.value)
+ if (pathCache.isExistingPath(filename))
{
- /* The filename exists and it's a directory.
+ /* The filename exists but it's a directory.
* Therefore, the result should be: filename/package.d
* iff filename/package.d is a file
*/
@@ -167,15 +206,15 @@ nothrow:
if (FileName.absolute(filename))
return null;
- if (!path.length)
+ if (!paths.length)
return null;
- foreach (entry; path)
+ foreach (entry; paths)
{
const p = entry.toDString();
const(char)[] n = FileName.combine(p, sdi);
- if (!packageExists(n)) {
+ if (!pathCache.pathExists(n)) {
FileName.free(n.ptr);
continue; // no need to check for anything else.
}
@@ -190,19 +229,11 @@ nothrow:
}
FileName.free(n.ptr);
- const b = FileName.removeExt(filename);
- n = FileName.combine(p, b);
- FileName.free(b.ptr);
-
+ n = FileName.combine(p, FileName.sansExt(filename));
scope(exit) FileName.free(n.ptr);
// also cache this if we are looking for package.d[i]
- auto cached = packageStatus.lookup(n);
- if (!cached) {
- cached = packageStatus.insert(n, FileName.exists(n) == 2);
- }
-
- if (cached.value)
+ if (pathCache.isExistingPath(n))
{
const n2i = FileName.combine(n, package_di);
if (FileName.exists(n2i) == 1)
@@ -216,7 +247,7 @@ nothrow:
}
}
- /* ImportC: No D modules found, now search along path[] for .i file, then .c file.
+ /* ImportC: No D modules found, now search along paths[] for .i file, then .c file.
*/
const si = FileName.forceExt(filename, i_ext);
if (FileName.exists(si) == 1)
@@ -227,7 +258,7 @@ nothrow:
if (FileName.exists(sc) == 1)
return sc;
scope(exit) FileName.free(sc.ptr);
- foreach (entry; path)
+ foreach (entry; paths)
{
const p = entry.toDString();
@@ -261,128 +292,31 @@ nothrow:
if (auto val = files.lookup(name)) // if `name` is cached
return val.value; // return its contents
+ OutBuffer buf;
if (name == "__stdin.d") // special name for reading from stdin
{
- const ubyte[] buffer = readFromStdin().extractSlice();
- if (this.files.insert(name, buffer) is null)
- // this.files already contains the name
- assert(0, "stdin: Insert after lookup failure should never return `null`");
- return buffer;
+ if (readFromStdin(buf))
+ fatal();
}
+ else
+ {
+ if (FileName.exists(name) != 1) // if not an ordinary file
+ return null;
- if (FileName.exists(name) != 1) // if not an ordinary file
- return null;
+ if (File.read(name, buf))
+ return null; // failed
+ }
- auto readResult = File.read(name);
- if (!readResult.success)
- return null;
+ buf.write32(0); // terminating dchar 0
- const ubyte[] fb = readResult.extractSlice();
+ const length = buf.length;
+ const ubyte[] fb = cast(ubyte[])(buf.extractSlice()[0 .. length - 4]);
if (files.insert(name, fb) is null)
assert(0, "Insert after lookup failure should never return `null`");
return fb;
}
- /**********************************
- * Take `text` and turn it into an InputRange that emits
- * slices into `text` for each line.
- * Params:
- * text = array of characters
- * Returns:
- * InputRange accessing `text` as a sequence of lines
- * Reference:
- * `std.string.splitLines()`
- */
- auto splitLines(const char[] text)
- {
- struct Range
- {
- @safe:
- @nogc:
- nothrow:
- pure:
- private:
-
- const char[] text;
- size_t index; // index of start of line
- size_t eolIndex; // index of end of line before newline characters
- size_t nextIndex; // index past end of line
-
- public this(const char[] text)
- {
- this.text = text;
- }
-
- public bool empty() { return index == text.length; }
-
- public void popFront() { advance(); index = nextIndex; }
-
- public const(char)[] front() { advance(); return text[index .. eolIndex]; }
-
- private void advance()
- {
- if (index != nextIndex) // if already advanced
- return;
-
- for (size_t i = index; i < text.length; ++i)
- {
- switch (text[i])
- {
- case '\v', '\f', '\n':
- eolIndex = i;
- nextIndex = i + 1;
- return;
-
- case '\r':
- if (i + 1 < text.length && text[i + 1] == '\n') // decode "\r\n"
- {
- eolIndex = i;
- nextIndex = i + 2;
- return;
- }
- eolIndex = i;
- nextIndex = i + 1;
- return;
-
- /* Manually decode:
- * NEL is C2 85
- */
- case 0xC2:
- if (i + 1 < text.length && text[i + 1] == 0x85)
- {
- eolIndex = i;
- nextIndex = i + 2;
- return;
- }
- break;
-
- /* Manually decode:
- * lineSep is E2 80 A8
- * paraSep is E2 80 A9
- */
- case 0xE2:
- if (i + 2 < text.length &&
- text[i + 1] == 0x80 &&
- (text[i + 2] == 0xA8 || text[i + 2] == 0xA9)
- )
- {
- eolIndex = i;
- nextIndex = i + 3;
- return;
- }
- break;
-
- default:
- break;
- }
- }
- }
- }
-
- return Range(text);
- }
-
/**
* Adds the contents of a file to the table.
* Params:
@@ -398,44 +332,34 @@ nothrow:
}
}
-private Buffer readFromStdin() nothrow
+private bool readFromStdin(ref OutBuffer sink) nothrow
{
import core.stdc.stdio;
import dmd.errors;
- import dmd.root.rmem;
- enum bufIncrement = 128 * 1024;
- size_t pos = 0;
- size_t sz = bufIncrement;
+ enum BufIncrement = 128 * 1024;
- ubyte* buffer = null;
- for (;;)
+ for (size_t j; 1; ++j)
{
- buffer = cast(ubyte*)mem.xrealloc(buffer, sz + 4); // +2 for sentinel and +2 for lexer
+ char[] buffer = sink.allocate(BufIncrement);
// Fill up buffer
+ size_t filled = 0;
do
{
- assert(sz > pos);
- size_t rlen = fread(buffer + pos, 1, sz - pos, stdin);
- pos += rlen;
+ filled += fread(buffer.ptr + filled, 1, buffer.length - filled, stdin);
if (ferror(stdin))
{
import core.stdc.errno;
error(Loc.initial, "cannot read from stdin, errno = %d", errno);
- fatal();
+ return true;
}
- if (feof(stdin))
+ if (feof(stdin)) // successful completion
{
- // We're done
- assert(pos < sz + 2);
- buffer[pos .. pos + 4] = '\0';
- return Buffer(buffer[0 .. pos]);
+ sink.setsize(j * BufIncrement + filled);
+ return false;
}
- } while (pos < sz);
-
- // Buffer full, expand
- sz += bufIncrement;
+ } while (filled < BufIncrement);
}
assert(0);
diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index 7003c2b..f3d7aba 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/dmd/func.d
@@ -109,7 +109,8 @@ enum BUILTIN : ubyte
yl2xp1,
toPrecFloat,
toPrecDouble,
- toPrecReal
+ toPrecReal,
+ ctfeWrite,
}
private struct FUNCFLAG
@@ -513,149 +514,6 @@ extern (C++) class FuncDeclaration : Declaration
}
/********************************************
- * Find function in overload list that exactly matches t.
- */
- extern (D) final FuncDeclaration overloadExactMatch(Type t)
- {
- FuncDeclaration fd;
- overloadApply(this, (Dsymbol s)
- {
- auto f = s.isFuncDeclaration();
- if (!f)
- return 0;
- if (f.storage_class & STC.disable)
- return 0;
- if (t.equals(f.type))
- {
- fd = f;
- return 1;
- }
-
- /* Allow covariant matches, as long as the return type
- * is just a const conversion.
- * This allows things like pure functions to match with an impure function type.
- */
- if (t.ty == Tfunction)
- {
- auto tf = cast(TypeFunction)f.type;
- if (tf.covariant(t) == Covariant.yes &&
- tf.nextOf().implicitConvTo(t.nextOf()) >= MATCH.constant)
- {
- fd = f;
- return 1;
- }
- }
- return 0;
- });
- return fd;
- }
-
- /********************************************
- * Find function in overload list that matches to the 'this' modifier.
- * There's four result types.
- *
- * 1. If the 'tthis' matches only one candidate, it's an "exact match".
- * Returns the function and 'hasOverloads' is set to false.
- * eg. If 'tthis" is mutable and there's only one mutable method.
- * 2. If there's two or more match candidates, but a candidate function will be
- * a "better match".
- * Returns the better match function but 'hasOverloads' is set to true.
- * eg. If 'tthis' is mutable, and there's both mutable and const methods,
- * the mutable method will be a better match.
- * 3. If there's two or more match candidates, but there's no better match,
- * Returns null and 'hasOverloads' is set to true to represent "ambiguous match".
- * eg. If 'tthis' is mutable, and there's two or more mutable methods.
- * 4. If there's no candidates, it's "no match" and returns null with error report.
- * e.g. If 'tthis' is const but there's no const methods.
- */
- extern (D) final FuncDeclaration overloadModMatch(const ref Loc loc, Type tthis, ref bool hasOverloads)
- {
- //printf("FuncDeclaration::overloadModMatch('%s')\n", toChars());
- MatchAccumulator m;
- overloadApply(this, (Dsymbol s)
- {
- auto f = s.isFuncDeclaration();
- if (!f || f == m.lastf) // skip duplicates
- return 0;
-
- auto tf = f.type.toTypeFunction();
- //printf("tf = %s\n", tf.toChars());
-
- MATCH match;
- if (tthis) // non-static functions are preferred than static ones
- {
- if (f.needThis())
- match = f.isCtorDeclaration() ? MATCH.exact : MODmethodConv(tthis.mod, tf.mod);
- else
- match = MATCH.constant; // keep static function in overload candidates
- }
- else // static functions are preferred than non-static ones
- {
- if (f.needThis())
- match = MATCH.convert;
- else
- match = MATCH.exact;
- }
- if (match == MATCH.nomatch)
- return 0;
-
- if (match > m.last) goto LcurrIsBetter;
- if (match < m.last) goto LlastIsBetter;
-
- // See if one of the matches overrides the other.
- if (m.lastf.overrides(f)) goto LlastIsBetter;
- if (f.overrides(m.lastf)) goto LcurrIsBetter;
-
- //printf("\tambiguous\n");
- m.nextf = f;
- m.count++;
- return 0;
-
- LlastIsBetter:
- //printf("\tlastbetter\n");
- m.count++; // count up
- return 0;
-
- LcurrIsBetter:
- //printf("\tisbetter\n");
- if (m.last <= MATCH.convert)
- {
- // clear last secondary matching
- m.nextf = null;
- m.count = 0;
- }
- m.last = match;
- m.lastf = f;
- m.count++; // count up
- return 0;
- });
-
- if (m.count == 1) // exact match
- {
- hasOverloads = false;
- }
- else if (m.count > 1) // better or ambiguous match
- {
- hasOverloads = true;
- }
- else // no match
- {
- hasOverloads = true;
- auto tf = this.type.toTypeFunction();
- assert(tthis);
- assert(!MODimplicitConv(tthis.mod, tf.mod)); // modifier mismatch
- {
- OutBuffer thisBuf, funcBuf;
- MODMatchToBuffer(&thisBuf, tthis.mod, tf.mod);
- MODMatchToBuffer(&funcBuf, tf.mod, tthis.mod);
- .error(loc, "%smethod %s is not callable using a %sobject", kind, toPrettyChars,
- funcBuf.peekChars(), this.toPrettyChars(), thisBuf.peekChars());
- }
- }
- return m.lastf;
- }
-
- /********************************************
* find function template root in overload list
*/
extern (D) final TemplateDeclaration findTemplateDeclRoot()
@@ -855,43 +713,6 @@ extern (C++) class FuncDeclaration : Declaration
return level;
}
- /***********************************
- * Determine lexical level difference from `this` to nested function `fd`.
- * Issue error if `this` cannot call `fd`.
- *
- * Params:
- * loc = location for error messages
- * sc = context
- * fd = target of call
- * decl = The `Declaration` that triggered this check.
- * Used to provide a better error message only.
- * Returns:
- * 0 same level
- * >0 decrease nesting by number
- * -1 increase nesting by 1 (`fd` is nested within 'this')
- * LevelError error
- */
- extern (D) final int getLevelAndCheck(const ref Loc loc, Scope* sc, FuncDeclaration fd,
- Declaration decl)
- {
- int level = getLevel(fd, sc.intypeof);
- if (level != LevelError)
- return level;
-
- // Don't give error if in template constraint
- if (!(sc.flags & SCOPE.constraint))
- {
- const(char)* xstatic = isStatic() ? "`static` " : "";
- // better diagnostics for static functions
- .error(loc, "%s%s `%s` cannot access %s `%s` in frame of function `%s`",
- xstatic, kind(), toPrettyChars(), decl.kind(), decl.toChars(),
- fd.toPrettyChars());
- .errorSupplemental(decl.loc, "`%s` declared here", decl.toChars());
- return LevelError;
- }
- return 1;
- }
-
enum LevelError = -2;
override const(char)* toPrettyChars(bool QualifyTypes = false)
@@ -990,47 +811,6 @@ extern (C++) class FuncDeclaration : Declaration
return false;
}
- /**********************************
- * Decide if attributes for this function can be inferred from examining
- * the function body.
- * Returns:
- * true if can
- */
- final bool canInferAttributes(Scope* sc)
- {
- if (!fbody)
- return false;
-
- if (isVirtualMethod() &&
- /*
- * https://issues.dlang.org/show_bug.cgi?id=21719
- *
- * If we have an auto virtual function we can infer
- * the attributes.
- */
- !(inferRetType && !isCtorDeclaration()))
- return false; // since they may be overridden
-
- if (sc.func &&
- /********** this is for backwards compatibility for the moment ********/
- (!isMember() || sc.func.isSafeBypassingInference() && !isInstantiated()))
- return true;
-
- if (isFuncLiteralDeclaration() || // externs are not possible with literals
- (storage_class & STC.inference) || // do attribute inference
- (inferRetType && !isCtorDeclaration()))
- return true;
-
- if (isInstantiated())
- {
- auto ti = parent.isTemplateInstance();
- if (ti is null || ti.isTemplateMixin() || ti.tempdecl.ident == ident)
- return true;
- }
-
- return false;
- }
-
/*****************************************
* Initialize for inferring the attributes of this function.
*/
@@ -1633,101 +1413,6 @@ extern (C++) class FuncDeclaration : Declaration
return result;
}
- /*********************************************
- * In the current function, we are calling 'this' function.
- * 1. Check to see if the current function can call 'this' function, issue error if not.
- * 2. If the current function is not the parent of 'this' function, then add
- * the current function to the list of siblings of 'this' function.
- * 3. If the current function is a literal, and it's accessing an uplevel scope,
- * then mark it as a delegate.
- * Returns true if error occurs.
- */
- extern (D) final bool checkNestedReference(Scope* sc, const ref Loc loc)
- {
- //printf("FuncDeclaration::checkNestedReference() %s\n", toPrettyChars());
-
- if (auto fld = this.isFuncLiteralDeclaration())
- {
- if (fld.tok == TOK.reserved)
- {
- fld.tok = TOK.function_;
- fld.vthis = null;
- }
- }
-
- if (!parent || parent == sc.parent)
- return false;
- if (ident == Id.require || ident == Id.ensure)
- return false;
- if (!isThis() && !isNested())
- return false;
-
- // The current function
- FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
- if (!fdthis)
- return false; // out of function scope
-
- Dsymbol p = toParentLocal();
- Dsymbol p2 = toParent2();
-
- // Function literals from fdthis to p must be delegates
- ensureStaticLinkTo(fdthis, p);
- if (p != p2)
- ensureStaticLinkTo(fdthis, p2);
-
- if (isNested())
- {
- // The function that this function is in
- bool checkEnclosing(FuncDeclaration fdv)
- {
- if (!fdv)
- return false;
- if (fdv == fdthis)
- return false;
-
- //printf("this = %s in [%s]\n", this.toChars(), this.loc.toChars());
- //printf("fdv = %s in [%s]\n", fdv .toChars(), fdv .loc.toChars());
- //printf("fdthis = %s in [%s]\n", fdthis.toChars(), fdthis.loc.toChars());
-
- // Add this function to the list of those which called us
- if (fdthis != this)
- {
- bool found = false;
- for (size_t i = 0; i < siblingCallers.length; ++i)
- {
- if (siblingCallers[i] == fdthis)
- found = true;
- }
- if (!found)
- {
- //printf("\tadding sibling %s to %s\n", fdthis.toPrettyChars(), toPrettyChars());
- if (!sc.intypeof && !(sc.flags & SCOPE.compile))
- {
- siblingCallers.push(fdthis);
- computedEscapingSiblings = false;
- }
- }
- }
-
- const lv = fdthis.getLevelAndCheck(loc, sc, fdv, this);
- if (lv == LevelError)
- return true; // error
- if (lv == -1)
- return false; // downlevel call
- if (lv == 0)
- return false; // same level call
-
- return false; // Uplevel call
- }
-
- if (checkEnclosing(p.isFuncDeclaration()))
- return true;
- if (checkEnclosing(p == p2 ? null : p2.isFuncDeclaration()))
- return true;
- }
- return false;
- }
-
/*******************************
* Look at all the variables in this function that are referenced
* by nested functions, and determine if a closure needs to be
@@ -1923,147 +1608,6 @@ extern (C++) class FuncDeclaration : Declaration
}
/****************************************************
- * Check whether result variable can be built.
- * Returns:
- * `true` if the function has a return type that
- * is different from `void`.
- */
- extern (D) private bool canBuildResultVar()
- {
- auto f = cast(TypeFunction)type;
- return f && f.nextOf() && f.nextOf().toBasetype().ty != Tvoid;
- }
-
- /****************************************************
- * Merge into this function the 'in' contracts of all it overrides.
- * 'in's are OR'd together, i.e. only one of them needs to pass.
- */
- extern (D) final Statement mergeFrequire(Statement sf, Expressions* params)
- {
- /* If a base function and its override both have an IN contract, then
- * only one of them needs to succeed. This is done by generating:
- *
- * void derived.in() {
- * try {
- * base.in();
- * }
- * catch () {
- * ... body of derived.in() ...
- * }
- * }
- *
- * So if base.in() doesn't throw, derived.in() need not be executed, and the contract is valid.
- * If base.in() throws, then derived.in()'s body is executed.
- */
-
- foreach (fdv; foverrides)
- {
- /* The semantic pass on the contracts of the overridden functions must
- * be completed before code generation occurs.
- * https://issues.dlang.org/show_bug.cgi?id=3602
- */
- if (fdv.frequires && fdv.semanticRun != PASS.semantic3done)
- {
- assert(fdv._scope);
- Scope* sc = fdv._scope.push();
- sc.stc &= ~STC.override_;
- fdv.semantic3(sc);
- sc.pop();
- }
-
- sf = fdv.mergeFrequire(sf, params);
- if (!sf || !fdv.fdrequire)
- return null;
- //printf("fdv.frequire: %s\n", fdv.frequire.toChars());
- /* Make the call:
- * try { __require(params); }
- * catch (Throwable) { frequire; }
- */
- params = Expression.arraySyntaxCopy(params);
- Expression e = new CallExp(loc, new VarExp(loc, fdv.fdrequire, false), params);
- Statement s2 = new ExpStatement(loc, e);
-
- auto c = new Catch(loc, getThrowable(), null, sf);
- c.internalCatch = true;
- auto catches = new Catches();
- catches.push(c);
- sf = new TryCatchStatement(loc, s2, catches);
- }
- return sf;
- }
-
- /****************************************************
- * Merge into this function the 'in' contracts of all it overrides.
- */
- extern (D) final Statement mergeFrequireInclusivePreview(Statement sf, Expressions* params)
- {
- /* If a base function and its override both have an IN contract, then
- * the override in contract must widen the guarantee of the base contract.
- * This is checked by generating:
- *
- * void derived.in() {
- * try {
- * ... body of derived.in() ...
- * }
- * catch () {
- * // derived in rejected this argument. so parent must also reject it, or we've tightened the contract.
- * base.in();
- * assert(false, "Logic error: " ~ thr.msg);
- * }
- * }
- */
-
- foreach (fdv; foverrides)
- {
- /* The semantic pass on the contracts of the overridden functions must
- * be completed before code generation occurs.
- * https://issues.dlang.org/show_bug.cgi?id=3602
- */
- if (fdv.frequires && fdv.semanticRun != PASS.semantic3done)
- {
- assert(fdv._scope);
- Scope* sc = fdv._scope.push();
- sc.stc &= ~STC.override_;
- fdv.semantic3(sc);
- sc.pop();
- }
-
- sf = fdv.mergeFrequireInclusivePreview(sf, params);
- if (sf && fdv.fdrequire)
- {
- const loc = this.fdrequire.loc;
-
- //printf("fdv.frequire: %s\n", fdv.frequire.toChars());
- /* Make the call:
- * try { frequire; }
- * catch (Throwable thr) { __require(params); assert(false, "Logic error: " ~ thr.msg); }
- */
- Identifier id = Identifier.generateId("thr");
- params = Expression.arraySyntaxCopy(params);
- Expression e = new CallExp(loc, new VarExp(loc, fdv.fdrequire, false), params);
- Statement s2 = new ExpStatement(loc, e);
- // assert(false, ...)
- // TODO make this a runtime helper to allow:
- // - chaining the original expression
- // - nogc concatenation
- Expression msg = new StringExp(loc, "Logic error: in-contract was tighter than parent in-contract");
- Statement fail = new ExpStatement(loc, new AssertExp(loc, IntegerExp.literal!0, msg));
-
- Statement s3 = new CompoundStatement(loc, s2, fail);
-
- auto c = new Catch(loc, getThrowable(), id, s3);
- c.internalCatch = true;
- auto catches = new Catches();
- catches.push(c);
- sf = new TryCatchStatement(loc, sf, catches);
- }
- else
- return null;
- }
- return sf;
- }
-
- /****************************************************
* Determine whether an 'out' contract is declared inside
* the given function or any of its overrides.
* Params:
@@ -2084,232 +1628,6 @@ extern (C++) class FuncDeclaration : Declaration
return false;
}
- /****************************************************
- * Rewrite contracts as statements.
- */
- final void buildEnsureRequire()
- {
-
- if (frequires)
- {
- /* in { statements1... }
- * in { statements2... }
- * ...
- * becomes:
- * in { { statements1... } { statements2... } ... }
- */
- assert(frequires.length);
- auto loc = (*frequires)[0].loc;
- auto s = new Statements;
- foreach (r; *frequires)
- {
- s.push(new ScopeStatement(r.loc, r, r.loc));
- }
- frequire = new CompoundStatement(loc, s);
- }
-
- if (fensures)
- {
- /* out(id1) { statements1... }
- * out(id2) { statements2... }
- * ...
- * becomes:
- * out(__result) { { ref id1 = __result; { statements1... } }
- * { ref id2 = __result; { statements2... } } ... }
- */
- assert(fensures.length);
- auto loc = (*fensures)[0].ensure.loc;
- auto s = new Statements;
- foreach (r; *fensures)
- {
- if (r.id && canBuildResultVar())
- {
- auto rloc = r.ensure.loc;
- auto resultId = new IdentifierExp(rloc, Id.result);
- auto init = new ExpInitializer(rloc, resultId);
- auto stc = STC.ref_ | STC.temp | STC.result;
- auto decl = new VarDeclaration(rloc, null, r.id, init, stc);
- auto sdecl = new ExpStatement(rloc, decl);
- s.push(new ScopeStatement(rloc, new CompoundStatement(rloc, sdecl, r.ensure), rloc));
- }
- else
- {
- s.push(r.ensure);
- }
- }
- fensure = new CompoundStatement(loc, s);
- }
-
- if (!isVirtual())
- return;
-
- /* Rewrite contracts as nested functions, then call them. Doing it as nested
- * functions means that overriding functions can call them.
- */
- TypeFunction f = cast(TypeFunction) type;
-
- /* Make a copy of the parameters and make them all ref */
- static Parameters* toRefCopy(ParameterList parameterList)
- {
- auto result = new Parameters();
-
- foreach (n, p; parameterList)
- {
- p = p.syntaxCopy();
- if (!p.isLazy())
- p.storageClass = (p.storageClass | STC.ref_) & ~STC.out_;
- p.defaultArg = null; // won't be the same with ref
- result.push(p);
- }
-
- return result;
- }
-
- if (frequire)
- {
- /* in { ... }
- * becomes:
- * void __require(ref params) { ... }
- * __require(params);
- */
- Loc loc = frequire.loc;
- fdrequireParams = new Expressions();
- if (parameters)
- {
- foreach (vd; *parameters)
- fdrequireParams.push(new VarExp(loc, vd));
- }
- auto fo = cast(TypeFunction)(originalType ? originalType : f);
- auto fparams = toRefCopy(fo.parameterList);
- auto tf = new TypeFunction(ParameterList(fparams), Type.tvoid, LINK.d);
- tf.isnothrow = f.isnothrow;
- tf.isnogc = f.isnogc;
- tf.purity = f.purity;
- tf.trust = f.trust;
- auto fd = new FuncDeclaration(loc, loc, Id.require, STC.undefined_, tf);
- fd.fbody = frequire;
- Statement s1 = new ExpStatement(loc, fd);
- Expression e = new CallExp(loc, new VarExp(loc, fd, false), fdrequireParams);
- Statement s2 = new ExpStatement(loc, e);
- frequire = new CompoundStatement(loc, s1, s2);
- fdrequire = fd;
- }
-
- /* We need to set fdensureParams here and not in the block below to
- * have the parameters available when calling a base class ensure(),
- * even if this function doesn't have an out contract.
- */
- fdensureParams = new Expressions();
- if (canBuildResultVar())
- fdensureParams.push(new IdentifierExp(loc, Id.result));
- if (parameters)
- {
- foreach (vd; *parameters)
- fdensureParams.push(new VarExp(loc, vd));
- }
-
- if (fensure)
- {
- /* out (result) { ... }
- * becomes:
- * void __ensure(ref tret result, ref params) { ... }
- * __ensure(result, params);
- */
- Loc loc = fensure.loc;
- auto fparams = new Parameters();
- if (canBuildResultVar())
- {
- Parameter p = new Parameter(loc, STC.ref_ | STC.const_, f.nextOf(), Id.result, null, null);
- fparams.push(p);
- }
- auto fo = cast(TypeFunction)(originalType ? originalType : f);
- fparams.pushSlice((*toRefCopy(fo.parameterList))[]);
- auto tf = new TypeFunction(ParameterList(fparams), Type.tvoid, LINK.d);
- tf.isnothrow = f.isnothrow;
- tf.isnogc = f.isnogc;
- tf.purity = f.purity;
- tf.trust = f.trust;
- auto fd = new FuncDeclaration(loc, loc, Id.ensure, STC.undefined_, tf);
- fd.fbody = fensure;
- Statement s1 = new ExpStatement(loc, fd);
- Expression e = new CallExp(loc, new VarExp(loc, fd, false), fdensureParams);
- Statement s2 = new ExpStatement(loc, e);
- fensure = new CompoundStatement(loc, s1, s2);
- fdensure = fd;
- }
- }
-
- /****************************************************
- * Merge into this function the 'out' contracts of all it overrides.
- * 'out's are AND'd together, i.e. all of them need to pass.
- */
- extern (D) final Statement mergeFensure(Statement sf, Identifier oid, Expressions* params)
- {
- /* Same comments as for mergeFrequire(), except that we take care
- * of generating a consistent reference to the 'result' local by
- * explicitly passing 'result' to the nested function as a reference
- * argument.
- * This won't work for the 'this' parameter as it would require changing
- * the semantic code for the nested function so that it looks on the parameter
- * list for the 'this' pointer, something that would need an unknown amount
- * of tweaking of various parts of the compiler that I'd rather leave alone.
- */
- foreach (fdv; foverrides)
- {
- /* The semantic pass on the contracts of the overridden functions must
- * be completed before code generation occurs.
- * https://issues.dlang.org/show_bug.cgi?id=3602 and
- * https://issues.dlang.org/show_bug.cgi?id=5230
- */
- if (needsFensure(fdv) && fdv.semanticRun != PASS.semantic3done)
- {
- assert(fdv._scope);
- Scope* sc = fdv._scope.push();
- sc.stc &= ~STC.override_;
- fdv.semantic3(sc);
- sc.pop();
- }
-
- sf = fdv.mergeFensure(sf, oid, params);
- if (fdv.fdensure)
- {
- //printf("fdv.fensure: %s\n", fdv.fensure.toChars());
- // Make the call: __ensure(result, params)
- params = Expression.arraySyntaxCopy(params);
- if (canBuildResultVar())
- {
- Type t1 = fdv.type.nextOf().toBasetype();
- Type t2 = this.type.nextOf().toBasetype();
- if (t1.isBaseOf(t2, null))
- {
- /* Making temporary reference variable is necessary
- * in covariant return.
- * https://issues.dlang.org/show_bug.cgi?id=5204
- * https://issues.dlang.org/show_bug.cgi?id=10479
- */
- Expression* eresult = &(*params)[0];
- auto ei = new ExpInitializer(Loc.initial, *eresult);
- auto v = new VarDeclaration(Loc.initial, t1, Identifier.generateId("__covres"), ei);
- v.storage_class |= STC.temp;
- auto de = new DeclarationExp(Loc.initial, v);
- auto ve = new VarExp(Loc.initial, v);
- *eresult = new CommaExp(Loc.initial, de, ve);
- }
- }
- Expression e = new CallExp(loc, new VarExp(loc, fdv.fdensure, false), params);
- Statement s2 = new ExpStatement(loc, e);
-
- if (sf)
- {
- sf = new CompoundStatement(sf.loc, s2, sf);
- }
- else
- sf = s2;
- }
- }
- return sf;
- }
-
/*********************************************
* Returns: the function's parameter list, and whether
* it is variadic or not.
@@ -2544,7 +1862,7 @@ extern (C++) class FuncDeclaration : Declaration
return this;
}
- inout(FuncDeclaration) toAliasFunc() inout
+ inout(FuncDeclaration) toAliasFunc() inout @safe
{
return this;
}
@@ -3073,56 +2391,6 @@ extern (C++) final class FuncLiteralDeclaration : FuncDeclaration
return false;
}
- /*******************************
- * Modify all expression type of return statements to tret.
- *
- * On function literals, return type may be modified based on the context type
- * after its semantic3 is done, in FuncExp::implicitCastTo.
- *
- * A function() dg = (){ return new B(); } // OK if is(B : A) == true
- *
- * If B to A conversion is convariant that requires offseet adjusting,
- * all return statements should be adjusted to return expressions typed A.
- */
- extern (D) void modifyReturns(Scope* sc, Type tret)
- {
- import dmd.statement_rewrite_walker;
-
- extern (C++) final class RetWalker : StatementRewriteWalker
- {
- alias visit = typeof(super).visit;
- public:
- Scope* sc;
- Type tret;
- FuncLiteralDeclaration fld;
-
- override void visit(ReturnStatement s)
- {
- Expression exp = s.exp;
- if (exp && !exp.type.equals(tret))
- s.exp = exp.implicitCastTo(sc, tret);
- }
- }
-
- if (semanticRun < PASS.semantic3done)
- return;
-
- if (fes)
- return;
-
- scope RetWalker w = new RetWalker();
- w.sc = sc;
- w.tret = tret;
- w.fld = this;
- fbody.accept(w);
-
- // Also update the inferred function type to match the new return type.
- // This is required so the code generator does not try to cast the
- // modified returns back to the original type.
- if (inferRetType && type.nextOf() != tret)
- type.toTypeFunction().next = tret;
- }
-
override inout(FuncLiteralDeclaration) isFuncLiteralDeclaration() inout
{
return this;
@@ -3654,136 +2922,6 @@ extern (C++) final class NewDeclaration : FuncDeclaration
}
}
-/**************************************
- * When a traits(compiles) is used on a function literal call
- * we need to take into account if the body of the function
- * violates any attributes, however, we must not affect the
- * attribute inference on the outer function. The attributes
- * of the function literal still need to be inferred, therefore
- * we need a way to check for the scope that the traits compiles
- * introduces.
- *
- * Params:
- * sc = scope to be checked for
- *
- * Returns: `true` if the provided scope is the root
- * of the traits compiles list of scopes.
- */
-bool isRootTraitsCompilesScope(Scope* sc)
-{
- return (sc.flags & SCOPE.compile) && !(sc.func.flags & SCOPE.compile);
-}
-
-/**************************************
- * A statement / expression in this scope is not `@safe`,
- * so mark the enclosing function as `@system`
- *
- * Params:
- * sc = scope that the unsafe statement / expression is in
- * gag = surpress error message (used in escape.d)
- * loc = location of error
- * fmt = printf-style format string
- * arg0 = (optional) argument for first %s format specifier
- * arg1 = (optional) argument for second %s format specifier
- * arg2 = (optional) argument for third %s format specifier
- * Returns: whether there's a safe error
- */
-bool setUnsafe(Scope* sc,
- bool gag = false, Loc loc = Loc.init, const(char)* fmt = null,
- RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
-{
- if (sc.intypeof)
- return false; // typeof(cast(int*)0) is safe
-
- if (sc.flags & SCOPE.debug_) // debug {} scopes are permissive
- return false;
-
- if (!sc.func)
- {
- if (sc.varDecl)
- {
- if (sc.varDecl.storage_class & STC.safe)
- {
- .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "");
- return true;
- }
- else if (!(sc.varDecl.storage_class & STC.trusted))
- {
- sc.varDecl.storage_class |= STC.system;
- sc.varDecl.systemInferred = true;
- }
- }
- return false;
- }
-
-
- if (isRootTraitsCompilesScope(sc)) // __traits(compiles, x)
- {
- if (sc.func.isSafeBypassingInference())
- {
- // Message wil be gagged, but still call error() to update global.errors and for
- // -verrors=spec
- .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "");
- return true;
- }
- return false;
- }
-
- return sc.func.setUnsafe(gag, loc, fmt, arg0, arg1, arg2);
-}
-
-/***************************************
- * Like `setUnsafe`, but for safety errors still behind preview switches
- *
- * Given a `FeatureState fs`, for example dip1000 / dip25 / systemVariables,
- * the behavior changes based on the setting:
- *
- * - In case of `-revert=fs`, it does nothing.
- * - In case of `-preview=fs`, it's the same as `setUnsafe`
- * - By default, print a deprecation in `@safe` functions, or store an attribute violation in inferred functions.
- *
- * Params:
- * sc = used to find affected function/variable, and for checking whether we are in a deprecated / speculative scope
- * fs = feature state from the preview flag
- * gag = surpress error message
- * loc = location of error
- * msg = printf-style format string
- * arg0 = (optional) argument for first %s format specifier
- * arg1 = (optional) argument for second %s format specifier
- * arg2 = (optional) argument for third %s format specifier
- * Returns: whether an actual safe error (not deprecation) occured
- */
-bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)* msg,
- RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
-{
- //printf("setUnsafePreview() fs:%d %s\n", fs, msg);
- with (FeatureState) final switch (fs)
- {
- case disabled:
- return false;
-
- case enabled:
- return sc.setUnsafe(gag, loc, msg, arg0, arg1, arg2);
-
- case default_:
- if (!sc.func)
- return false;
- if (sc.func.isSafeBypassingInference())
- {
- if (!gag && !sc.isDeprecated())
- {
- deprecation(loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "");
- }
- }
- else if (!sc.func.safetyViolation)
- {
- import dmd.func : AttributeViolation;
- sc.func.safetyViolation = new AttributeViolation(loc, msg, arg0, arg1, arg2);
- }
- return false;
- }
-}
-
/// Stores a reason why a function failed to infer a function attribute like `@safe` or `pure`
///
/// Has two modes:
diff --git a/gcc/d/dmd/funcsem.d b/gcc/d/dmd/funcsem.d
index 2cadc40..e058deb 100644
--- a/gcc/d/dmd/funcsem.d
+++ b/gcc/d/dmd/funcsem.d
@@ -1891,6 +1891,309 @@ Expression addInvariant(AggregateDeclaration ad, VarDeclaration vthis)
return e;
}
+/********************************************
+ * Find function in overload list that exactly matches t.
+ */
+FuncDeclaration overloadExactMatch(FuncDeclaration thisfd, Type t)
+{
+ FuncDeclaration fd;
+ overloadApply(thisfd, (Dsymbol s)
+ {
+ auto f = s.isFuncDeclaration();
+ if (!f)
+ return 0;
+ if (f.storage_class & STC.disable)
+ return 0;
+ if (t.equals(f.type))
+ {
+ fd = f;
+ return 1;
+ }
+ /* Allow covariant matches, as long as the return type
+ * is just a const conversion.
+ * This allows things like pure functions to match with an impure function type.
+ */
+ if (t.ty == Tfunction)
+ {
+ auto tf = cast(TypeFunction)f.type;
+ if (tf.covariant(t) == Covariant.yes &&
+ tf.nextOf().implicitConvTo(t.nextOf()) >= MATCH.constant)
+ {
+ fd = f;
+ return 1;
+ }
+ }
+ return 0;
+ });
+ return fd;
+}
+
+/********************************************
+ * Find function in overload list that matches to the 'this' modifier.
+ * There's four result types.
+ *
+ * 1. If the 'tthis' matches only one candidate, it's an "exact match".
+ * Returns the function and 'hasOverloads' is set to false.
+ * eg. If 'tthis" is mutable and there's only one mutable method.
+ * 2. If there's two or more match candidates, but a candidate function will be
+ * a "better match".
+ * Returns the better match function but 'hasOverloads' is set to true.
+ * eg. If 'tthis' is mutable, and there's both mutable and const methods,
+ * the mutable method will be a better match.
+ * 3. If there's two or more match candidates, but there's no better match,
+ * Returns null and 'hasOverloads' is set to true to represent "ambiguous match".
+ * eg. If 'tthis' is mutable, and there's two or more mutable methods.
+ * 4. If there's no candidates, it's "no match" and returns null with error report.
+ * e.g. If 'tthis' is const but there's no const methods.
+ */
+FuncDeclaration overloadModMatch(FuncDeclaration thisfd, const ref Loc loc, Type tthis, ref bool hasOverloads)
+{
+ //printf("FuncDeclaration::overloadModMatch('%s')\n", toChars());
+ MatchAccumulator m;
+ overloadApply(thisfd, (Dsymbol s)
+ {
+ auto f = s.isFuncDeclaration();
+ if (!f || f == m.lastf) // skip duplicates
+ return 0;
+ auto tf = f.type.toTypeFunction();
+ //printf("tf = %s\n", tf.toChars());
+ MATCH match;
+ if (tthis) // non-static functions are preferred than static ones
+ {
+ if (f.needThis())
+ match = f.isCtorDeclaration() ? MATCH.exact : MODmethodConv(tthis.mod, tf.mod);
+ else
+ match = MATCH.constant; // keep static function in overload candidates
+ }
+ else // static functions are preferred than non-static ones
+ {
+ if (f.needThis())
+ match = MATCH.convert;
+ else
+ match = MATCH.exact;
+ }
+ if (match == MATCH.nomatch)
+ return 0;
+ if (match > m.last) goto LcurrIsBetter;
+ if (match < m.last) goto LlastIsBetter;
+ // See if one of the matches overrides the other.
+ if (m.lastf.overrides(f)) goto LlastIsBetter;
+ if (f.overrides(m.lastf)) goto LcurrIsBetter;
+ //printf("\tambiguous\n");
+ m.nextf = f;
+ m.count++;
+ return 0;
+ LlastIsBetter:
+ //printf("\tlastbetter\n");
+ m.count++; // count up
+ return 0;
+ LcurrIsBetter:
+ //printf("\tisbetter\n");
+ if (m.last <= MATCH.convert)
+ {
+ // clear last secondary matching
+ m.nextf = null;
+ m.count = 0;
+ }
+ m.last = match;
+ m.lastf = f;
+ m.count++; // count up
+ return 0;
+ });
+ if (m.count == 1) // exact match
+ {
+ hasOverloads = false;
+ }
+ else if (m.count > 1) // better or ambiguous match
+ {
+ hasOverloads = true;
+ }
+ else // no match
+ {
+ hasOverloads = true;
+ auto tf = thisfd.type.toTypeFunction();
+ assert(tthis);
+ assert(!MODimplicitConv(tthis.mod, tf.mod)); // modifier mismatch
+ {
+ OutBuffer thisBuf, funcBuf;
+ MODMatchToBuffer(&thisBuf, tthis.mod, tf.mod);
+ MODMatchToBuffer(&funcBuf, tf.mod, tthis.mod);
+ .error(loc, "%smethod %s is not callable using a %sobject", thisfd.kind, thisfd.toPrettyChars,
+ funcBuf.peekChars(), thisfd.toPrettyChars(), thisBuf.peekChars());
+ }
+ }
+ return m.lastf;
+}
+
+/***********************************
+ * Determine lexical level difference from `fd` to nested function `target`.
+ * Issue error if `fd` cannot call `target`.
+ *
+ * Params:
+ * fd = function
+ * loc = location for error messages
+ * sc = context
+ * target = target of call
+ * decl = The `Declaration` that triggered this check.
+ * Used to provide a better error message only.
+ * Returns:
+ * 0 same level
+ * >0 decrease nesting by number
+ * -1 increase nesting by 1 (`target` is nested within 'fd')
+ * LevelError error
+ */
+int getLevelAndCheck(FuncDeclaration fd, const ref Loc loc, Scope* sc, FuncDeclaration target,
+ Declaration decl)
+{
+ int level = fd.getLevel(target, sc.intypeof);
+ if (level != fd.LevelError)
+ return level;
+ // Don't give error if in template constraint
+ if (!(sc.flags & SCOPE.constraint))
+ {
+ const(char)* xstatic = fd.isStatic() ? "`static` " : "";
+ // better diagnostics for static functions
+ .error(loc, "%s%s `%s` cannot access %s `%s` in frame of function `%s`",
+ xstatic, fd.kind(), fd.toPrettyChars(), decl.kind(), decl.toChars(),
+ target.toPrettyChars());
+ .errorSupplemental(decl.loc, "`%s` declared here", decl.toChars());
+ return fd.LevelError;
+ }
+ return 1;
+}
+
+/**********************************
+ * Decide if attributes for this function can be inferred from examining
+ * the function body.
+ * Returns:
+ * true if can
+ */
+bool canInferAttributes(FuncDeclaration fd, Scope* sc)
+{
+ if (!fd.fbody)
+ return false;
+ if (fd.isVirtualMethod() &&
+ /*
+ * https://issues.dlang.org/show_bug.cgi?id=21719
+ *
+ * If we have an auto virtual function we can infer
+ * the attributes.
+ */
+ !(fd.inferRetType && !fd.isCtorDeclaration()))
+ return false; // since they may be overridden
+ if (sc.func &&
+ /********** this is for backwards compatibility for the moment ********/
+ (!fd.isMember() || sc.func.isSafeBypassingInference() && !fd.isInstantiated()))
+ return true;
+ if (fd.isFuncLiteralDeclaration() || // externs are not possible with literals
+ (fd.storage_class & STC.inference) || // do attribute inference
+ (fd.inferRetType && !fd.isCtorDeclaration()))
+ return true;
+ if (fd.isInstantiated())
+ {
+ auto ti = fd.parent.isTemplateInstance();
+ if (ti is null || ti.isTemplateMixin() || ti.tempdecl.ident == fd.ident)
+ return true;
+ }
+ return false;
+}
+
+/*********************************************
+ * In the current function, we are calling 'this' function.
+ * 1. Check to see if the current function can call 'this' function, issue error if not.
+ * 2. If the current function is not the parent of 'this' function, then add
+ * the current function to the list of siblings of 'this' function.
+ * 3. If the current function is a literal, and it's accessing an uplevel scope,
+ * then mark it as a delegate.
+ * Returns true if error occurs.
+ */
+bool checkNestedReference(FuncDeclaration fd, Scope* sc, const ref Loc loc)
+{
+ //printf("FuncDeclaration::checkNestedReference() %s\n", toPrettyChars());
+ if (auto fld = fd.isFuncLiteralDeclaration())
+ {
+ if (fld.tok == TOK.reserved)
+ {
+ fld.tok = TOK.function_;
+ fld.vthis = null;
+ }
+ }
+ if (!fd.parent || fd.parent == sc.parent)
+ return false;
+ if (fd.ident == Id.require || fd.ident == Id.ensure)
+ return false;
+ if (!fd.isThis() && !fd.isNested())
+ return false;
+ // The current function
+ FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
+ if (!fdthis)
+ return false; // out of function scope
+ Dsymbol p = fd.toParentLocal();
+ Dsymbol p2 = fd.toParent2();
+ // Function literals from fdthis to p must be delegates
+ ensureStaticLinkTo(fdthis, p);
+ if (p != p2)
+ ensureStaticLinkTo(fdthis, p2);
+ if (fd.isNested())
+ {
+ // The function that this function is in
+ bool checkEnclosing(FuncDeclaration fdv)
+ {
+ if (!fdv)
+ return false;
+ if (fdv == fdthis)
+ return false;
+ //printf("this = %s in [%s]\n", this.toChars(), this.loc.toChars());
+ //printf("fdv = %s in [%s]\n", fdv .toChars(), fdv .loc.toChars());
+ //printf("fdthis = %s in [%s]\n", fdthis.toChars(), fdthis.loc.toChars());
+ // Add this function to the list of those which called us
+ if (fdthis != fd)
+ {
+ bool found = false;
+ for (size_t i = 0; i < fd.siblingCallers.length; ++i)
+ {
+ if (fd.siblingCallers[i] == fdthis)
+ found = true;
+ }
+ if (!found)
+ {
+ //printf("\tadding sibling %s to %s\n", fdthis.toPrettyChars(), toPrettyChars());
+ if (!sc.intypeof && !(sc.flags & SCOPE.compile))
+ {
+ fd.siblingCallers.push(fdthis);
+ fd.computedEscapingSiblings = false;
+ }
+ }
+ }
+ const lv = fdthis.getLevelAndCheck(loc, sc, fdv, fd);
+ if (lv == fd.LevelError)
+ return true; // error
+ if (lv == -1)
+ return false; // downlevel call
+ if (lv == 0)
+ return false; // same level call
+ return false; // Uplevel call
+ }
+ if (checkEnclosing(p.isFuncDeclaration()))
+ return true;
+ if (checkEnclosing(p == p2 ? null : p2.isFuncDeclaration()))
+ return true;
+ }
+ return false;
+}
+
+/****************************************************
+ * Check whether result variable can be built.
+ * Returns:
+ * `true` if the function has a return type that
+ * is different from `void`.
+ */
+private bool canBuildResultVar(FuncDeclaration fd)
+{
+ auto f = cast(TypeFunction)fd.type;
+ return f && f.nextOf() && f.nextOf().toBasetype().ty != Tvoid;
+}
+
/****************************************************
* Declare result variable lazily.
*/
@@ -1923,3 +2226,512 @@ void buildResultVar(FuncDeclaration fd, Scope* sc, Type tret)
assert(fd.vresult.parent == fd);
}
}
+
+/****************************************************
+ * Merge into this function the 'in' contracts of all it overrides.
+ * 'in's are OR'd together, i.e. only one of them needs to pass.
+ */
+Statement mergeFrequire(FuncDeclaration fd, Statement sf, Expressions* params)
+{
+ /* If a base function and its override both have an IN contract, then
+ * only one of them needs to succeed. This is done by generating:
+ *
+ * void derived.in() {
+ * try {
+ * base.in();
+ * }
+ * catch () {
+ * ... body of derived.in() ...
+ * }
+ * }
+ *
+ * So if base.in() doesn't throw, derived.in() need not be executed, and the contract is valid.
+ * If base.in() throws, then derived.in()'s body is executed.
+ */
+ foreach (fdv; fd.foverrides)
+ {
+ /* The semantic pass on the contracts of the overridden functions must
+ * be completed before code generation occurs.
+ * https://issues.dlang.org/show_bug.cgi?id=3602
+ */
+ if (fdv.frequires && fdv.semanticRun != PASS.semantic3done)
+ {
+ assert(fdv._scope);
+ Scope* sc = fdv._scope.push();
+ sc.stc &= ~STC.override_;
+ fdv.semantic3(sc);
+ sc.pop();
+ }
+ sf = fdv.mergeFrequire(sf, params);
+ if (!sf || !fdv.fdrequire)
+ return null;
+ //printf("fdv.frequire: %s\n", fdv.frequire.toChars());
+ /* Make the call:
+ * try { __require(params); }
+ * catch (Throwable) { frequire; }
+ */
+ params = Expression.arraySyntaxCopy(params);
+ Expression e = new CallExp(fd.loc, new VarExp(fd.loc, fdv.fdrequire, false), params);
+ Statement s2 = new ExpStatement(fd.loc, e);
+ auto c = new Catch(fd.loc, getThrowable(), null, sf);
+ c.internalCatch = true;
+ auto catches = new Catches();
+ catches.push(c);
+ sf = new TryCatchStatement(fd.loc, s2, catches);
+ }
+ return sf;
+}
+
+/****************************************************
+ * Merge into this function the 'in' contracts of all it overrides.
+ */
+Statement mergeFrequireInclusivePreview(FuncDeclaration fd, Statement sf, Expressions* params)
+{
+ /* If a base function and its override both have an IN contract, then
+ * the override in contract must widen the guarantee of the base contract.
+ * This is checked by generating:
+ *
+ * void derived.in() {
+ * try {
+ * ... body of derived.in() ...
+ * }
+ * catch () {
+ * // derived in rejected this argument. so parent must also reject it, or we've tightened the contract.
+ * base.in();
+ * assert(false, "Logic error: " ~ thr.msg);
+ * }
+ * }
+ */
+ foreach (fdv; fd.foverrides)
+ {
+ /* The semantic pass on the contracts of the overridden functions must
+ * be completed before code generation occurs.
+ * https://issues.dlang.org/show_bug.cgi?id=3602
+ */
+ if (fdv.frequires && fdv.semanticRun != PASS.semantic3done)
+ {
+ assert(fdv._scope);
+ Scope* sc = fdv._scope.push();
+ sc.stc &= ~STC.override_;
+ fdv.semantic3(sc);
+ sc.pop();
+ }
+ sf = fdv.mergeFrequireInclusivePreview(sf, params);
+ if (sf && fdv.fdrequire)
+ {
+ const loc = fd.fdrequire.loc;
+ //printf("fdv.frequire: %s\n", fdv.frequire.toChars());
+ /* Make the call:
+ * try { frequire; }
+ * catch (Throwable thr) { __require(params); assert(false, "Logic error: " ~ thr.msg); }
+ */
+ Identifier id = Identifier.generateId("thr");
+ params = Expression.arraySyntaxCopy(params);
+ Expression e = new CallExp(loc, new VarExp(loc, fdv.fdrequire, false), params);
+ Statement s2 = new ExpStatement(loc, e);
+ // assert(false, ...)
+ // TODO make this a runtime helper to allow:
+ // - chaining the original expression
+ // - nogc concatenation
+ Expression msg = new StringExp(loc, "Logic error: in-contract was tighter than parent in-contract");
+ Statement fail = new ExpStatement(loc, new AssertExp(loc, IntegerExp.literal!0, msg));
+ Statement s3 = new CompoundStatement(loc, s2, fail);
+ auto c = new Catch(loc, getThrowable(), id, s3);
+ c.internalCatch = true;
+ auto catches = new Catches();
+ catches.push(c);
+ sf = new TryCatchStatement(loc, sf, catches);
+ }
+ else
+ return null;
+ }
+ return sf;
+}
+
+/****************************************************
+ * Rewrite contracts as statements.
+ */
+void buildEnsureRequire(FuncDeclaration thisfd)
+{
+ if (thisfd.frequires)
+ {
+ /* in { statements1... }
+ * in { statements2... }
+ * ...
+ * becomes:
+ * in { { statements1... } { statements2... } ... }
+ */
+ assert(thisfd.frequires.length);
+ auto loc = (*thisfd.frequires)[0].loc;
+ auto s = new Statements;
+ foreach (r; *thisfd.frequires)
+ {
+ s.push(new ScopeStatement(r.loc, r, r.loc));
+ }
+ thisfd.frequire = new CompoundStatement(loc, s);
+ }
+ if (thisfd.fensures)
+ {
+ /* out(id1) { statements1... }
+ * out(id2) { statements2... }
+ * ...
+ * becomes:
+ * out(__result) { { ref id1 = __result; { statements1... } }
+ * { ref id2 = __result; { statements2... } } ... }
+ */
+ assert(thisfd.fensures.length);
+ auto loc = (*thisfd.fensures)[0].ensure.loc;
+ auto s = new Statements;
+ foreach (r; *thisfd.fensures)
+ {
+ if (r.id && thisfd.canBuildResultVar())
+ {
+ auto rloc = r.ensure.loc;
+ auto resultId = new IdentifierExp(rloc, Id.result);
+ auto init = new ExpInitializer(rloc, resultId);
+ auto stc = STC.ref_ | STC.temp | STC.result;
+ auto decl = new VarDeclaration(rloc, null, r.id, init, stc);
+ auto sdecl = new ExpStatement(rloc, decl);
+ s.push(new ScopeStatement(rloc, new CompoundStatement(rloc, sdecl, r.ensure), rloc));
+ }
+ else
+ {
+ s.push(r.ensure);
+ }
+ }
+ thisfd.fensure = new CompoundStatement(loc, s);
+ }
+ if (!thisfd.isVirtual())
+ return;
+ /* Rewrite contracts as nested functions, then call them. Doing it as nested
+ * functions means that overriding functions can call them.
+ */
+ TypeFunction f = cast(TypeFunction) thisfd.type;
+ /* Make a copy of the parameters and make them all ref */
+ static Parameters* toRefCopy(ParameterList parameterList)
+ {
+ auto result = new Parameters();
+ foreach (n, p; parameterList)
+ {
+ p = p.syntaxCopy();
+ if (!p.isLazy())
+ p.storageClass = (p.storageClass | STC.ref_) & ~STC.out_;
+ p.defaultArg = null; // won't be the same with ref
+ result.push(p);
+ }
+ return result;
+ }
+ if (thisfd.frequire)
+ {
+ /* in { ... }
+ * becomes:
+ * void __require(ref params) { ... }
+ * __require(params);
+ */
+ Loc loc = thisfd.frequire.loc;
+ thisfd.fdrequireParams = new Expressions();
+ if (thisfd.parameters)
+ {
+ foreach (vd; *thisfd.parameters)
+ thisfd.fdrequireParams.push(new VarExp(loc, vd));
+ }
+ auto fo = cast(TypeFunction)(thisfd.originalType ? thisfd.originalType : f);
+ auto fparams = toRefCopy(fo.parameterList);
+ auto tf = new TypeFunction(ParameterList(fparams), Type.tvoid, LINK.d);
+ tf.isnothrow = f.isnothrow;
+ tf.isnogc = f.isnogc;
+ tf.purity = f.purity;
+ tf.trust = f.trust;
+ auto fd = new FuncDeclaration(loc, loc, Id.require, STC.undefined_, tf);
+ fd.fbody = thisfd.frequire;
+ Statement s1 = new ExpStatement(loc, fd);
+ Expression e = new CallExp(loc, new VarExp(loc, fd, false), thisfd.fdrequireParams);
+ Statement s2 = new ExpStatement(loc, e);
+ thisfd.frequire = new CompoundStatement(loc, s1, s2);
+ thisfd.fdrequire = fd;
+ }
+ /* We need to set fdensureParams here and not in the block below to
+ * have the parameters available when calling a base class ensure(),
+ * even if this function doesn't have an out contract.
+ */
+ thisfd.fdensureParams = new Expressions();
+ if (thisfd.canBuildResultVar())
+ thisfd.fdensureParams.push(new IdentifierExp(thisfd.loc, Id.result));
+ if (thisfd.parameters)
+ {
+ foreach (vd; *thisfd.parameters)
+ thisfd.fdensureParams.push(new VarExp(thisfd.loc, vd));
+ }
+ if (thisfd.fensure)
+ {
+ /* out (result) { ... }
+ * becomes:
+ * void __ensure(ref tret result, ref params) { ... }
+ * __ensure(result, params);
+ */
+ Loc loc = thisfd.fensure.loc;
+ auto fparams = new Parameters();
+ if (thisfd.canBuildResultVar())
+ {
+ Parameter p = new Parameter(loc, STC.ref_ | STC.const_, f.nextOf(), Id.result, null, null);
+ fparams.push(p);
+ }
+ auto fo = cast(TypeFunction)(thisfd.originalType ? thisfd.originalType : f);
+ fparams.pushSlice((*toRefCopy(fo.parameterList))[]);
+ auto tf = new TypeFunction(ParameterList(fparams), Type.tvoid, LINK.d);
+ tf.isnothrow = f.isnothrow;
+ tf.isnogc = f.isnogc;
+ tf.purity = f.purity;
+ tf.trust = f.trust;
+ auto fd = new FuncDeclaration(loc, loc, Id.ensure, STC.undefined_, tf);
+ fd.fbody = thisfd.fensure;
+ Statement s1 = new ExpStatement(loc, fd);
+ Expression e = new CallExp(loc, new VarExp(loc, fd, false), thisfd.fdensureParams);
+ Statement s2 = new ExpStatement(loc, e);
+ thisfd.fensure = new CompoundStatement(loc, s1, s2);
+ thisfd.fdensure = fd;
+ }
+}
+
+/****************************************************
+ * Merge into this function the 'out' contracts of all it overrides.
+ * 'out's are AND'd together, i.e. all of them need to pass.
+ */
+Statement mergeFensure(FuncDeclaration fd, Statement sf, Identifier oid, Expressions* params)
+{
+ /* Same comments as for mergeFrequire(), except that we take care
+ * of generating a consistent reference to the 'result' local by
+ * explicitly passing 'result' to the nested function as a reference
+ * argument.
+ * This won't work for the 'this' parameter as it would require changing
+ * the semantic code for the nested function so that it looks on the parameter
+ * list for the 'this' pointer, something that would need an unknown amount
+ * of tweaking of various parts of the compiler that I'd rather leave alone.
+ */
+ foreach (fdv; fd.foverrides)
+ {
+ /* The semantic pass on the contracts of the overridden functions must
+ * be completed before code generation occurs.
+ * https://issues.dlang.org/show_bug.cgi?id=3602 and
+ * https://issues.dlang.org/show_bug.cgi?id=5230
+ */
+ if (fd.needsFensure(fdv) && fdv.semanticRun != PASS.semantic3done)
+ {
+ assert(fdv._scope);
+ Scope* sc = fdv._scope.push();
+ sc.stc &= ~STC.override_;
+ fdv.semantic3(sc);
+ sc.pop();
+ }
+ sf = fdv.mergeFensure(sf, oid, params);
+ if (fdv.fdensure)
+ {
+ //printf("fdv.fensure: %s\n", fdv.fensure.toChars());
+ // Make the call: __ensure(result, params)
+ params = Expression.arraySyntaxCopy(params);
+ if (fd.canBuildResultVar())
+ {
+ Type t1 = fdv.type.nextOf().toBasetype();
+ Type t2 = fd.type.nextOf().toBasetype();
+ if (t1.isBaseOf(t2, null))
+ {
+ /* Making temporary reference variable is necessary
+ * in covariant return.
+ * https://issues.dlang.org/show_bug.cgi?id=5204
+ * https://issues.dlang.org/show_bug.cgi?id=10479
+ */
+ Expression* eresult = &(*params)[0];
+ auto ei = new ExpInitializer(Loc.initial, *eresult);
+ auto v = new VarDeclaration(Loc.initial, t1, Identifier.generateId("__covres"), ei);
+ v.storage_class |= STC.temp;
+ auto de = new DeclarationExp(Loc.initial, v);
+ auto ve = new VarExp(Loc.initial, v);
+ *eresult = new CommaExp(Loc.initial, de, ve);
+ }
+ }
+ Expression e = new CallExp(fd.loc, new VarExp(fd.loc, fdv.fdensure, false), params);
+ Statement s2 = new ExpStatement(fd.loc, e);
+ if (sf)
+ {
+ sf = new CompoundStatement(sf.loc, s2, sf);
+ }
+ else
+ sf = s2;
+ }
+ }
+ return sf;
+}
+
+/*******************************
+ * Modify all expression type of return statements to tret.
+ *
+ * On function literals, return type may be modified based on the context type
+ * after its semantic3 is done, in FuncExp::implicitCastTo.
+ *
+ * A function() dg = (){ return new B(); } // OK if is(B : A) == true
+ *
+ * If B to A conversion is convariant that requires offseet adjusting,
+ * all return statements should be adjusted to return expressions typed A.
+ */
+void modifyReturns(FuncLiteralDeclaration fld, Scope* sc, Type tret)
+{
+ import dmd.statement_rewrite_walker;
+ extern (C++) final class RetWalker : StatementRewriteWalker
+ {
+ alias visit = typeof(super).visit;
+ public:
+ Scope* sc;
+ Type tret;
+ FuncLiteralDeclaration fld;
+ override void visit(ReturnStatement s)
+ {
+ Expression exp = s.exp;
+ if (exp && !exp.type.equals(tret))
+ s.exp = exp.implicitCastTo(sc, tret);
+ }
+ }
+ if (fld.semanticRun < PASS.semantic3done)
+ return;
+ if (fld.fes)
+ return;
+ scope RetWalker w = new RetWalker();
+ w.sc = sc;
+ w.tret = tret;
+ w.fld = fld;
+ fld.fbody.accept(w);
+ // Also update the inferred function type to match the new return type.
+ // This is required so the code generator does not try to cast the
+ // modified returns back to the original type.
+ if (fld.inferRetType && fld.type.nextOf() != tret)
+ fld.type.toTypeFunction().next = tret;
+}
+
+/**************************************
+ * When a traits(compiles) is used on a function literal call
+ * we need to take into account if the body of the function
+ * violates any attributes, however, we must not affect the
+ * attribute inference on the outer function. The attributes
+ * of the function literal still need to be inferred, therefore
+ * we need a way to check for the scope that the traits compiles
+ * introduces.
+ *
+ * Params:
+ * sc = scope to be checked for
+ *
+ * Returns: `true` if the provided scope is the root
+ * of the traits compiles list of scopes.
+ */
+bool isRootTraitsCompilesScope(Scope* sc)
+{
+ return (sc.flags & SCOPE.compile) && !(sc.func.flags & SCOPE.compile);
+}
+
+/**************************************
+ * A statement / expression in this scope is not `@safe`,
+ * so mark the enclosing function as `@system`
+ *
+ * Params:
+ * sc = scope that the unsafe statement / expression is in
+ * gag = surpress error message (used in escape.d)
+ * loc = location of error
+ * fmt = printf-style format string
+ * arg0 = (optional) argument for first %s format specifier
+ * arg1 = (optional) argument for second %s format specifier
+ * arg2 = (optional) argument for third %s format specifier
+ * Returns: whether there's a safe error
+ */
+bool setUnsafe(Scope* sc,
+ bool gag = false, Loc loc = Loc.init, const(char)* fmt = null,
+ RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
+{
+ if (sc.intypeof)
+ return false; // typeof(cast(int*)0) is safe
+
+ if (sc.flags & SCOPE.debug_) // debug {} scopes are permissive
+ return false;
+
+ if (!sc.func)
+ {
+ if (sc.varDecl)
+ {
+ if (sc.varDecl.storage_class & STC.safe)
+ {
+ .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "");
+ return true;
+ }
+ else if (!(sc.varDecl.storage_class & STC.trusted))
+ {
+ sc.varDecl.storage_class |= STC.system;
+ sc.varDecl.systemInferred = true;
+ }
+ }
+ return false;
+ }
+
+
+ if (isRootTraitsCompilesScope(sc)) // __traits(compiles, x)
+ {
+ if (sc.func.isSafeBypassingInference())
+ {
+ // Message wil be gagged, but still call error() to update global.errors and for
+ // -verrors=spec
+ .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "");
+ return true;
+ }
+ return false;
+ }
+
+ return sc.func.setUnsafe(gag, loc, fmt, arg0, arg1, arg2);
+}
+
+/***************************************
+ * Like `setUnsafe`, but for safety errors still behind preview switches
+ *
+ * Given a `FeatureState fs`, for example dip1000 / dip25 / systemVariables,
+ * the behavior changes based on the setting:
+ *
+ * - In case of `-revert=fs`, it does nothing.
+ * - In case of `-preview=fs`, it's the same as `setUnsafe`
+ * - By default, print a deprecation in `@safe` functions, or store an attribute violation in inferred functions.
+ *
+ * Params:
+ * sc = used to find affected function/variable, and for checking whether we are in a deprecated / speculative scope
+ * fs = feature state from the preview flag
+ * gag = surpress error message
+ * loc = location of error
+ * msg = printf-style format string
+ * arg0 = (optional) argument for first %s format specifier
+ * arg1 = (optional) argument for second %s format specifier
+ * arg2 = (optional) argument for third %s format specifier
+ * Returns: whether an actual safe error (not deprecation) occured
+ */
+bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)* msg,
+ RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
+{
+ //printf("setUnsafePreview() fs:%d %s\n", fs, msg);
+ with (FeatureState) final switch (fs)
+ {
+ case disabled:
+ return false;
+
+ case enabled:
+ return sc.setUnsafe(gag, loc, msg, arg0, arg1, arg2);
+
+ case default_:
+ if (!sc.func)
+ return false;
+ if (sc.func.isSafeBypassingInference())
+ {
+ if (!gag && !sc.isDeprecated())
+ {
+ deprecation(loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "");
+ }
+ }
+ else if (!sc.func.safetyViolation)
+ {
+ import dmd.func : AttributeViolation;
+ sc.func.safetyViolation = new AttributeViolation(loc, msg, arg0, arg1, arg2);
+ }
+ return false;
+ }
+}
diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d
index af7b1fa..c97aeb6 100644
--- a/gcc/d/dmd/globals.d
+++ b/gcc/d/dmd/globals.d
@@ -40,24 +40,6 @@ enum DiagnosticReporting : ubyte
off, /// disable diagnostic
}
-/// In which context checks for assertions, contracts, bounds checks etc. are enabled
-enum CHECKENABLE : ubyte
-{
- _default, /// initial value
- off, /// never do checking
- on, /// always do checking
- safeonly, /// do checking only in @safe functions
-}
-
-/// What should happend when an assertion fails
-enum CHECKACTION : ubyte
-{
- D, /// call D assert on failure
- C, /// call C assert on failure
- halt, /// cause program halt on failure
- context, /// call D assert with the error context on failure
-}
-
/**
Each flag represents a field that can be included in the JSON output.
@@ -90,6 +72,16 @@ enum FeatureState : ubyte
enabled = 2, /// Specified as `-preview=`
}
+/// Different identifier tables specifiable by CLI
+enum CLIIdentifierTable : ubyte
+{
+ default_ = 0, /// Not specified by user
+ C99 = 1, /// Tables from C99 standard
+ C11 = 2, /// Tables from C11 standard
+ UAX31 = 3, /// Tables from the Unicode Standard Annex 31: UNICODE IDENTIFIERS AND SYNTAX
+ All = 4, /// The least restrictive set of all other tables
+}
+
extern(C++) struct Output
{
bool doOutput; // Output is enabled
@@ -217,6 +209,9 @@ extern (C++) struct Param
CHECKACTION checkAction = CHECKACTION.D; // action to take when bounds, asserts or switch defaults are violated
+ CLIIdentifierTable dIdentifierTable = CLIIdentifierTable.default_;
+ CLIIdentifierTable cIdentifierTable = CLIIdentifierTable.default_;
+
const(char)[] argv0; // program name
Array!(const(char)*) modFileAliasStrings; // array of char*'s of -I module filename alias strings
Array!(const(char)*) imppath; // array of char*'s of where to look for import modules
@@ -289,6 +284,7 @@ extern (C++) struct Global
Param params; /// command line parameters
uint errors; /// number of errors reported so far
+ uint deprecations; /// number of deprecations reported so far
uint warnings; /// number of warnings reported so far
uint gag; /// !=0 means gag reporting of errors & warnings
uint gaggedErrors; /// number of errors reported while gagged
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index f553ae6..bd28d7b 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -13,6 +13,7 @@
#include "root/dcompat.h"
#include "root/ctfloat.h"
#include "common/outbuffer.h"
+#include "common/charactertables.h"
#include "root/filename.h"
#include "compiler.h"
@@ -82,6 +83,16 @@ enum class FeatureState : unsigned char
enabled = 2, /// Specified as `-preview=`
};
+/// Different identifier tables specifiable by CLI
+enum class CLIIdentifierTable : unsigned char
+{
+ default_ = 0, /// Not specified by user
+ C99 = 1, /// Tables from C99 standard
+ C11 = 2, /// Tables from C11 standard
+ UAX31 = 3, /// Tables from the Unicode Standard Annex 31: UNICODE IDENTIFIERS AND SYNTAX
+ All = 4, /// The least restrictive set of all other tables
+};
+
struct Output
{
/// Configuration for the compiler generator
@@ -200,6 +211,9 @@ struct Param
CHECKACTION checkAction; // action to take when bounds, asserts or switch defaults are violated
+ CLIIdentifierTable dIdentifierTable;
+ CLIIdentifierTable cIdentifierTable;
+
DString argv0; // program name
Array<const char *> modFileAliasStrings; // array of char*'s of -I module filename alias strings
Array<const char *> imppath; // array of char*'s of where to look for import modules
@@ -274,6 +288,9 @@ struct CompileEnv
DString timestamp;
d_bool previewIn;
d_bool ddocOutput;
+ d_bool masm;
+ IdentifierCharLookup cCharLookupTable;
+ IdentifierCharLookup dCharLookupTable;
};
struct Global
@@ -290,6 +307,7 @@ struct Global
Param params;
unsigned errors; // number of errors reported so far
+ unsigned deprecations; // number of deprecations reported so far
unsigned warnings; // number of warnings reported so far
unsigned gag; // !=0 means gag reporting of errors & warnings
unsigned gaggedErrors; // number of errors reported while gagged
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index 5ad324d..6dbc60b 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -448,6 +448,8 @@ immutable Msgtable[] msgtable =
{ "outp"},
{ "outpl"},
{ "outpw"},
+ { "builtinsModuleName", "builtins" },
+ { "ctfeWrite", "__ctfeWrite" },
// Traits
{ "isAbstractClass" },
@@ -529,6 +531,9 @@ immutable Msgtable[] msgtable =
{ "udaMustUse", "mustuse" },
{ "udaStandalone", "standalone" },
+ // Editions
+ { "__edition_latest_do_not_use", },
+
// C names, for undefined identifier error messages
{ "NULL" },
{ "TRUE" },
@@ -553,7 +558,7 @@ immutable Msgtable[] msgtable =
{ "_align", "align" },
{ "aligned" },
{ "__pragma", "pragma" },
- { "builtins", "__builtins" },
+ { "importc_builtins", "__importc_builtins" },
{ "builtin_va_list", "__builtin_va_list" },
{ "builtin_va_arg", "__builtin_va_arg" },
{ "va_list_tag", "__va_list_tag" },
diff --git a/gcc/d/dmd/identifier.d b/gcc/d/dmd/identifier.d
index 8ace310..6fd0d3a 100644
--- a/gcc/d/dmd/identifier.d
+++ b/gcc/d/dmd/identifier.d
@@ -269,12 +269,12 @@ nothrow:
/********************************************
* Create an identifier in the string table.
*/
- static Identifier idPool(const(char)* s, uint len)
+ static Identifier idPool(scope const(char)* s, uint len)
{
return idPool(s[0 .. len]);
}
- extern (D) static Identifier idPool(const(char)[] s, bool isAnonymous = false)
+ extern (D) static Identifier idPool(scope const(char)[] s, bool isAnonymous = false)
{
auto sv = stringtable.update(s);
auto id = sv.value;
@@ -292,7 +292,7 @@ nothrow:
* s = string for keyword
* value = TOK.xxxx for the keyword
*/
- extern (D) static void idPool(const(char)[] s, TOK value)
+ extern (D) static void idPool(scope const(char)[] s, TOK value)
{
auto sv = stringtable.insert(s, null);
assert(sv);
@@ -315,28 +315,83 @@ nothrow:
/**********************************
* ditto
*/
- extern (D) static bool isValidIdentifier(const(char)[] str) @safe
+ extern (D) static bool isValidIdentifier(const(char)[] str) @trusted
{
+ import dmd.common.charactertables;
+
if (str.length == 0 ||
(str[0] >= '0' && str[0] <= '9')) // beware of isdigit() on signed chars
{
return false;
}
- size_t idx = 0;
- while (idx < str.length)
+ // In a previous implementation this was implemented quite naively,
+ // by utilizing the libc.
+ // However we can do better, by copying the lexer approach to identifier validation.
+
+ const(char)* p = &str[0], pEnd = str.ptr + str.length;
+
+ // handle start characters
{
- dchar dc;
- const s = utf_decodeChar(str, idx, dc);
- if (s ||
- !((dc >= 0x80 && isUniAlpha(dc)) || isalnum(dc) || dc == '_'))
+ const c = *p;
+
+ if (isidchar(c))
+ p++;
+ else if (c & 0x80)
{
+ size_t countDecoded;
+ dchar decoded;
+
+ if (utf_decodeChar(p[0 .. pEnd - p], countDecoded, decoded) is null ||
+ isAnyStart(decoded))
+ p += countDecoded;
+ else
+ return false;
+ }
+ else
return false;
+ }
+
+ // handle continue characters
+ while(p !is pEnd)
+ {
+ const c = *p;
+
+ if (isidchar(c)) // handles ASCII subset
+ {
+ p++;
+ continue;
}
+ else if (c & 0x80)
+ {
+ size_t countDecoded;
+ dchar decoded;
+
+ if (utf_decodeChar(p[0 .. pEnd - p], countDecoded, decoded) is null ||
+ isAnyContinue(decoded))
+ {
+ p += countDecoded;
+ continue;
+ }
+ else
+ return false;
+ }
+ else
+ return false;
}
+
return true;
}
+ ///
+ unittest
+ {
+ assert(Identifier.isValidIdentifier("tes123_t".ptr));
+ assert(!Identifier.isValidIdentifier("tes123_^t".ptr));
+ assert(Identifier.isValidIdentifier("te123s_ÄŸt".ptr));
+ assert(!Identifier.isValidIdentifier("t^e123s_ÄŸt".ptr));
+ }
+
extern (D) static Identifier lookup(const(char)* s, size_t len)
{
return lookup(s[0 .. len]);
diff --git a/gcc/d/dmd/init.d b/gcc/d/dmd/init.d
index 62bd41e..7d9e3e6 100644
--- a/gcc/d/dmd/init.d
+++ b/gcc/d/dmd/init.d
@@ -51,38 +51,38 @@ extern (C++) class Initializer : ASTNode
this.kind = kind;
}
- final inout(ErrorInitializer) isErrorInitializer() inout @nogc nothrow pure
+ final inout(ErrorInitializer) isErrorInitializer() inout @nogc nothrow pure @trusted
{
// Use void* cast to skip dynamic casting call
return kind == InitKind.error ? cast(inout ErrorInitializer)cast(void*)this : null;
}
- final inout(VoidInitializer) isVoidInitializer() inout @nogc nothrow pure
+ final inout(VoidInitializer) isVoidInitializer() inout @nogc nothrow pure @trusted
{
return kind == InitKind.void_ ? cast(inout VoidInitializer)cast(void*)this : null;
}
- final inout(DefaultInitializer) isDefaultInitializer() inout @nogc nothrow pure
+ final inout(DefaultInitializer) isDefaultInitializer() inout @nogc nothrow pure @trusted
{
return kind == InitKind.default_ ? cast(inout DefaultInitializer)cast(void*)this : null;
}
- final inout(StructInitializer) isStructInitializer() inout @nogc nothrow pure
+ final inout(StructInitializer) isStructInitializer() inout @nogc nothrow pure @trusted
{
return kind == InitKind.struct_ ? cast(inout StructInitializer)cast(void*)this : null;
}
- final inout(ArrayInitializer) isArrayInitializer() inout @nogc nothrow pure
+ final inout(ArrayInitializer) isArrayInitializer() inout @nogc nothrow pure @trusted
{
return kind == InitKind.array ? cast(inout ArrayInitializer)cast(void*)this : null;
}
- final inout(ExpInitializer) isExpInitializer() inout @nogc nothrow pure
+ final inout(ExpInitializer) isExpInitializer() inout @nogc nothrow pure @trusted
{
return kind == InitKind.exp ? cast(inout ExpInitializer)cast(void*)this : null;
}
- final inout(CInitializer) isCInitializer() inout @nogc nothrow pure
+ final inout(CInitializer) isCInitializer() inout @nogc nothrow pure @trusted
{
return kind == InitKind.C_ ? cast(inout CInitializer)cast(void*)this : null;
}
diff --git a/gcc/d/dmd/init.h b/gcc/d/dmd/init.h
index 2485d78..2ee69f6 100644
--- a/gcc/d/dmd/init.h
+++ b/gcc/d/dmd/init.h
@@ -126,6 +126,6 @@ public:
namespace dmd
{
- Expression *initializerToExpression(Initializer *init, Type *t = NULL, const bool isCfile = false);
+ Expression *initializerToExpression(Initializer *init, Type *t = nullptr, const bool isCfile = false);
Initializer *initializerSemantic(Initializer *init, Scope *sc, Type *&tx, NeedInterpret needInterpret);
}
diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index b07699e..8faad30 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/dmd/initsem.d
@@ -868,11 +868,13 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
* by the initializer syntax. if a CInitializer has a Designator, it is probably
* a nested anonymous struct
*/
- if (cix.initializerList.length)
+ int found;
+ foreach (dix; cix.initializerList)
{
- DesigInit dix = cix.initializerList[0];
Designators* dlistx = dix.designatorList;
- if (dlistx && (*dlistx).length == 1 && (*dlistx)[0].ident)
+ if (!dlistx)
+ continue;
+ if ((*dlistx).length == 1 && (*dlistx)[0].ident)
{
auto id = (*dlistx)[0].ident;
foreach (k, f; sd.fields[]) // linear search for now
@@ -883,11 +885,18 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
si.addInit(id, dix.initializer);
++fieldi;
++index;
- continue Loop1;
+ ++found;
+ break;
}
}
}
+ else {
+ error(ci.loc, "only 1 designator currently allowed for C struct field initializer `%s`", toChars(ci));
+ }
}
+
+ if (found == cix.initializerList.length)
+ continue Loop1;
}
VarDeclaration field;
diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d
index c9c506e..26a56c2 100644
--- a/gcc/d/dmd/lexer.d
+++ b/gcc/d/dmd/lexer.d
@@ -22,9 +22,11 @@ import dmd.errorsink;
import dmd.id;
import dmd.identifier;
import dmd.location;
+import dmd.common.smallbuffer;
+import dmd.common.outbuffer;
+import dmd.common.charactertables;
import dmd.root.array;
import dmd.root.ctfloat;
-import dmd.common.outbuffer;
import dmd.root.port;
import dmd.root.rmem;
import dmd.root.utf;
@@ -42,6 +44,8 @@ version (DMDLIB)
*/
struct CompileEnv
{
+ import dmd.common.charactertables;
+
uint versionNumber; /// __VERSION__
const(char)[] date; /// __DATE__
const(char)[] time; /// __TIME__
@@ -51,6 +55,10 @@ struct CompileEnv
bool previewIn; /// `in` means `[ref] scope const`, accepts rvalues
bool ddocOutput; /// collect embedded documentation comments
bool masm; /// use MASM inline asm syntax
+
+ // these need a default otherwise tests won't work.
+ IdentifierCharLookup cCharLookupTable; /// C identifier table (set to the lexer by the C parser)
+ IdentifierCharLookup dCharLookupTable; /// D identifier table
}
/***********************************************************
@@ -66,6 +74,8 @@ class Lexer
Token token;
+ IdentifierCharLookup charLookup; /// Character table for identifiers
+
// For ImportC
bool Ccompile; /// true if compiling ImportC
@@ -142,6 +152,8 @@ class Lexer
{
this.compileEnv.versionNumber = 1;
this.compileEnv.vendor = "DLF";
+ this.compileEnv.cCharLookupTable = IdentifierCharLookup.forTable(IdentifierTable.LR);
+ this.compileEnv.dCharLookupTable = IdentifierCharLookup.forTable(IdentifierTable.LR);
}
//initKeywords();
/* If first line starts with '#!', ignore the line
@@ -175,6 +187,11 @@ class Lexer
}
endOfLine();
}
+
+ // setup the identifier table lookup functions
+ // C tables are setup in its parser constructor
+ // Due to us not knowing if we're in C at this point in time.
+ charLookup = this.compileEnv.dCharLookupTable;
}
/***********************
@@ -306,6 +323,8 @@ class Lexer
t.blockComment = null;
t.lineComment = null;
+ size_t universalCharacterName4, universalCharacterName8;
+
while (1)
{
t.ptr = p;
@@ -395,10 +414,35 @@ class Lexer
continue; // skip white space
case '\\':
- if (Ccompile && (p[1] == '\r' || p[1] == '\n'))
+ if (Ccompile)
{
- ++p; // ignore \ followed by new line, like VC does
- continue;
+ if (p[1] == '\r' || p[1] == '\n')
+ {
+ ++p; // ignore \ followed by new line, like VC does
+ continue;
+ }
+ else if (p[1] == 'u')
+ {
+ // Universal Character Name (C) 2 byte
+ // \uXXXX
+ // let the main case handling for identifiers process this
+
+ // case_indent will always increment, so subtract to prevent branching on the fast path
+ p--;
+
+ goto case_ident;
+ }
+ else if (p[1] == 'U')
+ {
+ // Universal Character Name (C) 4 byte
+ // \UXXXXXXXX
+ // let the main case handling for identifiers process this
+
+ // case_indent will always increment, so subtract to prevent branching on the fast path
+ p--;
+
+ goto case_ident;
+ }
}
goto default;
@@ -586,23 +630,161 @@ class Lexer
case '_':
case_ident:
{
- while (1)
+ IdentLoop: while (1)
{
+ // If this is changed, change the decrement in C's universal character name code above
+ // For syntax \uXXXX and \UXXXXXXXX
const c = *++p;
+
+ // Is this the first character of the identifier
+ // For the universal character name this will line up,
+ // for the main switch it won't since it wasn't the first,
+ // for the default it won't either because a decode increments.
+ const isStartCharacter = t.ptr is p;
+
if (isidchar(c))
continue;
else if (c & 0x80)
{
const s = p;
const u = decodeUTF();
- if (isUniAlpha(u))
- continue;
- error(t.loc, "char 0x%04x not allowed in identifier", u);
+
+ if (isStartCharacter)
+ {
+ if (charLookup.isStart(u))
+ continue;
+ error(t.loc, "character 0x%04x is not allowed as a start character in an identifier", u);
+ }
+ else
+ {
+ if (charLookup.isContinue(u))
+ continue;
+ error(t.loc, "character 0x%04x is not allowed as a continue character in an identifier", u);
+ }
+
p = s;
}
+ else if (Ccompile && c == '\\')
+ {
+ uint times;
+ const s = p;
+ p++;
+
+ if (*p == 'u')
+ {
+ // Universal Character Name (C) 2 byte
+ // \uXXXX
+ p++;
+ times = 4;
+ }
+ else if (*p == 'U')
+ {
+ // Universal Character Name (C) 4 byte
+ // \UXXXXXXXX
+ p++;
+ times = 8;
+ }
+ else
+ {
+ error(t.loc, "char 0x%x is not allowed to follow '\\' expecting a C universal character name in format \\uXXXX or \\UXXXXXXXX with hex digits instead of X with invalid u/U", *p);
+ p = s;
+ break;
+ }
+
+ foreach(_; 0 .. times)
+ {
+ const hc = *p;
+ p++;
+
+ if ((hc >= '0' && hc <= '9') || (hc >= 'a' && hc <= 'f') || (hc >= 'A' && hc <= 'F'))
+ continue;
+
+ error(t.loc, "char 0x%x is not allowed to follow '\\' expecting a C universal character name in format \\uXXXX or \\UXXXXXXXX with hex digits instead of X with invalid hex digit", hc);
+ p = s;
+ break IdentLoop;
+ }
+
+ continue;
+ }
break;
}
- Identifier id = Identifier.idPool((cast(char*)t.ptr)[0 .. p - t.ptr], false);
+
+ Identifier id;
+
+ if (universalCharacterName4 > 0 || universalCharacterName8 > 0)
+ {
+ auto priorValidation = t.ptr[0 .. p - t.ptr];
+ const(char)* priorVPtr = priorValidation.ptr;
+ const possibleLength = (
+ priorValidation.length - (
+ (universalCharacterName4 * 6) +
+ (universalCharacterName8 * 10)
+ )) + (
+ (universalCharacterName4 * 3) +
+ (universalCharacterName8 * 4)
+ );
+
+ char[64] buffer = void;
+ SmallBuffer!char sb = SmallBuffer!char(possibleLength, buffer[]);
+
+ char[] storage = sb.extent;
+ size_t offset;
+
+ while(priorVPtr < &priorValidation[$-1] + 1)
+ {
+ if (*priorVPtr == '\\')
+ {
+ dchar tempDchar = 0;
+ uint times;
+
+ // universal character name (C)
+ if (priorVPtr[1] == 'u')
+ times = 4;
+ else if (priorVPtr[1] == 'U')
+ times = 8;
+ else
+ assert(0, "ICE: Universal character name is 2 or 4 bytes only");
+ priorVPtr += 2;
+
+ foreach(_; 0 .. times)
+ {
+ char c = *++priorVPtr;
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'a' && c <= 'f')
+ c -= 'a' - 10;
+ else if (c >= 'A' && c <= 'F')
+ c -= 'A' - 10;
+
+ tempDchar <<= 4;
+ tempDchar |= c;
+ }
+
+ utf_encodeChar(&storage[offset], tempDchar);
+ offset += utf_codeLengthChar(tempDchar);
+
+ // Could be an error instead of a warning,
+ // but hey it was written specifically so why worry?
+ if (priorVPtr is priorValidation.ptr)
+ {
+ if (!charLookup.isStart(tempDchar))
+ warning(t.loc, "char 0x%x is not allowed start character for an identifier", tempDchar);
+ }
+ else
+ {
+ if (!charLookup.isContinue(tempDchar))
+ warning(t.loc, "char 0x%x is not allowed continue character for an identifier", tempDchar);
+ }
+ }
+ else
+ storage[offset++] = *++priorVPtr;
+ }
+
+ id = Identifier.idPool(storage[0 .. offset], false);
+ }
+ else
+ id = Identifier.idPool((cast(char*)t.ptr)[0 .. p - t.ptr], false);
+
t.ident = id;
t.value = cast(TOK)id.getValue();
@@ -1174,9 +1356,11 @@ class Lexer
if (c & 0x80)
{
c = decodeUTF();
- // Check for start of unicode identifier
- if (isUniAlpha(c))
+
+ // Check for start of an identifier
+ if (charLookup.isStart(c))
goto case_ident;
+
if (c == PS || c == LS)
{
endOfLine();
@@ -1688,7 +1872,7 @@ class Lexer
delimright = ']';
else if (c == '<')
delimright = '>';
- else if (isalpha(c) || c == '_' || (c >= 0x80 && isUniAlpha(c)))
+ else if (isalpha(c) || c == '_' || (c >= 0x80 && charLookup.isStart(c)))
{
// Start of identifier; must be a heredoc
Token tok;
@@ -1736,7 +1920,9 @@ class Lexer
}
else if (c == delimright)
goto Ldone;
- if (startline && (isalpha(c) || c == '_' || (c >= 0x80 && isUniAlpha(c))) && hereid)
+
+ // we're looking for a new identifier token
+ if (startline && (isalpha(c) || c == '_' || (c >= 0x80 && charLookup.isStart(c))) && hereid)
{
Token tok;
auto psave = p;
@@ -2988,6 +3174,11 @@ class Lexer
eSink.deprecation(loc, format, args);
}
+ void warning(T...)(const ref Loc loc, const(char)* format, T args)
+ {
+ eSink.warning(loc, format, args);
+ }
+
void deprecation(T...)(const(char)* format, T args)
{
eSink.deprecation(token.loc, format, args);
@@ -3416,124 +3607,6 @@ class Lexer
}
}
-
-/******************************* Private *****************************************/
-
-private:
-
-private enum LS = 0x2028; // UTF line separator
-private enum PS = 0x2029; // UTF paragraph separator
-
-/********************************************
- * Do our own char maps
- */
-private static immutable cmtable = ()
-{
- ubyte[256] table;
- foreach (const c; 0 .. table.length)
- {
- if ('0' <= c && c <= '7')
- table[c] |= CMoctal;
- if (c_isxdigit(c))
- table[c] |= CMhex;
- if (c_isalnum(c) || c == '_')
- table[c] |= CMidchar;
-
- switch (c)
- {
- case 'x': case 'X':
- case 'b': case 'B':
- table[c] |= CMzerosecond;
- break;
-
- case '0': .. case '9':
- case 'e': case 'E':
- case 'f': case 'F':
- case 'l': case 'L':
- case 'p': case 'P':
- case 'u': case 'U':
- case 'i':
- case '.':
- case '_':
- table[c] |= CMzerosecond | CMdigitsecond;
- break;
-
- default:
- break;
- }
-
- switch (c)
- {
- case '\\':
- case '\n':
- case '\r':
- case 0:
- case 0x1A:
- case '\'':
- break;
- default:
- if (!(c & 0x80))
- table[c] |= CMsinglechar;
- break;
- }
- }
- return table;
-}();
-
-private
-{
- enum CMoctal = 0x1;
- enum CMhex = 0x2;
- enum CMidchar = 0x4;
- enum CMzerosecond = 0x8;
- enum CMdigitsecond = 0x10;
- enum CMsinglechar = 0x20;
-}
-
-private bool isoctal(const char c) pure @nogc @safe
-{
- return (cmtable[c] & CMoctal) != 0;
-}
-
-private bool ishex(const char c) pure @nogc @safe
-{
- return (cmtable[c] & CMhex) != 0;
-}
-
-private bool isidchar(const char c) pure @nogc @safe
-{
- return (cmtable[c] & CMidchar) != 0;
-}
-
-private bool isZeroSecond(const char c) pure @nogc @safe
-{
- return (cmtable[c] & CMzerosecond) != 0;
-}
-
-private bool isDigitSecond(const char c) pure @nogc @safe
-{
- return (cmtable[c] & CMdigitsecond) != 0;
-}
-
-private bool issinglechar(const char c) pure @nogc @safe
-{
- return (cmtable[c] & CMsinglechar) != 0;
-}
-
-private bool c_isxdigit(const int c) pure @nogc @safe
-{
- return (( c >= '0' && c <= '9') ||
- ( c >= 'a' && c <= 'f') ||
- ( c >= 'A' && c <= 'F'));
-}
-
-private bool c_isalnum(const int c) pure @nogc @safe
-{
- return (( c >= '0' && c <= '9') ||
- ( c >= 'a' && c <= 'z') ||
- ( c >= 'A' && c <= 'Z'));
-}
-
/******************************* Unittest *****************************************/
unittest
diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h
index 379e8e6..7f02bec2 100644
--- a/gcc/d/dmd/module.h
+++ b/gcc/d/dmd/module.h
@@ -28,6 +28,14 @@ enum PKG
PKGpackage // already determined that's an actual package
};
+enum class Edition : unsigned char
+{
+ none = 0u,
+ legacy = 1u,
+ v2024 = 2u,
+ latest = 2u,
+};
+
class Package : public ScopeDsymbol
{
public:
@@ -75,6 +83,7 @@ public:
FileType filetype; // source file type
d_bool hasAlwaysInlines; // contains references to functions that must be inlined
d_bool isPackageFile; // if it is a package.d
+ Edition edition; // language edition that this module is compiled with
Package *pkg; // if isPackageFile is true, the Package that contains this package.d
Strings contentImportedFiles; // array of files whose content was imported
int needmoduleinfo;
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 715ee12..dcfe183 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -1412,7 +1412,7 @@ extern (C++) abstract class Type : ASTNode
* Returns:
* true if so
*/
- bool hasSystemFields()
+ bool hasUnsafeBitpatterns()
{
return false;
}
@@ -1690,7 +1690,7 @@ extern (C++) abstract class TypeNext : Type
* type is meant to be inferred, and semantic() hasn't yet ben run
* on the function. After semantic(), it must no longer be NULL.
*/
- override final Type nextOf()
+ override final Type nextOf() @safe
{
return next;
}
@@ -2340,6 +2340,11 @@ extern (C++) final class TypeBasic : Type
}
}
+ override bool hasUnsafeBitpatterns()
+ {
+ return ty == Tbool;
+ }
+
// For eliminating dynamic_cast
override TypeBasic isTypeBasic()
{
@@ -2657,9 +2662,9 @@ extern (C++) final class TypeSArray : TypeArray
return ae;
}
- override bool hasSystemFields()
+ override bool hasUnsafeBitpatterns()
{
- return next.hasSystemFields();
+ return next.hasUnsafeBitpatterns();
}
override bool hasVoidInitPointers()
@@ -3170,7 +3175,7 @@ extern (C++) final class TypeFunction : TypeNext
* Returns:
* true if D-style variadic
*/
- bool isDstyleVariadic() const pure nothrow
+ bool isDstyleVariadic() const pure nothrow @safe
{
return linkage == LINK.d && parameterList.varargs == VarArg.variadic;
}
@@ -3487,7 +3492,7 @@ extern (C++) final class TypeDelegate : TypeNext
* This is a shell containing a TraitsExp that can be
* either resolved to a type or to a symbol.
*
- * The point is to allow AliasDeclarationY to use `__traits()`, see https://issues.dlang.org/show_bug.cgi?id=7804.
+ * The point is to allow AliasDeclarationY to use `__traits()`, see $(LINK https://issues.dlang.org/show_bug.cgi?id=7804).
*/
extern (C++) final class TypeTraits : Type
{
@@ -3976,11 +3981,11 @@ extern (C++) final class TypeStruct : Type
return sym.hasVoidInitPointers;
}
- override bool hasSystemFields()
+ override bool hasUnsafeBitpatterns()
{
sym.size(Loc.initial); // give error for forward references
sym.determineTypeProperties();
- return sym.hasSystemFields;
+ return sym.hasUnsafeBitpatterns;
}
override bool hasInvariant()
@@ -3992,84 +3997,71 @@ extern (C++) final class TypeStruct : Type
extern (D) MATCH implicitConvToWithoutAliasThis(Type to)
{
- MATCH m;
+ //printf("TypeStruct::implicitConvToWithoutAliasThis(%s => %s)\n", toChars(), to.toChars());
- if (ty == to.ty && sym == (cast(TypeStruct)to).sym)
+ auto tos = to.isTypeStruct();
+ if (!(tos && sym == tos.sym))
+ return MATCH.nomatch;
+
+ if (mod == to.mod)
+ return MATCH.exact;
+
+ if (MODimplicitConv(mod, to.mod))
+ return MATCH.constant;
+
+ /* Check all the fields. If they can all be converted,
+ * allow the conversion.
+ */
+ MATCH m = MATCH.constant;
+ uint offset = ~0; // must never match a field offset
+ foreach (v; sym.fields[])
{
- m = MATCH.exact; // exact match
- if (mod != to.mod)
- {
- m = MATCH.constant;
- if (MODimplicitConv(mod, to.mod))
- {
- }
- else
- {
- /* Check all the fields. If they can all be converted,
- * allow the conversion.
- */
- uint offset = ~0; // dead-store to prevent spurious warning
- for (size_t i = 0; i < sym.fields.length; i++)
- {
- VarDeclaration v = sym.fields[i];
- if (i == 0)
- {
- }
- else if (v.offset == offset)
- {
- if (m > MATCH.nomatch)
- continue;
- }
- else
- {
- if (m == MATCH.nomatch)
- return m;
- }
-
- // 'from' type
- Type tvf = v.type.addMod(mod);
-
- // 'to' type
- Type tv = v.type.addMod(to.mod);
-
- // field match
- MATCH mf = tvf.implicitConvTo(tv);
- //printf("\t%s => %s, match = %d\n", v.type.toChars(), tv.toChars(), mf);
-
- if (mf == MATCH.nomatch)
- return mf;
- if (mf < m) // if field match is worse
- m = mf;
- offset = v.offset;
- }
- }
- }
+ /* Why are we only looking at the first member of a union?
+ * The check should check for overlap of v with the previous field,
+ * not just starting at the same point
+ */
+ if (v.offset == offset) // v is at same offset as previous field
+ continue; // ignore
+
+ Type tvf = v.type.addMod(mod); // from type
+ Type tvt = v.type.addMod(to.mod); // to type
+
+ // field match
+ MATCH mf = tvf.implicitConvTo(tvt);
+ //printf("\t%s => %s, match = %d\n", v.type.toChars(), tvt.toChars(), mf);
+
+ if (mf == MATCH.nomatch)
+ return MATCH.nomatch;
+ if (mf < m) // if field match is worse
+ m = mf;
+ offset = v.offset;
}
return m;
}
extern (D) MATCH implicitConvToThroughAliasThis(Type to)
{
- MATCH m;
- if (!(ty == to.ty && sym == (cast(TypeStruct)to).sym) && sym.aliasthis && !(att & AliasThisRec.tracing))
+ auto tos = to.isTypeStruct();
+ if (!(tos && sym == tos.sym) &&
+ sym.aliasthis &&
+ !(att & AliasThisRec.tracing))
{
if (auto ato = aliasthisOf(this))
{
att = cast(AliasThisRec)(att | AliasThisRec.tracing);
- m = ato.implicitConvTo(to);
+ MATCH m = ato.implicitConvTo(to);
att = cast(AliasThisRec)(att & ~AliasThisRec.tracing);
+ return m;
}
- else
- m = MATCH.nomatch; // no match
}
- return m;
+ return MATCH.nomatch;
}
override MATCH implicitConvTo(Type to)
{
//printf("TypeStruct::implicitConvTo(%s => %s)\n", toChars(), to.toChars());
MATCH m = implicitConvToWithoutAliasThis(to);
- return m ? m : implicitConvToThroughAliasThis(to);
+ return m == MATCH.nomatch ? implicitConvToThroughAliasThis(to) : m;
}
override MATCH constConv(Type to)
@@ -4252,9 +4244,9 @@ extern (C++) final class TypeEnum : Type
return memType().hasVoidInitPointers();
}
- override bool hasSystemFields()
+ override bool hasUnsafeBitpatterns()
{
- return memType().hasSystemFields();
+ return memType().hasUnsafeBitpatterns();
}
override bool hasInvariant()
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index ad64b12..1121711 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -276,7 +276,7 @@ public:
virtual bool isZeroInit(const Loc &loc = Loc()); // if initializer is 0
virtual int hasWild() const;
virtual bool hasVoidInitPointers();
- virtual bool hasSystemFields();
+ virtual bool hasUnsafeBitpatterns();
virtual bool hasInvariant();
virtual Type *nextOf();
Type *baseElemOf();
@@ -421,7 +421,7 @@ public:
MATCH constConv(Type *to) override;
MATCH implicitConvTo(Type *to) override;
Expression *defaultInitLiteral(const Loc &loc) override;
- bool hasSystemFields() override;
+ bool hasUnsafeBitpatterns() override;
bool hasVoidInitPointers() override;
bool hasInvariant() override;
bool needsDestruction() override;
@@ -739,7 +739,7 @@ public:
bool needsCopyOrPostblit() override;
bool needsNested() override;
bool hasVoidInitPointers() override;
- bool hasSystemFields() override;
+ bool hasUnsafeBitpatterns() override;
bool hasInvariant() override;
MATCH implicitConvTo(Type *to) override;
MATCH constConv(Type *to) override;
@@ -775,7 +775,7 @@ public:
MATCH constConv(Type *to) override;
bool isZeroInit(const Loc &loc) override;
bool hasVoidInitPointers() override;
- bool hasSystemFields() override;
+ bool hasUnsafeBitpatterns() override;
bool hasInvariant() override;
Type *nextOf() override;
@@ -877,7 +877,7 @@ namespace dmd
// return the symbol to which type t resolves
Dsymbol *toDsymbol(Type *t, Scope *sc);
bool equivalent(Type *src, Type *t);
- Covariant covariant(Type *, Type *, StorageClass * = NULL, bool = false);
+ Covariant covariant(Type *, Type *, StorageClass * = nullptr, bool = false);
bool isBaseOf(Type *tthis, Type *t, int *poffset);
Type *trySemantic(Type *type, const Loc &loc, Scope *sc);
Type *pointerTo(Type *type);
diff --git a/gcc/d/dmd/mustuse.d b/gcc/d/dmd/mustuse.d
index c2fa5fb..fc7618b 100644
--- a/gcc/d/dmd/mustuse.d
+++ b/gcc/d/dmd/mustuse.d
@@ -202,7 +202,7 @@ private bool isIncrementOrDecrement(Expression e)
*/
private bool hasMustUseAttribute(Dsymbol sym, Scope* sc)
{
- import dmd.attrib : foreachUda;
+ import dmd.attribsem : foreachUda;
bool result = false;
diff --git a/gcc/d/dmd/ob.d b/gcc/d/dmd/ob.d
index 0a59815..756caf8 100644
--- a/gcc/d/dmd/ob.d
+++ b/gcc/d/dmd/ob.d
@@ -7,6 +7,9 @@
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ob.d, _ob.d)
* Documentation: https://dlang.org/phobos/dmd_escape.html
* Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/ob.d
+ * Bug reports: use 'live' keyword:
+ * https://issues.dlang.org/buglist.cgi?bug_status=NEW&bug_status=REOPENED&keywords=live
+ * References: https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md Argument Ownership and Function Calls
*/
module dmd.ob;
@@ -32,6 +35,7 @@ import dmd.expression;
import dmd.foreachvar;
import dmd.func;
import dmd.globals;
+import dmd.hdrgen;
import dmd.identifier;
import dmd.init;
import dmd.location;
@@ -40,6 +44,7 @@ import dmd.printast;
import dmd.statement;
import dmd.stmtstate;
import dmd.tokens;
+import dmd.typesem;
import dmd.visitor;
import dmd.root.bitarray;
@@ -226,6 +231,8 @@ struct PtrVarState
* are being merged
* Params:
* pvs = path to be merged with `this`
+ * vi = variable's index into gen[]
+ * gen = array of variable states
*/
void combine(ref PtrVarState pvs, size_t vi, PtrVarState[] gen)
{
@@ -280,6 +287,9 @@ struct PtrVarState
}
/***********************
+ * Print a bracketed list of all the variables that depend on 'this'
+ * Params:
+ * vars = variables that depend on 'this'
*/
void print(VarDeclaration[] vars)
{
@@ -846,7 +856,7 @@ void toObNodes(ref ObNodes obnodes, Statement s)
case STMT.Mixin:
case STMT.Peel:
case STMT.Synchronized:
- debug printf("s: %s\n", s.toChars());
+ debug printf("s: %s\n", toChars(s));
assert(0); // should have been rewritten
}
}
@@ -1113,8 +1123,8 @@ bool isTrackableVar(VarDeclaration v)
/* Assume types with a destructor are doing their own tracking,
* such as being a ref counted type
*/
- if (v.needsScopeDtor())
- return false;
+// if (v.needsScopeDtor())
+// return false;
/* Not tracking function parameters that are not mutable
*/
@@ -1231,7 +1241,8 @@ void allocStates(ref ObState obstate)
*/
bool isBorrowedPtr(VarDeclaration v)
{
- return v.isScope() && !v.isowner && v.type.nextOf().isMutable();
+ return v.isScope() && !v.isowner &&
+ v.type.hasPointersToMutableFields();
}
/******************************
@@ -1241,7 +1252,7 @@ bool isBorrowedPtr(VarDeclaration v)
*/
bool isReadonlyPtr(VarDeclaration v)
{
- return v.isScope() && !v.type.nextOf().isMutable();
+ return v.isScope() && !v.type.hasPointersToMutableFields();
}
/***************************************
@@ -1251,7 +1262,7 @@ void genKill(ref ObState obstate, ObNode* ob)
{
enum log = false;
if (log)
- printf("-----------computeGenKill()-----------\n");
+ printf("-----------computeGenKill() %d -----------\n", ob.index);
/***************
* Assigning result of expression `e` to variable `v`.
@@ -1274,8 +1285,6 @@ void genKill(ref ObState obstate, ObNode* ob)
pvs.state = PtrState.Owner;
pvs.deps.zero();
- EscapeByResults er;
- escapeByValue(e, &er, true);
bool any = false; // if any variables are assigned to v
void by(VarDeclaration r)
@@ -1305,10 +1314,7 @@ void genKill(ref ObState obstate, ObNode* ob)
}
}
- foreach (VarDeclaration v2; er.byvalue)
- by(v2);
- foreach (VarDeclaration v2; er.byref)
- by(v2);
+ escapeLive(e, &by);
/* Make v an Owner for initializations like:
* scope v = malloc();
@@ -1435,6 +1441,41 @@ void genKill(ref ObState obstate, ObNode* ob)
assert(t.ty == Tdelegate);
tf = t.nextOf().isTypeFunction();
assert(tf);
+
+ }
+
+ if (auto dve = ce.e1.isDotVarExp())
+ {
+ if (!t.isTypeDelegate() && dve.e1.isVarExp())
+ {
+ //printf("dve: %s\n", dve.toChars());
+
+ void byf(VarDeclaration v)
+ {
+ //printf("byf v: %s\n", v.ident.toChars());
+ if (!isTrackableVar(v))
+ return;
+
+ const vi = obstate.vars.find(v);
+ if (vi == size_t.max)
+ return;
+
+ auto fd = dve.var.isFuncDeclaration();
+ if (fd && fd.storage_class & STC.scope_)
+ {
+ // borrow
+ obstate.varStack.push(vi);
+ obstate.mutableStack.push(isMutableRef(dve.e1.type.toBasetype()));
+ }
+ else
+ {
+ // move (i.e. consume arg)
+ makeUndefined(vi, ob.gen);
+ }
+ }
+
+ escapeLive(dve.e1, &byf);
+ }
}
// j=1 if _arguments[] is first argument
@@ -1450,14 +1491,13 @@ void genKill(ref ObState obstate, ObNode* ob)
Parameter p = tf.parameterList[i - j];
auto pt = p.type.toBasetype();
- EscapeByResults er;
- escapeByValue(arg, &er, true);
if (!(p.storageClass & STC.out_ && arg.isVarExp()))
arg.accept(this);
void by(VarDeclaration v)
{
+ //printf("by v: %s\n", v.ident.toChars());
if (!isTrackableVar(v))
return;
@@ -1484,18 +1524,12 @@ void genKill(ref ObState obstate, ObNode* ob)
}
}
- foreach (VarDeclaration v2; er.byvalue)
- by(v2);
- foreach (VarDeclaration v2; er.byref)
- by(v2);
+ escapeLive(arg, &by);
}
else // variadic args
{
arg.accept(this);
- EscapeByResults er;
- escapeByValue(arg, &er, true);
-
void byv(VarDeclaration v)
{
if (!isTrackableVar(v))
@@ -1517,10 +1551,7 @@ void genKill(ref ObState obstate, ObNode* ob)
makeUndefined(vi, ob.gen);
}
- foreach (VarDeclaration v2; er.byvalue)
- byv(v2);
- foreach (VarDeclaration v2; er.byref)
- byv(v2);
+ escapeLive(arg, &byv);
}
}
@@ -1721,6 +1752,15 @@ void genKill(ref ObState obstate, ObNode* ob)
}
foreachExp(ob, ob.exp);
+
+ if (log)
+ {
+ printf(" gen:\n");
+ foreach (i, ref pvs2; ob.gen[])
+ {
+ printf(" %s: ", obstate.vars[i].toChars()); pvs2.print(obstate.vars[]);
+ }
+ }
}
/***************************************
@@ -1946,6 +1986,25 @@ void doDataFlowAnalysis(ref ObState obstate)
/***************************************
+ * Check for escaping variables using DIP1000's `escapeByValue`, with `live` set to `true`
+ * Params:
+ * e = expression to check
+ * onVar = gets called for each variable escaped through `e`, either by value or by ref
+ */
+void escapeLive(Expression e, scope void delegate(VarDeclaration) onVar)
+{
+ scope EscapeByResults er = EscapeByResults(
+ (VarDeclaration v, bool) => onVar(v),
+ onVar,
+ (FuncDeclaration f, bool) {},
+ (Expression e, bool) {},
+ true,
+ );
+
+ escapeByValue(e, er, true);
+}
+
+/***************************************
* Check for Ownership/Borrowing errors.
*/
void checkObErrors(ref ObState obstate)
@@ -1976,8 +2035,6 @@ void checkObErrors(ref ObState obstate)
}
pvs.deps.zero();
- EscapeByResults er;
- escapeByValue(e, &er, true);
void by(VarDeclaration r) // `v` = `r`
{
@@ -2015,10 +2072,7 @@ void checkObErrors(ref ObState obstate)
}
}
- foreach (VarDeclaration v2; er.byvalue)
- by(v2);
- foreach (VarDeclaration v2; er.byref)
- by(v2);
+ escapeLive(e, &by);
}
else
{
@@ -2157,8 +2211,6 @@ void checkObErrors(ref ObState obstate)
if (!(p.storageClass & STC.out_ && arg.isVarExp()))
arg.accept(this);
- EscapeByResults er;
- escapeByValue(arg, &er, true);
void by(VarDeclaration v)
{
@@ -2192,18 +2244,11 @@ void checkObErrors(ref ObState obstate)
}
}
- foreach (VarDeclaration v2; er.byvalue)
- by(v2);
- foreach (VarDeclaration v2; er.byref)
- by(v2);
+ escapeLive(arg, &by);
}
else // variadic args
{
arg.accept(this);
-
- EscapeByResults er;
- escapeByValue(arg, &er, true);
-
void byv(VarDeclaration v)
{
if (!isTrackableVar(v))
@@ -2231,10 +2276,7 @@ void checkObErrors(ref ObState obstate)
}
}
- foreach (VarDeclaration v2; er.byvalue)
- byv(v2);
- foreach (VarDeclaration v2; er.byref)
- byv(v2);
+ escapeLive(arg, &byv);
}
}
@@ -2460,7 +2502,7 @@ void checkObErrors(ref ObState obstate)
{
static if (log)
{
- printf("%d: %s\n", obi, ob.exp ? ob.exp.toChars() : "".ptr);
+ printf("%d: %s\n", cast(int) obi, ob.exp ? ob.exp.toChars() : "".ptr);
printf(" input:\n");
foreach (i, ref pvs; ob.input[])
{
@@ -2490,7 +2532,9 @@ void checkObErrors(ref ObState obstate)
if (s1 != s2 && (s1 == PtrState.Owner || s2 == PtrState.Owner))
{
auto v = obstate.vars[i];
- .error(ob.exp ? ob.exp.loc : v.loc, "%s `%s` is both %s and %s", v.kind, v.toPrettyChars, PtrStateToChars(s1), PtrStateToChars(s2));
+ // Don't worry about non-pointers
+ if (hasPointers(v.type))
+ .error(ob.exp ? ob.exp.loc : v.loc, "%s `%s` is both %s and %s", v.kind, v.toPrettyChars, PtrStateToChars(s1), PtrStateToChars(s2));
}
pvs1.combine(*pvs2, i, ob.gen);
}
@@ -2522,9 +2566,6 @@ void checkObErrors(ref ObState obstate)
if (ob.obtype == ObType.retexp)
{
- EscapeByResults er;
- escapeByValue(ob.exp, &er, true);
-
void by(VarDeclaration r) // `r` is the rvalue
{
const ri = obstate.vars.find(r);
@@ -2552,11 +2593,7 @@ void checkObErrors(ref ObState obstate)
}
}
}
-
- foreach (VarDeclaration v2; er.byvalue)
- by(v2);
- foreach (VarDeclaration v2; er.byref)
- by(v2);
+ escapeLive(ob.exp, &by);
}
if (ob.obtype == ObType.return_ || ob.obtype == ObType.retexp)
@@ -2649,6 +2686,9 @@ void makeChildrenUndefined(size_t vi, PtrVarState[] gen)
/********************
* Recursively make Undefined vi undefined and all who list vi as a dependency
+ * Params:
+ * vi = variable's index
+ * gen = array of the states of variables
*/
void makeUndefined(size_t vi, PtrVarState[] gen)
{
diff --git a/gcc/d/dmd/objc.d b/gcc/d/dmd/objc.d
index 2f36d5d..624210b 100644
--- a/gcc/d/dmd/objc.d
+++ b/gcc/d/dmd/objc.d
@@ -17,6 +17,7 @@ import dmd.aggregate;
import dmd.arraytypes;
import dmd.astenums;
import dmd.attrib;
+import dmd.attribsem;
import dmd.cond;
import dmd.dclass;
import dmd.declaration;
diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d
index 70eeaff..0d32d7d 100644
--- a/gcc/d/dmd/opover.d
+++ b/gcc/d/dmd/opover.d
@@ -29,6 +29,7 @@ import dmd.errors;
import dmd.expression;
import dmd.expressionsem;
import dmd.func;
+import dmd.funcsem;
import dmd.globals;
import dmd.hdrgen;
import dmd.id;
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 646c4b7..a7a9303 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -233,6 +233,15 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
}
else
{
+ static if (is(typeof(mod.edition)))
+ if (exps && exps.length > 0)
+ if (auto id = (*exps)[0].isIdentifierExp())
+ if (id.ident == Id.__edition_latest_do_not_use)
+ {
+ mod.edition = Edition.latest;
+ continue;
+ }
+
udas = AST.UserAttributeDeclaration.concat(udas, exps);
}
if (stc)
@@ -5960,9 +5969,18 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
goto Lexp;
goto case;
+ // FunctionLiteral `auto ref (`
+ case TOK.auto_:
+ if (peekNext() == TOK.ref_ && peekNext2() == TOK.leftParenthesis)
+ goto Lexp;
+ goto Ldeclaration;
+ case TOK.ref_:
+ if (peekNext() == TOK.leftParenthesis)
+ goto Lexp;
+ goto Ldeclaration;
+
case TOK.alias_:
case TOK.const_:
- case TOK.auto_:
case TOK.abstract_:
case TOK.extern_:
case TOK.align_:
@@ -5972,7 +5990,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.deprecated_:
case TOK.nothrow_:
case TOK.pure_:
- case TOK.ref_:
case TOK.gshared:
case TOK.at:
case TOK.struct_:
@@ -9580,9 +9597,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
void usageOfBodyKeyword()
{
- version (none) // disable obsolete warning
+ if (mod.edition >= Edition.v2024)
{
- eSink.warning(token.loc, "usage of identifer `body` as a keyword is obsolete. Use `do` instead.");
+ eSink.error(token.loc, "usage of identifer `body` as a keyword is obsolete. Use `do` instead.");
}
}
}
diff --git a/gcc/d/dmd/pragmasem.d b/gcc/d/dmd/pragmasem.d
index b52b551..4dceb59 100644
--- a/gcc/d/dmd/pragmasem.d
+++ b/gcc/d/dmd/pragmasem.d
@@ -67,6 +67,8 @@ void pragmaDeclSemantic(PragmaDeclaration pd, Scope* sc)
}
version (all)
{
+ import dmd.common.charactertables;
+
/* Note: D language specification should not have any assumption about backend
* implementation. Ideally pragma(mangle) can accept a string of any content.
*
@@ -94,7 +96,7 @@ void pragmaDeclSemantic(PragmaDeclaration pd, Scope* sc)
.error(pd.loc, "%s `%s` %.*s", pd.kind, pd.toPrettyChars, cast(int)msg.length, msg.ptr);
break;
}
- if (!isUniAlpha(c))
+ if (!isAnyIdentifierCharacter(c))
{
.error(pd.loc, "%s `%s` char `0x%04x` not allowed in mangled name", pd.kind, pd.toPrettyChars, c);
break;
diff --git a/gcc/d/dmd/root/array.h b/gcc/d/dmd/root/array.h
index 3e28804..cb8f8dc 100644
--- a/gcc/d/dmd/root/array.h
+++ b/gcc/d/dmd/root/array.h
@@ -26,7 +26,7 @@ struct Array
public:
Array()
{
- data.ptr = NULL;
+ data.ptr = nullptr;
length = 0;
data.length = 0;
}
@@ -86,7 +86,7 @@ struct Array
if (nentries <= SMALLARRAYCAP)
{
data.length = SMALLARRAYCAP;
- data.ptr = SMALLARRAYCAP ? &smallarray[0] : NULL;
+ data.ptr = SMALLARRAYCAP ? &smallarray[0] : nullptr;
}
else
{
diff --git a/gcc/d/dmd/root/bitarray.h b/gcc/d/dmd/root/bitarray.h
index 2a82703..0bea2d5 100644
--- a/gcc/d/dmd/root/bitarray.h
+++ b/gcc/d/dmd/root/bitarray.h
@@ -15,7 +15,7 @@ struct BitArray
{
BitArray()
: len(0)
- , ptr(NULL)
+ , ptr(nullptr)
{}
~BitArray()
diff --git a/gcc/d/dmd/root/dcompat.h b/gcc/d/dmd/root/dcompat.h
index db2b2c6..e397fa7 100644
--- a/gcc/d/dmd/root/dcompat.h
+++ b/gcc/d/dmd/root/dcompat.h
@@ -18,7 +18,7 @@ struct DArray
size_t length;
T *ptr;
- DArray() : length(0), ptr(NULL) { }
+ DArray() : length(0), ptr(nullptr) { }
DArray(size_t length_in, T *ptr_in)
: length(length_in), ptr(ptr_in) { }
diff --git a/gcc/d/dmd/root/file.d b/gcc/d/dmd/root/file.d
index a4362e1..ee7170e 100644
--- a/gcc/d/dmd/root/file.d
+++ b/gcc/d/dmd/root/file.d
@@ -19,11 +19,13 @@ import core.sys.posix.fcntl;
import core.sys.posix.unistd;
import core.sys.windows.winbase;
import core.sys.windows.winnt;
+
import dmd.root.filename;
import dmd.root.rmem;
import dmd.root.string;
import dmd.common.file;
+import dmd.common.outbuffer;
import dmd.common.smallbuffer;
nothrow:
@@ -76,62 +78,52 @@ struct File
}
nothrow:
- /// Read the full content of a file.
- static ReadResult read(const(char)[] name)
+ /** Read the full content of a file, and append it to `buffer`
+ * Params:
+ * name = name of file
+ * buffer = file contents appended to it
+ * Returns:
+ * false = success, true = failed
+ */
+ static bool read(const char[] name, ref OutBuffer buffer)
{
- ReadResult result;
+ enum Success = false;
+ enum Failure = true;
version (Posix)
{
- size_t size;
- stat_t buf;
- ssize_t numread;
- //printf("File::read('%s')\n",name);
+ //printf("File::read('%.*s')\n", cast(int)name.length, name.ptr);
int fd = name.toCStringThen!(slice => open(slice.ptr, O_RDONLY));
if (fd == -1)
{
//perror("\topen error");
- return result;
+ return Failure;
}
//printf("\tfile opened\n");
- if (fstat(fd, &buf))
+ stat_t statbuf;
+ if (fstat(fd, &statbuf))
{
//perror("\tfstat error");
close(fd);
- return result;
+ return Failure;
}
- size = cast(size_t)buf.st_size;
- ubyte* buffer = cast(ubyte*)mem.xmalloc_noscan(size + 4);
- numread = .read(fd, buffer, size);
+ size_t size = cast(size_t)statbuf.st_size;
+ auto buf = buffer.allocate(size);
+ ssize_t numread = .read(fd, buf.ptr, size);
if (numread != size)
{
//perror("\tread error");
- goto err2;
+ close(fd);
+ return Failure;
}
if (close(fd) == -1)
{
//perror("\tclose error");
- goto err;
+ return Failure;
}
- // Always store a wchar ^Z past end of buffer so scanner has a
- // sentinel, although ^Z got obselete, so fill with two 0s and add
- // two more so lexer doesn't read pass the buffer.
- buffer[size .. size + 4] = 0;
-
- result.success = true;
- result.buffer.data = buffer[0 .. size];
- return result;
- err2:
- close(fd);
- err:
- mem.xfree(buffer);
- return result;
}
else version (Windows)
{
- DWORD size;
- DWORD numread;
-
// work around Windows file path length limitation
// (see documentation for extendedPathThen).
HANDLE h = name.extendedPathThen!
@@ -143,32 +135,24 @@ nothrow:
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
null));
if (h == INVALID_HANDLE_VALUE)
- return result;
- size = GetFileSize(h, null);
- ubyte* buffer = cast(ubyte*)mem.xmalloc_noscan(size + 4);
- if (ReadFile(h, buffer, size, &numread, null) != TRUE)
- goto err2;
- if (numread != size)
- goto err2;
+ return Failure;
+ DWORD size = GetFileSize(h, null);
+ auto buf = buffer.allocate(size);
+ DWORD numread;
+ if (ReadFile(h, buf.ptr, size, &numread, null) != TRUE ||
+ numread != size)
+ {
+ CloseHandle(h);
+ return Failure;
+ }
if (!CloseHandle(h))
- goto err;
- // Always store a wchar ^Z past end of buffer so scanner has a
- // sentinel, although ^Z got obselete, so fill with two 0s and add
- // two more so lexer doesn't read pass the buffer.
- buffer[size .. size + 4] = 0;
- result.success = true;
- result.buffer.data = buffer[0 .. size];
- return result;
- err2:
- CloseHandle(h);
- err:
- mem.xfree(buffer);
- return result;
+ return Failure;
}
else
{
- assert(0);
+ static assert(0);
}
+ return Success;
}
/// Write a file, returning `true` on success.
diff --git a/gcc/d/dmd/root/filename.d b/gcc/d/dmd/root/filename.d
index d9f1a04..1fbe0ae 100644
--- a/gcc/d/dmd/root/filename.d
+++ b/gcc/d/dmd/root/filename.d
@@ -13,6 +13,7 @@ module dmd.root.filename;
import core.stdc.ctype;
import core.stdc.errno;
+import core.stdc.stdio;
import core.stdc.string;
import dmd.common.file;
@@ -270,6 +271,20 @@ nothrow:
}
/********************************
+ * Slice of file name without extension.
+ * Params:
+ * filename = file name
+ * Returns:
+ * the slice
+ */
+ extern (D) static const(char)[] sansExt(const char[] filename)
+ {
+ auto e = ext(filename);
+ size_t length = e.length;
+ return filename[0 .. filename.length - (length ? length + 1 : 0)]; // +1 for .
+ }
+
+ /********************************
* Return filename name excluding path (read-only).
*/
extern (C++) static const(char)* name(const(char)* str) pure @nogc
@@ -452,17 +467,15 @@ nothrow:
assert(buildPath("a/", "bb", "ccc") == "a/bb/ccc");
}
- // Split a path into an Array of paths
- extern (C++) static Strings* splitPath(const(char)* path)
+ // Split a path and append the results to `array`
+ extern (C++) static void appendSplitPath(const(char)* path, ref Strings array)
{
- auto array = new Strings();
int sink(const(char)* p) nothrow
{
array.push(p);
return 0;
}
splitPath(&sink, path);
- return array;
}
/****
@@ -846,6 +859,7 @@ nothrow:
{
if (!name.length)
return 0;
+ //static int count; printf("count: %d %.*s\n", ++count, cast(int)name.length, name.ptr);
version (Posix)
{
stat_t st;
diff --git a/gcc/d/dmd/root/filename.h b/gcc/d/dmd/root/filename.h
index e8c8b11..b4d25b9 100644
--- a/gcc/d/dmd/root/filename.h
+++ b/gcc/d/dmd/root/filename.h
@@ -22,7 +22,7 @@ public:
static FileName create(const char *name);
static bool equals(const char *name1, const char *name2);
static bool absolute(const char *name);
- static const char *toAbsolute(const char *name, const char *base = NULL);
+ static const char *toAbsolute(const char *name, const char *base = nullptr);
static const char *ext(const char *);
const char *ext();
static const char *removeExt(const char *str);
@@ -31,7 +31,7 @@ public:
static const char *path(const char *);
static const char *combine(const char *path, const char *name);
- static Strings *splitPath(const char *path);
+ static void appendSplitPath(const char *path, Strings& array);
static const char *defaultExt(const char *name, const char *ext);
static const char *forceExt(const char *name, const char *ext);
static bool equalsExt(const char *name, const char *ext);
diff --git a/gcc/d/dmd/root/rmem.d b/gcc/d/dmd/root/rmem.d
index 1965207..c6986c0 100644
--- a/gcc/d/dmd/root/rmem.d
+++ b/gcc/d/dmd/root/rmem.d
@@ -318,7 +318,7 @@ Params:
Returns: A null-terminated copy of the input array.
*/
-extern (D) char[] xarraydup(const(char)[] s) pure nothrow
+extern (D) char[] xarraydup(scope const(char)[] s) pure nothrow
{
if (!s)
return null;
diff --git a/gcc/d/dmd/root/string.d b/gcc/d/dmd/root/string.d
index e82b0d2..4b4c3e1 100644
--- a/gcc/d/dmd/root/string.d
+++ b/gcc/d/dmd/root/string.d
@@ -10,6 +10,9 @@
*/
module dmd.root.string;
+import core.stdc.string;
+import dmd.root.rmem;
+
/// Slices a `\0`-terminated C-string, excluding the terminator
inout(char)[] toDString (inout(char)* s) pure nothrow @nogc
{
@@ -87,6 +90,23 @@ unittest
assert(null.toCStringThen!((v) => v == "\0"));
}
+/*********************************************
+ * Convert a D string to a C string by allocating memory,
+ * copying it, and adding a terminating 0.
+ * Params:
+ * s = string to copy
+ * Result:
+ * 0-terminated copy of s
+ */
+char[] toCString(scope const(char)[] s) nothrow
+{
+ const length = s.length;
+ char* p = cast(char*)mem.xmalloc_noscan(length + 1);
+ memcpy(p, s.ptr, length);
+ p[length] = 0;
+ return p[0 .. length];
+}
+
/**
* Strips one leading line terminator of the given string.
*
@@ -274,6 +294,15 @@ do
return true;
}
+///ditto
+nothrow @nogc pure @safe
+bool startsWith(scope const(char)[] str, scope const(char)[] prefix)
+{
+ if (str.length < prefix.length)
+ return false;
+ return str[0 .. prefix.length] == prefix;
+}
+
///
@system pure nothrow @nogc
unittest
@@ -286,3 +315,170 @@ unittest
assert(ptr.startsWith("123"));
assert(!ptr.startsWith("1234"));
}
+
+/**********************************
+ * Take `text` and turn it into an InputRange that emits
+ * slices into `text` for each line.
+ * Params:
+ * text = array of characters
+ * Returns:
+ * InputRange accessing `text` as a sequence of lines
+ * Reference:
+ * `std.string.splitLines()`
+ */
+auto splitLines(const char[] text)
+{
+ struct Range
+ {
+ @safe:
+ @nogc:
+ nothrow:
+ pure:
+ private:
+
+ const char[] text;
+ size_t index; // index of start of line
+ size_t eolIndex; // index of end of line before newline characters
+ size_t nextIndex; // index past end of line
+
+ public this(const char[] text)
+ {
+ this.text = text;
+ }
+
+ public bool empty() { return index == text.length; }
+
+ public void popFront() { advance(); index = nextIndex; }
+
+ public const(char)[] front() { advance(); return text[index .. eolIndex]; }
+
+ private void advance()
+ {
+ if (index != nextIndex) // if already advanced
+ return;
+
+ for (size_t i = index; i < text.length; ++i)
+ {
+ switch (text[i])
+ {
+ case '\v', '\f', '\n':
+ eolIndex = i;
+ nextIndex = i + 1;
+ return;
+
+ case '\r':
+ if (i + 1 < text.length && text[i + 1] == '\n') // decode "\r\n"
+ {
+ eolIndex = i;
+ nextIndex = i + 2;
+ return;
+ }
+ eolIndex = i;
+ nextIndex = i + 1;
+ return;
+
+ /* Manually decode:
+ * NEL is C2 85
+ */
+ case 0xC2:
+ if (i + 1 < text.length && text[i + 1] == 0x85)
+ {
+ eolIndex = i;
+ nextIndex = i + 2;
+ return;
+ }
+ break;
+
+ /* Manually decode:
+ * lineSep is E2 80 A8
+ * paraSep is E2 80 A9
+ */
+ case 0xE2:
+ if (i + 2 < text.length &&
+ text[i + 1] == 0x80 &&
+ (text[i + 2] == 0xA8 || text[i + 2] == 0xA9)
+ )
+ {
+ eolIndex = i;
+ nextIndex = i + 3;
+ return;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ return Range(text);
+}
+
+private struct FindSplit
+{
+@nogc nothrow pure @safe:
+ const(char)[][3] elem;
+
+ ref const(char)[] opIndex(size_t i) scope return { return elem[i]; }
+ bool opCast() const scope { return elem[1].length > 0; }
+}
+
+/**
+Find a substring in a string and split the string into before and after parts.
+Params:
+ str = string to look into
+ needle = substring to find in str (must not be empty)
+Returns:
+ a `FindSplit` object that casts to `true` iff `needle` was found inside `str`.
+ In that case, `split[1]` is the needle, and `split[0]`/`split[2]` are before/after the needle.
+*/
+FindSplit findSplit(return scope const(char)[] str, scope const(char)[] needle)
+{
+ if (needle.length > str.length)
+ return FindSplit([str, null, null]);
+
+ foreach (i; 0 .. str.length - needle.length + 1)
+ {
+ if (str[i .. i+needle.length] == needle[])
+ return FindSplit([ str[0 .. i], str[i .. i+needle.length], str[i+needle.length .. $] ]);
+ }
+ return FindSplit([str, null, null]);
+}
+
+unittest
+{
+ auto s = findSplit("a b c", "c");
+ assert(s[0] == "a b ");
+ assert(s[1] == "c");
+ assert(s[2] == "");
+ auto s1 = findSplit("a b c", "b");
+ assert(s1[0] == "a ");
+ assert(s1[1] == "b");
+ assert(s1[2] == " c");
+ assert(!findSplit("a b c", "d"));
+ assert(!findSplit("", "d"));
+}
+
+/**
+Find a string inbetween two substrings
+Params:
+ str = string to look into
+ l = substring to find on the left
+ r = substring to find on the right
+Returns:
+ substring of `str` inbetween `l` and `r`
+*/
+const(char)[] findBetween(const(char)[] str, const(char)[] l, const(char)[] r)
+{
+ if (auto s0 = str.findSplit(l))
+ if (auto s1 = s0[2].findSplit(r))
+ return s1[0];
+ return null;
+}
+
+unittest
+{
+ assert(findBetween("a b c", "a ", " c") == "b");
+ assert(findBetween("a b c", "a ", " d") == null);
+}
diff --git a/gcc/d/dmd/root/utf.d b/gcc/d/dmd/root/utf.d
index 7d732f2..36f0b98 100644
--- a/gcc/d/dmd/root/utf.d
+++ b/gcc/d/dmd/root/utf.d
@@ -27,281 +27,6 @@ bool utf_isValidDchar(dchar c)
return false;
}
-/*******************************
- * Return !=0 if unicode alpha.
- * Use table from C99 Appendix D.
- */
-bool isUniAlpha(dchar c)
-{
- static immutable wchar[2][] ALPHA_TABLE =
- [
- [0x00AA, 0x00AA],
- [0x00B5, 0x00B5],
- [0x00B7, 0x00B7],
- [0x00BA, 0x00BA],
- [0x00C0, 0x00D6],
- [0x00D8, 0x00F6],
- [0x00F8, 0x01F5],
- [0x01FA, 0x0217],
- [0x0250, 0x02A8],
- [0x02B0, 0x02B8],
- [0x02BB, 0x02BB],
- [0x02BD, 0x02C1],
- [0x02D0, 0x02D1],
- [0x02E0, 0x02E4],
- [0x037A, 0x037A],
- [0x0386, 0x0386],
- [0x0388, 0x038A],
- [0x038C, 0x038C],
- [0x038E, 0x03A1],
- [0x03A3, 0x03CE],
- [0x03D0, 0x03D6],
- [0x03DA, 0x03DA],
- [0x03DC, 0x03DC],
- [0x03DE, 0x03DE],
- [0x03E0, 0x03E0],
- [0x03E2, 0x03F3],
- [0x0401, 0x040C],
- [0x040E, 0x044F],
- [0x0451, 0x045C],
- [0x045E, 0x0481],
- [0x0490, 0x04C4],
- [0x04C7, 0x04C8],
- [0x04CB, 0x04CC],
- [0x04D0, 0x04EB],
- [0x04EE, 0x04F5],
- [0x04F8, 0x04F9],
- [0x0531, 0x0556],
- [0x0559, 0x0559],
- [0x0561, 0x0587],
- [0x05B0, 0x05B9],
- [0x05BB, 0x05BD],
- [0x05BF, 0x05BF],
- [0x05C1, 0x05C2],
- [0x05D0, 0x05EA],
- [0x05F0, 0x05F2],
- [0x0621, 0x063A],
- [0x0640, 0x0652],
- [0x0660, 0x0669],
- [0x0670, 0x06B7],
- [0x06BA, 0x06BE],
- [0x06C0, 0x06CE],
- [0x06D0, 0x06DC],
- [0x06E5, 0x06E8],
- [0x06EA, 0x06ED],
- [0x06F0, 0x06F9],
- [0x0901, 0x0903],
- [0x0905, 0x0939],
- [0x093D, 0x094D],
- [0x0950, 0x0952],
- [0x0958, 0x0963],
- [0x0966, 0x096F],
- [0x0981, 0x0983],
- [0x0985, 0x098C],
- [0x098F, 0x0990],
- [0x0993, 0x09A8],
- [0x09AA, 0x09B0],
- [0x09B2, 0x09B2],
- [0x09B6, 0x09B9],
- [0x09BE, 0x09C4],
- [0x09C7, 0x09C8],
- [0x09CB, 0x09CD],
- [0x09DC, 0x09DD],
- [0x09DF, 0x09E3],
- [0x09E6, 0x09F1],
- [0x0A02, 0x0A02],
- [0x0A05, 0x0A0A],
- [0x0A0F, 0x0A10],
- [0x0A13, 0x0A28],
- [0x0A2A, 0x0A30],
- [0x0A32, 0x0A33],
- [0x0A35, 0x0A36],
- [0x0A38, 0x0A39],
- [0x0A3E, 0x0A42],
- [0x0A47, 0x0A48],
- [0x0A4B, 0x0A4D],
- [0x0A59, 0x0A5C],
- [0x0A5E, 0x0A5E],
- [0x0A66, 0x0A6F],
- [0x0A74, 0x0A74],
- [0x0A81, 0x0A83],
- [0x0A85, 0x0A8B],
- [0x0A8D, 0x0A8D],
- [0x0A8F, 0x0A91],
- [0x0A93, 0x0AA8],
- [0x0AAA, 0x0AB0],
- [0x0AB2, 0x0AB3],
- [0x0AB5, 0x0AB9],
- [0x0ABD, 0x0AC5],
- [0x0AC7, 0x0AC9],
- [0x0ACB, 0x0ACD],
- [0x0AD0, 0x0AD0],
- [0x0AE0, 0x0AE0],
- [0x0AE6, 0x0AEF],
- [0x0B01, 0x0B03],
- [0x0B05, 0x0B0C],
- [0x0B0F, 0x0B10],
- [0x0B13, 0x0B28],
- [0x0B2A, 0x0B30],
- [0x0B32, 0x0B33],
- [0x0B36, 0x0B39],
- [0x0B3D, 0x0B43],
- [0x0B47, 0x0B48],
- [0x0B4B, 0x0B4D],
- [0x0B5C, 0x0B5D],
- [0x0B5F, 0x0B61],
- [0x0B66, 0x0B6F],
- [0x0B82, 0x0B83],
- [0x0B85, 0x0B8A],
- [0x0B8E, 0x0B90],
- [0x0B92, 0x0B95],
- [0x0B99, 0x0B9A],
- [0x0B9C, 0x0B9C],
- [0x0B9E, 0x0B9F],
- [0x0BA3, 0x0BA4],
- [0x0BA8, 0x0BAA],
- [0x0BAE, 0x0BB5],
- [0x0BB7, 0x0BB9],
- [0x0BBE, 0x0BC2],
- [0x0BC6, 0x0BC8],
- [0x0BCA, 0x0BCD],
- [0x0BE7, 0x0BEF],
- [0x0C01, 0x0C03],
- [0x0C05, 0x0C0C],
- [0x0C0E, 0x0C10],
- [0x0C12, 0x0C28],
- [0x0C2A, 0x0C33],
- [0x0C35, 0x0C39],
- [0x0C3E, 0x0C44],
- [0x0C46, 0x0C48],
- [0x0C4A, 0x0C4D],
- [0x0C60, 0x0C61],
- [0x0C66, 0x0C6F],
- [0x0C82, 0x0C83],
- [0x0C85, 0x0C8C],
- [0x0C8E, 0x0C90],
- [0x0C92, 0x0CA8],
- [0x0CAA, 0x0CB3],
- [0x0CB5, 0x0CB9],
- [0x0CBE, 0x0CC4],
- [0x0CC6, 0x0CC8],
- [0x0CCA, 0x0CCD],
- [0x0CDE, 0x0CDE],
- [0x0CE0, 0x0CE1],
- [0x0CE6, 0x0CEF],
- [0x0D02, 0x0D03],
- [0x0D05, 0x0D0C],
- [0x0D0E, 0x0D10],
- [0x0D12, 0x0D28],
- [0x0D2A, 0x0D39],
- [0x0D3E, 0x0D43],
- [0x0D46, 0x0D48],
- [0x0D4A, 0x0D4D],
- [0x0D60, 0x0D61],
- [0x0D66, 0x0D6F],
- [0x0E01, 0x0E3A],
- [0x0E40, 0x0E5B],
- [0x0E81, 0x0E82],
- [0x0E84, 0x0E84],
- [0x0E87, 0x0E88],
- [0x0E8A, 0x0E8A],
- [0x0E8D, 0x0E8D],
- [0x0E94, 0x0E97],
- [0x0E99, 0x0E9F],
- [0x0EA1, 0x0EA3],
- [0x0EA5, 0x0EA5],
- [0x0EA7, 0x0EA7],
- [0x0EAA, 0x0EAB],
- [0x0EAD, 0x0EAE],
- [0x0EB0, 0x0EB9],
- [0x0EBB, 0x0EBD],
- [0x0EC0, 0x0EC4],
- [0x0EC6, 0x0EC6],
- [0x0EC8, 0x0ECD],
- [0x0ED0, 0x0ED9],
- [0x0EDC, 0x0EDD],
- [0x0F00, 0x0F00],
- [0x0F18, 0x0F19],
- [0x0F20, 0x0F33],
- [0x0F35, 0x0F35],
- [0x0F37, 0x0F37],
- [0x0F39, 0x0F39],
- [0x0F3E, 0x0F47],
- [0x0F49, 0x0F69],
- [0x0F71, 0x0F84],
- [0x0F86, 0x0F8B],
- [0x0F90, 0x0F95],
- [0x0F97, 0x0F97],
- [0x0F99, 0x0FAD],
- [0x0FB1, 0x0FB7],
- [0x0FB9, 0x0FB9],
- [0x10A0, 0x10C5],
- [0x10D0, 0x10F6],
- [0x1E00, 0x1E9B],
- [0x1EA0, 0x1EF9],
- [0x1F00, 0x1F15],
- [0x1F18, 0x1F1D],
- [0x1F20, 0x1F45],
- [0x1F48, 0x1F4D],
- [0x1F50, 0x1F57],
- [0x1F59, 0x1F59],
- [0x1F5B, 0x1F5B],
- [0x1F5D, 0x1F5D],
- [0x1F5F, 0x1F7D],
- [0x1F80, 0x1FB4],
- [0x1FB6, 0x1FBC],
- [0x1FBE, 0x1FBE],
- [0x1FC2, 0x1FC4],
- [0x1FC6, 0x1FCC],
- [0x1FD0, 0x1FD3],
- [0x1FD6, 0x1FDB],
- [0x1FE0, 0x1FEC],
- [0x1FF2, 0x1FF4],
- [0x1FF6, 0x1FFC],
- [0x203F, 0x2040],
- [0x207F, 0x207F],
- [0x2102, 0x2102],
- [0x2107, 0x2107],
- [0x210A, 0x2113],
- [0x2115, 0x2115],
- [0x2118, 0x211D],
- [0x2124, 0x2124],
- [0x2126, 0x2126],
- [0x2128, 0x2128],
- [0x212A, 0x2131],
- [0x2133, 0x2138],
- [0x2160, 0x2182],
- [0x3005, 0x3007],
- [0x3021, 0x3029],
- [0x3041, 0x3093],
- [0x309B, 0x309C],
- [0x30A1, 0x30F6],
- [0x30FB, 0x30FC],
- [0x3105, 0x312C],
- [0x4E00, 0x9FA5],
- [0xAC00, 0xD7A3]
- ];
-
- size_t high = ALPHA_TABLE.length - 1;
- // Shortcut search if c is out of range
- size_t low = (c < ALPHA_TABLE[0][0] || ALPHA_TABLE[high][1] < c) ? high + 1 : 0;
- // Binary search
- while (low <= high)
- {
- const size_t mid = low + ((high - low) >> 1);
- if (c < ALPHA_TABLE[mid][0])
- high = mid - 1;
- else if (ALPHA_TABLE[mid][1] < c)
- low = mid + 1;
- else
- {
- assert(ALPHA_TABLE[mid][0] <= c && c <= ALPHA_TABLE[mid][1]);
- return true;
- }
- }
- return false;
-}
-
/**
* Returns the code length of c in code units.
*/
diff --git a/gcc/d/dmd/safe.d b/gcc/d/dmd/safe.d
index 1e5fb47..5064ac2 100644
--- a/gcc/d/dmd/safe.d
+++ b/gcc/d/dmd/safe.d
@@ -27,7 +27,7 @@ import dmd.mtype;
import dmd.target;
import dmd.tokens;
import dmd.typesem : hasPointers, arrayOf;
-import dmd.func : setUnsafe, setUnsafePreview;
+import dmd.funcsem : setUnsafe, setUnsafePreview;
/*************************************************************
* Check for unsafe access in @safe code:
@@ -75,6 +75,7 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg)
if (ad.sizeok != Sizeok.done)
ad.determineSize(ad.loc);
+ import dmd.globals : FeatureState;
const hasPointers = v.type.hasPointers();
if (hasPointers)
{
@@ -87,7 +88,6 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg)
}
else
{
- import dmd.globals : FeatureState;
// @@@DEPRECATED_2.116@@@
// https://issues.dlang.org/show_bug.cgi?id=20655
// Inferring `@system` because of union access breaks code,
@@ -111,6 +111,17 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg)
}
}
+ // @@@DEPRECATED_2.119@@@
+ // https://issues.dlang.org/show_bug.cgi?id=24477
+ // Should probably be turned into an error in a new edition
+ if (v.type.hasUnsafeBitpatterns() && v.overlapped && sc.setUnsafePreview(
+ FeatureState.default_, !printmsg, e.loc,
+ "cannot access overlapped field `%s.%s` with unsafe bit patterns in `@safe` code", ad, v)
+ )
+ {
+ return true;
+ }
+
if (readonly || !e.type.isMutable())
return false;
diff --git a/gcc/d/dmd/semantic2.d b/gcc/d/dmd/semantic2.d
index f5ce0c0..4bb3902 100644
--- a/gcc/d/dmd/semantic2.d
+++ b/gcc/d/dmd/semantic2.d
@@ -40,6 +40,7 @@ import dmd.escape;
import dmd.expression;
import dmd.expressionsem;
import dmd.func;
+import dmd.funcsem;
import dmd.globals;
import dmd.id;
import dmd.identifier;
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index 882d1a9..d88face 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -424,9 +424,12 @@ private extern(C++) final class Semantic3Visitor : Visitor
.error(funcdecl.loc, "%s `%s` `object.TypeInfo_Tuple` could not be found, but is implicitly used in D-style variadic functions", funcdecl.kind, funcdecl.toPrettyChars);
else
.error(funcdecl.loc, "%s `%s` `object.TypeInfo` could not be found, but is implicitly used in D-style variadic functions", funcdecl.kind, funcdecl.toPrettyChars);
- fatal();
+ funcdecl.errors = true;
}
+ }
+ if (!funcdecl.errors && f.linkage == LINK.d)
+ {
// Declare _arguments[]
funcdecl.v_arguments = new VarDeclaration(funcdecl.loc, Type.typeinfotypelist.type, Id._arguments_typeinfo, null);
funcdecl.v_arguments.storage_class |= STC.temp | STC.parameter;
@@ -442,7 +445,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
sc2.insert(_arguments);
_arguments.parent = funcdecl;
}
- if (f.linkage == LINK.d || f.parameterList.length)
+ if (!funcdecl.errors && (f.linkage == LINK.d || f.parameterList.length))
{
// Declare _argptr
Type t = target.va_listType(funcdecl.loc, sc);
@@ -906,26 +909,26 @@ private extern(C++) final class Semantic3Visitor : Visitor
}
}
- const hasCopyCtor = exp.type.ty == Tstruct && (cast(TypeStruct)exp.type).sym.hasCopyCtor;
- // if a copy constructor is present, the return type conversion will be handled by it
- if (!(hasCopyCtor && exp.isLvalue()))
+ // Function returns a reference
+ if (f.isref)
{
- if (f.isref && !MODimplicitConv(exp.type.mod, tret.mod) && !tret.isTypeSArray())
+ if (!MODimplicitConv(exp.type.mod, tret.mod) && !tret.isTypeSArray())
error(exp.loc, "expression `%s` of type `%s` is not implicitly convertible to return type `ref %s`",
exp.toChars(), exp.type.toChars(), tret.toChars());
else
exp = exp.implicitCastTo(sc2, tret);
- }
- if (f.isref)
- {
- // Function returns a reference
exp = exp.toLvalue(sc2, "`ref` return");
- checkReturnEscapeRef(sc2, exp, false);
+ checkReturnEscapeRef(*sc2, exp, false);
exp = exp.optimize(WANTvalue, /*keepLvalue*/ true);
}
else
{
+ // if a copy constructor is present, the return type conversion will be handled by it
+ const hasCopyCtor = exp.type.ty == Tstruct && (cast(TypeStruct)exp.type).sym.hasCopyCtor;
+ if (!hasCopyCtor || !exp.isLvalue())
+ exp = exp.implicitCastTo(sc2, tret);
+
exp = exp.optimize(WANTvalue);
/* https://issues.dlang.org/show_bug.cgi?id=10789
@@ -935,7 +938,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
exp = doCopyOrMove(sc2, exp, f.next);
if (tret.hasPointers())
- checkReturnEscape(sc2, exp, false);
+ checkReturnEscape(*sc2, exp, false);
}
exp = checkGC(sc2, exp);
diff --git a/gcc/d/dmd/statement.h b/gcc/d/dmd/statement.h
index ea80e51..9437238 100644
--- a/gcc/d/dmd/statement.h
+++ b/gcc/d/dmd/statement.h
@@ -119,40 +119,40 @@ public:
bool hasCode();
virtual Statement *last();
- virtual ReturnStatement *endsWithReturnStatement() { return NULL; }
-
- ErrorStatement *isErrorStatement() { return stmt == STMTerror ? (ErrorStatement*)this : NULL; }
- ScopeStatement *isScopeStatement() { return stmt == STMTscope ? (ScopeStatement*)this : NULL; }
- ExpStatement *isExpStatement() { return stmt == STMTexp ? (ExpStatement*)this : NULL; }
- 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; }
- GotoDefaultStatement *isGotoDefaultStatement() { return stmt == STMTgotoDefault ? (GotoDefaultStatement*)this : NULL; }
- GotoCaseStatement *isGotoCaseStatement() { return stmt == STMTgotoCase ? (GotoCaseStatement*)this : NULL; }
- BreakStatement *isBreakStatement() { return stmt == STMTbreak ? (BreakStatement*)this : NULL; }
- DtorExpStatement *isDtorExpStatement() { return stmt == STMTdtorExp ? (DtorExpStatement*)this : NULL; }
- MixinStatement *isMixinStatement() { return stmt == STMTmixin ? (MixinStatement*)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; }
- ForeachStatement *isForeachStatement() { return stmt == STMTforeach ? (ForeachStatement*)this : NULL; }
- SwitchStatement *isSwitchStatement() { return stmt == STMTswitch ? (SwitchStatement*)this : NULL; }
- ContinueStatement *isContinueStatement() { return stmt == STMTcontinue ? (ContinueStatement*)this : NULL; }
- 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; }
- CompoundDeclarationStatement *isCompoundDeclarationStatement() { return stmt == STMTcompoundDeclaration ? (CompoundDeclarationStatement*)this : NULL; }
+ virtual ReturnStatement *endsWithReturnStatement() { return nullptr; }
+
+ ErrorStatement *isErrorStatement() { return stmt == STMTerror ? (ErrorStatement*)this : nullptr; }
+ ScopeStatement *isScopeStatement() { return stmt == STMTscope ? (ScopeStatement*)this : nullptr; }
+ ExpStatement *isExpStatement() { return stmt == STMTexp ? (ExpStatement*)this : nullptr; }
+ CompoundStatement *isCompoundStatement() { return stmt == STMTcompound ? (CompoundStatement*)this : nullptr; }
+ ReturnStatement *isReturnStatement() { return stmt == STMTreturn ? (ReturnStatement*)this : nullptr; }
+ IfStatement *isIfStatement() { return stmt == STMTif ? (IfStatement*)this : nullptr; }
+ ConditionalStatement *isConditionalStatement() { return stmt == STMTconditional ? (ConditionalStatement*)this : nullptr; }
+ StaticForeachStatement *isStaticForeachStatement() { return stmt == STMTstaticForeach ? (StaticForeachStatement*)this : nullptr; }
+ CaseStatement *isCaseStatement() { return stmt == STMTcase ? (CaseStatement*)this : nullptr; }
+ DefaultStatement *isDefaultStatement() { return stmt == STMTdefault ? (DefaultStatement*)this : nullptr; }
+ LabelStatement *isLabelStatement() { return stmt == STMTlabel ? (LabelStatement*)this : nullptr; }
+ GotoDefaultStatement *isGotoDefaultStatement() { return stmt == STMTgotoDefault ? (GotoDefaultStatement*)this : nullptr; }
+ GotoCaseStatement *isGotoCaseStatement() { return stmt == STMTgotoCase ? (GotoCaseStatement*)this : nullptr; }
+ BreakStatement *isBreakStatement() { return stmt == STMTbreak ? (BreakStatement*)this : nullptr; }
+ DtorExpStatement *isDtorExpStatement() { return stmt == STMTdtorExp ? (DtorExpStatement*)this : nullptr; }
+ MixinStatement *isMixinStatement() { return stmt == STMTmixin ? (MixinStatement*)this : nullptr; }
+ ForwardingStatement *isForwardingStatement() { return stmt == STMTforwarding ? (ForwardingStatement*)this : nullptr; }
+ DoStatement *isDoStatement() { return stmt == STMTdo ? (DoStatement*)this : nullptr; }
+ ForStatement *isForStatement() { return stmt == STMTfor ? (ForStatement*)this : nullptr; }
+ ForeachStatement *isForeachStatement() { return stmt == STMTforeach ? (ForeachStatement*)this : nullptr; }
+ SwitchStatement *isSwitchStatement() { return stmt == STMTswitch ? (SwitchStatement*)this : nullptr; }
+ ContinueStatement *isContinueStatement() { return stmt == STMTcontinue ? (ContinueStatement*)this : nullptr; }
+ WithStatement *isWithStatement() { return stmt == STMTwith ? (WithStatement*)this : nullptr; }
+ TryCatchStatement *isTryCatchStatement() { return stmt == STMTtryCatch ? (TryCatchStatement*)this : nullptr; }
+ ThrowStatement *isThrowStatement() { return stmt == STMTthrow ? (ThrowStatement*)this : nullptr; }
+ DebugStatement *isDebugStatement() { return stmt == STMTdebug ? (DebugStatement*)this : nullptr; }
+ TryFinallyStatement *isTryFinallyStatement() { return stmt == STMTtryFinally ? (TryFinallyStatement*)this : nullptr; }
+ ScopeGuardStatement *isScopeGuardStatement() { return stmt == STMTscopeGuard ? (ScopeGuardStatement*)this : nullptr; }
+ SwitchErrorStatement *isSwitchErrorStatement() { return stmt == STMTswitchError ? (SwitchErrorStatement*)this : nullptr; }
+ UnrolledLoopStatement *isUnrolledLoopStatement() { return stmt == STMTunrolledLoop ? (UnrolledLoopStatement*)this : nullptr; }
+ ForeachRangeStatement *isForeachRangeStatement() { return stmt == STMTforeachRange ? (ForeachRangeStatement*)this : nullptr; }
+ CompoundDeclarationStatement *isCompoundDeclarationStatement() { return stmt == STMTcompoundDeclaration ? (CompoundDeclarationStatement*)this : nullptr; }
void accept(Visitor *v) override { v->visit(this); }
};
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index 1bf36e3..ae68d6a 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -989,7 +989,18 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
(tn.ty != tv.ty && tn.ty.isSomeChar && tv.ty.isSomeChar)) &&
!Type.tsize_t.implicitConvTo(tindex))
{
- deprecation(fs.loc, "foreach: loop index implicitly converted from `size_t` to `%s`",
+ bool err = true;
+ if (tab.isTypeDArray())
+ {
+ // check if overflow is possible
+ const maxLen = IntRange.fromType(tindex).imax.value + 1;
+ if (auto ale = fs.aggr.isArrayLiteralExp())
+ err = ale.elements.length > maxLen;
+ else if (auto se = fs.aggr.isSliceExp())
+ err = !(se.upr && se.upr.isConst() && se.upr.toInteger() <= maxLen);
+ }
+ if (err)
+ deprecation(fs.loc, "foreach: loop index implicitly converted from `size_t` to `%s`",
tindex.toChars());
}
}
@@ -1398,7 +1409,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
}
case Tdelegate:
if (fs.op == TOK.foreach_reverse_)
- deprecation(fs.loc, "cannot use `foreach_reverse` with a delegate");
+ error(fs.loc, "cannot use `foreach_reverse` with a delegate");
return retStmt(apply());
case Terror:
return retError();
@@ -2652,11 +2663,11 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
*/
Scope* sc2 = sc.push();
sc2.eSink = global.errorSinkNull;
- bool err = checkReturnEscapeRef(sc2, rs.exp, true);
+ bool err = checkReturnEscapeRef(*sc2, rs.exp, true);
sc2.pop();
if (err)
- turnOffRef(() { checkReturnEscapeRef(sc, rs.exp, false); });
+ turnOffRef(() { checkReturnEscapeRef(*sc, rs.exp, false); });
else if (!rs.exp.type.constConv(tf.next))
turnOffRef(
() => rs.loc.errorSupplemental("cannot implicitly convert `%s` of type `%s` to `%s`",
@@ -3018,8 +3029,8 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
*/
if (!ClassDeclaration.object)
{
- error(ss.loc, "missing or corrupt object.d");
- fatal();
+ ObjectNotFound(ss.loc, Id.Object);
+ return setError();
}
Type t = ClassDeclaration.object.type;
@@ -3690,7 +3701,7 @@ public bool throwSemantic(const ref Loc loc, ref Expression exp, Scope* sc)
exp.loc.deprecation("cannot throw object of qualified type `%s`", exp.type.toChars());
//return false;
}
- checkThrowEscape(sc, exp, false);
+ checkThrowEscape(*sc, exp, false);
ClassDeclaration cd = exp.type.toBasetype().isClassHandle();
if (!cd || ((cd != ClassDeclaration.throwable) && !ClassDeclaration.throwable.isBaseOf(cd, null)))
diff --git a/gcc/d/dmd/target.d b/gcc/d/dmd/target.d
index cff1d2e..87826b5 100644
--- a/gcc/d/dmd/target.d
+++ b/gcc/d/dmd/target.d
@@ -25,7 +25,8 @@
module dmd.target;
-import dmd.globals : Param, CHECKENABLE;
+import dmd.astenums : CHECKENABLE;
+import dmd.globals : Param;
enum CPU : ubyte
{
diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h
index 1209505..6237cf14 100644
--- a/gcc/d/dmd/target.h
+++ b/gcc/d/dmd/target.h
@@ -198,7 +198,7 @@ public:
unsigned fieldalign(Type *type);
Type *va_listType(const Loc &loc, Scope *sc); // get type of va_list
int isVectorTypeSupported(int sz, Type *type);
- bool isVectorOpSupported(Type *type, EXP op, Type *t2 = NULL);
+ bool isVectorOpSupported(Type *type, EXP op, Type *t2 = nullptr);
// ABI and backend.
LINK systemLinkage();
TypeTuple *toArgTypes(Type *t);
diff --git a/gcc/d/dmd/tokens.h b/gcc/d/dmd/tokens.h
index ef91001..929897a 100644
--- a/gcc/d/dmd/tokens.h
+++ b/gcc/d/dmd/tokens.h
@@ -476,7 +476,7 @@ struct Token
Identifier *ident;
};
- Token() : next(NULL) {}
+ Token() : next(nullptr) {}
const char *toChars() const;
static const char *toChars(TOK value);
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index be7aa99..81d42e6 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -20,6 +20,7 @@ import dmd.arraytypes;
import dmd.astcodegen;
import dmd.astenums;
import dmd.attrib;
+import dmd.attribsem;
import dmd.canthrow;
import dmd.dclass;
import dmd.declaration;
@@ -1245,7 +1246,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
// @@@DEPRECATION 2.100.2
if (auto td = s.isTemplateDeclaration())
{
- if (td.overnext || td.overroot)
+ if (td.overnext)
{
deprecation(e.loc, "`__traits(getAttributes)` may only be used for individual functions, not the overload set `%s`", td.ident.toChars());
deprecationSupplemental(e.loc, "the result of `__traits(getOverloads)` may be used to select the desired function to extract attributes from");
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index b2b9e38..195fdc7 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -1686,7 +1686,7 @@ Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
if (!ClassDeclaration.object)
{
- .error(Loc.initial, "missing or corrupt object.d");
+ ObjectNotFound(Loc.initial, cd.ident);
return error();
}
diff --git a/gcc/d/dmd/utils.d b/gcc/d/dmd/utils.d
index 72d8036..9228ba6 100644
--- a/gcc/d/dmd/utils.d
+++ b/gcc/d/dmd/utils.d
@@ -52,16 +52,18 @@ const(char)* toWinPath(const(char)* src)
* Params:
* loc = The line number information from where the call originates
* filename = Path to file
+ * buf = append contents of file to
+ * Returns:
+ * true on failure
*/
-Buffer readFile(Loc loc, const(char)[] filename)
+bool readFile(Loc loc, const(char)[] filename, ref OutBuffer buf)
{
- auto result = File.read(filename);
- if (!result.success)
+ if (File.read(filename, buf))
{
error(loc, "error reading file `%.*s`", cast(int)filename.length, filename.ptr);
- fatal();
+ return true;
}
- return Buffer(result.extractSlice());
+ return false;
}