From: Iain Buclaw Date: Fri, 30 Jan 2026 09:25:49 +0000 (+0100) Subject: d: Merge upstream dmd, druntime 1017635a96, phobos 5a142da0a X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=919b6fa6adcc102f95b17c13e8bdc26fd4ec1394;p=thirdparty%2Fgcc.git d: Merge upstream dmd, druntime 1017635a96, phobos 5a142da0a D front-end changes: - Import dmd v2.112.0-beta.1. D runtime changes: - Import druntime v2.112.0-beta.1. - Added 64-bit `mul' and `udivmod' overloads to `core.int128'. Phobos changes: - Added `lazyCache' to `std.algorithm.iteration'. - Added `writeText', `writeWText', and `writeDText' to `std.conv'. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd 1017635a96. * dmd/VERSION: Bump version to v2.112.0-beta.1. * decl.cc (DeclVisitor::finish_vtable): Update for new front-end interface. (DeclVisitor::visit): Likewise. * typeinfo.cc (TypeInfoVisitor::visit): Likewise. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 1017635a96. * libdruntime/Makefile.am (DRUNTIME_DSOURCES_LINUX): Add core/sys/linux/sys/syscall.d, core/sys/linux/syscall.d. * libdruntime/Makefile.in: Regenerate. * src/MERGE: Merge upstream phobos 5a142da0a. * src/Makefile.am (PHOBOS_DSOURCES): Remove std/internal/windows/bcrypt.d. * src/Makefile.in: Regenerate. gcc/testsuite/ChangeLog: * gdc.dg/asm1.d: Adjust test. --- diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc index c43270c61e2c..0b915b5632a4 100644 --- a/gcc/d/decl.cc +++ b/gcc/d/decl.cc @@ -534,7 +534,7 @@ public: { FuncDeclaration *fd = d->vtbl[i]->isFuncDeclaration (); - if (!fd || (!fd->fbody && d->isAbstract ())) + if (!fd || (!fd->fbody && dmd::isAbstract (d))) continue; /* Ensure function has a return value. */ @@ -643,7 +643,7 @@ public: { FuncDeclaration *fd = d->vtbl[i]->isFuncDeclaration (); - if (fd && (fd->fbody || !d->isAbstract ())) + if (fd && (fd->fbody || !dmd::isAbstract (d))) { CONSTRUCTOR_APPEND_ELT (elms, size_int (i), build_address (get_symbol_decl (fd))); diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index 58d19b4e951d..62d90e5770b5 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -956e73d64e532a68213970316c2590c572ec03f3 +1017635a9636ef6a7a4bda35b1e091875d829871 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 e972d6e93a4d..67e32f8d7ef1 100644 --- a/gcc/d/dmd/VERSION +++ b/gcc/d/dmd/VERSION @@ -1 +1 @@ -v2.111.0 +v2.112.0-beta.1 diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d index 51d6fc459539..6359674d4471 100644 --- a/gcc/d/dmd/aggregate.d +++ b/gcc/d/dmd/aggregate.d @@ -187,8 +187,6 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol return fields.length - isNested() - (vthis2 !is null); } - abstract void finalizeSize(); - override final uinteger_t size(Loc loc) { //printf("+AggregateDeclaration::size() %s, scope = %p, sizeok = %d\n", toChars(), _scope, sizeok); diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h index 82f8aeca0808..d89755cea27c 100644 --- a/gcc/d/dmd/aggregate.h +++ b/gcc/d/dmd/aggregate.h @@ -120,7 +120,6 @@ public: Sizeok sizeok; // set when structsize contains valid data virtual Scope *newScope(Scope *sc); - virtual void finalizeSize() = 0; uinteger_t size(Loc loc) override final; Type *getType() override final; bool isDeprecated() const override final; // is aggregate deprecated? @@ -172,7 +171,6 @@ public: static StructDeclaration *create(Loc loc, Identifier *id, bool inObject); StructDeclaration *syntaxCopy(Dsymbol *s) override; const char *kind() const override; - void finalizeSize() override final; bool isPOD(); bool zeroInit() const; // !=0 if initialize with 0 fill bool zeroInit(bool v); @@ -196,7 +194,7 @@ public: unsigned numArgTypes() const; Type *argType(unsigned index); - bool hasRegularCtor(bool checkDisabled = false); + bool hasRegularCtor(bool ignoreDisabled = false); }; class UnionDeclaration final : public StructDeclaration @@ -287,13 +285,11 @@ public: virtual bool isBaseOf(ClassDeclaration *cd, int *poffset); bool isBaseInfoComplete(); - void finalizeSize() override; bool hasMonitor(); bool isCOMclass() const; virtual bool isCOMinterface() const; bool isCPPclass() const; virtual bool isCPPinterface() const; - bool isAbstract(); virtual int vtblOffset() const; const char *kind() const override; diff --git a/gcc/d/dmd/arraytypes.d b/gcc/d/dmd/arraytypes.d index 2cd446ea5ed7..bed684b3a425 100644 --- a/gcc/d/dmd/arraytypes.d +++ b/gcc/d/dmd/arraytypes.d @@ -29,6 +29,7 @@ alias Strings = Array!(const(char)*); alias Identifiers = Array!(Identifier); alias TemplateParameters = Array!(TemplateParameter); alias Expressions = Array!(Expression); +alias ArgumentLabels = Array!(ArgumentLabel); alias Statements = Array!(Statement); alias BaseClasses = Array!(BaseClass*); alias ClassDeclarations = Array!(ClassDeclaration); diff --git a/gcc/d/dmd/arraytypes.h b/gcc/d/dmd/arraytypes.h index 28165f3ed8ea..a06144332db5 100644 --- a/gcc/d/dmd/arraytypes.h +++ b/gcc/d/dmd/arraytypes.h @@ -17,6 +17,8 @@ typedef Array TemplateParameters; typedef Array Expressions; +typedef Array ArgumentLabels; + typedef Array Statements; typedef Array BaseClasses; diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d index 1bfe7902a920..a03e7bbdc0e5 100644 --- a/gcc/d/dmd/attrib.d +++ b/gcc/d/dmd/attrib.d @@ -110,11 +110,6 @@ extern (C++) abstract class AttribDeclaration : Dsymbol return "attribute"; } - override final bool hasPointers() - { - return this.include(null).foreachDsymbol( (s) { return s.hasPointers(); } ) != 0; - } - /**************************************** */ override final void addObjcSymbols(ClassDeclarations* classes, ClassDeclarations* categories) diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h index ef37e0adece1..24d91abc6275 100644 --- a/gcc/d/dmd/attrib.h +++ b/gcc/d/dmd/attrib.h @@ -29,7 +29,6 @@ class AttribDeclaration : public Dsymbol public: Dsymbols *decl; // array of Dsymbol's const char *kind() const override; - bool hasPointers() override final; void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d index 1b11a9f1803b..31c01f1853e6 100644 --- a/gcc/d/dmd/cond.d +++ b/gcc/d/dmd/cond.d @@ -24,7 +24,6 @@ import dmd.dscope; import dmd.dsymbol; import dmd.errors; import dmd.expression; -import dmd.expressionsem : evalStaticCondition; import dmd.globals; import dmd.identifier; import dmd.location; @@ -71,8 +70,6 @@ extern (C++) abstract class Condition : ASTNode abstract Condition syntaxCopy(); - abstract int include(Scope* sc); - inout(DebugCondition) isDebugCondition() inout { return null; @@ -324,39 +321,6 @@ extern (C++) final class DebugCondition : DVCondition super(loc, mod, ident); } - override int include(Scope* sc) - { - //printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel); - if (inc != Include.notComputed) - { - return inc == Include.yes; - } - inc = Include.no; - bool definedInModule = false; - if (ident) - { - if (mod.debugids && findCondition(*mod.debugids, ident)) - { - inc = Include.yes; - definedInModule = true; - } - else if (findCondition(global.debugids, ident)) - inc = Include.yes; - else - { - if (!mod.debugidsNot) - mod.debugidsNot = new Identifiers(); - mod.debugidsNot.push(ident); - } - } - else if (global.params.debugEnabled) - inc = Include.yes; - - if (!definedInModule) - printDepsConditional(sc, this, "depsDebug "); - return (inc == Include.yes); - } - override inout(DebugCondition) isDebugCondition() inout { return this; @@ -390,7 +354,7 @@ extern (C++) final class VersionCondition : DVCondition * Returns: * `true` if it is reserved, `false` otherwise */ - extern(D) private static bool isReserved(const(char)[] ident) @safe + extern(D) public static bool isReserved(const(char)[] ident) @safe { // This list doesn't include "D_*" versions, see the last return switch (ident) @@ -599,41 +563,6 @@ extern (C++) final class VersionCondition : DVCondition super(loc, mod, ident); } - override int include(Scope* sc) - { - //printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel); - //if (ident) printf("\tident = '%s'\n", ident.toChars()); - if (inc != Include.notComputed) - { - return inc == Include.yes; - } - - inc = Include.no; - bool definedInModule = false; - if (ident) - { - if (mod.versionids && findCondition(*mod.versionids, ident)) - { - inc = Include.yes; - definedInModule = true; - } - else if (findCondition(global.versionids, ident)) - inc = Include.yes; - else - { - if (!mod.versionidsNot) - mod.versionidsNot = new Identifiers(); - mod.versionidsNot.push(ident); - } - } - if (!definedInModule && - (!ident || (!isReserved(ident.toString()) && ident != Id._unittest && ident != Id._assert))) - { - printDepsConditional(sc, this, "depsVersion "); - } - return (inc == Include.yes); - } - override inout(VersionCondition) isVersionCondition() inout { return this; @@ -662,47 +591,6 @@ extern (C++) final class StaticIfCondition : Condition return new StaticIfCondition(loc, exp.syntaxCopy()); } - override int include(Scope* sc) - { - // printf("StaticIfCondition::include(sc = %p) this=%p inc = %d\n", sc, this, inc); - - int errorReturn() - { - if (!global.gag) - inc = Include.no; // so we don't see the error message again - return 0; - } - - if (inc != Include.notComputed) - { - return inc == Include.yes; - } - - if (!sc) - { - error(loc, "`static if` conditional cannot be at global scope"); - inc = Include.no; - return 0; - } - - import dmd.staticcond; - bool errors; - - bool result = evalStaticCondition(sc, exp, exp, errors); - - // Prevent repeated condition evaluation. - // See: fail_compilation/fail7815.d - if (inc != Include.notComputed) - return (inc == Include.yes); - if (errors) - return errorReturn(); - if (result) - inc = Include.yes; - else - inc = Include.no; - return (inc == Include.yes); - } - override void accept(Visitor v) { v.visit(this); @@ -734,7 +622,7 @@ bool findCondition(ref Identifiers ids, Identifier ident) @safe nothrow pure } // Helper for printing dependency information -private void printDepsConditional(Scope* sc, DVCondition condition, const(char)[] depType) +public void printDepsConditional(Scope* sc, DVCondition condition, const(char)[] depType) { if (!global.params.moduleDeps.buffer || global.params.moduleDeps.name) return; diff --git a/gcc/d/dmd/cond.h b/gcc/d/dmd/cond.h index 174a8fb9aafc..0afa042f9daa 100644 --- a/gcc/d/dmd/cond.h +++ b/gcc/d/dmd/cond.h @@ -38,7 +38,6 @@ public: DYNCAST dyncast() const override final { return DYNCAST_CONDITION; } virtual Condition *syntaxCopy() = 0; - virtual int include(Scope *sc) = 0; virtual DebugCondition *isDebugCondition() { return nullptr; } virtual VersionCondition *isVersionCondition() { return nullptr; } void accept(Visitor *v) override { v->visit(this); } @@ -70,7 +69,6 @@ class DebugCondition final : public DVCondition public: static void addGlobalIdent(const char *ident); - int include(Scope *sc) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -80,7 +78,6 @@ public: static void addGlobalIdent(const char *ident); static void addPredefinedGlobalIdent(const char *ident); - int include(Scope *sc) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -90,6 +87,5 @@ public: Expression *exp; StaticIfCondition *syntaxCopy() override; - int include(Scope *sc) override; void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d index 1a2a1e9470ea..70369ba20c7a 100644 --- a/gcc/d/dmd/cparse.d +++ b/gcc/d/dmd/cparse.d @@ -832,8 +832,8 @@ final class CParser(AST) : Parser!AST const len2 = token.len; len = len1 + len2; auto s2 = cast(char*)mem.xmalloc_noscan(len * char.sizeof); - memcpy(s2, s, len1 * char.sizeof); - memcpy(s2 + len1, token.ustring, len2 * char.sizeof); + s2[0 .. len1] = s[0 .. len1]; + s2[len1 .. len1 + len2] = token.ustring[0 .. len2]; s = s2; } else @@ -982,6 +982,7 @@ final class CParser(AST) : Parser!AST * sizeof unary-expression * sizeof ( type-name ) * _Alignof ( type-name ) + * _Alignof unary-expression // gcc extension * * unary-operator: * & * + - ~ ! @@ -1044,8 +1045,10 @@ final class CParser(AST) : Parser!AST e = new AST.ComExp(loc, e); break; + case TOK._Alignof: case TOK.sizeof_: { + Identifier id = token.value == TOK.sizeof_? Id.__sizeof : Id.__xalignof; nextToken(); if (token.value == TOK.leftParenthesis) { @@ -1084,7 +1087,7 @@ final class CParser(AST) : Parser!AST e = cparseUnaryExp(); } - e = new AST.DotIdExp(loc, e, Id.__sizeof); + e = new AST.DotIdExp(loc, e, id); break; } @@ -1096,17 +1099,6 @@ final class CParser(AST) : Parser!AST e = cparseCastExp(); break; - case TOK._Alignof: - { - nextToken(); - check(TOK.leftParenthesis); - auto t = cparseTypeName(); - check(TOK.rightParenthesis); - e = new AST.TypeExp(loc, t); - e = new AST.DotIdExp(loc, e, Id.__xalignof); - break; - } - default: e = cparsePostfixExp(e); break; @@ -1728,6 +1720,34 @@ final class CParser(AST) : Parser!AST /********************************* Declaration Parser ***************************/ //{ + void declareTag(AST.TypeTag tt, ref Specifier specifier, bool generate_enum_id = false) + { + if (!tt.id && (generate_enum_id || tt.tok != TOK.enum_)) tt.id = Identifier.generateId("__tag"); + /* `struct tag;` and `struct tag { ... };` + * always result in a declaration in the current scope + */ + auto stag = (tt.tok == TOK.struct_) ? new AST.StructDeclaration(tt.loc, tt.id, false) : + (tt.tok == TOK.union_) ? new AST.UnionDeclaration(tt.loc, tt.id) : + new AST.EnumDeclaration(tt.loc, tt.id, tt.base); + if (!tt.alignExps && !tt.packalign.isUnknown()) + { + // saw `struct __declspec(align(N)) Tag ...` + auto st = stag.isStructDeclaration(); + st.alignment = tt.packalign; + } + stag.members = tt.members; + tt.members = null; + if (!symbols) + symbols = new AST.Dsymbols(); + AST.Dsymbol stags = stag; + if (tt.alignExps) + { + auto decls = new AST.Dsymbols(1); + (*decls)[0] = stags; + stags = new AST.AlignDeclaration(stags.loc, tt.alignExps, decls); + } + symbols.push(stags); + } /************************************* * C11 6.7 * declaration: @@ -1775,28 +1795,9 @@ final class CParser(AST) : Parser!AST specifier.packalign = this.packalign; auto tspec = cparseDeclarationSpecifiers(level, specifier); - AST.Dsymbol declareTag(AST.TypeTag tt, ref Specifier specifier) - { - /* `struct tag;` and `struct tag { ... };` - * always result in a declaration in the current scope - */ - auto stag = (tt.tok == TOK.struct_) ? new AST.StructDeclaration(tt.loc, tt.id, false) : - (tt.tok == TOK.union_) ? new AST.UnionDeclaration(tt.loc, tt.id) : - new AST.EnumDeclaration(tt.loc, tt.id, tt.base); - if (!tt.packalign.isUnknown()) - { - // saw `struct __declspec(align(N)) Tag ...` - auto st = stag.isStructDeclaration(); - st.alignment = tt.packalign; - } - stag.members = tt.members; - tt.members = null; - if (!symbols) - symbols = new AST.Dsymbols(); - auto stags = applySpecifier(stag, specifier); - symbols.push(stags); - return stags; - } + // Defer declaring a tagged type (struct/union/enum) so + // that anonymous types can use a typedef as their id. + /* If a declarator does not follow, it is unnamed */ @@ -1822,12 +1823,13 @@ final class CParser(AST) : Parser!AST !tt.id && (tt.tok == TOK.struct_ || tt.tok == TOK.union_)) return; // legal but meaningless empty declaration, ignore it - auto stags = declareTag(tt, specifier); + if (tt.members || tt.tok != TOK.enum_) + declareTag(tt, specifier); if (0 && tt.tok == TOK.enum_) // C11 proscribes enums with no members, but we allow it { if (!tt.members) - error(tt.loc, "`enum %s` has no members", stags.toChars()); + error(tt.loc, "`enum %s` has no members", tt.toChars()); } return; } @@ -1840,6 +1842,15 @@ final class CParser(AST) : Parser!AST return; } + if (auto tt = tspec.isTypeTag()) + { + if (tt.id && tt.members) + { + // Valid tag decl with name and members, go ahead and declare it now. + declareTag(tt, specifier); + } + } + if (tspec && specifier.mod & MOD.xconst) { tspec = toConst(tspec); @@ -1867,7 +1878,7 @@ final class CParser(AST) : Parser!AST { Identifier id; AST.StringExp asmName; - auto dt = cparseDeclarator(DTR.xdirect, tspec, id, specifier); + auto dt = cparseDeclarator(DTR.xdirect_fd, tspec, id, specifier); if (!dt) { panic(); @@ -1913,10 +1924,14 @@ final class CParser(AST) : Parser!AST break; } - if (specifier.alignExps && dt.isTypeFunction()) - error("no alignment-specifier for function declaration"); // C11 6.7.5-2 - if (specifier.alignExps && specifier.scw == SCW.xregister) - error("no alignment-specifier for `register` storage class"); // C11 6.7.5-2 + + // Check alignasExp and not alignExps so that gnu + // __atribute__((aligned())) is silently allowed, matching the + // behavior of other compilers. + if (specifier.alignasExp && dt.isTypeFunction()) + error(specifier.alignasExp.loc, "no alignment-specifier for function declaration"); // C11 6.7.5-2 + if (specifier.alignasExp && specifier.scw == SCW.xregister) + error(specifier.alignasExp.loc, "no alignment-specifier for `register` storage class"); // C11 6.7.5-2 /* C11 6.9.1 Function Definitions * function-definition: @@ -1952,7 +1967,7 @@ final class CParser(AST) : Parser!AST typedefTab.setDim(typedefTabLengthSave); symbols = symbolsSave; if (!symbols) - symbols = new AST.Dsymbols; // lazilly create it + symbols = new AST.Dsymbols; // lazily create it if (level != LVL.global && !tspec && !specifier.scw && !specifier.mod) error("declaration-specifier-seq required"); @@ -1960,8 +1975,8 @@ final class CParser(AST) : Parser!AST { if (token.value == TOK.assign) error("no initializer for typedef declaration"); - if (specifier.alignExps) - error("no alignment-specifier for typedef declaration"); // C11 6.7.5-2 + if (specifier.alignasExp) + error(specifier.alignasExp.loc, "no alignment-specifier for typedef declaration"); // C11 6.7.5-2 if (specifier.vector_size) { @@ -1973,38 +1988,33 @@ final class CParser(AST) : Parser!AST bool isalias = true; Identifier idt; - if (auto ts = dt.isTypeStruct()) - { - if (ts.sym.isAnonymous()) - { - // This is a typedef for an anonymous struct-or-union. - // Directly set the ident for the struct-or-union. - ts.sym.ident = id; - isalias = false; - } - idt = ts.sym.ident; - } - else if (auto te = dt.isTypeEnum()) - { - if (te.sym.isAnonymous()) - { - // This is a typedef for an anonymous enum. - te.sym.ident = id; - isalias = false; - } - idt = te.sym.ident; - } - else if (auto tt = dt.isTypeTag()) + if (auto tt = dt.isTypeTag()) { if (!tt.id && id) /* This applies for enums declared as * typedef enum {A} E; + * Or for similar structs and unions. */ tt.id = id; - Specifier spec; - declareTag(tt, spec); + if (tt.members) + { + Specifier spec; + declareTag(tt, spec); + } idt = tt.id; } + else if (auto tt = tspec.isTypeTag()) + { + // The unusual situation of an anonymous typedef struct where the + // first typedef can't be used as its name. + // Just declare it now so we can get a valid id. + if (!tt.id && tt.members) + { + Specifier spec; + declareTag(tt, spec, true); + idt = tt.id; + } + } if (isalias) { //printf("AliasDeclaration %s %s\n", id.toChars(), dt.toChars()); @@ -2033,6 +2043,16 @@ final class CParser(AST) : Parser!AST if (dt.ty == AST.Tvoid) error("`void` has no value"); + if (auto tt = tspec.isTypeTag()) + { + // Anonymous struct being used as a var decl type + if (!tt.id && tt.members && tt.tok != TOK.enum_) + { + Specifier spec; + declareTag(tt, spec); + } + } + AST.Initializer initializer; bool hasInitializer; if (token.value == TOK.assign) @@ -2456,25 +2476,7 @@ final class CParser(AST) : Parser!AST const sloc = token.loc; nextToken(); - Specifier tagSpecifier; - - /* GNU Extensions - * struct-or-union-specifier: - * struct-or-union gnu-attributes (opt) identifier (opt) { struct-declaration-list } gnu-attributes (opt) - * struct-or-union gnu-attribute (opt) identifier - */ - while (1) - { - if (token.value == TOK.__attribute__) - cparseGnuAttributes(tagSpecifier); - else if (token.value == TOK.__declspec) - cparseDeclspec(tagSpecifier); - else if (token.value == TOK.__pragma) - uupragmaDirective(sloc); - else - break; - } - t = cparseStruct(sloc, structOrUnion, tagSpecifier.packalign, symbols); + t = cparseStruct(sloc, structOrUnion, symbols); tkwx = TKW.xtag; break; } @@ -2536,6 +2538,7 @@ final class CParser(AST) : Parser!AST if (!specifier.alignExps) specifier.alignExps = new AST.Expressions(0); specifier.alignExps.push(exp); + specifier.alignasExp = exp; check(TOK.rightParenthesis); break; @@ -2839,6 +2842,18 @@ final class CParser(AST) : Parser!AST //printf("cparseDeclarator(%d, %s)\n", declarator, tbase.toChars()); AST.Types constTypes; // all the Types that will need `const` applied to them + // this.symbols can get changed to the symbol table for the + // parameter-type-list if we parse a function type. + // Callers are only ready to handle this if they pass DTR.xdirect_fd, + // so remember to restore this.symbols. + bool restore_symbols = true; + if (declarator == DTR.xdirect_fd) + { + declarator = DTR.xdirect; + restore_symbols = false; + } + + /* Insert tx -> t into * ts -> ... -> t * so that @@ -3030,7 +3045,7 @@ final class CParser(AST) : Parser!AST //tf = tf.addSTC(storageClass); // TODO insertTx(ts, tf, t); // ts -> ... -> tf -> t - if (ts != tf) + if (ts != tf || restore_symbols) this.symbols = symbolsSave; break; } @@ -3511,12 +3526,12 @@ final class CParser(AST) : Parser!AST case TOK.colonColon: // treat as two separate : tokens for iasmgcc *ptoklist = allocateToken(); - memcpy(*ptoklist, &token, Token.sizeof); + **ptoklist = this.token; (*ptoklist).value = TOK.colon; ptoklist = &(*ptoklist).next; *ptoklist = allocateToken(); - memcpy(*ptoklist, &token, Token.sizeof); + **ptoklist = this.token; (*ptoklist).value = TOK.colon; ptoklist = &(*ptoklist).next; @@ -3526,7 +3541,7 @@ final class CParser(AST) : Parser!AST default: *ptoklist = allocateToken(); - memcpy(*ptoklist, &token, Token.sizeof); + **ptoklist = this.token; ptoklist = &(*ptoklist).next; *ptoklist = null; nextToken(); @@ -3620,26 +3635,18 @@ final class CParser(AST) : Parser!AST if (token.value == TOK.leftParenthesis) { nextToken(); - if (token.value == TOK.int32Literal) - { - const n = token.unsvalue; - if (n < 1 || n & (n - 1) || ushort.max < n) - error("__attribute__((aligned(%lld))) must be an integer positive power of 2 and be <= 32,768", cast(ulong)n); - specifier.packalign.set(cast(uint)n); - specifier.packalign.setPack(true); - nextToken(); - } - else - { - error("alignment value expected, not `%s`", token.toChars()); - nextToken(); - } - + AST.Expression exp = cparseConstantExp(); + if (!specifier.alignExps) + specifier.alignExps = new AST.Expressions(0); + specifier.alignExps.push(exp); check(TOK.rightParenthesis); } - /* ignore __attribute__((aligned)), which sets the alignment to the largest value for any data - * type on the target machine. It's the opposite of __attribute__((packed)) - */ + else + { + /* ignore __attribute__((aligned)), which sets the alignment to the largest value for any data + * type on the target machine. It's the opposite of __attribute__((packed)) + */ + } } else if (token.ident == Id.packed) { @@ -3951,7 +3958,7 @@ final class CParser(AST) : Parser!AST * redeclaration, or reference to existing declaration. * Defer to the semantic() pass with a TypeTag. */ - return new AST.TypeTag(loc, TOK.enum_, tag, structalign_t.init, base, members); + return new AST.TypeTag(loc, TOK.enum_, tag, structalign_t.init, null, base, members); } /************************************* @@ -3978,8 +3985,25 @@ final class CParser(AST) : Parser!AST * Returns: * type of the struct */ - private AST.Type cparseStruct(Loc loc, TOK structOrUnion, structalign_t packalign, ref AST.Dsymbols* symbols) + private AST.Type cparseStruct(Loc loc, TOK structOrUnion, ref AST.Dsymbols* symbols) { + /* GNU Extensions + * struct-or-union-specifier: + * struct-or-union gnu-attributes (opt) identifier (opt) { struct-declaration-list } gnu-attributes (opt) + * struct-or-union gnu-attribute (opt) identifier + */ + Specifier tagSpecifier; + while (1) + { + if (token.value == TOK.__attribute__) + cparseGnuAttributes(tagSpecifier); + else if (token.value == TOK.__declspec) + cparseDeclspec(tagSpecifier); + else if (token.value == TOK.__pragma) + uupragmaDirective(loc); + else + break; + } Identifier tag; if (token.value == TOK.identifier) @@ -3995,7 +4019,7 @@ final class CParser(AST) : Parser!AST members = new AST.Dsymbols(); // so `members` will be non-null even with 0 members while (token.value != TOK.rightCurly) { - cparseStructDeclaration(members, packalign); + cparseStructDeclaration(members, tagSpecifier.packalign); if (token.value == TOK.endOfFile) break; @@ -4013,18 +4037,18 @@ final class CParser(AST) : Parser!AST /* GNU Extensions * Parse the postfix gnu-attributes (opt) */ - Specifier specifier; if (token.value == TOK.__attribute__) - cparseGnuAttributes(specifier); - if (!specifier.packalign.isUnknown) + cparseGnuAttributes(tagSpecifier); + if (!tagSpecifier.packalign.isUnknown) { - packalign.set(specifier.packalign.get()); - packalign.setPack(specifier.packalign.isPack()); foreach (ref d; (*members)[]) { + // skip possible static assert declarations + if (d.isStaticAssert()) continue; + auto decls = new AST.Dsymbols(1); (*decls)[0] = d; - d = new AST.AlignDeclaration(d.loc, specifier.packalign, decls); + d = new AST.AlignDeclaration(d.loc, tagSpecifier.packalign, decls); } } } @@ -4032,14 +4056,14 @@ final class CParser(AST) : Parser!AST error("missing tag `identifier` after `%s`", Token.toChars(structOrUnion)); // many ways and places to declare alignment - if (packalign.isUnknown() && !this.packalign.isUnknown()) - packalign.set(this.packalign.get()); + if (tagSpecifier.packalign.isUnknown() && !this.packalign.isUnknown()) + tagSpecifier.packalign.set(this.packalign.get()); /* Need semantic information to determine if this is a declaration, * redeclaration, or reference to existing declaration. * Defer to the semantic() pass with a TypeTag. */ - return new AST.TypeTag(loc, structOrUnion, tag, packalign, null, members); + return new AST.TypeTag(loc, structOrUnion, tag, tagSpecifier.packalign, tagSpecifier.alignExps, null, members); } /************************************* @@ -4103,7 +4127,7 @@ final class CParser(AST) : Parser!AST * struct { ... members ... }; * C11 6.7.2.1-13 */ - if (!tt.id && tt.members) + if (!tt.id && tt.members && tt.tok != TOK.enum_) { /* members of anonymous struct are considered members of * the containing struct @@ -4119,17 +4143,19 @@ final class CParser(AST) : Parser!AST /* `struct tag;` and `struct tag { ... };` * always result in a declaration in the current scope */ - // TODO: merge in specifier - auto stag = (tt.tok == TOK.struct_) - ? new AST.StructDeclaration(tt.loc, tt.id, false) - : new AST.UnionDeclaration(tt.loc, tt.id); - stag.members = tt.members; - if (!symbols) - symbols = new AST.Dsymbols(); - auto s = applySpecifier(stag, specifier); - symbols.push(s); + Specifier spec; + declareTag(tt, spec); return; } + if (auto tt = tspec.isTypeTag()) + { + // Declare the tagged type at this point. + if (tt.members) + { + Specifier spec; + declareTag(tt, spec); + } + } while (1) { @@ -4178,8 +4204,8 @@ final class CParser(AST) : Parser!AST error("specifier-qualifier-list required"); else if (width) { - if (specifier.alignExps) - error("no alignment-specifier for bit field declaration"); // C11 6.7.5-2 + if (specifier.alignasExp) + error(specifier.alignasExp.loc, "no alignment-specifier for bit field declaration"); // C11 6.7.5-2 auto s = new AST.BitFieldDeclaration(width.loc, dt, id, width); members.push(s); } @@ -4998,6 +5024,7 @@ final class CParser(AST) : Parser!AST return false; break; + case TOK._Alignof: case TOK.sizeof_: t = peek(t); if (t.value == TOK.leftParenthesis) @@ -5015,15 +5042,6 @@ final class CParser(AST) : Parser!AST return false; break; - case TOK._Alignof: - t = peek(t); - if (t.value != TOK.leftParenthesis) - return false; - t = peek(t); - if (!isTypeName(t) || t.value != TOK.rightParenthesis) - return false; - break; - default: // Compound literals are handled by cast and sizeof expressions, // so be content with just seeing a primary expression. @@ -5104,6 +5122,7 @@ final class CParser(AST) : Parser!AST /// Types of declarator to parse enum DTR { + xdirect_fd = 0, /// C11 6.7.6 direct-declarator, allow to start function definition xdirect = 1, /// C11 6.7.6 direct-declarator xabstract = 2, /// C11 6.7.7 abstract-declarator xparameter = 3, /// parameter declarator may be either direct or abstract @@ -5155,6 +5174,7 @@ final class CParser(AST) : Parser!AST SCW scw; /// storage-class specifiers MOD mod; /// type qualifiers AST.Expressions* alignExps; /// alignment + AST.Expression alignasExp; /// Last _Alignas() for errors structalign_t packalign; /// #pragma pack alignment value } @@ -6050,6 +6070,8 @@ final class CParser(AST) : Parser!AST //printf("addSym() %s\n", s.toChars()); if (auto v = s.isVarDeclaration()) v.isCmacro(true); // mark it as coming from a C #define + if (auto td = s.isTemplateDeclaration()) + td.isCmacro = true; // mark as coming from a C #define /* If it's already defined, replace the earlier * definition */ @@ -6073,6 +6095,14 @@ final class CParser(AST) : Parser!AST } } + void nextLine() + { + // scan to end of line + while (*p) + ++p; + ++p; // advance to start of next line + } + while (p < endp) { //printf("|%s|\n", p); @@ -6084,6 +6114,13 @@ final class CParser(AST) : Parser!AST if (token.value == TOK.identifier) { auto id = token.ident; + // https://github.com/dlang/dmd/issues/20423 + // skip macros that could shadow special builtins + if (id == Id.va_arg) + { + nextLine(); + continue; + } const params = *p == '('; nextToken(); @@ -6181,7 +6218,7 @@ final class CParser(AST) : Parser!AST /* Declare manifest constant: * enum id = "string"; */ - AST.Expression e = new AST.StringExp(scanloc, str[0 .. len], len, 1, postfix); + AST.Expression e = new AST.StringExp(scanloc, str[0 .. len], len, 1, postfix, true); auto v = new AST.VarDeclaration(scanloc, null, id, new AST.ExpInitializer(scanloc, e), STC.manifest); addSym(v); ++p; @@ -6329,10 +6366,7 @@ final class CParser(AST) : Parser!AST if (token.value == TOK.identifier) removeSym(token.ident); } - // scan to end of line - while (*p) - ++p; - ++p; // advance to start of next line + nextLine(); } if (newSymbols.length) diff --git a/gcc/d/dmd/cxxfrontend.d b/gcc/d/dmd/cxxfrontend.d index 234b6523afbf..b61137ff20fa 100644 --- a/gcc/d/dmd/cxxfrontend.d +++ b/gcc/d/dmd/cxxfrontend.d @@ -112,11 +112,6 @@ void mangleToBuffer(TemplateInstance ti, ref OutBuffer buf) /*********************************************************** * dmodule.d */ -void getLocalClasses(Module mod, ref ClassDeclarations aclasses) -{ - return dmd.dmodule.getLocalClasses(mod, aclasses); -} - FuncDeclaration findGetMembers(ScopeDsymbol dsym) { return dmd.dmodule.findGetMembers(dsym); @@ -192,6 +187,24 @@ Dsymbol vtblSymbol(ClassDeclaration cd) return dmd.dsymbolsem.vtblSymbol(cd); } +bool isAbstract(ClassDeclaration cd) +{ + import dmd.dsymbolsem; + return dmd.dsymbolsem.isAbstract(cd); +} + +bool hasPointers(Dsymbol d) +{ + import dmd.dsymbolsem; + return dmd.dsymbolsem.hasPointers(d); +} + +void getLocalClasses(Module mod, ref ClassDeclarations aclasses) +{ + import dmd.dsymbolsem; + return dmd.dsymbolsem.getLocalClasses(mod, aclasses); +} + /*********************************************************** * dtemplate.d */ @@ -256,7 +269,7 @@ Expression getDefaultValue(EnumDeclaration ed, Loc loc) /*********************************************************** * expression.d */ -void expandTuples(Expressions* exps, Identifiers* names = null) +void expandTuples(Expressions* exps, ArgumentLabels* names = null) { return dmd.expression.expandTuples(exps, names); } @@ -305,7 +318,7 @@ bool functionSemantic3(FuncDeclaration fd) return dmd.funcsem.functionSemantic3(fd); } -MATCH leastAsSpecialized(FuncDeclaration fd, FuncDeclaration g, Identifiers* names) +MATCH leastAsSpecialized(FuncDeclaration fd, FuncDeclaration g, ArgumentLabels* names) { import dmd.funcsem; return dmd.funcsem.leastAsSpecialized(fd, g, names); diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index 86d2f0f07c3f..9e35dde29697 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.d @@ -27,7 +27,6 @@ import dmd.dstruct; import dmd.dsymbol; import dmd.dsymbolsem; import dmd.errors; -import dmd.escape; import dmd.expression; import dmd.expressionsem; import dmd.func; @@ -149,8 +148,40 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t) //type = type.typeSemantic(loc, sc); //printf("type %s t %s\n", type.deco, t.deco); auto ts = toAutoQualChars(e.type, t); - error(e.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", - e.toErrMsg(), ts[0], ts[1]); + + // Special case for improved diagnostic when const to mutable conversion + // fails due to struct/union having pointers + if (e.type.ty == Tstruct && t.ty == Tstruct && + e.type.isTypeStruct().sym == t.isTypeStruct().sym && + e.type.mod == MODFlags.const_ && t.mod == 0 && e.type.hasPointers) + { + auto sym = e.type.isTypeStruct().sym; + error(e.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s` because %s `%s` contains pointers or references", + e.toErrMsg(), ts[0], ts[1], sym.kind(), sym.toErrMsg()); + return ErrorExp.get(); + } + + // Special case for pointer conversions + if (e.type.toBasetype().ty == Tpointer && t.toBasetype().ty == Tpointer) + { + Type fromPointee = e.type.nextOf(); + Type toPointee = t.nextOf(); + // Const -> mutable conversion (disallowed) + if (fromPointee.isConst() && !toPointee.isConst()) + { + error(e.loc, "cannot implicitly convert `%s` to `%s`", e.type.toChars(), t.toChars()); + errorSupplemental(e.loc, "Note: Converting const to mutable requires an explicit cast (`cast(int*)`)."); + return ErrorExp.get(); + } + // Incompatible pointee types (e.g., int* -> float* ) + else if (fromPointee.toBasetype().ty != toPointee.toBasetype().ty) + { + error(e.loc, "cannot implicitly convert `%s` to `%s`", e.type.toChars(), t.toChars()); + errorSupplemental(e.loc, "Note: Pointer types point to different base types (`%s` vs `%s`)", fromPointee.toChars(), toPointee.toChars()); + return ErrorExp.get(); + } + } + error(e.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", e.toErrMsg(), ts[0], ts[1]); } } return ErrorExp.get(); @@ -2715,13 +2746,6 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null) ArrayLiteralExp ae = e; Type tb = t.toBasetype(); - if (tb.ty == Tarray) - { - if (checkArrayLiteralEscape(*sc, ae, false)) - { - return ErrorExp.get(); - } - } if (e.type == t) { diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d index 80d39fac4267..51ac939ade09 100644 --- a/gcc/d/dmd/dclass.d +++ b/gcc/d/dmd/dclass.d @@ -23,7 +23,6 @@ import dmd.gluelayer; import dmd.declaration; import dmd.dscope; import dmd.dsymbol; -import dmd.dsymbolsem : dsymbolSemantic, addMember, setFieldOffset; import dmd.errors; import dmd.func; import dmd.id; @@ -33,7 +32,6 @@ import dmd.mtype; import dmd.objc; import dmd.root.rmem; import dmd.target; -import dmd.typesem : covariant, immutableOf, sarrayOf; import dmd.visitor; /*********************************************************** @@ -496,116 +494,6 @@ extern (C++) class ClassDeclaration : AggregateDeclaration return null; } - final override void finalizeSize() - { - assert(sizeok != Sizeok.done); - - // Set the offsets of the fields and determine the size of the class - if (baseClass) - { - assert(baseClass.sizeok == Sizeok.done); - - alignsize = baseClass.alignsize; - if (classKind == ClassKind.cpp) - structsize = target.cpp.derivedClassOffset(baseClass); - else - structsize = baseClass.structsize; - } - else if (classKind == ClassKind.objc) - structsize = 0; // no hidden member for an Objective-C class - else if (isInterfaceDeclaration()) - { - if (interfaces.length == 0) - { - alignsize = target.ptrsize; - structsize = target.ptrsize; // allow room for __vptr - } - } - else - { - alignsize = target.ptrsize; - structsize = target.ptrsize; // allow room for __vptr - if (hasMonitor()) - structsize += target.ptrsize; // allow room for __monitor - } - - //printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok); - size_t bi = 0; // index into vtblInterfaces[] - - /**** - * Runs through the inheritance graph to set the BaseClass.offset fields. - * Recursive in order to account for the size of the interface classes, if they are - * more than just interfaces. - * Params: - * cd = interface to look at - * baseOffset = offset of where cd will be placed - * Returns: - * subset of instantiated size used by cd for interfaces - */ - uint membersPlace(ClassDeclaration cd, uint baseOffset) - { - //printf(" membersPlace(%s, %d)\n", cd.toChars(), baseOffset); - uint offset = baseOffset; - - foreach (BaseClass* b; cd.interfaces) - { - if (b.sym.sizeok != Sizeok.done) - b.sym.finalizeSize(); - assert(b.sym.sizeok == Sizeok.done); - - if (!b.sym.alignsize) - b.sym.alignsize = target.ptrsize; - offset = alignmember(structalign_t(cast(ushort)b.sym.alignsize), b.sym.alignsize, offset); - assert(bi < vtblInterfaces.length); - - BaseClass* bv = (*vtblInterfaces)[bi]; - if (b.sym.interfaces.length == 0) - { - //printf("\tvtblInterfaces[%d] b=%p b.sym = %s, offset = %d\n", bi, bv, bv.sym.toChars(), offset); - bv.offset = offset; - ++bi; - // All the base interfaces down the left side share the same offset - for (BaseClass* b2 = bv; b2.baseInterfaces.length; ) - { - b2 = &b2.baseInterfaces[0]; - b2.offset = offset; - //printf("\tvtblInterfaces[%d] b=%p sym = %s, offset = %d\n", bi, b2, b2.sym.toChars(), b2.offset); - } - } - membersPlace(b.sym, offset); - //printf(" %s size = %d\n", b.sym.toChars(), b.sym.structsize); - offset += b.sym.structsize; - if (alignsize < b.sym.alignsize) - alignsize = b.sym.alignsize; - } - return offset - baseOffset; - } - - structsize += membersPlace(this, structsize); - - if (isInterfaceDeclaration()) - { - sizeok = Sizeok.done; - return; - } - - // FIXME: Currently setFieldOffset functions need to increase fields - // to calculate each variable offsets. It can be improved later. - fields.setDim(0); - - FieldState fieldState; - fieldState.offset = structsize; - foreach (s; *members) - { - s.setFieldOffset(this, &fieldState, false); - } - - sizeok = Sizeok.done; - - // Calculate fields[i].overlapped - checkOverlappedFields(); - } - /************** * Returns: true if there's a __monitor field */ @@ -757,106 +645,6 @@ extern (C++) class ClassDeclaration : AggregateDeclaration return false; } - /**************************************** - */ - final bool isAbstract() - { - enum log = false; - if (isabstract != ThreeState.none) - return isabstract == ThreeState.yes; - - if (log) printf("isAbstract(%s)\n", toChars()); - - bool no() { if (log) printf("no\n"); isabstract = ThreeState.no; return false; } - bool yes() { if (log) printf("yes\n"); isabstract = ThreeState.yes; return true; } - - if (storage_class & STC.abstract_ || _scope && _scope.stc & STC.abstract_) - return yes(); - - if (errors) - return no(); - - /* https://issues.dlang.org/show_bug.cgi?id=11169 - * Resolve forward references to all class member functions, - * and determine whether this class is abstract. - */ - static int func(Dsymbol s, void*) - { - auto fd = s.isFuncDeclaration(); - if (!fd) - return 0; - if (fd.storage_class & STC.static_) - return 0; - - if (fd.isAbstract()) - return 1; - return 0; - } - - // opaque class is not abstract if it is not declared abstract - if (!members) - return no(); - - for (size_t i = 0; i < members.length; i++) - { - auto s = (*members)[i]; - if (s.apply(&func, null)) - { - return yes(); - } - } - - /* If the base class is not abstract, then this class cannot - * be abstract. - */ - if (!isInterfaceDeclaration() && (!baseClass || !baseClass.isAbstract())) - return no(); - - /* If any abstract functions are inherited, but not overridden, - * then the class is abstract. Do this by checking the vtbl[]. - * Need to do semantic() on class to fill the vtbl[]. - */ - this.dsymbolSemantic(null); - - /* The next line should work, but does not because when ClassDeclaration.dsymbolSemantic() - * is called recursively it can set PASS.semanticdone without finishing it. - */ - //if (semanticRun < PASS.semanticdone) - { - /* Could not complete semantic(). Try running semantic() on - * each of the virtual functions, - * which will fill in the vtbl[] overrides. - */ - static int virtualSemantic(Dsymbol s, void*) - { - auto fd = s.isFuncDeclaration(); - if (fd && !(fd.storage_class & STC.static_) && !fd.isUnitTestDeclaration()) - fd.dsymbolSemantic(null); - return 0; - } - - for (size_t i = 0; i < members.length; i++) - { - auto s = (*members)[i]; - s.apply(&virtualSemantic,null); - } - } - - /* Finally, check the vtbl[] - */ - foreach (i; 1 .. vtbl.length) - { - auto fd = vtbl[i].isFuncDeclaration(); - //if (fd) printf("\tvtbl[%d] = [%s] %s\n", i, fd.loc.toChars(), fd.toPrettyChars()); - if (!fd || fd.isAbstract()) - { - return yes(); - } - } - - return no(); - } - /**************************************** * Determine if slot 0 of the vtbl[] is reserved for something else. * For class objects, yes, this is where the classinfo ptr goes. diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d index 4510927da711..25e5c31dcc6f 100644 --- a/gcc/d/dmd/declaration.d +++ b/gcc/d/dmd/declaration.d @@ -27,7 +27,6 @@ import dmd.dtemplate; import dmd.errors; import dmd.expression; import dmd.func; -import dmd.funcsem : overloadApply, getLevelAndCheck; import dmd.globals; import dmd.gluelayer; import dmd.hdrgen; @@ -783,25 +782,6 @@ extern (C++) final class OverDeclaration : Declaration return true; } - Dsymbol isUnique() - { - Dsymbol result = null; - overloadApply(aliassym, (Dsymbol s) - { - if (result) - { - result = null; - return 1; // ambiguous, done - } - else - { - result = s; - return 0; - } - }); - return result; - } - override void accept(Visitor v) { v.visit(this); @@ -1054,12 +1034,6 @@ extern (C++) class VarDeclaration : Declaration vbitoffset < bitoffset + tbitsize; } - override final bool hasPointers() - { - //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty); - return (!isDataseg() && type.hasPointers()); - } - /************************************* * Return true if we can take the address of this variable. */ @@ -1109,83 +1083,6 @@ extern (C++) class VarDeclaration : Declaration return e; } - /************************************ - * Check to see if this variable is actually in an enclosing function - * rather than the current one. - * Update nestedrefs[], closureVars[] and outerVars[]. - * Returns: true if error occurs. - */ - extern (D) final bool checkNestedReference(Scope* sc, Loc loc) - { - //printf("VarDeclaration::checkNestedReference() %s\n", toChars()); - if (sc.intypeof == 1 || sc.ctfe) - return false; - if (!parent || parent == sc.parent) - return false; - if (isDataseg() || (storage_class & STC.manifest)) - return false; - - // The current function - FuncDeclaration fdthis = sc.parent.isFuncDeclaration(); - if (!fdthis) - return false; // out of function scope - - Dsymbol p = toParent2(); - - // Function literals from fdthis to p must be delegates - ensureStaticLinkTo(fdthis, p); - - // The function that this variable is in - FuncDeclaration fdv = p.isFuncDeclaration(); - if (!fdv || fdv == fdthis) - return false; - - // Add fdthis to nestedrefs[] if not already there - if (!nestedrefs.contains(fdthis)) - nestedrefs.push(fdthis); - - //printf("\tfdv = %s\n", fdv.toChars()); - //printf("\tfdthis = %s\n", fdthis.toChars()); - if (loc.isValid()) - { - if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError) - return true; - } - - // Add this VarDeclaration to fdv.closureVars[] if not already there - if (!sc.intypeof && !sc.traitsCompiles && - // https://issues.dlang.org/show_bug.cgi?id=17605 - (fdv.skipCodegen || !fdthis.skipCodegen)) - { - if (!fdv.closureVars.contains(this)) - fdv.closureVars.push(this); - } - - if (!fdthis.outerVars.contains(this)) - fdthis.outerVars.push(this); - - //printf("fdthis is %s\n", fdthis.toChars()); - //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars()); - // __dollar creates problems because it isn't a real variable - // https://issues.dlang.org/show_bug.cgi?id=3326 - if (ident == Id.dollar) - { - .error(loc, "cannnot use `$` inside a function literal"); - return true; - } - if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759 - { - ExpInitializer ez = _init.isExpInitializer(); - assert(ez); - Expression e = ez.exp; - if (e.op == EXP.construct || e.op == EXP.blit) - e = (cast(AssignExp)e).e2; - return lambdaCheckForNestedRef(e, sc); - } - - return false; - } - override final Dsymbol toAlias() { //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym); diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h index c7e45526084d..74ea20cb56f8 100644 --- a/gcc/d/dmd/declaration.h +++ b/gcc/d/dmd/declaration.h @@ -35,10 +35,11 @@ namespace dmd bool functionSemantic(FuncDeclaration* fd); bool functionSemantic3(FuncDeclaration* fd); bool checkClosure(FuncDeclaration* fd); - MATCH leastAsSpecialized(FuncDeclaration *f, FuncDeclaration *g, Identifiers *names); + MATCH leastAsSpecialized(FuncDeclaration *f, FuncDeclaration *g, ArgumentLabels *names); PURE isPure(FuncDeclaration *f); FuncDeclaration *genCfunc(Parameters *args, Type *treturn, const char *name, StorageClass stc=0); FuncDeclaration *genCfunc(Parameters *args, Type *treturn, Identifier *id, StorageClass stc=0); + bool isAbstract(ClassDeclaration *cd); } //enum STC : ulong from astenums.d: @@ -297,7 +298,6 @@ public: bool isThreadlocal() override final; bool isCTFE(); bool isOverlappedWith(VarDeclaration *v); - bool hasPointers() override final; bool canTakeAddressOf(); bool needsScopeDtor(); Dsymbol *toAlias() override final; diff --git a/gcc/d/dmd/delegatize.d b/gcc/d/dmd/delegatize.d index 344130b5e31d..1f5dca66b598 100644 --- a/gcc/d/dmd/delegatize.d +++ b/gcc/d/dmd/delegatize.d @@ -21,6 +21,7 @@ import dmd.dsymbol; import dmd.expression; import dmd.expressionsem; import dmd.func; +import dmd.funcsem : checkNestedReference; import dmd.init; import dmd.initsem; import dmd.location; diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d index 13051db37897..543c0e22e39f 100644 --- a/gcc/d/dmd/dinterpret.d +++ b/gcc/d/dmd/dinterpret.d @@ -1027,12 +1027,6 @@ Expression interpretStatement(UnionExp* pue, Statement s, InterState* istate) * assigning a larger array into a smaller one, such as: * `a = [1, 2], a ~= [3]` => `[1, 2] ~= [3]` => `[1, 2] = [1, 2, 3]` */ - if (isRuntimeHook(s.exp, Id._d_arrayappendT) || isRuntimeHook(s.exp, Id._d_arrayappendTTrace)) - { - auto rs = new ReturnStatement(s.loc, e); - visitReturn(rs); - return; - } // Disallow returning pointers to stack-allocated variables (bug 7876) if (!stopPointersEscaping(s.loc, e)) @@ -3189,7 +3183,8 @@ public: if (cmp == -1) { char dir = (e.op == EXP.greaterThan || e.op == EXP.greaterOrEqual) ? '<' : '>'; - error(e.loc, "the ordering of pointers to unrelated memory blocks is indeterminate in CTFE. To check if they point to the same memory block, use both `>` and `<` inside `&&` or `||`, eg `%s && %s %c= %s + 1`", e.toChars(), e.e1.toChars(), dir, e.e2.toChars()); + error(e.loc, "the ordering of pointers to unrelated memory blocks is indeterminate in CTFE."); + errorSupplemental(e.loc, "to check if they point to the same memory block, use both `>` and `<` inside `&&` or `||`, eg `%s && %s %c= %s + 1`", e.toChars(), e.e1.toChars(), dir, e.e2.toChars()); result = CTFEExp.cantexp; return; } @@ -5001,61 +4996,6 @@ public: printf("%s CommaExp::interpret() %s\n", e.loc.toChars(), e.toChars()); } - bool isNewThrowableHook() - { - auto de = e.e1.isDeclarationExp(); - if (de is null) - return false; - - auto vd = de.declaration.isVarDeclaration(); - if (vd is null) - return false; - - auto ei = vd._init.isExpInitializer(); - if (ei is null) - return false; - - auto ce = ei.exp.isConstructExp(); - if (ce is null) - return false; - - return isRuntimeHook(ce.e2, Id._d_newThrowable) !is null; - } - - if (auto ce = isRuntimeHook(e.e1, Id._d_arrayappendcTX)) - { - // In expressionsem.d `arr ~= elem` was lowered to - // `_d_arrayappendcTX(arr, elem), arr[arr.length - 1] = elem, elem;`. - // The following code will rewrite it back to `arr ~= elem` - // and then interpret that expression. - assert(ce.arguments.length == 2); - - auto arr = (*ce.arguments)[0]; - auto elem = e.e2.isConstructExp().e2; - assert(elem); - - auto cae = new CatAssignExp(e.loc, arr, elem); - cae.type = arr.type; - - result = interpret(cae, istate); - return; - } - else if (isNewThrowableHook()) - { - // In expressionsem.d `throw new Exception(args)` was lowered to - // `throw (tmp = _d_newThrowable!Exception(), tmp.ctor(args), tmp)`. - // The following code will rewrite it back to `throw new Exception(args)` - // and then interpret this expression instead. - auto ce = e.e2.isCallExp(); - assert(ce); - - auto ne = new NewExp(e.loc, null, null, e.type, ce.arguments); - ne.type = e.e1.type; - - result = interpret(ne, istate); - return; - } - // If it creates a variable, and there's no context for // the variable to be created in, we need to create one now. InterState istateComma; diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d index 0e0070aab588..33539d4bf0b8 100644 --- a/gcc/d/dmd/dmodule.d +++ b/gcc/d/dmd/dmodule.d @@ -30,7 +30,7 @@ import dmd.dmacro; import dmd.doc; import dmd.dscope; import dmd.dsymbol; -import dmd.dsymbolsem : dsymbolSemantic, importAll, load, include; +import dmd.dsymbolsem : dsymbolSemantic, importAll, load; import dmd.errors; import dmd.errorsink; import dmd.expression; @@ -43,6 +43,7 @@ import dmd.id; import dmd.identifier; import dmd.location; import dmd.parse; +import dmd.root.aav; import dmd.root.array; import dmd.root.file; import dmd.root.filename; @@ -544,6 +545,8 @@ extern (C++) final class Module : Package } buf.printf("%s\t(%s)", ident.toChars(), m.srcfile.toChars()); message("import %s", buf.peekChars()); + if (loc != Loc.initial) + message("(imported from %s)", loc.toChars()); } if((m = m.parse()) is null) return null; @@ -1008,22 +1011,31 @@ extern (C++) final class Module : Package extern (D) static void addDeferredSemantic(Dsymbol s) { //printf("Module::addDeferredSemantic('%s')\n", s.toChars()); - if (!deferred.contains(s)) + if (!s.deferred) + { + s.deferred = true; deferred.push(s); + } } extern (D) static void addDeferredSemantic2(Dsymbol s) { //printf("Module::addDeferredSemantic2('%s')\n", s.toChars()); - if (!deferred2.contains(s)) + if (!s.deferred2) + { + s.deferred2 = true; deferred2.push(s); + } } extern (D) static void addDeferredSemantic3(Dsymbol s) { //printf("Module::addDeferredSemantic3('%s')\n", s.toChars()); - if (!deferred.contains(s)) + if (!s.deferred3) + { + s.deferred3 = true; deferred3.push(s); + } } /****************************************** @@ -1057,6 +1069,8 @@ extern (C++) final class Module : Package todoalloc = todo; } memcpy(todo, deferred.tdata(), len * Dsymbol.sizeof); + foreach (Dsymbol s; Module.deferred[]) + s.deferred = false; deferred.setDim(0); foreach (i; 0..len) @@ -1082,6 +1096,7 @@ extern (C++) final class Module : Package for (size_t i = 0; i < a.length; i++) { Dsymbol s = (*a)[i]; + s.deferred2 = false; //printf("[%d] %s semantic2a\n", i, s.toPrettyChars()); s.semantic2(null); @@ -1099,6 +1114,7 @@ extern (C++) final class Module : Package for (size_t i = 0; i < a.length; i++) { Dsymbol s = (*a)[i]; + s.deferred3 = false; //printf("[%d] %s semantic3a\n", i, s.toPrettyChars()); s.semantic3(null); @@ -1306,83 +1322,8 @@ extern (C++) struct ModuleDeclaration } } -/**************************************** - * Create array of the local classes in the Module, suitable - * for inclusion in ModuleInfo - * Params: - * mod = the Module - * aclasses = array to fill in - * Returns: array of local classes - */ -void getLocalClasses(Module mod, ref ClassDeclarations aclasses) -{ - //printf("members.length = %d\n", mod.members.length); - int pushAddClassDg(size_t n, Dsymbol sm) - { - if (!sm) - return 0; - - if (auto cd = sm.isClassDeclaration()) - { - // compatibility with previous algorithm - if (cd.parent && cd.parent.isTemplateMixin()) - return 0; - - if (cd.classKind != ClassKind.objc) - aclasses.push(cd); - } - return 0; - } - - _foreach(null, mod.members, &pushAddClassDg); -} - - alias ForeachDg = int delegate(size_t idx, Dsymbol s); -/*************************************** - * Expands attribute declarations in members in depth first - * order. Calls dg(size_t symidx, Dsymbol *sym) for each - * member. - * If dg returns !=0, stops and returns that value else returns 0. - * Use this function to avoid the O(N + N^2/2) complexity of - * calculating dim and calling N times getNth. - * Returns: - * last value returned by dg() - */ -int _foreach(Scope* sc, Dsymbols* members, scope ForeachDg dg, size_t* pn = null) -{ - assert(dg); - if (!members) - return 0; - size_t n = pn ? *pn : 0; // take over index - int result = 0; - foreach (size_t i; 0 .. members.length) - { - import dmd.attrib : AttribDeclaration; - import dmd.dtemplate : TemplateMixin; - - Dsymbol s = (*members)[i]; - if (AttribDeclaration a = s.isAttribDeclaration()) - result = _foreach(sc, a.include(sc), dg, &n); - else if (TemplateMixin tm = s.isTemplateMixin()) - result = _foreach(sc, tm.members, dg, &n); - else if (s.isTemplateInstance()) - { - } - else if (s.isUnitTestDeclaration()) - { - } - else - result = dg(n++, s); - if (result) - break; - } - if (pn) - *pn = n; // update index - return result; -} - /** * Process the content of a source file * diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d index 725a55e94184..c70e7d381b56 100644 --- a/gcc/d/dmd/dscope.d +++ b/gcc/d/dmd/dscope.d @@ -64,7 +64,7 @@ private extern (D) struct BitFields bool inTemplateConstraint; /// inside template constraint Contract contract; bool ctfe; /// inside a ctfe-only expression - bool traitsCompiles; /// inside __traits(compile) + bool traitsCompiles; /// inside __traits(compile) or is-expression /// ignore symbol visibility /// https://issues.dlang.org/show_bug.cgi?id=15907 bool ignoresymbolvisibility; diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d index d07be2f13193..5aef3585cafe 100644 --- a/gcc/d/dmd/dstruct.d +++ b/gcc/d/dmd/dstruct.d @@ -151,127 +151,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration return "struct"; } - override final void finalizeSize() - { - //printf("StructDeclaration::finalizeSize() %s, sizeok = %d\n", toChars(), sizeok); - assert(sizeok != Sizeok.done); - - if (sizeok == Sizeok.inProcess) - { - return; - } - sizeok = Sizeok.inProcess; - - //printf("+StructDeclaration::finalizeSize() %s, fields.length = %d, sizeok = %d\n", toChars(), fields.length, sizeok); - - fields.setDim(0); // workaround - - // Set the offsets of the fields and determine the size of the struct - FieldState fieldState; - bool isunion = isUnionDeclaration() !is null; - for (size_t i = 0; i < members.length; i++) - { - Dsymbol s = (*members)[i]; - s.setFieldOffset(this, &fieldState, isunion); - if (type.ty == Terror) - { - errorSupplemental(s.loc, "error on member `%s`", s.toPrettyChars); - errors = true; - return; - } - } - - if (structsize == 0) - { - hasNoFields = true; - alignsize = 1; - - // A fine mess of what size a zero sized struct should be - final switch (classKind) - { - case ClassKind.d: - case ClassKind.cpp: - structsize = 1; - break; - - case ClassKind.c: - case ClassKind.objc: - if (target.c.bitFieldStyle == TargetC.BitFieldStyle.MS) - { - /* Undocumented MS behavior for: - * struct S { int :0; }; - */ - structsize = 4; - } - else - structsize = 0; - break; - } - } - - // Round struct size up to next alignsize boundary. - // This will ensure that arrays of structs will get their internals - // aligned properly. - if (alignment.isDefault() || alignment.isPack()) - structsize = (structsize + alignsize - 1) & ~(alignsize - 1); - else - structsize = (structsize + alignment.get() - 1) & ~(alignment.get() - 1); - - sizeok = Sizeok.done; - - //printf("-StructDeclaration::finalizeSize() %s, fields.length = %d, structsize = %d\n", toChars(), cast(int)fields.length, cast(int)structsize); - - if (errors) - return; - - // Calculate fields[i].overlapped - if (checkOverlappedFields()) - { - errors = true; - return; - } - - // Determine if struct is all zeros or not - zeroInit = true; - auto lastOffset = -1; - foreach (vd; fields) - { - // First skip zero sized fields - if (vd.type.size(vd.loc) == 0) - continue; - - // only consider first sized member of an (anonymous) union - if (vd.overlapped && vd.offset == lastOffset) - continue; - lastOffset = vd.offset; - - if (vd._init) - { - if (vd._init.isVoidInitializer()) - /* Treat as 0 for the purposes of putting the initializer - * in the BSS segment, or doing a mass set to 0 - */ - continue; - - // Examine init to see if it is all 0s. - auto exp = vd.getConstInitializer(); - if (!exp || !_isZeroInit(exp)) - { - zeroInit = false; - break; - } - } - else if (!vd.type.isZeroInit(loc)) - { - zeroInit = false; - break; - } - } - - - argTypes = target.toArgTypes(type); - } - /// Compute cached type properties for `TypeStruct` extern(D) final void determineTypeProperties() { @@ -279,13 +158,14 @@ extern (C++) class StructDeclaration : AggregateDeclaration return; foreach (vd; fields) { + import dmd.dsymbolsem : hasPointers; if (vd.storage_class & STC.ref_ || vd.hasPointers()) { hasPointerField = true; hasUnsafeBitpatterns = true; } - if (vd._init && vd._init.isVoidInitializer() && vd.type.hasPointers()) + if (vd._init && vd._init.isVoidInitializer() && vd.hasPointers()) hasVoidInitPointers = true; if (vd.storage_class & STC.system || vd.type.hasUnsafeBitpatterns()) @@ -399,13 +279,12 @@ extern (C++) class StructDeclaration : AggregateDeclaration * is not disabled. * * Params: - * checkDisabled = if the struct has a regular - non-disabled constructor + * ignoreDisabled = true to ignore disabled constructors * Returns: * true, if the struct has a regular (optionally, * not disabled) constructor, false otherwise. */ - final bool hasRegularCtor(bool checkDisabled = false) + final bool hasRegularCtor(bool ignoreDisabled = false) { if (!ctor) return false; @@ -415,7 +294,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration { if (auto td = s.isTemplateDeclaration()) { - if (checkDisabled && td.onemember) + if (ignoreDisabled && td.onemember) { if (auto ctorDecl = td.onemember.isCtorDeclaration()) { @@ -428,7 +307,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration } if (auto ctorDecl = s.isCtorDeclaration()) { - if (!ctorDecl.isCpCtor && (!checkDisabled || !(ctorDecl.storage_class & STC.disable))) + if (!ctorDecl.isCpCtor && (!ignoreDisabled || !(ctorDecl.storage_class & STC.disable))) { result = true; return 1; @@ -440,96 +319,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration } } -/********************************** - * Determine if exp is all binary zeros. - * Params: - * exp = expression to check - * Returns: - * true if it's all binary 0 - */ -bool _isZeroInit(Expression exp) -{ - switch (exp.op) - { - case EXP.int64: - return exp.toInteger() == 0; - - case EXP.null_: - return true; - - case EXP.structLiteral: - { - auto sle = exp.isStructLiteralExp(); - if (sle.sd.isNested()) - return false; - const isCstruct = sle.sd.isCsymbol(); // C structs are default initialized to all zeros - foreach (i; 0 .. sle.sd.fields.length) - { - auto field = sle.sd.fields[i]; - if (field.type.size(field.loc)) - { - auto e = sle.elements && i < sle.elements.length ? (*sle.elements)[i] : null; - if (e ? !_isZeroInit(e) - : !isCstruct && !field.type.isZeroInit(field.loc)) - return false; - } - } - return true; - } - - case EXP.arrayLiteral: - { - auto ale = cast(ArrayLiteralExp)exp; - - const dim = ale.elements ? ale.elements.length : 0; - - if (ale.type.toBasetype().ty == Tarray) // if initializing a dynamic array - return dim == 0; - - foreach (i; 0 .. dim) - { - if (!_isZeroInit(ale[i])) - return false; - } - - /* Note that true is returned for all T[0] - */ - return true; - } - - case EXP.string_: - { - auto se = cast(StringExp)exp; - - if (se.type.toBasetype().ty == Tarray) // if initializing a dynamic array - return se.len == 0; - - foreach (i; 0 .. se.len) - { - if (se.getIndex(i) != 0) - return false; - } - return true; - } - - case EXP.vector: - { - auto ve = cast(VectorExp) exp; - return _isZeroInit(ve.e1); - } - - case EXP.float64: - case EXP.complex80: - { - import dmd.root.ctfloat : CTFloat; - return (exp.toReal() is CTFloat.zero) && - (exp.toImaginary() is CTFloat.zero); - } - - default: - return false; - } -} /*********************************************************** * Unions are a variation on structs. diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d index 74ca9cbda4d3..e65068c7622b 100644 --- a/gcc/d/dmd/dsymbol.d +++ b/gcc/d/dmd/dsymbol.d @@ -51,7 +51,6 @@ import dmd.statement; import dmd.staticassert; import dmd.tokens; import dmd.visitor; -import dmd.dsymbolsem; import dmd.common.outbuffer; @@ -344,6 +343,11 @@ extern (C++) class Dsymbol : ASTNode { bool errors; // this symbol failed to pass semantic() PASS semanticRun = PASS.initial; + + // Queued for deferred semantics: + bool deferred; // In Module.deferred + bool deferred2; // In Module.deferred2 + bool deferred3; // In Module.deferred3 } import dmd.common.bitfields; mixin(generateBitFields!(BitFields, ubyte)); @@ -900,78 +904,6 @@ extern (C++) class Dsymbol : ASTNode assert(0); } - /***************************************** - * Same as Dsymbol::oneMember(), but look at an array of Dsymbols. - */ - extern (D) static bool oneMembers(Dsymbols* members, out Dsymbol ps, Identifier ident) - { - //printf("Dsymbol::oneMembers() %d\n", members ? members.length : 0); - Dsymbol s = null; - if (!members) - { - ps = null; - return true; - } - - for (size_t i = 0; i < members.length; i++) - { - Dsymbol sx = (*members)[i]; - bool x = sx.oneMember(ps, ident); //MYTODO: this temporarily creates a new dependency to dsymbolsem, will need to extract oneMembers() later - //printf("\t[%d] kind %s = %d, s = %p\n", i, sx.kind(), x, *ps); - if (!x) - { - //printf("\tfalse 1\n"); - assert(ps is null); - return false; - } - if (ps) - { - assert(ident); - if (!ps.ident || !ps.ident.equals(ident)) - continue; - if (!s) - s = ps; - else if (s.isOverloadable() && ps.isOverloadable()) - { - // keep head of overload set - FuncDeclaration f1 = s.isFuncDeclaration(); - FuncDeclaration f2 = ps.isFuncDeclaration(); - if (f1 && f2) - { - assert(!f1.isFuncAliasDeclaration()); - assert(!f2.isFuncAliasDeclaration()); - for (; f1 != f2; f1 = f1.overnext0) - { - if (f1.overnext0 is null) - { - f1.overnext0 = f2; - break; - } - } - } - } - else // more than one symbol - { - ps = null; - //printf("\tfalse 2\n"); - return false; - } - } - } - ps = s; // s is the one symbol, null if none - //printf("\ttrue\n"); - return true; - } - - /***************************************** - * Is Dsymbol a variable that contains pointers? - */ - bool hasPointers() - { - //printf("Dsymbol::hasPointers() %s\n", toChars()); - return false; - } - void addObjcSymbols(ClassDeclarations* classes, ClassDeclarations* categories) { } @@ -1235,6 +1167,7 @@ extern (C++) class Dsymbol : ASTNode return null; } } + inout(AlignDeclaration) isAlignDeclaration() inout { return dsym == DSYM.alignDeclaration ? cast(inout(AlignDeclaration)) cast(void*) this : null; } inout(AnonDeclaration) isAnonDeclaration() inout { return dsym == DSYM.anonDeclaration ? cast(inout(AnonDeclaration)) cast(void*) this : null; } inout(CPPNamespaceDeclaration) isCPPNamespaceDeclaration() inout { return dsym == DSYM.cppNamespaceDeclaration ? cast(inout(CPPNamespaceDeclaration)) cast(void*) this : null; } inout(VisibilityDeclaration) isVisibilityDeclaration() inout { return dsym == DSYM.visibilityDeclaration ? cast(inout(VisibilityDeclaration)) cast(void*) this : null; } diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h index 558d15608884..77e7dabcb6cf 100644 --- a/gcc/d/dmd/dsymbol.h +++ b/gcc/d/dmd/dsymbol.h @@ -243,7 +243,6 @@ public: virtual bool needThis(); // need a 'this' pointer? virtual Visibility visible(); virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees - virtual bool hasPointers(); virtual void addObjcSymbols(ClassDeclarations *, ClassDeclarations *) { } virtual void addComment(const utf8_t *comment); @@ -428,7 +427,5 @@ namespace dmd Dsymbols *include(Dsymbol *d, Scope *sc); void setScope(Dsymbol *d, Scope *sc); void importAll(Dsymbol *d, Scope *sc); - void addComment(Dsymbol *d, const char *comment); - bool oneMember(Dsymbol *d, Dsymbol *&ps, Identifier *ident); - bool hasStaticCtorOrDtor(Dsymbol *d); + bool hasPointers(Dsymbol *d); } diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index acbac7a0e047..43fb0b72e4ba 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -953,6 +953,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (dsym.storage_class & STC.constscoperef) dsym.storage_class |= STC.scope_; + import dmd.typesem : hasPointers; + if (dsym.storage_class & STC.scope_) { STC stc = dsym.storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.gshared); @@ -3089,10 +3091,18 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor StructDeclaration sym = ts.sym; if (sd.isCsymbol() && sym.isCsymbol()) { - /* This is two structs imported from different C files. - * Just ignore sd, the second one. The first one will always - * be found when going through the type. - */ + + if (!isCCompatible(sd, sym)) + { + // Already issued an error. + errorSupplemental(sd.loc, "C %ss with the same name from different imports are merged", sd.kind); + } + else { + /* This is two structs imported from different C files. + * Just ignore sd, the second one. The first one will always + * be found when going through the type. + */ + } } else { @@ -3132,6 +3142,234 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor //printf("-StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok); } + // + // Checks if two structs are compatible + // Implements the rules according to C23 6.2.7 + // + static bool isCCompatible(StructDeclaration a, StructDeclaration b) + { + // Get the name of a type, while avoiding exposing "__tagXXX" anonymous structs + static const(char)* typeName(Type t) + { + if (TypeStruct ts = t.isTypeStruct()) + { + if (ts.sym.ident.toString().startsWith("__tag")) + return ts.sym.isUnionDeclaration() ? "(anonymous union)".ptr: "(anonymous struct)".ptr; + } + return t.toChars(); + } + + void incompatError() + { + .error(a.loc, "%s `%s` already exists with an incompatible definition.", + a.kind, typeName(a.type)); + errorSupplemental(b.loc, "previously declared here"); + } + + + // For recursive calls into unnamed structs (so Type.equals() doesn't work). + static bool isCCompatibleUnnamedStruct(Type a, Type b) + { + TypeStruct ats = a.isTypeStruct(); + if (!ats) return false; + TypeStruct bts = b.isTypeStruct(); + if (!bts) return false; + // Hack, anonymous structs within a struct are given + // an anonymous id starting with __tag. + if (!ats.sym.ident.toString().startsWith("__tag")) + return false; + if (!bts.sym.ident.toString().startsWith("__tag")) + return false; + return isCCompatible(ats.sym, bts.sym); + } + + if (a.fields.length != b.fields.length) + { + incompatError(); + errorSupplemental(a.loc, "`%s` has %zu field(s) while `%s` has %zu field(s)", + a.toPrettyChars(), a.fields.length, b.toPrettyChars(), b.fields.length); + return false; + } + // both are structs or both are unions + if ((a.isUnionDeclaration() is null) != (b.isUnionDeclaration() is null)) + { + incompatError(); + errorSupplemental(a.loc, "`%s` is a %s while `%s` is a %s", + a.toPrettyChars(), a.kind, b.toPrettyChars(), b.kind); + return false; + } + if (a.alignment != b.alignment) + { + incompatError(); + errorSupplemental(a.loc, "`%s` has different alignment or packing", a.toPrettyChars()); + if (a.alignment.isDefault() && ! b.alignment.isDefault()) + { + errorSupplemental(a.loc, "`%s` alignment: default", a.toPrettyChars()); + errorSupplemental(b.loc, "`%s` alignment: %u", + b.toPrettyChars(), cast(uint)b.alignment.get()); + } + else if (!a.alignment.isDefault() && b.alignment.isDefault()) + { + errorSupplemental(a.loc, "`%s` alignment: %u", + a.toPrettyChars(), cast(uint)a.alignment.get()); + errorSupplemental(b.loc, "`%s` alignment: default", + b.toPrettyChars()); + } + else if (a.alignment.get() != b.alignment.get()) + { + errorSupplemental(a.loc, "`%s` alignment: %u", + a.toPrettyChars(), cast(uint)a.alignment.get()); + errorSupplemental(b.loc, "`%s` alignment: %u", + b.toPrettyChars(), cast(uint)b.alignment.get()); + } + if (a.alignment.isPack() != b.alignment.isPack()) + { + errorSupplemental(a.loc, "`%s` packed: %s", + a.toPrettyChars(), a.alignment.isPack()?"true".ptr:"false".ptr); + errorSupplemental(b.loc, "`%s` packed: %s", + b.toPrettyChars(), b.alignment.isPack()?"true".ptr:"false".ptr); + } + return false; + } + foreach (size_t i, VarDeclaration a_field; a.fields[]) + { + VarDeclaration b_field = b.fields[i]; + // + // — there shall be a one-to-one correspondence between + // their members such that each pair of corresponding + // members are declared with compatible types; + // + if (!a_field.type.equals(b_field.type) && !isCCompatibleUnnamedStruct(a_field.type, b_field.type)) + { + // Already errored, just bail + incompatError(); + if (a_field.type.isTypeError()) return false; + if (b_field.type.isTypeError()) return false; + + errorSupplemental(a_field.loc, "Field %zu differs in type", i); + errorSupplemental(a_field.loc, "typeof(%s): %s", + a_field.toChars(), typeName(a_field.type)); + errorSupplemental(b_field.loc, "typeof(%s): %s", + b_field.toChars(), typeName(b_field.type)); + return false; + } + // + // — if one member of the pair is declared with an + // alignment specifier, the second is declared with an + // equivalent alignment specifier; + // + if (a_field.alignment != b_field.alignment) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in alignment or packing", i); + if (a_field.alignment.isDefault() && ! b_field.alignment.isDefault()) + { + errorSupplemental(a_field.loc, "`%s.%s` alignment: default", + a.toPrettyChars(),a_field.toChars()); + errorSupplemental(b_field.loc, "`%s.%s` alignment: %u", + b.toPrettyChars(), b_field.toChars(), cast(uint)b_field.alignment.get()); + } + else if (!a_field.alignment.isDefault() && b_field.alignment.isDefault()) + { + errorSupplemental(a_field.loc, "`%s.%s` alignment: %u", + a.toPrettyChars(), a_field.toChars(), cast(uint)a_field.alignment.get()); + errorSupplemental(b_field.loc, "`%s.%s` alignment: default", + b.toPrettyChars(), b_field.toChars()); + } + else if (a_field.alignment.get() != b_field.alignment.get()) + { + errorSupplemental(a_field.loc, "`%s.%s` alignment: %u", + a.toPrettyChars(), a_field.toChars(), + cast(uint)a_field.alignment.get()); + errorSupplemental(b_field.loc, "`%s.%s` alignment: %u", + b.toPrettyChars(), b_field.toChars(), + cast(uint)b_field.alignment.get()); + } + if (a_field.alignment.isPack() != b_field.alignment.isPack()) + { + errorSupplemental(a_field.loc, "`%s.%s` packed: %s", + a.toPrettyChars(), a_field.toChars(), + a_field.alignment.isPack()?"true".ptr:"false".ptr); + errorSupplemental(b_field.loc, "`%s.%s` packed: %s", + b.toPrettyChars(), b_field.toChars(), + b_field.alignment.isPack()?"true".ptr:"false".ptr); + } + return false; + } + // + // - and, if one member of the pair is declared with a + // name, the second is declared with the same name. + // + if (a_field.ident.isAnonymous()) + { + if (!b_field.ident.isAnonymous()) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in name", i); + errorSupplemental(a_field.loc, "(anonymous)", a_field.ident.toChars()); + errorSupplemental(b_field.loc, "%s", b_field.ident.toChars()); + return false; + } + } + else if (b_field.ident.isAnonymous()) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in name", i); + errorSupplemental(a_field.loc, "%s", a_field.ident.toChars()); + errorSupplemental(b_field.loc, "(anonymous)"); + return false; + } + else if (a_field.ident != b_field.ident) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in name", i); + errorSupplemental(a_field.loc, "%s", a_field.ident.toChars()); + errorSupplemental(b_field.loc, "%s", b_field.ident.toChars()); + return false; + } + + // + // For two structures or unions, corresponding bit-fields shall have the same widths. + // + BitFieldDeclaration bfa = a_field.isBitFieldDeclaration(); + BitFieldDeclaration bfb = b_field.isBitFieldDeclaration(); + if ((bfa is null) != (bfb is null)) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in being a bitfield", i); + if (bfa is null) + { + errorSupplemental(a_field.loc, "`%s.%s` is not a bitfield", + a.toPrettyChars(), a_field.toChars()); + errorSupplemental(b_field.loc, "`%s.%s` is a bitfield", + b.toPrettyChars(), b_field.toChars()); + } + else if (bfb is null) + { + errorSupplemental(a_field.loc, "`%s.%s` *is a bitfield", + a.toPrettyChars(), a_field.toChars()); + errorSupplemental(b_field.loc, "`%s.%s` is not a bitfield", + b.toPrettyChars(), b_field.toChars()); + } + return false; + } + if (bfa !is null && bfb !is null) + { + if (bfa.fieldWidth != bfb.fieldWidth) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in bitfield width", i); + errorSupplemental(a_field.loc, "`%s.%s`: %u", + a.toPrettyChars(), a_field.toChars(), bfa.fieldWidth); + errorSupplemental(b_field.loc, "`%s.%s`: %u", + b.toPrettyChars(), b_field.toChars(), bfb.fieldWidth); + return false; + } + } + } + return true; + } + void interfaceSemantic(ClassDeclaration cd) { cd.vtblInterfaces = new BaseClasses(); @@ -4520,7 +4758,7 @@ private bool isDRuntimeHook(Identifier id) id == Id._d_arrayassign_l || id == Id._d_arrayassign_r || id == Id._d_arraysetassign || id == Id._d_arraysetctor || id == Id._d_arrayctor || - id == Id._d_arraysetlengthTImpl || id == Id._d_arraysetlengthT || + id == Id._d_arraysetlengthT || id == Id._d_arraysetlengthTTrace || id == Id._d_arrayappendT || id == Id._d_arrayappendTTrace || id == Id._d_arrayappendcTX; @@ -4903,7 +5141,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList if (tempinst.members.length) { Dsymbol s; - if (Dsymbol.oneMembers(tempinst.members, s, tempdecl.ident) && s) + if (oneMembers(tempinst.members, s, tempdecl.ident) && s) { //printf("tempdecl.ident = %s, s = `%s %s`\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars()); //printf("setting aliasdecl\n"); @@ -4948,7 +5186,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList if (tempinst.members.length) { Dsymbol s; - if (Dsymbol.oneMembers(tempinst.members, s, tempdecl.ident) && s) + if (oneMembers(tempinst.members, s, tempdecl.ident) && s) { if (!tempinst.aliasdecl || tempinst.aliasdecl != s) { @@ -7531,14 +7769,14 @@ private extern(C++) class NewScopeVisitor : Visitor } -extern(C++) Dsymbols* include(Dsymbol d, Scope* sc) +Dsymbols* include(Dsymbol d, Scope* sc) { - scope icv = new IncludeVisitor(sc); + scope icv = new ConditionIncludeVisitor(sc); d.accept(icv); return icv.symbols; } -extern(C++) class IncludeVisitor : Visitor +extern(C++) class ConditionIncludeVisitor : Visitor { alias visit = typeof(super).visit; Scope* sc; @@ -7570,7 +7808,7 @@ extern(C++) class IncludeVisitor : Visitor return; } assert(cdc.condition); - symbols = cdc.condition.include(cdc._scope ? cdc._scope : sc) ? cdc.decl : cdc.elsedecl; + symbols = dmd.expressionsem.include(cdc.condition, cdc._scope ? cdc._scope : sc) ? cdc.decl : cdc.elsedecl; } override void visit(StaticIfDeclaration sif) @@ -7891,7 +8129,7 @@ Lfail: return false; } -extern (C++) void addComment(Dsymbol d, const(char)* comment) +void addComment(Dsymbol d, const(char)* comment) { scope v = new AddCommentVisitor(comment); d.accept(v); @@ -8004,7 +8242,7 @@ private extern(C++) class OneMemberVisitor : Visitor override void visit(AttribDeclaration atb) { Dsymbols* d = atb.include(null); - result = Dsymbol.oneMembers(d, *ps, ident); + result = oneMembers(d, *ps, ident); } override void visit(StaticForeachDeclaration sfd) @@ -8027,7 +8265,7 @@ private extern(C++) class OneMemberVisitor : Visitor override void visit(StorageClassDeclaration scd) { - bool t = Dsymbol.oneMembers(scd.decl, *ps, ident); + bool t = oneMembers(scd.decl, *ps, ident); if (t && *ps) { /* This is to deal with the following case: @@ -8056,12 +8294,12 @@ private extern(C++) class OneMemberVisitor : Visitor //printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition.inc); if (cd.condition.inc != Include.notComputed) { - Dsymbols* d = cd.condition.include(null) ? cd.decl : cd.elsedecl; - result = Dsymbol.oneMembers(d, *ps, ident); + Dsymbols* d = dmd.expressionsem.include(cd.condition, null) ? cd.decl : cd.elsedecl; + result = oneMembers(d, *ps, ident); } else { - bool res = (Dsymbol.oneMembers(cd.decl, *ps, ident) && *ps is null && Dsymbol.oneMembers(cd.elsedecl, *ps, ident) && *ps is null); + bool res = (oneMembers(cd.decl, *ps, ident) && *ps is null && oneMembers(cd.elsedecl, *ps, ident) && *ps is null); *ps = null; result = res; } @@ -8070,7 +8308,7 @@ private extern(C++) class OneMemberVisitor : Visitor override void visit(ScopeDsymbol sd) { if (sd.isAnonymous()) - result = Dsymbol.oneMembers(sd.members, *ps, ident); + result = oneMembers(sd.members, *ps, ident); else { // visit(Dsymbol dsym) *ps = sd; @@ -8108,7 +8346,7 @@ private extern(C++) class OneMemberVisitor : Visitor * Return true if any of the members are static ctors or static dtors, or if * any members have members that are. */ -extern(C++) bool hasStaticCtorOrDtor(Dsymbol d) +bool hasStaticCtorOrDtor(Dsymbol d) { scope v = new HasStaticCtorOrDtor(); d.accept(v); @@ -8162,7 +8400,7 @@ private extern(C++) class HasStaticCtorOrDtor : Visitor } } -extern(C++) bool isFuncHidden(ClassDeclaration cd, FuncDeclaration fd) +bool isFuncHidden(ClassDeclaration cd, FuncDeclaration fd) { import dmd.funcsem : overloadApply; //printf("ClassDeclaration.isFuncHidden(class = %s, fd = %s)\n", toChars(), fd.toPrettyChars()); @@ -8210,3 +8448,618 @@ Dsymbol vtblSymbol(ClassDeclaration cd) } return cd.vtblsym; } + +bool isAbstract(ClassDeclaration cd) +{ + enum log = false; + if (cd.isabstract != ThreeState.none) + return cd.isabstract == ThreeState.yes; + + if (log) printf("isAbstract(%s)\n", cd.toChars()); + + bool no() { if (log) printf("no\n"); cd.isabstract = ThreeState.no; return false; } + bool yes() { if (log) printf("yes\n"); cd.isabstract = ThreeState.yes; return true; } + + if (cd.storage_class & STC.abstract_ || cd._scope && cd._scope.stc & STC.abstract_) + return yes(); + + if (cd.errors) + return no(); + + /* https://issues.dlang.org/show_bug.cgi?id=11169 + * Resolve forward references to all class member functions, + * and determine whether this class is abstract. + */ + static int func(Dsymbol s, void*) + { + auto fd = s.isFuncDeclaration(); + if (!fd) + return 0; + if (fd.storage_class & STC.static_) + return 0; + + if (fd.isAbstract()) + return 1; + return 0; + } + + // opaque class is not abstract if it is not declared abstract + if (!(cd.members)) + return no(); + + for (size_t i = 0; i < cd.members.length; i++) + { + auto s = (*(cd.members))[i]; + if (s.apply(&func, null)) + { + return yes(); + } + } + + /* If the base class is not abstract, then this class cannot + * be abstract. + */ + if (!cd.isInterfaceDeclaration() && (!cd.baseClass || !cd.baseClass.isAbstract())) + return no(); + + /* If any abstract functions are inherited, but not overridden, + * then the class is abstract. Do this by checking the vtbl[]. + * Need to do semantic() on class to fill the vtbl[]. + */ + cd.dsymbolSemantic(null); + + /* The next line should work, but does not because when ClassDeclaration.dsymbolSemantic() + * is called recursively it can set PASS.semanticdone without finishing it. + */ + //if (semanticRun < PASS.semanticdone) + { + /* Could not complete semantic(). Try running semantic() on + * each of the virtual functions, + * which will fill in the vtbl[] overrides. + */ + static int virtualSemantic(Dsymbol s, void*) + { + auto fd = s.isFuncDeclaration(); + if (fd && !(fd.storage_class & STC.static_) && !fd.isUnitTestDeclaration()) + fd.dsymbolSemantic(null); + return 0; + } + + for (size_t i = 0; i < cd.members.length; i++) + { + auto s = (*(cd.members))[i]; + s.apply(&virtualSemantic,null); + } + } + + /* Finally, check the vtbl[] + */ + foreach (i; 1 .. cd.vtbl.length) + { + auto fd = cd.vtbl[i].isFuncDeclaration(); + //if (fd) printf("\tvtbl[%d] = [%s] %s\n", i, fd.loc.toChars(), fd.toPrettyChars()); + if (!fd || fd.isAbstract()) + { + return yes(); + } + } + + return no(); +} + +void finalizeSize(AggregateDeclaration ad) +{ + scope v = new FinalizeSizeVisitor(); + ad.accept(v); +} + +/********************************** + * Determine if exp is all binary zeros. + * Params: + * exp = expression to check + * Returns: + * true if it's all binary 0 + */ +bool _isZeroInit(Expression exp) +{ + switch (exp.op) + { + case EXP.int64: + return exp.toInteger() == 0; + + case EXP.null_: + return true; + + case EXP.structLiteral: + { + auto sle = exp.isStructLiteralExp(); + if (sle.sd.isNested()) + return false; + const isCstruct = sle.sd.isCsymbol(); // C structs are default initialized to all zeros + foreach (i; 0 .. sle.sd.fields.length) + { + auto field = sle.sd.fields[i]; + if (field.type.size(field.loc)) + { + auto e = sle.elements && i < sle.elements.length ? (*sle.elements)[i] : null; + if (e ? !_isZeroInit(e) + : !isCstruct && !field.type.isZeroInit(field.loc)) + return false; + } + } + return true; + } + + case EXP.arrayLiteral: + { + auto ale = cast(ArrayLiteralExp)exp; + + const dim = ale.elements ? ale.elements.length : 0; + + if (ale.type.toBasetype().ty == Tarray) // if initializing a dynamic array + return dim == 0; + + foreach (i; 0 .. dim) + { + if (!_isZeroInit(ale[i])) + return false; + } + + /* Note that true is returned for all T[0] + */ + return true; + } + + case EXP.string_: + { + auto se = cast(StringExp)exp; + + if (se.type.toBasetype().ty == Tarray) // if initializing a dynamic array + return se.len == 0; + + foreach (i; 0 .. se.len) + { + if (se.getIndex(i) != 0) + return false; + } + return true; + } + + case EXP.vector: + { + auto ve = cast(VectorExp) exp; + return _isZeroInit(ve.e1); + } + + case EXP.float64: + case EXP.complex80: + { + import dmd.root.ctfloat : CTFloat; + return (exp.toReal() is CTFloat.zero) && + (exp.toImaginary() is CTFloat.zero); + } + + default: + return false; + } +} + +private extern(C++) class FinalizeSizeVisitor : Visitor +{ + alias visit = Visitor.visit; + + override void visit(ClassDeclaration outerCd) + { + assert(outerCd.sizeok != Sizeok.done); + + // Set the offsets of the fields and determine the size of the class + if (outerCd.baseClass) + { + assert(outerCd.baseClass.sizeok == Sizeok.done); + + outerCd.alignsize = outerCd.baseClass.alignsize; + if (outerCd.classKind == ClassKind.cpp) + outerCd.structsize = target.cpp.derivedClassOffset(outerCd.baseClass); + else + outerCd.structsize = outerCd.baseClass.structsize; + } + else if (outerCd.classKind == ClassKind.objc) + outerCd.structsize = 0; // no hidden member for an Objective-C class + else if (outerCd.isInterfaceDeclaration()) + { + if (outerCd.interfaces.length == 0) + { + outerCd.alignsize = target.ptrsize; + outerCd.structsize = target.ptrsize; // allow room for __vptr + } + } + else + { + outerCd.alignsize = target.ptrsize; + outerCd.structsize = target.ptrsize; // allow room for __vptr + if (outerCd.hasMonitor()) + outerCd.structsize += target.ptrsize; // allow room for __monitor + } + + //printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok); + size_t bi = 0; // index into vtblInterfaces[] + + /**** + * Runs through the inheritance graph to set the BaseClass.offset fields. + * Recursive in order to account for the size of the interface classes, if they are + * more than just interfaces. + * Params: + * cd = interface to look at + * baseOffset = offset of where cd will be placed + * Returns: + * subset of instantiated size used by cd for interfaces + */ + uint membersPlace(ClassDeclaration cd, uint baseOffset) + { + //printf(" membersPlace(%s, %d)\n", cd.toChars(), baseOffset); + uint offset = baseOffset; + + foreach (BaseClass* b; cd.interfaces) + { + if (b.sym.sizeok != Sizeok.done) + b.sym.finalizeSize(); + assert(b.sym.sizeok == Sizeok.done); + + if (!b.sym.alignsize) + b.sym.alignsize = target.ptrsize; + offset = alignmember(structalign_t(cast(ushort)b.sym.alignsize), b.sym.alignsize, offset); + assert(bi < outerCd.vtblInterfaces.length); + + BaseClass* bv = (*(outerCd.vtblInterfaces))[bi]; + if (b.sym.interfaces.length == 0) + { + //printf("\tvtblInterfaces[%d] b=%p b.sym = %s, offset = %d\n", bi, bv, bv.sym.toChars(), offset); + bv.offset = offset; + ++bi; + // All the base interfaces down the left side share the same offset + for (BaseClass* b2 = bv; b2.baseInterfaces.length; ) + { + b2 = &b2.baseInterfaces[0]; + b2.offset = offset; + //printf("\tvtblInterfaces[%d] b=%p sym = %s, offset = %d\n", bi, b2, b2.sym.toChars(), b2.offset); + } + } + membersPlace(b.sym, offset); + //printf(" %s size = %d\n", b.sym.toChars(), b.sym.structsize); + offset += b.sym.structsize; + if (outerCd.alignsize < b.sym.alignsize) + outerCd.alignsize = b.sym.alignsize; + } + return offset - baseOffset; + } + + outerCd.structsize += membersPlace(outerCd, outerCd.structsize); + + if (outerCd.isInterfaceDeclaration()) + { + outerCd.sizeok = Sizeok.done; + return; + } + + // FIXME: Currently setFieldOffset functions need to increase fields + // to calculate each variable offsets. It can be improved later. + outerCd.fields.setDim(0); + + FieldState fieldState; + fieldState.offset = outerCd.structsize; + foreach (s; *(outerCd.members)) + { + s.setFieldOffset(outerCd, &fieldState, false); + } + + outerCd.sizeok = Sizeok.done; + + // Calculate fields[i].overlapped + outerCd.checkOverlappedFields(); + } + + override void visit(StructDeclaration sd) + { + //printf("StructDeclaration::finalizeSize() %s, sizeok = %d\n", toChars(), sizeok); + assert(sd.sizeok != Sizeok.done); + + if (sd.sizeok == Sizeok.inProcess) + { + return; + } + sd.sizeok = Sizeok.inProcess; + + //printf("+StructDeclaration::finalizeSize() %s, fields.length = %d, sizeok = %d\n", toChars(), fields.length, sizeok); + + sd.fields.setDim(0); // workaround + + // Set the offsets of the fields and determine the size of the struct + FieldState fieldState; + bool isunion = sd.isUnionDeclaration() !is null; + for (size_t i = 0; i < sd.members.length; i++) + { + Dsymbol s = (*sd.members)[i]; + s.setFieldOffset(sd, &fieldState, isunion); + if (sd.type.ty == Terror) + { + errorSupplemental(s.loc, "error on member `%s`", s.toPrettyChars); + sd.errors = true; + return; + } + } + + if (sd.structsize == 0) + { + sd.hasNoFields = true; + sd.alignsize = 1; + + // A fine mess of what size a zero sized struct should be + final switch (sd.classKind) + { + case ClassKind.d: + case ClassKind.cpp: + sd.structsize = 1; + break; + + case ClassKind.c: + case ClassKind.objc: + if (target.c.bitFieldStyle == TargetC.BitFieldStyle.MS) + { + /* Undocumented MS behavior for: + * struct S { int :0; }; + */ + sd.structsize = 4; + } + else + sd.structsize = 0; + break; + } + } + + // Round struct size up to next alignsize boundary. + // This will ensure that arrays of structs will get their internals + // aligned properly. + if (sd.alignment.isDefault() || sd.alignment.isPack()) + sd.structsize = (sd.structsize + sd.alignsize - 1) & ~(sd.alignsize - 1); + else + sd.structsize = (sd.structsize + sd.alignment.get() - 1) & ~(sd.alignment.get() - 1); + + sd.sizeok = Sizeok.done; + + //printf("-StructDeclaration::finalizeSize() %s, fields.length = %d, structsize = %d\n", toChars(), cast(int)fields.length, cast(int)structsize); + + if (sd.errors) + return; + + // Calculate fields[i].overlapped + if (sd.checkOverlappedFields()) + { + sd.errors = true; + return; + } + + // Determine if struct is all zeros or not + sd.zeroInit = true; + auto lastOffset = -1; + foreach (vd; sd.fields) + { + // First skip zero sized fields + if (vd.type.size(vd.loc) == 0) + continue; + + // only consider first sized member of an (anonymous) union + if (vd.overlapped && vd.offset == lastOffset) + continue; + lastOffset = vd.offset; + + if (vd._init) + { + if (vd._init.isVoidInitializer()) + /* Treat as 0 for the purposes of putting the initializer + * in the BSS segment, or doing a mass set to 0 + */ + continue; + + // Examine init to see if it is all 0s. + auto exp = vd.getConstInitializer(); + if (!exp || !_isZeroInit(exp)) + { + sd.zeroInit = false; + break; + } + } + else if (!vd.type.isZeroInit(sd.loc)) + { + sd.zeroInit = false; + break; + } + } + + + sd.argTypes = target.toArgTypes(sd.type); + } +} + +/***************************************** +* Is Dsymbol a variable that contains pointers? +*/ +bool hasPointers(Dsymbol d) +{ + scope v = new HasPointersVisitor(); + d.accept(v); + return v.result; +} + +private extern(C++) class HasPointersVisitor : Visitor +{ + import dmd.mtype : Type; + + alias visit = Visitor.visit; + bool result; + + override void visit(AttribDeclaration ad) + { + result = ad.include(null).foreachDsymbol( (s) { return s.hasPointers(); } ) != 0; + } + + override void visit(VarDeclaration vd) + { + import dmd.typesem : hasPointers; + result = (!vd.isDataseg() && vd.type.hasPointers()); + } + + override void visit(Dsymbol d) + { + //printf("Dsymbol::hasPointers() %s\n", toChars()); + result = false; + } + + override void visit(TemplateMixin tm) + { + //printf("TemplateMixin.hasPointers() %s\n", toChars()); + result = tm.members.foreachDsymbol( (s) { return s.hasPointers(); } ) != 0; + } + + override void visit(Nspace ns) + { + //printf("Nspace::hasPointers() %s\n", toChars()); + result = ns.members.foreachDsymbol( (s) { return s.hasPointers(); } ) != 0; + } +} + +/*************************************** + * Expands attribute declarations in members in depth first + * order. Calls dg(size_t symidx, Dsymbol *sym) for each + * member. + * If dg returns !=0, stops and returns that value else returns 0. + * Use this function to avoid the O(N + N^2/2) complexity of + * calculating dim and calling N times getNth. + * Returns: + * last value returned by dg() + */ +int _foreach(Scope* sc, Dsymbols* members, scope ForeachDg dg, size_t* pn = null) +{ + assert(dg); + if (!members) + return 0; + size_t n = pn ? *pn : 0; // take over index + int result = 0; + foreach (size_t i; 0 .. members.length) + { + import dmd.attrib : AttribDeclaration; + import dmd.dtemplate : TemplateMixin; + + Dsymbol s = (*members)[i]; + if (AttribDeclaration a = s.isAttribDeclaration()) + result = _foreach(sc, a.include(sc), dg, &n); + else if (TemplateMixin tm = s.isTemplateMixin()) + result = _foreach(sc, tm.members, dg, &n); + else if (s.isTemplateInstance()) + { + } + else if (s.isUnitTestDeclaration()) + { + } + else + result = dg(n++, s); + if (result) + break; + } + if (pn) + *pn = n; // update index + return result; +} + +/**************************************** + * Create array of the local classes in the Module, suitable + * for inclusion in ModuleInfo + * Params: + * mod = the Module + * aclasses = array to fill in + * Returns: array of local classes + */ +void getLocalClasses(Module mod, ref ClassDeclarations aclasses) +{ + //printf("members.length = %d\n", mod.members.length); + int pushAddClassDg(size_t n, Dsymbol sm) + { + if (!sm) + return 0; + + if (auto cd = sm.isClassDeclaration()) + { + // compatibility with previous algorithm + if (cd.parent && cd.parent.isTemplateMixin()) + return 0; + + if (cd.classKind != ClassKind.objc) + aclasses.push(cd); + } + return 0; + } + + _foreach(null, mod.members, &pushAddClassDg); +} + +/***************************************** +* Same as Dsymbol::oneMember(), but look at an array of Dsymbols. +*/ +extern (D) bool oneMembers(Dsymbols* members, out Dsymbol ps, Identifier ident) +{ + //printf("Dsymbol::oneMembers() %d\n", members ? members.length : 0); + Dsymbol s = null; + if (!members) + { + ps = null; + return true; + } + + for (size_t i = 0; i < members.length; i++) + { + Dsymbol sx = (*members)[i]; + bool x = sx.oneMember(ps, ident); //MYTODO: this temporarily creates a new dependency to dsymbolsem, will need to extract oneMembers() later + //printf("\t[%d] kind %s = %d, s = %p\n", i, sx.kind(), x, *ps); + if (!x) + { + //printf("\tfalse 1\n"); + assert(ps is null); + return false; + } + if (ps) + { + assert(ident); + if (!ps.ident || !ps.ident.equals(ident)) + continue; + if (!s) + s = ps; + else if (s.isOverloadable() && ps.isOverloadable()) + { + // keep head of overload set + FuncDeclaration f1 = s.isFuncDeclaration(); + FuncDeclaration f2 = ps.isFuncDeclaration(); + if (f1 && f2) + { + assert(!f1.isFuncAliasDeclaration()); + assert(!f2.isFuncAliasDeclaration()); + for (; f1 != f2; f1 = f1.overnext0) + { + if (f1.overnext0 is null) + { + f1.overnext0 = f2; + break; + } + } + } + } + else // more than one symbol + { + ps = null; + //printf("\tfalse 2\n"); + return false; + } + } + } + ps = s; // s is the one symbol, null if none + //printf("\ttrue\n"); + return true; +} diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d index 215889574570..16e192da20ff 100644 --- a/gcc/d/dmd/dtemplate.d +++ b/gcc/d/dmd/dtemplate.d @@ -53,7 +53,7 @@ import dmd.dinterpret; import dmd.dmodule; import dmd.dscope; import dmd.dsymbol; -import dmd.dsymbolsem : dsymbolSemantic, checkDeprecated, aliasSemantic, search, search_correct, setScope, importAll, include, hasStaticCtorOrDtor; +import dmd.dsymbolsem : dsymbolSemantic, checkDeprecated, aliasSemantic, search, search_correct, setScope, importAll, include, hasStaticCtorOrDtor, oneMembers; import dmd.errors; import dmd.errorsink; import dmd.expression; @@ -593,6 +593,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol bool isTrivialAliasSeq; /// matches pattern `template AliasSeq(T...) { alias AliasSeq = T; }` bool isTrivialAlias; /// matches pattern `template Alias(T) { alias Alias = qualifiers(T); }` bool deprecated_; /// this template declaration is deprecated + bool isCmacro; /// Whether this template is a translation of a C macro Visibility visibility; // threaded list of previous instantiation attempts on stack @@ -639,7 +640,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol return; Dsymbol s; - if (!Dsymbol.oneMembers(members, s, ident) || !s) + if (!oneMembers(members, s, ident) || !s) return; onemember = s; @@ -3661,11 +3662,11 @@ extern (C++) class TemplateInstance : ScopeDsymbol ScopeDsymbol argsym; // argument symbol table size_t hash; // cached result of toHash() - /// For function template, these are the function names and arguments + /// For function template, these are the function fnames(name and loc of it) and arguments /// Relevant because different resolutions of `auto ref` parameters /// create different template instances even with the same template arguments Expressions* fargs; - Identifiers* fnames; + ArgumentLabels* fnames; TemplateInstances* deferred; @@ -5273,7 +5274,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol if (members.length) { Dsymbol sa; - if (Dsymbol.oneMembers(members, sa, tempdecl.ident) && sa) + if (oneMembers(members, sa, tempdecl.ident) && sa) aliasdecl = sa; } done = true; @@ -5490,12 +5491,6 @@ extern (C++) final class TemplateMixin : TemplateInstance return "mixin"; } - override bool hasPointers() - { - //printf("TemplateMixin.hasPointers() %s\n", toChars()); - return members.foreachDsymbol( (s) { return s.hasPointers(); } ) != 0; - } - extern (D) bool findTempDecl(Scope* sc) { // Follow qualifications to find the TemplateDeclaration diff --git a/gcc/d/dmd/enumsem.d b/gcc/d/dmd/enumsem.d index 4f0d4e5f53f2..6d325e44c964 100644 --- a/gcc/d/dmd/enumsem.d +++ b/gcc/d/dmd/enumsem.d @@ -81,7 +81,7 @@ import dmd.visitor; /********************************* - * Perform semantic analysis on enum declaration `em` + * Perform semantic analysis on enum declaration `ed` */ void enumSemantic(Scope* sc, EnumDeclaration ed) { @@ -158,9 +158,10 @@ void enumSemantic(Scope* sc, EnumDeclaration ed) ed.semanticRun = PASS.initial; return; } - else - // Ensure that semantic is run to detect. e.g. invalid forward references - sym.dsymbolSemantic(sc); + // Ensure that semantic is run to detect. e.g. invalid forward references + sym.dsymbolSemantic(sc); + if (ed.errors) + ed.memtype = Type.terror; // avoid infinite recursion in toBaseType } if (ed.memtype.ty == Tvoid) { @@ -175,6 +176,8 @@ void enumSemantic(Scope* sc, EnumDeclaration ed) ed.semanticRun = PASS.semanticdone; return; } + if (global.params.useTypeInfo && Type.dtypeinfo && !ed.inNonRoot()) + semanticTypeInfo(sc, ed.memtype); } if (!ed.members) // enum ident : memtype; @@ -229,122 +232,24 @@ void enumSemantic(Scope* sc, EnumDeclaration ed) addEnumMembersToSymtab(ed, sc, sc.getScopesym()); if (sc.inCfile) - { - /* C11 6.7.2.2 - */ - Type commonType = ed.memtype; - if (!commonType) - commonType = Type.tint32; - ulong nextValue = 0; // C11 6.7.2.2-3 first member value defaults to 0 - - // C11 6.7.2.2-2 value must be representable as an int. - // The sizemask represents all values that int will fit into, - // from 0..uint.max. We want to cover int.min..uint.max. - IntRange ir = IntRange.fromType(commonType); - - void emSemantic(EnumMember em, ref ulong nextValue) - { - static void errorReturn(EnumMember em) - { - em.value = ErrorExp.get(); - em.errors = true; - em.semanticRun = PASS.semanticdone; - } - - em.semanticRun = PASS.semantic; - em.type = commonType; - em._linkage = LINK.c; - em.storage_class |= STC.manifest; - if (em.value) - { - Expression e = em.value; - assert(e.dyncast() == DYNCAST.expression); - - /* To merge the type of e with commonType, add 0 of type commonType - */ - if (!ed.memtype) - e = new AddExp(em.loc, e, new IntegerExp(em.loc, 0, commonType)); - - e = e.expressionSemantic(sc); - e = resolveProperties(sc, e); - e = e.integralPromotions(sc); - e = e.ctfeInterpret(); - if (e.op == EXP.error) - return errorReturn(em); - auto ie = e.isIntegerExp(); - if (!ie) - { - // C11 6.7.2.2-2 - .error(em.loc, "%s `%s` enum member must be an integral constant expression, not `%s` of type `%s`", em.kind, em.toPrettyChars, e.toChars(), e.type.toChars()); - return errorReturn(em); - } - if (ed.memtype && !ir.contains(getIntRange(ie))) - { - // C11 6.7.2.2-2 - .error(em.loc, "%s `%s` enum member value `%s` does not fit in `%s`", em.kind, em.toPrettyChars, e.toChars(), commonType.toChars()); - return errorReturn(em); - } - nextValue = ie.toInteger(); - if (!ed.memtype) - commonType = e.type; - em.value = new IntegerExp(em.loc, nextValue, commonType); - } - else - { - // C11 6.7.2.2-3 add 1 to value of previous enumeration constant - bool first = (em == (*em.ed.members)[0]); - if (!first) - { - Expression max = getProperty(commonType, null, em.loc, Id.max, 0); - if (nextValue == max.toInteger()) - { - .error(em.loc, "%s `%s` initialization with `%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars, max.toChars(), commonType.toChars()); - return errorReturn(em); - } - nextValue += 1; - } - em.value = new IntegerExp(em.loc, nextValue, commonType); - } - em.type = commonType; - em.semanticRun = PASS.semanticdone; - } - - ed.members.foreachDsymbol( (s) - { - if (EnumMember em = s.isEnumMember()) - emSemantic(em, nextValue); - }); - - if (!ed.memtype) - { - // cast all members to commonType - ed.members.foreachDsymbol( (s) - { - if (EnumMember em = s.isEnumMember()) - { - em.type = commonType; - // optimize out the cast so that other parts of the compiler can - // assume that an integral enum's members are `IntegerExp`s. - // https://issues.dlang.org/show_bug.cgi?id=24504 - em.value = em.value.castTo(sc, commonType).optimize(WANTvalue); - } - }); - } - - ed.memtype = commonType; - ed.semanticRun = PASS.semanticdone; - return; - } + return cEnumSemantic(sc, ed); ed.members.foreachDsymbol( (s) { if (EnumMember em = s.isEnumMember()) em.dsymbolSemantic(em._scope); }); + + if (global.params.useTypeInfo && Type.dtypeinfo && !ed.inNonRoot()) + semanticTypeInfo(sc, ed.memtype); //printf("ed.defaultval = %lld\n", ed.defaultval); //if (ed.defaultval) printf("ed.defaultval: %s %s\n", ed.defaultval.toChars(), ed.defaultval.type.toChars()); //printf("members = %s\n", members.toChars()); + + // Set semantic2done here to indicate all members have been processed + // This prevents using the enum in a final switch while being defined + ed.semanticRun = PASS.semantic2done; } Expression getDefaultValue(EnumDeclaration ed, Loc loc) @@ -625,6 +530,21 @@ void enumMemberSemantic(Scope* sc, EnumMember em) }); assert(emprev); + + // New check: if the base type is an enum, auto-increment is not supported, + // unless it is a special enum (for example, the C types like cpp_long/longlong). + if (auto te = em.ed.memtype ? em.ed.memtype.isTypeEnum() : null) + { + if (!te.sym.isSpecial()) + { + error(em.loc, + "cannot automatically assign value to enum member `%s` because base type `%s` is an enum; provide an explicit value", + em.toPrettyChars(), em.ed.memtype.toChars()); + return errorReturn(); + } + } + + if (emprev.semanticRun < PASS.semanticdone) // if forward reference emprev.dsymbolSemantic(emprev._scope); // resolve it if (emprev.errors) diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d index d65b163ee668..c29484d9e7bf 100644 --- a/gcc/d/dmd/expression.d +++ b/gcc/d/dmd/expression.d @@ -86,7 +86,7 @@ inout(Expression) lastComma(inout Expression e) * exps = array of Expressions * names = optional array of names corresponding to Expressions */ -void expandTuples(Expressions* exps, Identifiers* names = null) +void expandTuples(Expressions* exps, ArgumentLabels* names = null) { //printf("expandTuples()\n"); if (exps is null) @@ -116,7 +116,7 @@ void expandTuples(Expressions* exps, Identifiers* names = null) } foreach (i; 1 .. length) { - names.insert(index + i, cast(Identifier) null); + names.insert(index + i, ArgumentLabel(cast(Identifier) null, Loc.init)); } } } @@ -306,6 +306,7 @@ extern (C++) abstract class Expression : ASTNode { bool parens; // if this is a parenthesized expression bool rvalue; // true if this is considered to be an rvalue, even if it is an lvalue + bool gcPassDone; // `checkGC` has been run on this expression } import dmd.common.bitfields; mixin(generateBitFields!(BitFields, ubyte)); @@ -1405,6 +1406,8 @@ extern (C++) final class StringExp : Expression /// If the string is parsed from a hex string literal bool hexString = false; + /// If the string is from a collected C macro + bool cMacro = false; enum char NoPostfix = 0; @@ -1416,13 +1419,14 @@ extern (C++) final class StringExp : Expression this.sz = 1; // work around LDC bug #1286 } - extern (D) this(Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix = NoPostfix) scope + extern (D) this(Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix = NoPostfix, bool cMacro = false) scope { super(loc, EXP.string_); this.string = cast(char*)string.ptr; // note that this.string should be const this.len = len; this.sz = sz; this.postfix = postfix; + this.cMacro = cMacro; } static StringExp create(Loc loc, const(char)* s) @@ -2445,7 +2449,7 @@ extern (C++) final class NewExp : Expression Expression thisexp; // if !=null, 'this' for class being allocated Type newtype; Expressions* arguments; // Array of Expression's - Identifiers* names; // Array of names corresponding to expressions + ArgumentLabels* names; // Array of names(name and location of name) corresponding to expressions Expression placement; // if !=null, then PlacementExpression Expression argprefix; // expression to be evaluated just before arguments[] @@ -2457,9 +2461,10 @@ extern (C++) final class NewExp : Expression /// Puts the `arguments` and `names` into an `ArgumentList` for easily passing them around. /// The fields are still separate for backwards compatibility + extern (D) ArgumentList argumentList() { return ArgumentList(arguments, names); } - extern (D) this(Loc loc, Expression placement, Expression thisexp, Type newtype, Expressions* arguments, Identifiers* names = null) @safe + extern (D) this(Loc loc, Expression placement, Expression thisexp, Type newtype, Expressions* arguments, ArgumentLabels* names = null) @safe { super(loc, EXP.new_); this.placement = placement; @@ -3271,29 +3276,36 @@ extern (C++) final class DotTypeExp : UnaExp struct ArgumentList { Expressions* arguments; // function arguments - Identifiers* names; // named argument identifiers + ArgumentLabels* names; // named argument labels size_t length() const @nogc nothrow pure @safe { return arguments ? arguments.length : 0; } /// Returns: whether this argument list contains any named arguments - bool hasNames() const @nogc nothrow pure @safe + bool hasArgNames() const @nogc nothrow pure @safe { if (names is null) return false; - foreach (name; *names) - if (name !is null) + foreach (argLabel; *names) + if (argLabel.name !is null) return true; return false; } } +// Contains both `name` and `location of the name` for an expression. +struct ArgumentLabel +{ + Identifier name; // name of the argument + Loc loc; // location of the name + } + /*********************************************************** */ extern (C++) final class CallExp : UnaExp { Expressions* arguments; // function arguments - Identifiers* names; // named argument identifiers + ArgumentLabels *names; // named argument labels FuncDeclaration f; // symbol to call bool directcall; // true if a virtual call is devirtualized bool inDebugStatement; /// true if this was in a debug statement @@ -3305,7 +3317,7 @@ extern (C++) final class CallExp : UnaExp /// The fields are still separate for backwards compatibility extern (D) ArgumentList argumentList() { return ArgumentList(arguments, names); } - extern (D) this(Loc loc, Expression e, Expressions* exps, Identifiers* names = null) @safe + extern (D) this(Loc loc, Expression e, Expressions* exps, ArgumentLabels *names = null) @safe { super(loc, EXP.call, e); this.arguments = exps; @@ -3851,6 +3863,9 @@ extern (C++) final class CommaExp : BinExp /// false will be passed will be from the parser. bool allowCommaExp; + /// The original expression before any rewriting occurs. + /// This is used in error messages. + Expression originalExp; extern (D) this(Loc loc, Expression e1, Expression e2, bool generated = true) @safe { @@ -3858,6 +3873,12 @@ extern (C++) final class CommaExp : BinExp allowCommaExp = isGenerated = generated; } + extern (D) this(Loc loc, Expression e1, Expression e2, Expression oe) @safe + { + this(loc, e1, e2); + originalExp = oe; + } + override bool isLvalue() { return !rvalue && e2.isLvalue(); diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h index 3c8d90dd7eb6..6b4298b3308b 100644 --- a/gcc/d/dmd/expression.h +++ b/gcc/d/dmd/expression.h @@ -51,14 +51,13 @@ namespace dmd { // in expressionsem.d Expression *expressionSemantic(Expression *e, Scope *sc); - void lowerNonArrayAggregate(StaticForeach *sfe, Scope *sc); // in typesem.d Expression *defaultInit(Type *mt, Loc loc, const bool isCfile = false); // Entry point for CTFE. // A compile-time result is required. Give an error if not possible Expression *ctfeInterpret(Expression *e); - void expandTuples(Expressions *exps, Identifiers *names = nullptr); + void expandTuples(Expressions *exps, ArgumentLabels *names = nullptr); Expression *optimize(Expression *exp, int result, bool keepLvalue = false); } @@ -354,6 +353,7 @@ public: unsigned char sz; // 1: char, 2: wchar, 4: dchar d_bool committed; // if type is committed d_bool hexString; // if string is parsed from a hex string literal + d_bool cMacro; // If the string is from a collected C macro static StringExp *create(Loc loc, const char *s); static StringExp *create(Loc loc, const void *s, d_size_t len); @@ -518,7 +518,7 @@ public: Expression *thisexp; // if !NULL, 'this' for class being allocated Type *newtype; Expressions *arguments; // Array of Expression's - Identifiers *names; // Array of names corresponding to expressions + ArgumentLabels *names; // Array of argument Labels (name and location of name) corresponding to expressions Expression *placement; // if !NULL, placement expression Expression *argprefix; // expression to be evaluated just before arguments[] @@ -795,23 +795,38 @@ public: struct ArgumentList final { Expressions* arguments; - Identifiers* names; + ArgumentLabels* names; ArgumentList() : arguments(), names() { } - ArgumentList(Expressions* arguments, Identifiers* names = nullptr) : + ArgumentList(Expressions* arguments, ArgumentLabels* names = nullptr) : arguments(arguments), names(names) {} }; +struct ArgumentLabel final +{ + Identifier* name; + Loc loc; + ArgumentLabel() : + name(), + loc() + { + } + ArgumentLabel(Identifier* name, Loc loc = Loc()) : + name(name), + loc(loc) + {} +}; + class CallExp final : public UnaExp { public: Expressions *arguments; // function arguments - Identifiers *names; + ArgumentLabels* names; // function argument Labels (name + location of name) FuncDeclaration *f; // symbol to call d_bool directcall; // true if a virtual call is devirtualized d_bool inDebugStatement; // true if this was in a debug statement @@ -935,6 +950,7 @@ public: class ArrayLengthExp final : public UnaExp { public: + Expression lowering; void accept(Visitor *v) override { v->visit(this); } }; @@ -990,6 +1006,7 @@ class CommaExp final : public BinExp public: d_bool isGenerated; d_bool allowCommaExp; + Expression* originalExp; bool isLvalue() override; Optional toBool() override; void accept(Visitor *v) override { v->visit(this); } diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index b02f6ea64102..2576d7c0d056 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -1334,8 +1334,8 @@ private Expression resolveUFCS(Scope* sc, CallExp ce) ce.arguments = new Expressions(); ce.arguments.shift(eleft); if (!ce.names) - ce.names = new Identifiers(); - ce.names.shift(null); + ce.names = new ArgumentLabels(); + ce.names.shift(ArgumentLabel(cast(Identifier) null, Loc.init)); ce.isUfcsRewrite = true; return null; } @@ -4115,16 +4115,28 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor /* Look for what user might have meant */ - if (const n = importHint(exp.ident.toString())) - error(exp.loc, "`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr); - else if (auto s2 = sc.search_correct(exp.ident)) - error(exp.loc, "undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars()); - else if (const p = Scope.search_correct_C(exp.ident)) - error(exp.loc, "undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p); - else if (exp.ident == Id.dollar) - error(exp.loc, "undefined identifier `$`"); + if (!(sc && sc.inCfile)) + { + if (const n = importHint(exp.ident.toString())) + error(exp.loc, "`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr); + else if (auto s2 = sc.search_correct(exp.ident)) + error(exp.loc, "undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars()); + else if (const p = Scope.search_correct_C(exp.ident)) + error(exp.loc, "undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p); + else if (exp.ident == Id.dollar) + error(exp.loc, "undefined identifier `$`"); + else + error(exp.loc, "undefined identifier `%s`", exp.ident.toChars()); + } else - error(exp.loc, "undefined identifier `%s`", exp.ident.toChars()); + { + if (const n = cIncludeHint(exp.ident.toString())) + error(exp.loc, "`%s` is not defined, perhaps `#include %.*s` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr); + else if (auto s2 = sc.search_correct(exp.ident)) + error(exp.loc, "undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars()); + else + error(exp.loc, "undefined identifier `%s`", exp.ident.toChars()); + } result = ErrorExp.get(); } @@ -4416,7 +4428,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } buffer.write4(0); e.setData(buffer.extractData(), newlen, 4); - if (sc && sc.inCfile) + if (!e.cMacro && sc && sc.inCfile) e.type = Type.tuns32.sarrayOf(e.len + 1); else e.type = Type.tdchar.immutableOf().arrayOf(); @@ -4441,7 +4453,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } buffer.writeUTF16(0); e.setData(buffer.extractData(), newlen, 2); - if (sc && sc.inCfile) + if (!e.cMacro && sc && sc.inCfile) e.type = Type.tuns16.sarrayOf(e.len + 1); else e.type = Type.twchar.immutableOf().arrayOf(); @@ -4453,7 +4465,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor goto default; default: - if (sc && sc.inCfile) + if (!e.cMacro && sc && sc.inCfile) e.type = Type.tchar.sarrayOf(e.len + 1); else e.type = Type.tchar.immutableOf().arrayOf(); @@ -4551,7 +4563,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { printf("AssocArrayLiteralExp::semantic('%s')\n", e.toChars()); } - + if (e.type) + { + // already done, but we might have missed generating type info + semanticTypeInfo(sc, e.type); + result = e; + return; + } // Run semantic() on each element bool err_keys = arrayExpressionSemantic(e.keys.peekSlice(), sc); bool err_vals = arrayExpressionSemantic(e.values.peekSlice(), sc); @@ -4894,6 +4912,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor error(p.loc, "PlacementExpression `%s` of type `%s` be unshared and mutable", p.toChars(), toChars(p.type)); return setError(); } + checkModifiable(exp.placement, sc); } //for error messages if the argument in [] is not convertible to size_t @@ -5294,10 +5313,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { if (exp.names) { - exp.arguments = resolveStructLiteralNamedArgs(sd, exp.type, sc, exp.loc, - exp.names ? (*exp.names)[] : null, + exp.arguments = resolveStructLiteralNamedArgs(sd, exp.type, sc, exp.loc, exp.names.length, + i => (*exp.names)[i].name, (size_t i, Type t) => (*exp.arguments)[i], - i => (*exp.arguments)[i].loc + i => (*exp.arguments)[i].loc, + i => (*exp.names)[i].loc ); if (!exp.arguments) return setError(); @@ -5361,9 +5381,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } Expression arg = (*exp.arguments)[i]; - if (exp.names && (*exp.names)[i]) + if (exp.names && (*exp.names)[i].name) { - error(exp.loc, "no named argument `%s` allowed for array dimension", (*exp.names)[i].toChars()); + error(exp.loc, "no named argument `%s` allowed for array dimension", (*exp.names)[i].name.toChars()); return setError(); } @@ -5477,9 +5497,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else if (nargs == 1) { - if (exp.names && (*exp.names)[0]) + if (exp.names && (*exp.names)[0].name) { - error(exp.loc, "no named argument `%s` allowed for scalar", (*exp.names)[0].toChars()); + error(exp.loc, "no named argument `%s` allowed for scalar", (*exp.names)[0].name.toChars()); return setError(); } Expression e = (*exp.arguments)[0]; @@ -6269,10 +6289,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor Expressions* resolvedArgs = exp.arguments; if (exp.names) { - resolvedArgs = resolveStructLiteralNamedArgs(sd, exp.e1.type, sc, exp.loc, - (*exp.names)[], + resolvedArgs = resolveStructLiteralNamedArgs(sd, exp.e1.type, sc, exp.loc, exp.names.length, + i => (*exp.names)[i].name, (size_t i, Type t) => (*exp.arguments)[i], - i => (*exp.arguments)[i].loc + i => (*exp.arguments)[i].loc, + i => (*exp.names)[i].loc ); if (!resolvedArgs) { @@ -7303,6 +7324,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor sc2.tinst = null; sc2.minst = null; sc2.fullinst = true; + sc2.traitsCompiles = true; Type t = dmd.typesem.trySemantic(e.targ, e.loc, sc2); sc2.pop(); if (!t) // errors, so condition is false @@ -8177,37 +8199,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (exp.arrow) // ImportC only exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc); - if (exp.ident == Id.__xalignof && exp.e1.isTypeExp()) - { - // C11 6.5.3 says _Alignof only applies to types - Expression e; - Type t; - Dsymbol s; - dmd.typesem.resolve(exp.e1.type, exp.e1.loc, sc, e, t, s, true); - if (e) - { - error(exp.e1.loc, "argument to `_Alignof` must be a type"); - return setError(); - } - else if (t) - { - // Note similarity to getProperty() implementation of __xalignof - const explicitAlignment = t.alignment(); - const naturalAlignment = t.alignsize(); - const actualAlignment = (explicitAlignment.isDefault() ? naturalAlignment : explicitAlignment.get()); - result = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t); - } - else if (s) - { - error(exp.e1.loc, "argument to `_Alignof` must be a type"); - return setError(); - } - else - assert(0); - return; - } - - if (exp.ident != Id.__sizeof) + if (exp.ident != Id.__sizeof && exp.ident != Id.__xalignof) { result = fieldLookup(exp.e1, sc, exp.ident, exp.arrow); return; @@ -10595,7 +10587,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { TupleDeclaration td = isAliasThisTuple(e2x); if (!td) - goto Lnomatch; + { + Lnomatch: + error(exp.loc, "cannot assign `%s` to expression sequence `%s`", + exp.e2.type.toChars(), exp.e1.type.toChars()); + return setError(); + } assert(exp.e1.type.ty == Ttuple); TypeTuple tt = cast(TypeTuple)exp.e1.type; @@ -10637,7 +10634,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // Do not need to overwrite this.e2 goto Ltupleassign; } - Lnomatch: } /* Inside constructor, if this is the first assignment of object field, @@ -11241,25 +11237,30 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor */ if (auto ale = exp.e1.isArrayLengthExp()) { - // e1 is not an lvalue, but we let code generator handle it + // Ensure e1 is a modifiable lvalue auto ale1x = ale.e1.modifiableLvalueImpl(sc, exp.e1); if (ale1x.op == EXP.error) return setResult(ale1x); ale.e1 = ale1x; + // Ensure the element type has a valid constructor Type tn = ale.e1.type.toBasetype().nextOf(); checkDefCtor(ale.loc, tn); + // Choose correct GC hook Identifier hook = global.params.tracegc ? Id._d_arraysetlengthTTrace : Id._d_arraysetlengthT; - if (!verifyHookExist(exp.loc, *sc, Id._d_arraysetlengthTImpl, "resizing arrays")) + + // Verify the correct hook exists + if (!verifyHookExist(exp.loc, *sc, hook, "resizing arrays")) return setError(); exp.e2 = exp.e2.expressionSemantic(sc); auto lc = lastComma(exp.e2); lc = lc.optimize(WANTvalue); - // use slice expression when arr.length = 0 to avoid runtime call - if(lc.op == EXP.int64 && lc.toInteger() == 0) + + // Optimize case where arr.length = 0 + if (lc.op == EXP.int64 && lc.toInteger() == 0) { Expression se = new SliceExp(ale.loc, ale.e1, lc, lc); Expression as = new AssignExp(ale.loc, ale.e1, se); @@ -11269,30 +11270,27 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return setResult(res); } - if (!sc.needsCodegen()) // if compile time creature only + if (!sc.needsCodegen()) // Compile-time only case { exp.type = Type.tsize_t; return setResult(exp); } - // Lower to object._d_arraysetlengthTImpl!(typeof(e1))._d_arraysetlengthT{,Trace}(e1, e2) + // Ensure correct reference for _d_arraysetlengthT Expression id = new IdentifierExp(ale.loc, Id.empty); id = new DotIdExp(ale.loc, id, Id.object); - auto tiargs = new Objects(); - tiargs.push(ale.e1.type); - id = new DotTemplateInstanceExp(ale.loc, id, Id._d_arraysetlengthTImpl, tiargs); id = new DotIdExp(ale.loc, id, hook); id = id.expressionSemantic(sc); + // Generate call: _d_arraysetlengthT(e1, e2) auto arguments = new Expressions(); - arguments.push(ale.e1); - arguments.push(exp.e2); + arguments.push(ale.e1); // array + arguments.push(exp.e2); // new length Expression ce = new CallExp(ale.loc, id, arguments).expressionSemantic(sc); auto res = new LoweredAssignExp(exp, ce); - // if (global.params.verbose) - // message("lowered %s =>\n %s", exp.toChars(), res.toChars()); res.type = Type.tsize_t; + return setResult(res); } else if (auto se = exp.e1.isSliceExp()) @@ -11761,6 +11759,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor res = new LoweredAssignExp(ae, res); res.type = ae.type; + res = res.checkGC(sc); return res; } @@ -12795,6 +12794,57 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } + // Inline the expression, if possible. + PowExp pe = cast(PowExp)e; + if (pe.e1.type.isScalar() && pe.e2.isIntegerExp()) + { + Expression one; + if (pe.e1.type.isIntegral()) { + one = new IntegerExp(e.loc, 1, pe.e1.type); + } else { + one = new RealExp(e.loc, CTFloat.one, pe.e1.type); + } + + const expo = cast(sinteger_t)pe.e2.toInteger(); + // Replace e1 ^^ -1 with 1 / e1 + if (expo == -1) + { + Expression ex = new DivExp(exp.loc, one, pe.e1); + ex = ex.expressionSemantic(sc); + result = ex; + return; + } + // Replace e1 ^^ 0 with (e1, 1) + else if (expo == 0) + { + Expression ex = new CommaExp(exp.loc, pe.e1, one, exp); + ex = ex.expressionSemantic(sc); + result = ex; + return; + } + // Replace e1 ^^ 1 with e1 + else if (expo == 1) + { + Expression ex = pe.e1; + ex.loc = exp.loc; + ex = ex.expressionSemantic(sc); + result = ex; + return; + } + // Replace e1 ^^ 2 with e1 * e1 + else if (expo == 2) + { + auto v = copyToTemp(STC.const_, "__powtmp", pe.e1); + auto ve = new VarExp(exp.loc, v); + auto de = new DeclarationExp(exp.e1.loc, v); + auto me = new MulExp(exp.e2.loc, ve, ve); + Expression ex = new CommaExp(exp.loc, de, me, exp); + ex = ex.expressionSemantic(sc); + result = ex; + return; + } + } + Module mmath = Module.loadStdMath(); if (!mmath) { @@ -13874,6 +13924,7 @@ private bool expressionSemanticDone(Expression e) || e.isTypeExp() // stores its type in the Expression.type field || e.isCompoundLiteralExp() // stores its `(type) {}` in type field, gets rewritten to struct literal || e.isVarExp() // type sometimes gets set already before semantic + || (e.isAssocArrayLiteralExp() && !e.type.vtinfo) // semanticTypeInfo not run during initialization ); } @@ -15771,11 +15822,12 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, const(char)* action } /*************************************** - * Parameters: - * sc: scope - * flag: 1: do not issue error message for invalid modification - 2: the exp is a DotVarExp and a subfield of the leftmost - variable is modified + * Params: + * exp = expression to check if modifiable + * sc = scope + * flag = noError - do not issue error message for invalid modification + fieldAssign - exp is a DotVarExp and a subfield of the leftmost + variable is modified * Returns: * Whether the type is modifiable */ @@ -16728,11 +16780,12 @@ enum ModifyFlags } /************************************* - * Check to see if declaration can be modified in this context (sc). + * Check to see if `d` can be modified in this context `sc`. * Issue error if not. * Params: + * d = declaration to check * loc = location for error messages - * e1 = `null` or `this` expression when this declaration is a field + * e1 = `null` or `this` expression when `d` is a field * sc = context * flag = if the first bit is set it means do not issue error message for * invalid modification; if the second bit is set, it means that @@ -16742,6 +16795,7 @@ enum ModifyFlags */ private Modifiable checkModify(Declaration d, Loc loc, Scope* sc, Expression e1, ModifyFlags flag) { + //printf("checkModify() d: %s, e1: %s\n", d.toChars(), e1.toChars()); VarDeclaration v = d.isVarDeclaration(); if (v && v.canassign) return Modifiable.initialization; @@ -16787,15 +16841,19 @@ private Modifiable checkModify(Declaration d, Loc loc, Scope* sc, Expression e1, } /*********************************************** - * Mark variable v as modified if it is inside a constructor that var + * Mark variable `var` as modified if it is inside a constructor that `var` * is a field in. * Also used to allow immutable globals to be initialized inside a static constructor. + * Params: + * loc = location for error messages + * sc = scope + * var = field * Returns: - * true if it's an initialization of v + * true if it's an initialization of `var` */ private bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1) { - //printf("modifyFieldVar(var = %s)\n", var.toChars()); + //printf("modifyFieldVar(var: %s, e1: %s)\n", var.toChars(), e1.toChars()); Dsymbol s = sc.func; while (1) { @@ -16811,7 +16869,7 @@ private bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e bool result = true; var.ctorinit = true; - //printf("setting ctorinit\n"); + //printf("setting ctorinit for %s\n", var.toChars()); if (var.isField() && sc.ctorflow.fieldinit.length && !sc.intypeof) { @@ -17457,7 +17515,7 @@ bool fill(StructDeclaration sd, Loc loc, ref Expressions elements, bool ctorinit * sfe = The 'static foreach'. * sc = The current scope. */ -extern (C++) void lowerNonArrayAggregate(StaticForeach sfe, Scope* sc) +void lowerNonArrayAggregate(StaticForeach sfe, Scope* sc) { import dmd.statement; @@ -17671,3 +17729,143 @@ extern(D) void lowerArrayAggregate(StaticForeach sfe, Scope* sc) sfe.aggrfe.aggr = sfe.aggrfe.aggr.optimize(WANTvalue); sfe.aggrfe.aggr = sfe.aggrfe.aggr.ctfeInterpret(); } + +int include(Condition c, Scope* sc) +{ + scope v = new IncludeVisitor(sc); + c.accept(v); + return v.result; +} + +private extern(C++) class IncludeVisitor : Visitor { + alias visit = Visitor.visit; + + Scope *sc; + int result; + + this(Scope* sc) + { + this.sc = sc; + } + + override void visit(DebugCondition dc) + { + //printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel); + if (dc.inc != Include.notComputed) + { + result = dc.inc == Include.yes; + return; + } + dc.inc = Include.no; + bool definedInModule = false; + if (dc.ident) + { + if (dc.mod.debugids && findCondition(*dc.mod.debugids, dc.ident)) + { + dc.inc = Include.yes; + definedInModule = true; + } + else if (findCondition(global.debugids, dc.ident)) + dc.inc = Include.yes; + else + { + if (!dc.mod.debugidsNot) + dc.mod.debugidsNot = new Identifiers(); + dc.mod.debugidsNot.push(dc.ident); + } + } + else if (global.params.debugEnabled) + dc.inc = Include.yes; + + if (!definedInModule) + printDepsConditional(sc, dc, "depsDebug "); + result = (dc.inc == Include.yes); + } + + override void visit(VersionCondition vc) + { + //printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel); + //if (ident) printf("\tident = '%s'\n", ident.toChars()); + if (vc.inc != Include.notComputed) + { + result = vc.inc == Include.yes; + return; + } + + vc.inc = Include.no; + bool definedInModule = false; + if (vc.ident) + { + if (vc.mod.versionids && findCondition(*vc.mod.versionids, vc.ident)) + { + vc.inc = Include.yes; + definedInModule = true; + } + else if (findCondition(global.versionids, vc.ident)) + vc.inc = Include.yes; + else + { + if (!vc.mod.versionidsNot) + vc.mod.versionidsNot = new Identifiers(); + vc.mod.versionidsNot.push(vc.ident); + } + } + if (!definedInModule && + (!vc.ident || (!vc.isReserved(vc.ident.toString()) && vc.ident != Id._unittest && vc.ident != Id._assert))) + { + printDepsConditional(sc, vc, "depsVersion "); + } + result = (vc.inc == Include.yes); + } + + override void visit(StaticIfCondition sic) + { + // printf("StaticIfCondition::include(sc = %p) this=%p inc = %d\n", sc, this, inc); + + int errorReturn() + { + if (!global.gag) + sic.inc = Include.no; // so we don't see the error message again + return 0; + } + + if (sic.inc != Include.notComputed) + { + result = sic.inc == Include.yes; + return; + } + + if (!sc) + { + error(sic.loc, "`static if` conditional cannot be at global scope"); + sic.inc = Include.no; + result = 0; + return; + } + + import dmd.staticcond; + bool errors; + + bool local_result = evalStaticCondition(sc, sic.exp, sic.exp, errors); + + // Prevent repeated condition evaluation. + // See: fail_compilation/fail7815.d + if (sic.inc != Include.notComputed) + { + result = (sic.inc == Include.yes); + return; + } + + if (errors) + { + result = errorReturn(); + return; + } + + if (local_result) + sic.inc = Include.yes; + else + sic.inc = Include.no; + result = (sic.inc == Include.yes); + } +} diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index 064b67f96060..6a573810a4b9 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -820,15 +820,13 @@ extern (C++) class FuncDeclaration : Declaration bool addPreInvariant() { auto ad = isThis(); - ClassDeclaration cd = ad ? ad.isClassDeclaration() : null; - return (ad && !(cd && cd.isCPPclass()) && global.params.useInvariants == CHECKENABLE.on && (visibility.kind == Visibility.Kind.protected_ || visibility.kind == Visibility.Kind.public_ || visibility.kind == Visibility.Kind.export_) && !this.isNaked()); + return (ad && global.params.useInvariants == CHECKENABLE.on && (visibility.kind == Visibility.Kind.protected_ || visibility.kind == Visibility.Kind.public_ || visibility.kind == Visibility.Kind.export_) && !this.isNaked()); } bool addPostInvariant() { auto ad = isThis(); - ClassDeclaration cd = ad ? ad.isClassDeclaration() : null; - return (ad && !(cd && cd.isCPPclass()) && ad.inv && global.params.useInvariants == CHECKENABLE.on && (visibility.kind == Visibility.Kind.protected_ || visibility.kind == Visibility.Kind.public_ || visibility.kind == Visibility.Kind.export_) && !this.isNaked()); + return (ad && ad.inv && global.params.useInvariants == CHECKENABLE.on && (visibility.kind == Visibility.Kind.protected_ || visibility.kind == Visibility.Kind.public_ || visibility.kind == Visibility.Kind.export_) && !this.isNaked()); } override const(char)* kind() const diff --git a/gcc/d/dmd/funcsem.d b/gcc/d/dmd/funcsem.d index 1231496e41ab..10f6f154b2ff 100644 --- a/gcc/d/dmd/funcsem.d +++ b/gcc/d/dmd/funcsem.d @@ -235,6 +235,17 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl) if ((funcdecl.storage_class & STC.TYPECTOR) && !(ad || funcdecl.isNested())) funcdecl.storage_class &= ~STC.TYPECTOR; + auto tf = funcdecl.type.isTypeFunction(); + if ((funcdecl.storage_class & STC.auto_) && tf.isRef && !funcdecl.inferRetType) + { + if (!(funcdecl.storage_class & STC.autoref)) + { + // @@@DEPRECATED_2.122@@@ + // Deprecated in 2.112, turn into an error in 2.122 + deprecation(funcdecl.loc, "`auto ref` return type must have `auto` and `ref` adjacent"); + funcdecl.storage_class |= STC.autoref; + } + } //printf("function storage_class = x%llx, sc.stc = x%llx, %x\n", storage_class, sc.stc, Declaration.isFinal()); if (sc.traitsCompiles) @@ -272,20 +283,6 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl) if (!funcdecl.originalType) funcdecl.originalType = funcdecl.type.syntaxCopy(); - static TypeFunction getFunctionType(FuncDeclaration fd) - { - if (auto tf = fd.type.isTypeFunction()) - return tf; - - if (!fd.type.isTypeError()) - { - .error(fd.loc, "%s `%s` `%s` must be a function instead of `%s`", fd.kind, fd.toPrettyChars, fd.toChars(), fd.type.toChars()); - fd.type = Type.terror; - } - fd.errors = true; - return null; - } - if (sc.inCfile) { /* C11 allows a function to be declared with a typedef, D does not. @@ -313,7 +310,6 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl) sc = sc.push(); sc.stc |= funcdecl.storage_class & (STC.disable | STC.deprecated_); // forward to function type - TypeFunction tf = funcdecl.type.toTypeFunction(); if (sc.func) { /* If the nesting parent is pure without inference, @@ -563,587 +559,697 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl) if (ClassDeclaration cd = parent.isClassDeclaration()) { - parent = cd = objc.getParent(funcdecl, cd); + switch (classFuncSemantic(cd, funcdecl, parent, sc, f)) + { + case 0: break; + case 1: goto Ldone; + case 2: return; + default: assert(0); + } + } + else if (funcdecl.isOverride() && !parent.isTemplateInstance()) + .error(funcdecl.loc, "%s `%s` `override` only applies to class member functions", funcdecl.kind, funcdecl.toPrettyChars); + + if (auto ti = parent.isTemplateInstance) + { + objc.setSelector(funcdecl, sc); + objc.setAsOptional(funcdecl, sc); + } - if (funcdecl.isCtorDeclaration()) + objc.validateSelector(funcdecl); + objc.validateOptional(funcdecl); + // Reflect this.type to f because it could be changed by findVtblIndex + f = funcdecl.type.toTypeFunction(); + +Ldone: + if (!funcdecl.fbody && !funcdecl.allowsContractWithoutBody()) + .error(funcdecl.loc, "%s `%s` `in` and `out` contracts can only appear without a body when they are virtual interface functions or abstract", funcdecl.kind, funcdecl.toPrettyChars); + + /* Do not allow template instances to add virtual functions + * to a class. + */ + if (funcdecl.isVirtual()) + { + if (auto ti = parent.isTemplateInstance()) { - goto Ldone; + // Take care of nested templates + while (1) + { + TemplateInstance ti2 = ti.tempdecl.parent.isTemplateInstance(); + if (!ti2) + break; + ti = ti2; + } + + // If it's a member template + if (ClassDeclaration cd = ti.tempdecl.isClassMember()) + { + .error(funcdecl.loc, "%s `%s` cannot use template to add virtual function to class `%s`", funcdecl.kind, funcdecl.toPrettyChars, cd.toChars()); + } } + } + + funcdecl.checkMain(); // Check main() parameters and return type - if (funcdecl.storage_class & STC.abstract_) - cd.isabstract = ThreeState.yes; + /* Purity and safety can be inferred for some functions by examining + * the function body. + */ + if (funcdecl.canInferAttributes(sc)) + funcdecl.initInferAttributes(); + + funcdecl.semanticRun = PASS.semanticdone; - // if static function, do not put in vtbl[] - if (!funcdecl.isVirtual()) + /* Save scope for possible later use (if we need the + * function internals) + */ + funcdecl._scope = sc.copy(); + funcdecl._scope.setNoFree(); + + __gshared bool printedMain = false; // semantic might run more than once + if (global.params.v.verbose && !printedMain) + { + const(char)* type = funcdecl.isMain() ? "main" : funcdecl.isWinMain() ? "winmain" : funcdecl.isDllMain() ? "dllmain" : cast(const(char)*)null; + Module mod = sc._module; + + if (type && mod) { - //printf("\tnot virtual\n"); - goto Ldone; + printedMain = true; + auto name = mod.srcfile.toChars(); + auto path = FileName.searchPath(global.importPaths, name, true); + message("entry %-10s\t%s", type, path ? path : name); } - // Suppress further errors if the return type is an error - if (funcdecl.type.nextOf() == Type.terror) - goto Ldone; + } - bool may_override = false; - for (size_t i = 0; i < cd.baseclasses.length; i++) + if (funcdecl.fbody && sc._module.isRoot() && + (funcdecl.isMain() || funcdecl.isWinMain() || funcdecl.isDllMain() || funcdecl.isCMain())) + global.hasMainFunction = true; + + if (funcdecl.fbody && funcdecl.isMain() && sc._module.isRoot()) + { + // check if `_d_cmain` is defined + bool cmainTemplateExists() { - BaseClass* b = (*cd.baseclasses)[i]; - ClassDeclaration cbd = b.type.toBasetype().isClassHandle(); - if (!cbd) + Dsymbol pscopesym; + auto rootSymbol = sc.search(funcdecl.loc, Id.empty, pscopesym); + if (auto moduleSymbol = rootSymbol.search(funcdecl.loc, Id.object)) + if (moduleSymbol.search(funcdecl.loc, Id.CMain)) + return true; + + return false; + } + + // Only mixin `_d_cmain` if it is defined + if (cmainTemplateExists()) + { + // add `mixin _d_cmain!();` to the declaring module + auto tqual = new TypeIdentifier(funcdecl.loc, Id.CMain); + auto tm = new TemplateMixin(funcdecl.loc, null, tqual, null); + sc._module.members.push(tm); + } + } + + assert(funcdecl.type.ty != Terror || funcdecl.errors); + + // semantic for parameters' UDAs + foreach (i, param; f.parameterList) + { + if (param && param.userAttribDecl) + param.userAttribDecl.dsymbolSemantic(sc); + } +} + +/** + Returns: + 0 if semantic analysis in `funcDeclarationSemantic` should continue as normal + 1 if it should skip over some analysis and `goto Ldone;` + 2 if `funcDeclarationSemantic` should return early because of forward refernce error or + the derived class cd doesn't have its vtbl[] allocated yet + */ +private int classFuncSemantic(ClassDeclaration cd, FuncDeclaration funcdecl, + ref Dsymbol parent, Scope* sc, TypeFunction f) +{ + parent = cd = objc.getParent(funcdecl, cd); + + if (funcdecl.isCtorDeclaration()) + { + return 1; + } + + if (funcdecl.storage_class & STC.abstract_) + cd.isabstract = ThreeState.yes; + + // if static function, do not put in vtbl[] + if (!funcdecl.isVirtual()) + { + //printf("\tnot virtual\n"); + return 1; + } + // Suppress further errors if the return type is an error + if (funcdecl.type.nextOf() == Type.terror) + return 1; + + bool may_override = false; + for (size_t i = 0; i < cd.baseclasses.length; i++) + { + BaseClass* b = (*cd.baseclasses)[i]; + ClassDeclaration cbd = b.type.toBasetype().isClassHandle(); + if (!cbd) + continue; + for (size_t j = 0; j < cbd.vtbl.length; j++) + { + FuncDeclaration f2 = cbd.vtbl[j].isFuncDeclaration(); + if (!f2 || f2.ident != funcdecl.ident) continue; - for (size_t j = 0; j < cbd.vtbl.length; j++) + if (cbd.parent && cbd.parent.isTemplateInstance()) { - FuncDeclaration f2 = cbd.vtbl[j].isFuncDeclaration(); - if (!f2 || f2.ident != funcdecl.ident) - continue; - if (cbd.parent && cbd.parent.isTemplateInstance()) - { - if (!functionSemantic(f2)) - goto Ldone; - } - may_override = true; + if (!functionSemantic(f2)) + return 1; } + may_override = true; } - if (may_override && funcdecl.type.nextOf() is null) + } + if (may_override && funcdecl.type.nextOf() is null) + { + /* If same name function exists in base class but 'this' is auto return, + * cannot find index of base class's vtbl[] to override. + */ + .error(funcdecl.loc, "%s `%s` return type inference is not supported if may override base class function", funcdecl.kind, funcdecl.toPrettyChars); + } + + /* Find index of existing function in base class's vtbl[] to override + * (the index will be the same as in cd's current vtbl[]) + */ + int vi = cd.baseClass ? findVtblIndex(funcdecl, cd.baseClass.vtbl[]) : -1; + + bool doesoverride = false; + switch (vi) + { + case -1: + Lintro: + /* Didn't find one, so + * This is an 'introducing' function which gets a new + * slot in the vtbl[]. + */ + + // Verify this doesn't override previous final function + if (cd.baseClass) { - /* If same name function exists in base class but 'this' is auto return, - * cannot find index of base class's vtbl[] to override. - */ - .error(funcdecl.loc, "%s `%s` return type inference is not supported if may override base class function", funcdecl.kind, funcdecl.toPrettyChars); + Dsymbol s = cd.baseClass.search(funcdecl.loc, funcdecl.ident); + if (s) + { + if (auto f2 = s.isFuncDeclaration()) + { + f2 = f2.overloadExactMatch(funcdecl.type); + if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_) + .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s`", funcdecl.kind, funcdecl.toPrettyChars, f2.toPrettyChars()); + } + } } - /* Find index of existing function in base class's vtbl[] to override - * (the index will be the same as in cd's current vtbl[]) + /* These quirky conditions mimic what happens when virtual + inheritance is implemented by producing a virtual base table + with offsets to each of the virtual bases. */ - int vi = cd.baseClass ? findVtblIndex(funcdecl, cd.baseClass.vtbl[]) : -1; - - bool doesoverride = false; - switch (vi) + if (target.cpp.splitVBasetable && cd.classKind == ClassKind.cpp && + cd.baseClass && cd.baseClass.vtbl.length) { - case -1: - Lintro: - /* Didn't find one, so - * This is an 'introducing' function which gets a new - * slot in the vtbl[]. + /* if overriding an interface function, then this is not + * introducing and don't put it in the class vtbl[] */ + funcdecl.interfaceVirtual = overrideInterface(funcdecl); + if (funcdecl.interfaceVirtual) + { + //printf("\tinterface function %s\n", toChars()); + cd.vtblFinal.push(funcdecl); + goto Linterfaces; + } + } - // Verify this doesn't override previous final function - if (cd.baseClass) + if (funcdecl.isFinalFunc()) + { + // Don't check here, as it may override an interface function + //if (isOverride()) + // error("is marked as override, but does not override any function"); + cd.vtblFinal.push(funcdecl); + } + else + { + //printf("\tintroducing function %s\n", funcdecl.toChars()); + funcdecl.isIntroducing = true; + if (cd.classKind == ClassKind.cpp && target.cpp.reverseOverloads) { - Dsymbol s = cd.baseClass.search(funcdecl.loc, funcdecl.ident); - if (s) + /* Overloaded functions with same name are grouped and in reverse order. + * Search for first function of overload group, and insert + * funcdecl into vtbl[] immediately before it. + */ + funcdecl.vtblIndex = cast(int)cd.vtbl.length; + bool found; + foreach (const i, s; cd.vtbl) { - if (auto f2 = s.isFuncDeclaration()) + if (found) + // the rest get shifted forward + ++s.isFuncDeclaration().vtblIndex; + else if (s.ident == funcdecl.ident && s.parent == parent) { - f2 = f2.overloadExactMatch(funcdecl.type); - if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_) - .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s`", funcdecl.kind, funcdecl.toPrettyChars, f2.toPrettyChars()); + // found first function of overload group + funcdecl.vtblIndex = cast(int)i; + found = true; + ++s.isFuncDeclaration().vtblIndex; } } + cd.vtbl.insert(funcdecl.vtblIndex, funcdecl); + + debug foreach (const i, s; cd.vtbl) + { + // a C++ dtor gets its vtblIndex later (and might even be added twice to the vtbl), + // e.g. when compiling druntime with a debug compiler, namely with core.stdcpp.exception. + if (auto fd = s.isFuncDeclaration()) + assert(fd.vtblIndex == i || + (cd.classKind == ClassKind.cpp && fd.isDtorDeclaration) || + funcdecl.parent.isInterfaceDeclaration); // interface functions can be in multiple vtbls + } + } + else + { + // Append to end of vtbl[] + vi = cast(int)cd.vtbl.length; + cd.vtbl.push(funcdecl); + funcdecl.vtblIndex = vi; } + } + break; - /* These quirky conditions mimic what happens when virtual - inheritance is implemented by producing a virtual base table - with offsets to each of the virtual bases. - */ - if (target.cpp.splitVBasetable && cd.classKind == ClassKind.cpp && - cd.baseClass && cd.baseClass.vtbl.length) + case -2: + // can't determine because of forward references + funcdecl.errors = true; + return 2; + + default: + { + if (vi >= cd.vtbl.length) { - /* if overriding an interface function, then this is not - * introducing and don't put it in the class vtbl[] + /* the derived class cd doesn't have its vtbl[] allocated yet. + * https://issues.dlang.org/show_bug.cgi?id=21008 */ - funcdecl.interfaceVirtual = overrideInterface(funcdecl); - if (funcdecl.interfaceVirtual) - { - //printf("\tinterface function %s\n", toChars()); - cd.vtblFinal.push(funcdecl); - goto Linterfaces; - } + .error(funcdecl.loc, "%s `%s` circular reference to class `%s`", funcdecl.kind, funcdecl.toPrettyChars, cd.toChars()); + funcdecl.errors = true; + return 2; } + FuncDeclaration fdv = cd.baseClass.vtbl[vi].isFuncDeclaration(); + FuncDeclaration fdc = cd.vtbl[vi].isFuncDeclaration(); + // This function is covariant with fdv - if (funcdecl.isFinalFunc()) + if (fdc == funcdecl) { - // Don't check here, as it may override an interface function - //if (isOverride()) - // error("is marked as override, but does not override any function"); - cd.vtblFinal.push(funcdecl); + doesoverride = true; + break; } - else + + auto vtf = getFunctionType(fdv); + if (vtf.trust > TRUST.system && f.trust == TRUST.system) + .error(funcdecl.loc, "%s `%s` cannot override `@safe` method `%s` with a `@system` attribute", funcdecl.kind, funcdecl.toPrettyChars, + fdv.toPrettyChars); + + if (fdc.toParent() == parent) { - //printf("\tintroducing function %s\n", funcdecl.toChars()); - funcdecl.isIntroducing = true; - if (cd.classKind == ClassKind.cpp && target.cpp.reverseOverloads) - { - /* Overloaded functions with same name are grouped and in reverse order. - * Search for first function of overload group, and insert - * funcdecl into vtbl[] immediately before it. - */ - funcdecl.vtblIndex = cast(int)cd.vtbl.length; - bool found; - foreach (const i, s; cd.vtbl) - { - if (found) - // the rest get shifted forward - ++s.isFuncDeclaration().vtblIndex; - else if (s.ident == funcdecl.ident && s.parent == parent) - { - // found first function of overload group - funcdecl.vtblIndex = cast(int)i; - found = true; - ++s.isFuncDeclaration().vtblIndex; - } - } - cd.vtbl.insert(funcdecl.vtblIndex, funcdecl); + //printf("vi = %d,\tthis = %p %s %s @ [%s]\n\tfdc = %p %s %s @ [%s]\n\tfdv = %p %s %s @ [%s]\n", + // vi, this, this.toChars(), this.type.toChars(), this.loc.toChars(), + // fdc, fdc .toChars(), fdc .type.toChars(), fdc .loc.toChars(), + // fdv, fdv .toChars(), fdv .type.toChars(), fdv .loc.toChars()); + + // fdc overrides fdv exactly, then this introduces new function. + if (fdc.type.mod == fdv.type.mod && funcdecl.type.mod != fdv.type.mod) + goto Lintro; + } - debug foreach (const i, s; cd.vtbl) - { - // a C++ dtor gets its vtblIndex later (and might even be added twice to the vtbl), - // e.g. when compiling druntime with a debug compiler, namely with core.stdcpp.exception. - if (auto fd = s.isFuncDeclaration()) - assert(fd.vtblIndex == i || - (cd.classKind == ClassKind.cpp && fd.isDtorDeclaration) || - funcdecl.parent.isInterfaceDeclaration); // interface functions can be in multiple vtbls - } + if (fdv.isDeprecated && !funcdecl.isDeprecated) + deprecation(funcdecl.loc, "`%s` is overriding the deprecated method `%s`", + funcdecl.toPrettyChars, fdv.toPrettyChars); + + // This function overrides fdv + if (fdv.isFinalFunc()) + .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s`", funcdecl.kind, funcdecl.toPrettyChars, fdv.toPrettyChars()); + + if (!funcdecl.isOverride()) + { + if (fdv.isFuture()) + { + deprecation(funcdecl.loc, "method `%s` implicitly overrides `@__future` base class method; rename the former", + funcdecl.toPrettyChars()); + deprecationSupplemental(fdv.loc, "base method `%s` defined here", + fdv.toPrettyChars()); + // Treat 'this' as an introducing function, giving it a separate hierarchy in the vtbl[] + goto Lintro; } else { - // Append to end of vtbl[] - vi = cast(int)cd.vtbl.length; - cd.vtbl.push(funcdecl); - funcdecl.vtblIndex = vi; + // https://issues.dlang.org/show_bug.cgi?id=17349 + error(funcdecl.loc, "cannot implicitly override base class method `%s` with `%s`; add `override` attribute", + fdv.toPrettyChars(), funcdecl.toPrettyChars()); } } - break; - - case -2: - // can't determine because of forward references - funcdecl.errors = true; - return; - - default: + doesoverride = true; + if (fdc.toParent() == parent) { - if (vi >= cd.vtbl.length) + // If both are mixins, or both are not, then error. + // If either is not, the one that is not overrides the other. + bool thismixin = funcdecl.parent.isClassDeclaration() !is null; + bool fdcmixin = fdc.parent.isClassDeclaration() !is null; + if (thismixin == fdcmixin) + { + .error(funcdecl.loc, "%s `%s` multiple overrides of same function", funcdecl.kind, funcdecl.toPrettyChars); + } + /* + * https://issues.dlang.org/show_bug.cgi?id=711 + * + * If an overriding method is introduced through a mixin, + * we need to update the vtbl so that both methods are + * present. + */ + else if (thismixin) { - /* the derived class cd doesn't have its vtbl[] allocated yet. - * https://issues.dlang.org/show_bug.cgi?id=21008 + /* if the mixin introduced the overriding method, then reintroduce it + * in the vtbl. The initial entry for the mixined method + * will be updated at the end of the enclosing `if` block + * to point to the current (non-mixined) function. */ - .error(funcdecl.loc, "%s `%s` circular reference to class `%s`", funcdecl.kind, funcdecl.toPrettyChars, cd.toChars()); - funcdecl.errors = true; - return; + auto vitmp = cast(int)cd.vtbl.length; + cd.vtbl.push(fdc); + fdc.vtblIndex = vitmp; } - FuncDeclaration fdv = cd.baseClass.vtbl[vi].isFuncDeclaration(); - FuncDeclaration fdc = cd.vtbl[vi].isFuncDeclaration(); - // This function is covariant with fdv - - if (fdc == funcdecl) + else if (fdcmixin) { - doesoverride = true; + /* if the current overriding function is coming from a + * mixined block, then push the current function in the + * vtbl, but keep the previous (non-mixined) function as + * the overriding one. + */ + auto vitmp = cast(int)cd.vtbl.length; + cd.vtbl.push(funcdecl); + funcdecl.vtblIndex = vitmp; break; } - - auto vtf = getFunctionType(fdv); - if (vtf.trust > TRUST.system && f.trust == TRUST.system) - .error(funcdecl.loc, "%s `%s` cannot override `@safe` method `%s` with a `@system` attribute", funcdecl.kind, funcdecl.toPrettyChars, - fdv.toPrettyChars); - - if (fdc.toParent() == parent) + else // fdc overrides fdv { - //printf("vi = %d,\tthis = %p %s %s @ [%s]\n\tfdc = %p %s %s @ [%s]\n\tfdv = %p %s %s @ [%s]\n", - // vi, this, this.toChars(), this.type.toChars(), this.loc.toChars(), - // fdc, fdc .toChars(), fdc .type.toChars(), fdc .loc.toChars(), - // fdv, fdv .toChars(), fdv .type.toChars(), fdv .loc.toChars()); - - // fdc overrides fdv exactly, then this introduces new function. - if (fdc.type.mod == fdv.type.mod && funcdecl.type.mod != fdv.type.mod) - goto Lintro; + // this doesn't override any function + break; } + } + cd.vtbl[vi] = funcdecl; + funcdecl.vtblIndex = vi; - if (fdv.isDeprecated && !funcdecl.isDeprecated) - deprecation(funcdecl.loc, "`%s` is overriding the deprecated method `%s`", - funcdecl.toPrettyChars, fdv.toPrettyChars); - - // This function overrides fdv - if (fdv.isFinalFunc()) - .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s`", funcdecl.kind, funcdecl.toPrettyChars, fdv.toPrettyChars()); + /* Remember which functions this overrides + */ + funcdecl.foverrides.push(fdv); + + /* This works by whenever this function is called, + * it actually returns tintro, which gets dynamically + * cast to type. But we know that tintro is a base + * of type, so we could optimize it by not doing a + * dynamic cast, but just subtracting the isBaseOf() + * offset if the value is != null. + */ - if (!funcdecl.isOverride()) - { - if (fdv.isFuture()) - { - deprecation(funcdecl.loc, "method `%s` implicitly overrides `@__future` base class method; rename the former", - funcdecl.toPrettyChars()); - deprecationSupplemental(fdv.loc, "base method `%s` defined here", - fdv.toPrettyChars()); - // Treat 'this' as an introducing function, giving it a separate hierarchy in the vtbl[] - goto Lintro; - } - else - { - // https://issues.dlang.org/show_bug.cgi?id=17349 - error(funcdecl.loc, "cannot implicitly override base class method `%s` with `%s`; add `override` attribute", - fdv.toPrettyChars(), funcdecl.toPrettyChars()); - } - } - doesoverride = true; - if (fdc.toParent() == parent) + if (fdv.tintro) + funcdecl.tintro = fdv.tintro; + else if (!funcdecl.type.equals(fdv.type)) + { + auto tnext = funcdecl.type.nextOf(); + if (auto handle = tnext.isClassHandle()) { - // If both are mixins, or both are not, then error. - // If either is not, the one that is not overrides the other. - bool thismixin = funcdecl.parent.isClassDeclaration() !is null; - bool fdcmixin = fdc.parent.isClassDeclaration() !is null; - if (thismixin == fdcmixin) - { - .error(funcdecl.loc, "%s `%s` multiple overrides of same function", funcdecl.kind, funcdecl.toPrettyChars); - } - /* - * https://issues.dlang.org/show_bug.cgi?id=711 - * - * If an overriding method is introduced through a mixin, - * we need to update the vtbl so that both methods are - * present. - */ - else if (thismixin) - { - /* if the mixin introduced the overriding method, then reintroduce it - * in the vtbl. The initial entry for the mixined method - * will be updated at the end of the enclosing `if` block - * to point to the current (non-mixined) function. - */ - auto vitmp = cast(int)cd.vtbl.length; - cd.vtbl.push(fdc); - fdc.vtblIndex = vitmp; - } - else if (fdcmixin) - { - /* if the current overriding function is coming from a - * mixined block, then push the current function in the - * vtbl, but keep the previous (non-mixined) function as - * the overriding one. - */ - auto vitmp = cast(int)cd.vtbl.length; - cd.vtbl.push(funcdecl); - funcdecl.vtblIndex = vitmp; - break; - } - else // fdc overrides fdv - { - // this doesn't override any function - break; - } + if (handle.semanticRun < PASS.semanticdone && !handle.isBaseInfoComplete()) + handle.dsymbolSemantic(null); } - cd.vtbl[vi] = funcdecl; - funcdecl.vtblIndex = vi; - - /* Remember which functions this overrides + /* Only need to have a tintro if the vptr + * offsets differ */ - funcdecl.foverrides.push(fdv); - - /* This works by whenever this function is called, - * it actually returns tintro, which gets dynamically - * cast to type. But we know that tintro is a base - * of type, so we could optimize it by not doing a - * dynamic cast, but just subtracting the isBaseOf() - * offset if the value is != null. - */ - - if (fdv.tintro) - funcdecl.tintro = fdv.tintro; - else if (!funcdecl.type.equals(fdv.type)) + int offset; + if (fdv.type.nextOf().isBaseOf(tnext, &offset)) { - auto tnext = funcdecl.type.nextOf(); - if (auto handle = tnext.isClassHandle()) - { - if (handle.semanticRun < PASS.semanticdone && !handle.isBaseInfoComplete()) - handle.dsymbolSemantic(null); - } - /* Only need to have a tintro if the vptr - * offsets differ - */ - int offset; - if (fdv.type.nextOf().isBaseOf(tnext, &offset)) - { - funcdecl.tintro = fdv.type; - } + funcdecl.tintro = fdv.type; } - break; } + break; } + } - /* Go through all the interface bases. - * If this function is covariant with any members of those interface - * functions, set the tintro. - */ - Linterfaces: - bool foundVtblMatch = false; + /* Go through all the interface bases. + * If this function is covariant with any members of those interface + * functions, set the tintro. + */ +Linterfaces: + bool foundVtblMatch = false; - for (ClassDeclaration bcd = cd; !foundVtblMatch && bcd; bcd = bcd.baseClass) + for (ClassDeclaration bcd = cd; !foundVtblMatch && bcd; bcd = bcd.baseClass) + { + foreach (b; bcd.interfaces) { - foreach (b; bcd.interfaces) + vi = findVtblIndex(funcdecl, b.sym.vtbl[]); + switch (vi) { - vi = findVtblIndex(funcdecl, b.sym.vtbl[]); - switch (vi) - { - case -1: - break; + case -1: + break; - case -2: - // can't determine because of forward references - funcdecl.errors = true; - return; + case -2: + // can't determine because of forward references + funcdecl.errors = true; + return 2; - default: - { - auto fdv = cast(FuncDeclaration)b.sym.vtbl[vi]; - Type ti = null; + default: + { + auto fdv = cast(FuncDeclaration)b.sym.vtbl[vi]; + Type ti = null; - foundVtblMatch = true; + foundVtblMatch = true; - /* Remember which functions this overrides - */ - funcdecl.foverrides.push(fdv); + /* Remember which functions this overrides + */ + funcdecl.foverrides.push(fdv); - if (fdv.tintro) - ti = fdv.tintro; - else if (!funcdecl.type.equals(fdv.type)) + if (fdv.tintro) + ti = fdv.tintro; + else if (!funcdecl.type.equals(fdv.type)) + { + /* Only need to have a tintro if the vptr + * offsets differ + */ + int offset; + if (fdv.type.nextOf().isBaseOf(funcdecl.type.nextOf(), &offset)) { - /* Only need to have a tintro if the vptr - * offsets differ - */ - int offset; - if (fdv.type.nextOf().isBaseOf(funcdecl.type.nextOf(), &offset)) - { - ti = fdv.type; - } + ti = fdv.type; } - if (ti) + } + if (ti) + { + if (funcdecl.tintro) { - if (funcdecl.tintro) - { - if (!funcdecl.tintro.nextOf().equals(ti.nextOf()) && !funcdecl.tintro.nextOf().isBaseOf(ti.nextOf(), null) && !ti.nextOf().isBaseOf(funcdecl.tintro.nextOf(), null)) - { - .error(funcdecl.loc, "%s `%s` incompatible covariant types `%s` and `%s`", funcdecl.kind, funcdecl.toPrettyChars, funcdecl.tintro.toChars(), ti.toChars()); - } - } - else + if (!funcdecl.tintro.nextOf().equals(ti.nextOf()) && !funcdecl.tintro.nextOf().isBaseOf(ti.nextOf(), null) && !ti.nextOf().isBaseOf(funcdecl.tintro.nextOf(), null)) { - funcdecl.tintro = ti; + .error(funcdecl.loc, "%s `%s` incompatible covariant types `%s` and `%s`", funcdecl.kind, funcdecl.toPrettyChars, funcdecl.tintro.toChars(), ti.toChars()); } } + else + { + funcdecl.tintro = ti; + } } } } } - if (foundVtblMatch) + } + if (foundVtblMatch) + { + goto L2; + } + + if (!doesoverride && funcdecl.isOverride() && (funcdecl.type.nextOf() || !may_override)) + { + BaseClass* bc = null; + Dsymbol s = null; + for (size_t i = 0; i < cd.baseclasses.length; i++) { - goto L2; + bc = (*cd.baseclasses)[i]; + s = bc.sym.search_correct(funcdecl.ident); + if (s) + break; } - if (!doesoverride && funcdecl.isOverride() && (funcdecl.type.nextOf() || !may_override)) + if (s) { - BaseClass* bc = null; - Dsymbol s = null; - for (size_t i = 0; i < cd.baseclasses.length; i++) - { - bc = (*cd.baseclasses)[i]; - s = bc.sym.search_correct(funcdecl.ident); - if (s) - break; - } + HdrGenState hgs; + OutBuffer buf; - if (s) + auto fd = s.isFuncDeclaration(); + functionToBufferFull(cast(TypeFunction)(funcdecl.type), buf, + new Identifier(funcdecl.toPrettyChars()), hgs, null); + const(char)* funcdeclToChars = buf.peekChars(); + + if (fd) { - HdrGenState hgs; - OutBuffer buf; + OutBuffer buf1; - auto fd = s.isFuncDeclaration(); - functionToBufferFull(cast(TypeFunction)(funcdecl.type), buf, - new Identifier(funcdecl.toPrettyChars()), hgs, null); - const(char)* funcdeclToChars = buf.peekChars(); + if (fd.ident == funcdecl.ident) + hgs.fullQual = true; - if (fd) + // https://issues.dlang.org/show_bug.cgi?id=23745 + // If the potentially overridden function contains errors, + // inform the user to fix that one first + if (fd.errors) { - OutBuffer buf1; - - if (fd.ident == funcdecl.ident) - hgs.fullQual = true; + error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?", + funcdecl.toChars(), fd.toPrettyChars()); + errorSupplemental(fd.loc, "Function `%s` contains errors in its declaration, therefore it cannot be correctly overridden", + fd.toPrettyChars()); + } + else if (fd.isFinalFunc()) + { + // When trying to override a final method, don't suggest it as a candidate(Issue #19613) + .error(funcdecl.loc, "%s `%s` does not override any function", funcdecl.kind, funcdecl.toPrettyChars); - // https://issues.dlang.org/show_bug.cgi?id=23745 - // If the potentially overridden function contains errors, - // inform the user to fix that one first - if (fd.errors) - { - error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?", - funcdecl.toChars(), fd.toPrettyChars()); - errorSupplemental(fd.loc, "Function `%s` contains errors in its declaration, therefore it cannot be correctly overridden", - fd.toPrettyChars()); - } - else + // Look for a non-final method with the same name to suggest as an alternative + auto cdparent = fd.parent ? fd.parent.isClassDeclaration() : null; + if (cdparent) { - functionToBufferFull(cast(TypeFunction)(fd.type), buf1, - new Identifier(fd.toPrettyChars()), hgs, null); + Dsymbol nonFinalAlt = null; - error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?", - funcdeclToChars, buf1.peekChars()); - } + auto overloadableSyms = cdparent.symtab.lookup(fd.ident); + if (overloadableSyms) + { + // Check each overload to find one that's not final + overloadApply(overloadableSyms, (Dsymbol s) + { + if (auto funcAlt = s.isFuncDeclaration()) + { + if (funcAlt != fd && !funcAlt.isFinalFunc()) + { + nonFinalAlt = funcAlt; + return 1; + } + } + return 0; + }); + + // Provide a helpful suggestion if we found a viable alternative + if (nonFinalAlt) + { + auto funcAlt = nonFinalAlt.isFuncDeclaration(); + OutBuffer buf2; + functionToBufferFull(cast(TypeFunction)(funcAlt.type), buf2, + new Identifier(funcAlt.toPrettyChars()), hgs, null); + errorSupplemental(funcdecl.loc, "Did you mean to override `%s`?", buf2.peekChars()); + } + } + } } else { - error(funcdecl.loc, "function `%s` does not override any function, did you mean to override %s `%s`?", - funcdeclToChars, s.kind, s.toPrettyChars()); - errorSupplemental(funcdecl.loc, "Functions are the only declarations that may be overridden"); - } - } - else - .error(funcdecl.loc, "%s `%s` does not override any function", funcdecl.kind, funcdecl.toPrettyChars); - } + functionToBufferFull(cast(TypeFunction)(fd.type), buf1, + new Identifier(fd.toPrettyChars()), hgs, null); - L2: - objc.setSelector(funcdecl, sc); - objc.checkLinkage(funcdecl); - objc.addToClassMethodList(funcdecl, cd); - objc.setAsOptional(funcdecl, sc); + error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?", + funcdeclToChars, buf1.peekChars()); - /* Go through all the interface bases. - * Disallow overriding any final functions in the interface(s). - */ - foreach (b; cd.interfaces) - { - if (b.sym) - { - if (auto s = search_function(b.sym, funcdecl.ident)) - { - if (auto f2 = s.isFuncDeclaration()) - { - f2 = f2.overloadExactMatch(funcdecl.type); - if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_) - .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s.%s`", funcdecl.kind, funcdecl.toPrettyChars, b.sym.toChars(), f2.toPrettyChars()); - } - } - } - } - - if (funcdecl.isOverride) - { - if (funcdecl.storage_class & STC.disable) - deprecation(funcdecl.loc, - "`%s` cannot be annotated with `@disable` because it is overriding a function in the base class", - funcdecl.toPrettyChars); + // Supplemental error for parameter scope differences + auto tf1 = cast(TypeFunction)funcdecl.type; + auto tf2 = cast(TypeFunction)fd.type; - if (funcdecl.isDeprecated && !(funcdecl.foverrides.length && funcdecl.foverrides[0].isDeprecated)) - deprecation(funcdecl.loc, - "`%s` cannot be marked as `deprecated` because it is overriding a function in the base class", - funcdecl.toPrettyChars); - } + if (tf1 && tf2) + { + auto params1 = tf1.parameterList; + auto params2 = tf2.parameterList; - } - else if (funcdecl.isOverride() && !parent.isTemplateInstance()) - .error(funcdecl.loc, "%s `%s` `override` only applies to class member functions", funcdecl.kind, funcdecl.toPrettyChars); + if (params1.length == params2.length) + { + bool hasScopeDifference = false; - if (auto ti = parent.isTemplateInstance) - { - objc.setSelector(funcdecl, sc); - objc.setAsOptional(funcdecl, sc); - } + for (size_t i = 0; i < params1.length; i++) + { + auto p1 = params1[i]; + auto p2 = params2[i]; - objc.validateSelector(funcdecl); - objc.validateOptional(funcdecl); - // Reflect this.type to f because it could be changed by findVtblIndex - f = funcdecl.type.toTypeFunction(); + if ((p1.storageClass & STC.scope_) == (p2.storageClass & STC.scope_)) + continue; -Ldone: - if (!funcdecl.fbody && !funcdecl.allowsContractWithoutBody()) - .error(funcdecl.loc, "%s `%s` `in` and `out` contracts can only appear without a body when they are virtual interface functions or abstract", funcdecl.kind, funcdecl.toPrettyChars); + if (!(p2.storageClass & STC.scope_)) + continue; - /* Do not allow template instances to add virtual functions - * to a class. - */ - if (funcdecl.isVirtual()) - { - if (auto ti = parent.isTemplateInstance()) - { - // Take care of nested templates - while (1) - { - TemplateInstance ti2 = ti.tempdecl.parent.isTemplateInstance(); - if (!ti2) - break; - ti = ti2; + if (!hasScopeDifference) + { + // Intended signature + errorSupplemental(funcdecl.loc, "Did you intend to override:"); + errorSupplemental(funcdecl.loc, "`%s`", buf1.peekChars()); + hasScopeDifference = true; + } + errorSupplemental(funcdecl.loc, "Parameter %d is missing `scope`", + cast(int)(i + 1)); + } + } + } + } } - - // If it's a member template - if (ClassDeclaration cd = ti.tempdecl.isClassMember()) + else { - .error(funcdecl.loc, "%s `%s` cannot use template to add virtual function to class `%s`", funcdecl.kind, funcdecl.toPrettyChars, cd.toChars()); + error(funcdecl.loc, "function `%s` does not override any function, did you mean to override %s `%s`?", + funcdeclToChars, s.kind, s.toPrettyChars()); + errorSupplemental(funcdecl.loc, "Functions are the only declarations that may be overridden"); } } + else + .error(funcdecl.loc, "%s `%s` does not override any function", funcdecl.kind, funcdecl.toPrettyChars); } - funcdecl.checkMain(); // Check main() parameters and return type +L2: + objc.setSelector(funcdecl, sc); + objc.checkLinkage(funcdecl); + objc.addToClassMethodList(funcdecl, cd); + objc.setAsOptional(funcdecl, sc); - /* Purity and safety can be inferred for some functions by examining - * the function body. + /* Go through all the interface bases. + * Disallow overriding any final functions in the interface(s). */ - if (funcdecl.canInferAttributes(sc)) - funcdecl.initInferAttributes(); - - funcdecl.semanticRun = PASS.semanticdone; - - /* Save scope for possible later use (if we need the - * function internals) - */ - funcdecl._scope = sc.copy(); - funcdecl._scope.setNoFree(); - - __gshared bool printedMain = false; // semantic might run more than once - if (global.params.v.verbose && !printedMain) + foreach (b; cd.interfaces) { - const(char)* type = funcdecl.isMain() ? "main" : funcdecl.isWinMain() ? "winmain" : funcdecl.isDllMain() ? "dllmain" : cast(const(char)*)null; - Module mod = sc._module; - - if (type && mod) + if (b.sym) { - printedMain = true; - auto name = mod.srcfile.toChars(); - auto path = FileName.searchPath(global.importPaths, name, true); - message("entry %-10s\t%s", type, path ? path : name); + if (auto s = search_function(b.sym, funcdecl.ident)) + { + if (auto f2 = s.isFuncDeclaration()) + { + f2 = f2.overloadExactMatch(funcdecl.type); + if (f2 && f2.isFinalFunc() && f2.visible().kind != Visibility.Kind.private_) + .error(funcdecl.loc, "%s `%s` cannot override `final` function `%s.%s`", funcdecl.kind, funcdecl.toPrettyChars, b.sym.toChars(), f2.toPrettyChars()); + } + } } } - if (funcdecl.fbody && sc._module.isRoot() && - (funcdecl.isMain() || funcdecl.isWinMain() || funcdecl.isDllMain() || funcdecl.isCMain())) - global.hasMainFunction = true; - - if (funcdecl.fbody && funcdecl.isMain() && sc._module.isRoot()) + if (funcdecl.isOverride) { - // check if `_d_cmain` is defined - bool cmainTemplateExists() - { - Dsymbol pscopesym; - auto rootSymbol = sc.search(funcdecl.loc, Id.empty, pscopesym); - if (auto moduleSymbol = rootSymbol.search(funcdecl.loc, Id.object)) - if (moduleSymbol.search(funcdecl.loc, Id.CMain)) - return true; - - return false; - } + if (funcdecl.storage_class & STC.disable) + deprecation(funcdecl.loc, + "`%s` cannot be annotated with `@disable` because it is overriding a function in the base class", + funcdecl.toPrettyChars); - // Only mixin `_d_cmain` if it is defined - if (cmainTemplateExists()) - { - // add `mixin _d_cmain!();` to the declaring module - auto tqual = new TypeIdentifier(funcdecl.loc, Id.CMain); - auto tm = new TemplateMixin(funcdecl.loc, null, tqual, null); - sc._module.members.push(tm); - } + if (funcdecl.isDeprecated && !(funcdecl.foverrides.length && funcdecl.foverrides[0].isDeprecated)) + deprecation(funcdecl.loc, + "`%s` cannot be marked as `deprecated` because it is overriding a function in the base class", + funcdecl.toPrettyChars); } + return 0; +} - assert(funcdecl.type.ty != Terror || funcdecl.errors); +private TypeFunction getFunctionType(FuncDeclaration fd) +{ + if (auto tf = fd.type.isTypeFunction()) + return tf; - // semantic for parameters' UDAs - foreach (i, param; f.parameterList) + if (!fd.type.isTypeError()) { - if (param && param.userAttribDecl) - param.userAttribDecl.dsymbolSemantic(sc); + .error(fd.loc, "%s `%s` `%s` must be a function instead of `%s`", fd.kind, fd.toPrettyChars, fd.toChars(), fd.type.toChars()); + fd.type = Type.terror; } + fd.errors = true; + return null; } /***************************************** @@ -1657,13 +1763,17 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s, if (!od && !td.overnext) { .error(loc, "%s `%s` is not callable using argument types `!(%s)%s`", - td.kind(), td.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars()); + td.kind(), td.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars()); + + checkNamedArgErrorAndReport(td, argumentList, loc); } else { .error(loc, "none of the overloads of %s `%s.%s` are callable using argument types `!(%s)%s`", - td.kind(), td.parent.toPrettyChars(), td.ident.toChars(), - tiargsBuf.peekChars(), fargsBuf.peekChars()); + td.kind(), td.parent.toPrettyChars(), td.ident.toChars(), + tiargsBuf.peekChars(), fargsBuf.peekChars()); + + checkNamedArgErrorAndReport(td, argumentList, loc); } @@ -1683,7 +1793,9 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s, if (od) { .error(loc, "none of the overloads of `%s` are callable using argument types `!(%s)%s`", - od.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars()); + od.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars()); + + checkNamedArgErrorAndReportOverload(od, argumentList, loc); if (!global.gag || global.params.v.showGaggedErrors) printCandidates(loc, od, sc.isDeprecated()); return null; @@ -1713,8 +1825,14 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s, OutBuffer buf; buf.argExpTypesToCBuffer(fargs); if (fd.isCtorDeclaration()) - .error(loc, "none of the overloads of `%s` can construct a %sobject with argument types `(%s)`", - fd.toChars(), thisBuf.peekChars(), buf.peekChars()); + { + if (tthis.mod & MODFlags.immutable_) + .error(loc, "none of the overloads of `%s` can construct an immutable object with argument types `(%s)`. Expected `immutable(%s)`", + fd.toChars(), buf.peekChars(), buf.peekChars()); + else + .error(loc, "none of the overloads of `%s` can construct a %sobject with argument types `(%s)`", + fd.toChars(), thisBuf.peekChars(), buf.peekChars()); + } else .error(loc, "none of the overloads of `%s` are callable using a %sobject with argument types `(%s)`", fd.toChars(), thisBuf.peekChars(), buf.peekChars()); @@ -1782,10 +1900,15 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s, functionResolve(mErr, baseFunction, loc, sc, tiargs, baseClass.type, argumentList); if (mErr.last > MATCH.nomatch && mErr.lastf) { - errorSupplemental(loc, "%s `%s` hides base class function `%s`", - fd.kind, fd.toPrettyChars(), mErr.lastf.toPrettyChars()); - errorSupplemental(loc, "add `alias %s = %s` to `%s`'s body to merge the overload sets", - fd.toChars(), mErr.lastf.toPrettyChars(), tthis.toChars()); + errorSupplemental(loc, "Note: %s `%s` hides base class %s `%s`", + fd.kind, fd.toPrettyChars(), + mErr.lastf.kind, mErr.lastf.toPrettyChars()); + + if (!fd.isCtorDeclaration) + { + errorSupplemental(loc, "Add `alias %s = %s;` to `%s`'s body to merge the overload sets", + fd.toChars(), mErr.lastf.toPrettyChars(), tthis.toChars()); + } return null; } } @@ -1803,6 +1926,62 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s, return null; } +/******************************************************** + * Check for named argument errors in template declarations and report them. + * Params: + * td = template declaration to check + * argumentList = arguments to check + * loc = location for error reporting + */ +private void checkNamedArgErrorAndReport(TemplateDeclaration td, ArgumentList argumentList, Loc loc) +{ + if (!argumentList.hasArgNames()) + return; + + auto tf = td.onemember ? td.onemember.isFuncDeclaration() : null; + if (tf && tf.type && tf.type.ty == Tfunction) + { + OutBuffer buf; + auto resolvedArgs = tf.type.isTypeFunction().resolveNamedArgs(argumentList, &buf); + if (!resolvedArgs && buf.length) + .errorSupplemental(loc, "%s", buf.peekChars()); + } +} + +/****************************************** + * Check for named argument errors in overload sets and report them. + * Params: + * od = overload declaration to check + * argumentList = arguments to check + * loc = location for error report + */ +private void checkNamedArgErrorAndReportOverload(Dsymbol od, ArgumentList argumentList, Loc loc) +{ + if (!argumentList.hasArgNames()) + return; + + FuncDeclaration tf = null; + overloadApply(od, (Dsymbol s) { + if (!tf) + { + if (auto fd = s.isFuncDeclaration()) + tf = fd; + else if (auto td = s.isTemplateDeclaration()) + if (td.onemember) + tf = td.onemember.isFuncDeclaration(); + } + return 0; + }); + + if (tf && tf.type && tf.type.ty == Tfunction) + { + OutBuffer buf; + auto resolvedArgs = tf.type.isTypeFunction().resolveNamedArgs(argumentList, &buf); + if (!resolvedArgs && buf.length) + .errorSupplemental(loc, "%s", buf.peekChars()); + } +} + /******************************************* * Prints template and function overload candidates as supplemental errors. * Params: @@ -2050,16 +2229,17 @@ int overrides(FuncDeclaration fd1, FuncDeclaration fd2) * Params: * f = first function * g = second function - * names = names of parameters + * names = argument Labels of parameters(name and location of the name) * Returns: * match 'this' is at least as specialized as g * 0 g is more specialized than 'this' */ -MATCH leastAsSpecialized(FuncDeclaration f, FuncDeclaration g, Identifiers* names) +MATCH leastAsSpecialized(FuncDeclaration f, FuncDeclaration g, ArgumentLabels* names) { enum LOG_LEASTAS = 0; static if (LOG_LEASTAS) { + Identifiers *names = extractNames(names); import core.stdc.stdio : printf; printf("leastAsSpecialized(%s, %s, %s)\n", f.toChars(), g.toChars(), names ? names.toChars() : "null"); printf("%s, %s\n", f.type.toChars(), g.type.toChars()); @@ -3566,3 +3746,99 @@ extern (D) int overloadApply(Dsymbol fstart, scope int delegate(Dsymbol) dg, Sco } return overloadApplyRecurse(fstart, dg, sc); } + +Dsymbol isUnique(OverDeclaration od) +{ + Dsymbol result = null; + overloadApply(od.aliassym, (Dsymbol s) + { + if (result) + { + result = null; + return 1; // ambiguous, done + } + else + { + result = s; + return 0; + } + }); + return result; +} + +/************************************ +* Check to see if this variable is actually in an enclosing function +* rather than the current one. +* Update nestedrefs[], closureVars[] and outerVars[]. +* Returns: true if error occurs. +*/ +extern (D) bool checkNestedReference(VarDeclaration vd, Scope* sc, Loc loc) +{ + //printf("VarDeclaration::checkNestedReference() %s\n", toChars()); + if (sc.intypeof == 1 || sc.ctfe) + return false; + if (!vd.parent || vd.parent == sc.parent) + return false; + if (vd.isDataseg() || (vd.storage_class & STC.manifest)) + return false; + + // The current function + FuncDeclaration fdthis = sc.parent.isFuncDeclaration(); + if (!fdthis) + return false; // out of function scope + + Dsymbol p = vd.toParent2(); + + // Function literals from fdthis to p must be delegates + ensureStaticLinkTo(fdthis, p); + + // The function that this variable is in + FuncDeclaration fdv = p.isFuncDeclaration(); + if (!fdv || fdv == fdthis) + return false; + + // Add fdthis to nestedrefs[] if not already there + if (!vd.nestedrefs.contains(fdthis)) + vd.nestedrefs.push(fdthis); + + //printf("\tfdv = %s\n", fdv.toChars()); + //printf("\tfdthis = %s\n", fdthis.toChars()); + if (loc.isValid()) + { + if (fdthis.getLevelAndCheck(loc, sc, fdv, vd) == fdthis.LevelError) + return true; + } + + // Add this VarDeclaration to fdv.closureVars[] if not already there + if (!sc.intypeof && !sc.traitsCompiles && + // https://issues.dlang.org/show_bug.cgi?id=17605 + (fdv.skipCodegen || !fdthis.skipCodegen)) + { + if (!fdv.closureVars.contains(vd)) + fdv.closureVars.push(vd); + } + + if (!fdthis.outerVars.contains(vd)) + fdthis.outerVars.push(vd); + + //printf("fdthis is %s\n", fdthis.toChars()); + //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars()); + // __dollar creates problems because it isn't a real variable + // https://issues.dlang.org/show_bug.cgi?id=3326 + if (vd.ident == Id.dollar) + { + .error(loc, "cannnot use `$` inside a function literal"); + return true; + } + if (vd.ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759 + { + ExpInitializer ez = vd._init.isExpInitializer(); + assert(ez); + Expression e = ez.exp; + if (e.op == EXP.construct || e.op == EXP.blit) + e = (cast(AssignExp)e).e2; + return lambdaCheckForNestedRef(e, sc); + } + + return false; +} diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d index 61ff273c6b79..0f8c8c67b927 100644 --- a/gcc/d/dmd/hdrgen.d +++ b/gcc/d/dmd/hdrgen.d @@ -2724,6 +2724,12 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt void visitComma(CommaExp e) { + if (e.originalExp !is null) + { + e.originalExp.expressionPrettyPrint(buf, hgs); + return; + } + // CommaExp is generated by the compiler so it shouldn't // appear in error messages or header files. // For now, this treats the case where the compiler @@ -3695,9 +3701,9 @@ private void parameterToBuffer(Parameter p, ref OutBuffer buf, ref HdrGenState h * buf = buffer to write to * hgs = context * basis = replace `null`s in argument list with this expression (for sparse array literals) - * names = if non-null, use these as the names for the arguments + * names = if non-null, use these as the argument Labels for the arguments */ -private void argsToBuffer(Expressions* expressions, ref OutBuffer buf, ref HdrGenState hgs, Expression basis = null, Identifiers* names = null) +private void argsToBuffer(Expressions* expressions, ref OutBuffer buf, ref HdrGenState hgs, Expression basis = null, ArgumentLabels* names = null) { if (!expressions || !expressions.length) return; @@ -3708,9 +3714,9 @@ private void argsToBuffer(Expressions* expressions, ref OutBuffer buf, ref HdrGe if (i) buf.writestring(", "); - if (names && i < names.length && (*names)[i]) + if (names && i < names.length && (*names)[i].name) { - buf.writestring((*names)[i].toString()); + buf.writestring((*names)[i].name.toString()); buf.writestring(": "); } if (!el) diff --git a/gcc/d/dmd/iasmgcc.d b/gcc/d/dmd/iasmgcc.d index 3d6e6ab5b511..4d9a758bb471 100644 --- a/gcc/d/dmd/iasmgcc.d +++ b/gcc/d/dmd/iasmgcc.d @@ -69,7 +69,7 @@ public Statement gccAsmSemantic(GccAsmStatement s, Scope* sc) s.insn = semanticString(sc, s.insn, "asm instruction template"); if (s.labels && s.outputargs) - error(s.loc, "extended asm statements with labels cannot have output constraints"); + p.eSink.error(s.loc, "extended asm statements with labels cannot have output constraints"); // Analyse all input and output operands. if (s.args) @@ -143,6 +143,35 @@ public void gccAsmSemantic(CAsmDeclaration ad, Scope* sc) private: +/*********************************** + * Parse an expression that evaluates to a string. + * Grammar: + * | AsmStringExpr: + * | StringLiteral + * | ( AssignExpression ) + * Params: + * p = parser state + * Returns: + * the parsed string expression + */ +Expression parseAsmString(Parser)(Parser p) +{ + if (p.token.value == TOK.leftParenthesis) + { + p.nextToken(); + Expression insn = p.parseAssignExp(); + p.check(TOK.rightParenthesis); + return insn; + } + else if (p.token.value != TOK.string_) + { + p.eSink.error(p.token.loc, "expected string literal or expression in parentheses"); + return ErrorExp.get(); + } + + return p.parsePrimaryExp(); +} + /*********************************** * Parse list of extended asm input or output operands. * Grammar: @@ -202,7 +231,7 @@ int parseExtAsmOperands(Parser)(Parser p, GccAsmStatement s) if (p.token.value != TOK.leftParenthesis) { arg = p.parseAssignExp(); - error(arg.loc, "`%s` must be surrounded by parentheses", arg.toChars()); + p.eSink.error(arg.loc, "`%s` must be surrounded by parentheses", arg.toChars()); } else { @@ -352,13 +381,13 @@ Lerror: * | GotoAsmInstruction * | * | BasicAsmInstruction: - * | AssignExpression + * | AsmStringExpr * | * | ExtAsmInstruction: - * | AssignExpression : Operands(opt) : Operands(opt) : Clobbers(opt) + * | AsmStringExpr : Operands(opt) : Operands(opt) : Clobbers(opt) * | * | GotoAsmInstruction: - * | AssignExpression : : Operands(opt) : Clobbers(opt) : GotoLabels(opt) + * | AsmStringExpr : : Operands(opt) : Clobbers(opt) : GotoLabels(opt) * Params: * p = parser state * s = asm statement to parse @@ -367,7 +396,10 @@ Lerror: */ GccAsmStatement parseGccAsm(Parser)(Parser p, GccAsmStatement s) { - s.insn = p.parseAssignExp(); + s.insn = p.parseAsmString(); + if (s.insn.isErrorExp()) + return s; + if (p.token.value == TOK.semicolon || p.token.value == TOK.endOfFile) goto Ldone; @@ -519,11 +551,11 @@ unittest } }, // Any CTFE-able string allowed as instruction template. - q{ asm { generateAsm(); + q{ asm { (generateAsm); } }, // Likewise mixins, permissible so long as the result is a string. - q{ asm { mixin(`"repne"`, `~ "scasb"`); + q{ asm { (mixin(`"repne"`, `~ "scasb"`)); } }, // :: token tests @@ -557,6 +589,11 @@ unittest // https://issues.dlang.org/show_bug.cgi?id=20593 q{ asm { "instruction" : : "operand" 123; } }, + + // https://github.com/dlang/dmd/issues/21298 + q{ asm { 1; } }, + q{ asm { int; } }, + q{ asm { : "=r" (i); } }, ]; foreach (test; passAsmTests) diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d index e1c22f2f04ca..2d10e6f991af 100644 --- a/gcc/d/dmd/id.d +++ b/gcc/d/dmd/id.d @@ -324,7 +324,6 @@ immutable Msgtable[] msgtable = { "__switch_error"}, { "__ArrayCast"}, { "_d_HookTraceImpl" }, - { "_d_arraysetlengthTImpl"}, { "_d_arraysetlengthT"}, { "_d_arraysetlengthTTrace"}, { "_d_arrayappendT" }, diff --git a/gcc/d/dmd/imphint.d b/gcc/d/dmd/imphint.d index 382a0f378633..e22bcc8b123f 100644 --- a/gcc/d/dmd/imphint.d +++ b/gcc/d/dmd/imphint.d @@ -26,8 +26,15 @@ const(char)[] importHint(const(char)[] s) @safe return *entry; return null; } +const(char)[] cIncludeHint(const(char)[] s) @safe +{ + if (auto entry = s in cHints) + return *entry; + return null; +} private immutable string[string] hints; +private immutable string[string] cHints; shared static this() { @@ -83,6 +90,23 @@ shared static this() "InterpolationHeader": "core.interpolation", "InterpolationFooter": "core.interpolation", ]; + cHints = [ + "NULL": "", + "calloc": "", + "fopen": "", + "fprintf": "", + "free": "", + "malloc": "", + "memcpy": "", + "memmove": "", + "memset": "", + "printf": "", + "ptrdiff_t": "", + "size_t": "", + "stderr": "", + "stdin": "", + "stdout": "", + ]; } unittest diff --git a/gcc/d/dmd/importc.d b/gcc/d/dmd/importc.d index 2f88a21c049f..059de62b1f9c 100644 --- a/gcc/d/dmd/importc.d +++ b/gcc/d/dmd/importc.d @@ -17,16 +17,22 @@ import core.stdc.stdio; import dmd.astenums; import dmd.dcast; +import dmd.denum; import dmd.declaration; import dmd.dscope; import dmd.dsymbol; import dmd.dsymbolsem; +import dmd.dinterpret : ctfeInterpret; import dmd.errors; import dmd.expression; import dmd.expressionsem; import dmd.identifier; +import dmd.id : Id; import dmd.init; +import dmd.intrange : IntRange; import dmd.mtype; +import dmd.optimize : optimize; +import dmd.rootobject : DYNCAST; import dmd.tokens; import dmd.typesem; @@ -120,6 +126,12 @@ Expression fieldLookup(Expression e, Scope* sc, Identifier id, bool arrow) e = e.expressionSemantic(sc); if (e.isErrorExp()) return e; + if (arrow) + { + e = arrayFuncConv(e, sc); + if (e.isErrorExp()) + return e; + } auto t = e.type; if (t.isTypePointer()) @@ -532,11 +544,17 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy } } + // Don't let macros shadow real symbols + if (auto td = s.isTemplateDeclaration()) + { + if (td.isCmacro) return s2; + } + auto vd = s.isVarDeclaration(); // new declaration auto vd2 = s2.isVarDeclaration(); // existing declaration if (vd && vd.isCmacro()) - return vd2; + return s2; assert(!(vd2 && vd2.isCmacro())); @@ -638,3 +656,115 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy return collision(); } + +/********************************* + * ImportC-specific semantic analysis on enum declaration `ed` + */ +void cEnumSemantic(Scope* sc, EnumDeclaration ed) +{ + // C11 6.7.2.2 + Type commonType = ed.memtype; + if (!commonType) + commonType = Type.tint32; + ulong nextValue = 0; // C11 6.7.2.2-3 first member value defaults to 0 + + // C11 6.7.2.2-2 value must be representable as an int. + // The sizemask represents all values that int will fit into, + // from 0..uint.max. We want to cover int.min..uint.max. + IntRange ir = IntRange.fromType(commonType); + + void emSemantic(EnumMember em, ref ulong nextValue) + { + static void errorReturn(EnumMember em) + { + em.value = ErrorExp.get(); + em.errors = true; + em.semanticRun = PASS.semanticdone; + } + + em.semanticRun = PASS.semantic; + em.type = commonType; + em._linkage = LINK.c; + em.storage_class |= STC.manifest; + if (em.value) + { + Expression e = em.value; + assert(e.dyncast() == DYNCAST.expression); + + /* To merge the type of e with commonType, add 0 of type commonType + */ + if (!ed.memtype) + e = new AddExp(em.loc, e, new IntegerExp(em.loc, 0, commonType)); + + e = e.expressionSemantic(sc); + e = resolveProperties(sc, e); + e = e.integralPromotions(sc); + e = e.ctfeInterpret(); + if (e.op == EXP.error) + return errorReturn(em); + auto ie = e.isIntegerExp(); + if (!ie) + { + // C11 6.7.2.2-2 + .error(em.loc, "%s `%s` enum member must be an integral constant expression, not `%s` of type `%s`", em.kind, em.toPrettyChars, e.toChars(), e.type.toChars()); + return errorReturn(em); + } + if (ed.memtype && !ir.contains(getIntRange(ie))) + { + // C11 6.7.2.2-2 + .error(em.loc, "%s `%s` enum member value `%s` does not fit in `%s`", em.kind, em.toPrettyChars, e.toChars(), commonType.toChars()); + return errorReturn(em); + } + nextValue = ie.toInteger(); + if (!ed.memtype) + commonType = e.type; + em.value = new IntegerExp(em.loc, nextValue, commonType); + } + else + { + // C11 6.7.2.2-3 add 1 to value of previous enumeration constant + bool first = (em == (*em.ed.members)[0]); + if (!first) + { + Expression max = getProperty(commonType, null, em.loc, Id.max, 0); + if (nextValue == max.toInteger()) + { + .error(em.loc, "%s `%s` initialization with `%s+1` causes overflow for type `%s`", em.kind, em.toPrettyChars, max.toChars(), commonType.toChars()); + return errorReturn(em); + } + nextValue += 1; + } + em.value = new IntegerExp(em.loc, nextValue, commonType); + } + em.type = commonType; + em.semanticRun = PASS.semanticdone; + } + + ed.members.foreachDsymbol( (s) + { + if (EnumMember em = s.isEnumMember()) + emSemantic(em, nextValue); + }); + + if (!ed.memtype) + { + // cast all members to commonType + ed.members.foreachDsymbol( (s) + { + if (EnumMember em = s.isEnumMember()) + { + em.type = commonType; + // optimize out the cast so that other parts of the compiler can + // assume that an integral enum's members are `IntegerExp`s. + // https://issues.dlang.org/show_bug.cgi?id=24504 + em.value = em.value.castTo(sc, commonType).optimize(WANTvalue); + } + }); + } + + ed.memtype = commonType; + // Set semantic2done to mark C enums as fully processed + // Prevents issues with final switch statements that reference C enums + ed.semanticRun = PASS.semantic2done; + return; +} diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d index 1ebccf77ee32..7247d7479746 100644 --- a/gcc/d/dmd/initsem.d +++ b/gcc/d/dmd/initsem.d @@ -153,7 +153,10 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn // that is not disabled. if (sd.hasRegularCtor(true)) { - error(i.loc, "%s `%s` has constructors, cannot use `{ initializers }`, use `%s( initializers )` instead", sd.kind(), sd.toChars(), sd.toChars()); + error(i.loc, "Cannot use %s initializer syntax for %s `%s` because it has a constructor", + sd.kind(), sd.kind(), sd.toChars()); + errorSupplemental(i.loc, "Use `%s( arguments )` instead of `{ initializers }`", + sd.toChars()); return err(); } sd.size(i.loc); @@ -171,7 +174,8 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn return ex; } - auto elements = resolveStructLiteralNamedArgs(sd, t, sc, i.loc, i.field[], &getExp, (size_t j) => i.value[j].loc); + auto elements = resolveStructLiteralNamedArgs(sd, t, sc, i.loc, i.field.length, (size_t j) => i.field[j], &getExp, (size_t j) => i.value[j].loc, (size_t j) => i.value[j].loc); + //Keeping both the getArgLoc and getNameLoc same as i.field doesn't have a .loc value here. if (!elements) return err(); @@ -240,6 +244,9 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn goto default; break; + case Terror: + return err(); + default: error(i.loc, "cannot use array to initialize `%s`", t.toChars()); return err(); @@ -394,7 +401,10 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn if (needInterpret) i.exp = i.exp.ctfeInterpret(); if (i.exp.op == EXP.voidExpression) - error(i.loc, "variables cannot be initialized with an expression of type `void`. Use `void` initialization instead."); + { + error(i.loc, "variables cannot be initialized with an expression of type `void`"); + errorSupplemental(i.loc, "only `= void;` is allowed, which prevents default initialization"); + } } else { @@ -755,9 +765,13 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn // C11 6.2.5-20 "element type shall be complete whenever the array type is specified" assert(0); // should have been detected by parser } + auto bt = tsa.nextOf().toBasetype(); - auto tnsa = tsa.nextOf().toBasetype().isTypeSArray(); - + if (auto tnss = bt.isTypeStruct()) + { + return subStruct(tnss, index); + } + auto tnsa = bt.isTypeSArray(); auto ai = new ArrayInitializer(ci.loc); ai.isCarray = true; @@ -1505,15 +1519,18 @@ Params: t = type of struct (potentially including qualifiers such as `const` or `immutable`) sc = scope of the expression initializing the struct iloc = location of expression initializing the struct - names = identifiers passed in argument list, `null` entries for positional arguments - getExp = function that, given an index into `names` and destination type, returns the initializing expression - getLoc = function that, given an index into `names`, returns a location for error messages + argCount = count of argumnet present + getExp = function that, given an index into `argNames` and destination type, returns the initializing expression + getArgName = function that, given an index into `argNames`, returns the name of argument for error messages + getArgLoc = function that, given an index into `argNames`, returns a location of argument for error messages + getNameLoc = function that, given an index into `argNames`, returns a location of that `name` for error messages Returns: list of expressions ordered to the struct's fields, or `null` on error */ Expressions* resolveStructLiteralNamedArgs(StructDeclaration sd, Type t, Scope* sc, - Loc iloc, Identifier[] names, scope Expression delegate(size_t i, Type fieldType) getExp, - scope Loc delegate(size_t i) getLoc + Loc iloc, size_t argCount, scope Identifier delegate(size_t i) getArgName, scope Expression delegate(size_t i, Type fieldType) getExp, + scope Loc delegate(size_t i) getArgLoc, + scope Loc delegate(size_t i) getNameLoc ) { //expandTuples for non-identity arguments? @@ -1527,9 +1544,11 @@ Expressions* resolveStructLiteralNamedArgs(StructDeclaration sd, Type t, Scope* // TODO: this part is slightly different from StructLiteralExp::semantic. bool errors = false; size_t fieldi = 0; - foreach (j, id; names) + foreach (j; 0 .. argCount) { - const argLoc = getLoc(j); + const argLoc = getArgLoc(j); + const nameLoc = getNameLoc(j); + Identifier id = getArgName(j); if (id) { // Determine `fieldi` that `id` matches @@ -1538,9 +1557,9 @@ Expressions* resolveStructLiteralNamedArgs(StructDeclaration sd, Type t, Scope* { s = sd.search_correct(id); if (s) - error(argLoc, "`%s` is not a member of `%s`, did you mean %s `%s`?", id.toChars(), sd.toChars(), s.kind(), s.toChars()); + error(nameLoc, "`%s` is not a member of `%s`, did you mean %s `%s`?", id.toChars(), sd.toChars(), s.kind(), s.toChars()); else - error(argLoc, "`%s` is not a member of `%s`", id.toChars(), sd.toChars()); + error(nameLoc, "`%s` is not a member of `%s`", id.toChars(), sd.toChars()); return null; } s.checkDeprecated(iloc, sc); diff --git a/gcc/d/dmd/location.d b/gcc/d/dmd/location.d index 393ffb8a92d4..daff06f3d2c6 100644 --- a/gcc/d/dmd/location.d +++ b/gcc/d/dmd/location.d @@ -48,6 +48,15 @@ struct Loc nothrow: + /// Reset global (Base)Loc tables, invalidating every existing `Loc` out there + /// and giving room to create new `Loc`s + static void _init() + { + locIndex = 1; + locFileTable = null; + lastFileTableIndex = 0; + } + /******************************* * Configure how display is done * Params: @@ -282,9 +291,7 @@ private size_t fileTableIndex(uint index) nothrow @nogc // To speed up linear find, we cache the last hit and compare that first, // since usually we stay in the same file for some time when resolving source locations. // If it's a different file now, either scan forwards / backwards - __gshared size_t lastI = 0; // index of last found hit - - size_t i = lastI; + size_t i = lastFileTableIndex; if (index >= locFileTable[i].startIndex) { while (i + 1 < locFileTable.length && index >= locFileTable[i+1].startIndex) @@ -296,7 +303,7 @@ private size_t fileTableIndex(uint index) nothrow @nogc i--; } - lastI = i; + lastFileTableIndex = i; return i; } @@ -364,6 +371,11 @@ struct BaseLoc uint[] lines; /// For each line, the file offset at which it starts. At index 0 there's always a 0 entry. BaseLoc[] substitutions; /// Substitutions from #line / #file directives + /// Cache for the last line lookup + private size_t lastLineIndex = 0; + /// Cache for the last substitution lookup + private size_t lastSubstIndex = 0; + /// Register that a new line starts at `offset` bytes from the start of the source file void newLine(uint offset) { @@ -419,8 +431,61 @@ struct BaseLoc private size_t getSubstitutionIndex(uint offset) @nogc { + if (substitutions.length <= 1) + return 0; + + // Check if the offset falls within the current cached substitution or the next one + if (lastSubstIndex < substitutions.length - 1) + { + // For the current substitution's range + if (substitutions[lastSubstIndex].startIndex <= offset && + (lastSubstIndex == substitutions.length - 1 || + substitutions[lastSubstIndex + 1].startIndex > offset)) + return lastSubstIndex; + + // For the next substitution's range + if (lastSubstIndex + 1 < substitutions.length - 1 && + substitutions[lastSubstIndex + 1].startIndex <= offset && + substitutions[lastSubstIndex + 2].startIndex > offset) + { + lastSubstIndex++; + return lastSubstIndex; + } + + // For the previous substitution's range + if (lastSubstIndex > 0 && + substitutions[lastSubstIndex - 1].startIndex <= offset && + substitutions[lastSubstIndex].startIndex > offset) + { + lastSubstIndex--; + return lastSubstIndex; + } + } + else if (lastSubstIndex == substitutions.length - 1 && + substitutions[lastSubstIndex].startIndex <= offset) + { + // Last substitution case + return lastSubstIndex; + } + + // Fall back to binary search, but start near size_t lo = 0; - size_t hi = substitutions.length + -1; + size_t hi = substitutions.length - 1; + + // Adjust the range based on the offset relative to lastSubstIndex + if (offset < substitutions[lastSubstIndex].startIndex) + { + // Search backward + lo = 0; + hi = lastSubstIndex; + } + else + { + // Search forward + lo = lastSubstIndex; + hi = substitutions.length - 1; + } + size_t mid = 0; while (lo <= hi) { @@ -428,7 +493,10 @@ struct BaseLoc if (substitutions[mid].startIndex <= offset) { if (mid == substitutions.length - 1 || substitutions[mid + 1].startIndex > offset) + { + lastSubstIndex = mid; // Update cache return mid; + } lo = mid + 1; } @@ -441,10 +509,51 @@ struct BaseLoc } /// Binary search the index in `this.lines` corresponding to `offset` + /// lastLineIndex cache to avoid full binary search when possible private size_t getLineIndex(uint offset) @nogc { + if (lines.length <= 1) + return 0; + + if (lastLineIndex < lines.length - 1) + { + if (lines[lastLineIndex] <= offset && offset < lines[lastLineIndex + 1]) + return lastLineIndex; + + if (lastLineIndex + 1 < lines.length - 1 && + lines[lastLineIndex + 1] <= offset && offset < lines[lastLineIndex + 2]) + { + lastLineIndex++; + return lastLineIndex; + } + + if (lastLineIndex > 0 && + lines[lastLineIndex - 1] <= offset && offset < lines[lastLineIndex]) + { + lastLineIndex--; + return lastLineIndex; + } + } + else if (lastLineIndex == lines.length - 1 && lines[lastLineIndex] <= offset) + { + return lastLineIndex; + } + + // Fall back to binary search size_t lo = 0; - size_t hi = lines.length + -1; + size_t hi = lines.length - 1; + + if (offset < lines[lastLineIndex]) + { + lo = 0; + hi = lastLineIndex; + } + else + { + lo = lastLineIndex; + hi = lines.length - 1; + } + size_t mid = 0; while (lo <= hi) { @@ -452,7 +561,10 @@ struct BaseLoc if (lines[mid] <= offset) { if (mid == lines.length - 1 || lines[mid + 1] > offset) + { + lastLineIndex = mid; // Update cache return mid; + } lo = mid + 1; } @@ -470,3 +582,6 @@ private __gshared uint locIndex = 1; // Global mapping of Loc indices to source file offset/line/column, see `BaseLoc` private __gshared BaseLoc*[] locFileTable; + +// Index of last found hit in locFileTable, for optimization +private __gshared size_t lastFileTableIndex = 0; diff --git a/gcc/d/dmd/mangle/package.d b/gcc/d/dmd/mangle/package.d index 3ad2c7d57941..cc797614ed0b 100644 --- a/gcc/d/dmd/mangle/package.d +++ b/gcc/d/dmd/mangle/package.d @@ -1339,7 +1339,11 @@ extern (D) const(char)[] externallyMangledIdentifier(Declaration d) const par = d.toParent(); //toParent() skips over mixin templates if (!par || par.isModule() || linkage == LINK.cpp || (linkage == LINK.c && d.isCsymbol() && - (d.isFuncDeclaration() || + // https://github.com/dlang/dmd/issues/21241 + // Static check is so C static functions get a unique mangle so the linker + // won't merge them if compiling all-at-once. + // Non-static functions can use their ident as their mangle. + ((d.isFuncDeclaration() && !d.isStatic()) || (d.isVarDeclaration() && d.isDataseg() && d.storage_class & STC.extern_)))) { if (linkage != LINK.d && d.localNum) diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d index a3e1a8ca858b..c9b57449658a 100644 --- a/gcc/d/dmd/mtype.d +++ b/gcc/d/dmd/mtype.d @@ -2234,7 +2234,7 @@ extern (C++) final class TypeSArray : TypeArray auto elements = new Expressions(d); foreach (ref e; *elements) e = null; - auto ae = new ArrayLiteralExp(Loc.initial, this, elementinit, elements); + auto ae = new ArrayLiteralExp(loc, this, elementinit, elements); return ae; } @@ -2631,7 +2631,7 @@ extern (C++) final class TypeFunction : TypeNext extern(D) Expressions* resolveNamedArgs(ArgumentList argumentList, OutBuffer* buf) { Expression[] args = argumentList.arguments ? (*argumentList.arguments)[] : null; - Identifier[] names = argumentList.names ? (*argumentList.names)[] : null; + ArgumentLabel[] names = argumentList.names ? (*argumentList.names)[] : null; const nParams = parameterList.length(); // cached because O(n) auto newArgs = new Expressions(nParams); newArgs.zero(); @@ -2645,7 +2645,7 @@ extern (C++) final class TypeFunction : TypeNext ci++; continue; } - auto name = i < names.length ? names[i] : null; + auto name = i < names.length ? names[i].name : null; if (name) { hasNamedArgs = true; @@ -3761,6 +3761,7 @@ extern (C++) final class TypeTag : Type Loc loc; /// location of declaration TOK tok; /// TOK.struct_, TOK.union_, TOK.enum_ structalign_t packalign; /// alignment of struct/union fields + Expressions* alignExps; /// alignment of struct itself Identifier id; /// tag name identifier Type base; /// base type for enums otherwise null Dsymbols* members; /// members of struct, null if none @@ -3770,7 +3771,7 @@ extern (C++) final class TypeTag : Type /// struct S { int a; } s1, *s2; MOD mod; /// modifiers to apply after type is resolved (only MODFlags.const_ at the moment) - extern (D) this(Loc loc, TOK tok, Identifier id, structalign_t packalign, Type base, Dsymbols* members) @safe + extern (D) this(Loc loc, TOK tok, Identifier id, structalign_t packalign, Expressions* alignExps, Type base, Dsymbols* members) @safe { //printf("TypeTag ctor %s %p\n", id ? id.toChars() : "null".ptr, this); super(Ttag); @@ -3778,6 +3779,7 @@ extern (C++) final class TypeTag : Type this.tok = tok; this.id = id; this.packalign = packalign; + this.alignExps = alignExps; this.base = base; this.members = members; this.mod = 0; diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h index 4d1938f4a723..4d303acf3c3c 100644 --- a/gcc/d/dmd/mtype.h +++ b/gcc/d/dmd/mtype.h @@ -554,6 +554,8 @@ public: void isReturn(bool v); bool isReturnScope() const; void isReturnScope(bool v); + bool isRvalue() const; + void isRvalue(bool v); bool isScopeQual() const; void isScopeQual(bool v); bool isReturnInferred() const; diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d index f1494a409f6e..5e3c164acbb4 100644 --- a/gcc/d/dmd/nogc.d +++ b/gcc/d/dmd/nogc.d @@ -24,6 +24,7 @@ import dmd.dscope; import dmd.dtemplate : isDsymbol; import dmd.dsymbol : PASS; import dmd.errors; +import dmd.escape; import dmd.expression; import dmd.func; import dmd.globals; @@ -45,13 +46,15 @@ extern (C++) final class NOGCVisitor : StoppableVisitor alias visit = typeof(super).visit; public: FuncDeclaration f; + Scope* sc; bool checkOnly; // don't print errors bool err; bool nogcExceptions; // -preview=dip1008 enabled - extern (D) this(FuncDeclaration f) scope @safe + extern (D) this(FuncDeclaration f, Scope* sc) scope @safe { this.f = f; + this.sc = sc; } void doCond(Expression exp) @@ -86,6 +89,8 @@ public: */ private bool setGC(Expression e, const(char)* msg) { + if (sc.debug_) + return false; if (checkOnly) { err = true; @@ -119,10 +124,17 @@ public: override void visit(ArrayLiteralExp e) { - if (e.type.ty != Tarray || !e.elements || !e.elements.length || e.onstack) + if (e.type.toBasetype().isTypeSArray() || !e.elements || !e.elements.length || e.onstack) return; if (setGC(e, "this array literal")) return; + + if (checkArrayLiteralEscape(*sc, e, false)) + { + err = true; + return; + } + f.printGCUsage(e.loc, "array literal may cause a GC allocation"); } @@ -208,9 +220,10 @@ public: } } -Expression checkGC(Scope* sc, Expression e) +Expression checkGC(Expression e, Scope* sc) { - if (sc.ctfeBlock) // ignore GC in ctfe blocks + // printf("%s checkGC(%s)\n", e.loc.toChars, e.toChars); + if (e.gcPassDone || sc.ctfeBlock || sc.ctfe || sc.intypeof == 1 || !sc.func) return e; /* If betterC, allow GC to happen in non-CTFE code. @@ -219,28 +232,20 @@ Expression checkGC(Scope* sc, Expression e) */ const betterC = !global.params.useGC; FuncDeclaration f = sc.func; - if (e && e.op != EXP.error && f && sc.intypeof != 1 && - (!sc.ctfe || betterC) && - (f.type.ty == Tfunction && - (cast(TypeFunction)f.type).isNogc || f.nogcInprocess || global.params.v.gc) && - !sc.debug_) - { - scope NOGCVisitor gcv = new NOGCVisitor(f); - gcv.checkOnly = betterC; - gcv.nogcExceptions = sc.previews.dip1008; - walkPostorder(e, gcv); - if (gcv.err) - { - if (betterC) - { - /* Allow ctfe to use the gc code, but don't let it into the runtime - */ - f.skipCodegen = true; - } - else - return ErrorExp.get(); - } - } + scope NOGCVisitor gcv = new NOGCVisitor(f, sc); + gcv.checkOnly = betterC && (f.type.isTypeFunction().isNogc || f.nogcInprocess); + gcv.nogcExceptions = sc.previews.dip1008; + walkPostorder(e, gcv); + e.gcPassDone = true; + + if (!gcv.err) + return e; + + if (!betterC) + return ErrorExp.get(); + + // Allow ctfe to use the gc code, but don't let it into the runtime + f.skipCodegen = true; return e; } diff --git a/gcc/d/dmd/nspace.d b/gcc/d/dmd/nspace.d index 0c93f0e7994a..b8116343d6fe 100644 --- a/gcc/d/dmd/nspace.d +++ b/gcc/d/dmd/nspace.d @@ -78,12 +78,6 @@ extern (C++) final class Nspace : ScopeDsymbol return ns; } - override bool hasPointers() - { - //printf("Nspace::hasPointers() %s\n", toChars()); - return members.foreachDsymbol( (s) { return s.hasPointers(); } ) != 0; - } - override const(char)* kind() const { return "namespace"; diff --git a/gcc/d/dmd/nspace.h b/gcc/d/dmd/nspace.h index 7b4c302303da..782688b9de1c 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; - bool hasPointers() override; const char *kind() const override; void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d index 66b8c6a4953c..b13f8c64584f 100644 --- a/gcc/d/dmd/optimize.d +++ b/gcc/d/dmd/optimize.d @@ -1072,7 +1072,8 @@ Expression optimize(Expression e, int result, bool keepLvalue = false) // All negative integral powers are illegal. if (e.e1.type.isIntegral() && (e.e2.op == EXP.int64) && cast(sinteger_t)e.e2.toInteger() < 0) { - error(e.loc, "cannot raise `%s` to a negative integer power. Did you mean `(cast(real)%s)^^%s` ?", e.e1.type.toBasetype().toChars(), e.e1.toChars(), e.e2.toChars()); + error(e.loc, "cannot raise `%s` to a negative integer power.", e.e1.type.toBasetype().toChars()); + errorSupplemental(e.loc, "did you mean `(cast(real)%s)^^%s` ?", e.e1.toChars(), e.e2.toChars()); return errorReturn(); } // If e2 *could* have been an integer, make it one. diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index e68017c87e55..c57f1d3f7f74 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -28,6 +28,7 @@ import dmd.root.rmem; import dmd.rootobject; import dmd.root.string; import dmd.tokens; +import dmd.expression; alias CompileEnv = dmd.lexer.CompileEnv; @@ -1319,12 +1320,26 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer // Allow identifier, template instantiation, or function call // for `@Argument` (single UDA) form. - AST.Expression exp = parsePrimaryExp(); + AST.Expression exp; + + { + const loc = token.loc; + Identifier id = token.ident; + nextToken(); + if (token.value == TOK.not) + { + auto tempinst = new AST.TemplateInstance(loc, id, parseTemplateArguments()); + exp = new AST.ScopeExp(loc, tempinst); + } + else + exp = new AST.IdentifierExp(loc, id); + } + if (token.value == TOK.leftParenthesis) { const loc = token.loc; AST.Expressions* args = new AST.Expressions(); - AST.Identifiers* names = new AST.Identifiers(); + AST.ArgumentLabels* names = new AST.ArgumentLabels(); parseNamedArguments(args, names); exp = new AST.CallExp(loc, exp, args, names); } @@ -2758,7 +2773,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (len > 0) { docline = cast(char*)mem.xmalloc_noscan(len + 2); - memcpy(docline, begPtr, len); + docline[0 .. len] = begPtr[0 .. len]; docline[len] = '\n'; // Terminate all lines by LF docline[len + 1] = '\0'; } @@ -4067,7 +4082,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer */ if (isParameters(&peekt)) { - error("function declaration without return type. (Note that constructors are always named `this`)"); + error("function declaration without return type"); + errorSupplemental("Note that constructors are always named `this`"); } else error("unexpected `(` in declarator"); @@ -7090,12 +7106,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer case TOK.colonColon: // treat as two separate : tokens for iasmgcc *ptoklist = allocateToken(); - memcpy(*ptoklist, &token, Token.sizeof); + **ptoklist = this.token; (*ptoklist).value = TOK.colon; ptoklist = &(*ptoklist).next; *ptoklist = allocateToken(); - memcpy(*ptoklist, &token, Token.sizeof); + **ptoklist = this.token; (*ptoklist).value = TOK.colon; ptoklist = &(*ptoklist).next; @@ -7105,7 +7121,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer default: *ptoklist = allocateToken(); - memcpy(*ptoklist, &token, Token.sizeof); + **ptoklist = this.token; ptoklist = &(*ptoklist).next; *ptoklist = null; nextToken(); @@ -8249,9 +8265,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer const len2 = token.len; len = len1 + len2; auto s2 = cast(char*)mem.xmalloc_noscan(len * char.sizeof); - memcpy(s2, s, len1 * char.sizeof); - memcpy(s2 + len1, token.ustring, len2 * char.sizeof); - s = s2; + s2[0 .. len1] = s[0 .. len1]; + s2[len1 .. len1 + len2] = token.ustring[0 .. len2]; } else break; @@ -8454,10 +8469,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer nextToken(); if (token.value == TOK.identifier && peekNext() == TOK.leftParenthesis) { - error(loc, "unexpected `(` after `%s`, inside `is` expression. Try enclosing the contents of `is` with a `typeof` expression", token.toChars()); + error(loc, "unexpected `(` after `%s`, inside `is` expression", token.toChars()); + errorSupplemental("try enclosing the contents of `is` with a `typeof` expression"); nextToken(); Token* tempTok = peekPastParen(&token); - memcpy(&token, tempTok, Token.sizeof); + token = *tempTok; goto Lerr; } targ = parseType(&ident); @@ -9006,7 +9022,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer case TOK.leftParenthesis: AST.Expressions* args = new AST.Expressions(); - AST.Identifiers* names = new AST.Identifiers(); + AST.ArgumentLabels* names = new AST.ArgumentLabels(); parseNamedArguments(args, names); e = new AST.CallExp(loc, e, args, names); continue; @@ -9053,11 +9069,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer private AST.Expression parseMulExp() { - const loc = token.loc; auto e = parseUnaryExp(); while (1) { + const loc = token.loc; switch (token.value) { case TOK.mul: @@ -9088,11 +9104,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer private AST.Expression parseAddExp() { - const loc = token.loc; auto e = parseMulExp(); while (1) { + const loc = token.loc; switch (token.value) { case TOK.add: @@ -9123,11 +9139,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer private AST.Expression parseShiftExp() { - const loc = token.loc; auto e = parseAddExp(); while (1) { + const loc = token.loc; switch (token.value) { case TOK.leftShift: @@ -9158,10 +9174,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer private AST.Expression parseCmpExp() { - const loc = token.loc; - auto e = parseShiftExp(); EXP op = EXP.reserved; + const loc = token.loc; switch (token.value) { @@ -9223,28 +9238,26 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer private AST.Expression parseAndExp() { - Loc loc = token.loc; auto e = parseCmpExp(); while (token.value == TOK.and) { checkParens(TOK.and, e); + const loc = token.loc; nextToken(); auto e2 = parseCmpExp(); checkParens(TOK.and, e2); e = new AST.AndExp(loc, e, e2); - loc = token.loc; } return e; } private AST.Expression parseXorExp() { - const loc = token.loc; - auto e = parseAndExp(); while (token.value == TOK.xor) { checkParens(TOK.xor, e); + const loc = token.loc; nextToken(); auto e2 = parseAndExp(); checkParens(TOK.xor, e2); @@ -9255,12 +9268,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer private AST.Expression parseOrExp() { - const loc = token.loc; - auto e = parseXorExp(); while (token.value == TOK.or) { checkParens(TOK.or, e); + const loc = token.loc; nextToken(); auto e2 = parseXorExp(); checkParens(TOK.or, e2); @@ -9271,11 +9283,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer private AST.Expression parseAndAndExp() { - const loc = token.loc; - auto e = parseOrExp(); while (token.value == TOK.andAnd) { + const loc = token.loc; nextToken(); auto e2 = parseOrExp(); e = new AST.LogicalExp(loc, EXP.andAnd, e, e2); @@ -9285,11 +9296,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer private AST.Expression parseOrOrExp() { - const loc = token.loc; - auto e = parseAndAndExp(); while (token.value == TOK.orOr) { + const loc = token.loc; nextToken(); auto e2 = parseAndAndExp(); e = new AST.LogicalExp(loc, EXP.orOr, e, e2); @@ -9299,11 +9309,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer private AST.Expression parseCondExp() { - const loc = token.loc; - auto e = parseOrOrExp(); if (token.value == TOK.question) { + const loc = token.loc; nextToken(); auto e1 = parseExpression(); check(TOK.colon); @@ -9452,7 +9461,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer * Collect argument list. * Assume current token is ',', '$(LPAREN)' or '['. */ - private void parseNamedArguments(AST.Expressions* arguments, AST.Identifiers* names) + private void parseNamedArguments(AST.Expressions* arguments, AST.ArgumentLabels* names) { assert(arguments); @@ -9470,14 +9479,14 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer check(TOK.identifier); check(TOK.colon); if (names) - names.push(ident); + names.push(ArgumentLabel(ident, loc)); else error(loc, "named arguments not allowed here"); } else { if (names) - names.push(null); + names.push(ArgumentLabel(null, Loc.init)); } auto arg = parseAssignExp(); @@ -9518,7 +9527,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } AST.Expressions* arguments = null; - AST.Identifiers* names = null; + AST.ArgumentLabels* names = null; // An anonymous nested class starts with "class" if (token.value == TOK.class_) @@ -9527,7 +9536,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (token.value == TOK.leftParenthesis) { arguments = new AST.Expressions(); - names = new AST.Identifiers(); + names = new AST.ArgumentLabels(); parseNamedArguments(arguments, names); } @@ -9572,7 +9581,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer else if (token.value == TOK.leftParenthesis && t.ty != Tsarray) { arguments = new AST.Expressions(); - names = new AST.Identifiers(); + names = new AST.ArgumentLabels(); parseNamedArguments(arguments, names); } diff --git a/gcc/d/dmd/semantic2.d b/gcc/d/dmd/semantic2.d index 1c58e63936d7..26f0fa8a254f 100644 --- a/gcc/d/dmd/semantic2.d +++ b/gcc/d/dmd/semantic2.d @@ -287,7 +287,10 @@ private extern(C++) final class Semantic2Visitor : Visitor } if (hasInvalidEnumInitializer(ei.exp)) - .error(vd.loc, "%s `%s` : Unable to initialize enum with class or pointer to struct. Use static const variable instead.", vd.kind, vd.toPrettyChars); + { + .error(vd.loc, "%s `%s` : Unable to initialize enum with class or pointer to struct", vd.kind, vd.toPrettyChars); + .errorSupplemental(vd.loc, "use static const variable instead"); + } } } else if (vd._init && vd.isThreadlocal()) @@ -298,13 +301,20 @@ private extern(C++) final class Semantic2Visitor : Visitor { ExpInitializer ei = vd._init.isExpInitializer(); if (ei && ei.exp.op == EXP.classReference) - .error(vd.loc, "%s `%s` is a thread-local class and cannot have a static initializer. Use `static this()` to initialize instead.", vd.kind, vd.toPrettyChars); + { + .error(vd.loc, "%s `%s` is a thread-local class and cannot have a static initializer", vd.kind, vd.toPrettyChars); + .errorSupplemental(vd.loc, "use `static this()` to initialize instead"); + } } else if (vd.type.ty == Tpointer && vd.type.nextOf().ty == Tstruct && vd.type.nextOf().isMutable() && !vd.type.nextOf().isShared()) { ExpInitializer ei = vd._init.isExpInitializer(); if (ei && ei.exp.op == EXP.address && (cast(AddrExp)ei.exp).e1.op == EXP.structLiteral) - .error(vd.loc, "%s `%s` is a thread-local pointer to struct and cannot have a static initializer. Use `static this()` to initialize instead.", vd.kind, vd.toPrettyChars); + { + .error(vd.loc, "%s `%s` is a thread-local pointer to struct and cannot have a static initializer", vd.kind, vd.toPrettyChars); + .errorSupplemental(vd.loc, "use `static this()` to initialize instead"); + } + } } vd.semanticRun = PASS.semantic2done; diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d index a24af7bbbfcf..bafb2e7d8719 100644 --- a/gcc/d/dmd/semantic3.d +++ b/gcc/d/dmd/semantic3.d @@ -855,7 +855,7 @@ private extern(C++) final class Semantic3Visitor : Visitor if (tret.ty == Terror) { // https://issues.dlang.org/show_bug.cgi?id=13702 - exp = checkGC(sc2, exp); + exp = exp.checkGC(sc2); continue; } @@ -977,7 +977,7 @@ private extern(C++) final class Semantic3Visitor : Visitor checkReturnEscape(*sc2, exp, false); } - exp = checkGC(sc2, exp); + exp = exp.checkGC(sc2); if (funcdecl.vresult) { diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d index 0c9b6becb700..523ed7b39781 100644 --- a/gcc/d/dmd/statementsem.d +++ b/gcc/d/dmd/statementsem.d @@ -219,7 +219,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) s.exp = ErrorExp.get(); s.exp = s.exp.optimize(WANTvalue); - s.exp = checkGC(sc, s.exp); + s.exp = s.exp.checkGC(sc); if (s.exp.op == EXP.error) return setError(); result = s; @@ -585,7 +585,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (checkNonAssignmentArrayOp(ds.condition)) ds.condition = ErrorExp.get(); ds.condition = ds.condition.optimize(WANTvalue); - ds.condition = checkGC(sc, ds.condition); + ds.condition = ds.condition.checkGC(sc); ds.condition = ds.condition.toBoolean(sc); @@ -658,7 +658,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (checkNonAssignmentArrayOp(fs.condition)) fs.condition = ErrorExp.get(); fs.condition = fs.condition.optimize(WANTvalue); - fs.condition = checkGC(sc, fs.condition); + fs.condition = fs.condition.checkGC(sc); fs.condition = fs.condition.toBoolean(sc); } @@ -677,7 +677,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (checkNonAssignmentArrayOp(fs.increment)) fs.increment = ErrorExp.get(); fs.increment = fs.increment.optimize(WANTvalue); - fs.increment = checkGC(sc, fs.increment); + fs.increment = fs.increment.checkGC(sc); } sc.sbreak = fs; @@ -1709,7 +1709,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) // checkGC after optimizing the condition so that // compile time constants are reduced. - ifs.condition = checkGC(scd, ifs.condition); + ifs.condition = ifs.condition.checkGC(scd); // Save 'root' of two branches (then and else) at the point where it forks CtorFlow ctorflow_root = scd.ctorflow.clone(); @@ -1897,7 +1897,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (checkNonAssignmentArrayOp(ss.condition)) ss.condition = ErrorExp.get(); ss.condition = ss.condition.optimize(WANTvalue); - ss.condition = checkGC(sc, ss.condition); + ss.condition = ss.condition.checkGC(sc); if (ss.condition.op == EXP.error) conditionError = true; @@ -1959,6 +1959,16 @@ Statement statementSemanticVisit(Statement s, Scope* sc) ed = ds.isEnumDeclaration(); // typedef'ed enum if (!ed && te && ((ds = te.toDsymbol(sc)) !is null)) ed = ds.isEnumDeclaration(); + + // Circular references + // Check if enum semantic analysis is not yet complete + if (ed && ed.semanticRun < PASS.semantic2done) + { + error(ss.loc, "cannot use `final switch` on enum `%s` while it is being defined", ed.toChars()); + sc.pop(); + return setError(); + } + if (ed && ss.cases.length < ed.members.length) { int missingMembers = 0; @@ -2593,7 +2603,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (tbret && tbret.ty == Tvoid || convToVoid) { - if (!convToVoid) + if (!convToVoid && !texp.isTypeError()) { error(rs.loc, "cannot return non-void from `void` function"); errors = true; @@ -2626,7 +2636,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (e0) { e0 = e0.optimize(WANTvalue); - e0 = checkGC(sc, e0); + e0 = e0.checkGC(sc); } } @@ -3044,7 +3054,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) ss.exp = ss.exp.expressionSemantic(sc); ss.exp = resolveProperties(sc, ss.exp); ss.exp = ss.exp.optimize(WANTvalue); - ss.exp = checkGC(sc, ss.exp); + ss.exp = ss.exp.checkGC(sc); if (ss.exp.op == EXP.error) { if (ss._body) @@ -3168,7 +3178,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) ws.exp = ws.exp.expressionSemantic(sc); ws.exp = resolveProperties(sc, ws.exp); ws.exp = ws.exp.optimize(WANTvalue); - ws.exp = checkGC(sc, ws.exp); + ws.exp = ws.exp.checkGC(sc); if (ws.exp.op == EXP.error) return setError(); if (ws.exp.op == EXP.scope_) @@ -3730,7 +3740,7 @@ public bool throwSemantic(Loc loc, ref Expression exp, Scope* sc) exp = exp.expressionSemantic(sc); exp = resolveProperties(sc, exp); - exp = checkGC(sc, exp); + exp = exp.checkGC(sc); if (exp.isErrorExp()) return false; if (!exp.type.isNaked()) diff --git a/gcc/d/dmd/template.h b/gcc/d/dmd/template.h index 5576965ce4b2..bfc415148043 100644 --- a/gcc/d/dmd/template.h +++ b/gcc/d/dmd/template.h @@ -71,6 +71,7 @@ public: d_bool isTrivialAliasSeq; // matches `template AliasSeq(T...) { alias AliasSeq = T; } d_bool isTrivialAlias; // matches pattern `template Alias(T) { alias Alias = qualifiers(T); }` d_bool deprecated_; // this template declaration is deprecated + d_bool isCmacro; // Whether this template is a translation of a C macro Visibility visibility; TemplatePrevious *previous; // threaded list of previous instantiation attempts on stack @@ -284,7 +285,6 @@ public: TemplateMixin *syntaxCopy(Dsymbol *s) override; const char *kind() const override; - bool hasPointers() override; void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/templatesem.d b/gcc/d/dmd/templatesem.d index e5efce4a8bcc..a9cf867f1147 100644 --- a/gcc/d/dmd/templatesem.d +++ b/gcc/d/dmd/templatesem.d @@ -188,7 +188,7 @@ void templateDeclarationSemantic(Scope* sc, TemplateDeclaration tempdecl) if (tempdecl.members) { Dsymbol s; - if (Dsymbol.oneMembers(tempdecl.members, s, tempdecl.ident) && s) + if (oneMembers(tempdecl.members, s, tempdecl.ident) && s) { tempdecl.onemember = s; s.parent = tempdecl; @@ -948,7 +948,7 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat size_t nfargs2 = argumentList.length; // total number of arguments including applied defaultArgs uint inoutMatch = 0; // for debugging only Expression[] fargs = argumentList.arguments ? (*argumentList.arguments)[] : null; - Identifier[] fnames = argumentList.names ? (*argumentList.names)[] : null; + ArgumentLabel[] fnames = argumentList.names ? (*argumentList.names)[] : null; for (size_t parami = 0; parami < nfparams; parami++) { @@ -958,16 +958,17 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat Type prmtype = fparam.type.addStorageClass(fparam.storageClass); Expression farg; - Identifier fname = argi < fnames.length ? fnames[argi] : null; + Identifier fname = argi < fnames.length ? fnames[argi].name : null; bool foundName = false; if (fparam.ident) { foreach (i; 0 .. fnames.length) { - if (fparam.ident == fnames[i]) + if (fparam.ident == fnames[i].name) { argi = i; foundName = true; + break; //Exits the loop after a match } } } @@ -1002,9 +1003,9 @@ extern (D) MATCHpair deduceFunctionTemplateMatch(TemplateDeclaration td, Templat { break; } - foreach(name; fnames) + foreach(argLabel; fnames) { - if (p.ident == name) + if (p.ident == argLabel.name) break; } if (!reliesOnTemplateParameters(p.type, (*td.parameters)[inferStart .. td.parameters.length])) diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d index 127a89d19842..8cce1732e87e 100644 --- a/gcc/d/dmd/traits.d +++ b/gcc/d/dmd/traits.d @@ -1847,7 +1847,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc) const tf = sc2.func.type.isTypeFunction(); err |= tf.isNothrow && canThrow(ex, sc2.func, null); } - ex = checkGC(sc2, ex); + ex = ex.checkGC(sc2); if (ex.op == EXP.error) err = true; } diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index d4c7a5865d25..ffbdfed6eb37 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -169,17 +169,28 @@ private void resolveHelper(TypeQualified mt, Loc loc, Scope* sc, Dsymbol s, Dsym */ const p = mt.mutableOf().unSharedOf().toChars(); auto id = Identifier.idPool(p[0 .. strlen(p)]); - if (const n = importHint(id.toString())) - error(loc, "`%s` is not defined, perhaps `import %.*s;` ?", p, cast(int)n.length, n.ptr); - else if (auto s2 = sc.search_correct(id)) - error(loc, "undefined identifier `%s`, did you mean %s `%s`?", p, s2.kind(), s2.toChars()); - else if (const q = Scope.search_correct_C(id)) - error(loc, "undefined identifier `%s`, did you mean `%s`?", p, q); - else if ((id == Id.This && sc.getStructClassScope()) || - (id == Id._super && sc.getClassScope())) - error(loc, "undefined identifier `%s`, did you mean `typeof(%s)`?", p, p); - else - error(loc, "undefined identifier `%s`", p); + if (!(sc && sc.inCfile)) + { + if (const n = importHint(id.toString())) + error(loc, "`%s` is not defined, perhaps `import %.*s;` ?", p, cast(int)n.length, n.ptr); + else if (auto s2 = sc.search_correct(id)) + error(loc, "undefined identifier `%s`, did you mean %s `%s`?", p, s2.kind(), s2.toChars()); + else if (const q = Scope.search_correct_C(id)) + error(loc, "undefined identifier `%s`, did you mean `%s`?", p, q); + else if ((id == Id.This && sc.getStructClassScope()) || + (id == Id._super && sc.getClassScope())) + error(loc, "undefined identifier `%s`, did you mean `typeof(%s)`?", p, p); + else + error(mt.loc, "undefined identifier `%s`", p); + } + else { + if (const n = cIncludeHint(id.toString())) + error(loc, "`%s` is not defined, perhaps `#include %.*s` ?", p, cast(int)n.length, n.ptr); + else if (auto s2 = sc.search_correct(id)) + error(loc, "undefined identifier `%s`, did you mean %s `%s`?", p, s2.kind(), s2.toChars()); + else + error(loc, "undefined identifier `%s`", p); + } pt = Type.terror; return; @@ -1934,7 +1945,19 @@ Type typeSemantic(Type type, Loc loc, Scope* sc) Expression e; Type t; Dsymbol s; - mtype.index.resolve(loc, sc, e, t, s); + Loc indexLoc; + + switch (mtype.index.ty) + { + case Tident: indexLoc = mtype.index.isTypeIdentifier().loc; break; + case Tinstance: indexLoc = mtype.index.isTypeInstance().loc; break; + case Ttypeof: indexLoc = mtype.index.isTypeTypeof().loc; break; + case Treturn: indexLoc = mtype.index.isTypeReturn().loc; break; + case Tmixin: indexLoc = mtype.index.isTypeMixin().loc; break; + default: indexLoc = mtype.loc; + } + + mtype.index.resolve(indexLoc, sc, e, t, s); // https://issues.dlang.org/show_bug.cgi?id=15478 if (s) @@ -2737,7 +2760,11 @@ Type typeSemantic(Type type, Loc loc, Scope* sc) Expression e; Dsymbol s; //printf("TypeIdentifier::semantic(%s)\n", mtype.toChars()); - mtype.resolve(loc, sc, e, t, s); + if (mtype.loc != Loc.initial) + mtype.resolve(mtype.loc, sc, e, t, s); + else + mtype.resolve(loc, sc, e, t, s); + if (t) { //printf("\tit's a type %d, %s, %s\n", t.ty, t.toChars(), t.deco); @@ -3428,8 +3455,10 @@ Expression getProperty(Type t, Scope* scope_, Loc loc, Identifier ident, int fla } Dsymbol s = null; - if (mt.ty == Tstruct || mt.ty == Tclass || mt.ty == Tenum) - s = mt.toDsymbol(null); + auto derefType = mt.isTypePointer() ? mt.nextOf() : mt; + + if (derefType.isTypeStruct() || derefType.isTypeClass() || derefType.isTypeEnum()) + s = derefType.toDsymbol(null); if (s) s = s.search_correct(ident); if (s && !symbolIsVisible(scope_, s)) @@ -3439,18 +3468,21 @@ Expression getProperty(Type t, Scope* scope_, Loc loc, Identifier ident, int fla return ErrorExp.get(); if (s) - error(loc, "no property `%s` for type `%s`, did you mean `%s`?", ident.toChars(), mt.toChars(), s.toPrettyChars()); + { + error(loc, "no property `%s` for type `%s`", ident.toErrMsg(), mt.toErrMsg()); + errorSupplemental(s.loc, "did you mean `%s`?", ident == s.ident ? s.toPrettyChars() : s.toErrMsg()); + } else if (ident == Id.opCall && mt.ty == Tclass) - error(loc, "no property `%s` for type `%s`, did you mean `new %s`?", ident.toChars(), mt.toChars(), mt.toPrettyChars()); + error(loc, "no property `%s` for type `%s`, did you mean `new %s`?", ident.toErrMsg(), mt.toErrMsg(), mt.toPrettyChars()); else if (const n = importHint(ident.toString())) - error(loc, "no property `%s` for type `%s`, perhaps `import %.*s;` is needed?", ident.toChars(), mt.toChars(), cast(int)n.length, n.ptr); + error(loc, "no property `%s` for type `%s`, perhaps `import %.*s;` is needed?", ident.toErrMsg(), mt.toErrMsg(), cast(int)n.length, n.ptr); else { if (src) { error(loc, "no property `%s` for `%s` of type `%s`", - ident.toChars(), src.toChars(), mt.toPrettyChars(true)); + ident.toErrMsg(), src.toErrMsg(), mt.toPrettyChars(true)); auto s2 = scope_.search_correct(ident); // UFCS if (s2 && s2.isFuncDeclaration) @@ -3458,30 +3490,17 @@ Expression getProperty(Type t, Scope* scope_, Loc loc, Identifier ident, int fla if (s2.ident == ident) { errorSupplemental(s2.loc, "cannot call %s `%s` with UFCS because it is not declared at module scope", - s2.kind(), s2.toChars()); + s2.kind(), s2.toErrMsg()); } else errorSupplemental(s2.loc, "did you mean %s `%s`?", - s2.kind(), s2.toChars()); - } - else if (src.type.ty == Tpointer) - { - // structPtr.field - auto tn = (cast(TypeNext) src.type).nextOf(); - if (auto as = tn.isAggregate()) - { - if (auto s3 = as.search_correct(ident)) - { - errorSupplemental(s3.loc, "did you mean %s `%s`?", - s3.kind(), s3.toChars()); - } - } + s2.kind(), s2.toErrMsg()); } } else - error(loc, "no property `%s` for type `%s`", ident.toChars(), mt.toPrettyChars(true)); + error(loc, "no property `%s` for type `%s`", ident.toErrMsg(), mt.toPrettyChars(true)); - if (auto dsym = mt.toDsymbol(scope_)) + if (auto dsym = derefType.toDsymbol(scope_)) { if (auto sym = dsym.isAggregateDeclaration()) { @@ -3507,7 +3526,7 @@ Expression getProperty(Type t, Scope* scope_, Loc loc, Identifier ident, int fla } } errorSupplemental(dsym.loc, "%s `%s` defined here", - dsym.kind, dsym.toChars()); + dsym.kind, dsym.toErrMsg()); } } @@ -6704,6 +6723,7 @@ STC parameterStorageClass(TypeFunction tf, Type tthis, Parameter p, VarDeclarati // Check escaping through `this` if (tthis && tthis.isMutable()) { + import dmd.dsymbolsem : hasPointers; foreach (VarDeclaration v; isAggregate(tthis).fields) { if (v.hasPointers()) @@ -6714,6 +6734,7 @@ STC parameterStorageClass(TypeFunction tf, Type tthis, Parameter p, VarDeclarati // Check escaping through nested context if (outerVars && tf.isMutable()) { + import dmd.dsymbolsem : hasPointers; foreach (VarDeclaration v; *outerVars) { if (v.hasPointers()) diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc index 026b12fb93e1..160d37846f29 100644 --- a/gcc/d/typeinfo.cc +++ b/gcc/d/typeinfo.cc @@ -908,7 +908,7 @@ public: } } - if (cd->isAbstract ()) + if (dmd::isAbstract (cd)) flags |= ClassFlags::isAbstract; for (ClassDeclaration *bcd = cd; bcd; bcd = bcd->baseClass) @@ -919,7 +919,7 @@ public: for (size_t i = 0; i < bcd->members->length; i++) { Dsymbol *sm = (*bcd->members)[i]; - if (sm->hasPointers ()) + if (dmd::hasPointers (sm)) goto Lhaspointers; } } diff --git a/gcc/testsuite/gdc.dg/asm1.d b/gcc/testsuite/gdc.dg/asm1.d index 1593eb6acd34..e2f36b01c94a 100644 --- a/gcc/testsuite/gdc.dg/asm1.d +++ b/gcc/testsuite/gdc.dg/asm1.d @@ -11,7 +11,7 @@ void parse1() void parse2() { - asm + asm { "" : : "g" (1 ? 2 : 3); "" : : "g" (1 ? 2 : :) 3; @@ -22,11 +22,7 @@ void parse2() void parse3() { - asm { "" [; } - // { dg-error "expression expected, not ';'" "" { target *-*-* } .-1 } - // { dg-error "found 'End of File' when expecting ','" "" { target *-*-* } .-2 } - // { dg-error "found 'End of File' when expecting ']'" "" { target *-*-* } .-3 } - // { dg-error "found 'End of File' when expecting ';'" "" { target *-*-* } .-4 } + asm { "" [; } // { dg-error "found '\\\[' when expecting ':'" } } void parse4() @@ -68,9 +64,9 @@ void semantic2() void semantic3() { - asm + asm { - unknown; // { dg-error "undefined identifier 'unknown'" } + unknown; // { dg-error "expected string literal or expression in parentheses" } } } diff --git a/gcc/testsuite/gdc.test/compilable/imports/cstuff3.c b/gcc/testsuite/gdc.test/compilable/imports/cstuff3.c index f6aaf3b2a4ae..fb78ec76bca7 100644 --- a/gcc/testsuite/gdc.test/compilable/imports/cstuff3.c +++ b/gcc/testsuite/gdc.test/compilable/imports/cstuff3.c @@ -4,3 +4,16 @@ int squared(int a) { return a * a; } + +/* test case for issue #21094 */ +typedef enum upng_error { + UPNG_EOK = 0, /* success (no error) */ + UPNG_ENOMEM = 1, /* memory allocation failed */ + UPNG_ENOTFOUND = 2, /* resource not found (file missing) */ + UPNG_ENOTPNG = 3, /* image data does not have a PNG header */ + UPNG_EMALFORMED = 4, /* image data is not a valid PNG image */ + UPNG_EUNSUPPORTED = 5, /* critical PNG chunk type is not supported */ + UPNG_EUNINTERLACED = 6, /* image interlacing is not supported */ + UPNG_EUNFORMAT = 7, /* image color format is not supported */ + UPNG_EPARAM = 8 /* invalid parameter to method call */ +} upng_error; diff --git a/gcc/testsuite/gdc.test/compilable/imports/imp18127a.c b/gcc/testsuite/gdc.test/compilable/imports/imp18127a.c new file mode 100644 index 000000000000..cd173151dbff --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/imp18127a.c @@ -0,0 +1,74 @@ +// https://github.com/dlang/dmd/issues/18127 +union struct_or_union { + int x; +}; + +struct S_n_fields { + int x, y; +}; + +struct S_types { + float x; +}; + +struct S_names { + float x; +}; + +struct B { + int x; +}; + +struct S_b { + struct B b; +}; + +struct S_contains_anon_named { + struct { + int x; + } a; +}; + +struct S_contains_anon_unnamed { + struct { + int x; + }; +}; + +struct S_bitfields_mismatch1 { + unsigned x: 3; + unsigned y: 1; +}; +struct S_bitfields_mismatch2 { + unsigned x; + unsigned y: 1; +}; + +struct S_bitfields_widths { + unsigned x: 3; + unsigned y: 1; +}; + +struct S_bitfields_anon { + unsigned x: 3; + unsigned : 1; +}; + +struct S_alignas { + _Alignas(8) float x; +}; +struct S_aligned { + float x; +}__attribute__((aligned(8))); + +struct __attribute__((packed)) S_pack_1 { + float x; + char c; +}; +#pragma pack(push) +#pragma pack(1) +struct S_pack_2 { + float x; + char c; +}; +#pragma pack(pop) diff --git a/gcc/testsuite/gdc.test/compilable/imports/imp18127b.c b/gcc/testsuite/gdc.test/compilable/imports/imp18127b.c new file mode 100644 index 000000000000..cd173151dbff --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/imp18127b.c @@ -0,0 +1,74 @@ +// https://github.com/dlang/dmd/issues/18127 +union struct_or_union { + int x; +}; + +struct S_n_fields { + int x, y; +}; + +struct S_types { + float x; +}; + +struct S_names { + float x; +}; + +struct B { + int x; +}; + +struct S_b { + struct B b; +}; + +struct S_contains_anon_named { + struct { + int x; + } a; +}; + +struct S_contains_anon_unnamed { + struct { + int x; + }; +}; + +struct S_bitfields_mismatch1 { + unsigned x: 3; + unsigned y: 1; +}; +struct S_bitfields_mismatch2 { + unsigned x; + unsigned y: 1; +}; + +struct S_bitfields_widths { + unsigned x: 3; + unsigned y: 1; +}; + +struct S_bitfields_anon { + unsigned x: 3; + unsigned : 1; +}; + +struct S_alignas { + _Alignas(8) float x; +}; +struct S_aligned { + float x; +}__attribute__((aligned(8))); + +struct __attribute__((packed)) S_pack_1 { + float x; + char c; +}; +#pragma pack(push) +#pragma pack(1) +struct S_pack_2 { + float x; + char c; +}; +#pragma pack(pop) diff --git a/gcc/testsuite/gdc.test/compilable/imports/imp20344.c b/gcc/testsuite/gdc.test/compilable/imports/imp20344.c new file mode 100644 index 000000000000..56ac79c930c3 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/imp20344.c @@ -0,0 +1,2 @@ +// https://github.com/dlang/dmd/issues/20334 +#define X "X" diff --git a/gcc/testsuite/gdc.test/compilable/imports/imp20499.c b/gcc/testsuite/gdc.test/compilable/imports/imp20499.c new file mode 100644 index 000000000000..7ae74906f73c --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/imports/imp20499.c @@ -0,0 +1,8 @@ +// https://github.com/dlang/dmd/issues/20499 +typedef struct Foo { + int x; +} *pFoo; + +struct Bar { + struct Foo foo; +}; diff --git a/gcc/testsuite/gdc.test/compilable/test18127.d b/gcc/testsuite/gdc.test/compilable/test18127.d new file mode 100644 index 000000000000..3d6b454a2be1 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test18127.d @@ -0,0 +1,5 @@ +// https://github.com/dlang/dmd/issues/18127 +// EXTRA_FILES: imports/imp18127a.c imports/imp18127b.c + +import imports.imp18127a; +import imports.imp18127b; diff --git a/gcc/testsuite/gdc.test/compilable/test20344.d b/gcc/testsuite/gdc.test/compilable/test20344.d new file mode 100644 index 000000000000..26ee9a3269e5 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test20344.d @@ -0,0 +1,14 @@ +// https://github.com/dlang/dmd/issues/20334 +// EXTRA_FILES: imports/imp20344.c +import imports.imp20344; +string s = X; +const(char)* p = X; + +void takes_string(string){ } +void takes_char_star(const(char)*){ } + + +void test20344(){ + takes_string(X); + takes_char_star(X); +} diff --git a/gcc/testsuite/gdc.test/compilable/test20499.d b/gcc/testsuite/gdc.test/compilable/test20499.d new file mode 100644 index 000000000000..3263aed66b62 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/test20499.d @@ -0,0 +1,3 @@ +// https://github.com/dlang/dmd/issues/20499 +// EXTRA_FILES: imports/imp20499.c +import imports.imp20499; diff --git a/gcc/testsuite/gdc.test/compilable/test3004.d b/gcc/testsuite/gdc.test/compilable/test3004.d index 23ec46f29055..664452ef4e68 100644 --- a/gcc/testsuite/gdc.test/compilable/test3004.d +++ b/gcc/testsuite/gdc.test/compilable/test3004.d @@ -1,7 +1,7 @@ // https://issues.dlang.org/show_bug.cgi?id=3004 /* REQUIRED_ARGS: -ignore -v -TRANSFORM_OUTPUT: remove_lines("^(predefs|binary|version|config|DFLAG|parse|import|semantic|entry|library|function object|function core|\s*$)") +TRANSFORM_OUTPUT: remove_lines("^(predefs|binary|version|config|DFLAG|parse|import|\(imported|semantic|entry|library|function object|function core|\s*$)") TEST_OUTPUT: --- pragma GNU_attribute (__error) diff --git a/gcc/testsuite/gdc.test/compilable/testcstuff3.d b/gcc/testsuite/gdc.test/compilable/testcstuff3.d index 89228a9bc4ab..08aa3b03d11d 100644 --- a/gcc/testsuite/gdc.test/compilable/testcstuff3.d +++ b/gcc/testsuite/gdc.test/compilable/testcstuff3.d @@ -2,3 +2,22 @@ import imports.cstuff3; static assert(squared(4) == 16); + +/* test case for issue #21094 */ +string enum_to_str(E)(E v) if (is(E == enum)) +{ + final switch (v) with(E) + { + static foreach (m; __traits(allMembers, E)) + { + case mixin(m): + return m; + } + } +} + +void testEnumSwitch() +{ + auto str = enum_to_str(UPNG_EOK); + assert(str == "UPNG_EOK"); +} diff --git a/gcc/testsuite/gdc.test/compilable/uda_lambda.d b/gcc/testsuite/gdc.test/compilable/uda_lambda.d new file mode 100644 index 000000000000..df331747a7f1 --- /dev/null +++ b/gcc/testsuite/gdc.test/compilable/uda_lambda.d @@ -0,0 +1,3 @@ +enum UDA; +int fun() @UDA => 7; +static assert(fun() == 7); diff --git a/gcc/testsuite/gdc.test/compilable/vcg-ast.d b/gcc/testsuite/gdc.test/compilable/vcg-ast.d index 9197441affea..bcb7256723c6 100644 --- a/gcc/testsuite/gdc.test/compilable/vcg-ast.d +++ b/gcc/testsuite/gdc.test/compilable/vcg-ast.d @@ -75,3 +75,14 @@ template imported() } alias myImport = imported!(); + +// https://github.com/dlang/dmd/issues/21105 + +enum compiles = __traits(compiles,{ + int[] arr; + arr ~= 1; +}); +enum isexp = is(typeof({ + int[] arr; + arr ~= 1; +})); diff --git a/gcc/testsuite/gdc.test/fail_compilation/b23686.d b/gcc/testsuite/gdc.test/fail_compilation/b23686.d index 4c2a5bd026d2..5838f5c8e10c 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/b23686.d +++ b/gcc/testsuite/gdc.test/fail_compilation/b23686.d @@ -4,7 +4,7 @@ TEST_OUTPUT: fail_compilation/b23686.d(107): Error: undefined identifier `eFN1`, did you mean template `eFN0()()`? fail_compilation/b23686.d(107): Error: `mixin(_error_)` does not give a valid type fail_compilation/b23686.d(115): while looking for match for `eload!(int, 1)` -fail_compilation/b23686.d(121): Error: undefined identifier `FNwtf` +fail_compilation/b23686.d-mixin-121(121): Error: undefined identifier `FNwtf` fail_compilation/b23686.d(121): Error: `mixin(_error_)` does not give a valid type fail_compilation/b23686.d(126): while looking for match for `load!"wtf"` --- diff --git a/gcc/testsuite/gdc.test/fail_compilation/checkimports2.d b/gcc/testsuite/gdc.test/fail_compilation/checkimports2.d index 44c237f144f8..56e28e1ce7bb 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/checkimports2.d +++ b/gcc/testsuite/gdc.test/fail_compilation/checkimports2.d @@ -2,10 +2,12 @@ /* TEST_OUTPUT: --- -fail_compilation/checkimports2.d(25): Error: no property `X` for type `checkimports2.B`, did you mean `imports.imp2.X`? -fail_compilation/checkimports2.d(25): while evaluating: `static assert((B).X == 0)` -fail_compilation/checkimports2.d(26): Error: no property `Y` for type `checkimports2.B`, did you mean `imports.imp2.Y`? -fail_compilation/checkimports2.d(26): while evaluating: `static assert((B).Y == 2)` +fail_compilation/checkimports2.d(27): Error: no property `X` for type `checkimports2.B` +fail_compilation/imports/imp2.d(3): did you mean `imports.imp2.X`? +fail_compilation/checkimports2.d(27): while evaluating: `static assert((B).X == 0)` +fail_compilation/checkimports2.d(28): Error: no property `Y` for type `checkimports2.B` +fail_compilation/imports/imp2.d(4): did you mean `imports.imp2.Y`? +fail_compilation/checkimports2.d(28): while evaluating: `static assert((B).Y == 2)` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10405.d b/gcc/testsuite/gdc.test/fail_compilation/diag10405.d deleted file mode 100644 index 28da8af93ad1..000000000000 --- a/gcc/testsuite/gdc.test/fail_compilation/diag10405.d +++ /dev/null @@ -1,11 +0,0 @@ -/* -TEST_OUTPUT: ---- -fail_compilation/diag10405.d(10): Error: cannot return non-void from `void` function ---- -*/ - -void main() -{ - return 10; -} diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag20888.d b/gcc/testsuite/gdc.test/fail_compilation/diag20888.d index 84af42533fcc..d030a98ec2c2 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag20888.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag20888.d @@ -13,12 +13,12 @@ fail_compilation/diag20888.d(49): Error: return value `callback` of type `int de fail_compilation/diag20888.d(54): Error: return value `() => 3755` of type `int function() pure nothrow @nogc @safe` does not match return type `int`, and cannot be implicitly converted fail_compilation/diag20888.d(54): Did you intend to call the function pointer? fail_compilation/diag20888.d(59): Error: `return` expression expected -fail_compilation/diag20888.d(64): Error: cannot return non-void from `void` function fail_compilation/diag20888.d(70): Error: return value `() => i` of type `int delegate() pure nothrow @nogc @safe` does not match return type `int`, and cannot be implicitly converted fail_compilation/diag20888.d(70): Did you intend to call the delegate? --- */ + int alpha(int function() callback) { return callback; @@ -59,10 +59,10 @@ int theta() return; } -void iota() -{ - return 0xEAB; -} + + + + int kappa() { diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag23384.d b/gcc/testsuite/gdc.test/fail_compilation/diag23384.d index 1fa4da5ffb9e..9cb17c00d74f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag23384.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag23384.d @@ -4,8 +4,8 @@ TEST_OUTPUT: --- fail_compilation/diag23384.d(28): Error: function `diag23384.Derived.fun(B b)` is not callable using argument types `(A)` -fail_compilation/diag23384.d(28): function `diag23384.Derived.fun` hides base class function `diag23384.Base.fun` -fail_compilation/diag23384.d(28): add `alias fun = diag23384.Base.fun` to `diag23384.Derived`'s body to merge the overload sets +fail_compilation/diag23384.d(28): Note: function `diag23384.Derived.fun` hides base class function `diag23384.Base.fun` +fail_compilation/diag23384.d(28): Add `alias fun = diag23384.Base.fun;` to `diag23384.Derived`'s body to merge the overload sets --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag9679.d b/gcc/testsuite/gdc.test/fail_compilation/diag9679.d index 22e94e575969..50b8717adf31 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag9679.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag9679.d @@ -3,13 +3,14 @@ TEST_OUTPUT: --- fail_compilation/diag9679.d(93): Deprecation: `auto` and `ref` storage classes should be adjacent fail_compilation/diag9679.d(93): Deprecation: `auto` and `ref` storage classes should be adjacent -fail_compilation/diag9679.d(15): Error: rvalue `1` cannot be assigned to `ref n` -fail_compilation/diag9679.d(16): Error: variable `diag9679.main.n` - storage class `auto` has no effect if type is not inferred, did you mean `scope`? -fail_compilation/diag9679.d(17): Error: variable `diag9679.main.S.a` - field declarations cannot be `ref` -fail_compilation/diag9679.d(24): Error: returning `r` escapes a reference to local variable `i` +fail_compilation/diag9679.d(94): Deprecation: `auto ref` return type must have `auto` and `ref` adjacent +fail_compilation/diag9679.d(100): Deprecation: `auto ref` return type must have `auto` and `ref` adjacent +fail_compilation/diag9679.d(16): Error: rvalue `1` cannot be assigned to `ref n` +fail_compilation/diag9679.d(17): Error: variable `diag9679.main.n` - storage class `auto` has no effect if type is not inferred, did you mean `scope`? +fail_compilation/diag9679.d(18): Error: variable `diag9679.main.S.a` - field declarations cannot be `ref` +fail_compilation/diag9679.d(25): Error: returning `r` escapes a reference to local variable `i` --- */ - void main() { if (ref n = 1) {} @@ -60,7 +61,6 @@ fail_compilation/diag9679.d(96): Error: variable `x` - `auto ref` variable must --- */ - void test5() { ref int r5; @@ -90,8 +90,11 @@ void test9() auto ref int y = void; } -void testKeywordOrder()(ref auto int x, auto const ref float y) {} -void testKeywordOrder() +void testKeywordOrder()(ref auto int x, auto const ref float y) {}; +ref auto int testKeywordOrder() { ref auto int x = 3; + return 3; } + +auto { ref int autoFromScope() => 3; } diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag_ptr_conversion.d b/gcc/testsuite/gdc.test/fail_compilation/diag_ptr_conversion.d new file mode 100644 index 000000000000..ea144b2c9db2 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/diag_ptr_conversion.d @@ -0,0 +1,17 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/diag_ptr_conversion.d(15): Error: cannot implicitly convert `const(int)*` to `int*` +fail_compilation/diag_ptr_conversion.d(15): Note: Converting const to mutable requires an explicit cast (`cast(int*)`). +fail_compilation/diag_ptr_conversion.d(16): Error: cannot implicitly convert `int*` to `float*` +fail_compilation/diag_ptr_conversion.d(16): Note: Pointer types point to different base types (`int` vs `float`) +--- +*/ + +void testPointerConversions() +{ + int* p; + const(int)* cp = p; + p = cp; + float* f = p; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/enum_auto_increment.d b/gcc/testsuite/gdc.test/fail_compilation/enum_auto_increment.d new file mode 100644 index 000000000000..9c04e9a324f6 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/enum_auto_increment.d @@ -0,0 +1,18 @@ +/* +TEST_OUTPUT: +--- +fail_compilation\enum_auto_increment.d(17): Error: cannot automatically assign value to enum member `enum_auto_increment.A2.d` because base type `A1` is an enum; provide an explicit value +--- +*/ + +enum A1 : int +{ + a, + b, +} + +enum A2 : A1 +{ + c, + d, +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail109.d b/gcc/testsuite/gdc.test/fail_compilation/fail109.d index 003e65f9b807..94f951f9f953 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail109.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail109.d @@ -34,9 +34,7 @@ enum E1 : short /* https://issues.dlang.org/show_bug.cgi?id=14950 TEST_OUTPUT: --- -fail_compilation/fail109.d(50): Error: cannot check `fail109.B.end` value for overflow -fail_compilation/fail109.d(50): Error: comparison between different enumeration types `B` and `C`; If this behavior is intended consider using `std.conv.asOriginalType` -fail_compilation/fail109.d(50): Error: enum member `fail109.B.end` initialization with `B.start+1` causes overflow for type `C` +fail_compilation\fail109.d(48): Error: cannot automatically assign value to enum member `fail109.B.end` because base type `C` is an enum; provide an explicit value --- */ enum C @@ -53,10 +51,10 @@ enum B /* https://issues.dlang.org/show_bug.cgi?id=11849 TEST_OUTPUT: --- -fail_compilation/fail109.d(72): Error: enum member `fail109.RegValueType1a.Unknown` is forward referenced looking for `.max` -fail_compilation/fail109.d(79): Error: enum member `fail109.RegValueType1b.Unknown` is forward referenced looking for `.max` -fail_compilation/fail109.d(84): Error: enum member `fail109.RegValueType2a.Unknown` is forward referenced looking for `.min` -fail_compilation/fail109.d(91): Error: enum member `fail109.RegValueType2b.Unknown` is forward referenced looking for `.min` +fail_compilation/fail109.d(70): Error: enum member `fail109.RegValueType1a.Unknown` is forward referenced looking for `.max` +fail_compilation/fail109.d(77): Error: enum member `fail109.RegValueType1b.Unknown` is forward referenced looking for `.max` +fail_compilation/fail109.d(82): Error: enum member `fail109.RegValueType2a.Unknown` is forward referenced looking for `.min` +fail_compilation/fail109.d(89): Error: enum member `fail109.RegValueType2b.Unknown` is forward referenced looking for `.min` --- */ @@ -94,7 +92,7 @@ enum RegValueType2b : DWORD /* TEST_OUTPUT: --- -fail_compilation/fail109.d(107): Error: enum member `fail109.d` initialization with `__anonymous.c+1` causes overflow for type `Q` +fail_compilation/fail109.d(105): Error: enum member `fail109.d` initialization with `__anonymous.c+1` causes overflow for type `Q` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail11714.d b/gcc/testsuite/gdc.test/fail_compilation/fail11714.d index abc47087ffaa..f36f3e5831e9 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail11714.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail11714.d @@ -1,8 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/fail11714.d(14): Error: variable `fail11714.c` is a thread-local class and cannot have a static initializer. Use `static this()` to initialize instead. -fail_compilation/fail11714.d(21): Error: variable `fail11714.s` is a thread-local pointer to struct and cannot have a static initializer. Use `static this()` to initialize instead. +fail_compilation/fail11714.d(16): Error: variable `fail11714.c` is a thread-local class and cannot have a static initializer +fail_compilation/fail11714.d(16): use `static this()` to initialize instead +fail_compilation/fail11714.d(23): Error: variable `fail11714.s` is a thread-local pointer to struct and cannot have a static initializer +fail_compilation/fail11714.d(23): use `static this()` to initialize instead --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail15361.d b/gcc/testsuite/gdc.test/fail_compilation/fail15361.d index 8e5f9800a816..aec716556a4f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail15361.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail15361.d @@ -1,7 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/fail15361.d(8): Error: unexpected `(` after `errorize`, inside `is` expression. Try enclosing the contents of `is` with a `typeof` expression +fail_compilation/fail15361.d(9): Error: unexpected `(` after `errorize`, inside `is` expression +fail_compilation/fail15361.d(9): try enclosing the contents of `is` with a `typeof` expression --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail15616b.d b/gcc/testsuite/gdc.test/fail_compilation/fail15616b.d index 4b209685ca44..4cbd591cbf82 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail15616b.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail15616b.d @@ -1,6 +1,6 @@ /* REQUIRED_ARGS: -v -TRANSFORM_OUTPUT: remove_lines("^(predefs|binary|version|config|DFLAG|parse|import|semantic|entry|\s*$)") +TRANSFORM_OUTPUT: remove_lines("^(predefs|binary|version|config|DFLAG|parse|import|\(imported|semantic|entry|\s*$)") TEST_OUTPUT: --- fail_compilation/fail15616b.d(44): Error: none of the overloads of `foo` are callable using argument types `(double)` diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail16.d b/gcc/testsuite/gdc.test/fail_compilation/fail16.d index 4602d3de3bd6..ce021a95b859 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail16.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail16.d @@ -2,8 +2,9 @@ /* TEST_OUTPUT: --- -fail_compilation/fail16.d(19): Error: function declaration without return type. (Note that constructors are always named `this`) -fail_compilation/fail16.d(19): Error: variable name expected after type `bar!(typeof(X))(X)`, not `;` +fail_compilation/fail16.d(20): Error: function declaration without return type +fail_compilation/fail16.d(20): Note that constructors are always named `this` +fail_compilation/fail16.d(20): Error: variable name expected after type `bar!(typeof(X))(X)`, not `;` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail163.d b/gcc/testsuite/gdc.test/fail_compilation/fail163.d index 7f8f028fa52d..590bf23931c9 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail163.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail163.d @@ -14,7 +14,8 @@ void test1() /* TEST_OUTPUT: --- -fail_compilation/fail163.d(24): Error: cannot implicitly convert expression `p` of type `const(int***)` to `const(int)***` +fail_compilation/fail163.d(25): Error: cannot implicitly convert `const(int***)` to `const(int)***` +fail_compilation/fail163.d(25): Note: Converting const to mutable requires an explicit cast (`cast(int*)`). --- */ void test2() @@ -27,7 +28,7 @@ void test2() /* TEST_OUTPUT: --- -fail_compilation/fail163.d(37): Error: cannot modify `const` expression `p` +fail_compilation/fail163.d(38): Error: cannot modify `const` expression `p` --- */ void test3() @@ -40,7 +41,7 @@ void test3() /* TEST_OUTPUT: --- -fail_compilation/fail163.d(50): Error: cannot implicitly convert expression `cp` of type `const(int)***[]` to `const(uint***)[]` +fail_compilation/fail163.d(51): Error: cannot implicitly convert expression `cp` of type `const(int)***[]` to `const(uint***)[]` --- */ void test4() @@ -53,7 +54,7 @@ void test4() /* TEST_OUTPUT: --- -fail_compilation/fail163.d(63): Error: cannot modify `const` expression `*p` +fail_compilation/fail163.d(64): Error: cannot modify `const` expression `*p` --- */ void test5() @@ -66,8 +67,8 @@ void test5() /* TEST_OUTPUT: --- -fail_compilation/fail163.d(76): Error: cannot implicitly convert expression `& x` of type `int*` to `immutable(int)*` -fail_compilation/fail163.d(77): Error: cannot modify `immutable` expression `*p` +fail_compilation/fail163.d(77): Error: cannot implicitly convert expression `& x` of type `int*` to `immutable(int)*` +fail_compilation/fail163.d(78): Error: cannot modify `immutable` expression `*p` --- */ void test6() @@ -80,7 +81,8 @@ void test6() /* TEST_OUTPUT: --- -fail_compilation/fail163.d(89): Error: cannot implicitly convert expression `& x` of type `const(int)*` to `int*` +fail_compilation/fail163.d(91): Error: cannot implicitly convert `const(int)*` to `int*` +fail_compilation/fail163.d(91): Note: Converting const to mutable requires an explicit cast (`cast(int*)`). --- */ void test7() diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail18219.d b/gcc/testsuite/gdc.test/fail_compilation/fail18219.d index bf4b189f6ebc..f5fc27f1a89d 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail18219.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail18219.d @@ -3,11 +3,14 @@ /* TEST_OUTPUT: --- -fail_compilation/fail18219.d(17): Error: no property `Foobar` for type `AST`, did you mean `b18219.Foobar`? -fail_compilation/fail18219.d(18): Error: no property `Bar` for type `a18219.AST` +fail_compilation/fail18219.d(20): Error: no property `Foobar` for type `AST` +fail_compilation/imports/b18219.d(3): did you mean `b18219.Foobar`? +fail_compilation/fail18219.d(21): Error: no property `Bar` for type `a18219.AST` fail_compilation/imports/a18219.d(3): struct `AST` defined here -fail_compilation/fail18219.d(19): Error: no property `fun` for type `AST`, did you mean `b18219.fun`? -fail_compilation/fail18219.d(20): Error: no property `Foobar` for type `AST`, did you mean `b18219.Foobar`? +fail_compilation/fail18219.d(22): Error: no property `fun` for type `AST` +fail_compilation/imports/b18219.d(15): did you mean `b18219.fun`? +fail_compilation/fail18219.d(23): Error: no property `Foobar` for type `AST` +fail_compilation/imports/b18219.d(3): did you mean `b18219.Foobar`? --- */ import imports.a18219; diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19103.d b/gcc/testsuite/gdc.test/fail_compilation/fail19103.d index c1abd0df90af..e617249ed713 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail19103.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail19103.d @@ -5,10 +5,10 @@ fail_compilation/fail19103.d(14): Error: no property `puts` for `new C` of type fail_compilation/fail19103.d(26): class `C` defined here fail_compilation/fail19103.d(16): Error: no property `puts` for `s1` of type `fail19103.S1` fail_compilation/fail19103.d(30): struct `S1` defined here -fail_compilation/fail19103.d(18): Error: no property `puts` for type `S2`, did you mean `core.stdc.stdio.puts`? +fail_compilation/fail19103.d(18): Error: no property `puts` for type `S2` +$p:druntime/import/core/stdc/stdio.d$($n$): did you mean `core.stdc.stdio.puts`? --- */ - void main() { (new C).puts("OK."); // Error: no property puts for type test.C, did you mean core.stdc.stdio.puts(T...)(T args)? diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail196.d b/gcc/testsuite/gdc.test/fail_compilation/fail196.d index 78c596390b56..a5d4499f3fff 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail196.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail196.d @@ -21,7 +21,7 @@ fail_compilation/fail196.d(44): expression: `";\n assert(s == "` fail_compilation/fail196.d(45): Error: found `}` when expecting `;` following expression fail_compilation/fail196.d(45): expression: `xxx` fail_compilation/fail196.d(47): Error: found `<` when expecting `;` following expression -fail_compilation/fail196.d(45): expression: `");\n\n s = q" < foo` +fail_compilation/fail196.d(47): expression: `");\n\n s = q" < foo` fail_compilation/fail196.d(48): Error: found `foo` when expecting `;` following expression fail_compilation/fail196.d(47): expression: `xxx >> ";\n assert(s == "` fail_compilation/fail196.d(48): Error: found `<` instead of statement diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21547.d b/gcc/testsuite/gdc.test/fail_compilation/fail21547.d index 7a6a44a4a133..440a301de514 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail21547.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail21547.d @@ -3,8 +3,10 @@ /* TEST_OUTPUT: --- -fail_compilation/fail21547.d(32): Error: struct `Bar` has constructors, cannot use `{ initializers }`, use `Bar( initializers )` instead -fail_compilation/fail21547.d(33): Error: struct `Bar1` has constructors, cannot use `{ initializers }`, use `Bar1( initializers )` instead +fail_compilation/fail21547.d(34): Error: Cannot use struct initializer syntax for struct `Bar` because it has a constructor +fail_compilation/fail21547.d(34): Use `Bar( arguments )` instead of `{ initializers }` +fail_compilation/fail21547.d(35): Error: Cannot use struct initializer syntax for struct `Bar1` because it has a constructor +fail_compilation/fail21547.d(35): Use `Bar1( arguments )` instead of `{ initializers }` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail23439.d b/gcc/testsuite/gdc.test/fail_compilation/fail23439.d index b070e581a4a7..6f16bc134366 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail23439.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail23439.d @@ -2,7 +2,8 @@ // PERMUTE_ARGS: -lowmem /* TEST_OUTPUT: --- -fail_compilation/fail23439.d(13): Error: variable `fail23439.ice23439` is a thread-local class and cannot have a static initializer. Use `static this()` to initialize instead. +fail_compilation/fail23439.d(14): Error: variable `fail23439.ice23439` is a thread-local class and cannot have a static initializer +fail_compilation/fail23439.d(14): use `static this()` to initialize instead --- */ class C23439 diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail305.d b/gcc/testsuite/gdc.test/fail_compilation/fail305.d deleted file mode 100644 index aef1624a07ca..000000000000 --- a/gcc/testsuite/gdc.test/fail_compilation/fail305.d +++ /dev/null @@ -1,11 +0,0 @@ -/* -TEST_OUTPUT: ---- -fail_compilation/fail305.d(10): Error: cannot return non-void from `void` function ---- -*/ - -void main() -{ - return "a"; -} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail336.d b/gcc/testsuite/gdc.test/fail_compilation/fail336.d index 9df207120b36..8fb9857d4dc4 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail336.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail336.d @@ -1,7 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/fail336.d(16): Error: struct `S` has constructors, cannot use `{ initializers }`, use `S( initializers )` instead +fail_compilation/fail336.d(17): Error: Cannot use struct initializer syntax for struct `S` because it has a constructor +fail_compilation/fail336.d(17): Use `S( arguments )` instead of `{ initializers }` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail347.d b/gcc/testsuite/gdc.test/fail_compilation/fail347.d index c56acf5642cd..996990bd4001 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail347.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail347.d @@ -3,16 +3,16 @@ EXTRA_FILES: imports/fail347a.d TEST_OUTPUT: --- fail_compilation/fail347.d(26): Error: undefined identifier `bbr`, did you mean variable `bar`? -fail_compilation/fail347.d(27): Error: no property `ofo` for type `S`, did you mean `fail347.S.foo`? -fail_compilation/fail347.d(29): Error: no property `fool` for `sp` of type `fail347.S*` -fail_compilation/fail347.d(20): did you mean variable `foo`? +fail_compilation/fail347.d(27): Error: no property `ofo` for type `S` +fail_compilation/fail347.d(20): did you mean `foo`? +fail_compilation/fail347.d(29): Error: no property `fool` for type `S*` +fail_compilation/fail347.d(20): did you mean `foo`? fail_compilation/fail347.d(30): Error: undefined identifier `strlenx`, did you mean function `strlen`? fail_compilation/fail347.d(31): Error: no property `strlenx` for `"hello"` of type `string` fail_compilation/imports/fail347a.d(3): did you mean function `strlen`? --- */ -//import core.stdc.string; import imports.fail347a; struct S diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail41.d b/gcc/testsuite/gdc.test/fail_compilation/fail41.d deleted file mode 100644 index 6d8939505399..000000000000 --- a/gcc/testsuite/gdc.test/fail_compilation/fail41.d +++ /dev/null @@ -1,18 +0,0 @@ -/* -TEST_OUTPUT: ---- -fail_compilation/fail41.d(17): Error: cannot return non-void from `void` function ---- -*/ - -class MyClass -{ -} - -MyClass[char[]] myarray; - -void fn() -{ - foreach (MyClass mc; myarray) - return mc; -} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail98.d b/gcc/testsuite/gdc.test/fail_compilation/fail98.d index 7541d3718c7b..20b18d19db5b 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail98.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail98.d @@ -1,7 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/fail98.d(17): Error: cannot implicitly convert expression `256` of type `int` to `E` +fail_compilation/fail98.d(20): Error: cannot implicitly convert expression `256` of type `int` to `E` +fail_compilation/fail98.d(21): Error: cannot automatically assign value to enum member `fail98.D3DTS_WORLD1` because base type `E` is an enum; provide an explicit value +fail_compilation/fail98.d(22): Error: cannot automatically assign value to enum member `fail98.D3DTS_WORLD2` because base type `E` is an enum; provide an explicit value +fail_compilation/fail98.d(23): Error: cannot automatically assign value to enum member `fail98.D3DTS_WORLD3` because base type `E` is an enum; provide an explicit value --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_pretty_errors.d b/gcc/testsuite/gdc.test/fail_compilation/fail_pretty_errors.d index 79242b163eea..ebd36a7cc1d2 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail_pretty_errors.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail_pretty_errors.d @@ -16,7 +16,7 @@ fail_compilation/fail_pretty_errors.d(44): Error: mixin `fail_pretty_errors.test ^ fail_compilation/fail_pretty_errors.d(50): Error: invalid array operation `"" + ""` (possible missing []) auto x = ""+""; - ^ + ^ fail_compilation/fail_pretty_errors.d(50): did you mean to concatenate (`"" ~ ""`) instead ? fail_compilation/fail_pretty_errors.d(53): Error: cannot implicitly convert expression `1111` of type `int` to `byte` byte ɑ = 1111; diff --git a/gcc/testsuite/gdc.test/fail_compilation/failcontracts.d b/gcc/testsuite/gdc.test/fail_compilation/failcontracts.d index b6c3bc906a15..749d98f9bd0c 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/failcontracts.d +++ b/gcc/testsuite/gdc.test/fail_compilation/failcontracts.d @@ -1,14 +1,15 @@ /* TEST_OUTPUT: --- -fail_compilation/failcontracts.d(17): Error: missing `{ ... }` for function literal -fail_compilation/failcontracts.d(17): Error: semicolon expected following auto declaration, not `bode` -fail_compilation/failcontracts.d(18): Error: function declaration without return type. (Note that constructors are always named `this`) -fail_compilation/failcontracts.d(18): Error: variable name expected after type `test1()`, not `bode` -fail_compilation/failcontracts.d(18): Error: semicolon expected following function declaration, not `bode` +fail_compilation/failcontracts.d(18): Error: missing `{ ... }` for function literal +fail_compilation/failcontracts.d(18): Error: semicolon expected following auto declaration, not `bode` +fail_compilation/failcontracts.d(19): Error: function declaration without return type +fail_compilation/failcontracts.d(19): Note that constructors are always named `this` +fail_compilation/failcontracts.d(19): Error: variable name expected after type `test1()`, not `bode` fail_compilation/failcontracts.d(19): Error: semicolon expected following function declaration, not `bode` -fail_compilation/failcontracts.d(21): Error: unexpected `(` in declarator -fail_compilation/failcontracts.d(21): Error: found `T` when expecting `)` -fail_compilation/failcontracts.d(21): Error: expected `{`, not `;` for enum declaration +fail_compilation/failcontracts.d(20): Error: semicolon expected following function declaration, not `bode` +fail_compilation/failcontracts.d(22): Error: unexpected `(` in declarator +fail_compilation/failcontracts.d(22): Error: found `T` when expecting `)` +fail_compilation/failcontracts.d(22): Error: expected `{`, not `;` for enum declaration --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix19613.d b/gcc/testsuite/gdc.test/fail_compilation/fix19613.d new file mode 100644 index 000000000000..beca56fd7091 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fix19613.d @@ -0,0 +1,16 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/fix19613.d(15): Error: function `fix19613.B.a` cannot override `final` function `fix19613.A.a` +fail_compilation/fix19613.d(15): Error: function `fix19613.B.a` does not override any function +fail_compilation/fix19613.d(15): Did you mean to override `void fix19613.A.a(string)`? +--- +*/ + +class A { + final void a(int) {} + void a(string) {} +} +class B : A { + override void a(int) {} +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix20075.d b/gcc/testsuite/gdc.test/fail_compilation/fix20075.d new file mode 100644 index 000000000000..00f229d326b3 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fix20075.d @@ -0,0 +1,21 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/fix20075.d(15): Error: none of the overloads of `this` can construct an immutable object with argument types `(int*)`. Expected `immutable(int*)` +fail_compilation/fix20075.d(11): Candidate is: `fix20075.Foo.this(immutable(int*) a) immutable` +--- +*/ + +struct Foo { + @disable this(); + immutable this(immutable int* a) {} +} + +immutable(Foo) getFoo(int* a) { + return immutable Foo(a); +} + +void main() { + int x; + auto foo = getFoo(&x); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix20318.d b/gcc/testsuite/gdc.test/fail_compilation/fix20318.d new file mode 100644 index 000000000000..f32030001278 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fix20318.d @@ -0,0 +1,46 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/fix20318.d(16): Error: cannot implicitly convert expression `c` of type `const(Bar)` to `Bar` because struct `Bar` contains pointers or references +fail_compilation/fix20318.d(20): Error: cannot implicitly convert expression `complex_c` of type `const(ComplexBar)` to `ComplexBar` because struct `ComplexBar` contains pointers or references +--- +*/ + +void main() { + // This should work - struct without pointers + const Foo a; + Foo b = a; // This is okay + + // This should fail with improved diagnostic message + const Bar c; + Bar d = c; // Error with improved diagnostic message + + // Test with a more complex struct with nested pointers + const ComplexBar complex_c; + ComplexBar complex_d = complex_c; // Give improved error message +} + +struct Foo { + int value; +} + +struct Bar { + void* ptr; +} + +// Simple struct without pointers +struct Simple { + int value; +} + +// Struct with a pointer +struct WithPointer { + int* ptr; +} + +// Complex struct that contains another struct with pointers +struct ComplexBar { + Simple simple; // This is fine + int data; // This is fine + WithPointer nested; // This field prevents implicit conversion +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix20867.d b/gcc/testsuite/gdc.test/fail_compilation/fix20867.d new file mode 100644 index 000000000000..0ccad0980317 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fix20867.d @@ -0,0 +1,20 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/fix20867.d(14): Error: cannot use `final switch` on enum `E` while it is being defined +--- +*/ + +// Test case from Issue #20867 +enum E +{ + a = 3, + b = () { + E e; + final switch (e) // This should error out instead of segfaulting + { + case E.a: break; + } + return 4; + } () +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix21042.d b/gcc/testsuite/gdc.test/fail_compilation/fix21042.d new file mode 100644 index 000000000000..b2b224e5196e --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fix21042.d @@ -0,0 +1,15 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/fix21042.d(14): Error: template `gun` is not callable using argument types `!()(int)` +fail_compilation/fix21042.d(14): no parameter named `x` +fail_compilation/fix21042.d(10): Candidate is: `gun(T)(T a)` +--- +*/ + +void gun(T)(T a) {} + +void main() +{ + gun(x: 1); // (no explanation) --> (no parameter named `x`) +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix21165.d b/gcc/testsuite/gdc.test/fail_compilation/fix21165.d new file mode 100644 index 000000000000..1d38013b4df0 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fix21165.d @@ -0,0 +1,30 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/fix21165.d(12): Error: undefined identifier `foo` +fail_compilation/fix21165.d(16): Error: undefined identifier `foo` +fail_compilation/fix21165.d(21): Error: undefined identifier `foo` +fail_compilation/fix21165.d(30): Error: undefined identifier `foo` +--- +*/ + +// Test case from Issue #21165 +foo +f() {} + +// Test case from Issue #21171 +foo +bar; + +// Test case from Issue #21169 +void fun( + foo x +) {} + +// Test case from Issue #21168 +enum plusOne(int x) = x + 1; + +alias fooPlusOne = + plusOne + ! + foo; diff --git a/gcc/testsuite/gdc.test/fail_compilation/fix21166.d b/gcc/testsuite/gdc.test/fail_compilation/fix21166.d new file mode 100644 index 000000000000..24dbf8b4675c --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fix21166.d @@ -0,0 +1,13 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/fix21166.d(12): Error: invalid array operation `"foo" + "bar"` (possible missing []) +fail_compilation/fix21166.d(12): did you mean to concatenate (`"foo" ~ "bar"`) instead ? +--- +*/ + +// Test case for https://github.com/dlang/dmd/issues/21166 +auto r = + "foo" + + + "bar"; diff --git a/gcc/testsuite/gdc.test/fail_compilation/hidden_ctor.d b/gcc/testsuite/gdc.test/fail_compilation/hidden_ctor.d new file mode 100644 index 000000000000..8d6e6959f29b --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/hidden_ctor.d @@ -0,0 +1,27 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/hidden_ctor.d(25): Error: constructor `hidden_ctor.B.this(string s)` is not callable using argument types `()` +fail_compilation/hidden_ctor.d(25): Note: constructor `hidden_ctor.B.this` hides base class constructor `hidden_ctor.A.this` +--- +*/ + +class A { + int a; + + this() { + this.a = 1; + } +} +class B : A { + string b; + + this(string s) { + super(); + this.b = s; + } +} +void main() { + auto b = new B(); + b = new B("Hi, Mom!"); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice11153.d b/gcc/testsuite/gdc.test/fail_compilation/ice11153.d index 826bd8cd7ec1..936d987c1528 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice11153.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice11153.d @@ -1,8 +1,9 @@ /* TEST_OUTPUT: --- -fail_compilation/ice11153.d(11): Error: function declaration without return type. (Note that constructors are always named `this`) -fail_compilation/ice11153.d(11): Error: variable name expected after type `foo()`, not `{` +fail_compilation/ice11153.d(12): Error: function declaration without return type +fail_compilation/ice11153.d(12): Note that constructors are always named `this` +fail_compilation/ice11153.d(12): Error: variable name expected after type `foo()`, not `{` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice19755.d b/gcc/testsuite/gdc.test/fail_compilation/ice19755.d index 6d60fc43c1b2..2770676294c2 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice19755.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice19755.d @@ -1,7 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/ice19755.d(11): Error: no property `x` for `self` of type `ice19755.Thunk!int*` -fail_compilation/ice19755.d(16): Error: template instance `ice19755.Thunk!int` error instantiating +fail_compilation/ice19755.d(12): Error: no property `x` for `self` of type `ice19755.Thunk!int*` +fail_compilation/ice19755.d(8): struct `Thunk` defined here +fail_compilation/ice19755.d(17): Error: template instance `ice19755.Thunk!int` error instantiating --- */ struct Thunk(Dummy) { diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/imp18127a.c b/gcc/testsuite/gdc.test/fail_compilation/imports/imp18127a.c new file mode 100644 index 000000000000..2ef629e3b5b2 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/imports/imp18127a.c @@ -0,0 +1,83 @@ +// https://github.com/dlang/dmd/issues/18127 +// union in here, struct in other +union struct_or_union { + int x; +}; + +// mismatching number of fields +struct S_n_fields { + int x, y; +}; + +// mismatched types +struct S_types { + float x; +}; + +// mismatched names +struct S_names { + float x; +}; + +struct B { + int x; +}; + +// Contains a struct that is incompatible +struct S_b { + struct B b; +}; + +// mismatched anonymous struct +struct S_contains_anon_named { + struct { + int x; + } a; +}; + +struct S_contains_anon_unnamed { + struct { + int x; + }; +}; + +// bitfields +struct S_bitfields_mismatch1 { + unsigned x: 3; + unsigned y: 1; +}; +struct S_bitfields_mismatch2 { + unsigned x; + unsigned y: 1; +}; + +struct S_bitfields_widths { + unsigned x: 3; + unsigned y: 1; +}; + +struct S_bitfields_anon { + unsigned x: 3; + unsigned : 1; +}; + +// mismatched alignment +struct S_alignas { + _Alignas(8) float x; +}; +struct S_aligned { + float x; +}__attribute__((aligned(8))); + +// mismatched packing +struct __attribute__((packed)) S_pack_1 { + float x; + char c; +}; +#pragma pack(push) +#pragma pack(1) +struct S_pack_2 { + float x; + char c; +}; +#pragma pack(pop) diff --git a/gcc/testsuite/gdc.test/fail_compilation/imports/imp18127b.c b/gcc/testsuite/gdc.test/fail_compilation/imports/imp18127b.c new file mode 100644 index 000000000000..3cbbf7a9a638 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/imports/imp18127b.c @@ -0,0 +1,80 @@ +// https://github.com/dlang/dmd/issues/18127 +// struct in here, union in other +struct struct_or_union { + int x; +}; + +// mismatching number of fields +struct S_n_fields { + int x; +}; + +// mismatched types +struct S_types { + int x; +}; + +// mismatched names +struct S_names { + float y; +}; + +struct B { + float x; +}; + +// Contains a struct that is incompatible +struct S_b { + struct B b; +}; + +// mismatched anonymous struct +struct S_contains_anon_named { + struct { + float x; + } a; +}; + +struct S_contains_anon_unnamed { + struct { + float x; + }; +}; + +// bitfields +struct S_bitfields_mismatch1 { + unsigned x: 3; + unsigned y; +}; +struct S_bitfields_mismatch2 { + unsigned x: 3; + unsigned y: 1; +}; + +struct S_bitfields_widths { + unsigned x: 3; + unsigned y: 2; +}; + +struct S_bitfields_anon { + unsigned x: 3; + unsigned y: 1; +}; + +// mismatched alignment +struct S_alignas { + float x; +}; +struct S_aligned { + float x; +}__attribute__((aligned(4))); + +// mismatched packing +struct S_pack_1 { + float x; + char c; +}; +struct S_pack_2 { + float x; + char c; +}; diff --git a/gcc/testsuite/gdc.test/fail_compilation/lookup.d b/gcc/testsuite/gdc.test/fail_compilation/lookup.d index fe752f2f4d74..db7eedab30ac 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/lookup.d +++ b/gcc/testsuite/gdc.test/fail_compilation/lookup.d @@ -2,10 +2,12 @@ EXTRA_FILES: imports/imp1.d imports/imp2.d TEST_OUTPUT: --- -fail_compilation/lookup.d(24): Error: no property `X` for type `lookup.B`, did you mean `imports.imp2.X`? -fail_compilation/lookup.d(24): while evaluating: `static assert((B).X == 0)` -fail_compilation/lookup.d(25): Error: no property `Y` for type `lookup.B`, did you mean `imports.imp2.Y`? -fail_compilation/lookup.d(25): while evaluating: `static assert((B).Y == 2)` +fail_compilation/lookup.d(26): Error: no property `X` for type `lookup.B` +fail_compilation/imports/imp2.d(3): did you mean `imports.imp2.X`? +fail_compilation/lookup.d(26): while evaluating: `static assert((B).X == 0)` +fail_compilation/lookup.d(27): Error: no property `Y` for type `lookup.B` +fail_compilation/imports/imp2.d(4): did you mean `imports.imp2.Y`? +fail_compilation/lookup.d(27): while evaluating: `static assert((B).Y == 2)` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/mixinprop.d b/gcc/testsuite/gdc.test/fail_compilation/mixinprop.d index db8bf5968ddc..103c6b2a0473 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/mixinprop.d +++ b/gcc/testsuite/gdc.test/fail_compilation/mixinprop.d @@ -1,9 +1,9 @@ /* TEST_OUTPUT: --- -fail_compilation/mixinprop.d(12): Error: no property `x` for `mixin Foo!() F; -` of type `void` +fail_compilation/mixinprop.d(12): Error: no property `x` for `mixin Foo!() F;` of type `void` --- */ + mixin template Foo() { } void main() diff --git a/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d index 125ebcc926e5..761e1d4c78c1 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d +++ b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_error.d @@ -1,26 +1,27 @@ /* TEST_OUTPUT: --- -fail_compilation/named_arguments_error.d(37): Error: function `f` is not callable using argument types `(int, int, int)` -fail_compilation/named_arguments_error.d(37): parameter `x` assigned twice -fail_compilation/named_arguments_error.d(31): `named_arguments_error.f(int x, int y, int z)` declared here fail_compilation/named_arguments_error.d(38): Error: function `f` is not callable using argument types `(int, int, int)` -fail_compilation/named_arguments_error.d(38): argument `4` goes past end of parameter list -fail_compilation/named_arguments_error.d(31): `named_arguments_error.f(int x, int y, int z)` declared here +fail_compilation/named_arguments_error.d(38): parameter `x` assigned twice +fail_compilation/named_arguments_error.d(32): `named_arguments_error.f(int x, int y, int z)` declared here fail_compilation/named_arguments_error.d(39): Error: function `f` is not callable using argument types `(int, int, int)` -fail_compilation/named_arguments_error.d(39): parameter `y` assigned twice -fail_compilation/named_arguments_error.d(31): `named_arguments_error.f(int x, int y, int z)` declared here +fail_compilation/named_arguments_error.d(39): argument `4` goes past end of parameter list +fail_compilation/named_arguments_error.d(32): `named_arguments_error.f(int x, int y, int z)` declared here fail_compilation/named_arguments_error.d(40): Error: function `f` is not callable using argument types `(int, int, int)` -fail_compilation/named_arguments_error.d(40): no parameter named `a` -fail_compilation/named_arguments_error.d(31): `named_arguments_error.f(int x, int y, int z)` declared here -fail_compilation/named_arguments_error.d(41): Error: function `g` is not callable using argument types `(int, int)` -fail_compilation/named_arguments_error.d(41): missing argument for parameter #1: `int x` -fail_compilation/named_arguments_error.d(33): `named_arguments_error.g(int x, int y, int z = 3)` declared here -fail_compilation/named_arguments_error.d(43): Error: no named argument `element` allowed for array dimension -fail_compilation/named_arguments_error.d(44): Error: no named argument `number` allowed for scalar -fail_compilation/named_arguments_error.d(45): Error: cannot implicitly convert expression `g(x: 3, y: 4, z: 5)` of type `int` to `string` -fail_compilation/named_arguments_error.d(46): Error: template `tempfun` is not callable using argument types `!()(int, int)` -fail_compilation/named_arguments_error.d(49): Candidate is: `tempfun(T, U)(T t, U u)` +fail_compilation/named_arguments_error.d(40): parameter `y` assigned twice +fail_compilation/named_arguments_error.d(32): `named_arguments_error.f(int x, int y, int z)` declared here +fail_compilation/named_arguments_error.d(41): Error: function `f` is not callable using argument types `(int, int, int)` +fail_compilation/named_arguments_error.d(41): no parameter named `a` +fail_compilation/named_arguments_error.d(32): `named_arguments_error.f(int x, int y, int z)` declared here +fail_compilation/named_arguments_error.d(42): Error: function `g` is not callable using argument types `(int, int)` +fail_compilation/named_arguments_error.d(42): missing argument for parameter #1: `int x` +fail_compilation/named_arguments_error.d(34): `named_arguments_error.g(int x, int y, int z = 3)` declared here +fail_compilation/named_arguments_error.d(44): Error: no named argument `element` allowed for array dimension +fail_compilation/named_arguments_error.d(45): Error: no named argument `number` allowed for scalar +fail_compilation/named_arguments_error.d(46): Error: cannot implicitly convert expression `g(x: 3, y: 4, z: 5)` of type `int` to `string` +fail_compilation/named_arguments_error.d(47): Error: template `tempfun` is not callable using argument types `!()(int, int)` +fail_compilation/named_arguments_error.d(47): argument `1` goes past end of parameter list +fail_compilation/named_arguments_error.d(50): Candidate is: `tempfun(T, U)(T t, U u)` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/named_arguments_ifti_error.d b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_ifti_error.d index 6d8a70a2c469..a73fd3cb2e6f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/named_arguments_ifti_error.d +++ b/gcc/testsuite/gdc.test/fail_compilation/named_arguments_ifti_error.d @@ -1,12 +1,15 @@ /* TEST_OUTPUT: --- -fail_compilation/named_arguments_ifti_error.d(17): Error: template `f` is not callable using argument types `!()(int, int)` -fail_compilation/named_arguments_ifti_error.d(13): Candidate is: `f(T, U)(T x, U y)` -fail_compilation/named_arguments_ifti_error.d(18): Error: template `f` is not callable using argument types `!()(int, int)` -fail_compilation/named_arguments_ifti_error.d(13): Candidate is: `f(T, U)(T x, U y)` -fail_compilation/named_arguments_ifti_error.d(19): Error: template `f` is not callable using argument types `!()(int)` -fail_compilation/named_arguments_ifti_error.d(13): Candidate is: `f(T, U)(T x, U y)` +fail_compilation/named_arguments_ifti_error.d(20): Error: template `f` is not callable using argument types `!()(int, int)` +fail_compilation/named_arguments_ifti_error.d(20): parameter `x` assigned twice +fail_compilation/named_arguments_ifti_error.d(16): Candidate is: `f(T, U)(T x, U y)` +fail_compilation/named_arguments_ifti_error.d(21): Error: template `f` is not callable using argument types `!()(int, int)` +fail_compilation/named_arguments_ifti_error.d(21): argument `3` goes past end of parameter list +fail_compilation/named_arguments_ifti_error.d(16): Candidate is: `f(T, U)(T x, U y)` +fail_compilation/named_arguments_ifti_error.d(22): Error: template `f` is not callable using argument types `!()(int)` +fail_compilation/named_arguments_ifti_error.d(22): missing argument for parameter #1: `T x` +fail_compilation/named_arguments_ifti_error.d(16): Candidate is: `f(T, U)(T x, U y)` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/nogc3.d b/gcc/testsuite/gdc.test/fail_compilation/nogc3.d index 17daa96358b1..f1a469b5445f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/nogc3.d +++ b/gcc/testsuite/gdc.test/fail_compilation/nogc3.d @@ -94,3 +94,33 @@ int[] bar13702(bool b) @nogc auto aux = 1 ~ [2]; // error return aux; } + +/********** Enum and pointer types ***************/ +// https://github.com/dlang/dmd/issues/21052 +/* +TEST_OUTPUT: +--- +fail_compilation/nogc3.d(111): Error: this array literal causes a GC allocation in `@nogc` function `f` +fail_compilation/nogc3.d(112): Error: this array literal causes a GC allocation in `@nogc` function `f` +--- +*/ + +void f() @nogc +{ + enum DA : int[] { a = [1,2,3] } + DA da = DA.a; + int i = *cast(int*)cast(char[4])['0', '0', '0', '0']; +} + +/* +TEST_OUTPUT: +--- +fail_compilation/nogc3.d(125): Error: this array literal causes a GC allocation in `@nogc` function `g` +--- +*/ + +// https://github.com/dlang/dmd/issues/21054 +void g() @nogc +{ + int[] x = (int[2]).init[]; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/nonvoid_return.d b/gcc/testsuite/gdc.test/fail_compilation/nonvoid_return.d new file mode 100644 index 000000000000..bcced1b9bff2 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/nonvoid_return.d @@ -0,0 +1,37 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/nonvoid_return.d(15): Error: cannot return non-void from `void` function +fail_compilation/nonvoid_return.d(18): Error: cannot return non-void from `void` function +fail_compilation/nonvoid_return.d(29): Error: cannot return non-void from `void` function +fail_compilation/nonvoid_return.d(32): Error: undefined identifier `NONEXISTENT` +--- +*/ + + + +void main() +{ + return 10; +} + +void fs() => "a"; + +class MyClass +{ +} + +MyClass[char[]] myarray; + +void fn() +{ + foreach (MyClass mc; myarray) + return mc; +} + +auto err() { NONEXISTENT++; } + +// Because `err` contains an error, it fails to infer void and gets an error return type +// Don't print the 'cannot return non-void' error in this case + +void fe() => err; diff --git a/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d b/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d index ec6bd3ebce99..b49417436a53 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d +++ b/gcc/testsuite/gdc.test/fail_compilation/noreturn2.d @@ -117,7 +117,7 @@ TEST_OUTPUT: --- fail_compilation/noreturn2.d(130): Error: cannot create instance of interface `I` fail_compilation/noreturn2.d(133): Error: can only throw class objects derived from `Throwable`, not type `int[]` -fail_compilation/noreturn2.d(138): Error: undefined identifier `UnkownException` +fail_compilation/noreturn2.d(139): Error: undefined identifier `UnkownException` --- +/ diff --git a/gcc/testsuite/gdc.test/fail_compilation/powinline.d b/gcc/testsuite/gdc.test/fail_compilation/powinline.d new file mode 100644 index 000000000000..11ebacd16aaa --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/powinline.d @@ -0,0 +1,38 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/powinline.d(25): Error: cannot implicitly convert expression `(a + 5.0) ^^ 2L` of type `double` to `int` +fail_compilation/powinline.d(26): Error: cannot implicitly convert expression `(1.0 / foo()) ^^ 2L` of type `double` to `int` +fail_compilation/powinline.d(31): Error: void has no value +fail_compilation/powinline.d(31): Error: incompatible types for `(5.0) * (bar())`: `double` and `void` +fail_compilation/powinline.d(37): Error: cannot modify `immutable` expression `a` +--- +*/ + +double foo() +{ + return 5.0; +} + +void bar() +{ + return; +} + +void test1() +{ + double a = 2.0; + int b = (a + 5.0) ^^ 2.0; + b = (1 / foo()) ^^ 2.0; +} + +void test2() +{ + double a = (5.0 * bar()) ^^ 2.0; +} + +void test3() +{ + immutable double a = 3.0; + (a ^^= 2.0) = 6; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/retscope3.d b/gcc/testsuite/gdc.test/fail_compilation/retscope3.d index 438fdd76e1b0..8802469de2c4 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/retscope3.d +++ b/gcc/testsuite/gdc.test/fail_compilation/retscope3.d @@ -55,7 +55,9 @@ TEST_OUTPUT: --- fail_compilation/retscope3.d(4003): Error: escaping a reference to parameter `u` by copying `u[]` into allocated memory is not allowed in a `@safe` function fail_compilation/retscope3.d(4016): Error: storing reference to outer local variable `i` into allocated memory causes it to escape +fail_compilation/retscope3.d(4025): Deprecation: slice of static array temporary returned by `makeSA()` assigned to longer lived variable `a` fail_compilation/retscope3.d(4025): Error: escaping reference to stack allocated value returned by `makeSA()` into allocated memory +fail_compilation/retscope3.d(4032): Error: escaping a reference to local variable `i` by copying `& i` into allocated memory is not allowed in a `@safe` function --- */ @@ -87,3 +89,11 @@ void bar4003() @safe { int[][] a = [makeSA()[]]; } + +// https://github.com/dlang/dmd/issues/20901 +int* f20901() @safe +{ + int i = 3; + auto x = &[&i][0]; // Should error, i is escaped into allocated memory + return *x; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/seq_assign.d b/gcc/testsuite/gdc.test/fail_compilation/seq_assign.d new file mode 100644 index 000000000000..560bc344242c --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/seq_assign.d @@ -0,0 +1,43 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/seq_assign.d(28): Error: cannot assign `int` to expression sequence `(int)` +fail_compilation/seq_assign.d(29): Error: cannot implicitly convert expression `s` of type `string` to `int` +fail_compilation/seq_assign.d(30): Error: cannot modify constant `2` +fail_compilation/seq_assign.d(31): Error: mismatched sequence lengths, 1 and 2 +fail_compilation/seq_assign.d(35): Error: mismatched sequence lengths, 1 and 2 +fail_compilation/seq_assign.d(36): Error: cannot implicitly convert expression `__t_field_0` of type `string` to `int` +fail_compilation/seq_assign.d(40): Error: cannot assign `IntString` to expression sequence `(string, int)` +fail_compilation/seq_assign.d(42): Error: cannot implicitly convert expression `AliasSeq!(b, c)` of type `(int, int)` to `IntString` +--- +*/ + +alias Seq(A...) = A; + +struct IntString +{ + Seq!(int, string) expand; + alias this = expand; +} + +void main() +{ + int b, c; + string s; + + Seq!(b,) = 1; // RHS not seq + Seq!(b,) = Seq!(s,); // b type error + Seq!(2,) = Seq!(1,); // not lvalue + Seq!(b,) = Seq!(1, 2); // too many + + auto t = Seq!("two", 3); + Seq!(s, b) = t; // OK + Seq!(b,) = t; // too many + Seq!(b, c) = t; // b type error + + IntString t2; + Seq!(b, s) = t2; // OK + t = t2; // type mismatch + t2 = Seq!(b, s); // OK + t2 = Seq!(b, c); // c wrong type +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test15989.d b/gcc/testsuite/gdc.test/fail_compilation/test15989.d index 38ca33126724..85b74bfad583 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test15989.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test15989.d @@ -1,9 +1,11 @@ /* TEST_OUTPUT: --- -fail_compilation/test15989.d(39): Error: variable `test15989.main.ctRegex` : Unable to initialize enum with class or pointer to struct. Use static const variable instead. -fail_compilation/test15989.d(48): Error: variable `test15989.test.c` : Unable to initialize enum with class or pointer to struct. Use static const variable instead. -fail_compilation/test15989.d(49): Error: cannot use non-constant CTFE pointer in an initializer `new int(3)` +fail_compilation/test15989.d(41): Error: variable `test15989.main.ctRegex` : Unable to initialize enum with class or pointer to struct +fail_compilation/test15989.d(41): use static const variable instead +fail_compilation/test15989.d(50): Error: variable `test15989.test.c` : Unable to initialize enum with class or pointer to struct +fail_compilation/test15989.d(50): use static const variable instead +fail_compilation/test15989.d(51): Error: cannot use non-constant CTFE pointer in an initializer `new int(3)` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test18127.d b/gcc/testsuite/gdc.test/fail_compilation/test18127.d new file mode 100644 index 000000000000..ec0487cd8925 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test18127.d @@ -0,0 +1,106 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/imports/imp18127b.c(3): Error: struct `struct_or_union` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(3): previously declared here +fail_compilation/imports/imp18127b.c(3): `imp18127b.struct_or_union` is a struct while `imp18127a.struct_or_union` is a union +fail_compilation/imports/imp18127b.c(3): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(8): Error: struct `S_n_fields` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(8): previously declared here +fail_compilation/imports/imp18127b.c(8): `imp18127b.S_n_fields` has 1 field(s) while `imp18127a.S_n_fields` has 2 field(s) +fail_compilation/imports/imp18127b.c(8): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(13): Error: struct `S_types` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(13): previously declared here +fail_compilation/imports/imp18127b.c(14): Field 0 differs in type +fail_compilation/imports/imp18127b.c(14): typeof(x): int +fail_compilation/imports/imp18127a.c(14): typeof(x): float +fail_compilation/imports/imp18127b.c(13): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(18): Error: struct `S_names` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(18): previously declared here +fail_compilation/imports/imp18127b.c(19): Field 0 differs in name +fail_compilation/imports/imp18127b.c(19): y +fail_compilation/imports/imp18127a.c(19): x +fail_compilation/imports/imp18127b.c(18): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(22): Error: struct `B` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(22): previously declared here +fail_compilation/imports/imp18127b.c(23): Field 0 differs in type +fail_compilation/imports/imp18127b.c(23): typeof(x): float +fail_compilation/imports/imp18127a.c(23): typeof(x): int +fail_compilation/imports/imp18127b.c(22): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(27): Error: struct `S_b` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(27): previously declared here +fail_compilation/imports/imp18127b.c(27): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(33): Error: struct `(anonymous struct)` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(33): previously declared here +fail_compilation/imports/imp18127b.c(34): Field 0 differs in type +fail_compilation/imports/imp18127b.c(34): typeof(x): float +fail_compilation/imports/imp18127a.c(34): typeof(x): int +fail_compilation/imports/imp18127b.c(32): Error: struct `S_contains_anon_named` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(32): previously declared here +fail_compilation/imports/imp18127b.c(35): Field 0 differs in type +fail_compilation/imports/imp18127b.c(35): typeof(a): (anonymous struct) +fail_compilation/imports/imp18127a.c(35): typeof(a): (anonymous struct) +fail_compilation/imports/imp18127b.c(32): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(38): Error: struct `S_contains_anon_unnamed` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(38): previously declared here +fail_compilation/imports/imp18127b.c(40): Field 0 differs in type +fail_compilation/imports/imp18127b.c(40): typeof(x): float +fail_compilation/imports/imp18127a.c(40): typeof(x): int +fail_compilation/imports/imp18127b.c(38): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(45): Error: struct `S_bitfields_mismatch1` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(45): previously declared here +fail_compilation/imports/imp18127b.c(47): Field 1 differs in being a bitfield +fail_compilation/imports/imp18127b.c(47): `imp18127b.S_bitfields_mismatch1.y` is not a bitfield +fail_compilation/imports/imp18127a.c(47): `imp18127a.S_bitfields_mismatch1.y` is a bitfield +fail_compilation/imports/imp18127b.c(45): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(49): Error: struct `S_bitfields_mismatch2` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(49): previously declared here +fail_compilation/imports/imp18127b.c(50): Field 0 differs in being a bitfield +fail_compilation/imports/imp18127b.c(50): `imp18127b.S_bitfields_mismatch2.x` *is a bitfield +fail_compilation/imports/imp18127a.c(50): `imp18127a.S_bitfields_mismatch2.x` is not a bitfield +fail_compilation/imports/imp18127b.c(49): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(54): Error: struct `S_bitfields_widths` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(54): previously declared here +fail_compilation/imports/imp18127b.c(56): Field 1 differs in bitfield width +fail_compilation/imports/imp18127b.c(56): `imp18127b.S_bitfields_widths.y`: 2 +fail_compilation/imports/imp18127a.c(56): `imp18127a.S_bitfields_widths.y`: 1 +fail_compilation/imports/imp18127b.c(54): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(59): Error: struct `S_bitfields_anon` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(59): previously declared here +fail_compilation/imports/imp18127b.c(61): Field 1 differs in name +fail_compilation/imports/imp18127b.c(61): y +fail_compilation/imports/imp18127a.c(61): (anonymous) +fail_compilation/imports/imp18127b.c(59): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(65): Error: struct `S_alignas` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(65): previously declared here +fail_compilation/imports/imp18127b.c(66): Field 0 differs in alignment or packing +fail_compilation/imports/imp18127b.c(66): `imp18127b.S_alignas.x` alignment: default +fail_compilation/imports/imp18127a.c(66): `imp18127a.S_alignas.x` alignment: 8 +fail_compilation/imports/imp18127b.c(65): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(68): Error: struct `S_aligned` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(68): previously declared here +fail_compilation/imports/imp18127b.c(68): `imp18127b.S_aligned` has different alignment or packing +fail_compilation/imports/imp18127b.c(68): `imp18127b.S_aligned` alignment: 4 +fail_compilation/imports/imp18127a.c(68): `imp18127a.S_aligned` alignment: 8 +fail_compilation/imports/imp18127b.c(68): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(73): Error: struct `S_pack_1` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(73): previously declared here +fail_compilation/imports/imp18127b.c(73): `imp18127b.S_pack_1` has different alignment or packing +fail_compilation/imports/imp18127b.c(73): `imp18127b.S_pack_1` alignment: default +fail_compilation/imports/imp18127a.c(73): `imp18127a.S_pack_1` alignment: 1 +fail_compilation/imports/imp18127b.c(73): `imp18127b.S_pack_1` packed: false +fail_compilation/imports/imp18127a.c(73): `imp18127a.S_pack_1` packed: true +fail_compilation/imports/imp18127b.c(73): C structs with the same name from different imports are merged +fail_compilation/imports/imp18127b.c(77): Error: struct `S_pack_2` already exists with an incompatible definition. +fail_compilation/imports/imp18127a.c(79): previously declared here +fail_compilation/imports/imp18127b.c(77): `imp18127b.S_pack_2` has different alignment or packing +fail_compilation/imports/imp18127b.c(77): `imp18127b.S_pack_2` alignment: default +fail_compilation/imports/imp18127a.c(79): `imp18127a.S_pack_2` alignment: 1 +fail_compilation/imports/imp18127b.c(77): C structs with the same name from different imports are merged +--- +*/ + +// https://github.com/dlang/dmd/issues/18127 + +import imports.imp18127a; +import imports.imp18127b; diff --git a/gcc/testsuite/gdc.test/fail_compilation/test19661.d b/gcc/testsuite/gdc.test/fail_compilation/test19661.d index 369c0a862495..712721487caa 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test19661.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test19661.d @@ -2,7 +2,8 @@ EXTRA_FILES: imports/imp19661.d TEST_OUTPUT: --- -fail_compilation/test19661.d(11): Error: variables cannot be initialized with an expression of type `void`. Use `void` initialization instead. +fail_compilation/test19661.d(12): Error: variables cannot be initialized with an expression of type `void` +fail_compilation/test19661.d(12): only `= void;` is allowed, which prevents default initialization --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test20489.d b/gcc/testsuite/gdc.test/fail_compilation/test20489.d new file mode 100644 index 000000000000..1cd5350959c5 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test20489.d @@ -0,0 +1,20 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/test20489.d(19): Error: function `pure nothrow @nogc @safe int test20489.D.f(int delegate(int) pure nothrow @nogc @safe body)` does not override any function, did you mean to override `pure nothrow @nogc @safe int test20489.B.f(scope int delegate(int) pure nothrow @nogc @safe)`? +fail_compilation/test20489.d(19): Did you intend to override: +fail_compilation/test20489.d(19): `pure nothrow @nogc @safe int test20489.B.f(scope int delegate(int) pure nothrow @nogc @safe)` +fail_compilation/test20489.d(19): Parameter 1 is missing `scope` +--- +*/ + +// Test case for https://github.com/dlang/dmd/issues/20489 +// Improved error message on override mismatches + +class B { + pure nothrow @nogc @safe int f(scope int delegate(int) pure nothrow @nogc @safe) { return 0; } +} + +class D : B { + override pure nothrow @nogc @safe int f(int delegate(int) pure nothrow @nogc @safe body) { return 0; } +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21215.d b/gcc/testsuite/gdc.test/fail_compilation/test21215.d new file mode 100644 index 000000000000..5efa315723c2 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test21215.d @@ -0,0 +1,35 @@ +/* TEST_OUTPUT: +--- +fail_compilation/test21215.d(13): Error: `y` is not a member of `S` +fail_compilation/test21215.d(18): Error: `xhs` is not a member of `S`, did you mean variable `xsh`? +fail_compilation/test21215.d(28): Error: `y` is not a member of `S` +fail_compilation/test21215.d(32): Error: `yashu` is not a member of `S` +--- +*/ +struct S { int xsh; } + +void test() { + auto s1 = S( + y: + 1 + ); + + auto s2 = S( + xhs: + 1 + ); + + auto s3 = S( + xsh: 1 + ); + + auto s4 = S( + xsh: 1, + y: 2 + ); + + auto s5 = S( + yashu: + 2 + ); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21304.d b/gcc/testsuite/gdc.test/fail_compilation/test21304.d new file mode 100644 index 000000000000..9789e2b9c956 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test21304.d @@ -0,0 +1,6 @@ +/* TEST_OUTPUT: +--- +fail_compilation/test21304.d(6): Error: undefined identifier `unknown` +--- +*/ +int[unknown] values = [1, 2, 3]; diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21317.d b/gcc/testsuite/gdc.test/fail_compilation/test21317.d new file mode 100644 index 000000000000..39b3963799eb --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test21317.d @@ -0,0 +1,39 @@ +module dmd.compiler.test.fail_compilation.test21317; + +/* TEST_OUTPUT: +--- +fail_compilation/test21317.d(16): Error: `writeln` is not defined, perhaps `import std.stdio;` ? +fail_compilation/test21317.d(21): Error: undefined identifier `Zero`, did you mean variable `zero`? +fail_compilation/test21317.d(25): Error: undefined identifier `NULL`, did you mean `null`? +fail_compilation/test21317.d(31): Error: undefined identifier `this`, did you mean `typeof(this)`? +fail_compilation/test21317.d(38): Error: undefined identifier `unknown` +--- +*/ + +// Weird formatting is intended to check the loc + +int[ + writeln + ] arr1; + +int zero = 0; +int [ + Zero + ] arr2; + +int [ + NULL + ] arr3; + +struct S4 +{ + enum E4 : + this + { + fail, + } +} + +int [ + unknown + ] arr5; diff --git a/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d b/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d index 1173d14480d0..a0ade760fe52 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d +++ b/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d @@ -5,7 +5,7 @@ TEST_OUTPUT: --- fail_compilation/testrvaluecpctor.d(16): Error: cannot define both an rvalue constructor and a copy constructor for `struct Foo` fail_compilation/testrvaluecpctor.d(24): Template instance `testrvaluecpctor.Foo!int.Foo.__ctor!(immutable(Foo!int), immutable(Foo!int))` creates an rvalue constructor for `struct Foo` -fail_compilation/testrvaluecpctor.d(24): Error: none of the overloads of `this` can construct a `immutable` object with argument types `(immutable(Foo!int))` +fail_compilation/testrvaluecpctor.d(24): Error: none of the overloads of `this` can construct an immutable object with argument types `(immutable(Foo!int))`. Expected `immutable(immutable(Foo!int))` fail_compilation/testrvaluecpctor.d(18): Candidates are: `testrvaluecpctor.Foo!int.Foo.this(ref scope Foo!int rhs)` fail_compilation/testrvaluecpctor.d(16): `this(Rhs, this This)(scope Rhs rhs)` --- diff --git a/gcc/testsuite/gdc.test/fail_compilation/uda_lambda.d b/gcc/testsuite/gdc.test/fail_compilation/uda_lambda.d new file mode 100644 index 000000000000..bd3ff49e0e36 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/uda_lambda.d @@ -0,0 +1,7 @@ +/+ +TEST_OUTPUT: +--- +fail_compilation/uda_lambda.d(7): Error: declaration expected, not `=>` +--- ++/ +@a => 7 int b; diff --git a/gcc/testsuite/gdc.test/fail_compilation/union_conv.d b/gcc/testsuite/gdc.test/fail_compilation/union_conv.d index f08809c48500..134da36ecdbf 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/union_conv.d +++ b/gcc/testsuite/gdc.test/fail_compilation/union_conv.d @@ -2,7 +2,7 @@ REQUIRED_ARGS: -preview=fixImmutableConv TEST_OUTPUT: --- -fail_compilation/union_conv.d(18): Error: cannot implicitly convert expression `c` of type `const(U)` to `U` +fail_compilation/union_conv.d(18): Error: cannot implicitly convert expression `c` of type `const(U)` to `U` because union `U` contains pointers or references --- */ diff --git a/gcc/testsuite/gdc.test/runnable/placenew.d b/gcc/testsuite/gdc.test/runnable/placenew.d index d90d10a5e744..834a1f76bcbf 100644 --- a/gcc/testsuite/gdc.test/runnable/placenew.d +++ b/gcc/testsuite/gdc.test/runnable/placenew.d @@ -93,6 +93,47 @@ void test6() /*************************************************/ +struct S7 +{ + int x = 10; + int y = 20; +} + +void test7() +{ + S7 t = void; + new (t) S7(10,20); + assert(t.x == 10 && t.y == 20); +} + +/*************************************************/ +// https://github.com/dlang/dmd/issues/21203 + +struct Y8 +{ + int a; + this() @disable; // default disabled + this(int i) { a = i; } +} + +struct S8 +{ + Y8 m; + + this(int x) + { + new(m) Y8(x); // initialise `m` + } +} + +void test8() +{ + S8 s = S8(3); + assert(s.m.a == 3); +} + +/*************************************************/ + int main() { test1(); @@ -101,6 +142,8 @@ int main() test4(); test5(); test6(); + test7(); + test8(); return 0; } diff --git a/gcc/testsuite/gdc.test/runnable/powinline.d b/gcc/testsuite/gdc.test/runnable/powinline.d new file mode 100644 index 000000000000..92d1c04e5564 --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable/powinline.d @@ -0,0 +1,64 @@ +/* +REQUIRED_ARGS: -betterC +RUN_OUTPUT: +--- +Success +--- +*/ +import core.stdc.stdio; + +void test1() +{ + enum real Two = 2.0; + static assert(Two^^3 == 8.0); +} + +void test2() +{ + double x = 5.0; + assert(x^^-1 == 1/x); + x = -1.0; + assert(x^^1 == x); + assert((x += 3) ^^ 2.0 == 4.0); + assert((x) ^^ 2.0 == 4.0); + assert((x *= 5) ^^ 2.0 == (x * x)); + assert(x^^-1 == 1.0 / x); + assert((x^^-1) ^^ 0.0 == 1.0); +} + +void test3() +{ + int x = 6; + assert(x ^^ 0 == 1); + assert((x += 3) ^^ 2 == 81); + assert(x ^^ 2 == (x ^^ 1) * (x ^^ 1)); + static assert(4.0 ^^ -1 == 0.25); +} + +void test4() +{ + // Test that LHS side effects are evaluated. + int count = 0; + double x() + { + count++; + return 8.0; + } + assert(x ^^ -1 == 1.0 / 8.0); + assert(count == 1); + assert(x ^^ 0 == 1.0); + assert(count == 2); + assert(x ^^ 1 == 8.0); + assert(count == 3); + assert(x ^^ 2 == 64.0); + assert(count == 4); +} + +extern(C) void main() +{ + test1(); + test2(); + test3(); + test4(); + printf("Success\n"); +} diff --git a/gcc/testsuite/gdc.test/runnable/testaa2.d b/gcc/testsuite/gdc.test/runnable/testaa2.d index e1abcb4418c5..3d199d984125 100644 --- a/gcc/testsuite/gdc.test/runnable/testaa2.d +++ b/gcc/testsuite/gdc.test/runnable/testaa2.d @@ -307,6 +307,26 @@ void testinenum() assert("one" in aa); } +// https://github.com/dlang/dmd/issues/21258 +void test21258() +{ + alias AliasSeq(TList...) = TList; + + struct S { int x; } // use a local type to not generate required TypeInfo elsewhere + foreach (T; AliasSeq!(S[int])) + enum E { a = T.init, } // bug report uses bad syntax here, but this crashed, too +} + +// https://github.com/dlang/dmd/issues/21207 +void test21207() +{ + struct S { int x; } // use a local type to not generate required TypeInfo elsewhere + enum aa = ["baz": S(7)]; + + void foo(S[string] x = aa) { } + foo(); +} + /************************************************/ int main() @@ -318,6 +338,7 @@ int main() test3825x(); testinout(); testinenum(); + test21258(); printf("Success\n"); return 0; diff --git a/gcc/testsuite/gdc.test/runnable/testinvariant.d b/gcc/testsuite/gdc.test/runnable/testinvariant.d index 0ce855719117..11b8829b9fce 100644 --- a/gcc/testsuite/gdc.test/runnable/testinvariant.d +++ b/gcc/testsuite/gdc.test/runnable/testinvariant.d @@ -228,8 +228,52 @@ void test16384() assert(s == "needs to be thrown2"); } - /***************************************************/ +// Fix: https://github.com/dlang/dmd/issues/20924 (invariant not called on extern(C++) classes) + +extern(C++) class C +{ + invariant { assert(0); } + void f() {} +} + +extern(D) class D +{ + invariant { assert(0); } + void f() {} +} + +void test20924() +{ + import core.exception : AssertError; + // Test extern(C++) class invariant + try + { + auto c = new C(); + c.f(); // Trigger invariant + assert(false, "Failed: invariant in extern(C++) class not checked"); + } + catch (AssertError e) + { + // Expected behavior - invariant was checked + return; + } + assert(0, "Invariant in extern(C++) class was not checked"); + + // Test extern(D) class invariant + try + { + auto d = new D(); + d.f(); // Trigger invariant + assert(false, "Failed: invariant in extern(D) class not checked"); + } + catch (AssertError e) + { + // Expected behavior - invariant was checked + return; + } + assert(0, "Invariant in extern(D) class was not checked"); +} void main() { @@ -238,4 +282,5 @@ void main() test16384(); test13113(); test13147(); + test20924(); } diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index 840f8dd4f9d9..62d90e5770b5 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -1,4 +1,4 @@ -09ed02ce56ea5bf3e59f21ee0390cd85eb8bfaa7 +1017635a9636ef6a7a4bda35b1e091875d829871 The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am index 4c8d65b76f5f..0e9b71bfa5d2 100644 --- a/libphobos/libdruntime/Makefile.am +++ b/libphobos/libdruntime/Makefile.am @@ -297,8 +297,9 @@ DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \ core/sys/linux/sys/mman.d core/sys/linux/sys/mount.d \ core/sys/linux/sys/prctl.d core/sys/linux/sys/procfs.d \ core/sys/linux/sys/signalfd.d core/sys/linux/sys/socket.d \ - core/sys/linux/sys/sysinfo.d core/sys/linux/sys/time.d \ - core/sys/linux/sys/xattr.d core/sys/linux/termios.d \ + core/sys/linux/sys/syscall.d core/sys/linux/sys/sysinfo.d \ + core/sys/linux/sys/time.d core/sys/linux/sys/xattr.d \ + core/sys/linux/syscall.d core/sys/linux/termios.d \ core/sys/linux/time.d core/sys/linux/timerfd.d core/sys/linux/tipc.d \ core/sys/linux/uinput.d core/sys/linux/unistd.d diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in index a6bbb76c216b..8543c6e53edc 100644 --- a/libphobos/libdruntime/Makefile.in +++ b/libphobos/libdruntime/Makefile.in @@ -385,8 +385,9 @@ am__objects_19 = core/sys/linux/config.lo core/sys/linux/dlfcn.lo \ core/sys/linux/sys/mman.lo core/sys/linux/sys/mount.lo \ core/sys/linux/sys/prctl.lo core/sys/linux/sys/procfs.lo \ core/sys/linux/sys/signalfd.lo core/sys/linux/sys/socket.lo \ - core/sys/linux/sys/sysinfo.lo core/sys/linux/sys/time.lo \ - core/sys/linux/sys/xattr.lo core/sys/linux/termios.lo \ + core/sys/linux/sys/syscall.lo core/sys/linux/sys/sysinfo.lo \ + core/sys/linux/sys/time.lo core/sys/linux/sys/xattr.lo \ + core/sys/linux/syscall.lo core/sys/linux/termios.lo \ core/sys/linux/time.lo core/sys/linux/timerfd.lo \ core/sys/linux/tipc.lo core/sys/linux/uinput.lo \ core/sys/linux/unistd.lo @@ -981,8 +982,9 @@ DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \ core/sys/linux/sys/mman.d core/sys/linux/sys/mount.d \ core/sys/linux/sys/prctl.d core/sys/linux/sys/procfs.d \ core/sys/linux/sys/signalfd.d core/sys/linux/sys/socket.d \ - core/sys/linux/sys/sysinfo.d core/sys/linux/sys/time.d \ - core/sys/linux/sys/xattr.d core/sys/linux/termios.d \ + core/sys/linux/sys/syscall.d core/sys/linux/sys/sysinfo.d \ + core/sys/linux/sys/time.d core/sys/linux/sys/xattr.d \ + core/sys/linux/syscall.d core/sys/linux/termios.d \ core/sys/linux/time.d core/sys/linux/timerfd.d core/sys/linux/tipc.d \ core/sys/linux/uinput.d core/sys/linux/unistd.d @@ -1756,9 +1758,11 @@ core/sys/linux/sys/prctl.lo: core/sys/linux/sys/$(am__dirstamp) core/sys/linux/sys/procfs.lo: core/sys/linux/sys/$(am__dirstamp) core/sys/linux/sys/signalfd.lo: core/sys/linux/sys/$(am__dirstamp) core/sys/linux/sys/socket.lo: core/sys/linux/sys/$(am__dirstamp) +core/sys/linux/sys/syscall.lo: core/sys/linux/sys/$(am__dirstamp) core/sys/linux/sys/sysinfo.lo: core/sys/linux/sys/$(am__dirstamp) core/sys/linux/sys/time.lo: core/sys/linux/sys/$(am__dirstamp) core/sys/linux/sys/xattr.lo: core/sys/linux/sys/$(am__dirstamp) +core/sys/linux/syscall.lo: core/sys/linux/$(am__dirstamp) core/sys/linux/termios.lo: core/sys/linux/$(am__dirstamp) core/sys/linux/time.lo: core/sys/linux/$(am__dirstamp) core/sys/linux/timerfd.lo: core/sys/linux/$(am__dirstamp) diff --git a/libphobos/libdruntime/core/int128.d b/libphobos/libdruntime/core/int128.d index 27c8b99d2cbf..b1247891e69c 100644 --- a/libphobos/libdruntime/core/int128.d +++ b/libphobos/libdruntime/core/int128.d @@ -36,6 +36,12 @@ else else private enum Cent_alignment = (size_t.sizeof * 2); } +version (X86_64) +{ + version (GNU) version = GNU_OR_LDC_X86_64; + version (LDC) version = GNU_OR_LDC_X86_64; +} + /** * 128 bit integer type. * See_also: $(REF Int128, std,int128). @@ -189,10 +195,8 @@ Cent sar1(Cent c) */ pure Cent shl(Cent c, uint n) +in (n < Ubits * 2) { - if (n >= Ubits * 2) - return Zero; - if (n >= Ubits) { c.hi = c.lo << (n - Ubits); @@ -216,10 +220,8 @@ Cent shl(Cent c, uint n) */ pure Cent shr(Cent c, uint n) +in (n < Ubits * 2) { - if (n >= Ubits * 2) - return Zero; - if (n >= Ubits) { c.lo = c.hi >> (n - Ubits); @@ -243,18 +245,13 @@ Cent shr(Cent c, uint n) */ pure Cent sar(Cent c, uint n) +in (n < Ubits * 2) { const signmask = -(c.hi >> (Ubits - 1)); const signshift = (Ubits * 2) - n; c = shr(c, n); - // Sign extend all bits beyond the precision of Cent. - if (n >= Ubits * 2) - { - c.hi = signmask; - c.lo = signmask; - } - else if (signshift >= Ubits * 2) + if (signshift == Ubits * 2) { } else if (signshift >= Ubits) @@ -317,6 +314,8 @@ pure Cent rol(Cent c, uint n) { n &= Ubits * 2 - 1; + if (n == 0) + return c; Cent l = shl(c, n); Cent r = shr(c, Ubits * 2 - n); return or(l, r); @@ -334,6 +333,8 @@ pure Cent ror(Cent c, uint n) { n &= Ubits * 2 - 1; + if (n == 0) + return c; Cent r = shr(c, n); Cent l = shl(c, Ubits * 2 - n); return or(r, l); @@ -458,6 +459,55 @@ Cent mul(Cent c1, Cent c2) return ret; } +/**************************** + * Multiply 64-bit operands u1 * u2 in 128-bit precision. + * Params: + * u1 = operand 1 + * u2 = operand 2 + * Returns: + * u1 * u2 in 128-bit precision + */ +pure +Cent mul(ulong u1, ulong u2) +{ + if (!__ctfe) + { + version (GNU_OR_LDC_X86_64) + { + Cent ret = void; + asm pure @trusted nothrow @nogc + { + "mulq %3" + : "=a"(ret.lo), "=d"(ret.hi) + : "a"(u1), "r"(u2) + : "cc"; + } + return ret; + } + else version (D_InlineAsm_X86_64) + { + U lo = void; + U hi = void; + asm pure @trusted nothrow @nogc + { + mov RAX, u1; + mul u2; + mov lo, RAX; + mov hi, RDX; + } + return Cent(lo: lo, hi: hi); + } + } + + return mul(Cent(lo: u1), Cent(lo: u2)); +} + +unittest +{ + assert(mul(3, 42) == Cent(lo: 126)); + assert(mul(1L << 60, 1 << 10) == Cent(hi: 1 << 6)); +} + /**************************** * Unsigned divide c1 / c2. @@ -490,63 +540,6 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus) // Based on "Unsigned Doubleword Division" in Hacker's Delight import core.bitop; - // Divides a 128-bit dividend by a 64-bit divisor. - // The result must fit in 64 bits. - static U udivmod128_64(Cent c1, U c2, out U modulus) - { - // We work in base 2^^32 - enum base = 1UL << 32; - enum divmask = (1UL << (Ubits / 2)) - 1; - enum divshift = Ubits / 2; - - // Check for overflow and divide by 0 - if (c1.hi >= c2) - { - modulus = 0UL; - return ~0UL; - } - - // Computes [num1 num0] / den - static uint udiv96_64(U num1, uint num0, U den) - { - // Extract both digits of the denominator - const den1 = cast(uint)(den >> divshift); - const den0 = cast(uint)(den & divmask); - // Estimate ret as num1 / den1, and then correct it - U ret = num1 / den1; - const t2 = (num1 % den1) * base + num0; - const t1 = ret * den0; - if (t1 > t2) - ret -= (t1 - t2 > den) ? 2 : 1; - return cast(uint)ret; - } - - // Determine the normalization factor. We multiply c2 by this, so that its leading - // digit is at least half base. In binary this means just shifting left by the number - // of leading zeros, so that there's a 1 in the MSB. - // We also shift number by the same amount. This cannot overflow because c1.hi < c2. - const shift = (Ubits - 1) - bsr(c2); - c2 <<= shift; - U num2 = c1.hi; - num2 <<= shift; - num2 |= (c1.lo >> (-shift & 63)) & (-cast(I)shift >> 63); - c1.lo <<= shift; - - // Extract the low digits of the numerator (after normalizing) - const num1 = cast(uint)(c1.lo >> divshift); - const num0 = cast(uint)(c1.lo & divmask); - - // Compute q1 = [num2 num1] / c2 - const q1 = udiv96_64(num2, num1, c2); - // Compute the true (partial) remainder - const rem = num2 * base + num1 - q1 * c2; - // Compute q0 = [rem num0] / c2 - const q0 = udiv96_64(rem, num0, c2); - - modulus = (rem * base + num0 - q0 * c2) >> shift; - return (cast(U)q1 << divshift) | q0; - } - // Special cases if (!tst(c2)) { @@ -576,7 +569,7 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus) if (q1) c1.hi = c1.hi % c2.lo; Cent rem; - const q0 = udivmod128_64(c1, c2.lo, rem.lo); + const q0 = udivmod(c1, c2.lo, rem.lo); modulus = rem; const Cent ret = { lo:q0, hi:q1 }; return ret; @@ -597,7 +590,7 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus) // Get quotient from divide unsigned operation. U rem_ignored; - const Cent q1 = { lo:udivmod128_64(u1, v1, rem_ignored) }; + const Cent q1 = { lo:udivmod(u1, v1, rem_ignored) }; // Undo normalization and division of c1 by 2. Cent quotient = shr(shl(q1, shift), 63); @@ -624,6 +617,107 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus) return quotient; } +/**************************** + * Unsigned divide 128-bit c1 / 64-bit c2. The result must fit in 64 bits. + * The remainder after division is stored to modulus. + * Params: + * c1 = dividend + * c2 = divisor + * modulus = set to c1 % c2 + * Returns: + * quotient c1 / c2 + */ +pure +U udivmod(Cent c1, U c2, out U modulus) +{ + import core.bitop; + + if (!__ctfe) + { + version (GNU_OR_LDC_X86_64) + { + U ret = void; + asm pure @trusted nothrow @nogc + { + "divq %4" + : "=a"(ret), "=d"(modulus) + : "a"(c1.lo), "d"(c1.hi), "r"(c2) + : "cc"; + } + return ret; + } + else version (D_InlineAsm_X86_64) + { + const lo = c1.lo; + const hi = c1.hi; + U mod = void; + U ret = void; + asm pure @trusted nothrow @nogc + { + mov RAX, lo; + mov RDX, hi; + div c2; + mov mod, RDX; // DMD bug: cannot use modulus directly + mov ret, RAX; + } + modulus = mod; + return ret; + } + } + + // We work in base 2^^32 + enum base = 1UL << 32; + enum divmask = (1UL << (Ubits / 2)) - 1; + enum divshift = Ubits / 2; + + // Check for overflow and divide by 0 + if (c1.hi >= c2) + { + modulus = 0UL; + return ~0UL; + } + + // Computes [num1 num0] / den + static uint udiv96_64(U num1, uint num0, U den) + { + // Extract both digits of the denominator + const den1 = cast(uint)(den >> divshift); + const den0 = cast(uint)(den & divmask); + // Estimate ret as num1 / den1, and then correct it + U ret = num1 / den1; + const t2 = (num1 % den1) * base + num0; + const t1 = ret * den0; + if (t1 > t2) + ret -= (t1 - t2 > den) ? 2 : 1; + return cast(uint)ret; + } + + // Determine the normalization factor. We multiply c2 by this, so that its leading + // digit is at least half base. In binary this means just shifting left by the number + // of leading zeros, so that there's a 1 in the MSB. + // We also shift number by the same amount. This cannot overflow because c1.hi < c2. + const shift = (Ubits - 1) - bsr(c2); + c2 <<= shift; + U num2 = c1.hi; + num2 <<= shift; + num2 |= (c1.lo >> (-shift & 63)) & (-cast(I)shift >> 63); + c1.lo <<= shift; + + // Extract the low digits of the numerator (after normalizing) + const num1 = cast(uint)(c1.lo >> divshift); + const num0 = cast(uint)(c1.lo & divmask); + + // Compute q1 = [num2 num1] / c2 + const q1 = udiv96_64(num2, num1, c2); + // Compute the true (partial) remainder + const rem = num2 * base + num1 - q1 * c2; + // Compute q0 = [rem num0] / c2 + const q0 = udiv96_64(rem, num0, c2); + + modulus = (rem * base + num0 - q0 * c2) >> shift; + return (cast(U)q1 << divshift) | q0; +} + /**************************** * Signed divide c1 / c2. @@ -893,18 +987,14 @@ unittest assert(shl(C10,0) == C10); assert(shl(C10,Ubits) == C10_0); assert(shl(C10,1) == C20); - assert(shl(C10,Ubits * 2) == C0); assert(shr(C10_0,0) == C10_0); assert(shr(C10_0,Ubits) == C10); assert(shr(C10_0,Ubits - 1) == C20); assert(shr(C10_0,Ubits + 1) == C5); - assert(shr(C10_0,Ubits * 2) == C0); assert(sar(C10_0,0) == C10_0); assert(sar(C10_0,Ubits) == C10); assert(sar(C10_0,Ubits - 1) == C20); assert(sar(C10_0,Ubits + 1) == C5); - assert(sar(C10_0,Ubits * 2) == C0); - assert(sar(Cm1,Ubits * 2) == Cm1); assert(shl1(C10) == C20); assert(shr1(C10_0) == C5_0); @@ -916,7 +1006,6 @@ unittest assert(udiv(C10,C2) == C5); assert(udivmod(C10,C2, modulus) == C5); assert(modulus == C0); assert(udivmod(C10,C3, modulus) == C3); assert(modulus == C1); - assert(udivmod(C10,C0, modulus) == Cm1); assert(modulus == C0); assert(udivmod(C2,C90_30, modulus) == C0); assert(modulus == C2); assert(udiv(mul(C90_30, C2), C2) == C90_30); assert(udiv(mul(C90_30, C2), C90_30) == C2); @@ -961,4 +1050,6 @@ unittest assert(rol(ror(C7_9, 5), 5) == C7_9); assert(rol(C7_9, 1) == rol1(C7_9)); assert(ror(C7_9, 1) == ror1(C7_9)); + assert(rol(C7_9, 0) == C7_9); + assert(ror(C7_9, 0) == C7_9); } diff --git a/libphobos/libdruntime/core/internal/array/capacity.d b/libphobos/libdruntime/core/internal/array/capacity.d index 10ce2c65c958..11bd357d7c27 100644 --- a/libphobos/libdruntime/core/internal/array/capacity.d +++ b/libphobos/libdruntime/core/internal/array/capacity.d @@ -9,64 +9,314 @@ */ module core.internal.array.capacity; -// HACK: `nothrow` and `pure` is faked. -private extern (C) void[] _d_arraysetlengthT(const TypeInfo ti, size_t newlength, void[]* p) nothrow pure; -private extern (C) void[] _d_arraysetlengthiT(const TypeInfo ti, size_t newlength, void[]* p) nothrow pure; - -/* - * This template is needed because there need to be a `_d_arraysetlengthTTrace!Tarr` instance for every - * `_d_arraysetlengthT!Tarr`. By wrapping both of these functions inside of this template we force the - * compiler to create a instance of both function for every type that is used. - */ - -/// Implementation of `_d_arraysetlengthT` and `_d_arraysetlengthTTrace` -template _d_arraysetlengthTImpl(Tarr : T[], T) +debug (PRINTF) import core.stdc.stdio : printf; +debug (VALGRIND) import etc.valgrind.valgrind; + +// for now, all GC array functions are not exposed via core.memory. +extern(C) { + bool gc_expandArrayUsed(void[] slice, size_t newUsed, bool atomic) nothrow pure; + size_t gc_reserveArrayCapacity(void[] slice, size_t request, bool atomic) nothrow pure; + bool gc_shrinkArrayUsed(void[] slice, size_t existingUsed, bool atomic) nothrow pure; +} +/** +Set the array capacity. + +If the array capacity isn't currently large enough +to hold the requested capacity (in number of elements), then the array is +resized/reallocated to the appropriate size. + +Pass in a requested capacity of 0 to get the current capacity. + +Params: + T = the type of the elements in the array (this should be unqualified) + newcapacity = requested new capacity + p = pointer to array to set. Its `length` is left unchanged. + isshared = true if the underlying data is shared + +Returns: the number of elements that can actually be stored once the resizing is done +*/ +size_t _d_arraysetcapacityPureNothrow(T)(size_t newcapacity, void[]* p, bool isshared) pure nothrow @trusted +do +{ + alias PureNothrowType = size_t function(size_t, void[]*, bool) pure nothrow @trusted; + return (cast(PureNothrowType) &_d_arraysetcapacity!T)(newcapacity, p, isshared); +} + +size_t _d_arraysetcapacity(T)(size_t newcapacity, void[]* p, bool isshared) @trusted +in +{ + assert(!(*p).length || (*p).ptr); +} +do +{ + import core.checkedint : mulu; + import core.exception : onOutOfMemoryError; + import core.stdc.string : memcpy, memset; + import core.internal.array.utils: __typeAttrs; + import core.internal.lifetime : __doPostblit; + + import core.memory : GC; + + alias BlkAttr = GC.BlkAttr; + + auto size = T.sizeof; + bool overflow = false; + const reqsize = mulu(size, newcapacity, overflow); + if (overflow) + { + onOutOfMemoryError(); + assert(0); + } + + // step 1, see if we can ensure the capacity is valid in-place + auto datasize = (*p).length * size; + auto curCapacity = gc_reserveArrayCapacity((*p).ptr[0 .. datasize], reqsize, isshared); + if (curCapacity != 0) // in-place worked! + return curCapacity / size; + + if (reqsize <= datasize) // requested size is less than array size, the current array satisfies + // the request. But this is not an appendable GC array, so return 0. + return 0; + + // step 2, if reserving in-place doesn't work, allocate a new array with at + // least the requested allocated size. + auto attrs = __typeAttrs!T((*p).ptr) | BlkAttr.APPENDABLE; + + // use this static enum to avoid recomputing TypeInfo for every call. + static enum ti = typeid(T); + auto ptr = GC.malloc(reqsize, attrs, ti); + if (ptr is null) + { + onOutOfMemoryError(); + assert(0); + } + + // copy the data over. + // note that malloc will have initialized the data we did not request to 0. + memcpy(ptr, (*p).ptr, datasize); + + // handle postblit + __doPostblit!T(cast(T[])ptr[0 .. datasize]); + + if (!(attrs & BlkAttr.NO_SCAN)) + { + // need to memset the newly requested data, except for the data that + // malloc returned that we didn't request. + void* endptr = ptr + reqsize; + void* begptr = ptr + datasize; + + // sanity check + assert(endptr >= begptr); + memset(begptr, 0, endptr - begptr); + } + + *p = ptr[0 .. (*p).length]; + + // set up the correct length. Note that we need to do this here, because + // the GC malloc will automatically set the used size to what we requested. + gc_shrinkArrayUsed(ptr[0 .. datasize], reqsize, isshared); + + curCapacity = gc_reserveArrayCapacity(ptr[0 .. datasize], 0, isshared); + assert(curCapacity); + return curCapacity / size; +} + +/** +Resize a dynamic array by setting its `.length` property. + +Newly created elements are initialized based on their default value. +If the array's elements initialize to `0`, memory is zeroed out. Otherwise, elements are explicitly initialized. + +This function handles memory allocation, expansion, and initialization while maintaining array integrity. + +--- +void main() +{ + int[] a = [1, 2]; + a.length = 3; // Gets lowered to `_d_arraysetlengthT!(int)(a, 3, false)` +} +--- + +Params: + arr = The array to resize. + newlength = The new value for the array's `.length`. + +Returns: + The resized array with updated length and properly initialized elements. + +Throws: + OutOfMemoryError if allocation fails. +*/ +size_t _d_arraysetlengthT(Tarr : T[], T)(return ref scope Tarr arr, size_t newlength) @trusted +{ + import core.internal.traits : Unqual; + + // Check if the type is shared + enum isShared = is(T == shared); + + // Unqualify the type to remove `const`, `immutable`, `shared`, etc. + alias UnqT = Unqual!T; + + // Cast the array to the unqualified type + auto unqual_arr = cast(UnqT[]) arr; + + // Call the implementation with the unqualified array and sharedness flag + size_t result = _d_arraysetlengthT_(unqual_arr, newlength, isShared); + + arr = cast(Tarr) unqual_arr; + // Return the result + return result; +} + +private size_t _d_arraysetlengthT_(Tarr : T[], T)(return ref scope Tarr arr, size_t newlength, bool isShared) @trusted { - private enum errorMessage = "Cannot resize arrays if compiling without support for runtime type information!"; - - /** - * Resize dynamic array - * Params: - * arr = the array that will be resized, taken as a reference - * newlength = new length of array - * Returns: - * The new length of the array - * Bugs: - * The safety level of this function is faked. It shows itself as `@trusted pure nothrow` to not break existing code. - */ - size_t _d_arraysetlengthT(return scope ref Tarr arr, size_t newlength) @trusted pure nothrow + import core.checkedint : mulu; + import core.exception : onFinalizeError, onOutOfMemoryError; + import core.stdc.string : memcpy, memset; + import core.internal.traits : hasElaborateCopyConstructor, Unqual; + import core.lifetime : emplace; + import core.memory; + import core.internal.lifetime : __doPostblit; + + alias BlkAttr = GC.BlkAttr; + alias UnqT = Unqual!T; + + debug(PRINTF) + { + printf("_d_arraysetlengthT(arr.ptr = %p, arr.length = %zd, newlength = %zd)\n", + arr.ptr, arr.length, newlength); + } + + // If the new length is less than or equal to the current length, just truncate the array + if (newlength <= arr.length) + { + arr = arr[0 .. newlength]; + return newlength; + } + + enum sizeelem = T.sizeof; + enum hasPostblit = __traits(hasMember, T, "__postblit"); + enum hasEnabledPostblit = hasPostblit && !__traits(isDisabled, T.__postblit); + + bool overflow = false; + const newsize = mulu(sizeelem, newlength, overflow); + if (overflow) { - version (DigitalMars) pragma(inline, false); - version (D_TypeInfo) + onOutOfMemoryError(); + assert(0); + } + + debug(PRINTF) printf("newsize = %zx\n", newsize); + + uint gcAttrs = BlkAttr.APPENDABLE; + static if (is(T == struct) && __traits(hasMember, T, "xdtor")) + { + gcAttrs |= BlkAttr.FINALIZE; + } + + if (!arr.ptr) + { + assert(arr.length == 0); + void* ptr = GC.malloc(newsize, gcAttrs); + if (!ptr) + { + onOutOfMemoryError(); + assert(0); + } + + static if (__traits(isZeroInit, T)) + { + memset(ptr, 0, newsize); + } + else static if (hasElaborateCopyConstructor!T && !hasPostblit) { - auto ti = typeid(Tarr); + foreach (i; 0 .. newlength) + emplace(cast(UnqT*) ptr + i, UnqT.init); // safe default construction + } + else + { + auto temp = UnqT.init; + foreach (i; 0 .. newlength) + memcpy(cast(UnqT*) ptr + i, cast(const void*)&temp, T.sizeof); + + static if (hasEnabledPostblit) + __doPostblit!T((cast(T*) ptr)[0 .. newlength]); + } + + arr = (cast(T*) ptr)[0 .. newlength]; + return newlength; + } - static if (__traits(isZeroInit, T)) - ._d_arraysetlengthT(ti, newlength, cast(void[]*)&arr); - else - ._d_arraysetlengthiT(ti, newlength, cast(void[]*)&arr); + size_t oldsize = arr.length * sizeelem; - return arr.length; + auto newdata = cast(void*) arr.ptr; + + if (!gc_expandArrayUsed(newdata[0 .. oldsize], newsize, isShared)) + { + newdata = GC.malloc(newsize, gcAttrs); + if (!newdata) + { + onOutOfMemoryError(); + assert(0); + } + static if (hasElaborateCopyConstructor!T && !hasPostblit) + { + // Use emplace for types with copy constructors but not postblit + foreach (i; 0 .. arr.length) + emplace(cast(UnqT*)newdata + i, arr[i]); // safe copy } else - assert(0, errorMessage); + { + memcpy(newdata, cast(const(void)*)arr.ptr, oldsize); + + // Postblit handling for types with postblit, but ensure it compiles + static if (hasEnabledPostblit) + __doPostblit!T((cast(T*) (cast(ubyte*)newdata))[0 .. arr.length]); + } + } + + // Handle initialization based on whether the type requires zero-init + static if (__traits(isZeroInit, T)) + memset(cast(void*) (cast(ubyte*)newdata + oldsize), 0, newsize - oldsize); + else static if (hasElaborateCopyConstructor!T && !hasPostblit) + { + foreach (i; 0 .. newlength - arr.length) + emplace(cast(UnqT*) (cast(ubyte*)newdata + oldsize) + i, UnqT.init); + } + else + { + auto temp = UnqT.init; + foreach (i; 0 .. newlength - arr.length) + memcpy(cast(UnqT*) (cast(ubyte*)newdata + oldsize) + i, cast(const void*)&temp, T.sizeof); + + static if (hasEnabledPostblit) + __doPostblit!T((cast(T*) (cast(ubyte*)newdata + oldsize))[0 .. newlength - arr.length]); } - version (D_ProfileGC) + arr = (cast(T*) newdata)[0 .. newlength]; + return newlength; +} + +version (D_ProfileGC) +{ + enum errorMessage = "Cannot resize arrays"; + import core.internal.array.utils : _d_HookTraceImpl; + + // Function wrapper around the hook, so it’s callable + size_t _d_arraysetlengthTTrace(Tarr : T[], T)( + return ref scope Tarr arr, + size_t newlength, + string file = __FILE__, + int line = __LINE__, + string func = __FUNCTION__ + ) @trusted { - import core.internal.array.utils : _d_HookTraceImpl; - - /** - * TraceGC wrapper around $(REF _d_arraysetlengthT, core,internal,array,core.internal.array.capacity). - * Bugs: - * This function template was ported from a much older runtime hook that bypassed safety, - * purity, and throwabilty checks. To prevent breaking existing code, this function template - * is temporarily declared `@trusted pure nothrow` until the implementation can be brought up to modern D expectations. - */ - alias _d_arraysetlengthTTrace = _d_HookTraceImpl!(Tarr, _d_arraysetlengthT, errorMessage); + alias Hook = _d_HookTraceImpl!(Tarr, _d_arraysetlengthT!Tarr, errorMessage); + return Hook(arr, newlength, file, line, func); } } +// @safe unittest remains intact @safe unittest { struct S @@ -75,13 +325,13 @@ template _d_arraysetlengthTImpl(Tarr : T[], T) } int[] arr; - _d_arraysetlengthTImpl!(typeof(arr))._d_arraysetlengthT(arr, 16); + _d_arraysetlengthT!(typeof(arr))(arr, 16); assert(arr.length == 16); foreach (int i; arr) assert(i == int.init); shared S[] arr2; - _d_arraysetlengthTImpl!(typeof(arr2))._d_arraysetlengthT(arr2, 16); + _d_arraysetlengthT!(typeof(arr2))(arr2, 16); assert(arr2.length == 16); foreach (s; arr2) assert(s == S.init); diff --git a/libphobos/libdruntime/core/internal/array/concatenation.d b/libphobos/libdruntime/core/internal/array/concatenation.d index 13ec5fad40fd..fab2a5a9b7c1 100644 --- a/libphobos/libdruntime/core/internal/array/concatenation.d +++ b/libphobos/libdruntime/core/internal/array/concatenation.d @@ -19,7 +19,8 @@ module core.internal.array.concatenation; */ Tret _d_arraycatnTX(Tret, Tarr...)(auto ref Tarr froms) @trusted { - import core.internal.array.capacity : _d_arraysetlengthTImpl; + import core.exception : onOutOfMemoryError; + import core.internal.array.utils : __arrayAlloc; import core.internal.traits : hasElaborateCopyConstructor, Unqual; import core.lifetime : copyEmplace; import core.stdc.string : memcpy; @@ -27,37 +28,27 @@ Tret _d_arraycatnTX(Tret, Tarr...)(auto ref Tarr froms) @trusted Tret res; size_t totalLen; - alias T = typeof(res[0]); - enum elemSize = T.sizeof; - enum hasPostblit = __traits(hasPostblit, T); + alias T = typeof(res[0]); // Element type of the result array + alias UnqT = Unqual!T; // Unqualified version of T (strips const/immutable) + enum elemSize = T.sizeof; // Size of each element + enum hasPostblit = __traits(hasPostblit, T); // Whether T has a postblit constructor + // Compute total length of the resulting array static foreach (from; froms) - static if (is (typeof(from) : T)) - totalLen++; + static if (is(typeof(from) : T)) + totalLen++; // Single element contributes one to length else - totalLen += from.length; + totalLen += from.length; // Arrays contribute their full length if (totalLen == 0) - return res; + return res; // Return an empty array if no elements are present - // We cannot use this, because it refuses to work if the array type has disabled default construction. - // res.length = totalLen; - // Call the runtime function directly instead. - // TODO: once `__arrayAlloc` is templated, call that instead. - version (D_ProfileGC) - { - // TODO: forward file, line, name from _d_arraycatnTXTrace - _d_arraysetlengthTImpl!(typeof(res))._d_arraysetlengthTTrace( - res, totalLen, __FILE__, __LINE__, __FUNCTION__); - } - else - { - _d_arraysetlengthTImpl!(typeof(res))._d_arraysetlengthT(res, totalLen); - } + // Allocate memory for mutable arrays using __arrayAlloc + res = cast(Tret) __arrayAlloc!(UnqT)(elemSize * totalLen); + + if (res.ptr is null) + onOutOfMemoryError(); // Abort if allocation fails - /* Currently, if both a postblit and a cpctor are defined, the postblit is - * used. If this changes, the condition below will have to be adapted. - */ static if (hasElaborateCopyConstructor!T && !hasPostblit) { size_t i = 0; @@ -73,16 +64,16 @@ Tret _d_arraycatnTX(Tret, Tarr...)(auto ref Tarr froms) @trusted } else { - auto resptr = cast(Unqual!T *) res; + auto resptr = cast(UnqT *) res; foreach (ref from; froms) static if (is (typeof(from) : T)) - memcpy(resptr++, cast(Unqual!T *) &from, elemSize); + memcpy(resptr++, cast(UnqT *) &from, elemSize); else { const len = from.length; if (len) { - memcpy(resptr, cast(Unqual!T *) from, len * elemSize); + memcpy(resptr, cast(UnqT *) from, len * elemSize); resptr += len; } } diff --git a/libphobos/libdruntime/core/internal/array/construction.d b/libphobos/libdruntime/core/internal/array/construction.d index 40e5a61bbded..76811ef3ffd0 100644 --- a/libphobos/libdruntime/core/internal/array/construction.d +++ b/libphobos/libdruntime/core/internal/array/construction.d @@ -505,7 +505,7 @@ version (D_ProfileGC) * Returns: * newly allocated array */ -Tarr _d_newarraymTX(Tarr : U[], T, U)(size_t[] dims, bool isShared=false) @trusted +Tarr _d_newarraymTX(Tarr : U[], T, U)(scope size_t[] dims, bool isShared=false) @trusted { debug(PRINTF) printf("_d_newarraymTX(dims.length = %zd)\n", dims.length); @@ -520,7 +520,7 @@ Tarr _d_newarraymTX(Tarr : U[], T, U)(size_t[] dims, bool isShared=false) @trust auto dim = dims[0]; - debug(PRINTF) printf("__allocateInnerArray(UnqT = %s, dim = %lu, ndims = %lu\n", UnqT.stringof.ptr, dim, dims.length); + debug(PRINTF) printf("__allocateInnerArray(UnqT = %s, dim = %u, ndims = %u)\n", UnqT.stringof.ptr, cast(uint)dim, cast(uint)dims.length); if (dims.length == 1) { auto r = _d_newarrayT!UnqT(dim, isShared); @@ -602,7 +602,7 @@ version (D_ProfileGC) /** * TraceGC wrapper around $(REF _d_newarraymT, core,internal,array,construction). */ - Tarr _d_newarraymTXTrace(Tarr : U[], T, U)(size_t[] dims, bool isShared=false, string file = __FILE__, int line = __LINE__, string funcname = __FUNCTION__) @trusted + Tarr _d_newarraymTXTrace(Tarr : U[], T, U)(scope size_t[] dims, bool isShared=false, string file = __FILE__, int line = __LINE__, string funcname = __FUNCTION__) @trusted { version (D_TypeInfo) { diff --git a/libphobos/libdruntime/core/internal/array/utils.d b/libphobos/libdruntime/core/internal/array/utils.d index deaae3f95da6..1d105e6ebf19 100644 --- a/libphobos/libdruntime/core/internal/array/utils.d +++ b/libphobos/libdruntime/core/internal/array/utils.d @@ -156,3 +156,28 @@ void[] __arrayAlloc(T)(size_t arrSize) @trusted return ptr[0 .. arrSize]; return null; } + +uint __typeAttrs(T)(void *copyAttrsFrom = null) +{ + import core.internal.traits : hasIndirections, hasElaborateDestructor; + import core.memory : GC; + + alias BlkAttr = GC.BlkAttr; + + if (copyAttrsFrom) + { + // try to copy attrs from the given block + auto info = GC.query(copyAttrsFrom); + if (info.base) + return info.attr; + } + + uint attrs = 0; + static if (!hasIndirections!T) + attrs |= BlkAttr.NO_SCAN; + + static if (is(T == struct) && hasElaborateDestructor!T) + attrs |= BlkAttr.FINALIZE; + + return attrs; +} diff --git a/libphobos/libdruntime/core/internal/lifetime.d b/libphobos/libdruntime/core/internal/lifetime.d index a7446debae65..fd78de221d11 100644 --- a/libphobos/libdruntime/core/internal/lifetime.d +++ b/libphobos/libdruntime/core/internal/lifetime.d @@ -202,3 +202,22 @@ void swap(T)(ref T lhs, ref T rhs) moveEmplace(rhs, lhs); moveEmplace(tmp, rhs); } + +void __doPostblit(T)(T[] arr) +{ + // infer static postblit type, run postblit if any + static if (__traits(hasPostblit, T)) + { + static if (__traits(isStaticArray, T) && is(T : E[], E)) + __doPostblit(cast(E[]) arr); + else static if (!__traits(compiles, arr[0].__xpostblit)) + { + alias Unqual_T = Unqual!T; + foreach (ref elem; (() @trusted => cast(Unqual_T[]) arr)()) + elem.__xpostblit(); + } + else + foreach (ref elem; arr) + elem.__xpostblit(); + } +} diff --git a/libphobos/libdruntime/core/stdc/fenv.d b/libphobos/libdruntime/core/stdc/fenv.d index ce77d5c1e6b2..7d42d5c8c023 100644 --- a/libphobos/libdruntime/core/stdc/fenv.d +++ b/libphobos/libdruntime/core/stdc/fenv.d @@ -440,6 +440,11 @@ else version (CRuntime_Musl) } alias uint fexcept_t; } + else version (RICV64) + { + alias uint fenv_t; + alias uint fexcept_t; + } else { static assert(false, "Architecture not supported."); diff --git a/libphobos/libdruntime/core/stdc/math.d b/libphobos/libdruntime/core/stdc/math.d index 1f384f9cbd46..5b78d6f61f36 100644 --- a/libphobos/libdruntime/core/stdc/math.d +++ b/libphobos/libdruntime/core/stdc/math.d @@ -1509,51 +1509,51 @@ extern (D) { //int isgreater(real-floating x, real-floating y); /// - pure int isgreater(float x, float y) { return x > y; } + pure int isgreater()(float x, float y) { return x > y; } /// - pure int isgreater(double x, double y) { return x > y; } + pure int isgreater()(double x, double y) { return x > y; } /// - pure int isgreater(real x, real y) { return x > y; } + pure int isgreater()(real x, real y) { return x > y; } //int isgreaterequal(real-floating x, real-floating y); /// - pure int isgreaterequal(float x, float y) { return x >= y; } + pure int isgreaterequal()(float x, float y) { return x >= y; } /// - pure int isgreaterequal(double x, double y) { return x >= y; } + pure int isgreaterequal()(double x, double y) { return x >= y; } /// - pure int isgreaterequal(real x, real y) { return x >= y; } + pure int isgreaterequal()(real x, real y) { return x >= y; } //int isless(real-floating x, real-floating y); /// - pure int isless(float x, float y) { return x < y; } + pure int isless()(float x, float y) { return x < y; } /// - pure int isless(double x, double y) { return x < y; } + pure int isless()(double x, double y) { return x < y; } /// - pure int isless(real x, real y) { return x < y; } + pure int isless()(real x, real y) { return x < y; } //int islessequal(real-floating x, real-floating y); /// - pure int islessequal(float x, float y) { return x <= y; } + pure int islessequal()(float x, float y) { return x <= y; } /// - pure int islessequal(double x, double y) { return x <= y; } + pure int islessequal()(double x, double y) { return x <= y; } /// - pure int islessequal(real x, real y) { return x <= y; } + pure int islessequal()(real x, real y) { return x <= y; } //int islessgreater(real-floating x, real-floating y); /// - pure int islessgreater(float x, float y) { return x != y && !isunordered(x, y); } + pure int islessgreater()(float x, float y) { return x != y && !isunordered(x, y); } /// - pure int islessgreater(double x, double y) { return x != y && !isunordered(x, y); } + pure int islessgreater()(double x, double y) { return x != y && !isunordered(x, y); } /// - pure int islessgreater(real x, real y) { return x != y && !isunordered(x, y); } + pure int islessgreater()(real x, real y) { return x != y && !isunordered(x, y); } //int isunordered(real-floating x, real-floating y); /// - pure int isunordered(float x, float y) { return isnan(x) || isnan(y); } + pure int isunordered()(float x, float y) { return isnan(x) || isnan(y); } /// - pure int isunordered(double x, double y) { return isnan(x) || isnan(y); } + pure int isunordered()(double x, double y) { return isnan(x) || isnan(y); } /// - pure int isunordered(real x, real y) { return isnan(x) || isnan(y); } + pure int isunordered()(real x, real y) { return isnan(x) || isnan(y); } } /* MS define some functions inline. diff --git a/libphobos/libdruntime/core/stdc/stdarg.d b/libphobos/libdruntime/core/stdc/stdarg.d index 0ba1ebe34e38..c694dfb3ac3f 100644 --- a/libphobos/libdruntime/core/stdc/stdarg.d +++ b/libphobos/libdruntime/core/stdc/stdarg.d @@ -316,7 +316,7 @@ else version (LDC) } else version (DigitalMars) { - void va_end(va_list ap) {} + void va_end()(va_list ap) {} } diff --git a/libphobos/libdruntime/core/sys/bionic/err.d b/libphobos/libdruntime/core/sys/bionic/err.d index e2756e10c91b..a14f21bb1ec1 100644 --- a/libphobos/libdruntime/core/sys/bionic/err.d +++ b/libphobos/libdruntime/core/sys/bionic/err.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: Boost License 1.0. - * Authors: Ernesto Castellotti + * Authors: Emily Castellotti */ module core.sys.bionic.err; import core.stdc.stdarg : va_list; diff --git a/libphobos/libdruntime/core/sys/bionic/string.d b/libphobos/libdruntime/core/sys/bionic/string.d index 10a5610ac449..9430a7bab4e3 100644 --- a/libphobos/libdruntime/core/sys/bionic/string.d +++ b/libphobos/libdruntime/core/sys/bionic/string.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: Boost License 1.0. - * Authors: Ernesto Castellotti + * Authors: Emily Castellotti */ module core.sys.bionic.string; diff --git a/libphobos/libdruntime/core/sys/darwin/err.d b/libphobos/libdruntime/core/sys/darwin/err.d index d96c790f3b66..19b51626a167 100644 --- a/libphobos/libdruntime/core/sys/darwin/err.d +++ b/libphobos/libdruntime/core/sys/darwin/err.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: Boost License 1.0. - * Authors: Ernesto Castellotti + * Authors: Emily Castellotti */ module core.sys.darwin.err; import core.stdc.stdarg : va_list; diff --git a/libphobos/libdruntime/core/sys/darwin/string.d b/libphobos/libdruntime/core/sys/darwin/string.d index ac988b58f0d4..14bae215cde7 100644 --- a/libphobos/libdruntime/core/sys/darwin/string.d +++ b/libphobos/libdruntime/core/sys/darwin/string.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: Boost License 1.0. - * Authors: Ernesto Castellotti + * Authors: Emily Castellotti */ module core.sys.darwin.string; diff --git a/libphobos/libdruntime/core/sys/dragonflybsd/err.d b/libphobos/libdruntime/core/sys/dragonflybsd/err.d index c3693f85f5ea..7f7cf9467fa0 100644 --- a/libphobos/libdruntime/core/sys/dragonflybsd/err.d +++ b/libphobos/libdruntime/core/sys/dragonflybsd/err.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: Boost License 1.0. - * Authors: Ernesto Castellotti + * Authors: Emily Castellotti */ module core.sys.dragonflybsd.err; import core.stdc.stdarg : va_list; diff --git a/libphobos/libdruntime/core/sys/dragonflybsd/string.d b/libphobos/libdruntime/core/sys/dragonflybsd/string.d index 1a85ba606a19..c15bb9268e58 100644 --- a/libphobos/libdruntime/core/sys/dragonflybsd/string.d +++ b/libphobos/libdruntime/core/sys/dragonflybsd/string.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: Boost License 1.0. - * Authors: Ernesto Castellotti + * Authors: Emily Castellotti */ module core.sys.dragonflybsd.string; diff --git a/libphobos/libdruntime/core/sys/freebsd/err.d b/libphobos/libdruntime/core/sys/freebsd/err.d index 8937e0ec7057..5cb443a6f8a2 100644 --- a/libphobos/libdruntime/core/sys/freebsd/err.d +++ b/libphobos/libdruntime/core/sys/freebsd/err.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: Boost License 1.0. - * Authors: Ernesto Castellotti + * Authors: Emily Castellotti */ module core.sys.freebsd.err; import core.stdc.stdarg : va_list; diff --git a/libphobos/libdruntime/core/sys/freebsd/string.d b/libphobos/libdruntime/core/sys/freebsd/string.d index 459e9115878e..ba7b3c019d90 100644 --- a/libphobos/libdruntime/core/sys/freebsd/string.d +++ b/libphobos/libdruntime/core/sys/freebsd/string.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: Boost License 1.0. - * Authors: Ernesto Castellotti + * Authors: Emily Castellotti */ module core.sys.freebsd.string; diff --git a/libphobos/libdruntime/core/sys/linux/err.d b/libphobos/libdruntime/core/sys/linux/err.d index c3752de52070..d346a0805ff4 100644 --- a/libphobos/libdruntime/core/sys/linux/err.d +++ b/libphobos/libdruntime/core/sys/linux/err.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: Boost License 1.0. - * Authors: Ernesto Castellotti + * Authors: Emily Castellotti */ module core.sys.linux.err; import core.stdc.stdarg : va_list; diff --git a/libphobos/libdruntime/core/sys/linux/linux/if_packet.d b/libphobos/libdruntime/core/sys/linux/linux/if_packet.d index b50b6a339140..6dd95808d61c 100644 --- a/libphobos/libdruntime/core/sys/linux/linux/if_packet.d +++ b/libphobos/libdruntime/core/sys/linux/linux/if_packet.d @@ -169,7 +169,7 @@ struct tpacket_hdr } enum TPACKET_ALIGNMENT = 16; -size_t TPACKET_ALIGN(size_t x) { return (x + TPACKET_ALIGNMENT - 1) &~ (TPACKET_ALIGNMENT - 1); } +size_t TPACKET_ALIGN()(size_t x) { return (x + TPACKET_ALIGNMENT - 1) &~ (TPACKET_ALIGNMENT - 1); } enum TPACKET_HDRLEN = TPACKET_ALIGN(tpacket_hdr.sizeof) + sockaddr_ll.sizeof; struct tpacket2_hdr diff --git a/libphobos/libdruntime/core/sys/linux/netinet/in_.d b/libphobos/libdruntime/core/sys/linux/netinet/in_.d index 1b428f5aeccc..f3c23572fb2c 100644 --- a/libphobos/libdruntime/core/sys/linux/netinet/in_.d +++ b/libphobos/libdruntime/core/sys/linux/netinet/in_.d @@ -82,28 +82,28 @@ version (linux_libc) enum IPPORT_USERRESERVED = 5000; - extern(D) bool IN_CLASSA(in_addr_t i) pure @safe { return (i & 0x80000000) == 0; } + extern(D) bool IN_CLASSA()(in_addr_t i) pure @safe { return (i & 0x80000000) == 0; } enum IN_CLASSA_NET = 0xff000000; enum IN_CLASSA_NSHIFT = 24; enum IN_CLASSA_HOST = 0xffffffff & ~IN_CLASSA_NET; enum IN_CLASSA_MAX = 128; - extern(D) bool IN_CLASSB(in_addr_t i) pure @safe { return (i & 0xc0000000) == 0x80000000; } + extern(D) bool IN_CLASSB()(in_addr_t i) pure @safe { return (i & 0xc0000000) == 0x80000000; } enum IN_CLASSB_NET = 0xffff0000; enum IN_CLASSB_NSHIFT = 16; enum IN_CLASSB_HOST = 0xffffffff & ~IN_CLASSB_NET; enum IN_CLASSB_MAX = 65536; - extern(D) bool IN_CLASSC(in_addr_t i) pure @safe { return (i & 0xe0000000) == 0xc0000000; } + extern(D) bool IN_CLASSC()(in_addr_t i) pure @safe { return (i & 0xe0000000) == 0xc0000000; } enum IN_CLASSC_NET = 0xffffff00; enum IN_CLASSC_NSHIFT = 8; enum IN_CLASSC_HOST = 0xffffffff & ~IN_CLASSC_NET; - extern(D) bool IN_CLASSD(in_addr_t i) pure @safe { return (i & 0xf0000000) == 0xe0000000; } - extern(D) bool IN_MULTICAST(in_addr_t i) { return IN_CLASSD(i); } + extern(D) bool IN_CLASSD()(in_addr_t i) pure @safe { return (i & 0xf0000000) == 0xe0000000; } + extern(D) bool IN_MULTICAST()(in_addr_t i) { return IN_CLASSD(i); } - extern(D) bool IN_EXPERIMENTAL(in_addr_t i) pure @safe { return (i & 0xe0000000) == 0xe0000000; } - extern(D) bool IN_BADCLASS(in_addr_t i) pure @safe { return (i & 0xf0000000) == 0xf0000000; } + extern(D) bool IN_EXPERIMENTAL()(in_addr_t i) pure @safe { return (i & 0xe0000000) == 0xe0000000; } + extern(D) bool IN_BADCLASS()(in_addr_t i) pure @safe { return (i & 0xf0000000) == 0xf0000000; } enum IN_LOOPBACKNET = 127; diff --git a/libphobos/libdruntime/core/sys/linux/perf_event.d b/libphobos/libdruntime/core/sys/linux/perf_event.d index 0ad072974d5c..f8bedfb81bd9 100644 --- a/libphobos/libdruntime/core/sys/linux/perf_event.d +++ b/libphobos/libdruntime/core/sys/linux/perf_event.d @@ -13,82 +13,13 @@ nothrow: import core.sys.posix.sys.ioctl; import core.sys.posix.unistd; -version (HPPA) version = HPPA_Any; -version (HPPA64) version = HPPA_Any; -version (PPC) version = PPC_Any; -version (PPC64) version = PPC_Any; -version (RISCV32) version = RISCV_Any; -version (RISCV64) version = RISCV_Any; -version (S390) version = IBMZ_Any; -version (SPARC) version = SPARC_Any; -version (SPARC64) version = SPARC_Any; -version (SystemZ) version = IBMZ_Any; - -version (X86_64) -{ - version (D_X32) - enum __NR_perf_event_open = 0x40000000 + 298; - else - enum __NR_perf_event_open = 298; -} -else version (X86) -{ - enum __NR_perf_event_open = 336; -} -else version (ARM) -{ - enum __NR_perf_event_open = 364; -} -else version (AArch64) -{ - enum __NR_perf_event_open = 241; -} -else version (HPPA_Any) -{ - enum __NR_perf_event_open = 318; -} -else version (IBMZ_Any) -{ - enum __NR_perf_event_open = 331; -} -else version (MIPS32) -{ - enum __NR_perf_event_open = 4333; -} -else version (MIPS64) -{ - version (MIPS_N32) - enum __NR_perf_event_open = 6296; - else version (MIPS_N64) - enum __NR_perf_event_open = 5292; - else - static assert(0, "Architecture not supported"); -} -else version (PPC_Any) -{ - enum __NR_perf_event_open = 319; -} -else version (RISCV_Any) -{ - enum __NR_perf_event_open = 241; -} -else version (SPARC_Any) -{ - enum __NR_perf_event_open = 327; -} -else version (LoongArch64) -{ - enum __NR_perf_event_open = 241; -} -else -{ - static assert(0, "Architecture not supported"); -} -extern (C) extern long syscall(long __sysno, ...); static long perf_event_open(perf_event_attr* hw_event, pid_t pid, int cpu, int group_fd, ulong flags) { - return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); + import core.sys.linux.unistd : syscall; + import core.sys.linux.syscall : __NR_perf_event_open; + return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); } + /* * User-space ABI bits: */ diff --git a/libphobos/libdruntime/core/sys/linux/sched.d b/libphobos/libdruntime/core/sys/linux/sched.d index 5cd512e82630..0a940db65ed4 100644 --- a/libphobos/libdruntime/core/sys/linux/sched.d +++ b/libphobos/libdruntime/core/sys/linux/sched.d @@ -41,31 +41,31 @@ private // helpers /* Macros */ /* Basic access functions. */ - size_t __CPUELT(size_t cpu) pure + size_t __CPUELT()(size_t cpu) pure { return cpu / __NCPUBITS; } - cpu_mask __CPUMASK(size_t cpu) pure + cpu_mask __CPUMASK()(size_t cpu) pure { return 1UL << (cpu % __NCPUBITS); } - cpu_set_t* __CPU_ALLOC(size_t count) + cpu_set_t* __CPU_ALLOC()(size_t count) { return cast(cpu_set_t*) malloc(__CPU_ALLOC_SIZE(count)); } - size_t __CPU_ALLOC_SIZE(size_t count) pure + size_t __CPU_ALLOC_SIZE()(size_t count) pure { return ((count + __NCPUBITS - 1) / __NCPUBITS) * cpu_mask.sizeof; } - void __CPU_FREE(cpu_set_t* set) + void __CPU_FREE()(cpu_set_t* set) { free(cast(void*) set); } - cpu_mask __CPU_SET_S(size_t cpu, size_t setsize, cpu_set_t* cpusetp) pure + cpu_mask __CPU_SET_S()(size_t cpu, size_t setsize, cpu_set_t* cpusetp) pure { if (cpu < 8 * setsize) { @@ -76,14 +76,14 @@ private // helpers return 0; } - bool __CPU_ISSET_S(size_t cpu, size_t setsize, cpu_set_t* cpusetp) pure + bool __CPU_ISSET_S()(size_t cpu, size_t setsize, cpu_set_t* cpusetp) pure { if (cpu < 8 * setsize) return (cpusetp.__bits[__CPUELT(cpu)] & __CPUMASK(cpu)) != 0; return false; } - int __CPU_COUNT_S(size_t setsize, cpu_set_t* cpusetp) pure + int __CPU_COUNT_S()(size_t setsize, cpu_set_t* cpusetp) pure { int s = 0; foreach (i; cpusetp.__bits[0 .. (setsize / cpu_mask.sizeof)]) @@ -103,37 +103,37 @@ struct cpu_set_t /// Access macros for 'cpu_set' (missing a lot of them) -cpu_set_t* CPU_ALLOC(size_t count) +cpu_set_t* CPU_ALLOC()(size_t count) { return __CPU_ALLOC(count); } -size_t CPU_ALLOC_SIZE(size_t count) pure +size_t CPU_ALLOC_SIZE()(size_t count) pure { return __CPU_ALLOC_SIZE(count); } -void CPU_FREE(cpu_set_t* set) +void CPU_FREE()(cpu_set_t* set) { __CPU_FREE(set); } -cpu_mask CPU_SET(size_t cpu, cpu_set_t* cpusetp) pure +cpu_mask CPU_SET()(size_t cpu, cpu_set_t* cpusetp) pure { return __CPU_SET_S(cpu, cpu_set_t.sizeof, cpusetp); } -bool CPU_ISSET(size_t cpu, cpu_set_t* cpusetp) pure +bool CPU_ISSET()(size_t cpu, cpu_set_t* cpusetp) pure { return __CPU_ISSET_S(cpu, cpu_set_t.sizeof, cpusetp); } -int CPU_COUNT(cpu_set_t* cpusetp) pure +int CPU_COUNT()(cpu_set_t* cpusetp) pure { return __CPU_COUNT_S(cpu_set_t.sizeof, cpusetp); } -int CPU_COUNT_S(size_t setsize, cpu_set_t* cpusetp) pure +int CPU_COUNT_S()(size_t setsize, cpu_set_t* cpusetp) pure { return __CPU_COUNT_S(setsize, cpusetp); } diff --git a/libphobos/libdruntime/core/sys/linux/string.d b/libphobos/libdruntime/core/sys/linux/string.d index a8da39824612..7288231730d1 100644 --- a/libphobos/libdruntime/core/sys/linux/string.d +++ b/libphobos/libdruntime/core/sys/linux/string.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: Boost License 1.0. - * Authors: Ernesto Castellotti + * Authors: Emily Castellotti */ module core.sys.linux.string; diff --git a/libphobos/libdruntime/core/sys/linux/sys/syscall.d b/libphobos/libdruntime/core/sys/linux/sys/syscall.d new file mode 100644 index 000000000000..9e313e15c93d --- /dev/null +++ b/libphobos/libdruntime/core/sys/linux/sys/syscall.d @@ -0,0 +1,127 @@ +/** + * D header file for GNU/Linux + * + * $(LINK2 https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/sys/syscall.h, glibc sys/syscall.h) + */ + +module core.sys.linux.sys.syscall; + +version (linux): +extern (C): +@nogc: +nothrow: + +version (HPPA) version = HPPA_Any; +version (HPPA64) version = HPPA_Any; +version (PPC) version = PPC_Any; +version (PPC64) version = PPC_Any; +version (RISCV32) version = RISCV_Any; +version (RISCV64) version = RISCV_Any; +version (S390) version = IBMZ_Any; +version (SPARC) version = SPARC_Any; +version (SPARC64) version = SPARC_Any; +version (SystemZ) version = IBMZ_Any; + +/+ + Check out the following links for handy tables: + + - + - + +/ + +// +// List the numbers of the system calls the system knows. +version (X86_64) +{ + version (D_X32) + { + private enum __X32_SYSCALL_BIT = 0x40000000; + + enum __NR_getrandom = __X32_SYSCALL_BIT + 318; + enum __NR_perf_event_open = __X32_SYSCALL_BIT + 298; + } + else + { + enum __NR_getrandom = 318; + enum __NR_perf_event_open = 298; + } +} +else version (X86) +{ + enum __NR_getrandom = 355; + enum __NR_perf_event_open = 336; +} +else version (ARM) +{ + enum __NR_getrandom = 384; + enum __NR_perf_event_open = 364; +} +else version (AArch64) +{ + enum __NR_getrandom = 278; + enum __NR_perf_event_open = 241; +} +else version (HPPA_Any) +{ + enum __NR_getrandom = 339; + enum __NR_perf_event_open = 318; +} +else version (IBMZ_Any) +{ + enum __NR_getrandom = 349; + enum __NR_perf_event_open = 331; +} +else version (MIPS32) +{ + enum __NR_getrandom = 4353; + enum __NR_perf_event_open = 4333; +} +else version (MIPS64) +{ + version (MIPS_N32) + { + enum __NR_getrandom = 6317; + enum __NR_perf_event_open = 6296; + } + else version (MIPS_N64) + { + enum __NR_getrandom = 5313; + enum __NR_perf_event_open = 5292; + } + else + static assert(0, "Architecture not supported"); +} +else version (PPC_Any) +{ + enum __NR_getrandom = 359; + enum __NR_perf_event_open = 319; +} +else version (RISCV_Any) +{ + enum __NR_getrandom = 278; + enum __NR_perf_event_open = 241; +} +else version (SPARC_Any) +{ + enum __NR_getrandom = 347; + enum __NR_perf_event_open = 327; +} +else version (LoongArch64) +{ + enum __NR_getrandom = 278; + enum __NR_perf_event_open = 241; +} +else version (Xtensa) +{ + enum __NR_getrandom = 338; + enum __NR_perf_event_open = 327; +} +else +{ + static assert(0, "Architecture not supported"); +} + +// +// Defines SYS_* names for the __NR_* numbers of known names. +enum SYS_getrandom = __NR_getrandom; +enum SYS_perf_event_open = __NR_perf_event_open; diff --git a/libphobos/libdruntime/core/sys/linux/sys/time.d b/libphobos/libdruntime/core/sys/linux/sys/time.d index 4b56229687c7..9eb48f1c5ef7 100644 --- a/libphobos/libdruntime/core/sys/linux/sys/time.d +++ b/libphobos/libdruntime/core/sys/linux/sys/time.d @@ -23,7 +23,7 @@ version (linux): */ extern (D) pure @safe @nogc nothrow { - void timeradd(const timeval* a, const timeval* b, + void timeradd()(const timeval* a, const timeval* b, timeval* result) { result.tv_sec = a.tv_sec + b.tv_sec; @@ -35,7 +35,7 @@ extern (D) pure @safe @nogc nothrow { } } - void timersub(const timeval* a, const timeval* b, + void timersub()(const timeval* a, const timeval* b, timeval *result) { result.tv_sec = a.tv_sec - b.tv_sec; @@ -46,12 +46,12 @@ extern (D) pure @safe @nogc nothrow { } } - void timerclear(timeval* tvp) + void timerclear()(timeval* tvp) { (tvp.tv_sec = tvp.tv_usec = 0); } - int timerisset(timeval* tvp) + int timerisset()(timeval* tvp) { return cast(int) (tvp.tv_sec || tvp.tv_usec); } diff --git a/libphobos/libdruntime/core/sys/linux/syscall.d b/libphobos/libdruntime/core/sys/linux/syscall.d new file mode 100644 index 000000000000..84d03e75fb1a --- /dev/null +++ b/libphobos/libdruntime/core/sys/linux/syscall.d @@ -0,0 +1,14 @@ +/** + * D header file for GNU/Linux + * + * $(LINK2 https://sourceware.org/git/?p=glibc.git;a=blob;f=misc/syscall.h, glibc syscall.h) + */ + +module core.sys.linux.syscall; + +version (linux): +extern (C): +@nogc: +nothrow: + +public import core.sys.linux.sys.syscall; diff --git a/libphobos/libdruntime/core/sys/linux/unistd.d b/libphobos/libdruntime/core/sys/linux/unistd.d index 548870268dbf..3194ec2962c6 100644 --- a/libphobos/libdruntime/core/sys/linux/unistd.d +++ b/libphobos/libdruntime/core/sys/linux/unistd.d @@ -7,6 +7,8 @@ extern(C): nothrow: @nogc: +import core.stdc.config : c_long; + // Additional seek constants for sparse file handling // from Linux's unistd.h, stdio.h, and linux/fs.h // (see http://man7.org/linux/man-pages/man2/lseek.2.html) @@ -25,3 +27,6 @@ void exit_group(int status); /// Close all open file descriptors greater or equal to `lowfd` void closefrom(int lowfd); + +/// Invoke system call number `sysno`, passing it the remaining arguments. +c_long syscall(c_long sysno, ...); diff --git a/libphobos/libdruntime/core/sys/netbsd/err.d b/libphobos/libdruntime/core/sys/netbsd/err.d index 44eb66adc2fc..399ddea989a8 100644 --- a/libphobos/libdruntime/core/sys/netbsd/err.d +++ b/libphobos/libdruntime/core/sys/netbsd/err.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: Boost License 1.0. - * Authors: Ernesto Castellotti + * Authors: Emily Castellotti */ module core.sys.netbsd.err; import core.stdc.stdarg : va_list; diff --git a/libphobos/libdruntime/core/sys/netbsd/string.d b/libphobos/libdruntime/core/sys/netbsd/string.d index f1281da275b7..d83d22d56dd8 100644 --- a/libphobos/libdruntime/core/sys/netbsd/string.d +++ b/libphobos/libdruntime/core/sys/netbsd/string.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: Boost License 1.0. - * Authors: Ernesto Castellotti + * Authors: Emily Castellotti */ module core.sys.netbsd.string; diff --git a/libphobos/libdruntime/core/sys/netbsd/sys/featuretest.d b/libphobos/libdruntime/core/sys/netbsd/sys/featuretest.d index 3901ea9703ba..ded053a36e49 100644 --- a/libphobos/libdruntime/core/sys/netbsd/sys/featuretest.d +++ b/libphobos/libdruntime/core/sys/netbsd/sys/featuretest.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: Boost License 1.0. - * Authors: Ernesto Castellotti + * Authors: Emily Castellotti */ module core.sys.netbsd.sys.featuretest; diff --git a/libphobos/libdruntime/core/sys/openbsd/err.d b/libphobos/libdruntime/core/sys/openbsd/err.d index b4676140e382..271f2c4bfc63 100644 --- a/libphobos/libdruntime/core/sys/openbsd/err.d +++ b/libphobos/libdruntime/core/sys/openbsd/err.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: Boost License 1.0. - * Authors: Ernesto Castellotti + * Authors: Emily Castellotti */ module core.sys.openbsd.err; import core.stdc.stdarg : va_list; diff --git a/libphobos/libdruntime/core/sys/openbsd/string.d b/libphobos/libdruntime/core/sys/openbsd/string.d index 4480c94ac37b..e0c33be9d678 100644 --- a/libphobos/libdruntime/core/sys/openbsd/string.d +++ b/libphobos/libdruntime/core/sys/openbsd/string.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: Boost License 1.0. - * Authors: Ernesto Castellotti + * Authors: Emily Castellotti */ module core.sys.openbsd.string; diff --git a/libphobos/libdruntime/core/sys/posix/netdb.d b/libphobos/libdruntime/core/sys/posix/netdb.d index 70a5fe1901f3..4713f4b49559 100644 --- a/libphobos/libdruntime/core/sys/posix/netdb.d +++ b/libphobos/libdruntime/core/sys/posix/netdb.d @@ -153,7 +153,7 @@ version (CRuntime_Glibc) int h_addrtype; int h_length; char** h_addr_list; - char* h_addr() @property { return h_addr_list[0]; } // non-standard + char* h_addr()() @property { return h_addr_list[0]; } // non-standard } struct netent @@ -237,7 +237,7 @@ else version (Darwin) int h_addrtype; int h_length; char** h_addr_list; - char* h_addr() @property { return h_addr_list[0]; } // non-standard + char* h_addr()() @property { return h_addr_list[0]; } // non-standard } struct netent @@ -321,7 +321,7 @@ else version (FreeBSD) int h_addrtype; int h_length; char** h_addr_list; - extern (D) char* h_addr() @property { return h_addr_list[0]; } // non-standard + extern (D) char* h_addr()() @property { return h_addr_list[0]; } // non-standard } struct netent @@ -405,7 +405,7 @@ else version (NetBSD) int h_addrtype; int h_length; char** h_addr_list; - extern (D) char* h_addr() @property { return h_addr_list[0]; } // non-standard + extern (D) char* h_addr()() @property { return h_addr_list[0]; } // non-standard } struct netent @@ -512,7 +512,7 @@ else version (OpenBSD) int h_addrtype; int h_length; char** h_addr_list; - extern (D) char* h_addr() @property { return h_addr_list[0]; } // non-standard + extern (D) char* h_addr()() @property { return h_addr_list[0]; } // non-standard } struct netent @@ -608,7 +608,7 @@ else version (DragonFlyBSD) int h_addrtype; int h_length; char** h_addr_list; - extern (D) char* h_addr() @property { return h_addr_list[0]; } // non-standard + extern (D) char* h_addr()() @property { return h_addr_list[0]; } // non-standard } struct netent @@ -706,7 +706,7 @@ else version (Solaris) int h_length; char** h_addr_list; - extern (D) char* h_addr() @property { return h_addr_list[0]; } // non-standard + extern (D) char* h_addr()() @property { return h_addr_list[0]; } // non-standard } struct netent @@ -793,7 +793,7 @@ else version (CRuntime_Bionic) int h_addrtype; int h_length; char** h_addr_list; - extern (D) char* h_addr() @property { return h_addr_list[0]; } // non-standard + extern (D) char* h_addr()() @property { return h_addr_list[0]; } // non-standard } struct netent @@ -874,7 +874,7 @@ else version (CRuntime_Musl) int h_addrtype; int h_length; char** h_addr_list; - char* h_addr() @property { return h_addr_list[0]; } // non-standard + char* h_addr()() @property { return h_addr_list[0]; } // non-standard } struct netent @@ -952,7 +952,7 @@ else version (CRuntime_UClibc) int h_addrtype; int h_length; char** h_addr_list; - extern (D) char* h_addr() @property { return h_addr_list[0]; } // non-standard + extern (D) char* h_addr()() @property { return h_addr_list[0]; } // non-standard } struct netent diff --git a/libphobos/libdruntime/core/sys/posix/netinet/in_.d b/libphobos/libdruntime/core/sys/posix/netinet/in_.d index 5818ee6e22b6..09a4a5e07d10 100644 --- a/libphobos/libdruntime/core/sys/posix/netinet/in_.d +++ b/libphobos/libdruntime/core/sys/posix/netinet/in_.d @@ -547,7 +547,7 @@ version (CRuntime_Glibc) } // macros - extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_UNSPECIFIED()(const scope in6_addr* add) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -555,7 +555,7 @@ version (CRuntime_Glibc) (cast(uint32_t*) addr)[3] == 0; } - extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_LOOPBACK()(const scope in6_addr* add) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -563,29 +563,29 @@ version (CRuntime_Glibc) (cast(uint32_t*) addr)[3] == htonl( 1 ); } - extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MULTICAST()(const scope in6_addr* add) pure { return (cast(uint8_t*) addr)[0] == 0xff; } - extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_LINKLOCAL()(const scope in6_addr* add) pure { return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfe800000 ); } - extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_SITELOCAL()(const scope in6_addr* add) pure { return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfec00000 ); } - extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_V4MAPPED()(const scope in6_addr* add) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && (cast(uint32_t*) addr)[2] == htonl( 0xffff ); } - extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_V4COMPAT()(const scope in6_addr* add) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -593,31 +593,31 @@ version (CRuntime_Glibc) ntohl( (cast(uint32_t*) addr)[3] ) > 1; } - extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_NODELOCAL()(const scope in6_addr* add) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x1; } - extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()(const scope in6_addr* add) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x2; } - extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_SITELOCAL()(const scope in6_addr* add) pure { return IN6_IS_ADDR_MULTICAST(addr) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x5; } - extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()(const scope in6_addr* add) pure { return IN6_IS_ADDR_MULTICAST( addr) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x8; } - extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_GLOBAL()(const scope in6_addr* add) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0xe; @@ -670,7 +670,7 @@ else version (Darwin) } // macros - extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_UNSPECIFIED()(const scope in6_addr* add) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -678,7 +678,7 @@ else version (Darwin) (cast(uint32_t*) addr)[3] == 0; } - extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_LOOPBACK()(const scope in6_addr* add) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -686,29 +686,29 @@ else version (Darwin) (cast(uint32_t*) addr)[3] == ntohl( 1 ); } - extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MULTICAST()(const scope in6_addr* add) pure { return addr.s6_addr[0] == 0xff; } - extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_LINKLOCAL()(const scope in6_addr* add) pure { return addr.s6_addr[0] == 0xfe && (addr.s6_addr[1] & 0xc0) == 0x80; } - extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_SITELOCAL()(const scope in6_addr* add) pure { return addr.s6_addr[0] == 0xfe && (addr.s6_addr[1] & 0xc0) == 0xc0; } - extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_V4MAPPED()(const scope in6_addr* add) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && (cast(uint32_t*) addr)[2] == ntohl( 0x0000ffff ); } - extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_V4COMPAT()(const scope in6_addr* add) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -717,31 +717,31 @@ else version (Darwin) (cast(uint32_t*) addr)[3] != ntohl( 1 ); } - extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_NODELOCAL()(const scope in6_addr* add) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x1; } - extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()(const scope in6_addr* add) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x2; } - extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_SITELOCAL()(const scope in6_addr* add) pure { return IN6_IS_ADDR_MULTICAST(addr) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x5; } - extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()(const scope in6_addr* add) pure { return IN6_IS_ADDR_MULTICAST( addr) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x8; } - extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_GLOBAL()(const scope in6_addr* add) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0xe; @@ -804,7 +804,7 @@ else version (FreeBSD) } // macros - extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_UNSPECIFIED()( const scope in6_addr* a) pure { return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && @@ -812,7 +812,7 @@ else version (FreeBSD) (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == 0); } - extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_LOOPBACK()( const scope in6_addr* a) pure { return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && @@ -820,7 +820,7 @@ else version (FreeBSD) (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == ntohl(1)); } - extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_V4COMPAT()( const scope in6_addr* a) pure { return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && @@ -829,58 +829,58 @@ else version (FreeBSD) (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) != ntohl(1)); } - extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_V4MAPPED()( const scope in6_addr* a) pure { return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == ntohl(0x0000ffff)); } - extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_LINKLOCAL()( const scope in6_addr* a) pure { return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0x80; } - extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_SITELOCAL()( const scope in6_addr* a) pure { return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0xc0; } - extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MULTICAST()( const scope in6_addr* a) pure { return a.s6_addr[0] == 0xff; } - extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( const scope in6_addr* a ) pure + extern (D) uint8_t __IPV6_ADDR_MC_SCOPE()( const scope in6_addr* a) pure { return a.s6_addr[1] & 0x0f; } - extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_NODELOCAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL; } - extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL; } - extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_SITELOCAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL; } - extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL; } - extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_GLOBAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL; @@ -943,7 +943,7 @@ else version (NetBSD) } // macros - extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_UNSPECIFIED()( const scope in6_addr* a) pure { return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && @@ -951,7 +951,7 @@ else version (NetBSD) (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == 0); } - extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_LOOPBACK()( const scope in6_addr* a) pure { return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && @@ -959,7 +959,7 @@ else version (NetBSD) (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == ntohl(1)); } - extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_V4COMPAT()( const scope in6_addr* a) pure { return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && @@ -968,58 +968,58 @@ else version (NetBSD) (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) != ntohl(1)); } - extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_V4MAPPED()( const scope in6_addr* a) pure { return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == ntohl(0x0000ffff)); } - extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_LINKLOCAL()( const scope in6_addr* a) pure { return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0x80; } - extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_SITELOCAL()( const scope in6_addr* a) pure { return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0xc0; } - extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MULTICAST()( const scope in6_addr* a) pure { return a.s6_addr[0] == 0xff; } - extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( const scope in6_addr* a ) pure + extern (D) uint8_t __IPV6_ADDR_MC_SCOPE()( const scope in6_addr* a) pure { return a.s6_addr[1] & 0x0f; } - extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_NODELOCAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL; } - extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL; } - extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_SITELOCAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL; } - extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL; } - extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_GLOBAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL; @@ -1082,7 +1082,7 @@ else version (OpenBSD) } // macros - extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_UNSPECIFIED()( const scope in6_addr* a) pure { return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && @@ -1090,7 +1090,7 @@ else version (OpenBSD) (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == 0); } - extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_LOOPBACK()( const scope in6_addr* a) pure { return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && @@ -1098,7 +1098,7 @@ else version (OpenBSD) (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == ntohl(1)); } - extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_V4COMPAT()( const scope in6_addr* a) pure { return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && @@ -1107,58 +1107,58 @@ else version (OpenBSD) (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) != ntohl(1)); } - extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_V4MAPPED()( const scope in6_addr* a) pure { return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == ntohl(0x0000ffff)); } - extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_LINKLOCAL()( const scope in6_addr* a) pure { return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0x80; } - extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_SITELOCAL()( const scope in6_addr* a) pure { return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0xc0; } - extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MULTICAST()( const scope in6_addr* a) pure { return a.s6_addr[0] == 0xff; } - extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( const scope in6_addr* a ) pure + extern (D) uint8_t __IPV6_ADDR_MC_SCOPE()( const scope in6_addr* a) pure { return a.s6_addr[1] & 0x0f; } - extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_NODELOCAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL; } - extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL; } - extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_SITELOCAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL; } - extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL; } - extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_GLOBAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL; @@ -1221,7 +1221,7 @@ else version (DragonFlyBSD) } // macros - extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_UNSPECIFIED()( const scope in6_addr* a) pure { return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && @@ -1229,7 +1229,7 @@ else version (DragonFlyBSD) (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == 0); } - extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_LOOPBACK()( const scope in6_addr* a) pure { return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && @@ -1237,7 +1237,7 @@ else version (DragonFlyBSD) (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == ntohl(1)); } - extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_V4COMPAT()( const scope in6_addr* a) pure { return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && @@ -1246,58 +1246,58 @@ else version (DragonFlyBSD) (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) != ntohl(1)); } - extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_V4MAPPED()( const scope in6_addr* a) pure { return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) && (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == ntohl(0x0000ffff)); } - extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_LINKLOCAL()( const scope in6_addr* a) pure { return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0x80; } - extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_SITELOCAL()( const scope in6_addr* a) pure { return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0xc0; } - extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MULTICAST()( const scope in6_addr* a) pure { return a.s6_addr[0] == 0xff; } - extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( const scope in6_addr* a ) pure + extern (D) uint8_t __IPV6_ADDR_MC_SCOPE()( const scope in6_addr* a) pure { return a.s6_addr[1] & 0x0f; } - extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_NODELOCAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL; } - extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL; } - extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_SITELOCAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL; } - extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL; } - extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_GLOBAL()( const scope in6_addr* a) pure { return IN6_IS_ADDR_MULTICAST(a) && __IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL; @@ -1350,67 +1350,67 @@ else version (Solaris) } // macros - extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_UNSPECIFIED()( const scope in6_addr* a) pure { return (a.s6_addr32[0] == 0) && (a.s6_addr32[1] == 0) && (a.s6_addr32[2] == 0) && (a.s6_addr32[3] == 0); } - extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_LOOPBACK()( const scope in6_addr* a) pure { return (a.s6_addr32[0] == 0) && (a.s6_addr32[1] == 0) && (a.s6_addr32[2] == 0) && (a.s6_addr32[3] == ntohl(1)); } - extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_V4COMPAT()( const scope in6_addr* a) pure { return (a.s6_addr32[0] == 0) && (a.s6_addr32[1] == 0) && (a.s6_addr32[2] == 0) && (a.s6_addr32[3] != 0) && (a.s6_addr32[3] != ntohl(1)); } - extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_V4MAPPED()( const scope in6_addr* a) pure { return (a.s6_addr32[0] == 0) && (a.s6_addr32[1] == 0) && (a.s6_addr32[2] == ntohl(0x0000ffff)); } - extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_LINKLOCAL()( const scope in6_addr* a) pure { return a.s6_addr8[0] == 0xfe && (a.s6_addr8[1] & 0xc0) == 0x80; } - extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_SITELOCAL()( const scope in6_addr* a) pure { return a.s6_addr8[0] == 0xfe && (a.s6_addr8[1] & 0xc0) == 0xc0; } - extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MULTICAST()( const scope in6_addr* a) pure { return a.s6_addr8[0] == 0xff; } - extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_NODELOCAL()( const scope in6_addr* a) pure { return a.s6_addr8[0] == 0xff && (a.s6_addr8[1] & 0x0f) == 0x01; } - extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()( const scope in6_addr* a) pure { return a.s6_addr8[0] == 0xff && (a.s6_addr8[1] & 0x0f) == 0x02; } - extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_SITELOCAL()( const scope in6_addr* a) pure { return a.s6_addr8[0] == 0xff && (a.s6_addr8[1] & 0x0f) == 0x05; } - extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()( const scope in6_addr* a) pure { return a.s6_addr8[0] == 0xff && (a.s6_addr8[1] & 0x0f) == 0x08; } - extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* a ) pure + extern (D) int IN6_IS_ADDR_MC_GLOBAL()( const scope in6_addr* a) pure { return a.s6_addr8[0] == 0xff && (a.s6_addr8[1] & 0x0f) == 0x0e; } @@ -1640,7 +1640,7 @@ else version (CRuntime_UClibc) } // macros - extern (D) int IN6_IS_ADDR_UNSPECIFIED( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_UNSPECIFIED()( in6_addr* addr) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -1648,7 +1648,7 @@ else version (CRuntime_UClibc) (cast(uint32_t*) addr)[3] == 0; } - extern (D) int IN6_IS_ADDR_LOOPBACK( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_LOOPBACK()( in6_addr* addr) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -1656,29 +1656,29 @@ else version (CRuntime_UClibc) (cast(uint32_t*) addr)[3] == htonl( 1 ); } - extern (D) int IN6_IS_ADDR_MULTICAST( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MULTICAST()( in6_addr* addr) pure { return (cast(uint8_t*) addr)[0] == 0xff; } - extern (D) int IN6_IS_ADDR_LINKLOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_LINKLOCAL()( in6_addr* addr) pure { return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfe800000 ); } - extern (D) int IN6_IS_ADDR_SITELOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_SITELOCAL()( in6_addr* addr) pure { return ((cast(uint32_t*) addr)[0] & htonl( 0xffc00000 )) == htonl( 0xfec00000 ); } - extern (D) int IN6_IS_ADDR_V4MAPPED( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_V4MAPPED()( in6_addr* addr) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && (cast(uint32_t*) addr)[2] == htonl( 0xffff ); } - extern (D) int IN6_IS_ADDR_V4COMPAT( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_V4COMPAT()( in6_addr* addr) pure { return (cast(uint32_t*) addr)[0] == 0 && (cast(uint32_t*) addr)[1] == 0 && @@ -1686,7 +1686,7 @@ else version (CRuntime_UClibc) ntohl( (cast(uint32_t*) addr)[3] ) > 1; } - extern (D) int IN6_ARE_ADDR_EQUAL( in6_addr* a, in6_addr* b ) pure + extern (D) int IN6_ARE_ADDR_EQUAL()( in6_addr* a, in6_addr* b) pure { return (cast(uint32_t*) a)[0] == (cast(uint32_t*) b)[0] && (cast(uint32_t*) a)[1] == (cast(uint32_t*) b)[1] && @@ -1694,31 +1694,31 @@ else version (CRuntime_UClibc) (cast(uint32_t*) a)[3] == (cast(uint32_t*) b)[3]; } - extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_NODELOCAL()( in6_addr* addr) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x1; } - extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_LINKLOCAL()( in6_addr* addr) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x2; } - extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_SITELOCAL()( in6_addr* addr) pure { return IN6_IS_ADDR_MULTICAST(addr) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x5; } - extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_ORGLOCAL()( in6_addr* addr) pure { return IN6_IS_ADDR_MULTICAST( addr) && ((cast(uint8_t*) addr)[1] & 0xf) == 0x8; } - extern (D) int IN6_IS_ADDR_MC_GLOBAL( in6_addr* addr ) pure + extern (D) int IN6_IS_ADDR_MC_GLOBAL()( in6_addr* addr) pure { return IN6_IS_ADDR_MULTICAST( addr ) && ((cast(uint8_t*) addr)[1] & 0xf) == 0xe; diff --git a/libphobos/libdruntime/core/sys/posix/signal.d b/libphobos/libdruntime/core/sys/posix/signal.d index e3d80fb02180..bdc68687d0f6 100644 --- a/libphobos/libdruntime/core/sys/posix/signal.d +++ b/libphobos/libdruntime/core/sys/posix/signal.d @@ -179,7 +179,7 @@ else version (linux) int __libc_current_sigrtmax(); } - @property int SIGRTMIN() nothrow @nogc { + @property int SIGRTMIN()() nothrow @nogc { __gshared int sig = -1; if (sig == -1) { sig = __libc_current_sigrtmin(); @@ -187,7 +187,7 @@ else version (linux) return sig; } - @property int SIGRTMAX() nothrow @nogc { + @property int SIGRTMAX()() nothrow @nogc { __gshared int sig = -1; if (sig == -1) { sig = __libc_current_sigrtmax(); @@ -1012,12 +1012,12 @@ version (linux) } _sifields_t _sifields; nothrow @nogc: - @property ref pid_t si_pid() return { return _sifields._kill.si_pid; } - @property ref uid_t si_uid() return { return _sifields._kill.si_uid; } - @property ref void* si_addr() return { return _sifields._sigfault.si_addr; } - @property ref int si_status() return { return _sifields._sigchld.si_status; } - @property ref c_long si_band() return { return _sifields._sigpoll.si_band; } - @property ref sigval si_value() return { return _sifields._rt.si_sigval; } + @property ref pid_t si_pid()() { return _sifields._kill.si_pid; } + @property ref uid_t si_uid()() { return _sifields._kill.si_uid; } + @property ref void* si_addr()() { return _sifields._sigfault.si_addr; } + @property ref int si_status()() { return _sifields._sigchld.si_status; } + @property ref c_long si_band()() { return _sifields._sigpoll.si_band; } + @property ref sigval si_value()() { return _sifields._rt.si_sigval; } } enum @@ -2763,6 +2763,11 @@ else version (CRuntime_Musl) enum MINSIGSTKSZ = 4096; enum SIGSTKSZ = 16384; } + else version (RISCV64) + { + enum MINSIGSTKSZ = 2048; + enum SIGSTKSZ = 8192; + } else static assert(0, "unimplemented"); diff --git a/libphobos/libdruntime/core/sys/posix/sys/ioctl.d b/libphobos/libdruntime/core/sys/posix/sys/ioctl.d index caf3ebafb5a5..27584d357c4d 100644 --- a/libphobos/libdruntime/core/sys/posix/sys/ioctl.d +++ b/libphobos/libdruntime/core/sys/posix/sys/ioctl.d @@ -61,7 +61,7 @@ version (linux) (is(T == typeof(null)) ? 0 : T.sizeof << _IOC_SIZESHIFT); } - extern (D) int _IO(int type, int nr) + extern (D) int _IO()(int type, int nr) { return _IOC(_IOC_NONE, type, nr); } @@ -81,22 +81,22 @@ version (linux) return _IOC!T(_IOC_READ | _IOC_WRITE, type, nr); } - extern (D) int _IOC_DIR(int nr) + extern (D) int _IOC_DIR()(int nr) { return (nr >> _IOC_DIRSHIFT) & _IOC_DIRMASK; } - extern (D) int _IOC_TYPE(int nr) + extern (D) int _IOC_TYPE()(int nr) { return (nr >> _IOC_TYPESHIFT) & _IOC_TYPEMASK; } - extern (D) int _IOC_NR(int nr) + extern (D) int _IOC_NR()(int nr) { return (nr >> _IOC_NRSHIFT) & _IOC_NRMASK; } - extern (D) int _IOC_SIZE(int nr) + extern (D) int _IOC_SIZE()(int nr) { return (nr >> _IOC_SIZESHIFT) & _IOC_SIZEMASK; } diff --git a/libphobos/libdruntime/core/sys/posix/sys/select.d b/libphobos/libdruntime/core/sys/posix/sys/select.d index bd3425032521..c8a88bddc0ca 100644 --- a/libphobos/libdruntime/core/sys/posix/sys/select.d +++ b/libphobos/libdruntime/core/sys/posix/sys/select.d @@ -57,12 +57,12 @@ version (CRuntime_Glibc) alias c_long __fd_mask; enum uint __NFDBITS = 8 * __fd_mask.sizeof; - extern (D) auto __FDELT( int d ) pure + extern (D) auto __FDELT()( int d ) pure { return d / __NFDBITS; } - extern (D) auto __FDMASK( int d ) pure + extern (D) auto __FDMASK()( int d ) pure { return cast(__fd_mask) 1 << ( d % __NFDBITS ); } @@ -75,22 +75,22 @@ version (CRuntime_Glibc) __fd_mask[FD_SETSIZE / __NFDBITS] fds_bits; } - extern (D) void FD_CLR( int fd, fd_set* fdset ) pure + extern (D) void FD_CLR()( int fd, fd_set* fdset ) pure { fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd ); } - extern (D) bool FD_ISSET( int fd, const(fd_set)* fdset ) pure + extern (D) bool FD_ISSET()( int fd, const(fd_set)* fdset ) pure { return (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd )) != 0; } - extern (D) void FD_SET( int fd, fd_set* fdset ) pure + extern (D) void FD_SET()( int fd, fd_set* fdset ) pure { fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd ); } - extern (D) void FD_ZERO( fd_set* fdset ) pure + extern (D) void FD_ZERO()( fd_set* fdset ) pure { fdset.fds_bits[0 .. $] = 0; } @@ -148,22 +148,22 @@ else version (Darwin) int[(FD_SETSIZE + (__DARWIN_NFDBITS - 1)) / __DARWIN_NFDBITS] fds_bits; } - extern (D) void FD_CLR( int fd, fd_set* fdset ) pure + extern (D) void FD_CLR()( int fd, fd_set* fdset ) pure { fdset.fds_bits[fd / __DARWIN_NFDBITS] &= ~(1 << (fd % __DARWIN_NFDBITS)); } - extern (D) bool FD_ISSET( int fd, const(fd_set)* fdset ) pure + extern (D) bool FD_ISSET()( int fd, const(fd_set)* fdset ) pure { return (fdset.fds_bits[fd / __DARWIN_NFDBITS] & (1 << (fd % __DARWIN_NFDBITS))) != 0; } - extern (D) void FD_SET( int fd, fd_set* fdset ) pure + extern (D) void FD_SET()( int fd, fd_set* fdset ) pure { fdset.fds_bits[fd / __DARWIN_NFDBITS] |= 1 << (fd % __DARWIN_NFDBITS); } - extern (D) void FD_ZERO( fd_set* fdset ) pure + extern (D) void FD_ZERO()( fd_set* fdset ) pure { fdset.fds_bits[0 .. $] = 0; } @@ -187,27 +187,27 @@ else version (FreeBSD) deprecated("druntime incorrectly named fds_bits __fds_bits") alias __fds_bits = fds_bits; } - extern (D) __fd_mask __fdset_mask(uint n) pure + extern (D) __fd_mask __fdset_mask()(uint n) pure { return cast(__fd_mask) 1 << (n % _NFDBITS); } - extern (D) void FD_CLR( int n, fd_set* p ) pure + extern (D) void FD_CLR()( int n, fd_set* p ) pure { p.fds_bits[n / _NFDBITS] &= ~__fdset_mask(n); } - extern (D) bool FD_ISSET( int n, const(fd_set)* p ) pure + extern (D) bool FD_ISSET()( int n, const(fd_set)* p ) pure { return (p.fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0; } - extern (D) void FD_SET( int n, fd_set* p ) pure + extern (D) void FD_SET()( int n, fd_set* p ) pure { p.fds_bits[n / _NFDBITS] |= __fdset_mask(n); } - extern (D) void FD_ZERO( fd_set* p ) pure + extern (D) void FD_ZERO()( fd_set* p ) pure { fd_set *_p; size_t _n; @@ -237,27 +237,27 @@ else version (NetBSD) deprecated("druntime incorrectly named fds_bits __fds_bits") alias __fds_bits = fds_bits; } - extern (D) __fd_mask __fdset_mask(uint n) pure + extern (D) __fd_mask __fdset_mask()(uint n) pure { return cast(__fd_mask) 1 << (n % _NFDBITS); } - extern (D) void FD_CLR( int n, fd_set* p ) pure + extern (D) void FD_CLR()( int n, fd_set* p ) pure { p.fds_bits[n / _NFDBITS] &= ~__fdset_mask(n); } - extern (D) bool FD_ISSET( int n, const(fd_set)* p ) pure + extern (D) bool FD_ISSET()( int n, const(fd_set)* p ) pure { return (p.fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0; } - extern (D) void FD_SET( int n, fd_set* p ) pure + extern (D) void FD_SET()( int n, fd_set* p ) pure { p.fds_bits[n / _NFDBITS] |= __fdset_mask(n); } - extern (D) void FD_ZERO( fd_set* p ) pure + extern (D) void FD_ZERO()( fd_set* p ) pure { fd_set *_p; size_t _n; @@ -287,27 +287,27 @@ else version (OpenBSD) deprecated("druntime incorrectly named fds_bits __fds_bits") alias __fds_bits = fds_bits; } - extern (D) __fd_mask __fdset_mask(uint n) pure + extern (D) __fd_mask __fdset_mask()(uint n) pure { return cast(__fd_mask) 1 << (n % _NFDBITS); } - extern (D) void FD_CLR(int n, fd_set* p) pure + extern (D) void FD_CLR()(int n, fd_set* p) pure { p.fds_bits[n / _NFDBITS] &= ~__fdset_mask(n); } - extern (D) bool FD_ISSET(int n, const(fd_set)* p) pure + extern (D) bool FD_ISSET()(int n, const(fd_set)* p) pure { return (p.fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0; } - extern (D) void FD_SET(int n, fd_set* p) pure + extern (D) void FD_SET()(int n, fd_set* p) pure { p.fds_bits[n / _NFDBITS] |= __fdset_mask(n); } - extern (D) void FD_ZERO(fd_set* p) pure + extern (D) void FD_ZERO()(fd_set* p) pure { fd_set *_p = p; size_t _n = (FD_SETSIZE + (_NFDBITS - 1)) / _NFDBITS; @@ -335,27 +335,27 @@ else version (DragonFlyBSD) deprecated("druntime incorrectly named fds_bits __fds_bits") alias __fds_bits = fds_bits; } - extern (D) __fd_mask __fdset_mask(uint n) pure + extern (D) __fd_mask __fdset_mask()(uint n) pure { return cast(__fd_mask) 1 << (n % _NFDBITS); } - extern (D) void FD_CLR( int n, fd_set* p ) pure + extern (D) void FD_CLR()( int n, fd_set* p ) pure { p.fds_bits[n / _NFDBITS] &= ~__fdset_mask(n); } - extern (D) bool FD_ISSET( int n, const(fd_set)* p ) pure + extern (D) bool FD_ISSET()( int n, const(fd_set)* p ) pure { return (p.fds_bits[n / _NFDBITS] & __fdset_mask(n)) != 0; } - extern (D) void FD_SET( int n, fd_set* p ) pure + extern (D) void FD_SET()( int n, fd_set* p ) pure { p.fds_bits[n / _NFDBITS] |= __fdset_mask(n); } - extern (D) void FD_ZERO( fd_set* p ) pure + extern (D) void FD_ZERO()( fd_set* p ) pure { fd_set *_p; size_t _n; @@ -389,22 +389,22 @@ else version (Solaris) c_long[(FD_SETSIZE + (FD_NFDBITS - 1)) / FD_NFDBITS] fds_bits; } - extern (D) void FD_SET(int __n, fd_set* __p) pure + extern (D) void FD_SET()(int __n, fd_set* __p) pure { __p.fds_bits[__n / FD_NFDBITS] |= 1UL << (__n % FD_NFDBITS); } - extern (D) void FD_CLR(int __n, fd_set* __p) pure + extern (D) void FD_CLR()(int __n, fd_set* __p) pure { __p.fds_bits[__n / FD_NFDBITS] &= ~(1UL << (__n % FD_NFDBITS)); } - extern (D) bool FD_ISSET(int __n, const(fd_set)* __p) pure + extern (D) bool FD_ISSET()(int __n, const(fd_set)* __p) pure { return (__p.fds_bits[__n / FD_NFDBITS] & (1UL << (__n % FD_NFDBITS))) != 0; } - extern (D) void FD_ZERO(fd_set* __p) pure + extern (D) void FD_ZERO()(fd_set* __p) pure { __p.fds_bits[0 .. $] = 0; } @@ -419,12 +419,12 @@ else version (CRuntime_Bionic) alias c_ulong __fd_mask; enum uint __NFDBITS = 8 * __fd_mask.sizeof; - extern (D) auto __FDELT( int d ) pure + extern (D) auto __FDELT()( int d ) pure { return d / __NFDBITS; } - extern (D) auto __FDMASK( int d ) pure + extern (D) auto __FDMASK()( int d ) pure { return cast(__fd_mask) 1 << ( d % __NFDBITS ); } @@ -438,22 +438,22 @@ else version (CRuntime_Bionic) } // These functions are generated in assembly in bionic. - extern (D) void FD_CLR( int fd, fd_set* fdset ) pure + extern (D) void FD_CLR()( int fd, fd_set* fdset ) pure { fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd ); } - extern (D) bool FD_ISSET( int fd, const(fd_set)* fdset ) pure + extern (D) bool FD_ISSET()( int fd, const(fd_set)* fdset ) pure { return (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd )) != 0; } - extern (D) void FD_SET( int fd, fd_set* fdset ) pure + extern (D) void FD_SET()( int fd, fd_set* fdset ) pure { fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd ); } - extern (D) void FD_ZERO( fd_set* fdset ) pure + extern (D) void FD_ZERO()( fd_set* fdset ) pure { fdset.fds_bits[0 .. $] = 0; } @@ -471,12 +471,12 @@ else version (CRuntime_Musl) { enum uint __NFDBITS = 8 * fd_mask.sizeof; - extern (D) auto __FDELT( int d ) pure + extern (D) auto __FDELT()( int d ) pure { return d / __NFDBITS; } - extern (D) auto __FDMASK( int d ) pure + extern (D) auto __FDMASK()( int d ) pure { return cast(fd_mask) 1 << ( d % __NFDBITS ); } @@ -486,22 +486,22 @@ else version (CRuntime_Musl) ulong[FD_SETSIZE / 8 / long.sizeof] fds_bits; } - extern (D) void FD_CLR( int fd, fd_set* fdset ) pure + extern (D) void FD_CLR()( int fd, fd_set* fdset ) pure { fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd ); } - extern (D) bool FD_ISSET( int fd, const(fd_set)* fdset ) pure + extern (D) bool FD_ISSET()( int fd, const(fd_set)* fdset ) pure { return (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd )) != 0; } - extern (D) void FD_SET( int fd, fd_set* fdset ) pure + extern (D) void FD_SET()( int fd, fd_set* fdset ) pure { fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd ); } - extern (D) void FD_ZERO( fd_set* fdset ) pure + extern (D) void FD_ZERO()( fd_set* fdset ) pure { fdset.fds_bits[0 .. $] = 0; } @@ -517,12 +517,12 @@ else version (CRuntime_UClibc) alias c_long __fd_mask; enum uint __NFDBITS = 8 * __fd_mask.sizeof; - extern (D) auto __FDELT( int d ) pure + extern (D) auto __FDELT()( int d ) pure { return d / __NFDBITS; } - extern (D) auto __FDMASK( int d ) pure + extern (D) auto __FDMASK()( int d ) pure { return cast(__fd_mask) 1 << ( d % __NFDBITS ); } @@ -535,22 +535,22 @@ else version (CRuntime_UClibc) __fd_mask[FD_SETSIZE / __NFDBITS] fds_bits; } - extern (D) void FD_CLR( int fd, fd_set* fdset ) pure + extern (D) void FD_CLR()( int fd, fd_set* fdset ) pure { fdset.fds_bits[__FDELT( fd )] &= ~__FDMASK( fd ); } - extern (D) bool FD_ISSET( int fd, const(fd_set)* fdset ) pure + extern (D) bool FD_ISSET()( int fd, const(fd_set)* fdset ) pure { return (fdset.fds_bits[__FDELT( fd )] & __FDMASK( fd )) != 0; } - extern (D) void FD_SET( int fd, fd_set* fdset ) pure + extern (D) void FD_SET()( int fd, fd_set* fdset ) pure { fdset.fds_bits[__FDELT( fd )] |= __FDMASK( fd ); } - extern (D) void FD_ZERO( fd_set* fdset ) pure + extern (D) void FD_ZERO()( fd_set* fdset ) pure { fdset.fds_bits[0 .. $] = 0; } diff --git a/libphobos/libdruntime/core/sys/posix/sys/socket.d b/libphobos/libdruntime/core/sys/posix/sys/socket.d index 12824373d586..5bdc22294c1d 100644 --- a/libphobos/libdruntime/core/sys/posix/sys/socket.d +++ b/libphobos/libdruntime/core/sys/posix/sys/socket.d @@ -233,12 +233,12 @@ version (linux) extern (D) { - size_t CMSG_ALIGN( size_t len ) pure nothrow @nogc + size_t CMSG_ALIGN()( size_t len ) pure nothrow @nogc { return (len + size_t.sizeof - 1) & cast(size_t) (~(size_t.sizeof - 1)); } - size_t CMSG_LEN( size_t len ) pure nothrow @nogc + size_t CMSG_LEN()( size_t len ) pure nothrow @nogc { return CMSG_ALIGN(cmsghdr.sizeof) + len; } @@ -668,13 +668,13 @@ else version (Darwin) extern (D) { - socklen_t CMSG_ALIGN(socklen_t len) pure nothrow @nogc { return (len + socklen_t.sizeof - 1) & cast(socklen_t) (~(socklen_t.sizeof - 1)); } - socklen_t CMSG_SPACE(socklen_t len) pure nothrow @nogc { return CMSG_ALIGN(len) + CMSG_ALIGN(cmsghdr.sizeof); } - socklen_t CMSG_LEN(socklen_t len) pure nothrow @nogc { return CMSG_ALIGN(cmsghdr.sizeof) + len; } + socklen_t CMSG_ALIGN()(socklen_t len) pure nothrow @nogc { return (len + socklen_t.sizeof - 1) & cast(socklen_t) (~(socklen_t.sizeof - 1)); } + socklen_t CMSG_SPACE()(socklen_t len) pure nothrow @nogc { return CMSG_ALIGN(len) + CMSG_ALIGN(cmsghdr.sizeof); } + socklen_t CMSG_LEN()(socklen_t len) pure nothrow @nogc { return CMSG_ALIGN(cmsghdr.sizeof) + len; } - inout(ubyte)* CMSG_DATA( return scope inout(cmsghdr)* cmsg ) pure nothrow @nogc { return cast(ubyte*)( cmsg + 1 ); } + inout(ubyte)* CMSG_DATA()( return scope inout(cmsghdr)* cmsg ) pure nothrow @nogc { return cast(ubyte*)( cmsg + 1 ); } - inout(cmsghdr)* CMSG_FIRSTHDR( inout(msghdr)* mhdr ) pure nothrow @nogc + inout(cmsghdr)* CMSG_FIRSTHDR()( inout(msghdr)* mhdr ) pure nothrow @nogc { return ( cast(socklen_t)mhdr.msg_controllen >= cmsghdr.sizeof ? cast(inout(cmsghdr)*) mhdr.msg_control : cast(inout(cmsghdr)*) null ); } diff --git a/libphobos/libdruntime/core/sys/posix/sys/stat.d b/libphobos/libdruntime/core/sys/posix/sys/stat.d index 328f620a42a2..ab79a4067509 100644 --- a/libphobos/libdruntime/core/sys/posix/sys/stat.d +++ b/libphobos/libdruntime/core/sys/posix/sys/stat.d @@ -1464,19 +1464,19 @@ version (CRuntime_Glibc) private { - extern (D) bool S_ISTYPE( mode_t mode, uint mask ) + extern (D) bool S_ISTYPE()( mode_t mode, uint mask ) { return ( mode & S_IFMT ) == mask; } } - extern (D) bool S_ISBLK( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); } - extern (D) bool S_ISCHR( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); } - extern (D) bool S_ISDIR( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); } - extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); } - extern (D) bool S_ISREG( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); } - extern (D) bool S_ISLNK( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); } - extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); } + extern (D) bool S_ISBLK()( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); } + extern (D) bool S_ISCHR()( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); } + extern (D) bool S_ISDIR()( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); } + extern (D) bool S_ISFIFO()( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); } + extern (D) bool S_ISREG()( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); } + extern (D) bool S_ISLNK()( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); } + extern (D) bool S_ISSOCK()( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); } int utimensat(int dirfd, const char *pathname, ref const(timespec)[2] times, int flags); @@ -1501,19 +1501,19 @@ else version (Darwin) private { - extern (D) bool S_ISTYPE( mode_t mode, uint mask ) + extern (D) bool S_ISTYPE()( mode_t mode, uint mask ) { return ( mode & S_IFMT ) == mask; } } - extern (D) bool S_ISBLK( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); } - extern (D) bool S_ISCHR( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); } - extern (D) bool S_ISDIR( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); } - extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); } - extern (D) bool S_ISREG( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); } - extern (D) bool S_ISLNK( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); } - extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); } + extern (D) bool S_ISBLK()( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); } + extern (D) bool S_ISCHR()( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); } + extern (D) bool S_ISDIR()( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); } + extern (D) bool S_ISFIFO()( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); } + extern (D) bool S_ISREG()( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); } + extern (D) bool S_ISLNK()( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); } + extern (D) bool S_ISSOCK()( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); } } else version (FreeBSD) { @@ -1534,19 +1534,19 @@ else version (FreeBSD) private { - extern (D) bool S_ISTYPE( mode_t mode, uint mask ) + extern (D) bool S_ISTYPE()( mode_t mode, uint mask ) { return ( mode & S_IFMT ) == mask; } } - extern (D) bool S_ISBLK( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); } - extern (D) bool S_ISCHR( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); } - extern (D) bool S_ISDIR( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); } - extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); } - extern (D) bool S_ISREG( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); } - extern (D) bool S_ISLNK( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); } - extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); } + extern (D) bool S_ISBLK()( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); } + extern (D) bool S_ISCHR()( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); } + extern (D) bool S_ISDIR()( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); } + extern (D) bool S_ISFIFO()( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); } + extern (D) bool S_ISREG()( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); } + extern (D) bool S_ISLNK()( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); } + extern (D) bool S_ISSOCK()( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); } // Since FreeBSD 11: version (none) @@ -1575,19 +1575,19 @@ else version (NetBSD) private { - extern (D) bool S_ISTYPE( mode_t mode, uint mask ) + extern (D) bool S_ISTYPE()( mode_t mode, uint mask ) { return ( mode & S_IFMT ) == mask; } } - extern (D) bool S_ISBLK( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); } - extern (D) bool S_ISCHR( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); } - extern (D) bool S_ISDIR( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); } - extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); } - extern (D) bool S_ISREG( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); } - extern (D) bool S_ISLNK( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); } - extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); } + extern (D) bool S_ISBLK()( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); } + extern (D) bool S_ISCHR()( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); } + extern (D) bool S_ISDIR()( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); } + extern (D) bool S_ISFIFO()( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); } + extern (D) bool S_ISREG()( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); } + extern (D) bool S_ISLNK()( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); } + extern (D) bool S_ISSOCK()( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); } } else version (OpenBSD) { @@ -1606,13 +1606,13 @@ else version (OpenBSD) enum S_IXOTH = 0x1; // 0000001 enum S_IRWXO = 0x7; // 0000007 - extern (D) bool S_ISBLK(mode_t mode) { return (mode & S_IFMT) == S_IFBLK; } - extern (D) bool S_ISCHR(mode_t mode) { return (mode & S_IFMT) == S_IFCHR; } - extern (D) bool S_ISDIR(mode_t mode) { return (mode & S_IFMT) == S_IFDIR; } - extern (D) bool S_ISFIFO(mode_t mode) { return (mode & S_IFMT) == S_IFIFO; } - extern (D) bool S_ISREG(mode_t mode) { return (mode & S_IFMT) == S_IFREG; } - extern (D) bool S_ISLNK(mode_t mode) { return (mode & S_IFMT) == S_IFLNK; } - extern (D) bool S_ISSOCK(mode_t mode) { return (mode & S_IFMT) == S_IFSOCK; } + extern (D) bool S_ISBLK()(mode_t mode) { return (mode & S_IFMT) == S_IFBLK; } + extern (D) bool S_ISCHR()(mode_t mode) { return (mode & S_IFMT) == S_IFCHR; } + extern (D) bool S_ISDIR()(mode_t mode) { return (mode & S_IFMT) == S_IFDIR; } + extern (D) bool S_ISFIFO()(mode_t mode) { return (mode & S_IFMT) == S_IFIFO; } + extern (D) bool S_ISREG()(mode_t mode) { return (mode & S_IFMT) == S_IFREG; } + extern (D) bool S_ISLNK()(mode_t mode) { return (mode & S_IFMT) == S_IFLNK; } + extern (D) bool S_ISSOCK()(mode_t mode) { return (mode & S_IFMT) == S_IFSOCK; } } else version (DragonFlyBSD) { @@ -1633,19 +1633,19 @@ else version (DragonFlyBSD) private { - extern (D) bool S_ISTYPE( mode_t mode, uint mask ) + extern (D) bool S_ISTYPE()( mode_t mode, uint mask ) { return ( mode & S_IFMT ) == mask; } } - extern (D) bool S_ISBLK( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); } - extern (D) bool S_ISCHR( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); } - extern (D) bool S_ISDIR( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); } - extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); } - extern (D) bool S_ISREG( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); } - extern (D) bool S_ISLNK( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); } - extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); } + extern (D) bool S_ISBLK()( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); } + extern (D) bool S_ISCHR()( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); } + extern (D) bool S_ISDIR()( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); } + extern (D) bool S_ISFIFO()( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); } + extern (D) bool S_ISREG()( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); } + extern (D) bool S_ISLNK()( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); } + extern (D) bool S_ISSOCK()( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); } } else version (Solaris) { @@ -1666,21 +1666,21 @@ else version (Solaris) private { - extern (D) bool S_ISTYPE(mode_t mode, uint mask) + extern (D) bool S_ISTYPE()(mode_t mode, uint mask) { return (mode & S_IFMT) == mask; } } - extern (D) bool S_ISBLK(mode_t mode) { return S_ISTYPE(mode, S_IFBLK); } - extern (D) bool S_ISCHR(mode_t mode) { return S_ISTYPE(mode, S_IFCHR); } - extern (D) bool S_ISDIR(mode_t mode) { return S_ISTYPE(mode, S_IFDIR); } - extern (D) bool S_ISFIFO(mode_t mode) { return S_ISTYPE(mode, S_IFIFO); } - extern (D) bool S_ISREG(mode_t mode) { return S_ISTYPE(mode, S_IFREG); } - extern (D) bool S_ISLNK(mode_t mode) { return S_ISTYPE(mode, S_IFLNK); } - extern (D) bool S_ISSOCK(mode_t mode) { return S_ISTYPE(mode, S_IFSOCK); } - extern (D) bool S_ISDOOR(mode_t mode) { return S_ISTYPE(mode, S_IFDOOR); } - extern (D) bool S_ISPORT(mode_t mode) { return S_ISTYPE(mode, S_IFPORT); } + extern (D) bool S_ISBLK()(mode_t mode) { return S_ISTYPE(mode, S_IFBLK); } + extern (D) bool S_ISCHR()(mode_t mode) { return S_ISTYPE(mode, S_IFCHR); } + extern (D) bool S_ISDIR()(mode_t mode) { return S_ISTYPE(mode, S_IFDIR); } + extern (D) bool S_ISFIFO()(mode_t mode) { return S_ISTYPE(mode, S_IFIFO); } + extern (D) bool S_ISREG()(mode_t mode) { return S_ISTYPE(mode, S_IFREG); } + extern (D) bool S_ISLNK()(mode_t mode) { return S_ISTYPE(mode, S_IFLNK); } + extern (D) bool S_ISSOCK()(mode_t mode) { return S_ISTYPE(mode, S_IFSOCK); } + extern (D) bool S_ISDOOR()(mode_t mode) { return S_ISTYPE(mode, S_IFDOOR); } + extern (D) bool S_ISPORT()(mode_t mode) { return S_ISTYPE(mode, S_IFPORT); } } else version (CRuntime_Bionic) { @@ -1701,19 +1701,19 @@ else version (CRuntime_Bionic) private { - extern (D) bool S_ISTYPE( uint mode, uint mask ) + extern (D) bool S_ISTYPE()( uint mode, uint mask ) { return ( mode & S_IFMT ) == mask; } } - extern (D) bool S_ISBLK( uint mode ) { return S_ISTYPE( mode, S_IFBLK ); } - extern (D) bool S_ISCHR( uint mode ) { return S_ISTYPE( mode, S_IFCHR ); } - extern (D) bool S_ISDIR( uint mode ) { return S_ISTYPE( mode, S_IFDIR ); } - extern (D) bool S_ISFIFO( uint mode ) { return S_ISTYPE( mode, S_IFIFO ); } - extern (D) bool S_ISREG( uint mode ) { return S_ISTYPE( mode, S_IFREG ); } - extern (D) bool S_ISLNK( uint mode ) { return S_ISTYPE( mode, S_IFLNK ); } - extern (D) bool S_ISSOCK( uint mode ) { return S_ISTYPE( mode, S_IFSOCK ); } + extern (D) bool S_ISBLK()( uint mode ) { return S_ISTYPE( mode, S_IFBLK ); } + extern (D) bool S_ISCHR()( uint mode ) { return S_ISTYPE( mode, S_IFCHR ); } + extern (D) bool S_ISDIR()( uint mode ) { return S_ISTYPE( mode, S_IFDIR ); } + extern (D) bool S_ISFIFO()( uint mode ) { return S_ISTYPE( mode, S_IFIFO ); } + extern (D) bool S_ISREG()( uint mode ) { return S_ISTYPE( mode, S_IFREG ); } + extern (D) bool S_ISLNK()( uint mode ) { return S_ISTYPE( mode, S_IFLNK ); } + extern (D) bool S_ISSOCK()( uint mode ) { return S_ISTYPE( mode, S_IFSOCK ); } // Added since Lollipop int utimensat(int dirfd, const char *pathname, @@ -1740,19 +1740,19 @@ else version (CRuntime_Musl) private { - extern (D) bool S_ISTYPE( mode_t mode, uint mask ) + extern (D) bool S_ISTYPE()( mode_t mode, uint mask ) { return ( mode & S_IFMT ) == mask; } } - extern (D) bool S_ISBLK( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); } - extern (D) bool S_ISCHR( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); } - extern (D) bool S_ISDIR( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); } - extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); } - extern (D) bool S_ISREG( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); } - extern (D) bool S_ISLNK( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); } - extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); } + extern (D) bool S_ISBLK()( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); } + extern (D) bool S_ISCHR()( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); } + extern (D) bool S_ISDIR()( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); } + extern (D) bool S_ISFIFO()( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); } + extern (D) bool S_ISREG()( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); } + extern (D) bool S_ISLNK()( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); } + extern (D) bool S_ISSOCK()( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); } int utimensat(int dirfd, const char *pathname, ref const(timespec)[2] times, int flags); @@ -1776,19 +1776,19 @@ else version (CRuntime_UClibc) private { - extern (D) bool S_ISTYPE( mode_t mode, uint mask ) + extern (D) bool S_ISTYPE()( mode_t mode, uint mask ) { return ( mode & S_IFMT ) == mask; } } - extern (D) bool S_ISBLK( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); } - extern (D) bool S_ISCHR( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); } - extern (D) bool S_ISDIR( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); } - extern (D) bool S_ISFIFO( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); } - extern (D) bool S_ISREG( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); } - extern (D) bool S_ISLNK( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); } - extern (D) bool S_ISSOCK( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); } + extern (D) bool S_ISBLK()( mode_t mode ) { return S_ISTYPE( mode, S_IFBLK ); } + extern (D) bool S_ISCHR()( mode_t mode ) { return S_ISTYPE( mode, S_IFCHR ); } + extern (D) bool S_ISDIR()( mode_t mode ) { return S_ISTYPE( mode, S_IFDIR ); } + extern (D) bool S_ISFIFO()( mode_t mode ) { return S_ISTYPE( mode, S_IFIFO ); } + extern (D) bool S_ISREG()( mode_t mode ) { return S_ISTYPE( mode, S_IFREG ); } + extern (D) bool S_ISLNK()( mode_t mode ) { return S_ISTYPE( mode, S_IFLNK ); } + extern (D) bool S_ISSOCK()( mode_t mode ) { return S_ISTYPE( mode, S_IFSOCK ); } int utimensat(int dirfd, const char *pathname, ref const(timespec)[2] times, int flags); diff --git a/libphobos/libdruntime/core/sys/posix/sys/wait.d b/libphobos/libdruntime/core/sys/posix/sys/wait.d index f6b0674a3b16..131a9400dcf0 100644 --- a/libphobos/libdruntime/core/sys/posix/sys/wait.d +++ b/libphobos/libdruntime/core/sys/posix/sys/wait.d @@ -127,7 +127,7 @@ version (CRuntime_Glibc) private { - extern (D) int __WTERMSIG( int status ) { return status & 0x7F; } + extern (D) int __WTERMSIG()(int status) { return status & 0x7F; } } // @@ -135,128 +135,128 @@ version (CRuntime_Glibc) // C headers as the parameter definition there is different and // much more complicated. // - extern (D) int WEXITSTATUS( int status ) { return ( status & 0xFF00 ) >> 8; } - extern (D) int WIFCONTINUED( int status ) { return status == __W_CONTINUED; } - extern (D) bool WIFEXITED( int status ) { return __WTERMSIG( status ) == 0; } - extern (D) bool WIFSIGNALED( int status ) + extern (D) int WEXITSTATUS()( int status ) { return ( status & 0xFF00 ) >> 8; } + extern (D) int WIFCONTINUED()( int status ) { return status == __W_CONTINUED; } + extern (D) bool WIFEXITED()( int status ) { return __WTERMSIG( status ) == 0; } + extern (D) bool WIFSIGNALED()( int status ) { return ( cast(byte) ( ( status & 0x7F ) + 1 ) >> 1 ) > 0; } - extern (D) bool WIFSTOPPED( int status ) { return ( status & 0xFF ) == 0x7F; } - extern (D) int WSTOPSIG( int status ) { return WEXITSTATUS( status ); } - extern (D) int WTERMSIG( int status ) { return status & 0x7F; } + extern (D) bool WIFSTOPPED()( int status ) { return ( status & 0xFF ) == 0x7F; } + extern (D) int WSTOPSIG()( int status ) { return WEXITSTATUS( status ); } + extern (D) int WTERMSIG()( int status ) { return status & 0x7F; } } else version (Darwin) { @safe pure: - extern (D) int _WSTATUS(int status) { return (status & 0x7F); } - extern (D) int WEXITSTATUS( int status ) { return (status >> 8); } - extern (D) int WIFCONTINUED( int status ) { return status == 0x13; } - extern (D) bool WIFEXITED( int status ) { return _WSTATUS(status) == 0; } - extern (D) bool WIFSIGNALED( int status ) + extern (D) int _WSTATUS()(int status) { return (status & 0x7F); } + extern (D) int WEXITSTATUS()( int status ) { return (status >> 8); } + extern (D) int WIFCONTINUED()( int status ) { return status == 0x13; } + extern (D) bool WIFEXITED()( int status ) { return _WSTATUS(status) == 0; } + extern (D) bool WIFSIGNALED()( int status ) { return _WSTATUS( status ) != _WSTOPPED && _WSTATUS( status ) != 0; } - extern (D) bool WIFSTOPPED( int status ) { return _WSTATUS( status ) == _WSTOPPED; } - extern (D) int WSTOPSIG( int status ) { return status >> 8; } - extern (D) int WTERMSIG( int status ) { return _WSTATUS( status ); } + extern (D) bool WIFSTOPPED()( int status ) { return _WSTATUS( status ) == _WSTOPPED; } + extern (D) int WSTOPSIG()( int status ) { return status >> 8; } + extern (D) int WTERMSIG()( int status ) { return _WSTATUS( status ); } } else version (FreeBSD) { @safe pure: - extern (D) int _WSTATUS(int status) { return (status & 0x7F); } - extern (D) int WEXITSTATUS( int status ) { return (status >> 8); } - extern (D) int WIFCONTINUED( int status ) { return status == 0x13; } - extern (D) bool WIFEXITED( int status ) { return _WSTATUS(status) == 0; } - extern (D) bool WIFSIGNALED( int status ) + extern (D) int _WSTATUS()(int status) { return (status & 0x7F); } + extern (D) int WEXITSTATUS()( int status ) { return (status >> 8); } + extern (D) int WIFCONTINUED()( int status ) { return status == 0x13; } + extern (D) bool WIFEXITED()( int status ) { return _WSTATUS(status) == 0; } + extern (D) bool WIFSIGNALED()( int status ) { return _WSTATUS( status ) != _WSTOPPED && _WSTATUS( status ) != 0; } - extern (D) bool WIFSTOPPED( int status ) { return _WSTATUS( status ) == _WSTOPPED; } - extern (D) int WSTOPSIG( int status ) { return status >> 8; } - extern (D) int WTERMSIG( int status ) { return _WSTATUS( status ); } + extern (D) bool WIFSTOPPED()( int status ) { return _WSTATUS( status ) == _WSTOPPED; } + extern (D) int WSTOPSIG()( int status ) { return status >> 8; } + extern (D) int WTERMSIG()( int status ) { return _WSTATUS( status ); } } else version (NetBSD) { @safe pure: - extern (D) int _WSTATUS(int status) { return (status & 0x7F); } - extern (D) int WEXITSTATUS( int status ) { return (status >> 8); } - extern (D) int WIFCONTINUED( int status ) { return status == 0x13; } - extern (D) bool WIFEXITED( int status ) { return _WSTATUS(status) == 0; } - extern (D) bool WIFSIGNALED( int status ) + extern (D) int _WSTATUS()(int status) { return (status & 0x7F); } + extern (D) int WEXITSTATUS()( int status ) { return (status >> 8); } + extern (D) int WIFCONTINUED()( int status ) { return status == 0x13; } + extern (D) bool WIFEXITED()( int status ) { return _WSTATUS(status) == 0; } + extern (D) bool WIFSIGNALED()( int status ) { return _WSTATUS( status ) != _WSTOPPED && _WSTATUS( status ) != 0; } - extern (D) bool WIFSTOPPED( int status ) { return _WSTATUS( status ) == _WSTOPPED; } - extern (D) int WSTOPSIG( int status ) { return status >> 8; } - extern (D) int WTERMSIG( int status ) { return _WSTATUS( status ); } + extern (D) bool WIFSTOPPED()( int status ) { return _WSTATUS( status ) == _WSTOPPED; } + extern (D) int WSTOPSIG()( int status ) { return status >> 8; } + extern (D) int WTERMSIG()( int status ) { return _WSTATUS( status ); } } else version (OpenBSD) { @safe pure: - extern (D) int _WSTATUS(int status) { return (status & 0x7F); } - extern (D) int WEXITSTATUS(int status) { return (status >> 8) & 0xFF; } - extern (D) int WIFCONTINUED(int status) { return (status & _WCONTINUED) == _WCONTINUED; } - extern (D) bool WIFEXITED(int status) { return _WSTATUS(status) == 0; } - extern (D) bool WIFSIGNALED(int status) + extern (D) int _WSTATUS()(int status) { return (status & 0x7F); } + extern (D) int WEXITSTATUS()(int status) { return (status >> 8) & 0xFF; } + extern (D) int WIFCONTINUED()(int status) { return (status & _WCONTINUED) == _WCONTINUED; } + extern (D) bool WIFEXITED()(int status) { return _WSTATUS(status) == 0; } + extern (D) bool WIFSIGNALED()(int status) { return _WSTATUS(status) != _WSTOPPED && _WSTATUS(status) != 0; } - extern (D) bool WIFSTOPPED(int status) { return (status & 0xFF) == _WSTOPPED; } - extern (D) int WSTOPSIG(int status) { return (status >> 8) & 0xFF; } - extern (D) int WTERMSIG(int status) { return _WSTATUS(status); } + extern (D) bool WIFSTOPPED()(int status) { return (status & 0xFF) == _WSTOPPED; } + extern (D) int WSTOPSIG()(int status) { return (status >> 8) & 0xFF; } + extern (D) int WTERMSIG()(int status) { return _WSTATUS(status); } } else version (DragonFlyBSD) { @safe pure: - extern (D) int _WSTATUS(int status) { return (status & 0x7F); } - extern (D) int WEXITSTATUS( int status ) { return (status >> 8); } - extern (D) int WIFCONTINUED( int status ) { return status == 0x13; } - extern (D) bool WIFEXITED( int status ) { return _WSTATUS(status) == 0; } - extern (D) bool WIFSIGNALED( int status ) + extern (D) int _WSTATUS()(int status) { return (status & 0x7F); } + extern (D) int WEXITSTATUS()( int status ) { return (status >> 8); } + extern (D) int WIFCONTINUED()( int status ) { return status == 0x13; } + extern (D) bool WIFEXITED()( int status ) { return _WSTATUS(status) == 0; } + extern (D) bool WIFSIGNALED()( int status ) { return _WSTATUS( status ) != _WSTOPPED && _WSTATUS( status ) != 0; } - extern (D) bool WIFSTOPPED( int status ) { return _WSTATUS( status ) == _WSTOPPED; } - extern (D) int WSTOPSIG( int status ) { return status >> 8; } - extern (D) int WTERMSIG( int status ) { return _WSTATUS( status ); } + extern (D) bool WIFSTOPPED()( int status ) { return _WSTATUS( status ) == _WSTOPPED; } + extern (D) int WSTOPSIG()( int status ) { return status >> 8; } + extern (D) int WTERMSIG()( int status ) { return _WSTATUS( status ); } } else version (Solaris) { @safe pure: - extern (D) int WEXITSTATUS(int status) { return (status >> 8) & 0xff; } - extern (D) int WIFCONTINUED(int status) { return (status & 0xffff) == 0xffff; } - extern (D) bool WIFEXITED(int status) { return (status & 0xff) == 0; } - extern (D) bool WIFSIGNALED(int status) { return (status & 0xff) > 0 && (status & 0xff00) == 0; } - extern (D) bool WIFSTOPPED(int status) { return (status & 0xff) == 0x7f && (status & 0xff00) != 0; } - extern (D) int WSTOPSIG(int status) { return (status >> 8) & 0x7f; } - extern (D) int WTERMSIG(int status) { return (status & 0x7f); } + extern (D) int WEXITSTATUS()(int status) { return (status >> 8) & 0xff; } + extern (D) int WIFCONTINUED()(int status) { return (status & 0xffff) == 0xffff; } + extern (D) bool WIFEXITED()(int status) { return (status & 0xff) == 0; } + extern (D) bool WIFSIGNALED()(int status) { return (status & 0xff) > 0 && (status & 0xff00) == 0; } + extern (D) bool WIFSTOPPED()(int status) { return (status & 0xff) == 0x7f && (status & 0xff00) != 0; } + extern (D) int WSTOPSIG()(int status) { return (status >> 8) & 0x7f; } + extern (D) int WTERMSIG()(int status) { return (status & 0x7f); } } else version (CRuntime_Bionic) { @safe pure: - extern (D) int WEXITSTATUS( int status ) { return ( status & 0xFF00 ) >> 8; } - extern (D) bool WIFEXITED( int status ) { return WTERMSIG(status) == 0; } - extern (D) bool WIFSIGNALED( int status ) { return WTERMSIG(status + 1) >= 2; } - extern (D) bool WIFSTOPPED( int status ) { return WTERMSIG(status) == 0x7F; } - extern (D) int WSTOPSIG( int status ) { return WEXITSTATUS(status); } - extern (D) int WTERMSIG( int status ) { return status & 0x7F; } + extern (D) int WEXITSTATUS()( int status ) { return ( status & 0xFF00 ) >> 8; } + extern (D) bool WIFEXITED()( int status ) { return WTERMSIG(status) == 0; } + extern (D) bool WIFSIGNALED()( int status ) { return WTERMSIG(status + 1) >= 2; } + extern (D) bool WIFSTOPPED()( int status ) { return WTERMSIG(status) == 0x7F; } + extern (D) int WSTOPSIG()( int status ) { return WEXITSTATUS(status); } + extern (D) int WTERMSIG()( int status ) { return status & 0x7F; } } else version (CRuntime_Musl) { @safe pure: - extern (D) int WEXITSTATUS( int status ) { return ( status & 0xFF00 ) >> 8; } - extern (D) int WIFCONTINUED( int status ) { return status == 0xffff; } - extern (D) bool WIFEXITED( int status ) { return WTERMSIG( status ) == 0; } - extern (D) bool WIFSIGNALED( int status ) { return (status&0xffff)-1U < 0xffU; } - extern (D) bool WIFSTOPPED( int status ) { return cast(short)(((status&0xffff)*0x10001)>>8) > 0x7f00; } - extern (D) int WTERMSIG( int status ) { return status & 0x7F; } + extern (D) int WEXITSTATUS()( int status ) { return ( status & 0xFF00 ) >> 8; } + extern (D) int WIFCONTINUED()( int status ) { return status == 0xffff; } + extern (D) bool WIFEXITED()( int status ) { return WTERMSIG( status ) == 0; } + extern (D) bool WIFSIGNALED()( int status ) { return (status&0xffff)-1U < 0xffU; } + extern (D) bool WIFSTOPPED()( int status ) { return cast(short)(((status&0xffff)*0x10001)>>8) > 0x7f00; } + extern (D) int WTERMSIG()( int status ) { return status & 0x7F; } alias WEXITSTATUS WSTOPSIG; } else version (CRuntime_UClibc) @@ -265,7 +265,7 @@ else version (CRuntime_UClibc) private { - extern (D) int __WTERMSIG( int status ) { return status & 0x7F; } + extern (D) int __WTERMSIG()( int status ) { return status & 0x7F; } } // @@ -273,23 +273,23 @@ else version (CRuntime_UClibc) // C headers as the parameter definition there is different and // much more complicated. // - extern (D) int WEXITSTATUS( int status ) { return ( status & 0xFF00 ) >> 8; } - extern (D) int WIFCONTINUED( int status ) { return status == __W_CONTINUED; } - extern (D) bool WIFEXITED( int status ) { return __WTERMSIG( status ) == 0; } - extern (D) bool WIFSIGNALED( int status ) + extern (D) int WEXITSTATUS()( int status ) { return ( status & 0xFF00 ) >> 8; } + extern (D) int WIFCONTINUED()( int status ) { return status == __W_CONTINUED; } + extern (D) bool WIFEXITED()( int status ) { return __WTERMSIG( status ) == 0; } + extern (D) bool WIFSIGNALED()( int status ) { return ( cast(ulong) ( ( status & 0xffff ) - 1U ) >> 1 ) < 0xffU; } version (MIPS32) { - extern (D) bool WIFSTOPPED( int status ) { return ( status & 0xFF ) == 0x7F; } + extern (D) bool WIFSTOPPED()( int status ) { return ( status & 0xFF ) == 0x7F; } } else { - extern (D) bool WIFSTOPPED( int status ) { return ( status & 0xFF ) == 0x7F && ( status & 0xFF00 ); } + extern (D) bool WIFSTOPPED()( int status ) { return ( status & 0xFF ) == 0x7F && ( status & 0xFF00 ); } } - extern (D) int WSTOPSIG( int status ) { return WEXITSTATUS( status ); } - extern (D) int WTERMSIG( int status ) { return status & 0x7F; } + extern (D) int WSTOPSIG()( int status ) { return WEXITSTATUS( status ); } + extern (D) int WTERMSIG()( int status ) { return status & 0x7F; } } else { diff --git a/libphobos/libdruntime/core/sys/solaris/err.d b/libphobos/libdruntime/core/sys/solaris/err.d index f7876430150e..03bdd7ecb98b 100644 --- a/libphobos/libdruntime/core/sys/solaris/err.d +++ b/libphobos/libdruntime/core/sys/solaris/err.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: Boost License 1.0. - * Authors: Ernesto Castellotti + * Authors: Emily Castellotti */ module core.sys.solaris.err; import core.stdc.stdarg : va_list; diff --git a/libphobos/libdruntime/core/sys/windows/basetsd.d b/libphobos/libdruntime/core/sys/windows/basetsd.d index 1e5a45427c7f..d06bc5744ece 100644 --- a/libphobos/libdruntime/core/sys/windows/basetsd.d +++ b/libphobos/libdruntime/core/sys/windows/basetsd.d @@ -44,20 +44,20 @@ enum ulong ADDRESS_TAG_BIT = 0x40000000000; alias uint UHALF_PTR; alias uint* PUHALF_PTR; - uint HandleToULong(void* h) { return(cast(uint) cast(ULONG_PTR) h); } - int HandleToLong(void* h) { return(cast(int) cast(LONG_PTR) h); } - void* ULongToHandle(uint h) { return(cast(void*) cast(UINT_PTR) h); } - void* LongToHandle(int h) { return(cast(void*) cast(INT_PTR) h); } - uint PtrToUlong(void* p) { return(cast(uint) cast(ULONG_PTR) p); } - uint PtrToUint(void* p) { return(cast(uint) cast(UINT_PTR) p); } - ushort PtrToUshort(void* p) { return(cast(ushort) cast(uint) cast(ULONG_PTR) p); } - int PtrToLong(void* p) { return(cast(int) cast(LONG_PTR) p); } - int PtrToInt(void* p) { return(cast(int) cast(INT_PTR) p); } - short PtrToShort(void* p) { return(cast(short) cast(int) cast(LONG_PTR) p); } - void* IntToPtr(int i) { return(cast(void*) cast(INT_PTR) i); } - void* UIntToPtr(uint ui) { return(cast(void*) cast(UINT_PTR) ui); } - void* LongToPtr(int l) { return(cast(void*) cast(LONG_PTR) l); } - void* ULongToPtr(uint ul) { return(cast(void*) cast(ULONG_PTR) ul); } + uint HandleToULong()(void* h) { return(cast(uint) cast(ULONG_PTR) h); } + int HandleToLong()(void* h) { return(cast(int) cast(LONG_PTR) h); } + void* ULongToHandle()(uint h) { return(cast(void*) cast(UINT_PTR) h); } + void* LongToHandle()(int h) { return(cast(void*) cast(INT_PTR) h); } + uint PtrToUlong()(void* p) { return(cast(uint) cast(ULONG_PTR) p); } + uint PtrToUint()(void* p) { return(cast(uint) cast(UINT_PTR) p); } + ushort PtrToUshort()(void* p) { return(cast(ushort) cast(uint) cast(ULONG_PTR) p); } + int PtrToLong()(void* p) { return(cast(int) cast(LONG_PTR) p); } + int PtrToInt()(void* p) { return(cast(int) cast(INT_PTR) p); } + short PtrToShort()(void* p) { return(cast(short) cast(int) cast(LONG_PTR) p); } + void* IntToPtr()(int i) { return(cast(void*) cast(INT_PTR) i); } + void* UIntToPtr()(uint ui) { return(cast(void*) cast(UINT_PTR) ui); } + void* LongToPtr()(int l) { return(cast(void*) cast(LONG_PTR) l); } + void* ULongToPtr()(uint ul) { return(cast(void*) cast(ULONG_PTR) ul); } } else { alias int __int3264; @@ -72,16 +72,16 @@ enum uint ADDRESS_TAG_BIT = 0x80000000; alias ushort UHALF_PTR; alias ushort* PUHALF_PTR; - uint HandleToUlong(HANDLE h) { return cast(uint) h; } - int HandleToLong(HANDLE h) { return cast(int) h; } - HANDLE LongToHandle(LONG_PTR h) { return cast(HANDLE)h; } + uint HandleToUlong()(HANDLE h) { return cast(uint) h; } + int HandleToLong()(HANDLE h) { return cast(int) h; } + HANDLE LongToHandle()(LONG_PTR h) { return cast(HANDLE)h; } uint PtrToUlong(const(void)* p) { return cast(uint) p; } uint PtrToUint(const(void)* p) { return cast(uint) p; } int PtrToInt(const(void)* p) { return cast(int) p; } ushort PtrToUshort(const(void)* p) { return cast(ushort) p; } short PtrToShort(const(void)* p) { return cast(short) p; } - void* IntToPtr(int i) { return cast(void*) i; } - void* UIntToPtr(uint ui) { return cast(void*) ui; } + void* IntToPtr()(int i) { return cast(void*) i; } + void* UIntToPtr()(uint ui) { return cast(void*) ui; } alias IntToPtr LongToPtr; alias UIntToPtr ULongToPtr; } diff --git a/libphobos/libdruntime/core/sys/windows/commctrl.d b/libphobos/libdruntime/core/sys/windows/commctrl.d index 073587f01c15..fcece45be46b 100644 --- a/libphobos/libdruntime/core/sys/windows/commctrl.d +++ b/libphobos/libdruntime/core/sys/windows/commctrl.d @@ -4937,8 +4937,8 @@ static if (_WIN32_WINNT >= 0x501) { alias NMLINK* PNMLINK; } -uint INDEXTOOVERLAYMASK(uint i) { return i << 8; } -uint INDEXTOSTATEIMAGEMASK(uint i) { return i << 12; } +uint INDEXTOOVERLAYMASK()(uint i) { return i << 8; } +uint INDEXTOSTATEIMAGEMASK()(uint i) { return i << 12; } template HANDLE_WM_NOTIFY(R) { private alias _prm_HANDLE_WM_NOTIFY = extern (Windows) diff --git a/libphobos/libdruntime/core/sys/windows/dde.d b/libphobos/libdruntime/core/sys/windows/dde.d index 975c62e42f31..e4a75c5711ab 100644 --- a/libphobos/libdruntime/core/sys/windows/dde.d +++ b/libphobos/libdruntime/core/sys/windows/dde.d @@ -31,7 +31,7 @@ struct DDEACK { ubyte bAppReturnCode; ubyte _bf; - @property ubyte reserved() { return cast(ubyte) (_bf & 0x3F); } + @property ubyte reserved()() { return cast(ubyte) (_bf & 0x3F); } @property bool fBusy() { return cast(bool) (_bf & 0x40); } @property bool fAck() { return cast(bool) (_bf & 0x80); } @@ -49,7 +49,7 @@ struct DDEADVISE { short cfFormat; @property ushort reserved() { return cast(ushort) (_bf & 0x3FFF); } - @property bool fDeferUpd() { return cast(bool) (_bf & 0x4000); } + @property bool fDeferUpd()() { return cast(bool) (_bf & 0x4000); } @property bool fAckReq() { return cast(bool) (_bf & 0x8000); } @property ushort reserved(ushort r) { @@ -67,12 +67,12 @@ struct DDEDATA { byte _Value; @property ushort unused() { return cast(ushort) (_bf & 0x0FFF); } - @property bool fResponse() { return cast(bool) (_bf & 0x1000); } + @property bool fResponse()() { return cast(bool) (_bf & 0x1000); } @property bool fRelease() { return cast(bool) (_bf & 0x2000); } @property bool reserved() { return cast(bool) (_bf & 0x4000); } @property bool fAckReq() { return cast(bool) (_bf & 0x8000); } - @property byte* Value() return { return &_Value; } + @property byte* Value() { return &_Value; } @property ushort unused(ushort r) { _bf = cast(ushort) ((_bf & ~0x0FFF) | (r & 0x0FFF)); @@ -90,38 +90,38 @@ struct DDEPOKE { short cfFormat; byte _Value; - @property ushort unused() { return cast(ushort) (_bf & 0x1FFF); } - @property bool fRelease() { return cast(bool) (_bf & 0x2000); } - @property ubyte fReserved() { return cast(ubyte) ((_bf & 0xC000) >>> 14); } + @property ushort unused()() { return cast(ushort) (_bf & 0x1FFF); } + @property bool fRelease()() { return cast(bool) (_bf & 0x2000); } + @property ubyte fReserved()() { return cast(ubyte) ((_bf & 0xC000) >>> 14); } - @property byte* Value() return { return &_Value; } + @property byte* Value() { return &_Value; } - @property ushort unused(ushort u) { + @property ushort unused()(ushort u) { _bf = cast(ushort) ((_bf & ~0x1FFF) | (u & 0x1FFF)); return cast(ushort)(u & 0x1FFF); } - @property bool fRelease(bool f) { _bf = cast(ushort) ((_bf & ~0x2000) | (f << 13)); return f; } - @property ubyte fReserved(ubyte r) { _bf = cast(ushort) ((_bf & ~0xC000) | (r << 14)); return r; } + @property bool fRelease()(bool f) { _bf = cast(ushort) ((_bf & ~0x2000) | (f << 13)); return f; } + @property ubyte fReserved()(ubyte r) { _bf = cast(ushort) ((_bf & ~0xC000) | (r << 14)); return r; } } deprecated struct DDELN { ushort _bf; short cfFormat; - @property ushort unused() { return cast(ushort) (_bf & 0x1FFF); } - @property bool fRelease() { return cast(bool) (_bf & 0x2000); } - @property bool fDeferUpd() { return cast(bool) (_bf & 0x4000); } - @property bool fAckReq() { return cast(bool) (_bf & 0x8000); } + @property ushort unused()() { return cast(ushort) (_bf & 0x1FFF); } + @property bool fRelease()() { return cast(bool) (_bf & 0x2000); } + @property bool fDeferUpd()() { return cast(bool) (_bf & 0x4000); } + @property bool fAckReq()() { return cast(bool) (_bf & 0x8000); } - @property ushort unused(ushort u) { + @property ushort unused()(ushort u) { _bf = cast(ushort)((_bf & ~0x1FFF) | (u & 0x1FFF)); return cast(ushort)(u & 0x1FFF); } - @property bool fRelease(bool f) { _bf = cast(ushort) ((_bf & ~0x2000) | (f << 13)); return f; } - @property bool fDeferUpd(bool f) { _bf = cast(ushort) ((_bf & ~0x4000) | (f << 14)); return f; } - @property bool fAckReq(bool f) { _bf = cast(ushort) ((_bf & ~0x8000) | (f << 15)); return f; } + @property bool fRelease()(bool f) { _bf = cast(ushort) ((_bf & ~0x2000) | (f << 13)); return f; } + @property bool fDeferUpd()(bool f) { _bf = cast(ushort) ((_bf & ~0x4000) | (f << 14)); return f; } + @property bool fAckReq()(bool f) { _bf = cast(ushort) ((_bf & ~0x8000) | (f << 15)); return f; } } deprecated struct DDEUP { @@ -129,23 +129,23 @@ deprecated struct DDEUP { short cfFormat; byte _rgb; - @property ushort unused() { return cast(ushort) (_bf & 0x0FFF); } - @property bool fAck() { return cast(bool) (_bf & 0x1000); } - @property bool fRelease() { return cast(bool) (_bf & 0x2000); } - @property bool fReserved() { return cast(bool) (_bf & 0x4000); } - @property bool fAckReq() { return cast(bool) (_bf & 0x8000); } + @property ushort unused()() { return cast(ushort) (_bf & 0x0FFF); } + @property bool fAck()() { return cast(bool) (_bf & 0x1000); } + @property bool fRelease()() { return cast(bool) (_bf & 0x2000); } + @property bool fReserved()() { return cast(bool) (_bf & 0x4000); } + @property bool fAckReq()() { return cast(bool) (_bf & 0x8000); } - @property byte* rgb() return { return &_rgb; } + @property byte* rgb()() { return &_rgb; } - @property ushort unused(ushort r) { + @property ushort unused()(ushort r) { _bf = cast(ushort) ((_bf & ~0x0FFF) | (r & 0x0FFF)); return cast(ushort)(r & 0x0FFF); } - @property bool fAck(bool f) { _bf = cast(ushort) ((_bf & ~0x1000) | (f << 12)); return f; } - @property bool fRelease(bool f) { _bf = cast(ushort) ((_bf & ~0x2000) | (f << 13)); return f; } - @property bool fReserved(bool f) { _bf = cast(ushort) ((_bf & ~0x4000) | (f << 14)); return f; } - @property bool fAckReq(bool f) { _bf = cast(ushort) ((_bf & ~0x8000) | (f << 15)); return f; } + @property bool fAck()(bool f) { _bf = cast(ushort) ((_bf & ~0x1000) | (f << 12)); return f; } + @property bool fRelease()(bool f) { _bf = cast(ushort) ((_bf & ~0x2000) | (f << 13)); return f; } + @property bool fReserved()(bool f) { _bf = cast(ushort) ((_bf & ~0x4000) | (f << 14)); return f; } + @property bool fAckReq()(bool f) { _bf = cast(ushort) ((_bf & ~0x8000) | (f << 15)); return f; } } extern (Windows) nothrow @nogc { diff --git a/libphobos/libdruntime/core/sys/windows/mmsystem.d b/libphobos/libdruntime/core/sys/windows/mmsystem.d index 29c066e7c97a..2ce75aa7888f 100644 --- a/libphobos/libdruntime/core/sys/windows/mmsystem.d +++ b/libphobos/libdruntime/core/sys/windows/mmsystem.d @@ -283,8 +283,8 @@ enum MEVT_F_SHORT=0; enum MEVT_F_LONG=0x80000000; enum MEVT_F_CALLBACK=0x40000000; -BYTE MEVT_EVENTTYPE(DWORD x) { return cast(BYTE)((x>>24) &0xFF); } -DWORD MEVT_EVENTPARM(DWORD x) { return x & 0xFFFFFF; } +BYTE MEVT_EVENTTYPE()(DWORD x) { return cast(BYTE)((x>>24) &0xFF); } +DWORD MEVT_EVENTPARM()(DWORD x) { return x & 0xFFFFFF; } enum MEVT_SHORTMSG=0; enum MEVT_TEMPO=1; @@ -766,22 +766,22 @@ enum MCI_FORMAT_TMSF=10; // Macros -BYTE MCI_HMS_HOUR(DWORD t) { return cast(BYTE)(t); } -BYTE MCI_HMS_MINUTE(DWORD t) { return cast(BYTE)(t>>>8); } -BYTE MCI_HMS_SECOND(DWORD t) { return cast(BYTE)( t>>>16); } -DWORD MCI_MAKE_HMS(BYTE h, BYTE m, BYTE s) { return h |(m<<8)|(cast(DWORD)(s)<<16); } -DWORD MCI_MAKE_MSF(BYTE m, BYTE s, BYTE f) { return m |(s<<8)|(cast(DWORD)(f)<<16); } +BYTE MCI_HMS_HOUR()(DWORD t) { return cast(BYTE)(t); } +BYTE MCI_HMS_MINUTE()(DWORD t) { return cast(BYTE)(t>>>8); } +BYTE MCI_HMS_SECOND()(DWORD t) { return cast(BYTE)( t>>>16); } +DWORD MCI_MAKE_HMS()(BYTE h, BYTE m, BYTE s) { return h |(m<<8)|(cast(DWORD)(s)<<16); } +DWORD MCI_MAKE_MSF()(BYTE m, BYTE s, BYTE f) { return m |(s<<8)|(cast(DWORD)(f)<<16); } DWORD MCI_MAKE_TMSF(BYTE t, BYTE m, BYTE s, BYTE f) { return t |(m<<8)|(s<<16)|(cast(DWORD)(f)<< 24); } -BYTE MCI_MSF_MINUTE(DWORD t) { return cast(BYTE)(t); } -BYTE MCI_MSF_SECOND(DWORD t) { return cast(BYTE)(t >>> 8); } +BYTE MCI_MSF_MINUTE()(DWORD t) { return cast(BYTE)(t); } +BYTE MCI_MSF_SECOND()(DWORD t) { return cast(BYTE)(t >>> 8); } BYTE MCI_MSF_FRAME(DWORD t) { return cast(BYTE)(t >>> 16); } -BYTE MCI_TMSF_TRACK(DWORD t) { return cast(BYTE)(t); } -BYTE MCI_TMSF_MINUTE(DWORD t) { return cast(BYTE)(t>>8); } -BYTE MCI_TMSF_SECOND(DWORD t) { return cast(BYTE)(t>>16); } -BYTE MCI_TMSF_FRAME(DWORD t) { return cast(BYTE)(t>>24); } +BYTE MCI_TMSF_TRACK()(DWORD t) { return cast(BYTE)(t); } +BYTE MCI_TMSF_MINUTE()(DWORD t) { return cast(BYTE)(t>>8); } +BYTE MCI_TMSF_SECOND()(DWORD t) { return cast(BYTE)(t>>16); } +BYTE MCI_TMSF_FRAME()(DWORD t) { return cast(BYTE)(t>>24); } enum MCI_NOTIFY_SUCCESSFUL=1; diff --git a/libphobos/libdruntime/core/sys/windows/ntdef.d b/libphobos/libdruntime/core/sys/windows/ntdef.d index 160443312b4b..e45d0effcd9b 100644 --- a/libphobos/libdruntime/core/sys/windows/ntdef.d +++ b/libphobos/libdruntime/core/sys/windows/ntdef.d @@ -34,10 +34,10 @@ void InitializeObjectAttributes(OBJECT_ATTRIBUTES* p, UNICODE_STRING* n, } pragma(inline, true) @safe pure nothrow @nogc { - bool NT_SUCCESS(NTSTATUS Status) { return Status >= 0; } - bool NT_INFORMATION(NTSTATUS Status) { return ((cast(ULONG) Status) >> 30) == 1; } - bool NT_WARNING(NTSTATUS Status) { return ((cast(ULONG) Status) >> 30) == 2; } - bool NT_ERROR(NTSTATUS Status) { return ((cast(ULONG) Status) >> 30) == 3; } + bool NT_SUCCESS()(NTSTATUS Status) { return Status >= 0; } + bool NT_INFORMATION()(NTSTATUS Status) { return ((cast(ULONG) Status) >> 30) == 1; } + bool NT_WARNING()(NTSTATUS Status) { return ((cast(ULONG) Status) >> 30) == 2; } + bool NT_ERROR()(NTSTATUS Status) { return ((cast(ULONG) Status) >> 30) == 3; } } /* In MinGW, NTSTATUS, UNICODE_STRING, STRING and their associated pointer diff --git a/libphobos/libdruntime/core/sys/windows/ntsecapi.d b/libphobos/libdruntime/core/sys/windows/ntsecapi.d index 77101f669b4a..7088cb10202a 100644 --- a/libphobos/libdruntime/core/sys/windows/ntsecapi.d +++ b/libphobos/libdruntime/core/sys/windows/ntsecapi.d @@ -40,7 +40,7 @@ enum { LSA_MODE_LOG_FULL } -bool LSA_SUCCESS(int x) { return x >= 0; } +bool LSA_SUCCESS()(int x) { return x >= 0; } /* TOTHINKABOUT: These constants don't have ANSI/Unicode versioned * aliases. Should we merge them anyway? diff --git a/libphobos/libdruntime/core/sys/windows/oleauto.d b/libphobos/libdruntime/core/sys/windows/oleauto.d index f4bb40259ab8..cc7b937a03a6 100644 --- a/libphobos/libdruntime/core/sys/windows/oleauto.d +++ b/libphobos/libdruntime/core/sys/windows/oleauto.d @@ -41,7 +41,7 @@ enum DISPATCH_PROPERTYGET = 2; enum DISPATCH_PROPERTYPUT = 4; enum DISPATCH_PROPERTYPUTREF = 8; -//ULONG LHashValOfName(LCID l, OLECHAR* n) { return LHashValOfNameSys(SYSKIND.SYS_WIN32, l, n); } +//ULONG LHashValOfName()(LCID l, OLECHAR* n) { return LHashValOfNameSys(SYSKIND.SYS_WIN32, l, n); } // DAC: These aren't in the 2003 SDK. //MACRO #define WHashValOfLHashVal(h) ((unsigned short)(0x0000ffff&(h))) diff --git a/libphobos/libdruntime/core/sys/windows/shlobj.d b/libphobos/libdruntime/core/sys/windows/shlobj.d index bcd254b18eda..0e292d4c71de 100644 --- a/libphobos/libdruntime/core/sys/windows/shlobj.d +++ b/libphobos/libdruntime/core/sys/windows/shlobj.d @@ -1034,35 +1034,35 @@ struct SHELLFLAGSTATE { BOOL fHideIcons : 1; UINT fRestFlags : 3; */ - @property bool fShowAllObjects() { return cast(bool) (_bf & 0x0001); } - @property bool fShowExtensions() { return cast(bool) (_bf & 0x0002); } - @property bool fNoConfirmRecycle() { return cast(bool) (_bf & 0x0004); } - @property bool fShowSysFiles() { return cast(bool) (_bf & 0x0008); } - @property bool fShowCompColor() { return cast(bool) (_bf & 0x0010); } - @property bool fDoubleClickInWebView() { return cast(bool) (_bf & 0x0020); } - @property bool fDesktopHTML() { return cast(bool) (_bf & 0x0040); } - @property bool fWin95Classic() { return cast(bool) (_bf & 0x0080); } - @property bool fDontPrettyPath() { return cast(bool) (_bf & 0x0100); } - @property bool fShowAttribCol() { return cast(bool) (_bf & 0x0200); } - @property bool fMapNetDrvBtn() { return cast(bool) (_bf & 0x0400); } - @property bool fShowInfoTip() { return cast(bool) (_bf & 0x0800); } - @property bool fHideIcons() { return cast(bool) (_bf & 0x1000); } - @property ubyte fRestFlags() { return cast(ubyte) (_bf >> 13); } - - @property bool fShowAllObjects(bool f) { _bf = cast(ushort) ((_bf & ~0xFFFE) | f); return f; } - @property bool fShowExtensions(bool f) { _bf = cast(ushort) ((_bf & ~0xFFFD) | (f << 1)); return f; } - @property bool fNoConfirmRecycle(bool f) { _bf = cast(ushort) ((_bf & ~0xFFFB) | (f << 2)); return f; } - @property bool fShowSysFiles(bool f) { _bf = cast(ushort) ((_bf & ~0xFFF8) | (f << 3)); return f; } - @property bool fShowCompColor(bool f) { _bf = cast(ushort) ((_bf & ~0xFFEF) | (f << 4)); return f; } - @property bool fDoubleClickInWebView(bool f) { _bf = cast(ushort) ((_bf & ~0xFFDF) | (f << 5)); return f; } - @property bool fDesktopHTML(bool f) { _bf = cast(ushort) ((_bf & ~0xFFBF) | (f << 6)); return f; } - @property bool fWin95Classic(bool f) { _bf = cast(ushort) ((_bf & ~0xFF8F) | (f << 7)); return f; } - @property bool fDontPrettyPath(bool f) { _bf = cast(ushort) ((_bf & ~0xFEFF) | (f << 8)); return f; } - @property bool fShowAttribCol(bool f) { _bf = cast(ushort) ((_bf & ~0xFDFF) | (f << 9)); return f; } - @property bool fMapNetDrvBtn(bool f) { _bf = cast(ushort) ((_bf & ~0xFBFF) | (f << 10)); return f; } - @property bool fShowInfoTip(bool f) { _bf = cast(ushort) ((_bf & ~0xF8FF) | (f << 11)); return f; } - @property bool fHideIcons(bool f) { _bf = cast(ushort) ((_bf & ~0xEFFF) | (f << 12)); return f; } - @property ubyte fRestFlags(ubyte f) { _bf = cast(ushort) ((_bf & ~0x1FFF) | (f << 13)); return cast(ubyte) (f & 7); } + @property bool fShowAllObjects()() { return cast(bool) (_bf & 0x0001); } + @property bool fShowExtensions()() { return cast(bool) (_bf & 0x0002); } + @property bool fNoConfirmRecycle()() { return cast(bool) (_bf & 0x0004); } + @property bool fShowSysFiles()() { return cast(bool) (_bf & 0x0008); } + @property bool fShowCompColor()() { return cast(bool) (_bf & 0x0010); } + @property bool fDoubleClickInWebView()() { return cast(bool) (_bf & 0x0020); } + @property bool fDesktopHTML()() { return cast(bool) (_bf & 0x0040); } + @property bool fWin95Classic()() { return cast(bool) (_bf & 0x0080); } + @property bool fDontPrettyPath()() { return cast(bool) (_bf & 0x0100); } + @property bool fShowAttribCol()() { return cast(bool) (_bf & 0x0200); } + @property bool fMapNetDrvBtn()() { return cast(bool) (_bf & 0x0400); } + @property bool fShowInfoTip()() { return cast(bool) (_bf & 0x0800); } + @property bool fHideIcons()() { return cast(bool) (_bf & 0x1000); } + @property ubyte fRestFlags()() { return cast(ubyte) (_bf >> 13); } + + @property bool fShowAllObjects()(bool f) { _bf = cast(ushort) ((_bf & ~0xFFFE) | f); return f; } + @property bool fShowExtensions()(bool f) { _bf = cast(ushort) ((_bf & ~0xFFFD) | (f << 1)); return f; } + @property bool fNoConfirmRecycle()(bool f) { _bf = cast(ushort) ((_bf & ~0xFFFB) | (f << 2)); return f; } + @property bool fShowSysFiles()(bool f) { _bf = cast(ushort) ((_bf & ~0xFFF8) | (f << 3)); return f; } + @property bool fShowCompColor()(bool f) { _bf = cast(ushort) ((_bf & ~0xFFEF) | (f << 4)); return f; } + @property bool fDoubleClickInWebView()(bool f) { _bf = cast(ushort) ((_bf & ~0xFFDF) | (f << 5)); return f; } + @property bool fDesktopHTML()(bool f) { _bf = cast(ushort) ((_bf & ~0xFFBF) | (f << 6)); return f; } + @property bool fWin95Classic()(bool f) { _bf = cast(ushort) ((_bf & ~0xFF8F) | (f << 7)); return f; } + @property bool fDontPrettyPath()(bool f) { _bf = cast(ushort) ((_bf & ~0xFEFF) | (f << 8)); return f; } + @property bool fShowAttribCol()(bool f) { _bf = cast(ushort) ((_bf & ~0xFDFF) | (f << 9)); return f; } + @property bool fMapNetDrvBtn()(bool f) { _bf = cast(ushort) ((_bf & ~0xFBFF) | (f << 10)); return f; } + @property bool fShowInfoTip()(bool f) { _bf = cast(ushort) ((_bf & ~0xF8FF) | (f << 11)); return f; } + @property bool fHideIcons()(bool f) { _bf = cast(ushort) ((_bf & ~0xEFFF) | (f << 12)); return f; } + @property ubyte fRestFlags()(ubyte f) { _bf = cast(ushort) ((_bf & ~0x1FFF) | (f << 13)); return cast(ubyte) (f & 7); } } alias SHELLFLAGSTATE* LPSHELLFLAGSTATE; @@ -1118,56 +1118,56 @@ static if (_WIN32_WINNT >= 0x500) { BOOL fShowSuperHidden : 1; BOOL fNoNetCrawling : 1; */ - @property bool fShowAllObjects() { return cast(bool) (_bf1 & 0x00000001); } - @property bool fShowExtensions() { return cast(bool) (_bf1 & 0x00000002); } - @property bool fNoConfirmRecycle() { return cast(bool) (_bf1 & 0x00000004); } - @property bool fShowSysFiles() { return cast(bool) (_bf1 & 0x00000008); } - @property bool fShowCompColor() { return cast(bool) (_bf1 & 0x00000010); } - @property bool fDoubleClickInWebView() { return cast(bool) (_bf1 & 0x00000020); } - @property bool fDesktopHTML() { return cast(bool) (_bf1 & 0x00000040); } - @property bool fWin95Classic() { return cast(bool) (_bf1 & 0x00000080); } - @property bool fDontPrettyPath() { return cast(bool) (_bf1 & 0x00000100); } - @property bool fShowAttribCol() { return cast(bool) (_bf1 & 0x00000200); } - @property bool fMapNetDrvBtn() { return cast(bool) (_bf1 & 0x00000400); } - @property bool fShowInfoTip() { return cast(bool) (_bf1 & 0x00000800); } - @property bool fHideIcons() { return cast(bool) (_bf1 & 0x00001000); } - @property bool fWebView() { return cast(bool) (_bf1 & 0x00002000); } - @property bool fFilter() { return cast(bool) (_bf1 & 0x00004000); } - @property bool fShowSuperHidden() { return cast(bool) (_bf1 & 0x00008000); } - @property bool fNoNetCrawling() { return cast(bool) (_bf1 & 0x00010000); } - - @property bool fShowAllObjects(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFFE) | f); return f; } - @property bool fShowExtensions(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFFD) | (f << 1)); return f; } - @property bool fNoConfirmRecycle(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFFB) | (f << 2)); return f; } - @property bool fShowSysFiles(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFF8) | (f << 3)); return f; } - @property bool fShowCompColor(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFEF) | (f << 4)); return f; } - @property bool fDoubleClickInWebView(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFDF) | (f << 5)); return f; } - @property bool fDesktopHTML(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFBF) | (f << 6)); return f; } - @property bool fWin95Classic(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFF8F) | (f << 7)); return f; } - @property bool fDontPrettyPath(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFEFF) | (f << 8)); return f; } - @property bool fShowAttribCol(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFDFF) | (f << 9)); return f; } - @property bool fMapNetDrvBtn(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFBFF) | (f << 10)); return f; } - @property bool fShowInfoTip(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFF8FF) | (f << 11)); return f; } - @property bool fHideIcons(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFEFFF) | (f << 12)); return f; } - @property bool fWebView(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFDFFF) | (f << 13)); return f; } - @property bool fFilter(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFBFFF) | (f << 14)); return f; } - @property bool fShowSuperHidden(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFF8FFF) | (f << 15)); return f; } - @property bool fNoNetCrawling(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFEFFFF) | (f << 16)); return f; } + @property bool fShowAllObjects()() { return cast(bool) (_bf1 & 0x00000001); } + @property bool fShowExtensions()() { return cast(bool) (_bf1 & 0x00000002); } + @property bool fNoConfirmRecycle()() { return cast(bool) (_bf1 & 0x00000004); } + @property bool fShowSysFiles()() { return cast(bool) (_bf1 & 0x00000008); } + @property bool fShowCompColor()() { return cast(bool) (_bf1 & 0x00000010); } + @property bool fDoubleClickInWebView()() { return cast(bool) (_bf1 & 0x00000020); } + @property bool fDesktopHTML()() { return cast(bool) (_bf1 & 0x00000040); } + @property bool fWin95Classic()() { return cast(bool) (_bf1 & 0x00000080); } + @property bool fDontPrettyPath()() { return cast(bool) (_bf1 & 0x00000100); } + @property bool fShowAttribCol()() { return cast(bool) (_bf1 & 0x00000200); } + @property bool fMapNetDrvBtn()() { return cast(bool) (_bf1 & 0x00000400); } + @property bool fShowInfoTip()() { return cast(bool) (_bf1 & 0x00000800); } + @property bool fHideIcons()() { return cast(bool) (_bf1 & 0x00001000); } + @property bool fWebView()() { return cast(bool) (_bf1 & 0x00002000); } + @property bool fFilter()() { return cast(bool) (_bf1 & 0x00004000); } + @property bool fShowSuperHidden()() { return cast(bool) (_bf1 & 0x00008000); } + @property bool fNoNetCrawling()() { return cast(bool) (_bf1 & 0x00010000); } + + @property bool fShowAllObjects()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFFE) | f); return f; } + @property bool fShowExtensions()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFFD) | (f << 1)); return f; } + @property bool fNoConfirmRecycle()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFFB) | (f << 2)); return f; } + @property bool fShowSysFiles()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFF8) | (f << 3)); return f; } + @property bool fShowCompColor()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFEF) | (f << 4)); return f; } + @property bool fDoubleClickInWebView()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFDF) | (f << 5)); return f; } + @property bool fDesktopHTML()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFFBF) | (f << 6)); return f; } + @property bool fWin95Classic()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFF8F) | (f << 7)); return f; } + @property bool fDontPrettyPath()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFEFF) | (f << 8)); return f; } + @property bool fShowAttribCol()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFDFF) | (f << 9)); return f; } + @property bool fMapNetDrvBtn()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFFBFF) | (f << 10)); return f; } + @property bool fShowInfoTip()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFF8FF) | (f << 11)); return f; } + @property bool fHideIcons()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFEFFF) | (f << 12)); return f; } + @property bool fWebView()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFDFFF) | (f << 13)); return f; } + @property bool fFilter()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFFBFFF) | (f << 14)); return f; } + @property bool fShowSuperHidden()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFF8FFF) | (f << 15)); return f; } + @property bool fNoNetCrawling()(bool f) { _bf1 = cast(uint) ((_bf1 & ~0xFFFEFFFF) | (f << 16)); return f; } /* BOOL fSepProcess : 1; BOOL fStartPanelOn : 1; BOOL fShowStartPage : 1; UINT fSpareFlags : 13; */ - @property bool fSepProcess() { return cast(bool) (_bf2 & 0x00000001); } - @property bool fStartPanelOn() { return cast(bool) (_bf2 & 0x00000002); } - @property bool fShowStartPage() { return cast(bool) (_bf2 & 0x00000004); } - @property ushort fSpareFlags() { return cast(ushort) ((_bf2 & 0x0000FFF8) >> 3); } - - @property bool fSepProcess(bool f) { _bf2 = cast(uint) ((_bf2 & ~0xFFFFFFFE) | f); return f; } - @property bool fStartPanelOn(bool f) { _bf2 = cast(uint) ((_bf2 & ~0xFFFFFFFD) | (f << 1)); return f; } - @property bool fShowStartPage(bool f) { _bf2 = cast(uint) ((_bf2 & ~0xFFFFFFFB) | (f << 2)); return f; } - @property ushort fSpareFlags(ushort f) { + @property bool fSepProcess()() { return cast(bool) (_bf2 & 0x00000001); } + @property bool fStartPanelOn()() { return cast(bool) (_bf2 & 0x00000002); } + @property bool fShowStartPage()() { return cast(bool) (_bf2 & 0x00000004); } + @property ushort fSpareFlags()() { return cast(ushort) ((_bf2 & 0x0000FFF8) >> 3); } + + @property bool fSepProcess()(bool f) { _bf2 = cast(uint) ((_bf2 & ~0xFFFFFFFE) | f); return f; } + @property bool fStartPanelOn()(bool f) { _bf2 = cast(uint) ((_bf2 & ~0xFFFFFFFD) | (f << 1)); return f; } + @property bool fShowStartPage()(bool f) { _bf2 = cast(uint) ((_bf2 & ~0xFFFFFFFB) | (f << 2)); return f; } + @property ushort fSpareFlags()(ushort f) { _bf2 = cast(ushort) ((_bf2 & ~0xFFFF0007) | ((f & 0x1FFF) << 3)); return cast(ushort) (f & 0x1FFF); } diff --git a/libphobos/libdruntime/core/sys/windows/stat.d b/libphobos/libdruntime/core/sys/windows/stat.d index 85ed24f93d8c..dfc7d490c42f 100644 --- a/libphobos/libdruntime/core/sys/windows/stat.d +++ b/libphobos/libdruntime/core/sys/windows/stat.d @@ -24,11 +24,11 @@ enum S_IFNAM = 0x5000; @safe pure { -int S_ISREG(int m) { return (m & S_IFMT) == S_IFREG; } -int S_ISBLK(int m) { return (m & S_IFMT) == S_IFBLK; } -int S_ISNAM(int m) { return (m & S_IFMT) == S_IFNAM; } -int S_ISDIR(int m) { return (m & S_IFMT) == S_IFDIR; } -int S_ISCHR(int m) { return (m & S_IFMT) == S_IFCHR; } +int S_ISREG()(int m) { return (m & S_IFMT) == S_IFREG; } +int S_ISBLK()(int m) { return (m & S_IFMT) == S_IFBLK; } +int S_ISNAM()(int m) { return (m & S_IFMT) == S_IFNAM; } +int S_ISDIR()(int m) { return (m & S_IFMT) == S_IFDIR; } +int S_ISCHR()(int m) { return (m & S_IFMT) == S_IFCHR; } } version (CRuntime_Microsoft) diff --git a/libphobos/libdruntime/core/sys/windows/threadaux.d b/libphobos/libdruntime/core/sys/windows/threadaux.d index dae8896d4b08..40b833c1aaf8 100644 --- a/libphobos/libdruntime/core/sys/windows/threadaux.d +++ b/libphobos/libdruntime/core/sys/windows/threadaux.d @@ -311,8 +311,8 @@ struct thread_aux enum TEB_offset_TlsSlots = 0xE10; enum TEB_offset_TlsExpansionSlots = 0xF94; } - void* tlsSlotsAdr(void** teb) { return cast(void*) teb + TEB_offset_TlsSlots; } - ref void* tlsExpansionSlots(void** teb) { return *cast(void**)(cast(void*) teb + TEB_offset_TlsExpansionSlots); } + void* tlsSlotsAdr()(void** teb) { return cast(void*) teb + TEB_offset_TlsSlots; } + ref void* tlsExpansionSlots()(void** teb) { return *cast(void**)(cast(void*) teb + TEB_offset_TlsExpansionSlots); } import core.stdc.string; void*[64] slots = void; diff --git a/libphobos/libdruntime/core/sys/windows/vfw.d b/libphobos/libdruntime/core/sys/windows/vfw.d index c0f22a9fb5b8..313895f4acb4 100644 --- a/libphobos/libdruntime/core/sys/windows/vfw.d +++ b/libphobos/libdruntime/core/sys/windows/vfw.d @@ -2115,75 +2115,75 @@ enum { * message wrapper */ -BOOL capSetCallbackOnError(HWND hWnd, LPVOID fpProc) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_ERROR, 0, cast(LPARAM)fpProc); } -BOOL capSetCallbackOnStatus(HWND hWnd, LPVOID fpProc) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_STATUS, 0, cast(LPARAM)fpProc); } -BOOL capSetCallbackOnYield(HWND hWnd, LPVOID fpProc) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_YIELD, 0, cast(LPARAM)fpProc); } -BOOL capSetCallbackOnFrame(HWND hWnd, LPVOID fpProc) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_FRAME, 0, cast(LPARAM)fpProc); } -BOOL capSetCallbackOnVideoStream(HWND hWnd, LPVOID fpProc) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, cast(LPARAM)fpProc); } -BOOL capSetCallbackOnWaveStream(HWND hWnd, LPVOID fpProc) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_WAVESTREAM, 0, cast(LPARAM)fpProc); } -BOOL capSetCallbackOnCapControl(HWND hWnd, LPVOID fpProc) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_CAPCONTROL, 0, cast(LPARAM)fpProc); } - -BOOL capSetUserData(HWND hWnd, LPARAM lUser) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_USER_DATA, 0, lUser); } -BOOL capGetUserData(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GET_USER_DATA, 0, 0); } - -BOOL capDriverConnect(HWND hWnd, WPARAM i) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_CONNECT, i, 0); } -BOOL capDriverDisconnect(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_DISCONNECT, 0, 0); } -BOOL capDriverGetName(HWND hWnd, LPTSTR szName, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_GET_NAME, wSize, cast(LPARAM)szName); } -BOOL capDriverGetVersion(HWND hWnd, LPTSTR szVer, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_GET_VERSION, wSize, cast(LPARAM)szVer); } -BOOL capDriverGetCaps(HWND hWnd, LPCAPDRIVERCAPS s, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_GET_CAPS, wSize, cast(LPARAM)s); } - -BOOL capFileSetCaptureFile(HWND hWnd, LPTSTR szName) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_SET_CAPTURE_FILE, 0, cast(LPARAM)szName); } -BOOL capFileGetCaptureFile(HWND hWnd, LPTSTR szName, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_GET_CAPTURE_FILE, wSize, cast(LPARAM)szName); } -BOOL capFileAlloc(HWND hWnd, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_ALLOCATE, wSize, 0); } -BOOL capFileSaveAs(HWND hWnd, LPTSTR szName) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_SAVEAS, 0, cast(LPARAM)szName); } -BOOL capFileSetInfoChunk(HWND hWnd, LPCAPINFOCHUNK lpInfoChunk) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_SET_INFOCHUNK, 0, cast(LPARAM)lpInfoChunk); } -BOOL capFileSaveDIB(HWND hWnd, LPTSTR szName) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_SAVEDIB, 0, cast(LPARAM)szName); } - -BOOL capEditCopy(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_EDIT_COPY, 0, 0); } - -BOOL capSetAudioFormat(HWND hWnd, LPWAVEFORMATEX s, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_AUDIOFORMAT, wSize, cast(LPARAM)s); } -DWORD capGetAudioFormat(HWND hWnd, LPWAVEFORMATEX s, WPARAM wSize) { return cast(DWORD)AVICapSM(hWnd, WM_CAP_GET_AUDIOFORMAT, wSize, cast(LPARAM)s); } -DWORD capGetAudioFormatSize(HWND hWnd) { return cast(DWORD)AVICapSM(hWnd, WM_CAP_GET_AUDIOFORMAT, 0, 0); } - -BOOL capDlgVideoFormat(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DLG_VIDEOFORMAT, 0, 0); } -BOOL capDlgVideoSource(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DLG_VIDEOSOURCE, 0, 0); } -BOOL capDlgVideoDisplay(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DLG_VIDEODISPLAY, 0, 0); } -BOOL capDlgVideoCompression(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DLG_VIDEOCOMPRESSION, 0, 0); } - -DWORD capGetVideoFormat(HWND hWnd, void* s, WPARAM wSize) { return cast(DWORD)AVICapSM(hWnd, WM_CAP_GET_VIDEOFORMAT, wSize, cast(LPARAM)s); } -DWORD capGetVideoFormatSize(HWND hWnd) { return cast(DWORD)AVICapSM(hWnd, WM_CAP_GET_VIDEOFORMAT, 0, 0); } -BOOL capSetVideoFormat(HWND hWnd, void* s, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_VIDEOFORMAT, wSize, cast(LPARAM)s); } - -BOOL capPreview(HWND hWnd, BOOL f) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_PREVIEW, cast(WPARAM)f, 0); } -BOOL capPreviewRate(HWND hWnd, WPARAM wMS) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_PREVIEWRATE, wMS, 0); } -BOOL capOverlay(HWND hWnd, BOOL f) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_OVERLAY, cast(WPARAM)f, 0); } -BOOL capPreviewScale(HWND hWnd, BOOL f) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_SCALE, cast(WPARAM)f, 0); } -BOOL capGetStatus(HWND hWnd, LPCAPSTATUS s, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GET_STATUS, wSize, cast(LPARAM)s); } -BOOL capSetScrollPos(HWND hWnd, LPPOINT lpP) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_SCROLL, 0, cast(LPARAM)lpP); } - -BOOL capGrabFrame(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GRAB_FRAME, 0, 0); } -BOOL capGrabFrameNoStop(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0); } - -BOOL capCaptureSequence(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SEQUENCE, 0, 0); } -BOOL capCaptureSequenceNoFile(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SEQUENCE_NOFILE, 0, 0); } -BOOL capCaptureStop(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_STOP, 0, 0); } -BOOL capCaptureAbort(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_ABORT, 0, 0); } - -BOOL capCaptureSingleFrameOpen(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SINGLE_FRAME_OPEN, 0, 0); } -BOOL capCaptureSingleFrameClose(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SINGLE_FRAME_CLOSE, 0, 0); } -BOOL capCaptureSingleFrame(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SINGLE_FRAME, 0, 0); } - -BOOL capCaptureGetSetup(HWND hWnd, LPCAPTUREPARMS s, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GET_SEQUENCE_SETUP, wSize, cast(LPARAM)s); } -BOOL capCaptureSetSetup(HWND hWnd, LPCAPTUREPARMS s, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_SEQUENCE_SETUP, wSize, cast(LPARAM)s); } - -BOOL capSetMCIDeviceName(HWND hWnd, LPTSTR szName) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_MCI_DEVICE, 0, cast(LPARAM)szName); } -BOOL capGetMCIDeviceName(HWND hWnd, LPTSTR szName, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GET_MCI_DEVICE, wSize, cast(LPARAM)szName); } - -BOOL capPaletteOpen(HWND hWnd, LPTSTR szName) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_OPEN, 0, cast(LPARAM)szName); } -BOOL capPaletteSave(HWND hWnd, LPTSTR szName) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_SAVE, 0, cast(LPARAM)szName); } -BOOL capPalettePaste(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_PASTE, 0, 0); } -BOOL capPaletteAuto(HWND hWnd, WPARAM iFrames, LPARAM iColors) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_AUTOCREATE, iFrames, iColors); } -BOOL capPaletteManual(HWND hWnd, WPARAM fGrab, LPARAM iColors) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_MANUALCREATE, fGrab, iColors); } +BOOL capSetCallbackOnError()(HWND hWnd, LPVOID fpProc) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_ERROR, 0, cast(LPARAM)fpProc); } +BOOL capSetCallbackOnStatus()(HWND hWnd, LPVOID fpProc) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_STATUS, 0, cast(LPARAM)fpProc); } +BOOL capSetCallbackOnYield()(HWND hWnd, LPVOID fpProc) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_YIELD, 0, cast(LPARAM)fpProc); } +BOOL capSetCallbackOnFrame()(HWND hWnd, LPVOID fpProc) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_FRAME, 0, cast(LPARAM)fpProc); } +BOOL capSetCallbackOnVideoStream()(HWND hWnd, LPVOID fpProc) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, cast(LPARAM)fpProc); } +BOOL capSetCallbackOnWaveStream()(HWND hWnd, LPVOID fpProc) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_WAVESTREAM, 0, cast(LPARAM)fpProc); } +BOOL capSetCallbackOnCapControl()(HWND hWnd, LPVOID fpProc) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_CALLBACK_CAPCONTROL, 0, cast(LPARAM)fpProc); } + +BOOL capSetUserData()(HWND hWnd, LPARAM lUser) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_USER_DATA, 0, lUser); } +BOOL capGetUserData()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GET_USER_DATA, 0, 0); } + +BOOL capDriverConnect()(HWND hWnd, WPARAM i) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_CONNECT, i, 0); } +BOOL capDriverDisconnect()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_DISCONNECT, 0, 0); } +BOOL capDriverGetName()(HWND hWnd, LPTSTR szName, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_GET_NAME, wSize, cast(LPARAM)szName); } +BOOL capDriverGetVersion()(HWND hWnd, LPTSTR szVer, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_GET_VERSION, wSize, cast(LPARAM)szVer); } +BOOL capDriverGetCaps()(HWND hWnd, LPCAPDRIVERCAPS s, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DRIVER_GET_CAPS, wSize, cast(LPARAM)s); } + +BOOL capFileSetCaptureFile()(HWND hWnd, LPTSTR szName) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_SET_CAPTURE_FILE, 0, cast(LPARAM)szName); } +BOOL capFileGetCaptureFile()(HWND hWnd, LPTSTR szName, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_GET_CAPTURE_FILE, wSize, cast(LPARAM)szName); } +BOOL capFileAlloc()(HWND hWnd, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_ALLOCATE, wSize, 0); } +BOOL capFileSaveAs()(HWND hWnd, LPTSTR szName) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_SAVEAS, 0, cast(LPARAM)szName); } +BOOL capFileSetInfoChunk()(HWND hWnd, LPCAPINFOCHUNK lpInfoChunk) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_SET_INFOCHUNK, 0, cast(LPARAM)lpInfoChunk); } +BOOL capFileSaveDIB()(HWND hWnd, LPTSTR szName) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_FILE_SAVEDIB, 0, cast(LPARAM)szName); } + +BOOL capEditCopy()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_EDIT_COPY, 0, 0); } + +BOOL capSetAudioFormat()(HWND hWnd, LPWAVEFORMATEX s, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_AUDIOFORMAT, wSize, cast(LPARAM)s); } +DWORD capGetAudioFormat()(HWND hWnd, LPWAVEFORMATEX s, WPARAM wSize) { return cast(DWORD)AVICapSM(hWnd, WM_CAP_GET_AUDIOFORMAT, wSize, cast(LPARAM)s); } +DWORD capGetAudioFormatSize()(HWND hWnd) { return cast(DWORD)AVICapSM(hWnd, WM_CAP_GET_AUDIOFORMAT, 0, 0); } + +BOOL capDlgVideoFormat()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DLG_VIDEOFORMAT, 0, 0); } +BOOL capDlgVideoSource()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DLG_VIDEOSOURCE, 0, 0); } +BOOL capDlgVideoDisplay()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DLG_VIDEODISPLAY, 0, 0); } +BOOL capDlgVideoCompression()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_DLG_VIDEOCOMPRESSION, 0, 0); } + +DWORD capGetVideoFormat()(HWND hWnd, void* s, WPARAM wSize) { return cast(DWORD)AVICapSM(hWnd, WM_CAP_GET_VIDEOFORMAT, wSize, cast(LPARAM)s); } +DWORD capGetVideoFormatSize()(HWND hWnd) { return cast(DWORD)AVICapSM(hWnd, WM_CAP_GET_VIDEOFORMAT, 0, 0); } +BOOL capSetVideoFormat()(HWND hWnd, void* s, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_VIDEOFORMAT, wSize, cast(LPARAM)s); } + +BOOL capPreview()(HWND hWnd, BOOL f) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_PREVIEW, cast(WPARAM)f, 0); } +BOOL capPreviewRate()(HWND hWnd, WPARAM wMS) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_PREVIEWRATE, wMS, 0); } +BOOL capOverlay()(HWND hWnd, BOOL f) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_OVERLAY, cast(WPARAM)f, 0); } +BOOL capPreviewScale()(HWND hWnd, BOOL f) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_SCALE, cast(WPARAM)f, 0); } +BOOL capGetStatus()(HWND hWnd, LPCAPSTATUS s, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GET_STATUS, wSize, cast(LPARAM)s); } +BOOL capSetScrollPos()(HWND hWnd, LPPOINT lpP) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_SCROLL, 0, cast(LPARAM)lpP); } + +BOOL capGrabFrame()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GRAB_FRAME, 0, 0); } +BOOL capGrabFrameNoStop()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0); } + +BOOL capCaptureSequence()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SEQUENCE, 0, 0); } +BOOL capCaptureSequenceNoFile()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SEQUENCE_NOFILE, 0, 0); } +BOOL capCaptureStop()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_STOP, 0, 0); } +BOOL capCaptureAbort()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_ABORT, 0, 0); } + +BOOL capCaptureSingleFrameOpen()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SINGLE_FRAME_OPEN, 0, 0); } +BOOL capCaptureSingleFrameClose()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SINGLE_FRAME_CLOSE, 0, 0); } +BOOL capCaptureSingleFrame()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SINGLE_FRAME, 0, 0); } + +BOOL capCaptureGetSetup()(HWND hWnd, LPCAPTUREPARMS s, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GET_SEQUENCE_SETUP, wSize, cast(LPARAM)s); } +BOOL capCaptureSetSetup()(HWND hWnd, LPCAPTUREPARMS s, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_SEQUENCE_SETUP, wSize, cast(LPARAM)s); } + +BOOL capSetMCIDeviceName()(HWND hWnd, LPTSTR szName) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_SET_MCI_DEVICE, 0, cast(LPARAM)szName); } +BOOL capGetMCIDeviceName()(HWND hWnd, LPTSTR szName, WPARAM wSize) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_GET_MCI_DEVICE, wSize, cast(LPARAM)szName); } + +BOOL capPaletteOpen()(HWND hWnd, LPTSTR szName) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_OPEN, 0, cast(LPARAM)szName); } +BOOL capPaletteSave()(HWND hWnd, LPTSTR szName) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_SAVE, 0, cast(LPARAM)szName); } +BOOL capPalettePaste()(HWND hWnd) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_PASTE, 0, 0); } +BOOL capPaletteAuto()(HWND hWnd, WPARAM iFrames, LPARAM iColors) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_AUTOCREATE, iFrames, iColors); } +BOOL capPaletteManual()(HWND hWnd, WPARAM fGrab, LPARAM iColors) { return cast(BOOL)AVICapSM(hWnd, WM_CAP_PAL_MANUALCREATE, fGrab, iColors); } /** * structs diff --git a/libphobos/libdruntime/core/sys/windows/winbase.d b/libphobos/libdruntime/core/sys/windows/winbase.d index 935c7c432cfd..2c2905b6352c 100644 --- a/libphobos/libdruntime/core/sys/windows/winbase.d +++ b/libphobos/libdruntime/core/sys/windows/winbase.d @@ -963,7 +963,7 @@ struct DCB { bool fOutxDsrFlow() { return cast(bool) (_bf & 8); } byte fDtrControl() { return cast(byte) ((_bf & (32+16))>>4); } bool fDsrSensitivity() { return cast(bool) (_bf & 64); } - bool fTXContinueOnXoff() { return cast(bool) (_bf & 128); } + bool fTXContinueOnXoff()() { return cast(bool) (_bf & 128); } bool fOutX() { return cast(bool) (_bf & 256); } bool fInX() { return cast(bool) (_bf & 512); } bool fErrorChar() { return cast(bool) (_bf & 1024); } @@ -1031,9 +1031,9 @@ struct COMSTAT { bool fCtsHold() { return cast(bool) (_bf & 1); } bool fDsrHold() { return cast(bool) (_bf & 2); } - bool fRlsdHold() { return cast(bool) (_bf & 4); } - bool fXoffHold() { return cast(bool) (_bf & 8); } - bool fXoffSent() { return cast(bool) (_bf & 16); } + bool fRlsdHold()() { return cast(bool) (_bf & 4); } + bool fXoffHold()() { return cast(bool) (_bf & 8); } + bool fXoffSent()() { return cast(bool) (_bf & 16); } bool fEof() { return cast(bool) (_bf & 32); } bool fTxim() { return cast(bool) (_bf & 64); } @@ -1494,8 +1494,8 @@ struct LDT_ENTRY { byte LimitHi() { return cast(byte) (Flags2 & 0x0F); } bool Sys() { return cast(bool) (Flags2 & 0x10); } - bool Default_Big() { return cast(bool) (Flags2 & 0x40); } - bool Granularity() { return cast(bool) (Flags2 & 0x80); } + bool Default_Big()() { return cast(bool) (Flags2 & 0x40); } + bool Granularity()() { return cast(bool) (Flags2 & 0x80); } } /+ union HighWord { @@ -2567,8 +2567,8 @@ WINBASEAPI BOOL WINAPI SetEvent(HANDLE); // For compatibility with old core.sys.windows.windows: version (LittleEndian) nothrow @nogc { - BOOL QueryPerformanceCounter(long* lpPerformanceCount) { return QueryPerformanceCounter(cast(PLARGE_INTEGER)lpPerformanceCount); } - BOOL QueryPerformanceFrequency(long* lpFrequency) { return QueryPerformanceFrequency(cast(PLARGE_INTEGER)lpFrequency); } + BOOL QueryPerformanceCounter()(long* lpPerformanceCount) { return QueryPerformanceCounter(cast(PLARGE_INTEGER)lpPerformanceCount); } + BOOL QueryPerformanceFrequency()(long* lpFrequency) { return QueryPerformanceFrequency(cast(PLARGE_INTEGER)lpFrequency); } } mixin DECLARE_AW!("STARTUPINFO"); diff --git a/libphobos/libdruntime/core/sys/windows/wincrypt.d b/libphobos/libdruntime/core/sys/windows/wincrypt.d index cb52d9e717dc..f068a3a7958b 100644 --- a/libphobos/libdruntime/core/sys/windows/wincrypt.d +++ b/libphobos/libdruntime/core/sys/windows/wincrypt.d @@ -44,9 +44,9 @@ const TCHAR[] MS_ENH_RSA_AES_PROV = "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"; } -ALG_ID GET_ALG_CLASS(ALG_ID x) { return x & 0xE000; } -ALG_ID GET_ALG_TYPE (ALG_ID x) { return x & 0x1E00; } -ALG_ID GET_ALG_SID (ALG_ID x) { return x & 0x01FF; } +ALG_ID GET_ALG_CLASS()(ALG_ID x) { return x & 0xE000; } +ALG_ID GET_ALG_TYPE ()(ALG_ID x) { return x & 0x1E00; } +ALG_ID GET_ALG_SID ()(ALG_ID x) { return x & 0x01FF; } enum : ALG_ID { ALG_CLASS_ANY = 0, @@ -214,8 +214,8 @@ enum { CRYPT_SUCCEED = TRUE, } -bool RCRYPT_SUCCEEDED(BOOL r) { return r==CRYPT_SUCCEED; } -bool RCRYPT_FAILED(BOOL r) { return r==CRYPT_FAILED; } +bool RCRYPT_SUCCEEDED()(BOOL r) { return r==CRYPT_SUCCEED; } +bool RCRYPT_FAILED()(BOOL r) { return r==CRYPT_FAILED; } enum { PP_ENUMALGS = 1, diff --git a/libphobos/libdruntime/core/sys/windows/winnt.d b/libphobos/libdruntime/core/sys/windows/winnt.d index ca4a903fb6ae..097a2b6fd435 100644 --- a/libphobos/libdruntime/core/sys/windows/winnt.d +++ b/libphobos/libdruntime/core/sys/windows/winnt.d @@ -858,16 +858,16 @@ enum : WORD { } pure nothrow @nogc { - WORD MAKELANGID(/*USHORT*/uint p, /*USHORT*/ uint s) { return cast(WORD)((s << 10) | p); } - WORD PRIMARYLANGID(/*WORD*/uint lgid) { return cast(WORD)(lgid & 0x3FF); } - WORD SUBLANGID(/*WORD*/uint lgid) { return cast(WORD)(lgid >>> 10); } + WORD MAKELANGID()(/*USHORT*/uint p, /*USHORT*/ uint s) { return cast(WORD)((s << 10) | p); } + WORD PRIMARYLANGID()(/*WORD*/uint lgid) { return cast(WORD)(lgid & 0x3FF); } + WORD SUBLANGID()(/*WORD*/uint lgid) { return cast(WORD)(lgid >>> 10); } - DWORD MAKELCID(/*WORD*/uint lgid, /*WORD*/uint srtid) { return (cast(DWORD) srtid << 16) | cast(DWORD) lgid; } + DWORD MAKELCID()(/*WORD*/uint lgid, /*WORD*/uint srtid) { return (cast(DWORD) srtid << 16) | cast(DWORD) lgid; } // ??? - //DWORD MAKESORTLCID(WORD lgid, WORD srtid, WORD ver) { return (MAKELCID(lgid, srtid)) | ((cast(DWORD)ver) << 20); } - WORD LANGIDFROMLCID(LCID lcid) { return cast(WORD) lcid; } - WORD SORTIDFROMLCID(LCID lcid) { return cast(WORD) ((lcid >>> 16) & 0x0F); } - WORD SORTVERSIONFROMLCID(LCID lcid) { return cast(WORD) ((lcid >>> 20) & 0x0F); } + //DWORD MAKESORTLCID()(WORD lgid, WORD srtid, WORD ver) { return (MAKELCID(lgid, srtid)) | ((cast(DWORD)ver) << 20); } + WORD LANGIDFROMLCID()(LCID lcid) { return cast(WORD) lcid; } + WORD SORTIDFROMLCID()(LCID lcid) { return cast(WORD) ((lcid >>> 16) & 0x0F); } + WORD SORTVERSIONFROMLCID()(LCID lcid) { return cast(WORD) ((lcid >>> 20) & 0x0F); } } enum WORD LANG_SYSTEM_DEFAULT = (SUBLANG_SYS_DEFAULT << 10) | LANG_NEUTRAL; @@ -1555,8 +1555,8 @@ const TCHAR[] enum IMAGE_ORDINAL_FLAG32 = 0x80000000; -ulong IMAGE_ORDINAL64(ulong Ordinal) { return Ordinal & 0xFFFF; } -uint IMAGE_ORDINAL32(uint Ordinal) { return Ordinal & 0xFFFF; } +ulong IMAGE_ORDINAL64()(ulong Ordinal) { return Ordinal & 0xFFFF; } +uint IMAGE_ORDINAL32()(uint Ordinal) { return Ordinal & 0xFFFF; } bool IMAGE_SNAP_BY_ORDINAL32(uint Ordinal) { return (Ordinal & IMAGE_ORDINAL_FLAG32) != 0; @@ -1919,10 +1919,10 @@ static if (_WIN32_WINNT >= 0x501) { } // Macros -BYTE BTYPE(BYTE x) { return cast(BYTE) (x & N_BTMASK); } -bool ISPTR(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT); } -bool ISFCN(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT); } -bool ISARY(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_ARRAY << N_BTSHFT); } +BYTE BTYPE()(BYTE x) { return cast(BYTE) (x & N_BTMASK); } +bool ISPTR()(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT); } +bool ISFCN()(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT); } +bool ISARY()(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_ARRAY << N_BTSHFT); } bool ISTAG(uint x) { return x == IMAGE_SYM_CLASS_STRUCT_TAG || x == IMAGE_SYM_CLASS_UNION_TAG @@ -1932,7 +1932,7 @@ uint INCREF(uint x) { return ((x & ~N_BTMASK) << N_TSHIFT) | (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT) | (x & N_BTMASK); } -uint DECREF(uint x) { return ((x >>> N_TSHIFT) & ~N_BTMASK) | (x & N_BTMASK); } +uint DECREF()(uint x) { return ((x >>> N_TSHIFT) & ~N_BTMASK) | (x & N_BTMASK); } enum DWORD TLS_MINIMUM_AVAILABLE = 64; @@ -1948,9 +1948,9 @@ enum ULONG /* Although these are semantically boolean, they are documented and * implemented to return ULONG; this behaviour is preserved for compatibility */ -ULONG IsReparseTagMicrosoft(ULONG x) { return x & 0x80000000; } -ULONG IsReparseTagHighLatency(ULONG x) { return x & 0x40000000; } -ULONG IsReparseTagNameSurrogate(ULONG x) { return x & 0x20000000; } +ULONG IsReparseTagMicrosoft()(ULONG x) { return x & 0x80000000; } +ULONG IsReparseTagHighLatency()(ULONG x) { return x & 0x40000000; } +ULONG IsReparseTagNameSurrogate()(ULONG x) { return x & 0x20000000; } bool IsReparseTagValid(ULONG x) { return !(x & ~IO_REPARSE_TAG_VALID_VALUES) && (x > IO_REPARSE_TAG_RESERVED_RANGE); @@ -3380,7 +3380,7 @@ struct IMAGE_RESOURCE_DIRECTORY_ENTRY { uint NameOffset() { return Name & 0x7FFFFFFF; } bool NameIsString() { return cast(bool)(Name & 0x80000000); } - uint OffsetToDirectory() { return OffsetToData & 0x7FFFFFFF; } + uint OffsetToDirectory()() { return OffsetToData & 0x7FFFFFFF; } bool DataIsDirectory() { return cast(bool)(OffsetToData & 0x80000000); } uint NameOffset(uint n) { @@ -3498,7 +3498,7 @@ struct IMAGE_CE_RUNTIME_FUNCTION_ENTRY { +/ uint FuncLen() { return (_bf >> 8) & 0x3FFFFF; } bool ThirtyTwoBit() { return cast(bool)(_bf & 0x40000000); } - bool ExceptionFlag() { return cast(bool)(_bf & 0x80000000); } + bool ExceptionFlag()() { return cast(bool)(_bf & 0x80000000); } uint FuncLen(uint f) { _bf = (_bf & ~0x3FFFFF00) | ((f & 0x3FFFFF) << 8); return f & 0x3FFFFF; @@ -3543,8 +3543,8 @@ struct FPO_DATA { ubyte cbRegs() { return cast(ubyte)(_bf & 0x07); } bool fHasSEH() { return cast(bool)(_bf & 0x08); } bool fUseBP() { return cast(bool)(_bf & 0x10); } - bool reserved() { return cast(bool)(_bf & 0x20); } - ubyte cbFrame() { return cast(ubyte)(_bf >> 6); } + bool reserved()() { return cast(bool)(_bf & 0x20); } + ubyte cbFrame()() { return cast(ubyte)(_bf >> 6); } ubyte cbRegs(ubyte c) { _bf = cast(ubyte) ((_bf & ~0x07) | (c & 0x07)); @@ -4108,7 +4108,7 @@ struct PROCESSOR_POWER_POLICY_INFO { uint _bf; bool AllowDemotion() { return cast(bool)(_bf & 1); } - bool AllowPromotion() { return cast(bool)(_bf & 2); } + bool AllowPromotion()() { return cast(bool)(_bf & 2); } bool AllowDemotion(bool a) { _bf = (_bf & ~1) | a; return a; } bool AllowPromotion(bool a) { _bf = (_bf & ~2) | (a << 1); return a; } diff --git a/libphobos/libdruntime/core/sys/windows/winuser.d b/libphobos/libdruntime/core/sys/windows/winuser.d index f6414440783a..a7917b774f4c 100644 --- a/libphobos/libdruntime/core/sys/windows/winuser.d +++ b/libphobos/libdruntime/core/sys/windows/winuser.d @@ -3275,10 +3275,10 @@ struct MENUBARINFO { byte bf_; // Simulated bitfield // BOOL fBarFocused:1; // BOOL fFocused:1; - bool fBarFocused() { return (bf_ & 1) == 1; } - bool fFocused() { return (bf_ & 2) == 2; } - bool fBarFocused(bool b) { bf_ = cast(byte) ((bf_ & 0xFE) | b); return b; } - bool fFocused(bool b) { bf_ = cast(byte) (b ? (bf_ | 2) : bf_ & 0xFD); return b; } + bool fBarFocused()() { return (bf_ & 1) == 1; } + bool fFocused()() { return (bf_ & 2) == 2; } + bool fBarFocused()(bool b) { bf_ = cast(byte) ((bf_ & 0xFE) | b); return b; } + bool fFocused()(bool b) { bf_ = cast(byte) (b ? (bf_ | 2) : bf_ & 0xFD); return b; } } alias MENUBARINFO* PMENUBARINFO; @@ -4424,9 +4424,9 @@ int BroadcastSystemMessageW(DWORD, LPDWORD, UINT, WPARAM, LPARAM); UINT SendInput(UINT, LPINPUT, int); BOOL EnumDisplayMonitors(HDC, LPCRECT, MONITORENUMPROC, LPARAM); BOOL GetMonitorInfoA(HMONITOR, LPMONITORINFO); -extern(D) BOOL GetMonitorInfoA(HMONITOR m, LPMONITORINFOEXA mi) { return GetMonitorInfoA(m, cast(LPMONITORINFO)mi); } +extern(D) BOOL GetMonitorInfoA()(HMONITOR m, LPMONITORINFOEXA mi) { return GetMonitorInfoA(m, cast(LPMONITORINFO)mi); } BOOL GetMonitorInfoW(HMONITOR, LPMONITORINFO); -extern(D) BOOL GetMonitorInfoW(HMONITOR m, LPMONITORINFOEXW mi) { return GetMonitorInfoW(m, cast(LPMONITORINFO)mi); } +extern(D) BOOL GetMonitorInfoW()(HMONITOR m, LPMONITORINFOEXW mi) { return GetMonitorInfoW(m, cast(LPMONITORINFO)mi); } HMONITOR MonitorFromPoint(POINT, DWORD); HMONITOR MonitorFromRect(LPCRECT, DWORD); HMONITOR MonitorFromWindow(HWND, DWORD); diff --git a/libphobos/libdruntime/core/volatile.d b/libphobos/libdruntime/core/volatile.d index 1703450c65fb..76ce3879e0d1 100644 --- a/libphobos/libdruntime/core/volatile.d +++ b/libphobos/libdruntime/core/volatile.d @@ -3,7 +3,7 @@ * * Copyright: Copyright © 2019, The D Language Foundation * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Authors: Walter Bright, Ernesto Castellotti + * Authors: Walter Bright, Emily Castellotti * Source: $(DRUNTIMESRC core/volatile.d) */ diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d index e274fd30e8c4..e9838db4f383 100644 --- a/libphobos/libdruntime/object.d +++ b/libphobos/libdruntime/object.d @@ -3901,9 +3901,11 @@ private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr, assert(s == "abc"); } + // HACK: This is a lie. `_d_arraysetcapacity` is neither `nothrow` nor `pure`, but this lie is // necessary for now to prevent breaking code. -private extern (C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void[]* arrptr) pure nothrow; +import core.internal.array.capacity : _d_arraysetcapacityPureNothrow; +import core.internal.traits: Unqual; /** (Property) Gets the current _capacity of a slice. The _capacity is the size @@ -3918,7 +3920,10 @@ Note: The _capacity of a slice may be impacted by operations on other slices. */ @property size_t capacity(T)(T[] arr) pure nothrow @trusted { - return _d_arraysetcapacity(typeid(T[]), 0, cast(void[]*)&arr); + const isshared = is(T == shared); + alias Unqual_T = Unqual!T; + // The postblit of T may be impure, so we need to use the `pure nothrow` wrapper + return _d_arraysetcapacityPureNothrow!Unqual_T(0, cast(void[]*)&arr, isshared); } /// @@ -3957,7 +3962,12 @@ size_t reserve(T)(ref T[] arr, size_t newcapacity) pure nothrow @trusted if (__ctfe) return newcapacity; else - return _d_arraysetcapacity(typeid(T[]), newcapacity, cast(void[]*)&arr); + { + const isshared = is(T == shared); + alias Unqual_T = Unqual!T; + // The postblit of T may be impure, so we need to use the `pure nothrow` wrapper + return _d_arraysetcapacityPureNothrow!Unqual_T(newcapacity, cast(void[]*)&arr, isshared); + } } /// @@ -4692,6 +4702,7 @@ version (D_ProfileGC) public import core.lifetime : _d_newitemTTrace; public import core.internal.array.construction : _d_newarrayTTrace; public import core.internal.array.construction : _d_newarraymTXTrace; + public import core.internal.array.capacity: _d_arraysetlengthTTrace; } public import core.internal.array.appending : _d_arrayappendcTX; public import core.internal.array.comparison : __cmp; @@ -4705,7 +4716,7 @@ public import core.internal.array.construction : _d_newarraymTX; public import core.internal.array.arrayassign : _d_arrayassign_l; public import core.internal.array.arrayassign : _d_arrayassign_r; public import core.internal.array.arrayassign : _d_arraysetassign; -public import core.internal.array.capacity: _d_arraysetlengthTImpl; +public import core.internal.array.capacity : _d_arraysetlengthT; public import core.internal.dassert: _d_assert_fail; diff --git a/libphobos/libdruntime/rt/lifetime.d b/libphobos/libdruntime/rt/lifetime.d index f77d8b9c4e82..3558976bd084 100644 --- a/libphobos/libdruntime/rt/lifetime.d +++ b/libphobos/libdruntime/rt/lifetime.d @@ -313,119 +313,6 @@ void __doPostblit(void *ptr, size_t len, const TypeInfo ti) } } - -/** -Set the array capacity. - -If the array capacity isn't currently large enough -to hold the requested capacity (in number of elements), then the array is -resized/reallocated to the appropriate size. - -Pass in a requested capacity of 0 to get the current capacity. - -Params: - ti = type info of element type - newcapacity = requested new capacity - p = pointer to array to set. Its `length` is left unchanged. - -Returns: the number of elements that can actually be stored once the resizing is done -*/ -extern(C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void[]* p) @weak -in -{ - assert(ti); - assert(!(*p).length || (*p).ptr); -} -do -{ - auto isshared = typeid(ti) is typeid(TypeInfo_Shared); - auto tinext = unqualify(ti.next); - auto size = tinext.tsize; - version (D_InlineAsm_X86) - { - size_t reqsize = void; - - asm - { - mov EAX, newcapacity; - mul EAX, size; - mov reqsize, EAX; - jnc Lcontinue; - } - } - else version (D_InlineAsm_X86_64) - { - size_t reqsize = void; - - asm - { - mov RAX, newcapacity; - mul RAX, size; - mov reqsize, RAX; - jnc Lcontinue; - } - } - else - { - bool overflow = false; - size_t reqsize = mulu(size, newcapacity, overflow); - if (!overflow) - goto Lcontinue; - } -Loverflow: - onOutOfMemoryError(); - assert(0); -Lcontinue: - - // step 1, see if we can ensure the capacity is valid in-place - auto datasize = (*p).length * size; - auto curCapacity = gc_reserveArrayCapacity((*p).ptr[0 .. datasize], reqsize, isshared); - if (curCapacity != 0) - // in-place worked! - return curCapacity / size; - - if (reqsize <= datasize) - // requested size is less than array size, the current array satisfies - // the request. But this is not an appendable GC array, so return 0. - return 0; - - // step 2, if reserving in-place doesn't work, allocate a new array with at - // least the requested allocated size. - auto attrs = __typeAttrs(tinext, (*p).ptr) | BlkAttr.APPENDABLE; - auto ptr = GC.malloc(reqsize, attrs, tinext); - if (ptr is null) - goto Loverflow; - - // copy the data over. - // note that malloc will have initialized the data we did not request to 0. - memcpy(ptr, (*p).ptr, datasize); - - // handle postblit - __doPostblit(ptr, datasize, tinext); - - if (!(attrs & BlkAttr.NO_SCAN)) - { - // need to memset the newly requested data, except for the data that - // malloc returned that we didn't request. - void *endptr = ptr + reqsize; - void *begptr = ptr + datasize; - - // sanity check - assert(endptr >= begptr); - memset(begptr, 0, endptr - begptr); - } - - *p = ptr[0 .. (*p).length]; - - // set up the correct length. Note that we need to do this here, because - // the GC malloc will automatically set the used size to what we requested. - gc_shrinkArrayUsed(ptr[0 .. datasize], reqsize, isshared); - - curCapacity = gc_reserveArrayCapacity(ptr[0 .. datasize], 0, isshared); - assert(curCapacity); - return curCapacity / size; -} - /** Allocate an array with the garbage collector. @@ -741,259 +628,6 @@ extern (C) void rt_finalizeFromGC(void* p, size_t size, uint attr, TypeInfo type } -/** -Resize a dynamic array by setting the `.length` property - -Newly created elements are initialized to their default value. - -Has two variants: -- `_d_arraysetlengthT` for arrays with elements that initialize to 0 -- `_d_arraysetlengthiT` for non-zero initializers retrieved from `TypeInfo` - ---- -void main() -{ - int[] a = [1, 2]; - a.length = 3; // gets lowered to `_d_arraysetlengthT(typeid(int[]), 3, &a)` -} ---- - -Params: - ti = `TypeInfo` of array - newlength = new value for the array's `.length` - p = pointer to array to update the `.length` of. - While it's cast to `void[]`, its `.length` is still treated as element length. -Returns: `*p` after being updated -*/ -extern (C) void[] _d_arraysetlengthT(const TypeInfo ti, size_t newlength, void[]* p) @weak -in -{ - assert(ti); - assert(!(*p).length || (*p).ptr); -} -do -{ - debug(PRINTF) - { - //printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength); - if (p) - printf("\tp.ptr = %p, p.length = %zd\n", (*p).ptr, (*p).length); - } - - if (newlength <= (*p).length) - { - *p = (*p)[0 .. newlength]; - return *p; - } - auto tinext = unqualify(ti.next); - size_t sizeelem = tinext.tsize; - - /* Calculate: newsize = newlength * sizeelem - */ - bool overflow = false; - version (D_InlineAsm_X86) - { - size_t newsize = void; - - asm pure nothrow @nogc - { - mov EAX, newlength; - mul EAX, sizeelem; - mov newsize, EAX; - setc overflow; - } - } - else version (D_InlineAsm_X86_64) - { - size_t newsize = void; - - asm pure nothrow @nogc - { - mov RAX, newlength; - mul RAX, sizeelem; - mov newsize, RAX; - setc overflow; - } - } - else - { - const size_t newsize = mulu(sizeelem, newlength, overflow); - } - if (overflow) - { - onOutOfMemoryError(); - assert(0); - } - - debug(PRINTF) printf("newsize = %zx, newlength = %zx\n", newsize, newlength); - - if (!(*p).ptr) - { - assert((*p).length == 0); - // pointer was null, need to allocate - auto ptr = GC.malloc(newsize, __typeAttrs(tinext) | BlkAttr.APPENDABLE, tinext); - if (ptr is null) - { - onOutOfMemoryError(); - assert(0); - } - memset(ptr, 0, newsize); - *p = ptr[0 .. newlength]; - return *p; - } - - const size_t size = (*p).length * sizeelem; - const isshared = typeid(ti) is typeid(TypeInfo_Shared); - - /* Attempt to extend past the end of the existing array. - * If not possible, allocate new space for entire array and copy. - */ - void* newdata = (*p).ptr; - if (!gc_expandArrayUsed(newdata[0 .. size], newsize, isshared)) - { - newdata = GC.malloc(newsize, __typeAttrs(tinext, (*p).ptr) | BlkAttr.APPENDABLE, tinext); - if (newdata is null) - { - onOutOfMemoryError(); - assert(0); - } - - newdata[0 .. size] = (*p).ptr[0 .. size]; - - // Do postblit processing, as we are making a copy. - __doPostblit(newdata, size, tinext); - } - - // Zero the unused portion of the newly allocated space - memset(newdata + size, 0, newsize - size); - - *p = newdata[0 .. newlength]; - return *p; -} - -/// ditto -extern (C) void[] _d_arraysetlengthiT(const TypeInfo ti, size_t newlength, void[]* p) @weak -in -{ - assert(!(*p).length || (*p).ptr); -} -do -{ - debug(PRINTF) - { - //printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength); - if (p) - printf("\tp.ptr = %p, p.length = %zd\n", (*p).ptr, (*p).length); - } - - if (newlength <= (*p).length) - { - *p = (*p)[0 .. newlength]; - return *p; - } - auto tinext = unqualify(ti.next); - size_t sizeelem = tinext.tsize; - - /* Calculate: newsize = newlength * sizeelem - */ - bool overflow = false; - version (D_InlineAsm_X86) - { - size_t newsize = void; - - asm pure nothrow @nogc - { - mov EAX, newlength; - mul EAX, sizeelem; - mov newsize, EAX; - setc overflow; - } - } - else version (D_InlineAsm_X86_64) - { - size_t newsize = void; - - asm pure nothrow @nogc - { - mov RAX, newlength; - mul RAX, sizeelem; - mov newsize, RAX; - setc overflow; - } - } - else - { - const size_t newsize = mulu(sizeelem, newlength, overflow); - } - if (overflow) - { - onOutOfMemoryError(); - assert(0); - } - - debug(PRINTF) printf("newsize = %zx, newlength = %zx\n", newsize, newlength); - - static void doInitialize(void *start, void *end, const void[] initializer) - { - if (initializer.length == 1) - { - memset(start, *(cast(ubyte*)initializer.ptr), end - start); - } - else - { - auto q = initializer.ptr; - immutable initsize = initializer.length; - for (; start < end; start += initsize) - { - memcpy(start, q, initsize); - } - } - } - - if (!(*p).ptr) - { - assert((*p).length == 0); - // pointer was null, need to allocate - auto ptr = GC.malloc(newsize, __typeAttrs(tinext) | BlkAttr.APPENDABLE, tinext); - if (ptr is null) - { - onOutOfMemoryError(); - assert(0); - } - doInitialize(ptr, ptr + newsize, tinext.initializer); - *p = ptr[0 .. newlength]; - return *p; - } - - const size_t size = (*p).length * sizeelem; - const isshared = typeid(ti) is typeid(TypeInfo_Shared); - - /* Attempt to extend past the end of the existing array. - * If not possible, allocate new space for entire array and copy. - */ - void* newdata = (*p).ptr; - if (!gc_expandArrayUsed(newdata[0 .. size], newsize, isshared)) - { - newdata = GC.malloc(newsize, __typeAttrs(tinext, (*p).ptr) | BlkAttr.APPENDABLE, tinext); - if (newdata is null) - { - onOutOfMemoryError(); - assert(0); - } - - newdata[0 .. size] = (*p).ptr[0 .. size]; - - // Do postblit processing, as we are making a copy. - __doPostblit(newdata, size, tinext); - } - - // Initialize the unused portion of the newly allocated space - doInitialize(newdata + size, newdata + newsize, tinext.initializer); - *p = newdata[0 .. newlength]; - return *p; -} - - /** Given an array of length `size` that needs to be expanded to `newlength`, compute a new capacity. diff --git a/libphobos/libdruntime/rt/minfo.d b/libphobos/libdruntime/rt/minfo.d index 6e9cd1c8fe14..6f0967441273 100644 --- a/libphobos/libdruntime/rt/minfo.d +++ b/libphobos/libdruntime/rt/minfo.d @@ -492,7 +492,10 @@ struct ModuleGroup if (!bt(ctordone, idx)) { if (!processMod(idx)) + { + .free(ctors); return false; + } } } diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE index a28116af8f23..b1bf0c3c930f 100644 --- a/libphobos/src/MERGE +++ b/libphobos/src/MERGE @@ -1,4 +1,4 @@ -40ffbb3641495b02815891ee004d4c6e173b1089 +5a142da0af7b72bfed314278d14464d8f1147391 The first line of this file holds the git revision number of the last merge done from the dlang/phobos repository. diff --git a/libphobos/src/Makefile.am b/libphobos/src/Makefile.am index 9cbb94fc8276..7529b360eea8 100644 --- a/libphobos/src/Makefile.am +++ b/libphobos/src/Makefile.am @@ -145,15 +145,14 @@ PHOBOS_DSOURCES = etc/c/curl.d etc/c/odbc/odbc32.d etc/c/odbc/odbc64.d \ std/internal/unicode_comp.d std/internal/unicode_decomp.d \ std/internal/unicode_grapheme.d std/internal/unicode_norm.d \ std/internal/unicode_tables.d std/internal/windows/advapi32.d \ - std/internal/windows/bcrypt.d std/json.d std/logger/core.d \ - std/logger/filelogger.d std/logger/multilogger.d \ - std/logger/nulllogger.d std/logger/package.d std/math/algebraic.d \ - std/math/constants.d std/math/exponential.d std/math/hardware.d \ - std/math/operations.d std/math/package.d std/math/remainder.d \ - std/math/rounding.d std/math/traits.d std/math/trigonometry.d \ - std/mathspecial.d std/meta.d std/mmfile.d std/net/curl.d \ - std/net/isemail.d std/numeric.d std/outbuffer.d std/package.d \ - std/parallelism.d std/path.d std/process.d std/random.d \ + std/json.d std/logger/core.d std/logger/filelogger.d \ + std/logger/multilogger.d std/logger/nulllogger.d std/logger/package.d \ + std/math/algebraic.d std/math/constants.d std/math/exponential.d \ + std/math/hardware.d std/math/operations.d std/math/package.d \ + std/math/remainder.d std/math/rounding.d std/math/traits.d \ + std/math/trigonometry.d std/mathspecial.d std/meta.d std/mmfile.d \ + std/net/curl.d std/net/isemail.d std/numeric.d std/outbuffer.d \ + std/package.d std/parallelism.d std/path.d std/process.d std/random.d \ std/range/interfaces.d std/range/package.d std/range/primitives.d \ std/regex/internal/backtracking.d std/regex/internal/generator.d \ std/regex/internal/ir.d std/regex/internal/kickstart.d \ diff --git a/libphobos/src/Makefile.in b/libphobos/src/Makefile.in index 2bbd70f960ad..27ed8788a470 100644 --- a/libphobos/src/Makefile.in +++ b/libphobos/src/Makefile.in @@ -254,7 +254,6 @@ am__dirstamp = $(am__leading_dot)dirstamp @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/internal/unicode_norm.lo \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/internal/unicode_tables.lo \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/internal/windows/advapi32.lo \ -@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/internal/windows/bcrypt.lo \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/json.lo std/logger/core.lo \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/logger/filelogger.lo \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/logger/multilogger.lo \ @@ -618,15 +617,14 @@ libgphobos_la_LINK = $(LIBTOOL) --tag=D $(libgphobos_la_LIBTOOLFLAGS) \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/internal/unicode_comp.d std/internal/unicode_decomp.d \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/internal/unicode_grapheme.d std/internal/unicode_norm.d \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/internal/unicode_tables.d std/internal/windows/advapi32.d \ -@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/internal/windows/bcrypt.d std/json.d std/logger/core.d \ -@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/logger/filelogger.d std/logger/multilogger.d \ -@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/logger/nulllogger.d std/logger/package.d std/math/algebraic.d \ -@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/math/constants.d std/math/exponential.d std/math/hardware.d \ -@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/math/operations.d std/math/package.d std/math/remainder.d \ -@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/math/rounding.d std/math/traits.d std/math/trigonometry.d \ -@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/mathspecial.d std/meta.d std/mmfile.d std/net/curl.d \ -@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/net/isemail.d std/numeric.d std/outbuffer.d std/package.d \ -@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/parallelism.d std/path.d std/process.d std/random.d \ +@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/json.d std/logger/core.d std/logger/filelogger.d \ +@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/logger/multilogger.d std/logger/nulllogger.d std/logger/package.d \ +@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/math/algebraic.d std/math/constants.d std/math/exponential.d \ +@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/math/hardware.d std/math/operations.d std/math/package.d \ +@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/math/remainder.d std/math/rounding.d std/math/traits.d \ +@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/math/trigonometry.d std/mathspecial.d std/meta.d std/mmfile.d \ +@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/net/curl.d std/net/isemail.d std/numeric.d std/outbuffer.d \ +@ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/package.d std/parallelism.d std/path.d std/process.d std/random.d \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/range/interfaces.d std/range/package.d std/range/primitives.d \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/backtracking.d std/regex/internal/generator.d \ @ENABLE_LIBDRUNTIME_ONLY_FALSE@ std/regex/internal/ir.d std/regex/internal/kickstart.d \ @@ -908,7 +906,6 @@ std/internal/windows/$(am__dirstamp): @: > std/internal/windows/$(am__dirstamp) std/internal/windows/advapi32.lo: \ std/internal/windows/$(am__dirstamp) -std/internal/windows/bcrypt.lo: std/internal/windows/$(am__dirstamp) std/json.lo: std/$(am__dirstamp) std/logger/$(am__dirstamp): @$(MKDIR_P) std/logger diff --git a/libphobos/src/std/algorithm/iteration.d b/libphobos/src/std/algorithm/iteration.d index f8e1c05b658a..7923eeee944d 100644 --- a/libphobos/src/std/algorithm/iteration.d +++ b/libphobos/src/std/algorithm/iteration.d @@ -8,6 +8,8 @@ $(BOOKTABLE Cheat Sheet, $(TR $(TH Function Name) $(TH Description)) $(T2 cache, Eagerly evaluates and caches another range's `front`.) +$(T2 lazyCache, + Lazily evaluates and caches another range's `front`, unlike `cache`.) $(T2 cacheBidirectional, As above, but also provides `back` and `popBack`.) $(T2 chunkBy, @@ -50,7 +52,7 @@ $(T2 reduce, $(T2 splitWhen, Lazily splits a range by comparing adjacent elements.) $(T2 splitter, - Lazily splits a range by a separator.) + Lazily splits a range by a separator, element predicate or whitespace.) $(T2 substitute, `[1, 2].substitute(1, 0.1)` returns `[0.1, 2]`.) $(T2 sum, @@ -420,6 +422,203 @@ private struct _Cache(R, bool bidir) } } +/** + * Similar to `cache`, but lazily evaluates the elements. Unlike `cache`, + * this function does not eagerly evaluate the front of the range until + * it's explicitly requested. + * + * This can be useful when evaluation of range elements has side effects that + * should be delayed until actually needed. + * + * See_Also: cache + * + * Params: + * range = an $(REF_ALTTEXT input range, isInputRange, std,range,primitives) + * + * Returns: + * An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) with the lazily cached values of range + */ + +auto lazyCache(Range)(Range range) +if (isInputRange!Range) +{ + return LazyCache!(Range, isBidirectionalRange!Range)(range); +} + +/// +@safe unittest +{ + import std.algorithm.comparison : equal; + import std.range, std.stdio; + import std.typecons : tuple; + + ulong counter = 0; + double fun(int x) + { + ++counter; + // http://en.wikipedia.org/wiki/Quartic_function + return ( (x + 4.0) * (x + 1.0) * (x - 1.0) * (x - 3.0) ) / 14.0 + 0.5; + } + // With lazyCache, front won't be evaluated until requested + counter = 0; + auto result = iota(-4, 5).map!(a => tuple(a, fun(a)))() + .lazyCache(); + // At this point, no elements have been evaluated yet + assert(counter == 0); + // Now access the first element + auto firstElement = result.front; + // Only now the first element is evaluated + assert(counter == 1); + // Process the result lazily + auto filtered = result.filter!(a => a[1] < 0)() + .map!(a => a[0])(); + // Values are calculated as we iterate + assert(equal(filtered, [-3, -2, 2])); + // Only elements we actually accessed were evaluated + assert(counter == iota(-4, 5).length); +} + +private struct LazyCache(R, bool bidir) +{ + import core.exception : RangeError; + + private + { + import std.algorithm.internal : algoFormat; + import std.meta : AliasSeq; + + alias E = ElementType!R; + alias UE = Unqual!E; + + R source; + + static if (bidir) alias CacheTypes = AliasSeq!(UE, UE); + else alias CacheTypes = AliasSeq!UE; + CacheTypes caches; + // Flags to track if front/back have been cached + bool frontCached = false; + static if (bidir) bool backCached = false; + + static assert(isAssignable!(UE, E) && is(UE : E), + algoFormat( + "Cannot instantiate range with %s because %s elements are not assignable to %s.", + R.stringof, + E.stringof, + UE.stringof + ) + ); + } + + this(R range) + { + source = range; + // Don't eagerly evaluate anything in the constructor + } + + static if (isInfinite!R) + enum empty = false; + else + bool empty() @property + { + return source.empty; + } + + mixin ImplementLength!source; + + E front() @property + { + version (assert) if (empty) throw new RangeError(); + // Only evaluate front if it hasn't been cached yet + if (!frontCached && !source.empty) + { + caches[0] = source.front; + frontCached = true; + } + return caches[0]; + } + static if (bidir) E back() @property + { + version (assert) if (empty) throw new RangeError(); + // Only evaluate back if it hasn't been cached yet + if (!backCached && !source.empty) + { + caches[1] = source.back; + backCached = true; + } + return caches[1]; + } + + void popFront() + { + version (assert) if (empty) throw new RangeError(); + source.popFront(); + // Reset the cache state for front + frontCached = false; + } + static if (bidir) void popBack() + { + version (assert) if (empty) throw new RangeError(); + source.popBack(); + // Reset the cache state for back + backCached = false; + } + + static if (isForwardRange!R) + { + private this(R source, ref CacheTypes caches, bool frontCached, bool backCached = false) + { + this.source = source; + this.caches = caches; + this.frontCached = frontCached; + static if (bidir) this.backCached = backCached; + } + typeof(this) save() @property + { + static if (bidir) + return typeof(this)(source.save, caches, frontCached, backCached); + else + return typeof(this)(source.save, caches, frontCached); + } + } + + static if (hasSlicing!R) + { + enum hasEndSlicing = is(typeof(source[size_t.max .. $])); + + static if (hasEndSlicing) + { + private static struct DollarToken{} + enum opDollar = DollarToken.init; + + auto opSlice(size_t low, DollarToken) + { + return typeof(this)(source[low .. $]); + } + } + + static if (!isInfinite!R) + { + typeof(this) opSlice(size_t low, size_t high) + { + return typeof(this)(source[low .. high]); + } + } + else static if (hasEndSlicing) + { + auto opSlice(size_t low, size_t high) + in + { + assert(low <= high, "Bounds error when slicing lazyCache."); + } + do + { + import std.range : takeExactly; + return this[low .. $].takeExactly(high - low); + } + } + } +} + /** Implements the homonym function (also known as `transform`) present in many languages of functional flavor. The call `map!(fun)(range)` @@ -865,8 +1064,8 @@ See_Also: $(REF tee, std,range) template each(alias fun = "a") { import std.meta : AliasSeq; - import std.traits : Parameters; - import std.typecons : Flag, Yes, No; + import std.traits : Parameters, isInstanceOf; + import std.typecons : Flag, Yes, No, Tuple; private: alias BinaryArgs = AliasSeq!(fun, "i", "a"); @@ -912,7 +1111,8 @@ public: Flag!"each" each(Range)(Range r) if (!isForeachIterable!Range && ( isRangeIterable!Range || - __traits(compiles, typeof(r.front).length))) + // Tuples get automatically expanded if function takes right number of args + (isInputRange!Range && isInstanceOf!(Tuple, typeof(r.front))))) { static if (isRangeIterable!Range) { @@ -953,7 +1153,11 @@ public: } else { - // range interface with >2 parameters. + /* Range over Tuples, fun must have correct number of args + * If number of args of fun is <= 2, calling fun(tuple) or fun(idx, tuple) + * will have precendence over fun(tuple.expand). + * Provide types to delegate params to control this. + */ for (auto range = r; !range.empty; range.popFront()) { static if (!is(typeof(fun(r.front.expand)) == Flag!"each")) @@ -2806,10 +3010,10 @@ if (isInputRange!Range) /** Splits a forward range into subranges in places determined by a binary -predicate. +predicate called with adjacent elements. When iterating, one element of `r` is compared with `pred` to the next -element. If `pred` return true, a new subrange is started for the next element. +element. If `pred` returns true, a new subrange is started for the next element. Otherwise, they are part of the same subrange. If the elements are compared with an inequality (!=) operator, consider @@ -2819,7 +3023,8 @@ Params: pred = Predicate for determining where to split. The earlier element in the source range is always given as the first argument. r = A $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) to be split. -Returns: a range of subranges of `r`, split such that within a given subrange, + +Returns: A range of subranges of `r`, split such that within a given subrange, calling `pred` with any pair of adjacent elements as arguments returns `false`. Copying the range currently has reference semantics, but this may change in the future. @@ -2829,7 +3034,7 @@ relations. */ auto splitWhen(alias pred, Range)(Range r) -if (isForwardRange!Range) +if (is(typeof(binaryFun!pred(r.front, r.front)) : bool) && isForwardRange!Range) { import std.functional : not; return ChunkByImpl!(not!pred, not!pred, GroupingOpType.binaryAny, Range)(r); } @@ -4309,19 +4514,23 @@ Implements the homonym function (also known as `accumulate`, $(D compress), `inject`, or `foldl`) present in various programming languages of functional flavor. There is also $(LREF fold) which does the same thing but with the opposite parameter order. -The call `reduce!(fun)(seed, range)` first assigns `seed` to -an internal variable `result`, also called the accumulator. -Then, for each element `x` in `range`, `result = fun(result, x)` -gets evaluated. Finally, `result` is returned. + +* Use `seed` to initialize an internal `accumulator`. +* For each element `e` in $(D range), evaluate `accumulator = fun(result, e)`. +* Return $(D accumulator). + The one-argument version `reduce!(fun)(range)` works similarly, but it uses the first element of the range as the -seed (the range must be non-empty). +seed (the range must be non-empty, else this throws). + +If range has only one element, the functions are never invoked and +`result` and the seed is returned unchanged. Returns: - the accumulated `result` + the accumulated result Params: - fun = one or more functions + fun = one or more functions of the form `Acc function(Acc, ElemT)` See_Also: $(HTTP en.wikipedia.org/wiki/Fold_(higher-order_function), Fold (higher-order function)) @@ -4803,26 +5012,28 @@ languages of functional flavor, iteratively calling one or more predicates. $(P Each predicate in `fun` must take two arguments:) * An accumulator value * An element of the range `r` -$(P Each predicate must return a value which implicitly converts to the +$(P Each function must return a value which implicitly converts to the type of the accumulator.) -$(P For a single predicate, +$(P For a single function, the call `fold!(fun)(range, seed)` will:) -* Use `seed` to initialize an internal variable `result` (also called - the accumulator). -* For each element `e` in $(D range), evaluate `result = fun(result, e)`. -* Return $(D result). +* Use `seed` to initialize an internal `accumulator`. +* For each element `e` in $(D range), evaluate `accumulator = fun(result, e)`. +* Return $(D accumulator). $(P The one-argument version `fold!(fun)(range)` works similarly, but it uses the first element of the range as the seed (the range must be non-empty) and iterates over the remaining elements.) -Multiple results are produced when using multiple predicates. +Multiple results are produced when using multiple functions. + +If range has only one element, the functions are never invoked and +`result` and the seed is returned unchanged. Params: - fun = the predicate function(s) to apply to the elements + fun = one or more functions of the form `Acc function(Acc, ElemT)` See_Also: * $(HTTP en.wikipedia.org/wiki/Fold_(higher-order_function), Fold (higher-order function)) @@ -4913,7 +5124,7 @@ This function is also known as $(HTTP mathworld.wolfram.com/CumulativeSum.html, Cumulative Sum). Params: - fun = one or more functions to use as fold operation + fun = one or more functions of the form `Acc function(Acc, ElemT)` Returns: The function returns a range containing the consecutive reduced values. If @@ -5296,12 +5507,9 @@ empty elements. The predicate is passed to $(REF binaryFun, std,functional) and accepts any callable function that can be executed via `pred(element, s)`. -Notes: +Note: If splitting a string on whitespace and token compression is desired, - consider using `splitter` without specifying a separator. - - If no separator is passed, the $(REF_ALTTEXT, unary, unaryFun, std,functional) - predicate `isTerminator` decides whether to accept an element of `r`. + consider using the `splitter(r)` overload. Params: pred = The predicate for comparing each element with the separator, @@ -5310,7 +5518,6 @@ Params: split. Must support slicing and `.length` or be a narrow string type. s = The element (or range) to be treated as the separator between range segments to be split. - isTerminator = The predicate for deciding where to split the range when no separator is passed keepSeparators = The flag for deciding if the separators are kept Constraints: @@ -5324,16 +5531,16 @@ Returns: the returned range will be likewise. When a range is used a separator, bidirectionality isn't possible. - If keepSeparators is equal to Yes.keepSeparators the output will also contain the + If `keepSeparators` is equal to `Yes.keepSeparators` the output will also contain the separators. If an empty range is given, the result is an empty range. If a range with one separator is given, the result is a range with two empty elements. See_Also: - $(REF _splitter, std,regex) for a version that splits using a regular expression defined separator, - $(REF _split, std,array) for a version that splits eagerly and - $(LREF splitWhen), which compares adjacent elements instead of element against separator. + - $(REF _splitter, std,regex) for a version that splits using a regular expression defined separator. + - $(REF _split, std,array) for a version that splits eagerly. + - $(LREF splitWhen), which compares adjacent elements instead of element against separator. */ auto splitter(alias pred = "a == b", Flag!"keepSeparators" keepSeparators = No.keepSeparators, @@ -5736,29 +5943,6 @@ if (is(typeof(binaryFun!pred(r.front, s)) : bool) .equal([ [[0]], [[1]], [[2]] ])); } -/// Use splitter without a separator -@safe unittest -{ - import std.algorithm.comparison : equal; - import std.range.primitives : front; - - assert(equal(splitter!(a => a == '|')("a|bc|def"), [ "a", "bc", "def" ])); - assert(equal(splitter!(a => a == ' ')("hello world"), [ "hello", "", "world" ])); - - int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ]; - int[][] w = [ [1, 2], [], [3], [4, 5], [] ]; - assert(equal(splitter!(a => a == 0)(a), w)); - - a = [ 0 ]; - assert(equal(splitter!(a => a == 0)(a), [ (int[]).init, (int[]).init ])); - - a = [ 0, 1 ]; - assert(equal(splitter!(a => a == 0)(a), [ [], [1] ])); - - w = [ [0], [1], [2] ]; - assert(equal(splitter!(a => a.front == 1)(w), [ [[0]], [[2]] ])); -} - /// Leading separators, trailing separators, or no separators. @safe unittest { @@ -5798,17 +5982,6 @@ if (is(typeof(binaryFun!pred(r.front, s)) : bool) .retro.equal([ "def", "|", "bc", "|", "a" ])); } -/// Splitting by word lazily -@safe unittest -{ - import std.ascii : isWhite; - import std.algorithm.comparison : equal; - import std.algorithm.iteration : splitter; - - string str = "Hello World!"; - assert(str.splitter!(isWhite).equal(["Hello", "World!"])); -} - @safe unittest { import std.algorithm; @@ -6133,13 +6306,61 @@ if (is(typeof(binaryFun!pred(r.front, s.front)) : bool) assert(words.equal([ "i", "am", "pointing" ])); } -/// ditto +/++ +Lazily splits a range `r` whenever a predicate `isTerminator` returns true for an element. + +As above, two adjacent separators are considered to surround an empty element in +the split range. + +Params: + r = The $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) to be + split. + isTerminator = A $(REF_ALTTEXT unary, unaryFun, std,functional) predicate for + deciding where to split the range. + +Returns: + A forward range of slices of the original range split by whitespace. + +/ auto splitter(alias isTerminator, Range)(Range r) if (isForwardRange!Range && is(typeof(unaryFun!isTerminator(r.front)))) { return SplitterResult!(unaryFun!isTerminator, Range)(r); } +/// +@safe unittest +{ + import std.ascii : isWhite; + import std.algorithm.comparison : equal; + import std.algorithm.iteration : splitter; + + string str = "Hello World\t!"; + assert(str.splitter!(isWhite).equal(["Hello", "World", "!"])); +} + +/// +@safe unittest +{ + import std.algorithm.comparison : equal; + import std.range.primitives : front; + + assert(equal(splitter!(a => a == '|')("a|bc|def"), [ "a", "bc", "def" ])); + assert(equal(splitter!(a => a == ' ')("hello world"), [ "hello", "", "world" ])); + + int[] a = [ 1, 2, 0, 0, 3, 0, 4, 5, 0 ]; + int[][] w = [ [1, 2], [], [3], [4, 5], [] ]; + assert(equal(splitter!(a => a == 0)(a), w)); + + a = [ 0 ]; + assert(equal(splitter!(a => a == 0)(a), [ (int[]).init, (int[]).init ])); + + a = [ 0, 1 ]; + assert(equal(splitter!(a => a == 0)(a), [ [], [1] ])); + + w = [ [0], [1], [2] ]; + assert(equal(splitter!(a => a.front == 1)(w), [ [[0]], [[2]] ])); +} + private struct SplitterResult(alias isTerminator, Range) { import std.algorithm.searching : find; diff --git a/libphobos/src/std/algorithm/searching.d b/libphobos/src/std/algorithm/searching.d index 924ea1c6b64d..e43aeb533172 100644 --- a/libphobos/src/std/algorithm/searching.d +++ b/libphobos/src/std/algorithm/searching.d @@ -776,26 +776,36 @@ if (isInputRange!R && !isInfinite!R) /++ Counts elements in the given - $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) - until the given predicate is true for one of the given `needles`. + $(REF_ALTTEXT input range, isInputRange, std,range,primitives) + until the given predicate is true for one of the given `needles` or `needle`. Params: - pred = The predicate for determining when to stop counting. + pred = Binary predicate for determining when to stop counting, + which will be passed each element of `haystack` and a needle. haystack = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to be - counted. - needles = Either a single element, or a - $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) - of elements, to be evaluated in turn against each - element in `haystack` under the given predicate. + counted. Must be a + $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) to + use multiple needles. + needles = A sequence of values or + $(REF_ALTTEXT forward ranges, isForwardRange, std,range,primitives) + of values, to be evaluated in turn by calling `pred(element, needle)` + with each element of `haystack`. + needle = A value passed as the 2nd argument to `pred`. - Returns: The number of elements which must be popped from the front of + Returns: + - The number of elements which must be popped from the front of `haystack` before reaching an element for which - `startsWith!pred(haystack, needles)` is `true`. If + $(LREF startsWith)`!pred(haystack, needles)` is `true`. + - If `startsWith!pred(haystack, needles)` is not `true` for any element in - `haystack`, then `-1` is returned. If more than one needle is provided, - `countUntil` will wrap the result in a tuple similar to - `Tuple!(ptrdiff_t, "steps", ptrdiff_t needle)` + `haystack`, then `-1` is returned. + - If more than one needle is provided, + `countUntil` will wrap the result in a pseudo-tuple similar to + `Tuple!(ptrdiff_t, "steps", ptrdiff_t, "needle")`. + - `steps` is the count value, which can be implicitly tested for equality. + - `needle` is the index into `needles` which matched. + - Both are `-1` if there was no match. See_Also: $(REF indexOf, std,string) +/ @@ -923,19 +933,29 @@ if (isInputRange!R && assert(countUntil("日本語", '語') == 2); assert(countUntil("日本語", "五") == -1); assert(countUntil("日本語", '五') == -1); - assert(countUntil([0, 7, 12, 22, 9], [12, 22]) == 2); - assert(countUntil([0, 7, 12, 22, 9], 9) == 4); - assert(countUntil!"a > b"([0, 7, 12, 22, 9], 20) == 3); - // supports multiple needles + const arr = [0, 7, 12, 22, 9]; + assert(countUntil(arr, [12, 22]) == 2); + assert(countUntil(arr, 9) == 4); + assert(countUntil!"a > b"(arr, 20) == 3); +} + +/// Multiple needles +@safe unittest +{ auto res = "...hello".countUntil("ha", "he"); assert(res.steps == 3); - assert(res.needle == 1); + assert(res.needle == 1); // the 2nd needle matched // returns -1 if no needle was found res = "hello".countUntil("ha", "hu"); assert(res.steps == -1); assert(res.needle == -1); + + // `steps` can also be implicitly compared + const arr = [0, 7, 12, 22, 9]; + assert(countUntil(arr, 22, 12) == 2); // `12` found after 2 elements + assert(countUntil(arr, 5, 6) == -1); } @safe unittest @@ -1009,7 +1029,24 @@ if (isInputRange!R && assert(10.iota.repeat.joiner.countUntil!(a => a >= 9) == 9); } -/// ditto +/++ + Counts elements in the given + $(REF_ALTTEXT input range, isInputRange, std,range,primitives) + until the given predicate is true for one of the elements of `haystack`. + + Params: + pred = Unary predicate for determining when to stop counting. + haystack = The + $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to be + counted. + + Returns: + - The number of elements which must be popped from the front of + `haystack` before reaching an element for which + $(LREF startsWith)`!pred(haystack)` is `true`. + - If `startsWith!pred(haystack)` is not `true` for any element in + `haystack`, then `-1` is returned. + +/ ptrdiff_t countUntil(alias pred, R)(R haystack) if (isInputRange!R && is(typeof(unaryFun!pred(haystack.front)) : bool)) diff --git a/libphobos/src/std/complex.d b/libphobos/src/std/complex.d index 01e8dd2c1dac..256d0dc2b489 100644 --- a/libphobos/src/std/complex.d +++ b/libphobos/src/std/complex.d @@ -749,9 +749,22 @@ if (is(T R == Complex!R)) /** - Params: z = A complex number. - Returns: The absolute value (or modulus) of `z`. -*/ + * Calculates the absolute value (or modulus) of a complex number. + * + * $(TABLE_SV + * $(TR $(TH $(I z)) $(TH abs(z)) $(TH Notes)) + * $(TR $(TD (0, 0)) $(TD 0) $(TD )) + * $(TR $(TD (NaN, any) or (any, NaN)) $(TD NaN) $(TD )) + * $(TR $(TD (Inf, any) or (any, Inf)) $(TD Inf) $(TD )) + * $(TR $(TD (a, b)) normal case $(TD hypot(a, b)) $(TD Uses algorithm to prevent overflow/underflow )) + * ) + * + * Params: + * z = A complex number of type Complex!T + * + * Returns: + * The absolute value (modulus) of `z` + */ T abs(T)(Complex!T z) @safe pure nothrow @nogc { import std.math.algebraic : hypot; @@ -767,6 +780,26 @@ T abs(T)(Complex!T z) @safe pure nothrow @nogc assert(abs(complex(1.0L, -2.0L)) == core.math.sqrt(5.0L)); } +@safe pure nothrow unittest +{ + { + auto x = Complex!float(-5.016556e-20, 0); + assert(x.abs == 5.016556e-20f); + auto x1 = Complex!float(-5.016556e-20f, 0); + assert(x1.abs == 5.016556e-20f); + auto x2 = Complex!float(5.016556e-20f, 0); + assert(x2.abs == 5.016556e-20f); + } + { + import std.math.traits : isNaN, isInfinity; + assert(Complex!double(double.nan, 0).abs.isNaN); + assert(Complex!double(double.nan, double.nan).abs.isNaN); + assert(Complex!double(double.infinity, 0).abs.isInfinity); + assert(Complex!double(0, double.infinity).abs.isInfinity); + assert(Complex!double(0, 0).abs == 0); + } +} + @safe pure nothrow @nogc unittest { static import core.math; @@ -788,6 +821,7 @@ T abs(T)(Complex!T z) @safe pure nothrow @nogc }} } + /++ Params: z = A complex number. @@ -812,6 +846,7 @@ T sqAbs(T)(Complex!T z) @safe pure nothrow @nogc assert(isClose(sqAbs(complex(1.0f,-1.0f)), 2.0f)); } + /// ditto T sqAbs(T)(const T x) @safe pure nothrow @nogc if (isFloatingPoint!T) diff --git a/libphobos/src/std/container/rbtree.d b/libphobos/src/std/container/rbtree.d index 53697029c970..fe139a56be38 100644 --- a/libphobos/src/std/container/rbtree.d +++ b/libphobos/src/std/container/rbtree.d @@ -1737,6 +1737,26 @@ assert(equal(rbt[], [5])); } } + /** + * Returns a static array of 3 ranges `r` such that `r[0]` is the + * same as the result of `lowerBound(value)`, `r[1]` is the same + * as the result of $(D equalRange(value)), and `r[2]` is the same + * as the result of $(D upperBound(value)). + * + * Complexity: $(BIGOH log(n)) + */ + auto trisect(this This)(Elem e) + { + auto equalRange = this.equalRange(e); + alias RangeType = typeof(equalRange); + RangeType[3] result = [ + RangeType(_begin, equalRange._begin), + equalRange, + RangeType(equalRange._end, _end) + ]; + return result; + } + static if (doUnittest) @safe pure unittest { import std.algorithm.comparison : equal; @@ -2186,6 +2206,11 @@ if ( is(typeof(binaryFun!less((ElementType!Stuff).init, (ElementType!Stuff).init assert(rt1.lowerBound(3).equal([1, 2])); assert(rt1.equalRange(3).equal([3])); assert(rt1[].equal([1, 2, 3, 4, 5])); + + auto t = rt1.trisect(3); + assert(t[0].equal(rt1.lowerBound(3))); + assert(t[1].equal(rt1.equalRange(3))); + assert(t[2].equal(rt1.upperBound(3))); } //immutable checks diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d index 65042b81095f..0d44e5c3565d 100644 --- a/libphobos/src/std/conv.d +++ b/libphobos/src/std/conv.d @@ -19,6 +19,9 @@ $(TR $(TD Strings) $(TD $(LREF text) $(LREF wtext) $(LREF dtext) + $(LREF writeText) + $(LREF writeWText) + $(LREF writeDText) $(LREF hexString) )) $(TR $(TD Numeric) $(TD @@ -540,6 +543,23 @@ template to(T) } } +private T toImpl(T, S)(S) +if (isInputRange!S && isInfinite!S && isExactSomeString!T) +{ + static assert(0, "Cannot convert infinite range to string. " ~ + "Use `std.range.take` or `std.range.takeExactly` to make it finite."); +} + +// Test for issue : https://github.com/dlang/phobos/issues/10559 +@safe pure nothrow unittest +{ + import std.range : repeat; + import std.conv : to; + + // Test that converting an infinite range doesn't compile + static assert(!__traits(compiles, repeat(1).to!string)); +} + /** If the source type is implicitly convertible to the target type, $(D to) simply performs the implicit conversion. @@ -2470,7 +2490,8 @@ if (isIntegral!Target && !is(Target == enum) && alias source = s; } - size_t count = 0; + static if (doCount) + size_t count = 0; if (source.empty) goto Lerr; @@ -2485,7 +2506,8 @@ if (isIntegral!Target && !is(Target == enum) && sign = true; goto case '+'; case '+': - ++count; + static if (doCount) + ++count; source.popFront(); if (source.empty) @@ -2504,7 +2526,8 @@ if (isIntegral!Target && !is(Target == enum) && { Target v = cast(Target) c; - ++count; + static if (doCount) + ++count; source.popFront(); while (!source.empty) @@ -2520,7 +2543,8 @@ if (isIntegral!Target && !is(Target == enum) && // Note: `v` can become negative here in case of parsing // the most negative value: v = cast(Target) (v * 10 + c); - ++count; + static if (doCount) + ++count; source.popFront(); } else @@ -2877,7 +2901,8 @@ do alias s = source; } - size_t count = 0; + static if (doCount) + size_t count = 0; auto found = false; do { @@ -2904,7 +2929,8 @@ do auto nextv = v.mulu(radix, overflow).addu(c - '0', overflow); enforce!ConvOverflowException(!overflow && nextv <= Target.max, "Overflow in integral conversion"); v = cast(Target) nextv; - ++count; + static if (doCount) + ++count; s.popFront(); found = true; } while (!s.empty); @@ -3163,36 +3189,35 @@ if (isFloatingPoint!Target && !is(Target == enum) && enforce(!p.empty, bailOut()); - size_t count = 0; bool sign = false; switch (p.front) { case '-': sign = true; - ++count; + static if (doCount) ++count; p.popFront(); enforce(!p.empty, bailOut()); if (toLower(p.front) == 'i') goto case 'i'; break; case '+': - ++count; + static if (doCount) ++count; p.popFront(); enforce(!p.empty, bailOut()); break; case 'i': case 'I': // inf - ++count; + static if (doCount) ++count; p.popFront(); enforce(!p.empty && toUpper(p.front) == 'N', bailOut("error converting input to floating point")); - ++count; + static if (doCount) ++count; p.popFront(); enforce(!p.empty && toUpper(p.front) == 'F', bailOut("error converting input to floating point")); // skip past the last 'f' - ++count; + static if (doCount) ++count; p.popFront(); advanceSource(); static if (doCount) @@ -3210,7 +3235,7 @@ if (isFloatingPoint!Target && !is(Target == enum) && bool startsWithZero = p.front == '0'; if (startsWithZero) { - ++count; + static if (doCount) ++count; p.popFront(); if (p.empty) { @@ -3228,23 +3253,23 @@ if (isFloatingPoint!Target && !is(Target == enum) && isHex = p.front == 'x' || p.front == 'X'; if (isHex) { - ++count; + static if (doCount) ++count; p.popFront(); } } else if (toLower(p.front) == 'n') { // nan - ++count; + static if (doCount) ++count; p.popFront(); enforce(!p.empty && toUpper(p.front) == 'A', bailOut("error converting input to floating point")); - ++count; + static if (doCount) ++count; p.popFront(); enforce(!p.empty && toUpper(p.front) == 'N', bailOut("error converting input to floating point")); // skip past the last 'n' - ++count; + static if (doCount) ++count; p.popFront(); advanceSource(); static if (doCount) @@ -3332,14 +3357,14 @@ if (isFloatingPoint!Target && !is(Target == enum) && exp += expIter; } exp -= dot; - ++count; + static if (doCount) ++count; p.popFront(); if (p.empty) break; i = p.front; if (i == '_') { - ++count; + static if (doCount) ++count; p.popFront(); if (p.empty) break; @@ -3348,7 +3373,7 @@ if (isFloatingPoint!Target && !is(Target == enum) && } if (i == '.' && !dot) { - ++count; + static if (doCount) ++count; p.popFront(); dot += expIter; } @@ -3373,14 +3398,14 @@ if (isFloatingPoint!Target && !is(Target == enum) && char sexp = 0; int e = 0; - ++count; + static if (doCount) ++count; p.popFront(); enforce(!p.empty, new ConvException("Unexpected end of input")); switch (p.front) { case '-': sexp++; goto case; - case '+': ++count; + case '+': static if (doCount) ++count; p.popFront(); break; default: {} @@ -3392,7 +3417,7 @@ if (isFloatingPoint!Target && !is(Target == enum) && { e = e * 10 + p.front - '0'; } - ++count; + static if (doCount) ++count; p.popFront(); sawDigits = true; } @@ -4098,7 +4123,12 @@ if (isDynamicArray!Target && !is(Target == enum) && auto result = appender!Target(); parseCheck!s(lbracket); - size_t count = 1 + skipWS!(Source, Yes.doCount)(s); + static if (doCount) + size_t count = 1; + static if (doCount) + count += skipWS!(Source, Yes.doCount)(s); + else + skipWS!(Source, No.doCount)(s); if (s.empty) throw convError!(Source, Target)(s); if (s.front == rbracket) @@ -4106,36 +4136,54 @@ if (isDynamicArray!Target && !is(Target == enum) && s.popFront(); static if (doCount) { - return tuple!("data", "count")(result.data, ++count); + ++count; + return tuple!("data", "count")(result.data, count); } else { return result.data; } } - for (;; s.popFront(), count += 1 + skipWS!(Source, Yes.doCount)(s)) + for (;;) { if (!s.empty && s.front == rbracket) break; - auto r = parseElement!(WideElementType!Target, Source, Yes.doCount)(s); - result ~= r.data; - count += r.count + skipWS!(Source, Yes.doCount)(s); + static if (doCount) + { + auto r = parseElement!(WideElementType!Target, Source, Yes.doCount)(s); + result ~= r.data; + count += r.count; + count += skipWS!(Source, Yes.doCount)(s); + } + else + { + auto r = parseElement!(WideElementType!Target, Source, No.doCount)(s); + result ~= r; + skipWS!(Source, No.doCount)(s); + } if (s.empty) throw convError!(Source, Target)(s); if (s.front != comma) break; + s.popFront(); + static if (doCount) + ++count; + static if (doCount) + count += skipWS!(Source, Yes.doCount)(s); + else + skipWS!(Source, No.doCount)(s); } parseCheck!s(rbracket); static if (doCount) { - return tuple!("data", "count")(result.data, ++count); + ++count; + return tuple!("data", "count")(result.data, count); } else { return result.data; } } - /// @safe pure unittest { @@ -4286,7 +4334,12 @@ if (isStaticArray!Target && !is(Target == enum) && Target result = void; parseCheck!s(lbracket); - size_t count = 1 + skipWS!(Source, Yes.doCount)(s); + static if (doCount) + size_t count = 1; + static if (doCount) + count += skipWS!(Source, Yes.doCount)(s); + else + skipWS!(Source, No.doCount)(s); if (s.empty) throw convError!(Source, Target)(s); if (s.front == rbracket) @@ -4298,7 +4351,8 @@ if (isStaticArray!Target && !is(Target == enum) && s.popFront(); static if (doCount) { - return tuple!("data", "count")(result, ++count); + ++count; + return tuple!("data", "count")(result, count); } else { @@ -4306,13 +4360,23 @@ if (isStaticArray!Target && !is(Target == enum) && } } } - for (size_t i = 0; ; s.popFront(), count += 1 + skipWS!(Source, Yes.doCount)(s)) + for (size_t i = 0; ; ) { if (i == result.length) goto Lmanyerr; - auto r = parseElement!(ElementType!Target, Source, Yes.doCount)(s); - result[i++] = r.data; - count += r.count + skipWS!(Source, Yes.doCount)(s); + static if (doCount) + { + auto r = parseElement!(ElementType!Target, Source, Yes.doCount)(s); + result[i++] = r.data; + count += r.count; + count += skipWS!(Source, Yes.doCount)(s); + } + else + { + auto r = parseElement!(ElementType!Target, Source, No.doCount)(s); + result[i++] = r; + skipWS!(Source, No.doCount)(s); + } if (s.empty) throw convError!(Source, Target)(s); if (s.front != comma) @@ -4321,21 +4385,27 @@ if (isStaticArray!Target && !is(Target == enum) && goto Lfewerr; break; } + s.popFront(); + static if (doCount) + ++count; + static if (doCount) + count += skipWS!(Source, Yes.doCount)(s); + else + skipWS!(Source, No.doCount)(s); } parseCheck!s(rbracket); static if (doCount) { - return tuple!("data", "count")(result, ++count); + ++count; + return tuple!("data", "count")(result, count); } else { return result; } - Lmanyerr: throw parseError(text("Too many elements in input, ", result.length, " elements expected.")); - Lfewerr: throw parseError(text("Too few elements in input, ", result.length, " elements expected.")); } @@ -4393,46 +4463,60 @@ if (isAssociativeArray!Target && !is(Target == enum) && alias ValType = typeof(Target.init.values[0]); Target result; + static if (doCount) size_t count; parseCheck!s(lbracket); - size_t count = 1 + skipWS!(Source, Yes.doCount)(s); + static if (doCount) + count = 1 + skipWS!(Source, Yes.doCount)(s); + else + skipWS!(Source, No.doCount)(s); if (s.empty) throw convError!(Source, Target)(s); if (s.front == rbracket) { s.popFront(); + static if (doCount) + return tuple!("data", "count")(result, count + 1); + else + return result; + } + for (;;) + { static if (doCount) { - return tuple!("data", "count")(result, ++count); + auto key = parseElement!(KeyType, Source, Yes.doCount)(s); + count += key.count + skipWS!(Source, Yes.doCount)(s); + parseCheck!s(keyval); + count += 1 + skipWS!(Source, Yes.doCount)(s); + auto val = parseElement!(ValType, Source, Yes.doCount)(s); + count += val.count + skipWS!(Source, Yes.doCount)(s); + result[key.data] = val.data; } else { - return result; + auto key = parseElement!(KeyType, Source, No.doCount)(s); + skipWS!(Source, No.doCount)(s); + parseCheck!s(keyval); + skipWS!(Source, No.doCount)(s); + auto val = parseElement!(ValType, Source, No.doCount)(s); + skipWS!(Source, No.doCount)(s); + result[key] = val; } - } - for (;; s.popFront(), count += 1 + skipWS!(Source, Yes.doCount)(s)) - { - auto key = parseElement!(KeyType, Source, Yes.doCount)(s); - count += key.count + skipWS!(Source, Yes.doCount)(s); - parseCheck!s(keyval); - count += 1 + skipWS!(Source, Yes.doCount)(s); - auto val = parseElement!(ValType, Source, Yes.doCount)(s); - count += val.count + skipWS!(Source, Yes.doCount)(s); - result[key.data] = val.data; if (s.empty) throw convError!(Source, Target)(s); if (s.front != comma) break; + s.popFront(); + static if (doCount) + count += 1 + skipWS!(Source, Yes.doCount)(s); + else + skipWS!(Source, No.doCount)(s); } parseCheck!s(rbracket); static if (doCount) - { - return tuple!("data", "count")(result, ++count); - } + return tuple!("data", "count")(result, count + 1); else - { return result; - } } /// @@ -4489,7 +4573,9 @@ private auto parseEscape(Source, Flag!"doCount" doCount = No.doCount)(ref Source if (isInputRange!Source && isSomeChar!(ElementType!Source)) { parseCheck!s('\\'); - size_t count = 1; + size_t count; + static if (doCount) + count = 1; if (s.empty) throw parseError("Unterminated escape sequence"); @@ -4507,15 +4593,15 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source)) throw parseError("Hex digit is missing"); return isAlpha(c) ? ((c & ~0x20) - ('A' - 10)) : c - '0'; } - // We need to do octals separate, because they need a lookahead to find out, // where the escape sequence ends. auto first = s.front; if (first >= '0' && first <= '7') { dchar c1 = s.front; - ++count; s.popFront(); + static if (doCount) + ++count; if (s.empty) { static if (doCount) @@ -4539,8 +4625,9 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source)) return cast (dchar)(c1 - '0'); } } - ++count; s.popFront(); + static if (doCount) + ++count; dchar c3 = s.front; if (c3 < '0' || c3 > '7') { @@ -4553,8 +4640,9 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source)) return cast (dchar) (8 * (c1 - '0') + (c2 - '0')); } } - ++count; s.popFront(); + static if (doCount) + ++count; if (c1 > '3') throw parseError("Octal sequence is larger than \\377"); static if (doCount) @@ -4585,14 +4673,16 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source)) case 'x': result = getHexDigit() << 4; result |= getHexDigit(); - count += 2; + static if (doCount) + count += 2; break; case 'u': result = getHexDigit() << 12; result |= getHexDigit() << 8; result |= getHexDigit() << 4; result |= getHexDigit(); - count += 4; + static if (doCount) + count += 4; break; case 'U': result = getHexDigit() << 28; @@ -4603,7 +4693,8 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source)) result |= getHexDigit() << 8; result |= getHexDigit() << 4; result |= getHexDigit(); - count += 8; + static if (doCount) + count += 8; break; default: throw parseError("Unknown escape character " ~ to!string(s.front)); @@ -4643,7 +4734,6 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source)) // https://issues.dlang.org/show_bug.cgi?id=9621 (Named Character Entities) //'\&', '\"', ]; - foreach (i ; 0 .. s1.length) { assert(s2[i] == parseEscape(s1[i])); @@ -4696,7 +4786,9 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum } parseCheck!s('\"'); - size_t count = 1; + size_t count; + static if (doCount) + count = 1; if (s.empty) throw convError!(Source, Target)(s); if (s.front == '\"') @@ -4704,13 +4796,13 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum s.popFront(); static if (doCount) { - return tuple!("data", "count")(result.data, ++count); + count++; + return tuple!("data", "count")(result.data, count); } else { return result.data; } - } while (true) { @@ -4722,20 +4814,30 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum s.popFront(); static if (doCount) { - return tuple!("data", "count")(result.data, ++count); + count++; + return tuple!("data", "count")(result.data, count); } else { return result.data; } case '\\': - auto r = parseEscape!(typeof(s), Yes.doCount)(s); - result.put(r[0]); - count += r[1]; + static if (doCount) + { + auto r = parseEscape!(typeof(s), Yes.doCount)(s); + result.put(r[0]); + count += r[1]; + } + else + { + auto r = parseEscape!(typeof(s), No.doCount)(s); + result.put(r); + } break; default: result.put(s.front); - ++count; + static if (doCount) + count++; s.popFront(); break; } @@ -4751,21 +4853,30 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum Unqual!Target c; parseCheck!s('\''); - size_t count = 1; + size_t count; + static if (doCount) + count = 1; if (s.empty) throw convError!(Source, Target)(s); - ++count; // for the following if-else sequence + static if (doCount) + count++; if (s.front != '\\') { c = s.front; s.popFront(); } else - c = parseEscape(s); + { + static if (doCount) + c = parseEscape!(typeof(s), Yes.doCount)(s).data; + else + c = parseEscape!(typeof(s), No.doCount)(s); + } parseCheck!s('\''); static if (doCount) { - return tuple!("data", "count")(c, ++count); + count++; + return tuple!("data", "count")(c, count); } else { @@ -4835,6 +4946,225 @@ if (T.length > 0) { return textImpl!dstring(args); } assert(dtext(cs, ' ', ws, " ", ds) == "今日は 여보세요 Здравствуйте"d); } +// Ensure that ranges are being printed as expected. +@safe unittest +{ + static struct Range + { + int counter = 0; + + @safe pure nothrow @nogc: + bool empty() const => (counter <= 0); + int front() const => counter; + void popFront() { --counter; } + } + + auto m = Range(2); + assert(text(m) == "[2, 1]"); + + const c = Range(3); + assert(text(c) == "const(Range)(3)"); +} + +// Ensure that a usage pattern seen in libraries like "unit-threaded" works. +@safe unittest +{ + static final class Foo + { + override string toString() const @safe + { + return ":-)"; + } + } + + const c = new Foo(); + assert(text(c) == ":-)"); + assert(text(c, " ") == ":-) "); +} + +// Ensure that classes are printed as expected. +@system unittest +{ + import std.string : endsWith, startsWith; + + static final class Bar {} + + // CTFE: `Bar` + // Runtime: `std.conv.__unittest_L4875_C9.Bar` + static assert(text( new Bar () ) == "Bar" ); + assert(text( new Bar () ).endsWith ( ".Bar" )); + static assert(text("=", new Bar (), ".") == "=Bar." ); + assert(text("=", new Bar (), ".").endsWith ( ".Bar." )); + static assert(text( new const(Bar)() ) == "const(Bar)" ); + assert(text( new const(Bar)() ).startsWith( "const(" )); + assert(text( new const(Bar)() ).endsWith ( ".Bar)" )); + static assert(text("=", new const(Bar)(), ".") == "=const(Bar)." ); + assert(text("=", new const(Bar)(), ".").startsWith("=const(" )); + assert(text("=", new const(Bar)(), ".").endsWith ( ".Bar).")); +} + +// Ensure that various types are printed as expected. +@safe unittest +{ + import std.string : endsWith; + + int dummy; + + static struct Foo {} + struct Bar { int i() @safe => dummy; } + + static struct Point + { + int x; + int y; + } + + struct Range + { + bool empty() => dummy > 9; + int front() => dummy; + void popFront() => cast(void) ++dummy; + } + + assert(text(null ) == "null" ); + assert(text(null, null ) == "nullnull" ); + assert(text(0, null, '\0') == "0null\x00"); + + assert(text('\r','\n','\t','\x00') == "\r\n\t\0"); + assert(text("\r\n\t\0" ) == "\r\n\t\0"); + + assert(text( 3141, ) == "3141" ); + assert(text(": ", 3141, '\0') == ": 3141\0"); + assert(text( -3141, ) == "-3141" ); + assert(text(": ", -3141, '\0') == ": -3141\0"); + + () @trusted + { + int* pointer = cast(int*) 3141; + assert(text( pointer, ) == "C45" ); + assert(text(": ", pointer, '\0') == ": C45\0"); + }(); + + assert(text( 3.1415923, ) == "3.14159" ); + assert(text(": ", 3.1415923, '\0') == ": 3.14159\0"); + assert(text( 3.1415923f, ) == "3.14159" ); + assert(text(": ", 3.1415923f, '\0') == ": 3.14159\0"); + + assert(text( !3141, ) == "false" ); + assert(text(": ", !3141, '\0') == ": false\0"); + assert(text( !!3141, ) == "true" ); + assert(text(": ", !!3141, '\0') == ": true\0" ); + + assert(text( Foo(), ) == "Foo()" ); + assert(text(": ", Foo(), '\0') == ": Foo()\0"); + assert(text( const(Foo)(), ) == "const(Foo)()" ); + assert(text(": ", const(Foo)(), '\0') == ": const(Foo)()\0"); + + assert(text( Bar(), ) == "Bar()" ); + assert(text(": ", Bar(), '\0') == ": Bar()\0"); + assert(text( const(Bar)(), ) == "const(Bar)()" ); + assert(text(": ", const(Bar)(), '\0') == ": const(Bar)()\0"); + + assert(text( Point(3, 141), ) == "Point(3, 141)" ); + assert(text(": ", Point(3, 141), '\0') == ": Point(3, 141)\0"); + assert(text( const(Point)(3, 141), ) == "const(Point)(3, 141)" ); + assert(text(": ", const(Point)(3, 141), '\0') == ": const(Point)(3, 141)\0"); + assert(text( shared(Point)(3, 141), ) == "shared(Point)(3, 141)" ); + assert(text(": ", shared(Point)(3, 141), '\0') == ": shared(Point)(3, 141)\0"); + assert(text( immutable(Point)(3, 141), ) == "immutable(Point)(3, 141)" ); + assert(text(": ", immutable(Point)(3, 141), '\0') == ": immutable(Point)(3, 141)\0"); + + dummy = 0; + assert(text( Range(), ) == "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" ); + dummy = 0; + assert(text(": ", Range(), '\0') == ": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\0"); + assert(text( const(Range)(), ) == "const(Range)()" ); + assert(text(": ", const(Range)(), '\0') == ": const(Range)()\0" ); + + void function() @safe fn1; + void delegate() @safe dg1; + assert(text(fn1) == "null"); + assert(text(dg1) == "void delegate() @safe"); + + bool function(bool, int) @safe fn2; + bool delegate(bool, int) @safe dg2; + bool delegate(bool, int) @system dg3; + bool delegate(bool, int) @trusted dg4; + assert(text(fn2) == "null"); + assert(text(dg2) == "bool delegate(bool, int) @safe"); + assert(text(dg3) == "bool delegate(bool, int) @system"); + assert(text(dg4) == "bool delegate(bool, int) @trusted"); +} + +/// Convenience functions for writing arguments to an output range as text. +void writeText(Sink, T...)(ref Sink sink, T args) +if (isOutputRange!(Sink, char) && T.length > 0) +{ + sink.writeTextImpl!string(args); +} + +/// ditto +void writeWText(Sink, T...)(ref Sink sink, T args) +if (isOutputRange!(Sink, wchar) && T.length > 0) +{ + sink.writeTextImpl!wstring(args); +} + +/// ditto +void writeDText(Sink, T...)(ref Sink sink, T args) +if (isOutputRange!(Sink, dchar) && T.length > 0) +{ + sink.writeTextImpl!dstring(args); +} + +/// +@safe unittest +{ + import std.array : appender; + + auto output = appender!string(); + output.writeText("The answer is ", 42); + + assert(output.data == "The answer is 42"); +} + +/// +@safe unittest +{ + import std.array : appender; + + const color = "red"; + auto output = appender!string(); + output.writeText(i"My favorite color is $(color)"); + + assert(output.data == "My favorite color is red"); +} + +@safe unittest +{ + auto capp = appender!string(); + auto wapp = appender!wstring(); + auto dapp = appender!dstring(); + + capp.writeText(42, ' ', 1.5, ": xyz"); + wapp.writeWText(42, ' ', 1.5, ": xyz"); + dapp.writeDText(42, ' ', 1.5, ": xyz"); + + assert(capp.data == "42 1.5: xyz"c); + assert(wapp.data == "42 1.5: xyz"w); + assert(dapp.data == "42 1.5: xyz"d); +} + +// Check range API compliance using OutputRange interface +@system unittest +{ + import std.range.interfaces : OutputRange, outputRangeObject; + import std.range : nullSink; + + OutputRange!char testOutput = outputRangeObject!char(nullSink); + testOutput.writeText(42, ' ', 1.5, ": xyz"); +} + private S textImpl(S, U...)(U args) { static if (U.length == 0) @@ -4855,30 +5185,35 @@ private S textImpl(S, U...)(U args) // assume that on average, parameters will have less // than 20 elements app.reserve(U.length * 20); - // Must be static foreach because of https://issues.dlang.org/show_bug.cgi?id=21209 - static foreach (arg; args) - { - static if ( - isSomeChar!(typeof(arg)) - || isSomeString!(typeof(arg)) - || ( isInputRange!(typeof(arg)) && isSomeChar!(ElementType!(typeof(arg))) ) - ) - app.put(arg); - else static if ( - - is(immutable typeof(arg) == immutable uint) || is(immutable typeof(arg) == immutable ulong) || - is(immutable typeof(arg) == immutable int) || is(immutable typeof(arg) == immutable long) - ) - // https://issues.dlang.org/show_bug.cgi?id=17712#c15 - app.put(textImpl!(S)(arg)); - else - app.put(to!S(arg)); - } - + app.writeTextImpl!S(args); return app.data; } } +private void writeTextImpl(S, Sink, U...)(ref Sink sink, U args) +if (isSomeString!S && isOutputRange!(Sink, ElementEncodingType!S)) +{ + // Must be static foreach because of https://issues.dlang.org/show_bug.cgi?id=21209 + static foreach (arg; args) + { + static if ( + isSomeChar!(typeof(arg)) + || isSomeString!(typeof(arg)) + || ( isInputRange!(typeof(arg)) && isSomeChar!(ElementType!(typeof(arg))) ) + ) + put(sink, arg); + else static if ( + + is(immutable typeof(arg) == immutable uint) || is(immutable typeof(arg) == immutable ulong) || + is(immutable typeof(arg) == immutable int) || is(immutable typeof(arg) == immutable long) + ) + // https://issues.dlang.org/show_bug.cgi?id=17712#c15 + put(sink, textImpl!(S)(arg)); + else + put(sink, to!S(arg)); + } +} + /*************************************************************** The `octal` facility provides a means to declare a number in base 8. diff --git a/libphobos/src/std/encoding.d b/libphobos/src/std/encoding.d index 9334f3183f6a..c7c161e7d4d5 100644 --- a/libphobos/src/std/encoding.d +++ b/libphobos/src/std/encoding.d @@ -1879,7 +1879,7 @@ immutable(E)[] sanitize(E)(immutable(E)[] s) offset += n; t = t[n..$]; } - return cast(immutable(E)[])array[0 .. offset]; + return array[0 .. offset]; } /// diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d index 0b8da501d3f5..a5b53270f952 100644 --- a/libphobos/src/std/file.d +++ b/libphobos/src/std/file.d @@ -983,10 +983,10 @@ private void renameImpl(scope const(char)[] f, scope const(char)[] t, import std.conv : to, text; if (!f) - f = fromz ? to!(typeof(f))(fromz[0 .. wcslen(fromz)]) : "(null)"; + f = to!(typeof(f))(fromz[0 .. wcslen(fromz)]); if (!t) - t = toz ? to!(typeof(t))(toz[0 .. wcslen(toz)]) : "(null)"; + t = to!(typeof(t))(toz[0 .. wcslen(toz)]); enforce(false, new FileException( @@ -2369,7 +2369,6 @@ if (isConvertibleToString!R) } /// - @safe unittest { import std.exception : assertThrown; @@ -4638,6 +4637,7 @@ private struct DirIteratorImpl DirEntry _cur; DirHandle[] _stack; DirEntry[] _stashed; //used in depth first mode + string _pathPrefix = null; //stack helpers void pushExtra(DirEntry de) @@ -4793,20 +4793,12 @@ private struct DirIteratorImpl } } - this(R)(R pathname, SpanMode mode, bool followSymlink) - if (isSomeFiniteCharInputRange!R) + this(string pathname, SpanMode mode, bool followSymlink) { _mode = mode; _followSymlink = followSymlink; - static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char)) - alias pathnameStr = pathname; - else - { - import std.array : array; - string pathnameStr = pathname.array; - } - if (stepIn(pathnameStr)) + if (stepIn(pathname)) { if (_mode == SpanMode.depth) while (mayStepIn()) @@ -5105,6 +5097,15 @@ auto dirEntries(bool useDIP1000 = dip1000Enabled) // https://issues.dlang.org/show_bug.cgi?id=15146 dirEntries("", SpanMode.shallow).walkLength(); + + // https://github.com/dlang/phobos/issues/9584 + string cwd = getcwd(); + foreach (string entry; dirEntries(testdir, SpanMode.shallow)) + { + if (entry.isDir) + chdir(entry); + } + chdir(cwd); // needed for the directories to be removed } /// Ditto diff --git a/libphobos/src/std/format/internal/write.d b/libphobos/src/std/format/internal/write.d index bb6d878c8395..8d3288579303 100644 --- a/libphobos/src/std/format/internal/write.d +++ b/libphobos/src/std/format/internal/write.d @@ -1412,6 +1412,12 @@ if (isInputRange!T) // if the format spec is valid enum formatTestMode = is(Writer == NoOpSink); + static if (!formatTestMode && isInfinite!T) + { + static assert(!isInfinite!T, "Cannot format an infinite range. " ~ + "Convert it to a finite range first using `std.range.take` or `std.range.takeExactly`."); + } + // Formatting character ranges like string if (f.spec == 's') { @@ -1582,18 +1588,16 @@ if (isInputRange!T) throw new FormatException(text("Incorrect format specifier for range: %", f.spec)); } -// https://issues.dlang.org/show_bug.cgi?id=20218 @safe pure unittest { - void notCalled() - { - import std.range : repeat; + import std.range : repeat; + import std.format : format; - auto value = 1.repeat; + auto value = 1.repeat; - // test that range is not evaluated to completion at compiletime - format!"%s"(value); - } + // This should fail to compile — so we assert that it *doesn't* compile + static assert(!__traits(compiles, format!"%s"(value)), + "Test failed: formatting an infinite range should not compile."); } // character formatting with ecaping diff --git a/libphobos/src/std/format/write.d b/libphobos/src/std/format/write.d index 68a96d48625c..d704c14f5faa 100644 --- a/libphobos/src/std/format/write.d +++ b/libphobos/src/std/format/write.d @@ -534,8 +534,6 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[] // Are we already done with formats? Then just dump each parameter in turn uint currentArg = 0; - bool lastWasConsumeAll; - while (spec.writeUpToNextSpec(w)) { if (currentArg == Args.length && !spec.indexStart) @@ -651,10 +649,7 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[] } default: if (spec.indexEnd == spec.indexEnd.max) - { - lastWasConsumeAll = true; break; - } else if (spec.indexEnd == spec.indexStart) throw new FormatException( text("Positional specifier %", spec.indexStart, '$', spec.spec, @@ -665,8 +660,7 @@ uint formattedWrite(Writer, Char, Args...)(auto ref Writer w, const scope Char[] " index exceeds ", Args.length)); } } - - return lastWasConsumeAll ? Args.length : currentArg; + return currentArg; } /// @@ -1218,8 +1212,7 @@ if (isSomeString!(typeof(fmt))) import std.array : appender; auto w = appender!(char[])(); - uint count = formattedWrite(w, "%1:$d", 1, 2, 3); - assert(count == 3); + formattedWrite(w, "%1:$d", 1, 2, 3); assert(w.data == "123"); } diff --git a/libphobos/src/std/functional.d b/libphobos/src/std/functional.d index 2e1c6e9ae678..12c261bd0bd8 100644 --- a/libphobos/src/std/functional.d +++ b/libphobos/src/std/functional.d @@ -1808,7 +1808,6 @@ private struct DelegateFaker(F) * * BUGS: * $(UL - * $(LI Does not work with `@safe` functions.) * $(LI Ignores C-style / D-style variadic arguments.) * ) */ diff --git a/libphobos/src/std/internal/math/biguintcore.d b/libphobos/src/std/internal/math/biguintcore.d index 9c794b60de12..b2c2b890e2c1 100644 --- a/libphobos/src/std/internal/math/biguintcore.d +++ b/libphobos/src/std/internal/math/biguintcore.d @@ -940,7 +940,11 @@ public: uint [] wasteful = new BigDigit[x.data.length]; wasteful[] = x.data[]; immutable rem = multibyteDivAssign(wasteful, y, 0); - () @trusted { GC.free(wasteful.ptr); } (); + if (!__ctfe) + { + //use free only at runtime + () @trusted { GC.free(wasteful.ptr); } (); + } return rem; } } @@ -1279,6 +1283,13 @@ pure @safe unittest assert(s == 5); } +pure @safe unittest +{ //evaluate mod at compile time + enum BigUint r = BigUint([5]); + enum BigUint t = BigUint([7]); + enum BigUint s = BigUint.mod(r, t); + static assert(s == 5); +} @safe pure unittest { @@ -1725,7 +1736,11 @@ void mulInternal(BigDigit[] result, const(BigDigit)[] x, const(BigDigit)[] y) mulKaratsuba(result[half .. $], y, x[half .. $], scratchbuff); BigDigit c = addAssignSimple(result[half .. half + y.length], partial); if (c) multibyteIncrementAssign!('+')(result[half + y.length..$], c); - () @trusted { GC.free(scratchbuff.ptr); } (); + if (!__ctfe) + { + //use free only at runtime + () @trusted { GC.free(scratchbuff.ptr); } (); + } } else { @@ -1784,7 +1799,11 @@ void mulInternal(BigDigit[] result, const(BigDigit)[] x, const(BigDigit)[] y) addAssignSimple(result[done .. done + y.length + chunksize], partial); done += chunksize; } - () @trusted { GC.free(scratchbuff.ptr); } (); + if (!__ctfe) + { + //use free only at runtime + () @trusted { GC.free(scratchbuff.ptr); } (); + } } } else @@ -1792,7 +1811,11 @@ void mulInternal(BigDigit[] result, const(BigDigit)[] x, const(BigDigit)[] y) // Balanced. Use Karatsuba directly. BigDigit [] scratchbuff = new BigDigit[karatsubaRequiredBuffSize(x.length)]; mulKaratsuba(result, x, y, scratchbuff); - () @trusted { GC.free(scratchbuff.ptr); } (); + if (!__ctfe) + { + //use free only at runtime + () @trusted { GC.free(scratchbuff.ptr); } (); + } } } @@ -1828,24 +1851,28 @@ void mulInternal(BigDigit[] result, const(BigDigit)[] x, const(BigDigit)[] y) */ void squareInternal(BigDigit[] result, const BigDigit[] x) pure nothrow @safe { - import core.memory : GC; - // Squaring is potentially half a multiply, plus add the squares of - // the diagonal elements. - assert(result.length == 2*x.length, - "result needs to have twice the capacity of x"); - if (x.length <= KARATSUBASQUARELIMIT) - { - if (x.length == 1) - { - result[1] = multibyteMul(result[0 .. 1], x, x[0], 0); - return; - } - return squareSimple(result, x); - } - // The nice thing about squaring is that it always stays balanced - BigDigit [] scratchbuff = new BigDigit[karatsubaRequiredBuffSize(x.length)]; - squareKaratsuba(result, x, scratchbuff); - () @trusted { GC.free(scratchbuff.ptr); } (); + import core.memory : GC; + // Squaring is potentially half a multiply, plus add the squares of + // the diagonal elements. + assert(result.length == 2*x.length, + "result needs to have twice the capacity of x"); + if (x.length <= KARATSUBASQUARELIMIT) + { + if (x.length == 1) + { + result[1] = multibyteMul(result[0 .. 1], x, x[0], 0); + return; + } + return squareSimple(result, x); + } + // The nice thing about squaring is that it always stays balanced + BigDigit [] scratchbuff = new BigDigit[karatsubaRequiredBuffSize(x.length)]; + squareKaratsuba(result, x, scratchbuff); + if (!__ctfe) + { + //use free only at runtime + () @trusted { GC.free(scratchbuff.ptr); } (); + } } @@ -1897,7 +1924,11 @@ void divModInternal(BigDigit [] quotient, BigDigit[] remainder, const BigDigit [ if (s == 0) remainder[] = un[0 .. vn.length]; else multibyteShr(remainder, un[0 .. vn.length+1], s); } - () @trusted { GC.free(un.ptr); GC.free(vn.ptr); } (); + if (!__ctfe) + { + //use free only at runtime + () @trusted { GC.free(un.ptr); GC.free(vn.ptr); } (); + } } pure @safe unittest @@ -2842,7 +2873,11 @@ pure nothrow @safe m -= v.length; } recursiveDivMod(quotient[0 .. m], u[0 .. m + v.length], v, scratch); - () @trusted { GC.free(scratch.ptr); } (); + if (!__ctfe) + { + //use free only at runtime + () @trusted { GC.free(scratch.ptr); } (); + } } @system unittest diff --git a/libphobos/src/std/internal/windows/bcrypt.d b/libphobos/src/std/internal/windows/bcrypt.d deleted file mode 100644 index 239dcd52e662..000000000000 --- a/libphobos/src/std/internal/windows/bcrypt.d +++ /dev/null @@ -1,65 +0,0 @@ -module std.internal.windows.bcrypt; - -version (Windows): - -import core.sys.windows.bcrypt : BCryptGenRandom, BCRYPT_USE_SYSTEM_PREFERRED_RNG; -import core.sys.windows.windef : HMODULE, PUCHAR, ULONG; -import core.sys.windows.ntdef : NT_SUCCESS; - -pragma(lib, "Bcrypt.lib"); - -package(std) bool bcryptGenRandom(T)(out T result) @trusted -{ - loadBcrypt(); - - const gotRandom = ptrBCryptGenRandom( - null, - cast(PUCHAR) &result, - ULONG(T.sizeof), - BCRYPT_USE_SYSTEM_PREFERRED_RNG, - ); - - return NT_SUCCESS(gotRandom); -} - -private -{ - HMODULE hBcrypt = null; - typeof(BCryptGenRandom)* ptrBCryptGenRandom; -} - -private void loadBcrypt() @nogc nothrow -{ - import core.sys.windows.winbase : GetProcAddress, LoadLibraryA; - - if (!hBcrypt) - { - hBcrypt = LoadLibraryA("Bcrypt.dll"); - if (!hBcrypt) - assert(false, `LoadLibraryA("Bcrypt.dll") failed.`); // `@nogc` - - ptrBCryptGenRandom = cast(typeof(ptrBCryptGenRandom)) GetProcAddress(hBcrypt , "BCryptGenRandom"); - if (!ptrBCryptGenRandom) - assert(false, `GetProcAddress(hBcrypt , "BCryptGenRandom") failed.`); // `@nogc` - } -} - -// Will free `Bcrypt.dll`. -private void freeBcrypt() @nogc nothrow -{ - import core.sys.windows.winbase : FreeLibrary; - - if (hBcrypt) - { - if (!FreeLibrary(hBcrypt)) - assert(false, `FreeLibrary("Bcrypt.dll") failed.`); // `@nogc` - - hBcrypt = null; - ptrBCryptGenRandom = null; - } -} - -static ~this() -{ - freeBcrypt(); -} diff --git a/libphobos/src/std/json.d b/libphobos/src/std/json.d index eb08de8f048d..2875faef947b 100644 --- a/libphobos/src/std/json.d +++ b/libphobos/src/std/json.d @@ -1058,6 +1058,41 @@ struct JSONValue } } + /// Calculate a numerical hash value for this value, + /// allowing `JSONValue` to be used in associative arrays. + hash_t toHash() const @nogc nothrow pure @trusted + { + final switch (type_tag) + { + case JSONType.integer: + return hashOf(store.integer); + case JSONType.uinteger: + return hashOf(store.uinteger); + case JSONType.float_: + return hashOf(store.floating); + case JSONType.string: + return hashOf(store.str); + case JSONType.object: + hash_t result = hashOf(type_tag); + if (!store.object.isOrdered) + foreach (ref pair; store.object.unordered.byKeyValue) + result ^= hashOf(pair.key, pair.value.toHash()); + else + foreach (ref pair; store.object.ordered) + result ^= hashOf(pair.key, pair.value.toHash()); + return result; + case JSONType.array: + hash_t result = hashOf(type_tag); + foreach (ref v; store.array) + result = hashOf(v, result); + return result; + case JSONType.true_: + case JSONType.false_: + case JSONType.null_: + return hashOf(type_tag); + } + } + /// @safe unittest { @@ -2736,3 +2771,15 @@ pure nothrow @safe unittest assert(app.data == s, app.data); } + +@safe unittest +{ + bool[JSONValue] aa; + aa[JSONValue("test")] = true; + assert(parseJSON(`"test"`) in aa); + assert(parseJSON(`"boo"`) !in aa); + + aa[JSONValue(int(5))] = true; + assert(JSONValue(int(5)) in aa); + assert(JSONValue(uint(5)) in aa); +} diff --git a/libphobos/src/std/math/algebraic.d b/libphobos/src/std/math/algebraic.d index cfb88c89f756..f96f24f153f6 100644 --- a/libphobos/src/std/math/algebraic.d +++ b/libphobos/src/std/math/algebraic.d @@ -256,7 +256,7 @@ real sqrt(real x) @nogc @safe pure nothrow { return core.math.sqrt(x); } * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)$(INFIN)) $(TD no) ) * ) */ -real cbrt(real x) @trusted nothrow @nogc +real cbrt(real x) @trusted pure nothrow @nogc { version (CRuntime_Microsoft) { @@ -273,7 +273,7 @@ real cbrt(real x) @trusted nothrow @nogc } /// -@safe unittest +@safe pure unittest { import std.math.operations : feqrel; @@ -294,10 +294,11 @@ real cbrt(real x) @trusted nothrow @nogc * hypot(x, -y) are equivalent. * * $(TABLE_SV - * $(TR $(TH x) $(TH y) $(TH hypot(x, y)) $(TH invalid?)) - * $(TR $(TD x) $(TD $(PLUSMN)0.0) $(TD |x|) $(TD no)) - * $(TR $(TD $(PLUSMNINF)) $(TD y) $(TD +$(INFIN)) $(TD no)) - * $(TR $(TD $(PLUSMNINF)) $(TD $(NAN)) $(TD +$(INFIN)) $(TD no)) + * $(TR $(TH x) $(TH y) $(TH hypot(x, y)) $(TH invalid?)) + * $(TR $(TD x) $(TD $(PLUSMN)0.0) $(TD |x|) $(TD no)) + * $(TR $(TD $(PLUSMNINF)) $(TD y) $(TD +$(INFIN)) $(TD no)) + * $(TR $(TD $(PLUSMNINF)) $(TD $(NAN)) $(TD +$(INFIN)) $(TD no)) + * $(TR $(TD $(NAN)) $(TD y != $(PLUSMNINF)) $(TD $(NAN)) $(TD no)) * ) */ T hypot(T)(const T x, const T y) @safe pure nothrow @nogc @@ -308,19 +309,22 @@ if (isFloatingPoint!T) // If both are huge, avoid overflow by scaling by 2^^-N. // If both are tiny, avoid underflow by scaling by 2^^N. import core.math : fabs, sqrt; - import std.math.traits : floatTraits, RealFormat; + import std.math.traits : floatTraits, RealFormat, isNaN; alias F = floatTraits!T; T u = fabs(x); T v = fabs(y); - if (!(u >= v)) // check for NaN as well. + if (!(u >= v)) { v = u; u = fabs(y); if (u == T.infinity) return u; // hypot(inf, nan) == inf if (v == T.infinity) return v; // hypot(nan, inf) == inf + if (u.isNaN || v.isNaN) + return T.nan; } + assert(!(u.isNaN || v.isNaN), "Comparison to NaN always fails, thus is is always handled in the branch above"); static if (F.realFormat == RealFormat.ieeeSingle) { @@ -349,6 +353,13 @@ if (isFloatingPoint!T) else assert(0, "hypot not implemented"); + if (u * T.epsilon > v) + { + // hypot (huge, tiny) = huge + // also: hypot(x, 0) = x + return u; + } + // Now u >= v, or else one is NaN. T ratio = 1.0; if (v >= SQRTMAX) @@ -368,12 +379,6 @@ if (isFloatingPoint!T) v *= SCALE_UNDERFLOW; } - if (u * T.epsilon > v) - { - // hypot (huge, tiny) = huge - return u; - } - // both are in the normal range return ratio * sqrt(u*u + v*v); } @@ -382,11 +387,16 @@ if (isFloatingPoint!T) @safe unittest { import std.math.operations : feqrel; + import std.math.traits : isNaN; assert(hypot(1.0, 1.0).feqrel(1.4142) > 16); assert(hypot(3.0, 4.0).feqrel(5.0) > 16); assert(hypot(real.infinity, 1.0L) == real.infinity); + assert(hypot(1.0L, real.infinity) == real.infinity); assert(hypot(real.infinity, real.nan) == real.infinity); + assert(hypot(real.nan, real.infinity) == real.infinity); + assert(hypot(real.nan, 1.0L).isNaN); + assert(hypot(1.0L, real.nan).isNaN); } @safe unittest @@ -404,6 +414,16 @@ if (isFloatingPoint!T) assert(hypot(double.infinity, double.nan) == double.infinity); } +// https://github.com/dlang/phobos/issues/10491 +@safe pure nothrow unittest +{ + import std.math : isClose; + + enum small = 5.016556e-20f; + assert(hypot(small, 0).isClose(small)); + assert(hypot(small, float.min_normal).isClose(small)); +} + @safe unittest { import std.math.operations : feqrel; diff --git a/libphobos/src/std/math/exponential.d b/libphobos/src/std/math/exponential.d index 7a72f428cd72..7e420289bbc6 100644 --- a/libphobos/src/std/math/exponential.d +++ b/libphobos/src/std/math/exponential.d @@ -830,28 +830,39 @@ if (isUnsigned!F && isUnsigned!G && isUnsigned!H) { static if (T.sizeof == 8) { - static T addmod(T a, T b, T c) + if (c <= 0x100000000) { - b = c - b; - if (a >= b) - return a - b; - else - return c - b + a; + T result = a * b; + return result % c; } + else + { + import core.int128 : Cent, mul, udivmod; - T result = 0, tmp; + auto product = mul(a, b); - b %= c; - while (a > 0) - { - if (a & 1) - result = addmod(result, b, c); + if (product.hi >= c) + { + product.hi %= c; + } - a >>= 1; - b = addmod(b, b, c); + T remainder = void; + udivmod(product, c, remainder); + return remainder; + } + } + else static if (T.sizeof == 4) + { + if (c <= 0x10000) + { + T result = a * b; + return result % c; + } + else + { + DoubleT result = cast(DoubleT) (cast(DoubleT) a * cast(DoubleT) b); + return result % c; } - - return result; } else { diff --git a/libphobos/src/std/net/curl.d b/libphobos/src/std/net/curl.d index 07905fc70038..efbb4f8811c0 100644 --- a/libphobos/src/std/net/curl.d +++ b/libphobos/src/std/net/curl.d @@ -1226,9 +1226,10 @@ private auto _decodeContent(T)(ubyte[] content, string encoding) { import std.exception : enforce; import std.format : format; + import std.uni : icmp; // Optimally just return the utf8 encoded content - if (encoding == "UTF-8") + if (icmp(encoding, "UTF-8") == 0) return cast(char[])(content); // The content has to be re-encoded to utf8 diff --git a/libphobos/src/std/path.d b/libphobos/src/std/path.d index 5fb31566baf3..13694ee875e1 100644 --- a/libphobos/src/std/path.d +++ b/libphobos/src/std/path.d @@ -992,7 +992,7 @@ private auto _stripDrive(R)(R path) Returns: index of extension separator (the dot), or -1 if not found */ -private ptrdiff_t extSeparatorPos(R)(const R path) +private ptrdiff_t extSeparatorPos(R)(R path) if (isRandomAccessRange!R && hasLength!R && isSomeChar!(ElementType!R) || isNarrowString!R) { @@ -1280,6 +1280,11 @@ if (isSomeChar!C1 && isSomeChar!C2) assert(withExtension("file.ext"w.byWchar, ".").array == "file."w); } +@safe unittest +{ + assert(chainPath("directory", "file").withExtension(".ext").array == buildPath("directory", "file.ext")); +} + @safe unittest { import std.algorithm.comparison : equal; diff --git a/libphobos/src/std/random.d b/libphobos/src/std/random.d index edb8902c6493..fb4e5469088f 100644 --- a/libphobos/src/std/random.d +++ b/libphobos/src/std/random.d @@ -1774,71 +1774,41 @@ else version (linux) { - version (linux_legacy_emulate_getrandom) - { - /+ - Emulates `getrandom()` for backwards compatibility - with outdated kernels and legacy libc versions. - - `getrandom()` was added to the GNU C Library in v2.25. - +/ - pragma(msg, "`getrandom()` emulation for legacy Linux targets is enabled."); - - /+ - On modern kernels (5.6+), `/dev/random` would behave more similar - to `getrandom()`. - However, this emulator was specifically written for systems older - than that. Hence, `/dev/urandom` is the CSPRNG of choice. - - - +/ - private static immutable _pathLinuxSystemCSPRNG = "/dev/urandom"; - - import core.sys.posix.sys.types : ssize_t; - - /+ - Linux `getrandom()` emulation built upon `/dev/urandom`. - The fourth parameter (`uint flags`) is happily ignored. - +/ - private ssize_t getrandom( - void* buf, - size_t buflen, - uint, - ) @system nothrow @nogc - { - import core.stdc.stdio : fclose, fopen, fread; + // `getrandom()` was introduced in Linux 3.17. - auto blockDev = fopen(_pathLinuxSystemCSPRNG.ptr, "r"); - if (blockDev is null) - assert(false, "System CSPRNG unavailable: `fopen(\"" ~ _pathLinuxSystemCSPRNG ~ "\")` failed."); - scope (exit) fclose(blockDev); - - const bytesRead = fread(buf, 1, buflen, blockDev); - return bytesRead; - } - } + // Shim for missing bindings in druntime + version (none) + import core.sys.linux.sys.random : getrandom; else { - // `getrandom()` was introduced in Linux 3.17. - - // Shim for missing bindings in druntime - version (none) - import core.sys.linux.sys.random : getrandom; - else - { - import core.sys.posix.sys.types : ssize_t; - private extern extern(C) ssize_t getrandom( - void* buf, - size_t buflen, - uint flags, - ) @system nothrow @nogc; - } + import core.sys.posix.sys.types : ssize_t; + extern extern(C) ssize_t getrandom( + void* buf, + size_t buflen, + uint flags, + ) @system nothrow @nogc; } } version (Windows) { - import std.internal.windows.bcrypt : bcryptGenRandom; + pragma(lib, "Bcrypt.lib"); + + private bool bcryptGenRandom(T)(out T result) @trusted + { + import core.sys.windows.windef : PUCHAR, ULONG; + import core.sys.windows.ntdef : NT_SUCCESS; + import core.sys.windows.bcrypt : BCryptGenRandom, BCRYPT_USE_SYSTEM_PREFERRED_RNG; + + const gotRandom = BCryptGenRandom( + null, + cast(PUCHAR) &result, + ULONG(T.sizeof), + BCRYPT_USE_SYSTEM_PREFERRED_RNG, + ); + + return NT_SUCCESS(gotRandom); + } } /** diff --git a/libphobos/src/std/sumtype.d b/libphobos/src/std/sumtype.d index ab6ade0e1d8b..1a26235a08bf 100644 --- a/libphobos/src/std/sumtype.d +++ b/libphobos/src/std/sumtype.d @@ -32,9 +32,9 @@ version (D_BetterC) {} else { import std.math.operations : isClose; - struct Fahrenheit { double degrees; } - struct Celsius { double degrees; } - struct Kelvin { double degrees; } + struct Fahrenheit { double value; } + struct Celsius { double value; } + struct Kelvin { double value; } alias Temperature = SumType!(Fahrenheit, Celsius, Kelvin); @@ -48,29 +48,29 @@ version (D_BetterC) {} else { return Fahrenheit( t.match!( - (Fahrenheit f) => f.degrees, - (Celsius c) => c.degrees * 9.0/5 + 32, - (Kelvin k) => k.degrees * 9.0/5 - 459.4 + (Fahrenheit f) => f.value, + (Celsius c) => c.value * 9.0/5 + 32, + (Kelvin k) => k.value * 9.0/5 - 459.4 ) ); } - assert(toFahrenheit(t1).degrees.isClose(98.6)); - assert(toFahrenheit(t2).degrees.isClose(212)); - assert(toFahrenheit(t3).degrees.isClose(32)); + assert(toFahrenheit(t1).value.isClose(98.6)); + assert(toFahrenheit(t2).value.isClose(212)); + assert(toFahrenheit(t3).value.isClose(32)); // Use ref to modify the value in place. void freeze(ref Temperature t) { t.match!( - (ref Fahrenheit f) => f.degrees = 32, - (ref Celsius c) => c.degrees = 0, - (ref Kelvin k) => k.degrees = 273 + (ref Fahrenheit f) => f.value = 32, + (ref Celsius c) => c.value = 0, + (ref Kelvin k) => k.value = 273 ); } freeze(t1); - assert(toFahrenheit(t1).degrees.isClose(32)); + assert(toFahrenheit(t1).value.isClose(32)); // Use a catch-all handler to give a default result. bool isFahrenheit(Temperature t) diff --git a/libphobos/src/std/traits.d b/libphobos/src/std/traits.d index f230aa3b74e4..9bdd9775f9cb 100644 --- a/libphobos/src/std/traits.d +++ b/libphobos/src/std/traits.d @@ -4728,10 +4728,7 @@ It will return `void` if a symbol without a template is given. alias TemplateOf(alias T : Base!Args, alias Base, Args...) = Base; /// ditto -alias TemplateOf(T : Base!Args, alias Base, Args...) = Base; - -/// ditto -alias TemplateOf(T) = void; +alias TemplateOf(alias T) = void; /// @safe unittest @@ -4768,6 +4765,10 @@ alias TemplateOf(T) = void; { static assert(is(TemplateOf!(int[]) == void)); static assert(is(TemplateOf!bool == void)); + + // https://github.com/dlang/phobos/issues/10527 + static void foo() {} + static assert(is(TemplateOf!foo == void)); } /** diff --git a/libphobos/src/std/uuid.d b/libphobos/src/std/uuid.d index 09ce2f73f380..3a054a5aef34 100644 --- a/libphobos/src/std/uuid.d +++ b/libphobos/src/std/uuid.d @@ -1204,32 +1204,52 @@ public struct UUID * * This function is not supported at compile time. * + * Bugs: + * $(LINK2 https://github.com/dlang/phobos/issues/9881, Issue #9881 - Randomness in UUID generation is insufficient) + * + * Warning: + * $(B This function must not be used for cryptographic purposes.) + * UUIDs generated by this function do not have sufficient randomness + * for all use cases. + * This especially applies to the overload that accepts a caller-provided RNG. + * At the moment, Phobos does not provide a $(I cryptographically-secure + * pseudo-random number generator (CSPRNG)) that could be supplied to this + * function. + * + * While the function overload with no parameters will attempt to use the + * system CSPRNG where available and implemented, there are no guarantees. + * See $(REF unpredictableSeed, std, random) for details. + * * Params: * randomGen = uniform RNG * See_Also: $(REF isUniformRNG, std,random) */ @nogc nothrow @safe UUID randomUUID() { - import std.random : rndGen; - // A PRNG with fewer than `n` bytes of state cannot produce - // every distinct `n` byte sequence. - static if (typeof(rndGen).sizeof >= UUID.sizeof) - { - return randomUUID(rndGen); - } - else - { - import std.random : unpredictableSeed, Xorshift192; - static assert(Xorshift192.sizeof >= UUID.sizeof); - static Xorshift192 rng; - static bool initialized; - if (!initialized) - { - rng.seed(unpredictableSeed); - initialized = true; - } - return randomUUID(rng); - } + import std.conv : bitCast; + import std.random : unpredictableSeed; + + enum bufferSize = UUID.data.sizeof; + ubyte[bufferSize] data; + + static assert(ulong.sizeof * 2 == bufferSize); + const half1 = unpredictableSeed!ulong(); + const half2 = unpredictableSeed!ulong(); + + data[0 .. ulong.sizeof] = (() @trusted => half1.bitCast!(ubyte[ulong.sizeof]))(); + data[ulong.sizeof .. $] = (() @trusted => half2.bitCast!(ubyte[ulong.sizeof]))(); + + // set variant + // must be 0b_10xxxxxx + data[8] &= 0b_10_111111; + data[8] |= 0b_10_000000; + + // set version + // must be 0b_0100xxxx + data[6] &= 0b_0100_1111; + data[6] |= 0b_0100_0000; + + return UUID(data); } /// ditto diff --git a/libphobos/src/std/variant.d b/libphobos/src/std/variant.d index a0b564440120..a094aeb3409e 100644 --- a/libphobos/src/std/variant.d +++ b/libphobos/src/std/variant.d @@ -850,7 +850,14 @@ public: */ @property inout(T) get(T)() inout { - inout(T) result = void; + static union SupressDestructor { + T val; + } + + /* If this function fails and it throws, copy elision will not run and the destructor might be called. + * But since this value is void initialized, this is undesireable. + */ + inout(SupressDestructor) result = void; static if (is(T == shared)) alias R = shared Unqual!T; else @@ -861,7 +868,7 @@ public: { throw new VariantException(type, typeid(T)); } - return result; + return result.val; } /// Ditto @@ -3255,3 +3262,44 @@ if (isAlgebraic!VariantType && Handler.length > 0) immutable aa = ["0": 0]; auto v = Variant(aa); // compile error } + +// https://github.com/dlang/phobos/issues/9585 +// Verify that alignment is respected +@safe unittest +{ + static struct Foo { double x; } + alias AFoo1 = Algebraic!(Foo); + static assert(AFoo1.alignof >= double.alignof); + + // Algebraic using a function pointer is an implementation detail. If test fails, this is safe to change + enum FP_SIZE = (int function()).sizeof; + static assert(AFoo1.sizeof >= double.sizeof + FP_SIZE); +} + +// https://github.com/dlang/phobos/issues/10518 +@system unittest +{ + import std.exception : assertThrown; + + struct Huge { + real a, b, c, d, e, f, g; + } + Huge h = {1,1,1,1,1,1,1}; + Variant variant = Variant([ + "one": Variant(1), + ]); + // Testing that this doesn't segfault. Future work might make enable this + assertThrown!VariantException(variant["three"] = 3); + assertThrown!VariantException(variant["four"] = Variant(4)); + /* Storing huge works too, value will moved to the heap + * Testing this as a regression test here as the AA handling code is still somewhat brittle and might add changes + * that depend payload size in the future + */ + assertThrown!VariantException(variant["huge"] = Variant(h)); + /+ + assert(variant["one"] == Variant(1)); + assert(variant["three"] == Variant(3)); + assert(variant["three"] == 3); + assert(variant["huge"] == Variant(h)); + +/ +}