diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2023-12-07 11:55:12 +0100 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2023-12-11 11:06:23 +0100 |
commit | f9b4dbb8ac75f96c4897ba9aafcaf0bbad4fbe44 (patch) | |
tree | 0cbb768778c3ece2ccdae2f1e34aceb483917c1d /gcc | |
parent | 63194a0e8ede9e15dfa01c6ec7aeea8f7702d3b7 (diff) | |
download | gcc-f9b4dbb8ac75f96c4897ba9aafcaf0bbad4fbe44.zip gcc-f9b4dbb8ac75f96c4897ba9aafcaf0bbad4fbe44.tar.gz gcc-f9b4dbb8ac75f96c4897ba9aafcaf0bbad4fbe44.tar.bz2 |
d: Merge upstream dmd, druntime 2bbf64907c, phobos b64bfbf91
D front-end changes:
- Import dmd v2.106.0.
D runtime changes:
- Import druntime v2.106.0.
Phobos changes:
- Import phobos v2.106.0.
gcc/d/ChangeLog:
* Make-lang.in (D_FRONTEND_OBJS): Rename d/common-string.o to
d/common-smallbuffer.o.
* dmd/MERGE: Merge upstream dmd 2bbf64907c.
* dmd/VERSION: Bump version to v2.106.0.
* modules.cc (layout_moduleinfo_fields): Update for new front-end
interface.
(layout_moduleinfo): Likewise.
libphobos/ChangeLog:
* libdruntime/MERGE: Merge upstream druntime 2bbf64907c.
* src/MERGE: Merge upstream phobos b64bfbf91.
Diffstat (limited to 'gcc')
38 files changed, 453 insertions, 374 deletions
diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in index b3007a9..a0d4d7c 100644 --- a/gcc/d/Make-lang.in +++ b/gcc/d/Make-lang.in @@ -95,7 +95,7 @@ D_FRONTEND_OBJS = \ d/common-bitfields.o \ d/common-file.o \ d/common-outbuffer.o \ - d/common-string.o \ + d/common-smallbuffer.o \ d/compiler.o \ d/cond.o \ d/constfold.o \ diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index aa0062c..5edcee1 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -ff57fec51558013b25cadb7e83da9f4675915d56 +2bbf64907cbbb483d003e0a8fcf8b502e4883799 The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION index 41fdc65..8c95cd0 100644 --- a/gcc/d/dmd/VERSION +++ b/gcc/d/dmd/VERSION @@ -1 +1 @@ -v2.106.0-rc.1 +v2.106.0 diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d index 307bb01..352ca88 100644 --- a/gcc/d/dmd/aggregate.d +++ b/gcc/d/dmd/aggregate.d @@ -178,16 +178,6 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol return sc2; } - override final void setScope(Scope* sc) - { - // Might need a scope to resolve forward references. The check for - // semanticRun prevents unnecessary setting of _scope during deferred - // setScope phases for aggregates which already finished semantic(). - // See https://issues.dlang.org/show_bug.cgi?id=16607 - if (semanticRun < PASS.semanticdone) - ScopeDsymbol.setScope(sc); - } - /*************************************** * Returns: * The total number of fields minus the number of hidden fields. diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h index cd8f1a1..98fa6bd 100644 --- a/gcc/d/dmd/aggregate.h +++ b/gcc/d/dmd/aggregate.h @@ -113,7 +113,6 @@ public: Sizeok sizeok; // set when structsize contains valid data virtual Scope *newScope(Scope *sc); - void setScope(Scope *sc) override final; virtual void finalizeSize() = 0; uinteger_t size(const Loc &loc) override final; bool fill(const Loc &loc, Expressions &elements, bool ctorinit); diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d index 251e2e8..faf0489 100644 --- a/gcc/d/dmd/attrib.d +++ b/gcc/d/dmd/attrib.d @@ -123,19 +123,6 @@ extern (C++) abstract class AttribDeclaration : Dsymbol return sc; } - override void setScope(Scope* sc) - { - Dsymbols* d = include(sc); - //printf("\tAttribDeclaration::setScope '%s', d = %p\n",toChars(), d); - if (d) - { - Scope* sc2 = newScope(sc); - d.foreachDsymbol( s => s.setScope(sc2) ); - if (sc2 != sc) - sc2.pop(); - } - } - override void importAll(Scope* sc) { Dsymbols* d = include(sc); @@ -338,14 +325,6 @@ extern (C++) final class DeprecatedDeclaration : StorageClassDeclaration return scx; } - override void setScope(Scope* sc) - { - //printf("DeprecatedDeclaration::setScope() %p\n", this); - if (decl) - Dsymbol.setScope(sc); // for forward reference - return AttribDeclaration.setScope(sc); - } - override void accept(Visitor v) { v.visit(this); @@ -433,13 +412,6 @@ extern (C++) final class CPPMangleDeclaration : AttribDeclaration sc.aligndecl, sc.inlining); } - override void setScope(Scope* sc) - { - if (decl) - Dsymbol.setScope(sc); // for forward reference - return AttribDeclaration.setScope(sc); - } - override const(char)* toChars() const { return toString().ptr; @@ -703,13 +675,6 @@ extern (C++) final class AnonDeclaration : AttribDeclaration return new AnonDeclaration(loc, isunion, Dsymbol.arraySyntaxCopy(decl)); } - override void setScope(Scope* sc) - { - if (decl) - Dsymbol.setScope(sc); - return AttribDeclaration.setScope(sc); - } - override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion) { //printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", this); @@ -913,11 +878,6 @@ extern (C++) class ConditionalDeclaration : AttribDeclaration } } - override void setScope(Scope* sc) - { - include(sc).foreachDsymbol( s => s.setScope(sc) ); - } - override void accept(Visitor v) { v.visit(this); @@ -983,13 +943,6 @@ extern (C++) final class StaticIfDeclaration : ConditionalDeclaration } } - override void setScope(Scope* sc) - { - // do not evaluate condition before semantic pass - // But do set the scope, in case we need it for forward referencing - Dsymbol.setScope(sc); - } - override void importAll(Scope* sc) { // do not evaluate condition before semantic pass @@ -1104,13 +1057,6 @@ extern (C++) final class StaticForeachDeclaration : AttribDeclaration // change this to give semantics to documentation comments on static foreach declarations } - override void setScope(Scope* sc) - { - // do not evaluate condition before semantic pass - // But do set the scope, in case we need it for forward referencing - Dsymbol.setScope(sc); - } - override void importAll(Scope* sc) { // do not evaluate aggregate before semantic pass @@ -1209,11 +1155,6 @@ extern (C++) final class MixinDeclaration : AttribDeclaration return new MixinDeclaration(loc, Expression.arraySyntaxCopy(exps)); } - override void setScope(Scope* sc) - { - Dsymbol.setScope(sc); - } - override const(char)* kind() const { return "mixin"; @@ -1264,14 +1205,6 @@ extern (C++) final class UserAttributeDeclaration : AttribDeclaration return sc2; } - override void setScope(Scope* sc) - { - //printf("UserAttributeDeclaration::setScope() %p\n", this); - if (decl) - Dsymbol.setScope(sc); // for forward reference of UDAs - return AttribDeclaration.setScope(sc); - } - extern (D) static Expressions* concat(Expressions* udas1, Expressions* udas2) { Expressions* udas; diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h index efea9af..98c5e52 100644 --- a/gcc/d/dmd/attrib.h +++ b/gcc/d/dmd/attrib.h @@ -26,7 +26,6 @@ public: virtual Dsymbols *include(Scope *sc); virtual Scope *newScope(Scope *sc); - void setScope(Scope *sc) override; void importAll(Scope *sc) override; void addComment(const utf8_t *comment) override; const char *kind() const override; @@ -61,7 +60,6 @@ public: DeprecatedDeclaration *syntaxCopy(Dsymbol *s) override; Scope *newScope(Scope *sc) override; - void setScope(Scope *sc) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -84,7 +82,6 @@ public: CPPMangleDeclaration *syntaxCopy(Dsymbol *s) override; Scope *newScope(Scope *sc) override; - void setScope(Scope *sc) override; const char *toChars() const override; void accept(Visitor *v) override { v->visit(this); } }; @@ -135,7 +132,6 @@ public: unsigned anonalignsize; // size of anonymous struct for alignment purposes AnonDeclaration *syntaxCopy(Dsymbol *s) override; - void setScope(Scope *sc) override; void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override; const char *kind() const override; AnonDeclaration *isAnonDeclaration() override { return this; } @@ -163,7 +159,6 @@ public: bool oneMember(Dsymbol **ps, Identifier *ident) override final; Dsymbols *include(Scope *sc) override; void addComment(const utf8_t *comment) override final; - void setScope(Scope *sc) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -176,7 +171,6 @@ public: StaticIfDeclaration *syntaxCopy(Dsymbol *s) override; Dsymbols *include(Scope *sc) override; - void setScope(Scope *sc) override; void importAll(Scope *sc) override; StaticIfDeclaration *isStaticIfDeclaration() override { return this; } const char *kind() const override; @@ -196,7 +190,6 @@ public: bool oneMember(Dsymbol **ps, Identifier *ident) override; Dsymbols *include(Scope *sc) override; void addComment(const utf8_t *comment) override; - void setScope(Scope *sc) override; void importAll(Scope *sc) override; const char *kind() const override; void accept(Visitor *v) override { v->visit(this); } @@ -223,7 +216,6 @@ public: d_bool compiled; MixinDeclaration *syntaxCopy(Dsymbol *s) override; - void setScope(Scope *sc) override; const char *kind() const override; void accept(Visitor *v) override { v->visit(this); } }; @@ -239,7 +231,6 @@ public: UserAttributeDeclaration *syntaxCopy(Dsymbol *s) override; Scope *newScope(Scope *sc) override; - void setScope(Scope *sc) override; Expressions *getAttributes(); const char *kind() const override; void accept(Visitor *v) override { v->visit(this); } diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d index 6730592..5a608a9 100644 --- a/gcc/d/dmd/canthrow.d +++ b/gcc/d/dmd/canthrow.d @@ -22,7 +22,6 @@ import dmd.declaration; import dmd.dsymbol; import dmd.errorsink; import dmd.expression; -import dmd.expressionsem; import dmd.func; import dmd.globals; import dmd.init; @@ -81,6 +80,7 @@ CT canThrow(Expression e, FuncDeclaration func, ErrorSink eSink) if (!f.isDtorDeclaration()) errorSupplementalInferredAttr(f, 10, false, STC.nothrow_); + import dmd.expressionsem : checkOverriddenDtor; f.checkOverriddenDtor(null, e.loc, dd => dd.type.toTypeFunction().isnothrow, "not nothrow"); } else if (func) diff --git a/gcc/d/dmd/common/README.md b/gcc/d/dmd/common/README.md index 853fd4f..ad507c7 100644 --- a/gcc/d/dmd/common/README.md +++ b/gcc/d/dmd/common/README.md @@ -5,4 +5,4 @@ | [bitfields.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/bitfields.d) | Pack multiple boolean fields into bit fields | | [file.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/file.d) | Functions and objects dedicated to file I/O and management | | [outbuffer.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/outbuffer.d) | An expandable buffer in which you can write text or binary data | -| [string.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/string.d) | Common string functions including filename manipulation | +| [string.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/smallbuffer.d) | Common string functions including filename manipulation | diff --git a/gcc/d/dmd/common/file.d b/gcc/d/dmd/common/file.d index 076f357..704110f 100644 --- a/gcc/d/dmd/common/file.d +++ b/gcc/d/dmd/common/file.d @@ -17,13 +17,13 @@ module dmd.common.file; import core.stdc.errno : errno; import core.stdc.stdio : fprintf, remove, rename, stderr; import core.stdc.stdlib : exit; -import core.stdc.string : strerror; +import core.stdc.string : strerror, strlen; import core.sys.windows.winbase; import core.sys.windows.winnt; import core.sys.posix.fcntl; import core.sys.posix.unistd; -import dmd.common.string; +import dmd.common.smallbuffer; nothrow: @@ -129,7 +129,8 @@ struct FileMapping(Datum) enum openFlags = CREATE_ALWAYS; } - handle = filename.asDString.extendedPathThen!(p => CreateFileW(p.ptr, createFileMode, 0, null, openFlags, FILE_ATTRIBUTE_NORMAL, null)); + handle = filename[0 .. strlen(filename)]. + extendedPathThen!(p => CreateFileW(p.ptr, createFileMode, 0, null, openFlags, FILE_ATTRIBUTE_NORMAL, null)); if (handle == invalidHandle) { static if (is(Datum == const)) @@ -312,7 +313,7 @@ struct FileMapping(Datum) else version(Windows) { import core.sys.windows.winbase; - if (deleteme.asDString.extendedPathThen!(p => DeleteFileW(p.ptr)) == 0) + if (deleteme[0 .. strlen(deleteme)].extendedPathThen!(p => DeleteFileW(p.ptr)) == 0) { fprintf(stderr, "DeleteFileW error %d\n", GetLastError()); return false; @@ -447,8 +448,8 @@ struct FileMapping(Datum) else version(Windows) { import core.sys.windows.winbase; - auto r = oldname.asDString.extendedPathThen!( - p1 => filename.asDString.extendedPathThen!(p2 => MoveFileExW(p1.ptr, p2.ptr, MOVEFILE_REPLACE_EXISTING)) + auto r = oldname[0 .. strlen(oldname)].extendedPathThen!( + p1 => filename[0 .. strlen(filename)].extendedPathThen!(p2 => MoveFileExW(p1.ptr, p2.ptr, MOVEFILE_REPLACE_EXISTING)) ); if (r == 0) { @@ -483,7 +484,7 @@ extern(D) static bool writeFile(const(char)* name, const void[] data) nothrow else version (Windows) { DWORD numwritten; // here because of the gotos - const nameStr = name.asDString; + const nameStr = name[0 .. strlen(name)]; // work around Windows file path length limitation // (see documentation for extendedPathThen). HANDLE h = nameStr.extendedPathThen! diff --git a/gcc/d/dmd/common/string.d b/gcc/d/dmd/common/smallbuffer.d index 9453a34..ec0eaae 100644 --- a/gcc/d/dmd/common/string.d +++ b/gcc/d/dmd/common/smallbuffer.d @@ -4,11 +4,11 @@ * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/string.d, common/_string.d) - * Documentation: https://dlang.org/phobos/dmd_common_string.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/string.d + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/smallbuffer.d, common/_smallbuffer.d) + * Documentation: https://dlang.org/phobos/dmd_common_smallbuffer.html + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/smallbuffer */ -module dmd.common.string; +module dmd.common.smallbuffer; nothrow: @@ -107,33 +107,11 @@ unittest } /** -Converts a zero-terminated C string to a D slice. Takes linear time and allocates no memory. - -Params: -stringz = the C string to be converted - -Returns: -a slice comprehending the string. The terminating 0 is not part of the slice. -*/ -auto asDString(C)(C* stringz) pure @nogc nothrow -{ - import core.stdc.string : strlen; - return stringz[0 .. strlen(stringz)]; -} - -/// -unittest -{ - const char* p = "123".ptr; - assert(p.asDString == "123"); -} - -/** (Windows only) Converts a narrow string to a wide string using `buffer` as strorage. Returns a slice managed by `buffer` containing the converted string. The terminating zero is not part of the returned slice, but is guaranteed to follow it. */ -version(Windows) wchar[] toWStringz(const(char)[] narrow, ref SmallBuffer!wchar buffer) nothrow +version(Windows) wchar[] toWStringz(scope const(char)[] narrow, ref SmallBuffer!wchar buffer) nothrow { import core.sys.windows.winnls : MultiByteToWideChar; import dmd.common.file : CodePage; @@ -141,16 +119,17 @@ version(Windows) wchar[] toWStringz(const(char)[] narrow, ref SmallBuffer!wchar if (narrow is null) return null; - const requiredLength = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, cast(int) buffer.length); - if (requiredLength < cast(int) buffer.length) + size_t length; + int i; + while (1) { - buffer[requiredLength] = 0; - return buffer[0 .. requiredLength]; + // https://learn.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-multibytetowidechar + length = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, cast(int) buffer.length); + if (length < buffer.length) + break; + buffer.create(length + 1); + assert(++i == 1); // ensure loop should only execute once or twice } - - buffer.create(requiredLength + 1); - const length = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, requiredLength); - assert(length == requiredLength); buffer[length] = 0; return buffer[0 .. length]; } diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d index ed5f1f8..89a5948 100644 --- a/gcc/d/dmd/cparse.d +++ b/gcc/d/dmd/cparse.d @@ -1890,6 +1890,14 @@ final class CParser(AST) : Parser!AST if (specifier.alignExps) error("no alignment-specifier for typedef declaration"); // C11 6.7.5-2 + if (specifier.vector_size) + { + auto length = new AST.IntegerExp(token.loc, specifier.vector_size / dt.size(), AST.Type.tuns32); + auto tsa = new AST.TypeSArray(dt, length); + dt = new AST.TypeVector(tsa); + specifier.vector_size = 0; // used it up + } + bool isalias = true; if (auto ts = dt.isTypeStruct()) { diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index 14c67f0..bb86b08 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.d @@ -68,7 +68,6 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t) Expression visit(Expression e) { // printf("Expression.implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars()); - if (const match = (sc && sc.flags & SCOPE.Cfile) ? e.cimplicitConvTo(t) : e.implicitConvTo(t)) { // no need for an extra cast when matching is exact @@ -802,8 +801,8 @@ extern(C++) MATCH implicitConvTo(Expression e, Type t) return result; } - else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray)) - { + else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray || typeb.ty == Tpointer)) + { // Tpointer because ImportC eagerly converts Tsarray to Tpointer result = MATCH.exact; // Convert array literal to vector type TypeVector tv = tb.isTypeVector(); @@ -1487,6 +1486,10 @@ MATCH cimplicitConvTo(Expression e, Type t) if (tb.equals(typeb)) return MATCH.exact; + + if (tb.isTypeVector() || typeb.isTypeVector()) + return implicitConvTo(e, t); // permissive checking doesn't apply to vectors + if ((typeb.isintegral() || typeb.isfloating()) && (tb.isintegral() || tb.isfloating())) return MATCH.convert; @@ -2298,9 +2301,10 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null) ae.type = tp; } } - else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray)) + else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray || typeb.ty == Tpointer)) { // Convert array literal to vector type + // The Tpointer case comes from C eagerly converting Tsarray to Tpointer TypeVector tv = tb.isTypeVector(); TypeSArray tbase = tv.basetype.isTypeSArray(); assert(tbase.ty == Tsarray); diff --git a/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d index 797f6ee..5713be1 100644 --- a/gcc/d/dmd/denum.d +++ b/gcc/d/dmd/denum.d @@ -83,13 +83,6 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol return ed; } - override void setScope(Scope* sc) - { - if (semanticRun > PASS.initial) - return; - ScopeDsymbol.setScope(sc); - } - override bool oneMember(Dsymbol* ps, Identifier ident) { if (isAnonymous()) diff --git a/gcc/d/dmd/dimport.d b/gcc/d/dmd/dimport.d index 0132e49..5c01a9f 100644 --- a/gcc/d/dmd/dimport.d +++ b/gcc/d/dmd/dimport.d @@ -305,22 +305,6 @@ extern (C++) final class Import : Dsymbol return this; } - override void setScope(Scope* sc) - { - Dsymbol.setScope(sc); - if (aliasdecls.length) - { - if (!mod) - importAll(sc); - - sc = sc.push(mod); - sc.visibility = visibility; - foreach (ad; aliasdecls) - ad.setScope(sc); - sc = sc.pop(); - } - } - override bool overloadInsert(Dsymbol s) { /* Allow multiple imports with the same package base, but disallow diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d index 5f5de63..d096e43 100644 --- a/gcc/d/dmd/dmodule.d +++ b/gcc/d/dmd/dmodule.d @@ -33,6 +33,7 @@ import dmd.errorsink; import dmd.expression; import dmd.expressionsem; import dmd.file_manager; +import dmd.func; import dmd.globals; import dmd.id; import dmd.identifier; @@ -969,7 +970,7 @@ extern (C++) final class Module : Package * If this works out well, it can be extended to all modules * before any semantic() on any of them. */ - setScope(sc); // remember module scope for semantic + this.setScope(sc); // remember module scope for semantic for (size_t i = 0; i < members.length; i++) { Dsymbol s = (*members)[i]; @@ -1576,3 +1577,36 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod) return buf; } + +/******************************************* + * Look for member of the form: + * const(MemberInfo)[] getMembers(string); + * Returns NULL if not found + */ +extern(C++) FuncDeclaration findGetMembers(ScopeDsymbol dsym) +{ + import dmd.opover : search_function; + Dsymbol s = search_function(dsym, Id.getmembers); + FuncDeclaration fdx = s ? s.isFuncDeclaration() : null; + version (none) + { + // Finish + __gshared TypeFunction tfgetmembers; + if (!tfgetmembers) + { + Scope sc; + sc.eSink = global.errorSink; + auto parameters = new Parameters(); + Parameters* p = new Parameter(STC.in_, Type.tchar.constOf().arrayOf(), null, null); + parameters.push(p); + Type tret = null; + TypeFunction tf = new TypeFunction(parameters, tret, VarArg.none, LINK.d); + tfgetmembers = tf.dsymbolSemantic(Loc.initial, &sc).isTypeFunction(); + } + if (fdx) + fdx = fdx.overloadExactMatch(tfgetmembers); + } + if (fdx && fdx.isVirtual()) + fdx = null; + return fdx; +} diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d index a52745f..8f5a292 100644 --- a/gcc/d/dmd/dsymbol.d +++ b/gcc/d/dmd/dsymbol.d @@ -31,7 +31,6 @@ import dmd.dmodule; import dmd.dversion; import dmd.dscope; import dmd.dstruct; -import dmd.dsymbolsem; import dmd.dtemplate; import dmd.errors; import dmd.expression; @@ -44,11 +43,9 @@ import dmd.lexer; import dmd.location; import dmd.mtype; import dmd.nspace; -import dmd.opover; import dmd.root.aav; import dmd.root.rmem; import dmd.rootobject; -import dmd.root.speller; import dmd.root.string; import dmd.statement; import dmd.staticassert; @@ -386,40 +383,6 @@ extern (C++) class Dsymbol : ASTNode return '`' ~ cstr.toDString() ~ "`\0"; } - final bool checkDeprecated(const ref Loc loc, Scope* sc) - { - if (global.params.useDeprecated == DiagnosticReporting.off) - return false; - if (!this.isDeprecated()) - return false; - // Don't complain if we're inside a deprecated symbol's scope - if (sc.isDeprecated()) - return false; - // Don't complain if we're inside a template constraint - // https://issues.dlang.org/show_bug.cgi?id=21831 - if (sc.flags & SCOPE.constraint) - return false; - - const(char)* message = null; - for (Dsymbol p = this; p; p = p.parent) - { - message = p.depdecl ? p.depdecl.getMessage() : null; - if (message) - break; - } - if (message) - deprecation(loc, "%s `%s` is deprecated - %s", kind, toPrettyChars, message); - else - deprecation(loc, "%s `%s` is deprecated", kind, toPrettyChars); - - if (auto ti = sc.parent ? sc.parent.isInstantiated() : null) - ti.printInstantiationTrace(Classification.deprecation); - else if (auto ti = sc.parent ? sc.parent.isTemplateInstance() : null) - ti.printInstantiationTrace(Classification.deprecation); - - return true; - } - /********************************** * Determine which Module a Dsymbol is in. */ @@ -749,113 +712,10 @@ extern (C++) class Dsymbol : ASTNode return toAlias(); } - /************************************* - * Set scope for future semantic analysis so we can - * deal better with forward references. - */ - void setScope(Scope* sc) - { - //printf("Dsymbol::setScope() %p %s, %p stc = %llx\n", this, toChars(), sc, sc.stc); - if (!sc.nofree) - sc.setNoFree(); // may need it even after semantic() finishes - _scope = sc; - if (sc.depdecl) - depdecl = sc.depdecl; - if (!userAttribDecl) - userAttribDecl = sc.userAttribDecl; - } - void importAll(Scope* sc) { } - extern (D) final Dsymbol search_correct(Identifier ident) - { - /*************************************************** - * Search for symbol with correct spelling. - */ - extern (D) Dsymbol symbol_search_fp(const(char)[] seed, out int cost) - { - /* If not in the lexer's string table, it certainly isn't in the symbol table. - * Doing this first is a lot faster. - */ - if (!seed.length) - return null; - Identifier id = Identifier.lookup(seed); - if (!id) - return null; - cost = 0; // all the same cost - Dsymbol s = this; - Module.clearCache(); - return s.search(Loc.initial, id, IgnoreErrors); - } - - if (global.gag) - return null; // don't do it for speculative compiles; too time consuming - // search for exact name first - if (auto s = this.search(Loc.initial, ident, IgnoreErrors)) - return s; - return speller!symbol_search_fp(ident.toString()); - } - - /*************************************** - * Search for identifier id as a member of `this`. - * `id` may be a template instance. - * - * Params: - * loc = location to print the error messages - * sc = the scope where the symbol is located - * id = the id of the symbol - * flags = the search flags which can be `SearchLocalsOnly` or `IgnorePrivateImports` - * - * Returns: - * symbol found, NULL if not - */ - extern (D) final Dsymbol searchX(const ref Loc loc, Scope* sc, RootObject id, int flags) - { - //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars()); - Dsymbol s = toAlias(); - Dsymbol sm; - if (Declaration d = s.isDeclaration()) - { - if (d.inuse) - { - .error(loc, "circular reference to `%s`", d.toPrettyChars()); - return null; - } - } - switch (id.dyncast()) - { - case DYNCAST.identifier: - sm = s.search(loc, cast(Identifier)id, flags); - break; - case DYNCAST.dsymbol: - { - // It's a template instance - //printf("\ttemplate instance id\n"); - Dsymbol st = cast(Dsymbol)id; - TemplateInstance ti = st.isTemplateInstance(); - sm = s.search(loc, ti.name); - if (!sm) - return null; - sm = sm.toAlias(); - TemplateDeclaration td = sm.isTemplateDeclaration(); - if (!td) - return null; // error but handled later - ti.tempdecl = td; - if (!ti.semanticRun) - ti.dsymbolSemantic(sc); - sm = ti.toAlias(); - break; - } - case DYNCAST.type: - case DYNCAST.expression: - default: - assert(0); - } - return sm; - } - bool overloadInsert(Dsymbol s) { //printf("Dsymbol::overloadInsert('%s')\n", s.toChars()); @@ -1468,38 +1328,6 @@ public: return "ScopeDsymbol"; } - /******************************************* - * Look for member of the form: - * const(MemberInfo)[] getMembers(string); - * Returns NULL if not found - */ - final FuncDeclaration findGetMembers() - { - Dsymbol s = search_function(this, Id.getmembers); - FuncDeclaration fdx = s ? s.isFuncDeclaration() : null; - version (none) - { - // Finish - __gshared TypeFunction tfgetmembers; - if (!tfgetmembers) - { - Scope sc; - sc.eSink = global.errorSink; - auto parameters = new Parameters(); - Parameters* p = new Parameter(STC.in_, Type.tchar.constOf().arrayOf(), null, null); - parameters.push(p); - Type tret = null; - TypeFunction tf = new TypeFunction(parameters, tret, VarArg.none, LINK.d); - tfgetmembers = tf.dsymbolSemantic(Loc.initial, &sc).isTypeFunction(); - } - if (fdx) - fdx = fdx.overloadExactMatch(tfgetmembers); - } - if (fdx && fdx.isVirtual()) - fdx = null; - return fdx; - } - /******************************** * Insert Dsymbol in table. * Params: diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h index e0c2046..15c9970 100644 --- a/gcc/d/dmd/dsymbol.h +++ b/gcc/d/dmd/dsymbol.h @@ -205,7 +205,6 @@ public: const char *locToChars(); bool equals(const RootObject * const o) const override; bool isAnonymous() const; - bool checkDeprecated(const Loc &loc, Scope *sc); Module *getModule(); bool isCsymbol(); Module *getAccessModule(); @@ -228,7 +227,6 @@ public: virtual const char *kind() const; virtual Dsymbol *toAlias(); // resolve real symbol virtual Dsymbol *toAlias2(); - virtual void setScope(Scope *sc); virtual void importAll(Scope *sc); virtual bool overloadInsert(Dsymbol *s); virtual uinteger_t size(const Loc &loc); @@ -342,7 +340,6 @@ public: bool isforwardRef() override final; static void multiplyDefined(const Loc &loc, Dsymbol *s1, Dsymbol *s2); const char *kind() const override; - FuncDeclaration *findGetMembers(); virtual Dsymbol *symtabInsert(Dsymbol *s); virtual Dsymbol *symtabLookup(Dsymbol *s, Identifier *id); bool hasStaticCtorOrDtor() override; @@ -431,3 +428,5 @@ public: void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds); Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); +bool checkDeprecated(Dsymbol *d, const Loc &loc, Scope *sc); +void setScope(Dsymbol *d, Scope *sc); diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index 430377f..060abfe 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -212,6 +212,39 @@ const(char)* getMessage(DeprecatedDeclaration dd) return dd.msgstr; } +bool checkDeprecated(Dsymbol d, const ref Loc loc, Scope* sc) +{ + if (global.params.useDeprecated == DiagnosticReporting.off) + return false; + if (!d.isDeprecated()) + return false; + // Don't complain if we're inside a deprecated symbol's scope + if (sc.isDeprecated()) + return false; + // Don't complain if we're inside a template constraint + // https://issues.dlang.org/show_bug.cgi?id=21831 + if (sc.flags & SCOPE.constraint) + return false; + + const(char)* message = null; + for (Dsymbol p = d; p; p = p.parent) + { + message = p.depdecl ? p.depdecl.getMessage() : null; + if (message) + break; + } + if (message) + deprecation(loc, "%s `%s` is deprecated - %s", d.kind, d.toPrettyChars, message); + else + deprecation(loc, "%s `%s` is deprecated", d.kind, d.toPrettyChars); + + if (auto ti = sc.parent ? sc.parent.isInstantiated() : null) + ti.printInstantiationTrace(Classification.deprecation); + else if (auto ti = sc.parent ? sc.parent.isTemplateInstance() : null) + ti.printInstantiationTrace(Classification.deprecation); + + return true; +} // Returns true if a contract can appear without a function body. package bool allowsContractWithoutBody(FuncDeclaration funcdecl) @@ -7811,6 +7844,37 @@ extern(C++) Dsymbol search(Dsymbol d, const ref Loc loc, Identifier ident, int f return v.result; } +Dsymbol search_correct(Dsymbol d, Identifier ident) +{ + /*************************************************** + * Search for symbol with correct spelling. + */ + Dsymbol symbol_search_fp(const(char)[] seed, out int cost) + { + /* If not in the lexer's string table, it certainly isn't in the symbol table. + * Doing this first is a lot faster. + */ + if (!seed.length) + return null; + Identifier id = Identifier.lookup(seed); + if (!id) + return null; + cost = 0; // all the same cost + Dsymbol s = d; + Module.clearCache(); + return s.search(Loc.initial, id, IgnoreErrors); + } + + if (global.gag) + return null; // don't do it for speculative compiles; too time consuming + // search for exact name first + if (auto s = d.search(Loc.initial, ident, IgnoreErrors)) + return s; + + import dmd.root.speller : speller; + return speller!symbol_search_fp(ident.toString()); +} + private extern(C++) class SearchVisitor : Visitor { alias visit = Visitor.visit; @@ -8407,3 +8471,153 @@ private extern(C++) class SearchVisitor : Visitor return setResult(s); } } +/************************************* + * Set scope for future semantic analysis so we can + * deal better with forward references. + * + * Params: + * d = dsymbol for which the scope is set + * sc = scope that is used to set the value + */ +extern(C++) void setScope(Dsymbol d, Scope* sc) +{ + scope setScopeVisitor = new SetScopeVisitor(sc); + d.accept(setScopeVisitor); +} + +private extern(C++) class SetScopeVisitor : Visitor +{ + alias visit = typeof(super).visit; + Scope* sc; + + this(Scope* sc) + { + this.sc = sc; + } + + override void visit(Dsymbol d) + { + //printf("Dsymbol::setScope() %p %s, %p stc = %llx\n", d, d.toChars(), sc, sc.stc); + if (!sc.nofree) + sc.setNoFree(); // may need it even after semantic() finishes + d._scope = sc; + if (sc.depdecl) + d.depdecl = sc.depdecl; + if (!d.userAttribDecl) + d.userAttribDecl = sc.userAttribDecl; + } + + override void visit(Import i) + { + visit(cast(Dsymbol)i); + if (i.aliasdecls.length) + { + if (!i.mod) + i.importAll(sc); + + sc = sc.push(i.mod); + sc.visibility = i.visibility; + foreach (ad; i.aliasdecls) + ad.setScope(sc); + sc = sc.pop(); + } + } + + override void visit(Nspace ns) + { + visit(cast(Dsymbol)ns); + if (ns.members) + { + assert(sc); + sc = sc.push(ns); + sc.linkage = LINK.cpp; // namespaces default to C++ linkage + sc.parent = ns; + ns.members.foreachDsymbol(s => s.setScope(sc)); + sc.pop(); + } + } + + override void visit(EnumDeclaration ed) + { + if (ed.semanticRun > PASS.initial) + return; + visit(cast(Dsymbol)ed); + } + + override void visit(AggregateDeclaration ad) + { + // Might need a scope to resolve forward references. The check for + // semanticRun prevents unnecessary setting of _scope during deferred + // setScope phases for aggregates which already finished semantic(). + // See https://issues.dlang.org/show_bug.cgi?id=16607 + if (ad.semanticRun < PASS.semanticdone) + visit(cast(Dsymbol)ad); + } + + override void visit(AttribDeclaration atr) + { + Dsymbols* d = atr.include(sc); + //printf("\tAttribDeclaration::setScope '%s', d = %p\n",toChars(), d); + if (d) + { + Scope* sc2 = atr.newScope(sc); + d.foreachDsymbol( s => s.setScope(sc2) ); + if (sc2 != sc) + sc2.pop(); + } + } + + override void visit(DeprecatedDeclaration dd) + { + //printf("DeprecatedDeclaration::setScope() %p\n", this); + if (dd.decl) + visit(cast(Dsymbol)dd); // for forward reference + visit(cast(AttribDeclaration)dd); + } + + override void visit(CPPMangleDeclaration cppmd) + { + if (cppmd.decl) + visit(cast(Dsymbol)cppmd); // for forward reference + visit(cast(AttribDeclaration)cppmd); + } + + override void visit(AnonDeclaration anond) + { + if (anond.decl) + visit(cast(Dsymbol)anond); // for forward reference + visit(cast(AttribDeclaration)anond); + } + + override void visit(ConditionalDeclaration condd) + { + condd.include(sc).foreachDsymbol( s => s.setScope(sc) ); + } + + override void visit(StaticIfDeclaration sid) + { + // do not evaluate condition before semantic pass + // But do set the scope, in case we need it for forward referencing + visit(cast(Dsymbol)sid); // for forward reference + } + + override void visit(StaticForeachDeclaration sfd) + { + // do not evaluate condition before semantic pass + // But do set the scope, in case we need it for forward referencing + visit(cast(Dsymbol)sfd); // for forward reference + } + + override void visit(MixinDeclaration md) + { + visit(cast(Dsymbol)md); + } + + override void visit(UserAttributeDeclaration uad) + { + //printf("UserAttributeDeclaration::setScope() %p\n", this); + if (uad.decl) + visit(cast(Dsymbol)uad); + visit(cast(AttribDeclaration)uad); + } +} diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d index 037e0d0..326d663 100644 --- a/gcc/d/dmd/dtemplate.d +++ b/gcc/d/dmd/dtemplate.d @@ -7515,7 +7515,12 @@ extern (C++) class TemplateInstance : ScopeDsymbol } //printf("\t-. mi = %s\n", mi.toPrettyChars()); - assert(!memberOf || (!memberOf.isRoot() && mi.isRoot()), "can only re-append from non-root to root module"); + if (memberOf) // already appended to some module + { + assert(mi.isRoot(), "can only re-append to a root module"); + if (memberOf.isRoot()) + return null; // no need to move to another root module + } Dsymbols* a = mi.members; a.push(this); diff --git a/gcc/d/dmd/enum.h b/gcc/d/dmd/enum.h index e17e8cf..5f91ead 100644 --- a/gcc/d/dmd/enum.h +++ b/gcc/d/dmd/enum.h @@ -46,7 +46,6 @@ public: bool inuse(bool v); EnumDeclaration *syntaxCopy(Dsymbol *s) override; - void setScope(Scope *sc) override; bool oneMember(Dsymbol **ps, Identifier *ident) override; Type *getType() override; const char *kind() const override; diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d index e25fc84..f928b08 100644 --- a/gcc/d/dmd/escape.d +++ b/gcc/d/dmd/escape.d @@ -2343,7 +2343,7 @@ void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f) VarDeclaration[10] tmp = void; size_t dim = (funcdecl.vthis !is null) + (funcdecl.parameters ? funcdecl.parameters.length : 0); - import dmd.common.string : SmallBuffer; + import dmd.common.smallbuffer : SmallBuffer; auto sb = SmallBuffer!VarDeclaration(dim, tmp[]); VarDeclaration[] array = sb[]; diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index e6b9018..1664bf2 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -4387,7 +4387,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor auto e = initializerToExpression(init, t, (sc.flags & SCOPE.Cfile) != 0); if (!e) { - error(cle.loc, "cannot convert initializer `%s` to expression", init.toChars()); + error(cle.loc, "cannot convert initializer `%s` to expression", toChars(init)); return setError(); } result = e; diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d index ac2dda3..0944ade 100644 --- a/gcc/d/dmd/hdrgen.d +++ b/gcc/d/dmd/hdrgen.d @@ -1968,6 +1968,10 @@ private void visitVarDecl(VarDeclaration v, bool anywritten, ref OutBuffer buf, v._init.initializerToBuffer(buf, &hgs); } + const commentIt = hgs.importcHdr && isSpecialCName(v.ident); + if (commentIt) + buf.writestring("/+"); + if (anywritten) { buf.writestring(", "); @@ -2000,8 +2004,31 @@ private void visitVarDecl(VarDeclaration v, bool anywritten, ref OutBuffer buf, buf.writestring(" = "); vinit(v); } + if (commentIt) + buf.writestring("+/"); } +/************************************* + * The names __DATE__, __TIME__,__EOF__, __VENDOR__, __TIMESTAMP__, __VERSION__ + * are special to the D lexer and cannot be used as D source variable names. + * Params: + * id = name to check + * Returns: + * true if special C name + */ +private bool isSpecialCName(Identifier id) +{ + auto s = id.toString(); + if (s.length >= 7 && s[0] == '_' && s[1] == '_' && + (id == Id.DATE || + id == Id.TIME || + id == Id.EOFX || + id == Id.VENDOR || + id == Id.TIMESTAMP || + id == Id.VERSIONX)) + return true; + return false; +} /********************************************* * Print expression to buffer. diff --git a/gcc/d/dmd/import.h b/gcc/d/dmd/import.h index aeb3621..624cd74 100644 --- a/gcc/d/dmd/import.h +++ b/gcc/d/dmd/import.h @@ -43,7 +43,6 @@ public: Import *syntaxCopy(Dsymbol *s) override; // copy only syntax trees void importAll(Scope *sc) override; Dsymbol *toAlias() override; - void setScope(Scope* sc) override; bool overloadInsert(Dsymbol *s) override; Import *isImport() override { return this; } diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d index 76c2d89..6d31f95 100644 --- a/gcc/d/dmd/initsem.d +++ b/gcc/d/dmd/initsem.d @@ -199,7 +199,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ uint length; const(uint) amax = 0x80000000; bool errors = false; - //printf("ArrayInitializer::semantic(%s), ai: %s %p\n", t.toChars(), i.toChars(), i); + //printf("ArrayInitializer::semantic(%s), ai: %s\n", t.toChars(), toChars(i)); if (i.sem) // if semantic() already run { return i; @@ -600,7 +600,17 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ Initializer visitC(CInitializer ci) { - //printf("CInitializer::semantic() tx: %s t: %s ci: %s\n", (tx ? tx.toChars() : "".ptr), t.toChars(), ci.toChars()); + //printf("CInitializer::semantic() tx: %s t: %s ci: %s\n", (tx ? tx.toChars() : "".ptr), t.toChars(), toChars(ci)); + static if (0) + if (auto ts = tx.isTypeStruct()) + { + import dmd.common.outbuffer; + OutBuffer buf; + HdrGenStage hgs; + toCBuffer(ts.sym, buf, hgs); + printf("%s\n", buf.peekChars()); + } + /* Rewrite CInitializer into ExpInitializer, ArrayInitializer, or StructInitializer */ t = t.toBasetype(); @@ -794,6 +804,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ for (size_t index = 0; index < ci.initializerList.length; ) { CInitializer cprev; + size_t indexprev; L1: DesigInit di = ci.initializerList[index]; Designators* dlist = di.designatorList; @@ -827,6 +838,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ /* The peeling didn't work, so unpeel it */ ci = cprev; + index = indexprev; di = ci.initializerList[index]; goto L2; } @@ -837,12 +849,14 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ { if (fieldi == nfields) break; - if (index == 0 && ci.initializerList.length == 1 && di.initializer.isCInitializer()) + if (/*index == 0 && ci.initializerList.length == 1 &&*/ di.initializer.isCInitializer()) { /* Try peeling off this set of { } and see if it works */ cprev = ci; ci = di.initializer.isCInitializer(); + indexprev = index; + index = 0; goto L1; } diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h index 92efc16..cab0b0a 100644 --- a/gcc/d/dmd/module.h +++ b/gcc/d/dmd/module.h @@ -169,3 +169,4 @@ struct ModuleDeclaration }; extern void getLocalClasses(Module* mod, Array<ClassDeclaration* >& aclasses); +FuncDeclaration *findGetMembers(ScopeDsymbol *dsym); diff --git a/gcc/d/dmd/nspace.d b/gcc/d/dmd/nspace.d index a49e0bf..22c6e63 100644 --- a/gcc/d/dmd/nspace.d +++ b/gcc/d/dmd/nspace.d @@ -85,20 +85,6 @@ extern (C++) final class Nspace : ScopeDsymbol return ns; } - override void setScope(Scope* sc) - { - ScopeDsymbol.setScope(sc); - if (members) - { - assert(sc); - sc = sc.push(this); - sc.linkage = LINK.cpp; // namespaces default to C++ linkage - sc.parent = this; - members.foreachDsymbol(s => s.setScope(sc)); - sc.pop(); - } - } - override bool hasPointers() { //printf("Nspace::hasPointers() %s\n", toChars()); diff --git a/gcc/d/dmd/nspace.h b/gcc/d/dmd/nspace.h index 7d30402..701cc93 100644 --- a/gcc/d/dmd/nspace.h +++ b/gcc/d/dmd/nspace.h @@ -21,7 +21,6 @@ class Nspace final : public ScopeDsymbol public: Expression *identExp; Nspace *syntaxCopy(Dsymbol *s) override; - void setScope(Scope *sc) override; bool hasPointers() override; void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override; const char *kind() const override; diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index f9d174a..b6f30b9 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -8428,7 +8428,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer AST.TemplateParameters* tpl = null; nextToken(); - if (token.value == TOK.leftParenthesis) + if (token.value != TOK.leftParenthesis) + { + error("expected `(` following `is`, not `%s`", token.toChars()); + goto Lerr; + } + else { nextToken(); if (token.value == TOK.identifier && peekNext() == TOK.leftParenthesis) @@ -8476,11 +8481,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer else check(TOK.rightParenthesis); } - else - { - error("`type identifier : specialization` expected following `is`"); - goto Lerr; - } e = new AST.IsExp(loc, targ, ident, tok, tspec, tok2, tpl); break; } diff --git a/gcc/d/dmd/root/file.d b/gcc/d/dmd/root/file.d index 1fb1056..fdf13d4 100644 --- a/gcc/d/dmd/root/file.d +++ b/gcc/d/dmd/root/file.d @@ -24,7 +24,7 @@ import dmd.root.rmem; import dmd.root.string; import dmd.common.file; -import dmd.common.string; +import dmd.common.smallbuffer; nothrow: diff --git a/gcc/d/dmd/root/filename.d b/gcc/d/dmd/root/filename.d index 631c08c..8f31f21 100644 --- a/gcc/d/dmd/root/filename.d +++ b/gcc/d/dmd/root/filename.d @@ -37,7 +37,7 @@ version (Windows) import core.sys.windows.windef; import core.sys.windows.winnls; - import dmd.common.string : extendedPathThen; + import dmd.common.smallbuffer : extendedPathThen; extern (Windows) DWORD GetFullPathNameW(LPCWSTR, DWORD, LPWSTR, LPWSTR*) nothrow @nogc; extern (Windows) void SetLastError(DWORD) nothrow @nogc; @@ -1177,7 +1177,7 @@ version(Windows) */ private auto toWStringzThen(alias F)(const(char)[] str) nothrow { - import dmd.common.string : SmallBuffer, toWStringz; + import dmd.common.smallbuffer : SmallBuffer, toWStringz; if (!str.length) return F(""w.ptr); diff --git a/gcc/d/dmd/root/speller.d b/gcc/d/dmd/root/speller.d index b646bdd..7ad08b7 100644 --- a/gcc/d/dmd/root/speller.d +++ b/gcc/d/dmd/root/speller.d @@ -42,7 +42,7 @@ private: import core.stdc.stdlib; import core.stdc.string; -import dmd.common.string : SmallBuffer; +import dmd.common.smallbuffer : SmallBuffer; enum isSearchFunction(alias fun) = is(searchFunctionType!fun); alias searchFunctionType(alias fun) = typeof(() {int x; return fun("", x);}()); diff --git a/gcc/d/dmd/root/string.d b/gcc/d/dmd/root/string.d index 8b204ab..5ee81a9 100644 --- a/gcc/d/dmd/root/string.d +++ b/gcc/d/dmd/root/string.d @@ -69,7 +69,7 @@ The return value of `T` auto toCStringThen(alias dg)(const(char)[] src) nothrow { import dmd.root.rmem : mem; - import dmd.common.string : SmallBuffer; + import dmd.common.smallbuffer : SmallBuffer; const len = src.length + 1; char[512] small = void; diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index 8795002..2063a95 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -372,6 +372,64 @@ private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymb pt = t.merge(); } +/*************************************** + * Search for identifier id as a member of `this`. + * `id` may be a template instance. + * + * Params: + * loc = location to print the error messages + * sc = the scope where the symbol is located + * id = the id of the symbol + * flags = the search flags which can be `SearchLocalsOnly` or `IgnorePrivateImports` + * + * Returns: + * symbol found, NULL if not + */ +private Dsymbol searchX(Dsymbol dsym, const ref Loc loc, Scope* sc, RootObject id, int flags) +{ + //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars()); + Dsymbol s = dsym.toAlias(); + Dsymbol sm; + if (Declaration d = s.isDeclaration()) + { + if (d.inuse) + { + .error(loc, "circular reference to `%s`", d.toPrettyChars()); + return null; + } + } + switch (id.dyncast()) + { + case DYNCAST.identifier: + sm = s.search(loc, cast(Identifier)id, flags); + break; + case DYNCAST.dsymbol: + { + // It's a template instance + //printf("\ttemplate instance id\n"); + Dsymbol st = cast(Dsymbol)id; + TemplateInstance ti = st.isTemplateInstance(); + sm = s.search(loc, ti.name); + if (!sm) + return null; + sm = sm.toAlias(); + TemplateDeclaration td = sm.isTemplateDeclaration(); + if (!td) + return null; // error but handled later + ti.tempdecl = td; + if (!ti.semanticRun) + ti.dsymbolSemantic(sc); + sm = ti.toAlias(); + break; + } + case DYNCAST.type: + case DYNCAST.expression: + default: + assert(0); + } + return sm; +} + /****************************************** * We've mistakenly parsed `t` as a type. * Redo `t` as an Expression only if there are no type modifiers. diff --git a/gcc/d/modules.cc b/gcc/d/modules.cc index e3c1ef9..250743e 100644 --- a/gcc/d/modules.cc +++ b/gcc/d/modules.cc @@ -503,7 +503,7 @@ layout_moduleinfo_fields (Module *decl, tree type) if (decl->sshareddtor) layout_moduleinfo_field (ptr_type_node, type, offset); - if (decl->findGetMembers ()) + if (findGetMembers (decl)) layout_moduleinfo_field (ptr_type_node, type, offset); if (decl->sictor) @@ -571,7 +571,7 @@ layout_moduleinfo (Module *decl) aimports_dim--; } - sgetmembers = decl->findGetMembers (); + sgetmembers = findGetMembers (decl); size_t flags = 0; if (decl->sctor) diff --git a/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d b/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d index 9de436b..a170b77 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d +++ b/gcc/testsuite/gdc.test/fail_compilation/misc_parser_err_cov1.d @@ -7,7 +7,7 @@ fail_compilation/misc_parser_err_cov1.d(30): Error: basic type expected, not `)` fail_compilation/misc_parser_err_cov1.d(31): Error: `__traits(identifier, args...)` expected fail_compilation/misc_parser_err_cov1.d(31): Error: semicolon expected following auto declaration, not `o` fail_compilation/misc_parser_err_cov1.d(31): Error: expression expected, not `)` -fail_compilation/misc_parser_err_cov1.d(32): Error: `type identifier : specialization` expected following `is` +fail_compilation/misc_parser_err_cov1.d(32): Error: expected `(` following `is`, not `;` fail_compilation/misc_parser_err_cov1.d(33): Error: semicolon expected following auto declaration, not `auto` fail_compilation/misc_parser_err_cov1.d(33): Error: found `+` when expecting `(` following `mixin` fail_compilation/misc_parser_err_cov1.d(35): Error: `key:value` expected for associative array literal diff --git a/gcc/testsuite/gdc.test/runnable/dbitfields.d b/gcc/testsuite/gdc.test/runnable/dbitfields.d index 0d1877a..aa154c7 100644 --- a/gcc/testsuite/gdc.test/runnable/dbitfields.d +++ b/gcc/testsuite/gdc.test/runnable/dbitfields.d @@ -174,6 +174,39 @@ static assert(test7s() == -1); static assert(test7s2() == -2); /******************************************/ +// https://issues.dlang.org/show_bug.cgi?id=24257 + +struct S24257 +{ + uint : 15; + bool done : 1; +} + +bool advance() +{ + S24257 n; + n.done = false; + n.done = true; + return n.done; +} + +bool retard() +{ + S24257 n; + n.done = true; + n.done = false; + return n.done; +} + +static assert(advance() == true); + +void test24257() +{ + assert(advance() == true); + assert(retard() == false); +} + +/******************************************/ int main() { @@ -184,6 +217,7 @@ int main() test5(); test6(); test7(); + test24257(); return 0; } |