aboutsummaryrefslogtreecommitdiff
path: root/gcc/d
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2022-03-21 16:52:40 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2022-03-21 19:51:50 +0100
commitfbdaa58162ee4189f441b75170af89215465d189 (patch)
tree77c5816b721cad2691bea1d228cb5ecc31568f9c /gcc/d
parent4a3073f04e8b7987ad7bfe1bc23bfeb1d627ee6a (diff)
downloadgcc-fbdaa58162ee4189f441b75170af89215465d189.zip
gcc-fbdaa58162ee4189f441b75170af89215465d189.tar.gz
gcc-fbdaa58162ee4189f441b75170af89215465d189.tar.bz2
d: Merge upstream dmd 2503f17e5, phobos a74fa63e6.
D front-end changes: - Import dmd mainline development. - Removed internal d_intN and d_unsN aliases to stdint types, which caused a regression on Solaris where int8_t is a char (PR104911). Phobos changes: - Import phobos mainline development. PR d/104911 gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 2503f17e5. * d-convert.cc (convert_expr): Replace d_uns64 with dinteger_t. * d-lang.cc: Remove dmd/root/file.h include. (d_handle_option): Update for new front-end interface. (d_parse_file): Likewise. libphobos/ChangeLog: * src/MERGE: Merge upstream phobos a74fa63e6.
Diffstat (limited to 'gcc/d')
-rw-r--r--gcc/d/d-convert.cc4
-rw-r--r--gcc/d/d-lang.cc20
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/aggregate.d2
-rw-r--r--gcc/d/dmd/aggregate.h2
-rw-r--r--gcc/d/dmd/astenums.d9
-rw-r--r--gcc/d/dmd/attrib.d8
-rw-r--r--gcc/d/dmd/blockexit.d2
-rw-r--r--gcc/d/dmd/canthrow.d2
-rw-r--r--gcc/d/dmd/constfold.d50
-rw-r--r--gcc/d/dmd/cparse.d175
-rw-r--r--gcc/d/dmd/cppmangle.d2
-rw-r--r--gcc/d/dmd/ctfeexpr.d65
-rw-r--r--gcc/d/dmd/dcast.d8
-rw-r--r--gcc/d/dmd/declaration.d8
-rw-r--r--gcc/d/dmd/declaration.h3
-rw-r--r--gcc/d/dmd/dinterpret.d84
-rw-r--r--gcc/d/dmd/dmacro.d29
-rw-r--r--gcc/d/dmd/dmodule.d78
-rw-r--r--gcc/d/dmd/doc.d4
-rw-r--r--gcc/d/dmd/dscope.d2
-rw-r--r--gcc/d/dmd/dsymbol.d7
-rw-r--r--gcc/d/dmd/dsymbol.h2
-rw-r--r--gcc/d/dmd/dsymbolsem.d134
-rw-r--r--gcc/d/dmd/dtemplate.d4
-rw-r--r--gcc/d/dmd/dtoh.d25
-rw-r--r--gcc/d/dmd/escape.d120
-rw-r--r--gcc/d/dmd/expression.d22
-rw-r--r--gcc/d/dmd/expressionsem.d18
-rw-r--r--gcc/d/dmd/file_manager.d133
-rw-r--r--gcc/d/dmd/file_manager.h19
-rw-r--r--gcc/d/dmd/globals.d19
-rw-r--r--gcc/d/dmd/globals.h19
-rw-r--r--gcc/d/dmd/hdrgen.d1
-rw-r--r--gcc/d/dmd/id.d3
-rw-r--r--gcc/d/dmd/importc.d22
-rw-r--r--gcc/d/dmd/lexer.d14
-rw-r--r--gcc/d/dmd/module.h6
-rw-r--r--gcc/d/dmd/mtype.d52
-rw-r--r--gcc/d/dmd/mtype.h40
-rw-r--r--gcc/d/dmd/optimize.d8
-rw-r--r--gcc/d/dmd/parse.d6
-rw-r--r--gcc/d/dmd/root/file.h41
-rw-r--r--gcc/d/dmd/root/filename.d7
-rw-r--r--gcc/d/dmd/root/string.d6
-rw-r--r--gcc/d/dmd/semantic2.d11
-rw-r--r--gcc/d/dmd/semantic3.d16
-rw-r--r--gcc/d/dmd/statementsem.d33
-rw-r--r--gcc/d/dmd/target.d37
-rw-r--r--gcc/d/dmd/target.h14
-rw-r--r--gcc/d/dmd/template.h1
-rw-r--r--gcc/d/dmd/tokens.d6
-rw-r--r--gcc/d/dmd/traits.d48
-rw-r--r--gcc/d/dmd/typesem.d25
54 files changed, 803 insertions, 675 deletions
diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc
index 5a7a64f..3a6a32a 100644
--- a/gcc/d/d-convert.cc
+++ b/gcc/d/d-convert.cc
@@ -518,8 +518,8 @@ convert_expr (tree exp, Type *etype, Type *totype)
else if (tbtype->ty == TY::Tarray)
{
/* Assume tvoid->size() == 1. */
- d_uns64 fsize = ebtype->nextOf ()->toBasetype ()->size ();
- d_uns64 tsize = tbtype->nextOf ()->toBasetype ()->size ();
+ dinteger_t fsize = ebtype->nextOf ()->toBasetype ()->size ();
+ dinteger_t tsize = tbtype->nextOf ()->toBasetype ()->size ();
if (fsize != tsize)
{
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index f887840..4a7aa89 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -32,7 +32,6 @@ along with GCC; see the file COPYING3. If not see
#include "dmd/mangle.h"
#include "dmd/module.h"
#include "dmd/mtype.h"
-#include "dmd/root/file.h"
#include "dmd/target.h"
#include "opts.h"
@@ -579,7 +578,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
global.params.fix16997 = value;
global.params.markdown = value;
global.params.noSharedAccess = value;
- global.params.rvalueRefParam = value;
+ global.params.rvalueRefParam = FeatureState::enabled;
global.params.inclusiveInContracts = value;
global.params.shortenedMethods = value;
break;
@@ -625,7 +624,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
break;
case OPT_fpreview_rvaluerefparam:
- global.params.rvalueRefParam = value;
+ global.params.rvalueRefParam = FeatureState::enabled;
break;
case OPT_fpreview_shortenedmethods:
@@ -1069,9 +1068,8 @@ d_parse_file (void)
/* Overwrite the source file for the module, the one created by
Module::create would have a forced a `.d' suffix. */
- m->srcBuffer = FileBuffer::create ();
- m->srcBuffer->data.length = len;
- m->srcBuffer->data.ptr = buffer;
+ m->src.length = len;
+ m->src.ptr = buffer;
}
else
{
@@ -1108,7 +1106,7 @@ d_parse_file (void)
m->importedFrom = m;
m->parse ();
- if (m->isDocFile)
+ if (m->filetype == FileType::ddoc)
{
gendocfile (m);
/* Remove M from list of modules. */
@@ -1146,7 +1144,8 @@ d_parse_file (void)
for (size_t i = 0; i < modules.length; i++)
{
Module *m = modules[i];
- if (m->isHdrFile || (d_option.fonly && m != Module::rootModule))
+ if (m->filetype == FileType::dhdr
+ || (d_option.fonly && m != Module::rootModule))
continue;
if (global.params.verbose)
@@ -1374,7 +1373,7 @@ d_parse_file (void)
/* Skip generating code for header files, or when the module wasn't
specified by `-fonly=`. */
- if ((m->isHdrFile && m != main_module)
+ if ((m->filetype == FileType::dhdr && m != main_module)
|| (d_option.fonly && m != Module::rootModule))
continue;
@@ -1421,7 +1420,8 @@ d_parse_file (void)
for (size_t i = 0; i < modules.length; i++)
{
Module *m = modules[i];
- if (m->isHdrFile || (d_option.fonly && m != Module::rootModule))
+ if (m->filetype == FileType::dhdr
+ || (d_option.fonly && m != Module::rootModule))
continue;
remove (m->hdrfile.toChars ());
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 2200889..3e3e113 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-cbba5f41a32cfed7f22a213d537f8e2dee0b92f7
+2503f17e5767bc4fcd0cf3889c90fa0415b0edaa
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/aggregate.d b/gcc/d/dmd/aggregate.d
index 1add36a..f790730 100644
--- a/gcc/d/dmd/aggregate.d
+++ b/gcc/d/dmd/aggregate.d
@@ -234,7 +234,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
abstract void finalizeSize();
- override final d_uns64 size(const ref Loc loc)
+ override final uinteger_t size(const ref Loc loc)
{
//printf("+AggregateDeclaration::size() %s, scope = %p, sizeok = %d\n", toChars(), _scope, sizeok);
bool ok = determineSize(loc);
diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h
index 796144a..bdeb38e 100644
--- a/gcc/d/dmd/aggregate.h
+++ b/gcc/d/dmd/aggregate.h
@@ -124,7 +124,7 @@ public:
size_t nonHiddenFields();
bool determineSize(const Loc &loc);
virtual void finalizeSize() = 0;
- d_uns64 size(const Loc &loc);
+ uinteger_t size(const Loc &loc);
bool fill(const Loc &loc, Expressions *elements, bool ctorinit);
Type *getType();
bool isDeprecated() const; // is aggregate deprecated?
diff --git a/gcc/d/dmd/astenums.d b/gcc/d/dmd/astenums.d
index ea10c4e..1a2cf8b 100644
--- a/gcc/d/dmd/astenums.d
+++ b/gcc/d/dmd/astenums.d
@@ -430,3 +430,12 @@ enum PINLINE : ubyte
never, /// never inline
always, /// always inline
}
+
+/// Source file type
+enum FileType : ubyte
+{
+ d, /// normal D source file
+ dhdr, /// D header file (.di)
+ ddoc, /// Ddoc documentation file (.dd)
+ c, /// C source file
+}
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index cf9e9ce..9c2bbd6 100644
--- a/gcc/d/dmd/attrib.d
+++ b/gcc/d/dmd/attrib.d
@@ -247,12 +247,12 @@ extern (C++) class StorageClassDeclaration : AttribDeclaration
*/
if (stc & (STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.manifest))
scstc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.manifest);
- if (stc & (STC.auto_ | STC.scope_ | STC.static_ | STC.tls | STC.manifest | STC.gshared))
- scstc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.tls | STC.manifest | STC.gshared);
+ if (stc & (STC.auto_ | STC.scope_ | STC.static_ | STC.manifest | STC.gshared))
+ scstc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.manifest | STC.gshared);
if (stc & (STC.const_ | STC.immutable_ | STC.manifest))
scstc &= ~(STC.const_ | STC.immutable_ | STC.manifest);
- if (stc & (STC.gshared | STC.shared_ | STC.tls))
- scstc &= ~(STC.gshared | STC.shared_ | STC.tls);
+ if (stc & (STC.gshared | STC.shared_))
+ scstc &= ~(STC.gshared | STC.shared_);
if (stc & (STC.safe | STC.trusted | STC.system))
scstc &= ~(STC.safe | STC.trusted | STC.system);
scstc |= stc;
diff --git a/gcc/d/dmd/blockexit.d b/gcc/d/dmd/blockexit.d
index 5132a2d..5c01204 100644
--- a/gcc/d/dmd/blockexit.d
+++ b/gcc/d/dmd/blockexit.d
@@ -146,7 +146,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
else if (sd && (!sd.statement.hasCode() || sd.statement.isCaseStatement() || sd.statement.isErrorStatement()))
{
}
- else if (!func.getModule().isCFile)
+ else if (func.getModule().filetype != FileType.c)
{
const(char)* gototype = s.isCaseStatement() ? "case" : "default";
s.error("switch case fallthrough - use 'goto %s;' if intended", gototype);
diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d
index 745e552..a38cbb1 100644
--- a/gcc/d/dmd/canthrow.d
+++ b/gcc/d/dmd/canthrow.d
@@ -246,7 +246,7 @@ private CT Dsymbol_canThrow(Dsymbol s, FuncDeclaration func, bool mustNotThrow)
if (vd.storage_class & STC.manifest)
{
}
- else if (vd.isStatic() || vd.storage_class & (STC.extern_ | STC.tls | STC.gshared))
+ else if (vd.isStatic() || vd.storage_class & (STC.extern_ | STC.gshared))
{
}
else
diff --git a/gcc/d/dmd/constfold.d b/gcc/d/dmd/constfold.d
index 96ca520..9941c16 100644
--- a/gcc/d/dmd/constfold.d
+++ b/gcc/d/dmd/constfold.d
@@ -619,31 +619,31 @@ UnionExp Shr(const ref Loc loc, Type type, Expression e1, Expression e2)
switch (e1.type.toBasetype().ty)
{
case Tint8:
- value = cast(d_int8)value >> count;
+ value = cast(byte)value >> count;
break;
case Tuns8:
case Tchar:
- value = cast(d_uns8)value >> count;
+ value = cast(ubyte)value >> count;
break;
case Tint16:
- value = cast(d_int16)value >> count;
+ value = cast(short)value >> count;
break;
case Tuns16:
case Twchar:
- value = cast(d_uns16)value >> count;
+ value = cast(ushort)value >> count;
break;
case Tint32:
- value = cast(d_int32)value >> count;
+ value = cast(int)value >> count;
break;
case Tuns32:
case Tdchar:
- value = cast(d_uns32)value >> count;
+ value = cast(uint)value >> count;
break;
case Tint64:
- value = cast(d_int64)value >> count;
+ value = cast(long)value >> count;
break;
case Tuns64:
- value = cast(d_uns64)value >> count;
+ value = cast(ulong)value >> count;
break;
case Terror:
emplaceExp!(ErrorExp)(&ue);
@@ -1106,31 +1106,31 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
switch (typeb.ty)
{
case Tint8:
- result = cast(d_int8)cast(sinteger_t)r;
+ result = cast(byte)cast(sinteger_t)r;
break;
case Tchar:
case Tuns8:
- result = cast(d_uns8)cast(dinteger_t)r;
+ result = cast(ubyte)cast(dinteger_t)r;
break;
case Tint16:
- result = cast(d_int16)cast(sinteger_t)r;
+ result = cast(short)cast(sinteger_t)r;
break;
case Twchar:
case Tuns16:
- result = cast(d_uns16)cast(dinteger_t)r;
+ result = cast(ushort)cast(dinteger_t)r;
break;
case Tint32:
- result = cast(d_int32)r;
+ result = cast(int)r;
break;
case Tdchar:
case Tuns32:
- result = cast(d_uns32)r;
+ result = cast(uint)r;
break;
case Tint64:
- result = cast(d_int64)r;
+ result = cast(long)r;
break;
case Tuns64:
- result = cast(d_uns64)r;
+ result = cast(ulong)r;
break;
default:
assert(0);
@@ -1348,14 +1348,6 @@ UnionExp Slice(Type type, Expression e1, Expression lwr, Expression upr)
}
}
- static bool sliceBoundsCheck(uinteger_t lwr, uinteger_t upr, uinteger_t newlwr, uinteger_t newupr) pure
- {
- assert(lwr <= upr);
- return !(newlwr <= newupr &&
- lwr <= newlwr &&
- newupr <= upr);
- }
-
if (e1.op == EXP.string_ && lwr.op == EXP.int64 && upr.op == EXP.int64)
{
StringExp es1 = cast(StringExp)e1;
@@ -1395,6 +1387,16 @@ UnionExp Slice(Type type, Expression e1, Expression lwr, Expression upr)
return ue;
}
+/* Check whether slice `[newlwr .. newupr]` is in the range `[lwr .. upr]`
+ */
+bool sliceBoundsCheck(uinteger_t lwr, uinteger_t upr, uinteger_t newlwr, uinteger_t newupr) pure
+{
+ assert(lwr <= upr);
+ return !(newlwr <= newupr &&
+ lwr <= newlwr &&
+ newupr <= upr);
+}
+
/* Set a slice of char/integer array literal 'existingAE' from a string 'newval'.
* existingAE[firstIndex..firstIndex+newval.length] = newval.
*/
diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index 2edab14..fb52b63 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/dmd/cparse.d
@@ -48,14 +48,16 @@ final class CParser(AST) : Parser!AST
Array!structalign_t* packs; // parallel alignment values
}
- /** C allows declaring a function with a typedef:
- * typedef int (myfunc)(); myfunc fun;
- * but we need to distinguish `fun` being a function as opposed to a variable in the
- * parse pass. This is accomplished by having a simple symbol table of typedefs
- * where we know, by syntax, if they are function types or non-function types.
- * funcTypeIds is the symbol table, of the identifiers of typedefs of function types.
+ /* C cannot be parsed without determining if an identifier is a type or a variable.
+ * For expressions like `(T)-3`, is it a cast or a minus expression?
+ * It also occurs with `typedef int (F)(); F fun;`
+ * but to build the AST we need to distinguish `fun` being a function as opposed to a variable.
+ * To fix, build a symbol table for the typedefs.
+ * Symbol table of typedefs indexed by Identifier cast to void*.
+ * 1. if an identifier is a typedef, then it will return a non-null Type
+ * 2. if an identifier is not a typedef, then it will return null
*/
- AST.Identifiers funcTypeIds; /// Identifiers in this are typedefs of function types
+ Array!(void*) typedefTab; /// Array of AST.Type[Identifier], typedef's indexed by Identifier
extern (D) this(TARGET)(AST.Module _module, const(char)[] input, bool doDocComment,
const ref TARGET target)
@@ -97,6 +99,7 @@ final class CParser(AST) : Parser!AST
{
//printf("cparseTranslationUnit()\n");
symbols = new AST.Dsymbols();
+ typedefTab.push(null); // C11 6.2.1-3 symbol table for "file scope"
while (1)
{
if (token.value == TOK.endOfFile)
@@ -115,6 +118,10 @@ final class CParser(AST) : Parser!AST
wrap.push(s);
}
+ // end of file scope
+ typedefTab.pop();
+ assert(typedefTab.length == 0);
+
return wrap;
}
@@ -150,10 +157,17 @@ final class CParser(AST) : Parser!AST
//printf("cparseStatement()\n");
- const funcTypeIdsLengthSave = funcTypeIds.length;
+ const typedefTabLengthSave = typedefTab.length;
auto symbolsSave = symbols;
+ if (flags & ParseStatementFlags.scope_)
+ {
+ typedefTab.push(null); // introduce new block scope
+ }
+
if (!(flags & (ParseStatementFlags.scope_ | ParseStatementFlags.curlyScope)))
+ {
symbols = new AST.Dsymbols();
+ }
switch (token.value)
{
@@ -593,7 +607,7 @@ final class CParser(AST) : Parser!AST
if (pEndloc)
*pEndloc = prevloc;
symbols = symbolsSave;
- funcTypeIds.setDim(funcTypeIdsLengthSave);
+ typedefTab.setDim(typedefTabLengthSave);
return s;
}
@@ -1002,8 +1016,18 @@ final class CParser(AST) : Parser!AST
{
if (token.value == TOK.leftParenthesis)
{
+ auto tk = peek(&token);
+ if (tk.value == TOK.identifier &&
+ !isTypedef(tk.ident) &&
+ peek(tk).value == TOK.rightParenthesis)
+ {
+ // ( identifier ) is an expression
+ return cparseUnaryExp();
+ }
+
// If ( type-name )
auto pt = &token;
+
if (isCastExpression(pt))
{
// Expression may be either a cast or a compound literal, which
@@ -1573,7 +1597,7 @@ final class CParser(AST) : Parser!AST
return;
}
- const funcTypeIdsLengthSave = funcTypeIds.length;
+ const typedefTabLengthSave = typedefTab.length;
auto symbolsSave = symbols;
Specifier specifier;
specifier.packalign = this.packalign;
@@ -1683,13 +1707,13 @@ final class CParser(AST) : Parser!AST
t.value == TOK.leftCurly) // start of compound-statement
{
auto s = cparseFunctionDefinition(id, dt.isTypeFunction(), specifier);
- funcTypeIds.setDim(funcTypeIdsLengthSave);
+ typedefTab.setDim(typedefTabLengthSave);
symbols = symbolsSave;
symbols.push(s);
return;
}
AST.Dsymbol s = null;
- funcTypeIds.setDim(funcTypeIdsLengthSave);
+ typedefTab.setDim(typedefTabLengthSave);
symbols = symbolsSave;
if (!symbols)
symbols = new AST.Dsymbols; // lazilly create it
@@ -1747,12 +1771,9 @@ final class CParser(AST) : Parser!AST
}
}
}
- else if (isFunctionTypedef(dt))
- {
- funcTypeIds.push(id); // remember function typedefs
- }
if (isalias)
s = new AST.AliasDeclaration(token.loc, id, dt);
+ insertTypedefToTypedefTab(id, dt); // remember typedefs
}
else if (id)
{
@@ -1791,6 +1812,8 @@ final class CParser(AST) : Parser!AST
initializer = new AST.VoidInitializer(token.loc);
s = new AST.VarDeclaration(token.loc, dt, id, initializer, specifiersToSTC(level, specifier));
}
+ if (level != LVL.global)
+ insertIdToTypedefTab(id); // non-typedef declarations can hide typedefs in outer scopes
}
if (s !is null)
{
@@ -1868,6 +1891,10 @@ final class CParser(AST) : Parser!AST
*/
AST.Dsymbol cparseFunctionDefinition(Identifier id, AST.TypeFunction ft, ref Specifier specifier)
{
+ /* Start function scope
+ */
+ typedefTab.push(null);
+
if (token.value != TOK.leftCurly) // if not start of a compound-statement
{
// Do declaration-list
@@ -1930,6 +1957,8 @@ final class CParser(AST) : Parser!AST
const locFunc = token.loc;
auto body = cparseStatement(ParseStatementFlags.curly); // don't start a new scope; continue with parameter scope
+ typedefTab.pop(); // end of function scope
+
auto fd = new AST.FuncDeclaration(locFunc, prevloc, id, specifiersToSTC(LVL.global, specifier), ft, specifier.noreturn);
if (addFuncName)
@@ -2737,6 +2766,16 @@ final class CParser(AST) : Parser!AST
return AST.ParameterList(parameters, AST.VarArg.variadic, varargsStc);
}
+ /* Create function prototype scope
+ */
+ typedefTab.push(null);
+
+ AST.ParameterList finish()
+ {
+ typedefTab.pop();
+ return AST.ParameterList(parameters, varargs, varargsStc);
+ }
+
/* The check for identifier-list comes later,
* when doing the trailing declaration-list (opt)
*/
@@ -2752,7 +2791,7 @@ final class CParser(AST) : Parser!AST
varargs = AST.VarArg.variadic; // C-style variadics
nextToken();
check(TOK.rightParenthesis);
- return AST.ParameterList(parameters, varargs, varargsStc);
+ return finish();
}
Specifier specifier;
@@ -2777,7 +2816,7 @@ final class CParser(AST) : Parser!AST
check(TOK.comma);
}
nextToken();
- return AST.ParameterList(parameters, varargs, varargsStc);
+ return finish();
}
/***********************************
@@ -4121,12 +4160,14 @@ final class CParser(AST) : Parser!AST
* ( expression )
* Params:
* pt = starting token, updated to one past end of constant-expression if true
- * afterParenType = true if already seen ( type-name )
+ * afterParenType = true if already seen `( type-name )`
* Returns:
* true if matches ( type-name ) ...
*/
private bool isCastExpression(ref Token* pt, bool afterParenType = false)
{
+ enum log = false;
+ if (log) printf("isCastExpression(tk: `%s`, afterParenType: %d)\n", token.toChars(pt.value), afterParenType);
auto t = pt;
switch (t.value)
{
@@ -4144,19 +4185,23 @@ final class CParser(AST) : Parser!AST
{
// ( type-name ) { initializer-list }
if (!isInitializer(tk))
+ {
return false;
+ }
t = tk;
break;
}
if (tk.value == TOK.leftParenthesis && peek(tk).value == TOK.rightParenthesis)
+ {
return false; // (type-name)() is not a cast (it might be a function call)
+ }
if (!isCastExpression(tk, true))
{
if (afterParenType) // could be ( type-name ) ( unary-expression )
goto default; // where unary-expression also matched type-name
- return false;
+ return true;
}
// ( type-name ) cast-expression
t = tk;
@@ -4164,11 +4209,14 @@ final class CParser(AST) : Parser!AST
default:
if (!afterParenType || !isUnaryExpression(t, afterParenType))
+ {
return false;
+ }
// if we've already seen ( type-name ), then this is a cast
break;
}
pt = t;
+ if (log) printf("isCastExpression true\n");
return true;
}
@@ -4576,9 +4624,14 @@ final class CParser(AST) : Parser!AST
return s;
}
+ //}
+
+ /******************************************************************************/
+ /************************** typedefTab symbol table ***************************/
+ //{
+
/********************************
* Determines if type t is a function type.
- * Make this work without needing semantic analysis.
* Params:
* t = type to test
* Returns:
@@ -4591,20 +4644,84 @@ final class CParser(AST) : Parser!AST
return true;
if (auto tid = t.isTypeIdentifier())
{
- /* Scan array of typedef identifiers that are an alias for
- * a function type
- */
- foreach (ftid; funcTypeIds[])
+ auto pt = lookupTypedef(tid.ident);
+ if (pt && *pt)
{
- if (tid.ident == ftid)
- {
- return true;
- }
+ return (*pt).isTypeFunction() !is null;
}
}
return false;
}
+ /********************************
+ * Determine if `id` is a symbol for a Typedef.
+ * Params:
+ * id = possible typedef
+ * Returns:
+ * true if id is a Type
+ */
+ bool isTypedef(Identifier id)
+ {
+ auto pt = lookupTypedef(id);
+ return (pt && *pt);
+ }
+
+ /*******************************
+ * Add `id` to typedefTab[], but only if it will mask an existing typedef.
+ * Params: id = identifier for non-typedef symbol
+ */
+ void insertIdToTypedefTab(Identifier id)
+ {
+ //printf("insertIdToTypedefTab(id: %s) level %d\n", id.toChars(), cast(int)typedefTab.length - 1);
+ if (isTypedef(id)) // if existing typedef
+ {
+ /* Add id as null, so we can later distinguish it from a non-null typedef
+ */
+ auto tab = cast(void*[void*])(typedefTab[$ - 1]);
+ tab[cast(void*)id] = cast(void*)null;
+ }
+ }
+
+ /*******************************
+ * Add `id` to typedefTab[]
+ * Params:
+ * id = identifier for typedef symbol
+ * t = type of the typedef symbol
+ */
+ void insertTypedefToTypedefTab(Identifier id, AST.Type t)
+ {
+ //printf("insertTypedefToTypedefTab(id: %s, t: %s) level %d\n", id.toChars(), t ? t.toChars() : "null".ptr, cast(int)typedefTab.length - 1);
+ if (auto tid = t.isTypeIdentifier())
+ {
+ // Try to resolve the TypeIdentifier to its type
+ auto pt = lookupTypedef(tid.ident);
+ if (pt && *pt)
+ t = *pt;
+ }
+ auto tab = cast(void*[void*])(typedefTab[$ - 1]);
+ tab[cast(void*)id] = cast(void*)t;
+ typedefTab[$ - 1] = cast(void*)tab;
+ }
+
+ /*********************************
+ * Lookup id in typedefTab[].
+ * Returns:
+ * if not found, then null.
+ * if found, then Type*. Deferencing it will yield null if it is not
+ * a typedef, and a type if it is a typedef.
+ */
+ AST.Type* lookupTypedef(Identifier id)
+ {
+ foreach_reverse (tab; typedefTab[])
+ {
+ if (auto pt = cast(void*)id in cast(void*[void*])tab)
+ {
+ return cast(AST.Type*)pt;
+ }
+ }
+ return null; // not found
+ }
+
//}
/******************************************************************************/
diff --git a/gcc/d/dmd/cppmangle.d b/gcc/d/dmd/cppmangle.d
index 9564b03..13ef34c 100644
--- a/gcc/d/dmd/cppmangle.d
+++ b/gcc/d/dmd/cppmangle.d
@@ -1908,6 +1908,8 @@ extern(C++):
return writeBasicType(t, 0, 'l');
else if (id == Id.__c_ulong)
return writeBasicType(t, 0, 'm');
+ else if (id == Id.__c_char)
+ return writeBasicType(t, 0, 'c');
else if (id == Id.__c_wchar_t)
return writeBasicType(t, 0, 'w');
else if (id == Id.__c_longlong)
diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d
index 9bc453d..9078f90 100644
--- a/gcc/d/dmd/ctfeexpr.d
+++ b/gcc/d/dmd/ctfeexpr.d
@@ -343,10 +343,9 @@ UnionExp copyLiteral(Expression e)
{
auto tsa = v.type.isTypeSArray();
auto len = cast(size_t)tsa.dim.toInteger();
- UnionExp uex = void;
- m = createBlockDuplicatedArrayLiteral(&uex, e.loc, v.type, m, len);
- if (m == uex.exp())
- m = uex.copy();
+ m = createBlockDuplicatedArrayLiteral(&ue, e.loc, v.type, m, len);
+ if (m == ue.exp())
+ m = ue.copy();
}
}
el = m;
@@ -583,10 +582,9 @@ ArrayLiteralExp createBlockDuplicatedArrayLiteral(UnionExp* pue, const ref Loc l
// If it is a multidimensional array literal, do it recursively
auto tsa = type.nextOf().isTypeSArray();
const len = cast(size_t)tsa.dim.toInteger();
- UnionExp ue = void;
- elem = createBlockDuplicatedArrayLiteral(&ue, loc, type.nextOf(), elem, len);
- if (elem == ue.exp())
- elem = ue.copy();
+ elem = createBlockDuplicatedArrayLiteral(pue, loc, type.nextOf(), elem, len);
+ if (elem == pue.exp())
+ elem = pue.copy();
}
// Buzilla 15681
@@ -791,9 +789,8 @@ bool pointToSameMemoryBlock(Expression agg1, Expression agg2)
}
// return e1 - e2 as an integer, or error if not possible
-UnionExp pointerDifference(const ref Loc loc, Type type, Expression e1, Expression e2)
+Expression pointerDifference(UnionExp* pue, const ref Loc loc, Type type, Expression e1, Expression e2)
{
- UnionExp ue = void;
dinteger_t ofs1, ofs2;
Expression agg1 = getAggregateFromPointer(e1, &ofs1);
Expression agg2 = getAggregateFromPointer(e2, &ofs2);
@@ -801,39 +798,38 @@ UnionExp pointerDifference(const ref Loc loc, Type type, Expression e1, Expressi
{
Type pointee = (cast(TypePointer)agg1.type).next;
const sz = pointee.size();
- emplaceExp!(IntegerExp)(&ue, loc, (ofs1 - ofs2) * sz, type);
+ emplaceExp!(IntegerExp)(pue, loc, (ofs1 - ofs2) * sz, type);
}
else if (agg1.op == EXP.string_ && agg2.op == EXP.string_ &&
(cast(StringExp)agg1).peekString().ptr == (cast(StringExp)agg2).peekString().ptr)
{
Type pointee = (cast(TypePointer)agg1.type).next;
const sz = pointee.size();
- emplaceExp!(IntegerExp)(&ue, loc, (ofs1 - ofs2) * sz, type);
+ emplaceExp!(IntegerExp)(pue, loc, (ofs1 - ofs2) * sz, type);
}
else if (agg1.op == EXP.symbolOffset && agg2.op == EXP.symbolOffset &&
(cast(SymOffExp)agg1).var == (cast(SymOffExp)agg2).var)
{
- emplaceExp!(IntegerExp)(&ue, loc, ofs1 - ofs2, type);
+ emplaceExp!(IntegerExp)(pue, loc, ofs1 - ofs2, type);
}
else
{
error(loc, "`%s - %s` cannot be interpreted at compile time: cannot subtract pointers to two different memory blocks", e1.toChars(), e2.toChars());
- emplaceExp!(CTFEExp)(&ue, EXP.cantExpression);
+ emplaceExp!(CTFEExp)(pue, EXP.cantExpression);
}
- return ue;
+ return pue.exp();
}
// Return eptr op e2, where eptr is a pointer, e2 is an integer,
// and op is EXP.add or EXP.min
-UnionExp pointerArithmetic(const ref Loc loc, EXP op, Type type, Expression eptr, Expression e2)
+Expression pointerArithmetic(UnionExp* pue, const ref Loc loc, EXP op, Type type, Expression eptr, Expression e2)
{
- UnionExp ue;
if (eptr.type.nextOf().ty == Tvoid)
{
error(loc, "cannot perform arithmetic on `void*` pointers at compile time");
Lcant:
- emplaceExp!(CTFEExp)(&ue, EXP.cantExpression);
- return ue;
+ emplaceExp!(CTFEExp)(pue, EXP.cantExpression);
+ return pue.exp();
}
if (eptr.op == EXP.address)
eptr = (cast(AddrExp)eptr).e1;
@@ -885,10 +881,10 @@ UnionExp pointerArithmetic(const ref Loc loc, EXP op, Type type, Expression eptr
}
if (agg1.op == EXP.symbolOffset)
{
- emplaceExp!(SymOffExp)(&ue, loc, (cast(SymOffExp)agg1).var, indx * sz);
- SymOffExp se = cast(SymOffExp)ue.exp();
+ emplaceExp!(SymOffExp)(pue, loc, (cast(SymOffExp)agg1).var, indx * sz);
+ SymOffExp se = cast(SymOffExp)pue.exp();
se.type = type;
- return ue;
+ return pue.exp();
}
if (agg1.op != EXP.arrayLiteral && agg1.op != EXP.string_)
{
@@ -903,17 +899,17 @@ UnionExp pointerArithmetic(const ref Loc loc, EXP op, Type type, Expression eptr
ctfeEmplaceExp!IntegerExp(loc, indx, Type.tsize_t),
ctfeEmplaceExp!IntegerExp(loc, indx + dim, Type.tsize_t));
se.type = type.toBasetype().nextOf();
- emplaceExp!(AddrExp)(&ue, loc, se);
- ue.exp().type = type;
- return ue;
+ emplaceExp!(AddrExp)(pue, loc, se);
+ pue.exp().type = type;
+ return pue.exp();
}
// Create a CTFE pointer &agg1[indx]
auto ofs = ctfeEmplaceExp!IntegerExp(loc, indx, Type.tsize_t);
Expression ie = ctfeEmplaceExp!IndexExp(loc, agg1, ofs);
ie.type = type.toBasetype().nextOf(); // https://issues.dlang.org/show_bug.cgi?id=13992
- emplaceExp!(AddrExp)(&ue, loc, ie);
- ue.exp().type = type;
- return ue;
+ emplaceExp!(AddrExp)(pue, loc, ie);
+ pue.exp().type = type;
+ return pue.exp();
}
// Return 1 if true, 0 if false
@@ -1755,9 +1751,8 @@ Expression assignAssocArrayElement(const ref Loc loc, AssocArrayLiteralExp aae,
/// Given array literal oldval of type ArrayLiteralExp or StringExp, of length
/// oldlen, change its length to newlen. If the newlen is longer than oldlen,
/// all new elements will be set to the default initializer for the element type.
-UnionExp changeArrayLiteralLength(const ref Loc loc, TypeArray arrayType, Expression oldval, size_t oldlen, size_t newlen)
+Expression changeArrayLiteralLength(UnionExp* pue, const ref Loc loc, TypeArray arrayType, Expression oldval, size_t oldlen, size_t newlen)
{
- UnionExp ue;
Type elemType = arrayType.next;
assert(elemType);
Expression defaultElem = elemType.defaultInitLiteral(loc);
@@ -1794,8 +1789,8 @@ UnionExp changeArrayLiteralLength(const ref Loc loc, TypeArray arrayType, Expres
assert(0);
}
}
- emplaceExp!(StringExp)(&ue, loc, s[0 .. newlen * oldse.sz], newlen, oldse.sz);
- StringExp se = cast(StringExp)ue.exp();
+ emplaceExp!(StringExp)(pue, loc, s[0 .. newlen * oldse.sz], newlen, oldse.sz);
+ StringExp se = cast(StringExp)pue.exp();
se.type = arrayType;
se.sz = oldse.sz;
se.committed = oldse.committed;
@@ -1823,11 +1818,11 @@ UnionExp changeArrayLiteralLength(const ref Loc loc, TypeArray arrayType, Expres
foreach (size_t i; copylen .. newlen)
(*elements)[i] = defaultElem;
}
- emplaceExp!(ArrayLiteralExp)(&ue, loc, arrayType, elements);
- ArrayLiteralExp aae = cast(ArrayLiteralExp)ue.exp();
+ emplaceExp!(ArrayLiteralExp)(pue, loc, arrayType, elements);
+ ArrayLiteralExp aae = cast(ArrayLiteralExp)pue.exp();
aae.ownedByCtfe = OwnedBy.ctfe;
}
- return ue;
+ return pue.exp();
}
/*************************** CTFE Sanity Checks ***************************/
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index 69036ad..887bb89 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -1894,7 +1894,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
if (e.committed && tb.ty == Tsarray && typeb.ty == Tarray)
{
se = e.copy().isStringExp();
- d_uns64 szx = tb.nextOf().size();
+ uinteger_t szx = tb.nextOf().size();
assert(szx <= 255);
se.sz = cast(ubyte)szx;
se.len = cast(size_t)tb.isTypeSArray().dim.toInteger();
@@ -2059,7 +2059,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
}
{
- d_uns64 szx = tb.nextOf().size();
+ uinteger_t szx = tb.nextOf().size();
assert(szx <= 255);
se.setData(buffer.extractSlice().ptr, newlen, cast(ubyte)szx);
}
@@ -2742,7 +2742,7 @@ Expression scaleFactor(BinExp be, Scope* sc)
// Replace (ptr + int) with (ptr + (int * stride))
Type t = Type.tptrdiff_t;
- d_uns64 stride = t1b.nextOf().size(be.loc);
+ uinteger_t stride = t1b.nextOf().size(be.loc);
if (!t.equals(t2b))
be.e2 = be.e2.castTo(sc, t);
eoff = be.e2;
@@ -2757,7 +2757,7 @@ Expression scaleFactor(BinExp be, Scope* sc)
Type t = Type.tptrdiff_t;
Expression e;
- d_uns64 stride = t2b.nextOf().size(be.loc);
+ uinteger_t stride = t2b.nextOf().size(be.loc);
if (!t.equals(t1b))
e = be.e1.castTo(sc, t);
else
diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index 585ac2f0..82a5f3b 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/dmd/declaration.d
@@ -250,7 +250,7 @@ extern (C++) abstract class Declaration : Dsymbol
return "declaration";
}
- override final d_uns64 size(const ref Loc loc)
+ override final uinteger_t size(const ref Loc loc)
{
assert(type);
const sz = type.size();
@@ -1141,7 +1141,7 @@ extern (C++) class VarDeclaration : Declaration
if (!isField())
return;
- assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter | STC.tls)));
+ assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter)));
//printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
@@ -1217,7 +1217,7 @@ extern (C++) class VarDeclaration : Declaration
override final inout(AggregateDeclaration) isThis() inout
{
- if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.tls | STC.gshared | STC.ctfe)))
+ if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.gshared | STC.ctfe)))
{
/* The casting is necessary because `s = s.parent` is otherwise rejected
*/
@@ -1285,7 +1285,7 @@ extern (C++) class VarDeclaration : Declaration
error("forward referenced");
type = Type.terror;
}
- else if (storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared) ||
+ else if (storage_class & (STC.static_ | STC.extern_ | STC.gshared) ||
parent.isModule() || parent.isTemplateInstance() || parent.isNspace())
{
assert(!isParameter() && !isResult());
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 93e3a5a..9986ea3 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -71,7 +71,6 @@ struct IntRange;
#define STCnodtor 0x10000000ULL /// do not run destructor
#define STCnothrow 0x20000000ULL /// `nothrow` meaning never throws exceptions
#define STCpure 0x40000000ULL /// `pure` function
- #define STCtls 0x80000000ULL /// thread local
#define STCalias 0x100000000ULL /// `alias` parameter
#define STCshared 0x200000000ULL /// accessible from multiple threads
@@ -123,7 +122,7 @@ public:
DString mangleOverride; // overridden symbol with pragma(mangle, "...")
const char *kind() const;
- d_uns64 size(const Loc &loc);
+ uinteger_t size(const Loc &loc);
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d
index 6c3454d..30a8a44 100644
--- a/gcc/d/dmd/dinterpret.d
+++ b/gcc/d/dmd/dinterpret.d
@@ -1886,7 +1886,7 @@ public:
{
// Check for unsupported type painting operations
Type elemtype = (cast(TypeArray)val.type).next;
- d_uns64 elemsize = elemtype.size();
+ const elemsize = elemtype.size();
// It's OK to cast from fixed length to fixed length array, eg &int[n] to int[d]*.
if (val.type.ty == Tsarray && pointee.ty == Tsarray && elemsize == pointee.nextOf().size())
@@ -2981,8 +2981,7 @@ public:
Expression e2 = interpret(&ue2, e.e2, istate);
if (exceptionOrCant(e2))
return;
- *pue = pointerDifference(e.loc, e.type, e1, e2);
- result = (*pue).exp();
+ result = pointerDifference(pue, e.loc, e.type, e1, e2);
return;
}
if (e.e1.type.ty == Tpointer && e.e2.type.isintegral())
@@ -2995,8 +2994,7 @@ public:
Expression e2 = interpret(&ue2, e.e2, istate);
if (exceptionOrCant(e2))
return;
- *pue = pointerArithmetic(e.loc, e.op, e.type, e1, e2);
- result = (*pue).exp();
+ result = pointerArithmetic(pue, e.loc, e.op, e.type, e1, e2);
return;
}
if (e.e2.type.ty == Tpointer && e.e1.type.isintegral() && e.op == EXP.add)
@@ -3009,8 +3007,7 @@ public:
Expression e2 = interpret(&ue2, e.e2, istate);
if (exceptionOrCant(e2))
return;
- *pue = pointerArithmetic(e.loc, e.op, e.type, e2, e1);
- result = (*pue).exp();
+ result = pointerArithmetic(pue, e.loc, e.op, e.type, e2, e1);
return;
}
if (e.e1.type.ty == Tpointer || e.e2.type.ty == Tpointer)
@@ -3041,7 +3038,7 @@ public:
if (e.op == EXP.rightShift || e.op == EXP.leftShift || e.op == EXP.unsignedRightShift)
{
const sinteger_t i2 = e2.toInteger();
- const d_uns64 sz = e1.type.size() * 8;
+ const uinteger_t sz = e1.type.size() * 8;
if (i2 < 0 || i2 >= sz)
{
e.error("shift by %lld is outside the range 0..%llu", i2, cast(ulong)sz - 1);
@@ -3602,7 +3599,9 @@ public:
e.op == EXP.plusPlus ||
e.op == EXP.minusMinus))
{
- newval = pointerArithmetic(e.loc, e.op, e.type, oldval, newval).copy();
+ newval = pointerArithmetic(pue, e.loc, e.op, e.type, oldval, newval).copy();
+ if (newval == pue.exp())
+ newval = pue.copy();
}
else
{
@@ -3675,7 +3674,9 @@ public:
UnionExp utmp = void;
oldval = resolveSlice(oldval, &utmp);
- newval = changeArrayLiteralLength(e.loc, cast(TypeArray)t, oldval, oldlen, newlen).copy();
+ newval = changeArrayLiteralLength(pue, e.loc, cast(TypeArray)t, oldval, oldlen, newlen);
+ if (newval == pue.exp())
+ newval = pue.copy();
e1 = assignToLvalue(e, e1, newval);
if (exceptionOrCant(e1))
@@ -3994,61 +3995,18 @@ public:
// aggregate[] = newval
// aggregate[low..upp] = newval
// ------------------------------
- version (all) // should be move in interpretAssignCommon as the evaluation of e1
- {
- Expression oldval = interpretRegion(se.e1, istate);
-
- // Set the $ variable
- uinteger_t dollar = resolveArrayLength(oldval);
- if (se.lengthVar)
- {
- Expression dollarExp = ctfeEmplaceExp!IntegerExp(e1.loc, dollar, Type.tsize_t);
- ctfeGlobals.stack.push(se.lengthVar);
- setValue(se.lengthVar, dollarExp);
- }
- Expression lwr = interpretRegion(se.lwr, istate);
- if (exceptionOrCantInterpret(lwr))
- {
- if (se.lengthVar)
- ctfeGlobals.stack.pop(se.lengthVar);
- return lwr;
- }
- Expression upr = interpretRegion(se.upr, istate);
- if (exceptionOrCantInterpret(upr))
- {
- if (se.lengthVar)
- ctfeGlobals.stack.pop(se.lengthVar);
- return upr;
- }
- if (se.lengthVar)
- ctfeGlobals.stack.pop(se.lengthVar); // $ is defined only in [L..U]
-
- const dim = dollar;
- lowerbound = lwr ? lwr.toInteger() : 0;
- upperbound = upr ? upr.toInteger() : dim;
-
- if (lowerbound < 0 || dim < upperbound)
- {
- e.error("array bounds `[0..%llu]` exceeded in slice `[%llu..%llu]`",
- ulong(dim), ulong(lowerbound), ulong(upperbound));
- return CTFEExp.cantexp;
- }
- }
- aggregate = oldval;
- firstIndex = lowerbound;
+ aggregate = interpretRegion(se.e1, istate);
+ lowerbound = se.lwr ? se.lwr.toInteger() : 0;
+ upperbound = se.upr ? se.upr.toInteger() : resolveArrayLength(aggregate);
+ // Slice of a slice --> change the bounds
if (auto oldse = aggregate.isSliceExp())
{
- // Slice of a slice --> change the bounds
- if (oldse.upr.toInteger() < upperbound + oldse.lwr.toInteger())
- {
- e.error("slice `[%llu..%llu]` exceeds array bounds `[0..%llu]`",
- ulong(lowerbound), ulong(upperbound), oldse.upr.toInteger() - oldse.lwr.toInteger());
- return CTFEExp.cantexp;
- }
aggregate = oldse.e1;
firstIndex = lowerbound + oldse.lwr.toInteger();
}
+ else
+ firstIndex = lowerbound;
}
else
{
@@ -5520,7 +5478,7 @@ public:
assert(agg.op == EXP.arrayLiteral || agg.op == EXP.string_);
dinteger_t len = ArrayLength(Type.tsize_t, agg).exp().toInteger();
//Type *pointee = ((TypePointer *)agg.type)->next;
- if (iupr > (len + 1) || iupr < ilwr)
+ if (sliceBoundsCheck(0, len, ilwr, iupr))
{
e.error("pointer slice `[%lld..%lld]` exceeds allocated memory block `[0..%lld]`", ilwr, iupr, len);
result = CTFEExp.cantexp;
@@ -5624,9 +5582,9 @@ public:
// aggregate[lo1..up1][lwr..upr] ---> aggregate[lwr'..upr']
uinteger_t lo1 = se.lwr.toInteger();
uinteger_t up1 = se.upr.toInteger();
- if (ilwr > iupr || iupr > up1 - lo1)
+ if (sliceBoundsCheck(0, up1 - lo1, ilwr, iupr))
{
- e.error("slice `[%llu..%llu]` exceeds array bounds `[%llu..%llu]`", ilwr, iupr, lo1, up1);
+ e.error("slice `[%llu..%llu]` exceeds array bounds `[0..%llu]`", ilwr, iupr, up1 - lo1);
result = CTFEExp.cantexp;
return;
}
@@ -5641,7 +5599,7 @@ public:
}
if (e1.op == EXP.arrayLiteral || e1.op == EXP.string_)
{
- if (iupr < ilwr || dollar < iupr)
+ if (sliceBoundsCheck(0, dollar, ilwr, iupr))
{
e.error("slice `[%lld..%lld]` exceeds array bounds `[0..%lld]`", ilwr, iupr, dollar);
result = CTFEExp.cantexp;
diff --git a/gcc/d/dmd/dmacro.d b/gcc/d/dmd/dmacro.d
index 0e891fb..9beac6b 100644
--- a/gcc/d/dmd/dmacro.d
+++ b/gcc/d/dmd/dmacro.d
@@ -31,18 +31,12 @@ extern (C++) struct MacroTable
extern (D) void define(const(char)[] name, const(char)[] text)
{
//printf("MacroTable::define('%.*s' = '%.*s')\n", cast(int)name.length, name.ptr, text.length, text.ptr);
- Macro* table;
- for (table = mactab; table; table = table.next)
+ if (auto table = name in mactab)
{
- if (table.name == name)
- {
- table.text = text;
- return;
- }
+ (*table).text = text;
+ return;
}
- table = new Macro(name, text);
- table.next = mactab;
- mactab = table;
+ mactab[name] = new Macro(name, text);
}
/*****************************************************
@@ -266,20 +260,16 @@ extern (C++) struct MacroTable
extern (D) Macro* search(const(char)[] name)
{
- Macro* table;
//printf("Macro::search(%.*s)\n", cast(int)name.length, name.ptr);
- for (table = mactab; table; table = table.next)
+ if (auto table = name in mactab)
{
- if (table.name == name)
- {
- //printf("\tfound %d\n", table.textlen);
- break;
- }
+ //printf("\tfound %d\n", table.textlen);
+ return *table;
}
- return table;
+ return null;
}
- Macro* mactab;
+ private Macro*[const(char)[]] mactab;
}
/* ************************************************************************ */
@@ -288,7 +278,6 @@ private:
struct Macro
{
- Macro* next; // next in list
const(char)[] name; // macro name
const(char)[] text; // macro replacement text
int inuse; // macro is in use (don't expand)
diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index 00fa031..35d2aba 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/dmd/dmodule.d
@@ -75,7 +75,7 @@ void removeHdrFilesAndFail(ref Param params, ref Modules modules)
{
foreach (m; modules)
{
- if (m.isHdrFile)
+ if (m.filetype == FileType.dhdr)
continue;
File.remove(m.hdrfile.toChars());
}
@@ -351,12 +351,10 @@ extern (C++) final class Module : Package
const FileName objfile; // output .obj file
const FileName hdrfile; // 'header' file
FileName docfile; // output documentation file
- FileBuffer* srcBuffer; // set during load(), free'd in parse()
+ const(ubyte)[] src; /// Raw content of the file
uint errors; // if any errors in file
uint numlines; // number of lines in source file
- bool isHdrFile; // if it is a header (.di) file
- bool isCFile; // if it is a C (.c) file
- bool isDocFile; // if it is a documentation input file, not D source
+ FileType filetype; // source file type
bool hasAlwaysInlines; // contains references to functions that must be inlined
bool isPackageFile; // if it is a package.d
Package pkg; // if isPackageFile is true, the Package that contains this package.d
@@ -590,24 +588,17 @@ extern (C++) final class Module : Package
}
/**
- * Loads the source buffer from the given read result into `this.srcBuffer`.
+ * Trigger the relevant semantic error when a file cannot be read
*
- * Will take ownership of the buffer located inside `readResult`.
+ * We special case `object.d` as a failure is likely to be a rare
+ * but difficult to diagnose case for the user. Packages also require
+ * special handling to avoid exposing the compiler's internals.
*
* Params:
- * loc = the location
- * readResult = the result of reading a file containing the source code
- *
- * Returns: `true` if successful
+ * loc = The location at which the file read originated (e.g. import)
*/
- bool loadSourceBuffer(const ref Loc loc, ref File.ReadResult readResult)
+ private void onFileReadError(const ref Loc loc)
{
- //printf("Module::loadSourceBuffer('%s') file '%s'\n", toChars(), srcfile.toChars());
- // take ownership of buffer
- srcBuffer = new FileBuffer(readResult.extractSlice());
- if (readResult.success)
- return true;
-
if (FileName.equals(srcfile.toString(), "object.d"))
{
.error(loc, "cannot find source code for runtime library file 'object.d'");
@@ -621,7 +612,6 @@ extern (C++) final class Module : Package
// 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());
- return false;
}
else
{
@@ -653,7 +643,6 @@ extern (C++) final class Module : Package
removeHdrFilesAndFail(global.params, Module.amodules);
}
- return false;
}
/**
@@ -666,37 +655,23 @@ extern (C++) final class Module : Package
* loc = the location
*
* Returns: `true` if successful
- * See_Also: loadSourceBuffer
*/
bool read(const ref Loc loc)
{
- if (srcBuffer)
+ if (this.src)
return true; // already read
//printf("Module::read('%s') file '%s'\n", toChars(), srcfile.toChars());
-
-
-
- bool success;
- if (auto readResult = FileManager.fileManager.lookup(srcfile))
+ if (auto result = FileManager.fileManager.lookup(srcfile))
{
- srcBuffer = readResult;
- success = true;
- }
- else
- {
- auto readResult = File.read(srcfile.toChars());
- if (loadSourceBuffer(loc, readResult))
- {
- FileManager.fileManager.add(srcfile, srcBuffer);
- success = true;
- }
- }
- if (success && global.params.emitMakeDeps)
- {
- global.params.makeDeps.push(srcfile.toChars());
+ this.src = result.data;
+ if (global.params.emitMakeDeps)
+ global.params.makeDeps.push(srcfile.toChars());
+ return true;
}
- return success;
+
+ this.onFileReadError(loc);
+ return false;
}
/// syntactic parse
@@ -830,7 +805,7 @@ extern (C++) final class Module : Package
//printf("Module::parse(srcname = '%s')\n", srcname);
isPackageFile = (strcmp(srcfile.name(), package_d) == 0 ||
strcmp(srcfile.name(), package_di) == 0);
- const(char)[] buf = cast(const(char)[]) srcBuffer.data;
+ const(char)[] buf = cast(const(char)[]) this.src;
bool needsReencoding = true;
bool hasBOM = true; //assume there's a BOM
@@ -942,7 +917,7 @@ extern (C++) final class Module : Package
if (buf.length>= 4 && buf[0..4] == "Ddoc")
{
comment = buf.ptr + 4;
- isDocFile = true;
+ filetype = FileType.ddoc;
if (!docfile)
setDocfile();
return this;
@@ -955,7 +930,7 @@ extern (C++) final class Module : Package
if (FileName.equalsExt(arg, dd_ext))
{
comment = buf.ptr; // the optional Ddoc, if present, is handled above.
- isDocFile = true;
+ filetype = FileType.ddoc;
if (!docfile)
setDocfile();
return this;
@@ -963,9 +938,7 @@ extern (C++) final class Module : Package
/* If it has the extension ".di", it is a "header" file.
*/
if (FileName.equalsExt(arg, hdr_ext))
- {
- isHdrFile = true;
- }
+ filetype = FileType.dhdr;
/// Promote `this` to a root module if requested via `-i`
void checkCompiledImport()
@@ -982,7 +955,7 @@ extern (C++) final class Module : Package
*/
if (FileName.equalsExt(arg, c_ext) || FileName.equalsExt(arg, i_ext))
{
- isCFile = true;
+ filetype = FileType.c;
scope p = new CParser!AST(this, buf, cast(bool) docfile, target.c);
p.nextToken();
@@ -1014,8 +987,7 @@ extern (C++) final class Module : Package
members = p.parseModuleContent();
numlines = p.scanloc.linnum;
}
- srcBuffer.destroy();
- srcBuffer = null;
+
/* The symbol table into which the module is to be inserted.
*/
@@ -1141,7 +1113,7 @@ extern (C++) final class Module : Package
//printf("+Module::importAll(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
if (_scope)
return; // already done
- if (isDocFile)
+ if (filetype == FileType.ddoc)
{
error("is a Ddoc file, cannot import it");
return;
diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d
index d03b5bb..d05060d 100644
--- a/gcc/d/dmd/doc.d
+++ b/gcc/d/dmd/doc.d
@@ -425,7 +425,7 @@ extern(C++) void gendocfile(Module m)
dc.copyright.nooutput = 1;
m.macrotable.define("COPYRIGHT", dc.copyright.body_);
}
- if (m.isDocFile)
+ if (m.filetype == FileType.ddoc)
{
const ploc = m.md ? &m.md.loc : &m.loc;
const loc = Loc(ploc.filename ? ploc.filename : srcfilename.ptr,
@@ -4991,7 +4991,7 @@ private void highlightText(Scope* sc, Dsymbols* a, Loc loc, ref OutBuffer buf, s
default:
leadingBlank = false;
- if (sc._module.isDocFile || inCode)
+ if (sc._module.filetype == FileType.ddoc || inCode)
break;
const start = cast(char*)buf[].ptr + i;
if (isIdStart(start))
diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index 936d19a..aa30b5d 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/dmd/dscope.d
@@ -174,7 +174,7 @@ struct Scope
m = m.parent;
m.addMember(null, sc.scopesym);
m.parent = null; // got changed by addMember()
- if (_module.isCFile)
+ if (_module.filetype == FileType.c)
sc.flags |= SCOPE.Cfile;
// Create the module scope underneath the global scope
sc = sc.push(_module);
diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index f8ada2b..9e50bd5 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/dmd/dsymbol.d
@@ -465,10 +465,7 @@ extern (C++) class Dsymbol : ASTNode
final bool isCsymbol()
{
if (Module m = getModule())
- {
- if (m.isCFile)
- return true;
- }
+ return m.filetype == FileType.c;
return false;
}
@@ -975,7 +972,7 @@ extern (C++) class Dsymbol : ASTNode
* Returns:
* SIZE_INVALID when the size cannot be determined
*/
- d_uns64 size(const ref Loc loc)
+ uinteger_t size(const ref Loc loc)
{
error("Dsymbol `%s` has no size", toChars());
return SIZE_INVALID;
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index c5af06e..aad0f2d 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -223,7 +223,7 @@ public:
virtual void importAll(Scope *sc);
virtual Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone);
virtual bool overloadInsert(Dsymbol *s);
- virtual d_uns64 size(const Loc &loc);
+ virtual uinteger_t size(const Loc &loc);
virtual bool isforwardRef();
virtual AggregateDeclaration *isThis(); // is a 'this' required to access the member
virtual bool isExport() const; // is Dsymbol exported?
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index b68d840..b31dc9d 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/dmd/dsymbolsem.d
@@ -716,7 +716,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (dsym.storage_class & STC.scope_)
{
- StorageClass stc = dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.tls | STC.gshared);
+ StorageClass stc = dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.gshared);
if (stc)
{
OutBuffer buf;
@@ -733,7 +733,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}
}
- if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.tls | STC.gshared | STC.ctfe))
+ if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.gshared | STC.ctfe))
{
}
else
@@ -794,7 +794,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (dsym.type.hasWild())
{
- if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared | STC.manifest | STC.field) || dsym.isDataseg())
+ if (dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field) || dsym.isDataseg())
{
dsym.error("only parameters or stack based variables can be `inout`");
}
@@ -841,7 +841,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
FuncDeclaration fd = parent.isFuncDeclaration();
if (dsym.type.isscope() && !(dsym.storage_class & STC.nodtor))
{
- if (dsym.storage_class & (STC.field | STC.out_ | STC.ref_ | STC.static_ | STC.manifest | STC.tls | STC.gshared) || !fd)
+ if (dsym.storage_class & (STC.field | STC.out_ | STC.ref_ | STC.static_ | STC.manifest | STC.gshared) || !fd)
{
dsym.error("globals, statics, fields, manifest constants, ref and out parameters cannot be `scope`");
}
@@ -871,7 +871,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
}
}
else if (!dsym._init &&
- !(dsym.storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared | STC.manifest | STC.field | STC.parameter)) &&
+ !(dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field | STC.parameter)) &&
dsym.type.hasVoidInitPointers())
{
if (sc.func.setUnsafe())
@@ -891,7 +891,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
dsym.error("manifest constants must have initializers");
bool isBlit = false;
- d_uns64 sz;
+ uinteger_t sz;
if (sc.flags & SCOPE.Cfile && !dsym._init)
{
addDefaultCInitializer(dsym);
@@ -977,7 +977,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
{
// If local variable, use AssignExp to handle all the various
// possibilities.
- if (fd && !(dsym.storage_class & (STC.manifest | STC.static_ | STC.tls | STC.gshared | STC.extern_)) && !dsym._init.isVoidInitializer())
+ if (fd && !(dsym.storage_class & (STC.manifest | STC.static_ | STC.gshared | STC.extern_)) && !dsym._init.isVoidInitializer())
{
//printf("fd = '%s', var = '%s'\n", fd.toChars(), toChars());
if (!ei)
@@ -1476,7 +1476,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
if (scd.decl)
{
sc = sc.push();
- sc.stc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.tls | STC.gshared);
+ sc.stc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.gshared);
sc.inunion = scd.isunion ? scd : null;
sc.flags = 0;
for (size_t i = 0; i < scd.decl.dim; i++)
@@ -4233,21 +4233,41 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
*/
if (scd.isInstantiated() && scd.semanticRun < PASS.semantic)
{
- /* Add this prefix to the function:
- * static int gate;
- * if (++gate != 1) return;
- * Note that this is not thread safe; should not have threads
- * during static construction.
+ /* Add this prefix to the constructor:
+ * ```
+ * static int gate;
+ * if (++gate != 1) return;
+ * ```
+ * or, for shared constructor:
+ * ```
+ * shared int gate;
+ * if (core.atomic.atomicOp!"+="(gate, 1) != 1) return;
+ * ```
*/
+ const bool isShared = !!scd.isSharedStaticCtorDeclaration();
auto v = new VarDeclaration(Loc.initial, Type.tint32, Id.gate, null);
- v.storage_class = STC.temp | (scd.isSharedStaticCtorDeclaration() ? STC.static_ : STC.tls);
+ v.storage_class = STC.temp | STC.static_ | (isShared ? STC.shared_ : 0);
auto sa = new Statements();
Statement s = new ExpStatement(Loc.initial, v);
sa.push(s);
- Expression e = new IdentifierExp(Loc.initial, v.ident);
- e = new AddAssignExp(Loc.initial, e, IntegerExp.literal!1);
+ Expression e;
+ if (isShared)
+ {
+ e = doAtomicOp("+=", v.ident, IntegerExp.literal!(1));
+ if (e is null)
+ {
+ scd.error("shared static constructor within a template require `core.atomic : atomicOp` to be present");
+ return;
+ }
+ }
+ else
+ {
+ e = new AddAssignExp(
+ Loc.initial, new IdentifierExp(Loc.initial, v.ident), IntegerExp.literal!1);
+ }
+
e = new EqualExp(EXP.notEqual, Loc.initial, e, IntegerExp.literal!1);
s = new IfStatement(Loc.initial, null, e, new ReturnStatement(Loc.initial, null), null, Loc.initial);
@@ -4309,22 +4329,41 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
*/
if (sdd.isInstantiated() && sdd.semanticRun < PASS.semantic)
{
- /* Add this prefix to the function:
- * static int gate;
- * if (--gate != 0) return;
- * Increment gate during constructor execution.
- * Note that this is not thread safe; should not have threads
- * during static destruction.
+ /* Add this prefix to the constructor:
+ * ```
+ * static int gate;
+ * if (--gate != 0) return;
+ * ```
+ * or, for shared constructor:
+ * ```
+ * shared int gate;
+ * if (core.atomic.atomicOp!"-="(gate, 1) != 0) return;
+ * ```
*/
+ const bool isShared = !!sdd.isSharedStaticDtorDeclaration();
auto v = new VarDeclaration(Loc.initial, Type.tint32, Id.gate, null);
- v.storage_class = STC.temp | (sdd.isSharedStaticDtorDeclaration() ? STC.static_ : STC.tls);
+ v.storage_class = STC.temp | STC.static_ | (isShared ? STC.shared_ : 0);
auto sa = new Statements();
Statement s = new ExpStatement(Loc.initial, v);
sa.push(s);
- Expression e = new IdentifierExp(Loc.initial, v.ident);
- e = new AddAssignExp(Loc.initial, e, IntegerExp.literal!(-1));
+ Expression e;
+ if (isShared)
+ {
+ e = doAtomicOp("-=", v.ident, IntegerExp.literal!(1));
+ if (e is null)
+ {
+ sdd.error("shared static destructo within a template require `core.atomic : atomicOp` to be present");
+ return;
+ }
+ }
+ else
+ {
+ e = new AddAssignExp(
+ Loc.initial, new IdentifierExp(Loc.initial, v.ident), IntegerExp.literal!(-1));
+ }
+
e = new EqualExp(EXP.notEqual, Loc.initial, e, IntegerExp.literal!0);
s = new IfStatement(Loc.initial, null, e, new ReturnStatement(Loc.initial, null), null, Loc.initial);
@@ -6833,3 +6872,48 @@ bool determineFields(AggregateDeclaration ad)
return true;
}
+
+/// Do an atomic operation (currently tailored to [shared] static ctors|dtors) needs
+private CallExp doAtomicOp (string op, Identifier var, Expression arg)
+{
+ __gshared Import imp = null;
+ __gshared Identifier[1] id;
+
+ assert(op == "-=" || op == "+=");
+
+ const loc = Loc.initial;
+
+ // Below code is similar to `loadStdMath` (used for `^^` operator)
+ if (!imp)
+ {
+ id[0] = Id.core;
+ auto s = new Import(Loc.initial, id[], Id.atomic, null, true);
+ // Module.load will call fatal() if there's no std.math available.
+ // Gag the error here, pushing the error handling to the caller.
+ uint errors = global.startGagging();
+ s.load(null);
+ if (s.mod)
+ {
+ s.mod.importAll(null);
+ s.mod.dsymbolSemantic(null);
+ }
+ global.endGagging(errors);
+ imp = s;
+ }
+ // Module couldn't be loaded
+ if (imp.mod is null)
+ return null;
+
+ Objects* tiargs = new Objects(1);
+ (*tiargs)[0] = new StringExp(loc, op);
+
+ Expressions* args = new Expressions(2);
+ (*args)[0] = new IdentifierExp(loc, var);
+ (*args)[1] = arg;
+
+ auto sc = new ScopeExp(loc, imp.mod);
+ auto dti = new DotTemplateInstanceExp(
+ loc, sc, Id.atomicOp, tiargs);
+
+ return CallExp.create(loc, dti, args);
+}
diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index adb91ed..366ed60 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -1943,7 +1943,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
{
// Allow conversion from T[lwr .. upr] to ref T[upr-lwr]
}
- else if (global.params.rvalueRefParam)
+ else if (global.params.rvalueRefParam == FeatureState.enabled)
{
// Allow implicit conversion to ref
}
@@ -8346,7 +8346,7 @@ struct TemplateStats
}
}
-void printTemplateStats()
+extern (C++) void printTemplateStats()
{
static struct TemplateDeclarationStats
{
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index 285b834..46982e3 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/dmd/dtoh.d
@@ -860,7 +860,7 @@ public:
origType = vd.originalType;
scope(exit) origType = null;
- if (!vd.alignment.isDefault())
+ if (!vd.alignment.isDefault() && !vd.alignment.isUnknown())
{
buf.printf("// Ignoring var %s alignment %d", vd.toChars(), vd.alignment.get());
buf.writenl();
@@ -940,7 +940,7 @@ public:
return;
}
- if (vd.storage_class & (AST.STC.static_ | AST.STC.extern_ | AST.STC.tls | AST.STC.gshared) ||
+ if (vd.storage_class & (AST.STC.static_ | AST.STC.extern_ | AST.STC.gshared) ||
vd.parent && vd.parent.isModule())
{
if (vd.linkage != LINK.c && vd.linkage != LINK.cpp && !(tdparent && (this.linkage == LINK.c || this.linkage == LINK.cpp)))
@@ -948,11 +948,6 @@ public:
ignored("variable %s because of linkage", vd.toPrettyChars());
return;
}
- if (vd.storage_class & AST.STC.tls)
- {
- ignored("variable %s because of thread-local storage", vd.toPrettyChars());
- return;
- }
if (!isSupportedType(type))
{
ignored("variable %s because its type cannot be mapped to C++", vd.toPrettyChars());
@@ -1934,6 +1929,8 @@ public:
buf.writestring("unsigned long long");
else if (ed.ident == DMDType.c_long_double)
buf.writestring("long double");
+ else if (ed.ident == DMDType.c_char)
+ buf.writestring("char");
else if (ed.ident == DMDType.c_wchar_t)
buf.writestring("wchar_t");
else if (ed.ident == DMDType.c_complex_float)
@@ -2681,6 +2678,18 @@ public:
{
if (vd._init && !vd._init.isVoidInitializer())
return AST.initializerToExpression(vd._init);
+ else if (auto ts = vd.type.isTypeStruct())
+ {
+ if (!ts.sym.noDefaultCtor && !ts.sym.isUnionDeclaration())
+ {
+ // Generate a call to the default constructor that we've generated.
+ auto sle = new AST.StructLiteralExp(Loc.initial, ts.sym, new AST.Expressions(0));
+ sle.type = vd.type;
+ return sle;
+ }
+ else
+ return vd.type.defaultInitLiteral(Loc.initial);
+ }
else
return vd.type.defaultInitLiteral(Loc.initial);
}
@@ -2971,6 +2980,7 @@ struct DMDType
__gshared Identifier c_longlong;
__gshared Identifier c_ulonglong;
__gshared Identifier c_long_double;
+ __gshared Identifier c_char;
__gshared Identifier c_wchar_t;
__gshared Identifier c_complex_float;
__gshared Identifier c_complex_double;
@@ -2984,6 +2994,7 @@ struct DMDType
c_ulonglong = Identifier.idPool("__c_ulonglong");
c_long_double = Identifier.idPool("__c_long_double");
c_wchar_t = Identifier.idPool("__c_wchar_t");
+ c_char = Identifier.idPool("__c_char");
c_complex_float = Identifier.idPool("__c_complex_float");
c_complex_double = Identifier.idPool("__c_complex_double");
c_complex_real = Identifier.idPool("__c_complex_real");
diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index be11f26..e9dcdc0 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/dmd/escape.d
@@ -658,7 +658,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
p == fd)
{
if (log) printf("inferring 'return' for parameter %s in function %s\n", v.toChars(), fd.toChars());
- inferReturn(fd, v); // infer addition of 'return' to make `return scope`
+ inferReturn(fd, v, /*returnScope:*/ true); // infer addition of 'return' to make `return scope`
}
if (!(va && va.isScope()) || vaIsRef)
@@ -1215,7 +1215,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
sc.func.flags & FUNCFLAG.returnInprocess &&
p == sc.func)
{
- inferReturn(sc.func, v); // infer addition of 'return'
+ inferReturn(sc.func, v, /*returnScope:*/ true); // infer addition of 'return'
continue;
}
@@ -1355,7 +1355,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
if (sc.func.flags & FUNCFLAG.returnInprocess && p == sc.func &&
(vsr == ScopeRef.Ref || vsr == ScopeRef.RefScope))
{
- inferReturn(sc.func, v); // infer addition of 'return'
+ inferReturn(sc.func, v, /*returnScope:*/ false); // infer addition of 'return'
}
else
{
@@ -1404,23 +1404,25 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
* Params:
* fd = function that v is a parameter to
* v = parameter that needs to be STC.return_
+ * returnScope = infer `return scope` instead of `return ref`
*/
-
-private void inferReturn(FuncDeclaration fd, VarDeclaration v)
+private void inferReturn(FuncDeclaration fd, VarDeclaration v, bool returnScope)
{
// v is a local in the current function
- //printf("for function '%s' inferring 'return' for variable '%s'\n", fd.toChars(), v.toChars());
- v.storage_class |= STC.return_ | STC.returninferred;
+ //printf("for function '%s' inferring 'return' for variable '%s', returnScope: %d\n", fd.toChars(), v.toChars(), returnScope);
+ auto newStcs = STC.return_ | STC.returninferred | (returnScope ? STC.returnScope : 0);
+ v.storage_class |= newStcs;
if (v == fd.vthis)
{
/* v is the 'this' reference, so mark the function
*/
- fd.storage_class |= STC.return_ | STC.returninferred;
+ fd.storage_class |= newStcs;
if (auto tf = fd.type.isTypeFunction())
{
//printf("'this' too %p %s\n", tf, sc.func.toChars());
+ tf.isreturnscope = returnScope;
tf.isreturn = true;
tf.isreturninferred = true;
}
@@ -1434,7 +1436,7 @@ private void inferReturn(FuncDeclaration fd, VarDeclaration v)
{
if (p.ident == v.ident)
{
- p.storageClass |= STC.return_ | STC.returninferred;
+ p.storageClass |= newStcs;
break; // there can be only one
}
}
@@ -1732,33 +1734,69 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false)
{
DotVarExp dve = e.e1.isDotVarExp();
FuncDeclaration fd = dve.var.isFuncDeclaration();
- AggregateDeclaration ad;
- if (global.params.useDIP1000 == FeatureState.enabled && tf.isreturn && fd && (ad = fd.isThis()) !is null)
+ if (global.params.useDIP1000 == FeatureState.enabled)
{
- if (ad.isClassDeclaration() || tf.isScopeQual) // this is 'return scope'
- dve.e1.accept(this);
- else if (ad.isStructDeclaration()) // this is 'return ref'
- {
- if (tf.isref)
+ if (fd && fd.isThis())
+ {
+ /* Calling a non-static member function dve.var, which is returning `this`, and with dve.e1 representing `this`
+ */
+
+ /*****************************
+ * Concoct storage class for member function's implicit `this` parameter.
+ * Params:
+ * fd = member function
+ * Returns:
+ * storage class for fd's `this`
+ */
+ StorageClass getThisStorageClass(FuncDeclaration fd)
{
- /* Treat calling:
- * struct S { ref S foo() return; }
- * as:
- * this;
- */
+ StorageClass stc;
+ auto tf = fd.type.toBasetype().isTypeFunction();
+ if (tf.isreturn)
+ stc |= STC.return_;
+ if (tf.isreturnscope)
+ stc |= STC.returnScope;
+ auto ad = fd.isThis();
+ if (ad.isClassDeclaration() || tf.isScopeQual)
+ stc |= STC.scope_;
+ if (ad.isStructDeclaration())
+ stc |= STC.ref_; // `this` for a struct member function is passed by `ref`
+ return stc;
+ }
+
+ const psr = buildScopeRef(getThisStorageClass(fd));
+ if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
dve.e1.accept(this);
+ else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
+ {
+ if (tf.isref)
+ {
+ /* Treat calling:
+ * struct S { ref S foo() return; }
+ * as:
+ * this;
+ */
+ dve.e1.accept(this);
+ }
+ else
+ escapeByRef(dve.e1, er, live);
}
- else
- escapeByRef(dve.e1, er, live);
}
}
- else if (dve.var.storage_class & STC.return_ || tf.isreturn)
+ else
{
- if (dve.var.storage_class & STC.scope_)
+ // Calling member function before dip1000
+ StorageClass stc = dve.var.storage_class & (STC.return_ | STC.scope_ | STC.ref_);
+ if (tf.isreturn)
+ stc |= STC.return_;
+
+ const psr = buildScopeRef(stc);
+ if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
dve.e1.accept(this);
- else if (dve.var.storage_class & STC.ref_)
+ else if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
escapeByRef(dve.e1, er, live);
}
+
// If it's also a nested function that is 'return scope'
if (fd && fd.isNested())
{
@@ -1996,19 +2034,29 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false)
return;
}
- if (dve.var.storage_class & STC.return_ || tf.isreturn)
- {
- if (dve.var.storage_class & STC.ref_ || tf.isref)
- dve.e1.accept(this);
- else if (dve.var.storage_class & STC.scope_ || tf.isScopeQual)
- escapeByValue(dve.e1, er, live);
- }
+ StorageClass stc = dve.var.storage_class & (STC.return_ | STC.scope_ | STC.ref_);
+ if (tf.isreturn)
+ stc |= STC.return_;
+ if (tf.isref)
+ stc |= STC.ref_;
+ if (tf.isScopeQual)
+ stc |= STC.scope_;
+ if (tf.isreturnscope)
+ stc |= STC.returnScope;
+
+ const psr = buildScopeRef(stc);
+ if (psr == ScopeRef.ReturnRef || psr == ScopeRef.ReturnRef_Scope)
+ dve.e1.accept(this);
+ else if (psr == ScopeRef.ReturnScope || psr == ScopeRef.Ref_ReturnScope)
+ escapeByValue(dve.e1, er, live);
+
// If it's also a nested function that is 'return ref'
- FuncDeclaration fd = dve.var.isFuncDeclaration();
- if (fd && fd.isNested())
+ if (FuncDeclaration fd = dve.var.isFuncDeclaration())
{
- if (tf.isreturn)
+ if (fd.isNested() && tf.isreturn)
+ {
er.byexp.push(e);
+ }
}
}
// If it's a delegate, check it too
diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 45fefc0..7abfe7f 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -1797,7 +1797,7 @@ extern (C++) final class IntegerExp : Expression
{
super(Loc.initial, EXP.int64, __traits(classInstanceSize, IntegerExp));
this.type = Type.tint32;
- this.value = cast(d_int32)value;
+ this.value = cast(int)value;
}
static IntegerExp create(const ref Loc loc, dinteger_t value, Type type)
@@ -1838,8 +1838,8 @@ extern (C++) final class IntegerExp : Expression
const val = normalize(ty, value);
value = val;
return (ty == Tuns64)
- ? real_t(cast(d_uns64)val)
- : real_t(cast(d_int64)val);
+ ? real_t(cast(ulong)val)
+ : real_t(cast(long)val);
}
override real_t toImaginary()
@@ -1895,38 +1895,38 @@ extern (C++) final class IntegerExp : Expression
break;
case Tint8:
- result = cast(d_int8)value;
+ result = cast(byte)value;
break;
case Tchar:
case Tuns8:
- result = cast(d_uns8)value;
+ result = cast(ubyte)value;
break;
case Tint16:
- result = cast(d_int16)value;
+ result = cast(short)value;
break;
case Twchar:
case Tuns16:
- result = cast(d_uns16)value;
+ result = cast(ushort)value;
break;
case Tint32:
- result = cast(d_int32)value;
+ result = cast(int)value;
break;
case Tdchar:
case Tuns32:
- result = cast(d_uns32)value;
+ result = cast(uint)value;
break;
case Tint64:
- result = cast(d_int64)value;
+ result = cast(long)value;
break;
case Tuns64:
- result = cast(d_uns64)value;
+ result = cast(ulong)value;
break;
case Tpointer:
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index f8e5af4..5802816 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/dmd/expressionsem.d
@@ -1992,7 +1992,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
}
else if (p.storageClass & STC.ref_)
{
- if (global.params.rvalueRefParam &&
+ if (global.params.rvalueRefParam == FeatureState.enabled &&
!arg.isLvalue() &&
targ.isCopyable())
{ /* allow rvalues to be passed to ref parameters by copying
@@ -7118,6 +7118,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
+ exp.e1 = exp.e1.arrayFuncConv(sc);
+
Type tb = exp.e1.type.toBasetype();
switch (tb.ty)
{
@@ -7441,6 +7443,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return;
}
+ if (exp.to && !exp.to.isTypeSArray() && !exp.to.isTypeFunction())
+ exp.e1 = exp.e1.arrayFuncConv(sc);
+
// for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
if (exp.e1.op == EXP.type)
exp.e1 = resolveAliasThis(sc, exp.e1);
@@ -10336,7 +10341,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
// Need to divide the result by the stride
// Replace (ptr - ptr) with (ptr - ptr) / stride
- d_int64 stride;
+ long stride;
// make sure pointer types are compatible
if (Expression ex = typeCombine(exp, sc))
@@ -10351,7 +10356,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
e = new IntegerExp(exp.loc, 0, Type.tptrdiff_t);
}
- else if (stride == cast(d_int64)SIZE_INVALID)
+ else if (stride == cast(long)SIZE_INVALID)
e = ErrorExp.get();
else
{
@@ -12575,6 +12580,13 @@ Expression semanticY(DotIdExp exp, Scope* sc, int flag)
Expression e = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
return e;
}
+ else if (sc.flags & SCOPE.Cfile && exp.ident == Id.__sizeof && exp.e1.isStringExp())
+ {
+ // Sizeof string literal includes the terminating 0
+ auto se = exp.e1.isStringExp();
+ Expression e = new IntegerExp(exp.loc, (se.len + 1) * se.sz, Type.tsize_t);
+ return e;
+ }
else
{
if (exp.e1.isTypeExp() || exp.e1.isTemplateExp())
diff --git a/gcc/d/dmd/file_manager.d b/gcc/d/dmd/file_manager.d
index 7e0f404..9ba3807 100644
--- a/gcc/d/dmd/file_manager.d
+++ b/gcc/d/dmd/file_manager.d
@@ -20,38 +20,12 @@ import dmd.identifier;
enum package_d = "package." ~ mars_ext;
enum package_di = "package." ~ hdr_ext;
-extern(C++) struct FileManager
+struct FileManager
{
private StringTable!(FileBuffer*) files;
private __gshared bool initialized = false;
nothrow:
- extern(D) private FileBuffer* readToFileBuffer(const(char)[] filename)
- {
- if (!initialized)
- FileManager._init();
-
- auto readResult = File.read(filename);
- if (readResult.success)
- {
- FileBuffer* fb;
- if (auto val = files.lookup(filename))
- fb = val.value;
-
- if (!fb)
- fb = FileBuffer.create();
-
- fb.data = readResult.extractSlice();
-
- return files.insert(filename, fb) == null ? null : fb;
- }
- else
- {
- return null;
- }
-
- }
-
/********************************************
* Look for the source file if it's different from filename.
* Look for .di, .d, directory, and along global.path.
@@ -63,7 +37,7 @@ nothrow:
* the found file name or
* `null` if it is not different from filename.
*/
- extern(D) static const(char)[] lookForSourceFile(const char[] filename, const char*[] path)
+ static const(char)[] lookForSourceFile(const char[] filename, const char*[] path)
{
//printf("lookForSourceFile(`%.*s`)\n", cast(int)filename.length, filename.ptr);
/* Search along path[] for .di file, then .d file, then .i file, then .c file.
@@ -74,6 +48,9 @@ nothrow:
scope(exit) FileName.free(sdi.ptr);
const sd = FileName.forceExt(filename, mars_ext);
+ // Special file name representing `stdin`, always assume its presence
+ if (sd == "__stdin.d")
+ return sd;
if (FileName.exists(sd) == 1)
return sd;
scope(exit) FileName.free(sd.ptr);
@@ -164,33 +141,35 @@ nothrow:
* Returns: the loaded source file if it was found in memory,
* otherwise `null`
*/
- extern(D) FileBuffer* lookup(FileName filename)
+ const(FileBuffer)* lookup(FileName filename)
{
if (!initialized)
FileManager._init();
- if (auto val = files.lookup(filename.toString))
+ const name = filename.toString;
+ if (auto val = files.lookup(name))
+ return val.value;
+
+ if (name == "__stdin.d")
{
- // There is a chance that the buffer could've been
- // stolen by a reader with extractSlice, so we should
- // try and do our reading logic if that happens.
- if (val !is null && val.value.data !is null)
- {
- return val.value;
- }
+ auto buffer = new FileBuffer(readFromStdin().extractSlice());
+ if (this.files.insert(name, buffer) is null)
+ assert(0, "stdin: Insert after lookup failure should never return `null`");
+ return buffer;
}
- const name = filename.toString;
- auto res = FileName.exists(name);
- if (res == 1)
- return readToFileBuffer(name);
+ if (FileName.exists(name) != 1)
+ return null;
- return null;
- }
+ auto readResult = File.read(name);
+ if (!readResult.success)
+ return null;
- extern(C++) FileBuffer* lookup(const(char)* filename)
- {
- return lookup(FileName(filename.toDString));
+ FileBuffer* fb = new FileBuffer(readResult.extractSlice());
+ if (files.insert(name, fb) is null)
+ assert(0, "Insert after lookup failure should never return `null`");
+
+ return fb;
}
/**
@@ -201,15 +180,15 @@ nothrow:
* Returns: the loaded source file if it was found in memory,
* otherwise `null`
*/
- extern(D) const(char)[][] getLines(FileName file)
+ const(char)[][] getLines(FileName file)
{
if (!initialized)
FileManager._init();
const(char)[][] lines;
- if (FileBuffer* buffer = lookup(file))
+ if (const buffer = lookup(file))
{
- ubyte[] slice = buffer.data[0 .. buffer.data.length];
+ const slice = buffer.data[0 .. buffer.data.length];
size_t start, end;
ubyte c;
for (auto i = 0; i < slice.length; i++)
@@ -260,7 +239,7 @@ nothrow:
*
* Returns: The FileBuffer added, or null
*/
- extern(D) FileBuffer* add(FileName filename, FileBuffer* filebuffer)
+ FileBuffer* add(FileName filename, FileBuffer* filebuffer)
{
if (!initialized)
FileManager._init();
@@ -269,19 +248,10 @@ nothrow:
return val == null ? null : val.value;
}
- extern(C++) FileBuffer* add(const(char)* filename, FileBuffer* filebuffer)
- {
- if (!initialized)
- FileManager._init();
-
- auto val = files.insert(filename.toDString, filebuffer);
- return val == null ? null : val.value;
- }
-
__gshared fileManager = FileManager();
// Initialize the global FileManager singleton
- extern(C++) static __gshared void _init()
+ private void _init()
{
if (!initialized)
{
@@ -295,3 +265,46 @@ nothrow:
files._init();
}
}
+
+private FileBuffer readFromStdin() nothrow
+{
+ import core.stdc.stdio;
+ import dmd.errors;
+ import dmd.root.rmem;
+
+ enum bufIncrement = 128 * 1024;
+ size_t pos = 0;
+ size_t sz = bufIncrement;
+
+ ubyte* buffer = null;
+ for (;;)
+ {
+ buffer = cast(ubyte*)mem.xrealloc(buffer, sz + 4); // +2 for sentinel and +2 for lexer
+
+ // Fill up buffer
+ do
+ {
+ assert(sz > pos);
+ size_t rlen = fread(buffer + pos, 1, sz - pos, stdin);
+ pos += rlen;
+ if (ferror(stdin))
+ {
+ import core.stdc.errno;
+ error(Loc.initial, "cannot read from stdin, errno = %d", errno);
+ fatal();
+ }
+ if (feof(stdin))
+ {
+ // We're done
+ assert(pos < sz + 2);
+ buffer[pos .. pos + 4] = '\0';
+ return FileBuffer(buffer[0 .. pos]);
+ }
+ } while (pos < sz);
+
+ // Buffer full, expand
+ sz += bufIncrement;
+ }
+
+ assert(0);
+}
diff --git a/gcc/d/dmd/file_manager.h b/gcc/d/dmd/file_manager.h
deleted file mode 100644
index 6705f24..0000000
--- a/gcc/d/dmd/file_manager.h
+++ /dev/null
@@ -1,19 +0,0 @@
-
-/* Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * https://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * https://www.boost.org/LICENSE_1_0.txt
- * https://github.com/dlang/dmd/blob/master/src/dmd/file_manager.h
- */
-
-#pragma once
-
-#include "root/file.h"
-
-struct FileManager
-{
- static void _init();
- FileBuffer* lookup(const char* filename);
- FileBuffer* add(const char* filename, FileBuffer* filebuffer);
-};
diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d
index eccd1ee..6697a05 100644
--- a/gcc/d/dmd/globals.d
+++ b/gcc/d/dmd/globals.d
@@ -161,11 +161,11 @@ extern (C++) struct Param
FeatureState dtorFields; // destruct fields of partially constructed objects
// https://issues.dlang.org/show_bug.cgi?id=14246
bool fieldwise; // do struct equality testing field-wise rather than by memcmp()
- bool rvalueRefParam; // allow rvalues to be arguments to ref parameters
- // https://dconf.org/2019/talks/alexandrescu.html
- // https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a
- // https://digitalmars.com/d/archives/digitalmars/D/Binding_rvalues_to_ref_parameters_redux_325087.html
- // Implementation: https://github.com/dlang/dmd/pull/9817
+ FeatureState rvalueRefParam; // allow rvalues to be arguments to ref parameters
+ // https://dconf.org/2019/talks/alexandrescu.html
+ // https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a
+ // https://digitalmars.com/d/archives/digitalmars/D/Binding_rvalues_to_ref_parameters_redux_325087.html
+ // Implementation: https://github.com/dlang/dmd/pull/9817
CppStdRevision cplusplus = CppStdRevision.cpp11; // version of C++ standard to support
@@ -486,15 +486,6 @@ alias dinteger_t = ulong;
alias sinteger_t = long;
alias uinteger_t = ulong;
-alias d_int8 = int8_t;
-alias d_uns8 = uint8_t;
-alias d_int16 = int16_t;
-alias d_uns16 = uint16_t;
-alias d_int32 = int32_t;
-alias d_uns32 = uint32_t;
-alias d_int64 = int64_t;
-alias d_uns64 = uint64_t;
-
version (DMDLIB)
{
version = LocOffset;
diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h
index 49fa5b9..9bbe0c9 100644
--- a/gcc/d/dmd/globals.h
+++ b/gcc/d/dmd/globals.h
@@ -145,7 +145,7 @@ struct Param
FeatureState dtorFields; // destruct fields of partially constructed objects
// https://issues.dlang.org/show_bug.cgi?id=14246
bool fieldwise; // do struct equality testing field-wise rather than by memcmp()
- bool rvalueRefParam; // allow rvalues to be arguments to ref parameters
+ FeatureState rvalueRefParam; // allow rvalues to be arguments to ref parameters
CppStdRevision cplusplus; // version of C++ name mangling to support
bool markdown; // enable Markdown replacements in Ddoc
bool vmarkdown; // list instances of Markdown replacements in Ddoc
@@ -346,15 +346,6 @@ typedef long long sinteger_t;
typedef unsigned long long uinteger_t;
#endif
-typedef int8_t d_int8;
-typedef uint8_t d_uns8;
-typedef int16_t d_int16;
-typedef uint16_t d_uns16;
-typedef int32_t d_int32;
-typedef uint32_t d_uns32;
-typedef int64_t d_int64;
-typedef uint64_t d_uns64;
-
// file location
struct Loc
{
@@ -415,4 +406,12 @@ enum class PINLINE : uint8_t
always // always inline
};
+enum class FileType : uint8_t
+{
+ d, /// normal D source file
+ dhdr, /// D header file (.di)
+ ddoc, /// Ddoc documentation file (.dd)
+ c, /// C source file
+};
+
typedef uinteger_t StorageClass;
diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 6b8ecc5..f2552d4 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/dmd/hdrgen.d
@@ -2843,7 +2843,6 @@ string stcToString(ref StorageClass stc)
SCstring(STC.pure_, Token.toString(TOK.pure_)),
SCstring(STC.ref_, Token.toString(TOK.ref_)),
SCstring(STC.return_, Token.toString(TOK.return_)),
- SCstring(STC.tls, "__thread"),
SCstring(STC.gshared, Token.toString(TOK.gshared)),
SCstring(STC.nogc, "@nogc"),
SCstring(STC.live, "@live"),
diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index 31a44db..2ec75ab 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/dmd/id.d
@@ -123,6 +123,7 @@ immutable Msgtable[] msgtable =
{ "__c_longlong" },
{ "__c_ulonglong" },
{ "__c_long_double" },
+ { "__c_char" },
{ "__c_wchar_t" },
{ "__c_complex_float" },
{ "__c_complex_double" },
@@ -359,6 +360,8 @@ immutable Msgtable[] msgtable =
{ "core" },
{ "etc" },
{ "attribute" },
+ { "atomic" },
+ { "atomicOp" },
{ "math" },
{ "sin" },
{ "cos" },
diff --git a/gcc/d/dmd/importc.d b/gcc/d/dmd/importc.d
index 72e0e1a..ec44ee0 100644
--- a/gcc/d/dmd/importc.d
+++ b/gcc/d/dmd/importc.d
@@ -274,6 +274,7 @@ Expression castCallAmbiguity(Expression e, Scope* sc)
bool cFuncEquivalence(TypeFunction tf1, TypeFunction tf2)
{
+ //printf("cFuncEquivalence()\n %s\n %s\n", tf1.toChars(), tf2.toChars());
if (tf1.equals(tf2))
return true;
@@ -284,22 +285,31 @@ bool cFuncEquivalence(TypeFunction tf1, TypeFunction tf2)
if (tf1.parameterList.length == 0 && tf2.parameterList.length == 0)
return true;
- if (!tf1.parameterList.hasIdentifierList &&
- !tf2.parameterList.hasIdentifierList)
- return false; // both functions are prototyped
-
- // Otherwise ignore variadicness, as K+R functions are all variadic
-
if (!tf1.nextOf().equals(tf2.nextOf()))
return false; // function return types don't match
if (tf1.parameterList.length != tf2.parameterList.length)
return false;
+ if (!tf1.parameterList.hasIdentifierList && !tf2.parameterList.hasIdentifierList) // if both are prototyped
+ {
+ if (tf1.parameterList.varargs != tf2.parameterList.varargs)
+ return false;
+ }
+
foreach (i, fparam ; tf1.parameterList)
{
Type t1 = fparam.type;
Type t2 = tf2.parameterList[i].type;
+
+ /* Strip off head const.
+ * Not sure if this is C11, but other compilers treat
+ * `void fn(int)` and `fn(const int x)`
+ * as equivalent.
+ */
+ t1 = t1.mutableOf();
+ t2 = t2.mutableOf();
+
if (!t1.equals(t2))
return false;
}
diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d
index dbdf6a5..3ff2eae 100644
--- a/gcc/d/dmd/lexer.d
+++ b/gcc/d/dmd/lexer.d
@@ -371,6 +371,12 @@ class Lexer
'd';
return;
}
+ else if (p[1] == '8' && p[2] == '\"') // C UTF-8 string literal
+ {
+ p += 2;
+ escapeStringConstant(t);
+ return;
+ }
goto case_ident;
case 'r':
@@ -1979,8 +1985,8 @@ class Lexer
if (base <= 10 && n > 0 && (isalpha(p[1]) || p[1] == '_' || p[1] & 0x80))
{
if (Ccompile && base == 10 &&
- (p[1] == 'f' || p[1] == 'F' || p[1] == 'l' || p[1] == 'L'))
- goto Lreal; // if `1.f` or `1.L`
+ (p[1] == 'e' || p[1] == 'E' || p[1] == 'f' || p[1] == 'F' || p[1] == 'l' || p[1] == 'L'))
+ goto Lreal; // if `1.e6` or `1.f` or `1.L`
goto Ldone; // if ".identifier" or ".unicode"
}
if (base == 16 && (!ishex(p[1]) || p[1] == '_' || p[1] & 0x80))
@@ -2495,8 +2501,10 @@ class Lexer
}
}
const isLong = (result == TOK.float80Literal || result == TOK.imaginary80Literal);
- if (isOutOfRange && !isLong)
+ if (isOutOfRange && !isLong && (!Ccompile || hex))
{
+ /* C11 6.4.4.2 doesn't actually care if it is not representable if it is not hex
+ */
const char* suffix = (result == TOK.float32Literal || result == TOK.imaginary32Literal) ? "f" : "";
error(scanloc, "number `%s%s` is not representable", sbufptr, suffix);
}
diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h
index f020bfd..048b3a0 100644
--- a/gcc/d/dmd/module.h
+++ b/gcc/d/dmd/module.h
@@ -71,12 +71,10 @@ public:
FileName objfile; // output .obj file
FileName hdrfile; // 'header' file
FileName docfile; // output documentation file
- FileBuffer *srcBuffer; // set during load(), free'd in parse()
+ DArray<unsigned char> src; // Raw content of the file
unsigned errors; // if any errors in file
unsigned numlines; // number of lines in source file
- bool isHdrFile; // if it is a header (.di) file
- bool isCFile; // if it is a C (.c) file
- bool isDocFile; // if it is a documentation input file, not D source
+ FileType filetype; // source file type
bool hasAlwaysInlines; // contains references to functions that must be inlined
bool isPackageFile; // if it is a package.d
Package *pkg; // if isPackageFile is true, the Package that contains this package.d
diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d
index 18af772..1494044 100644
--- a/gcc/d/dmd/mtype.d
+++ b/gcc/d/dmd/mtype.d
@@ -55,7 +55,7 @@ import dmd.visitor;
enum LOGDOTEXP = 0; // log ::dotExp()
enum LOGDEFAULTINIT = 0; // log ::defaultInit()
-enum SIZE_INVALID = (~cast(d_uns64)0); // error return from size() functions
+enum SIZE_INVALID = (~cast(uinteger_t)0); // error return from size() functions
/***************************
@@ -887,12 +887,12 @@ extern (C++) abstract class Type : ASTNode
stringtable = stringtable.init;
}
- final d_uns64 size()
+ final uinteger_t size()
{
return size(Loc.initial);
}
- d_uns64 size(const ref Loc loc)
+ uinteger_t size(const ref Loc loc)
{
error(loc, "no size for type `%s`", toChars());
return SIZE_INVALID;
@@ -2770,7 +2770,7 @@ extern (C++) final class TypeError : Type
return this;
}
- override d_uns64 size(const ref Loc loc)
+ override uinteger_t size(const ref Loc loc)
{
return SIZE_INVALID;
}
@@ -3237,7 +3237,7 @@ extern (C++) final class TypeBasic : Type
return this;
}
- override d_uns64 size(const ref Loc loc) const
+ override uinteger_t size(const ref Loc loc) const
{
uint size;
//printf("TypeBasic::size()\n");
@@ -3411,8 +3411,8 @@ extern (C++) final class TypeBasic : Type
// If converting from integral to integral
if (tob.flags & TFlags.integral)
{
- d_uns64 sz = size(Loc.initial);
- d_uns64 tosz = tob.size(Loc.initial);
+ const sz = size(Loc.initial);
+ const tosz = tob.size(Loc.initial);
/* Can't convert to smaller size
*/
@@ -3512,7 +3512,7 @@ extern (C++) final class TypeVector : Type
return new TypeVector(basetype.syntaxCopy());
}
- override d_uns64 size(const ref Loc loc)
+ override uinteger_t size(const ref Loc loc)
{
return basetype.size();
}
@@ -3661,7 +3661,7 @@ extern (C++) final class TypeSArray : TypeArray
return dim.isIntegerExp() && dim.isIntegerExp().getInteger() == 0;
}
- override d_uns64 size(const ref Loc loc)
+ override uinteger_t size(const ref Loc loc)
{
//printf("TypeSArray::size()\n");
const n = numberOfElems(loc);
@@ -3860,7 +3860,7 @@ extern (C++) final class TypeDArray : TypeArray
return result;
}
- override d_uns64 size(const ref Loc loc) const
+ override uinteger_t size(const ref Loc loc) const
{
//printf("TypeDArray::size()\n");
return target.ptrsize * 2;
@@ -3964,7 +3964,7 @@ extern (C++) final class TypeAArray : TypeArray
return result;
}
- override d_uns64 size(const ref Loc loc) const
+ override uinteger_t size(const ref Loc loc) const
{
return target.ptrsize;
}
@@ -4056,7 +4056,7 @@ extern (C++) final class TypePointer : TypeNext
return result;
}
- override d_uns64 size(const ref Loc loc) const
+ override uinteger_t size(const ref Loc loc) const
{
return target.ptrsize;
}
@@ -4159,7 +4159,7 @@ extern (C++) final class TypeReference : TypeNext
return result;
}
- override d_uns64 size(const ref Loc loc) const
+ override uinteger_t size(const ref Loc loc) const
{
return target.ptrsize;
}
@@ -4596,8 +4596,10 @@ extern (C++) final class TypeFunction : TypeNext
if (global.gag && !global.params.showGaggedErrors)
return null;
// show qualification when toChars() is the same but types are different
- auto at = arg.type.toChars();
- bool qual = !arg.type.equals(par.type) && strcmp(at, par.type.toChars()) == 0;
+ // https://issues.dlang.org/show_bug.cgi?id=19948
+ // when comparing the type with strcmp, we need to drop the qualifier
+ auto at = arg.type.mutableOf().toChars();
+ bool qual = !arg.type.equals(par.type) && strcmp(at, par.type.mutableOf().toChars()) == 0;
if (qual)
at = arg.type.toPrettyChars(true);
OutBuffer buf;
@@ -4845,7 +4847,7 @@ extern (C++) final class TypeFunction : TypeNext
// Need to make this a rvalue through a temporary
m = MATCH.convert;
}
- else if (!global.params.rvalueRefParam ||
+ else if (global.params.rvalueRefParam != FeatureState.enabled ||
p.storageClass & STC.out_ ||
!arg.type.isCopyable()) // can't copy to temp for ref parameter
{
@@ -5328,7 +5330,7 @@ extern (C++) final class TypeDelegate : TypeNext
return t;
}
- override d_uns64 size(const ref Loc loc) const
+ override uinteger_t size(const ref Loc loc) const
{
return target.ptrsize * 2;
}
@@ -5435,7 +5437,7 @@ extern (C++) final class TypeTraits : Type
v.visit(this);
}
- override d_uns64 size(const ref Loc loc)
+ override uinteger_t size(const ref Loc loc)
{
return SIZE_INVALID;
}
@@ -5562,7 +5564,7 @@ extern (C++) abstract class TypeQualified : Type
idents.push(e);
}
- override d_uns64 size(const ref Loc loc)
+ override uinteger_t size(const ref Loc loc)
{
error(this.loc, "size of type `%s` is not known", toChars());
return SIZE_INVALID;
@@ -5717,7 +5719,7 @@ extern (C++) final class TypeTypeof : TypeQualified
return s;
}
- override d_uns64 size(const ref Loc loc)
+ override uinteger_t size(const ref Loc loc)
{
if (exp.type)
return exp.type.size(loc);
@@ -5792,7 +5794,7 @@ extern (C++) final class TypeStruct : Type
return "struct";
}
- override d_uns64 size(const ref Loc loc)
+ override uinteger_t size(const ref Loc loc)
{
return sym.size(loc);
}
@@ -6148,7 +6150,7 @@ extern (C++) final class TypeEnum : Type
return this;
}
- override d_uns64 size(const ref Loc loc)
+ override uinteger_t size(const ref Loc loc)
{
return sym.getMemtype(loc).size(loc);
}
@@ -6315,7 +6317,7 @@ extern (C++) final class TypeClass : Type
return "class";
}
- override d_uns64 size(const ref Loc loc) const
+ override uinteger_t size(const ref Loc loc) const
{
return target.ptrsize;
}
@@ -6718,7 +6720,7 @@ extern (C++) final class TypeNull : Type
return true;
}
- override d_uns64 size(const ref Loc loc) const
+ override uinteger_t size(const ref Loc loc) const
{
return tvoidptr.size(loc);
}
@@ -6777,7 +6779,7 @@ extern (C++) final class TypeNoreturn : Type
return true; // bottom type can be implicitly converted to any other type
}
- override d_uns64 size(const ref Loc loc) const
+ override uinteger_t size(const ref Loc loc) const
{
return 0;
}
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index 3f085b0..07c574d 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -100,7 +100,7 @@ enum class TY : uint8_t
TMAX
};
-#define SIZE_INVALID (~(d_uns64)0) // error return from size() functions
+#define SIZE_INVALID (~(uinteger_t)0) // error return from size() functions
/**
@@ -230,8 +230,8 @@ public:
char *toPrettyChars(bool QualifyTypes = false);
static void _init();
- d_uns64 size();
- virtual d_uns64 size(const Loc &loc);
+ uinteger_t size();
+ virtual uinteger_t size(const Loc &loc);
virtual unsigned alignsize();
Type *trySemantic(const Loc &loc, Scope *sc);
Type *merge2();
@@ -357,7 +357,7 @@ public:
const char *kind();
TypeError *syntaxCopy();
- d_uns64 size(const Loc &loc);
+ uinteger_t size(const Loc &loc);
Expression *defaultInitLiteral(const Loc &loc);
void accept(Visitor *v) { v->visit(this); }
};
@@ -393,7 +393,7 @@ public:
const char *kind();
TypeBasic *syntaxCopy();
- d_uns64 size(const Loc &loc) /*const*/;
+ uinteger_t size(const Loc &loc) /*const*/;
unsigned alignsize();
bool isintegral();
bool isfloating() /*const*/;
@@ -418,7 +418,7 @@ public:
static TypeVector *create(Type *basetype);
const char *kind();
TypeVector *syntaxCopy();
- d_uns64 size(const Loc &loc);
+ uinteger_t size(const Loc &loc);
unsigned alignsize();
bool isintegral();
bool isfloating();
@@ -448,7 +448,7 @@ public:
const char *kind();
TypeSArray *syntaxCopy();
bool isIncomplete();
- d_uns64 size(const Loc &loc);
+ uinteger_t size(const Loc &loc);
unsigned alignsize();
bool isString();
bool isZeroInit(const Loc &loc);
@@ -471,7 +471,7 @@ class TypeDArray : public TypeArray
public:
const char *kind();
TypeDArray *syntaxCopy();
- d_uns64 size(const Loc &loc) /*const*/;
+ uinteger_t size(const Loc &loc) /*const*/;
unsigned alignsize() /*const*/;
bool isString();
bool isZeroInit(const Loc &loc) /*const*/;
@@ -491,7 +491,7 @@ public:
static TypeAArray *create(Type *t, Type *index);
const char *kind();
TypeAArray *syntaxCopy();
- d_uns64 size(const Loc &loc);
+ uinteger_t size(const Loc &loc);
bool isZeroInit(const Loc &loc) /*const*/;
bool isBoolean() /*const*/;
bool hasPointers() /*const*/;
@@ -507,7 +507,7 @@ public:
static TypePointer *create(Type *t);
const char *kind();
TypePointer *syntaxCopy();
- d_uns64 size(const Loc &loc) /*const*/;
+ uinteger_t size(const Loc &loc) /*const*/;
MATCH implicitConvTo(Type *to);
MATCH constConv(Type *to);
bool isscalar() /*const*/;
@@ -522,7 +522,7 @@ class TypeReference : public TypeNext
public:
const char *kind();
TypeReference *syntaxCopy();
- d_uns64 size(const Loc &loc) /*const*/;
+ uinteger_t size(const Loc &loc) /*const*/;
bool isZeroInit(const Loc &loc) /*const*/;
void accept(Visitor *v) { v->visit(this); }
};
@@ -655,7 +655,7 @@ public:
const char *kind();
TypeDelegate *syntaxCopy();
Type *addStorageClass(StorageClass stc);
- d_uns64 size(const Loc &loc) /*const*/;
+ uinteger_t size(const Loc &loc) /*const*/;
unsigned alignsize() /*const*/;
MATCH implicitConvTo(Type *to);
bool isZeroInit(const Loc &loc) /*const*/;
@@ -675,7 +675,7 @@ class TypeTraits : public Type
const char *kind();
TypeTraits *syntaxCopy();
- d_uns64 size(const Loc &loc);
+ uinteger_t size(const Loc &loc);
Dsymbol *toDsymbol(Scope *sc);
void accept(Visitor *v) { v->visit(this); }
};
@@ -704,7 +704,7 @@ public:
void addIdent(Identifier *ident);
void addInst(TemplateInstance *inst);
void addIndex(RootObject *expr);
- d_uns64 size(const Loc &loc);
+ uinteger_t size(const Loc &loc);
void accept(Visitor *v) { v->visit(this); }
};
@@ -744,7 +744,7 @@ public:
const char *kind();
TypeTypeof *syntaxCopy();
Dsymbol *toDsymbol(Scope *sc);
- d_uns64 size(const Loc &loc);
+ uinteger_t size(const Loc &loc);
void accept(Visitor *v) { v->visit(this); }
};
@@ -778,7 +778,7 @@ public:
static TypeStruct *create(StructDeclaration *sym);
const char *kind();
- d_uns64 size(const Loc &loc);
+ uinteger_t size(const Loc &loc);
unsigned alignsize();
TypeStruct *syntaxCopy();
Dsymbol *toDsymbol(Scope *sc);
@@ -808,7 +808,7 @@ public:
const char *kind();
TypeEnum *syntaxCopy();
- d_uns64 size(const Loc &loc);
+ uinteger_t size(const Loc &loc);
unsigned alignsize();
Type *memType(const Loc &loc = Loc());
Dsymbol *toDsymbol(Scope *sc);
@@ -844,7 +844,7 @@ public:
CPPMANGLE cppmangle;
const char *kind();
- d_uns64 size(const Loc &loc) /*const*/;
+ uinteger_t size(const Loc &loc) /*const*/;
TypeClass *syntaxCopy();
Dsymbol *toDsymbol(Scope *sc);
ClassDeclaration *isClassHandle();
@@ -899,7 +899,7 @@ public:
MATCH implicitConvTo(Type *to);
bool isBoolean() /*const*/;
- d_uns64 size(const Loc &loc) /*const*/;
+ uinteger_t size(const Loc &loc) /*const*/;
void accept(Visitor *v) { v->visit(this); }
};
@@ -911,7 +911,7 @@ public:
MATCH implicitConvTo(Type* to);
MATCH constConv(Type* to);
bool isBoolean() /* const */;
- d_uns64 size(const Loc& loc) /* const */;
+ uinteger_t size(const Loc& loc) /* const */;
unsigned alignsize();
void accept(Visitor *v) { v->visit(this); }
diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index cc02bd9..5a86931 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -221,7 +221,7 @@ package void setLengthVarIfKnown(VarDeclaration lengthVar, Expression arr)
return;
if (lengthVar._init && !lengthVar._init.isVoidInitializer())
return; // we have previously calculated the length
- d_uns64 len;
+ dinteger_t len;
if (auto se = arr.isStringExp())
len = se.len;
else if (auto ale = arr.isArrayLiteralExp())
@@ -253,7 +253,7 @@ package void setLengthVarIfKnown(VarDeclaration lengthVar, Type type)
auto tsa = type.toBasetype().isTypeSArray();
if (!tsa)
return; // we don't know the length yet
- d_uns64 len = tsa.dim.toInteger();
+ const len = tsa.dim.toInteger();
Expression dollar = new IntegerExp(Loc.initial, len, Type.tsize_t);
lengthVar._init = new ExpInitializer(Loc.initial, dollar);
lengthVar.storage_class |= STC.static_ | STC.const_;
@@ -809,7 +809,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
if (e.e2.isConst() == 1)
{
sinteger_t i2 = e.e2.toInteger();
- d_uns64 sz = e.e1.type.size(e.e1.loc);
+ uinteger_t sz = e.e1.type.size(e.e1.loc);
assert(sz != SIZE_INVALID);
sz *= 8;
if (i2 < 0 || i2 >= sz)
@@ -895,7 +895,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
if (e.e2.isConst() == 1)
{
sinteger_t i2 = e.e2.toInteger();
- d_uns64 sz = e.e1.type.size(e.e1.loc);
+ uinteger_t sz = e.e1.type.size(e.e1.loc);
assert(sz != SIZE_INVALID);
sz *= 8;
if (i2 < 0 || i2 >= sz)
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 480a96c..f6472bf 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/dmd/parse.d
@@ -30,7 +30,7 @@ import dmd.tokens;
/***********************************************************
*/
-class Parser(AST) : Lexer
+class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
{
AST.ModuleDeclaration* md;
@@ -1263,7 +1263,7 @@ class Parser(AST) : Lexer
}
checkConflictSTCGroup(STC.const_ | STC.immutable_ | STC.manifest);
- checkConflictSTCGroup(STC.gshared | STC.shared_ | STC.tls);
+ checkConflictSTCGroup(STC.gshared | STC.shared_);
checkConflictSTCGroup!true(STC.safeGroup);
return orig;
@@ -9599,5 +9599,3 @@ private bool writeMixin(const(char)[] s, ref Loc loc)
return true;
}
-
-
diff --git a/gcc/d/dmd/root/file.h b/gcc/d/dmd/root/file.h
deleted file mode 100644
index 44ca024..0000000
--- a/gcc/d/dmd/root/file.h
+++ /dev/null
@@ -1,41 +0,0 @@
-
-/* Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * https://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * https://www.boost.org/LICENSE_1_0.txt
- * https://github.com/dlang/dmd/blob/master/src/dmd/root/file.h
- */
-
-#pragma once
-
-#include "array.h"
-#include "filename.h"
-
-struct FileBuffer
-{
- DArray<unsigned char> data;
-
- FileBuffer(const FileBuffer &) /* = delete */;
- ~FileBuffer() { mem.xfree(data.ptr); }
-
- static FileBuffer *create();
-};
-
-struct File
-{
- struct ReadResult
- {
- bool success;
- FileBuffer buffer;
- };
-
- // Read the full content of a file.
- static ReadResult read(const char *name);
-
- // Write a file, returning `true` on success.
- static bool write(const char *name, const void *data, d_size_t size);
-
- // Delete a file.
- static void remove(const char *name);
-};
diff --git a/gcc/d/dmd/root/filename.d b/gcc/d/dmd/root/filename.d
index 292fccf..3b7b75b0 100644
--- a/gcc/d/dmd/root/filename.d
+++ b/gcc/d/dmd/root/filename.d
@@ -36,6 +36,8 @@ version (Windows)
import core.sys.windows.windef;
import core.sys.windows.winnls;
+ import dmd.common.string : extendedPathThen;
+
extern (Windows) DWORD GetFullPathNameW(LPCWSTR, DWORD, LPWSTR, LPWSTR*) nothrow @nogc;
extern (Windows) void SetLastError(DWORD) nothrow @nogc;
extern (C) char* getcwd(char* buffer, size_t maxlen) nothrow;
@@ -855,7 +857,7 @@ nothrow:
}
else version (Windows)
{
- return name.toWStringzThen!((wname)
+ return name.extendedPathThen!((wname)
{
const dw = GetFileAttributesW(&wname[0]);
if (dw == -1)
@@ -1005,7 +1007,7 @@ nothrow:
// Have canonicalize_file_name, which malloc's memory.
// We need a dmd.root.rmem allocation though.
auto path = name.toCStringThen!((n) => canonicalize_file_name(n.ptr));
- scope(exit) .free(path.ptr);
+ scope(exit) .free(path);
if (path !is null)
return xarraydup(path.toDString);
}
@@ -1124,7 +1126,6 @@ version(Windows)
*/
private int _mkdir(const(char)[] path) nothrow
{
- import dmd.common.string : extendedPathThen;
const createRet = path.extendedPathThen!(
p => CreateDirectoryW(&p[0], null /*securityAttributes*/));
// different conventions for CreateDirectory and mkdir
diff --git a/gcc/d/dmd/root/string.d b/gcc/d/dmd/root/string.d
index ec62292..93c596f 100644
--- a/gcc/d/dmd/root/string.d
+++ b/gcc/d/dmd/root/string.d
@@ -201,10 +201,10 @@ int dstrcmp()( scope const char[] s1, scope const char[] s2 ) @trusted
unittest
{
assert(dstrcmp("Fraise", "Fraise") == 0);
- assert(dstrcmp("Baguette", "Croissant") == -1);
- assert(dstrcmp("Croissant", "Baguette") == 1);
+ assert(dstrcmp("Baguette", "Croissant") < 0);
+ assert(dstrcmp("Croissant", "Baguette") > 0);
- static assert(dstrcmp("Baguette", "Croissant") == -1);
+ static assert(dstrcmp("Baguette", "Croissant") < 0);
// UTF-8 decoding for the CT variant
assert(dstrcmp("안녕하세요!", "안녕하세요!") == 0);
diff --git a/gcc/d/dmd/semantic2.d b/gcc/d/dmd/semantic2.d
index 85c4d5b..b9029a1 100644
--- a/gcc/d/dmd/semantic2.d
+++ b/gcc/d/dmd/semantic2.d
@@ -330,11 +330,14 @@ private extern(C++) final class Semantic2Visitor : Visitor
// gets imported, it is unaffected by context.
Scope* sc = Scope.createGlobal(mod); // create root scope
//printf("Module = %p\n", sc.scopesym);
- // Pass 2 semantic routines: do initializers and function bodies
- for (size_t i = 0; i < mod.members.dim; i++)
+ if (mod.members)
{
- Dsymbol s = (*mod.members)[i];
- s.semantic2(sc);
+ // Pass 2 semantic routines: do initializers and function bodies
+ for (size_t i = 0; i < mod.members.dim; i++)
+ {
+ Dsymbol s = (*mod.members)[i];
+ s.semantic2(sc);
+ }
}
if (mod.userAttribDecl)
{
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index b706777..d237caf 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/dmd/semantic3.d
@@ -187,14 +187,17 @@ private extern(C++) final class Semantic3Visitor : Visitor
// gets imported, it is unaffected by context.
Scope* sc = Scope.createGlobal(mod); // create root scope
//printf("Module = %p\n", sc.scopesym);
- // Pass 3 semantic routines: do initializers and function bodies
- for (size_t i = 0; i < mod.members.dim; i++)
+ if (mod.members)
{
- Dsymbol s = (*mod.members)[i];
- //printf("Module %s: %s.semantic3()\n", toChars(), s.toChars());
- s.semantic3(sc);
+ // Pass 3 semantic routines: do initializers and function bodies
+ for (size_t i = 0; i < mod.members.dim; i++)
+ {
+ Dsymbol s = (*mod.members)[i];
+ //printf("Module %s: %s.semantic3()\n", toChars(), s.toChars());
+ s.semantic3(sc);
- mod.runDeferredSemantic2();
+ mod.runDeferredSemantic2();
+ }
}
if (mod.userAttribDecl)
{
@@ -1282,6 +1285,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
if (funcdecl.type == f)
f = cast(TypeFunction)f.copy();
f.isreturn = true;
+ f.isreturnscope = cast(bool) (funcdecl.storage_class & STC.returnScope);
if (funcdecl.storage_class & STC.returninferred)
f.isreturninferred = true;
}
diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index f229918..6ffba68 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/dmd/statementsem.d
@@ -987,18 +987,17 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
if (dim == 2)
{
Parameter p = (*fs.parameters)[0];
- auto var = new VarDeclaration(loc, p.type.mutableOf(), Identifier.generateId("__key"), null);
- var.storage_class |= STC.temp | STC.foreach_;
- if (var.storage_class & (STC.ref_ | STC.out_))
- var.storage_class |= STC.nodtor;
+ fs.key = new VarDeclaration(loc, p.type.mutableOf(), Identifier.generateId("__key"), null);
+ fs.key.storage_class |= STC.temp | STC.foreach_;
+ if (fs.key.isReference())
+ fs.key.storage_class |= STC.nodtor;
- fs.key = var;
if (p.storageClass & STC.ref_)
{
- if (var.type.constConv(p.type) == MATCH.nomatch)
+ if (fs.key.type.constConv(p.type) == MATCH.nomatch)
{
fs.error("key type mismatch, `%s` to `ref %s`",
- var.type.toChars(), p.type.toChars());
+ fs.key.type.toChars(), p.type.toChars());
return retError();
}
}
@@ -1008,7 +1007,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
IntRange dimrange = getIntRange(ta.dim);
// https://issues.dlang.org/show_bug.cgi?id=12504
dimrange.imax = SignExtendedNumber(dimrange.imax.value-1);
- if (!IntRange.fromType(var.type).contains(dimrange))
+ if (!IntRange.fromType(fs.key.type).contains(dimrange))
{
fs.error("index type `%s` cannot cover index range 0..%llu",
p.type.toChars(), ta.dim.toInteger());
@@ -1020,17 +1019,15 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
// Now declare the value
{
Parameter p = (*fs.parameters)[dim - 1];
- auto var = new VarDeclaration(loc, p.type, p.ident, null);
- var.storage_class |= STC.foreach_;
- var.storage_class |= p.storageClass & (STC.scope_ | STC.IOR | STC.TYPECTOR);
- if (var.isReference())
- var.storage_class |= STC.nodtor;
-
- fs.value = var;
- if (var.storage_class & STC.ref_)
+ fs.value = new VarDeclaration(loc, p.type, p.ident, null);
+ fs.value.storage_class |= STC.foreach_;
+ fs.value.storage_class |= p.storageClass & (STC.scope_ | STC.IOR | STC.TYPECTOR);
+ if (fs.value.isReference())
{
+ fs.value.storage_class |= STC.nodtor;
+
if (fs.aggr.checkModifiable(sc2, ModifyFlags.noError) == Modifiable.initialization)
- var.setInCtorOnly = true;
+ fs.value.setInCtorOnly = true;
Type t = tab.nextOf();
if (t.constConv(p.type) == MATCH.nomatch)
@@ -1053,7 +1050,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
*/
auto id = Identifier.generateId("__r");
auto ie = new ExpInitializer(loc, new SliceExp(loc, fs.aggr, null, null));
- const valueIsRef = cast(bool) ((*fs.parameters)[dim - 1].storageClass & STC.ref_);
+ const valueIsRef = (*fs.parameters)[$ - 1].isReference();
VarDeclaration tmp;
if (fs.aggr.op == EXP.arrayLiteral && !valueIsRef)
{
diff --git a/gcc/d/dmd/target.d b/gcc/d/dmd/target.d
index 7b9c454..eb85c67 100644
--- a/gcc/d/dmd/target.d
+++ b/gcc/d/dmd/target.d
@@ -61,7 +61,7 @@ extern (C++) struct Target
import dmd.dscope : Scope;
import dmd.expression : Expression;
import dmd.func : FuncDeclaration;
- import dmd.globals : Loc, d_int64;
+ import dmd.globals : Loc;
import dmd.astenums : LINK, TY;
import dmd.mtype : Type, TypeFunction, TypeTuple;
import dmd.root.ctfloat : real_t;
@@ -125,18 +125,18 @@ extern (C++) struct Target
*/
extern (C++) struct FPTypeProperties(T)
{
- real_t max; /// largest representable value that's not infinity
- real_t min_normal; /// smallest representable normalized value that's not 0
- real_t nan; /// NaN value
- real_t infinity; /// infinity value
- real_t epsilon; /// smallest increment to the value 1
-
- d_int64 dig; /// number of decimal digits of precision
- d_int64 mant_dig; /// number of bits in mantissa
- d_int64 max_exp; /// maximum int value such that 2$(SUPERSCRIPT `max_exp-1`) is representable
- d_int64 min_exp; /// minimum int value such that 2$(SUPERSCRIPT `min_exp-1`) is representable as a normalized value
- d_int64 max_10_exp; /// maximum int value such that 10$(SUPERSCRIPT `max_10_exp` is representable)
- d_int64 min_10_exp; /// minimum int value such that 10$(SUPERSCRIPT `min_10_exp`) is representable as a normalized value
+ real_t max; /// largest representable value that's not infinity
+ real_t min_normal; /// smallest representable normalized value that's not 0
+ real_t nan; /// NaN value
+ real_t infinity; /// infinity value
+ real_t epsilon; /// smallest increment to the value 1
+
+ long dig; /// number of decimal digits of precision
+ long mant_dig; /// number of bits in mantissa
+ long max_exp; /// maximum int value such that 2$(SUPERSCRIPT `max_exp-1`) is representable
+ long min_exp; /// minimum int value such that 2$(SUPERSCRIPT `min_exp-1`) is representable as a normalized value
+ long max_10_exp; /// maximum int value such that 10$(SUPERSCRIPT `max_10_exp` is representable)
+ long min_10_exp; /// minimum int value such that 10$(SUPERSCRIPT `min_10_exp`) is representable as a normalized value
}
FPTypeProperties!float FloatProperties; ///
@@ -245,17 +245,6 @@ extern (C++) struct Target
*/
extern (C++) bool isReturnOnStack(TypeFunction tf, bool needsThis);
- /***
- * Determine the size a value of type `t` will be when it
- * is passed on the function parameter stack.
- * Params:
- * loc = location to use for error messages
- * t = type of parameter
- * Returns:
- * size used on parameter stack
- */
- extern (C++) ulong parameterSize(const ref Loc loc, Type t);
-
/**
* Decides whether an `in` parameter of the specified POD type is to be
* passed by reference or by value. To be used with `-preview=in` only!
diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h
index f3d3859..096c16f 100644
--- a/gcc/d/dmd/target.h
+++ b/gcc/d/dmd/target.h
@@ -175,12 +175,12 @@ struct Target
real_t infinity;
real_t epsilon;
- d_int64 dig;
- d_int64 mant_dig;
- d_int64 max_exp;
- d_int64 min_exp;
- d_int64 max_10_exp;
- d_int64 min_10_exp;
+ int64_t dig;
+ int64_t mant_dig;
+ int64_t max_exp;
+ int64_t min_exp;
+ int64_t max_10_exp;
+ int64_t min_10_exp;
};
FPTypeProperties<float> FloatProperties;
@@ -194,7 +194,6 @@ private:
public:
void _init(const Param& params);
// Type sizes and support.
- void setTriple(const char* _triple);
unsigned alignsize(Type *type);
unsigned fieldalign(Type *type);
Type *va_listType(const Loc &loc, Scope *sc); // get type of va_list
@@ -204,7 +203,6 @@ public:
LINK systemLinkage();
TypeTuple *toArgTypes(Type *t);
bool isReturnOnStack(TypeFunction *tf, bool needsThis);
- d_uns64 parameterSize(const Loc& loc, Type *t);
bool preferPassByRef(Type *t);
Expression *getTargetInfo(const char* name, const Loc& loc);
bool isCalleeDestroyingArgs(TypeFunction* tf);
diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h
index 42517f6..8686376 100644
--- a/gcc/d/dmd/template.h
+++ b/gcc/d/dmd/template.h
@@ -314,3 +314,4 @@ Tuple *isTuple(RootObject *o);
Parameter *isParameter(RootObject *o);
TemplateParameter *isTemplateParameter(RootObject *o);
bool isError(const RootObject *const o);
+void printTemplateStats();
diff --git a/gcc/d/dmd/tokens.d b/gcc/d/dmd/tokens.d
index 6e56eb2..1790996 100644
--- a/gcc/d/dmd/tokens.d
+++ b/gcc/d/dmd/tokens.d
@@ -942,17 +942,17 @@ nothrow:
switch (value)
{
case TOK.int32Literal:
- sprintf(&buffer[0], "%d", cast(d_int32)intvalue);
+ sprintf(&buffer[0], "%d", cast(int)intvalue);
break;
case TOK.uns32Literal:
case TOK.wcharLiteral:
case TOK.dcharLiteral:
case TOK.wchar_tLiteral:
- sprintf(&buffer[0], "%uU", cast(d_uns32)unsvalue);
+ sprintf(&buffer[0], "%uU", cast(uint)unsvalue);
break;
case TOK.charLiteral:
{
- const v = cast(d_int32)intvalue;
+ const v = cast(int)intvalue;
if (v >= ' ' && v <= '~')
sprintf(&buffer[0], "'%c'", v);
else
diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index 6160251..dbdcfd4 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/dmd/traits.d
@@ -166,28 +166,28 @@ shared static this()
/**
* get an array of size_t values that indicate possible pointer words in memory
* if interpreted as the type given as argument
- * Returns: the size of the type in bytes, d_uns64.max on error
+ * Returns: the size of the type in bytes, ulong.max on error
*/
-d_uns64 getTypePointerBitmap(Loc loc, Type t, Array!(d_uns64)* data)
+ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data)
{
- d_uns64 sz;
+ ulong sz;
if (t.ty == Tclass && !(cast(TypeClass)t).sym.isInterfaceDeclaration())
sz = (cast(TypeClass)t).sym.AggregateDeclaration.size(loc);
else
sz = t.size(loc);
if (sz == SIZE_INVALID)
- return d_uns64.max;
+ return ulong.max;
const sz_size_t = Type.tsize_t.size(loc);
if (sz > sz.max - sz_size_t)
{
error(loc, "size overflow for type `%s`", t.toChars());
- return d_uns64.max;
+ return ulong.max;
}
- d_uns64 bitsPerWord = sz_size_t * 8;
- d_uns64 cntptr = (sz + sz_size_t - 1) / sz_size_t;
- d_uns64 cntdata = (cntptr + bitsPerWord - 1) / bitsPerWord;
+ ulong bitsPerWord = sz_size_t * 8;
+ ulong cntptr = (sz + sz_size_t - 1) / sz_size_t;
+ ulong cntdata = (cntptr + bitsPerWord - 1) / bitsPerWord;
data.setDim(cast(size_t)cntdata);
data.zero();
@@ -196,15 +196,15 @@ d_uns64 getTypePointerBitmap(Loc loc, Type t, Array!(d_uns64)* data)
{
alias visit = Visitor.visit;
public:
- extern (D) this(Array!(d_uns64)* _data, d_uns64 _sz_size_t)
+ extern (D) this(Array!(ulong)* _data, ulong _sz_size_t)
{
this.data = _data;
this.sz_size_t = _sz_size_t;
}
- void setpointer(d_uns64 off)
+ void setpointer(ulong off)
{
- d_uns64 ptroff = off / sz_size_t;
+ ulong ptroff = off / sz_size_t;
(*data)[cast(size_t)(ptroff / (8 * sz_size_t))] |= 1L << (ptroff % (8 * sz_size_t));
}
@@ -242,12 +242,12 @@ d_uns64 getTypePointerBitmap(Loc loc, Type t, Array!(d_uns64)* data)
override void visit(TypeSArray t)
{
- d_uns64 arrayoff = offset;
- d_uns64 nextsize = t.next.size();
+ ulong arrayoff = offset;
+ ulong nextsize = t.next.size();
if (nextsize == SIZE_INVALID)
error = true;
- d_uns64 dim = t.dim.toInteger();
- for (d_uns64 i = 0; i < dim; i++)
+ ulong dim = t.dim.toInteger();
+ for (ulong i = 0; i < dim; i++)
{
offset = arrayoff + i * nextsize;
t.next.accept(this);
@@ -340,7 +340,7 @@ d_uns64 getTypePointerBitmap(Loc loc, Type t, Array!(d_uns64)* data)
override void visit(TypeStruct t)
{
- d_uns64 structoff = offset;
+ ulong structoff = offset;
foreach (v; t.sym.fields)
{
offset = structoff + v.offset;
@@ -355,7 +355,7 @@ d_uns64 getTypePointerBitmap(Loc loc, Type t, Array!(d_uns64)* data)
// a "toplevel" class is treated as an instance, while TypeClass fields are treated as references
void visitClass(TypeClass t)
{
- d_uns64 classoff = offset;
+ ulong classoff = offset;
// skip vtable-ptr and monitor
if (t.sym.baseClass)
visitClass(cast(TypeClass)t.sym.baseClass.type);
@@ -367,9 +367,9 @@ d_uns64 getTypePointerBitmap(Loc loc, Type t, Array!(d_uns64)* data)
offset = classoff;
}
- Array!(d_uns64)* data;
- d_uns64 offset;
- d_uns64 sz_size_t;
+ Array!(ulong)* data;
+ ulong offset;
+ ulong sz_size_t;
bool error;
}
@@ -378,7 +378,7 @@ d_uns64 getTypePointerBitmap(Loc loc, Type t, Array!(d_uns64)* data)
pbv.visitClass(cast(TypeClass)t);
else
t.accept(pbv);
- return pbv.error ? d_uns64.max : sz;
+ return pbv.error ? ulong.max : sz;
}
/**
@@ -406,9 +406,9 @@ private Expression pointerBitmap(TraitsExp e)
return ErrorExp.get();
}
- Array!(d_uns64) data;
- d_uns64 sz = getTypePointerBitmap(e.loc, t, &data);
- if (sz == d_uns64.max)
+ Array!(ulong) data;
+ ulong sz = getTypePointerBitmap(e.loc, t, &data);
+ if (sz == ulong.max)
return ErrorExp.get();
auto exps = new Expressions(data.dim + 1);
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index 57188af..e5f839b 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -1304,7 +1304,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
// default arg must be an lvalue
if (isRefOrOut && !isAuto &&
!(global.params.previewIn && (fparam.storageClass & STC.in_)) &&
- !(global.params.rvalueRefParam))
+ global.params.rvalueRefParam != FeatureState.enabled)
e = e.toLvalue(sc, e);
fparam.defaultArg = e;
@@ -1504,16 +1504,6 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
/* Scope attribute is not necessary if the parameter type does not have pointers
*/
- /* Constructors are treated as if they are being returned through the hidden parameter,
- * which is by ref, and the ref there is ignored.
- */
- const returnByRef = tf.isref && !tf.isctor;
- if (!returnByRef && isRefReturnScope(fparam.storageClass))
- {
- /* if `ref return scope`, evaluate to `ref` `return scope`
- */
- fparam.storageClass |= STC.returnScope;
- }
const sr = buildScopeRef(fparam.storageClass);
switch (sr)
{
@@ -1534,17 +1524,6 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
break;
}
- /* now set STC.returnScope based only on tf.isref. This is inconsistent, as mentioned above,
- * but necessary for compatibility for now.
- */
- fparam.storageClass &= ~STC.returnScope;
- if (!tf.isref && isRefReturnScope(fparam.storageClass))
- {
- /* if `ref return scope`, evaluate to `ref` `return scope`
- */
- fparam.storageClass |= STC.returnScope;
- }
-
// Remove redundant storage classes for type, they are already applied
fparam.storageClass &= ~(STC.TYPECTOR);
@@ -2411,7 +2390,7 @@ Expression getProperty(Type t, Scope* scope_, const ref Loc loc, Identifier iden
}
if (ident == Id.__sizeof)
{
- d_uns64 sz = mt.size(loc);
+ const sz = mt.size(loc);
if (sz == SIZE_INVALID)
return ErrorExp.get();
e = new IntegerExp(loc, sz, Type.tsize_t);