diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2022-03-21 16:52:40 +0100 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2022-03-21 19:51:50 +0100 |
commit | fbdaa58162ee4189f441b75170af89215465d189 (patch) | |
tree | 77c5816b721cad2691bea1d228cb5ecc31568f9c /gcc/d | |
parent | 4a3073f04e8b7987ad7bfe1bc23bfeb1d627ee6a (diff) | |
download | gcc-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')
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); |