diff --git a/CHANGELOG.md b/CHANGELOG.md index e75e67c922f..35a331a152a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # LDC master #### Big news +- Frontend, druntime and Phobos are at version ~[2.112.0](https://dlang.org/changelog/2.112.0.html). (#4949) - **Breaking change for dcompute**: The special `@kernel` UDA is now a function and _**requires**_ parentheses as in `@kernel() void foo(){}`. Optionally you can provide launch dimensions, `@kernel([2,4,8])`, to specify to the compute runtime how the kernel is intended to be launched. #### Platform support diff --git a/CMakeLists.txt b/CMakeLists.txt index 21aad6d367d..1f34e1dea73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -121,9 +121,9 @@ include(GetLinuxDistribution) # # Version information -set(LDC_VERSION "1.41.0") # May be overridden by git hash tag +set(LDC_VERSION "1.42.0") # May be overridden by git hash tag set(DMDFE_MAJOR_VERSION 2) -set(DMDFE_MINOR_VERSION 111) +set(DMDFE_MINOR_VERSION 112) set(DMDFE_PATCH_VERSION 0) set(DMD_VERSION ${DMDFE_MAJOR_VERSION}.${DMDFE_MINOR_VERSION}.${DMDFE_PATCH_VERSION}) diff --git a/dmd/aggregate.d b/dmd/aggregate.d index b7b0b0993c3..1272d2a9df3 100644 --- a/dmd/aggregate.d +++ b/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/dmd/aggregate.h b/dmd/aggregate.h index cb114f8b980..7f994f21d3a 100644 --- a/dmd/aggregate.h +++ b/dmd/aggregate.h @@ -120,7 +120,6 @@ class AggregateDeclaration : public ScopeDsymbol 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? @@ -174,7 +173,6 @@ class StructDeclaration : public AggregateDeclaration 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); @@ -200,7 +198,7 @@ class StructDeclaration : public AggregateDeclaration unsigned numArgTypes() const; Type *argType(unsigned index); - bool hasRegularCtor(bool checkDisabled = false); + bool hasRegularCtor(bool ignoreDisabled = false); }; class UnionDeclaration final : public StructDeclaration @@ -293,13 +291,11 @@ class ClassDeclaration : public AggregateDeclaration 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/dmd/attrib.d b/dmd/attrib.d index 1bfe7902a92..a03e7bbdc0e 100644 --- a/dmd/attrib.d +++ b/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/dmd/attrib.h b/dmd/attrib.h index ef37e0adece..24d91abc627 100644 --- a/dmd/attrib.h +++ b/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/dmd/cli.d b/dmd/cli.d index 01b8348bb87..46a4ef4a88d 100644 --- a/dmd/cli.d +++ b/dmd/cli.d @@ -664,8 +664,13 @@ dmd -cov -unittest myprog.d ), Option("nothrow", "assume no Exceptions will be thrown", - `Turns off generation of exception stack unwinding code, enables - more efficient code for RAII objects.`, + "Turns off generation of exception stack unwinding code, enables + more efficient code for RAII objects. Note: this doesn't change + function mangling, so it is possible to link `-nothrow` code with + code that throws Exceptions, which can result in undefined behavior + without any protection from the type system. Prefer the `nothrow` + function attribute for partial disabling of Exceptions instead, + and only use this flag to globally disable Exceptions.", ), Option("O", "optimize", diff --git a/dmd/cond.d b/dmd/cond.d index 1b11a9f1803..31c01f1853e 100644 --- a/dmd/cond.d +++ b/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/dmd/cond.h b/dmd/cond.h index 174a8fb9aaf..0afa042f9da 100644 --- a/dmd/cond.h +++ b/dmd/cond.h @@ -38,7 +38,6 @@ class Condition : public ASTNode 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 @@ class VersionCondition final : public DVCondition 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 @@ class StaticIfCondition final : public Condition Expression *exp; StaticIfCondition *syntaxCopy() override; - int include(Scope *sc) override; void accept(Visitor *v) override { v->visit(this); } }; diff --git a/dmd/cparse.d b/dmd/cparse.d index f5e914868e0..6c61d214326 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -835,8 +835,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 @@ -985,6 +985,7 @@ final class CParser(AST) : Parser!AST * sizeof unary-expression * sizeof ( type-name ) * _Alignof ( type-name ) + * _Alignof unary-expression // gcc extension * * unary-operator: * & * + - ~ ! @@ -1047,8 +1048,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) { @@ -1087,7 +1090,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; } @@ -1099,17 +1102,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; @@ -1731,6 +1723,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: @@ -1778,28 +1798,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 */ @@ -1825,12 +1826,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; } @@ -1843,6 +1845,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); @@ -1916,10 +1927,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: @@ -1955,7 +1970,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"); @@ -1963,8 +1978,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) { @@ -1976,38 +1991,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()); @@ -2036,6 +2046,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) @@ -2459,25 +2479,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; } @@ -2539,6 +2541,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; @@ -3531,12 +3534,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; @@ -3546,7 +3549,7 @@ final class CParser(AST) : Parser!AST default: *ptoklist = allocateToken(); - memcpy(*ptoklist, &token, Token.sizeof); + **ptoklist = this.token; ptoklist = &(*ptoklist).next; *ptoklist = null; nextToken(); @@ -3640,26 +3643,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) { @@ -3971,7 +3966,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); } /************************************* @@ -3998,8 +3993,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) @@ -4015,7 +4027,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; @@ -4033,18 +4045,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); } } } @@ -4052,14 +4064,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); } /************************************* @@ -4123,7 +4135,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 @@ -4139,17 +4151,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) { @@ -4198,8 +4212,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); } @@ -5018,6 +5032,7 @@ final class CParser(AST) : Parser!AST return false; break; + case TOK._Alignof: case TOK.sizeof_: t = peek(t); if (t.value == TOK.leftParenthesis) @@ -5035,15 +5050,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. @@ -5176,6 +5182,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 } @@ -6081,6 +6088,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 */ @@ -6104,6 +6113,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); @@ -6115,6 +6132,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(); @@ -6212,7 +6236,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; @@ -6360,10 +6384,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/dmd/cxxfrontend.d b/dmd/cxxfrontend.d index 59fc6ba0e75..c25b5bc4c2e 100644 --- a/dmd/cxxfrontend.d +++ b/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); @@ -193,6 +188,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 */ diff --git a/dmd/dcast.d b/dmd/dcast.d index 86d2f0f07c3..9e35dde2969 100644 --- a/dmd/dcast.d +++ b/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/dmd/dclass.d b/dmd/dclass.d index f96095144fa..1dffebf05c0 100644 --- a/dmd/dclass.d +++ b/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; /*********************************************************** @@ -499,116 +497,6 @@ version (IN_LLVM) {} else 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 */ @@ -760,106 +648,6 @@ version (IN_LLVM) {} else 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/dmd/declaration.d b/dmd/declaration.d index 77f3a0027f6..8149b86dcd6 100644 --- a/dmd/declaration.d +++ b/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; @@ -789,25 +788,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); @@ -1064,12 +1044,6 @@ version (IN_LLVM) 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. */ @@ -1119,83 +1093,6 @@ version (IN_LLVM) 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/dmd/declaration.h b/dmd/declaration.h index e336dff302a..544e41cecc9 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -39,6 +39,7 @@ namespace dmd 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: @@ -305,7 +306,6 @@ class VarDeclaration : public Declaration 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/dmd/delegatize.d b/dmd/delegatize.d index 344130b5e31..1f5dca66b59 100644 --- a/dmd/delegatize.d +++ b/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/dmd/dinterpret.d b/dmd/dinterpret.d index 13051db3789..bdaaace6be0 100644 --- a/dmd/dinterpret.d +++ b/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; @@ -6763,8 +6703,9 @@ ThrownExceptionExp chainExceptions(ThrownExceptionExp oldest, ThrownExceptionExp } // Little sanity check to make sure it's really a Throwable ClassReferenceExp boss = oldest.thrown; - const next = 5; // index of Throwable.next - assert((*boss.value.elements)[next].type.ty == Tclass); // Throwable.next + const next = 5; // index of Throwable._nextInChainPtr + with ((*boss.value.elements)[next].type) // Throwable._nextInChainPtr + assert(ty == Tpointer || ty == Tclass); ClassReferenceExp collateral = newest.thrown; if (collateral.originalClass().isErrorException() && !boss.originalClass().isErrorException()) { diff --git a/dmd/dmodule.d b/dmd/dmodule.d index f4b52c4bf90..c79fa9c8468 100644 --- a/dmd/dmodule.d +++ b/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; @@ -570,6 +571,8 @@ else } 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; @@ -1056,22 +1059,31 @@ else 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); + } } /****************************************** @@ -1105,6 +1117,8 @@ else todoalloc = todo; } memcpy(todo, deferred.tdata(), len * Dsymbol.sizeof); + foreach (Dsymbol s; Module.deferred[]) + s.deferred = false; deferred.setDim(0); foreach (i; 0..len) @@ -1130,6 +1144,7 @@ else 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); @@ -1147,6 +1162,7 @@ else 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); @@ -1378,83 +1394,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/dmd/dscope.d b/dmd/dscope.d index 00d2fab829d..0fbdccf2986 100644 --- a/dmd/dscope.d +++ b/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/dmd/dstruct.d b/dmd/dstruct.d index 70743831c74..ff4108a981b 100644 --- a/dmd/dstruct.d +++ b/dmd/dstruct.d @@ -154,127 +154,6 @@ version (IN_LLVM) {} else 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() { @@ -282,13 +161,14 @@ version (IN_LLVM) {} else 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()) @@ -402,13 +282,12 @@ version (IN_LLVM) {} else * 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; @@ -418,7 +297,7 @@ version (IN_LLVM) {} else { if (auto td = s.isTemplateDeclaration()) { - if (checkDisabled && td.onemember) + if (ignoreDisabled && td.onemember) { if (auto ctorDecl = td.onemember.isCtorDeclaration()) { @@ -431,7 +310,7 @@ version (IN_LLVM) {} else } if (auto ctorDecl = s.isCtorDeclaration()) { - if (!ctorDecl.isCpCtor && (!checkDisabled || !(ctorDecl.storage_class & STC.disable))) + if (!ctorDecl.isCpCtor && !ctorDecl.isMoveCtor && (!ignoreDisabled || !(ctorDecl.storage_class & STC.disable))) { result = true; return 1; @@ -443,96 +322,6 @@ version (IN_LLVM) {} else } } -/********************************** - * 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/dmd/dsymbol.d b/dmd/dsymbol.d index 1efe773d5ec..406a24dfa99 100644 --- a/dmd/dsymbol.d +++ b/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; @@ -359,6 +358,11 @@ else { 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)); @@ -936,78 +940,6 @@ version (IN_LLVM) 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) { } @@ -1271,6 +1203,7 @@ version (IN_LLVM) 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/dmd/dsymbol.h b/dmd/dsymbol.h index 51511c14499..1947a6d9811 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -250,7 +250,6 @@ class Dsymbol : public ASTNode 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); @@ -435,7 +434,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/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 439232c0ddd..8a88e30ce01 100644 --- a/dmd/dsymbolsem.d +++ b/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); @@ -3111,10 +3113,18 @@ else 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 { @@ -3154,6 +3164,234 @@ else //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(); @@ -4542,7 +4780,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; @@ -4937,7 +5175,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"); @@ -4992,7 +5230,7 @@ version (IN_LLVM) 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) { @@ -7596,14 +7834,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; @@ -7635,7 +7873,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) @@ -7956,7 +8194,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); @@ -8069,7 +8307,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) @@ -8092,7 +8330,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: @@ -8121,12 +8359,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; } @@ -8135,7 +8373,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; @@ -8173,7 +8411,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); @@ -8227,7 +8465,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()); @@ -8276,3 +8514,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/dmd/dtemplate.d b/dmd/dtemplate.d index 4de19146756..5ffbaebde94 100644 --- a/dmd/dtemplate.d +++ b/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 @@ -644,7 +645,7 @@ version (IN_LLVM) return; Dsymbol s; - if (!Dsymbol.oneMembers(members, s, ident) || !s) + if (!oneMembers(members, s, ident) || !s) return; onemember = s; @@ -5313,7 +5314,7 @@ version (IN_LLVM) if (members.length) { Dsymbol sa; - if (Dsymbol.oneMembers(members, sa, tempdecl.ident) && sa) + if (oneMembers(members, sa, tempdecl.ident) && sa) aliasdecl = sa; } done = true; @@ -5530,12 +5531,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/dmd/enumsem.d b/dmd/enumsem.d index 566a0637a17..6d325e44c96 100644 --- a/dmd/enumsem.d +++ b/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) { @@ -232,112 +232,7 @@ 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) { @@ -351,6 +246,10 @@ void enumSemantic(Scope* sc, EnumDeclaration ed) //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) @@ -631,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/dmd/expression.d b/dmd/expression.d index b457f7d5032..3d52470e3d3 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -307,6 +307,7 @@ extern (C++) /* IN_LLVM 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)); @@ -1419,6 +1420,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; @@ -1430,13 +1433,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) @@ -3892,6 +3896,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 { @@ -3899,6 +3906,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/dmd/expression.h b/dmd/expression.h index 336da1db322..13863e773b2 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -53,7 +53,6 @@ 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); @@ -356,6 +355,7 @@ class StringExp final : public Expression 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); @@ -972,6 +972,7 @@ class SliceExp final : public UnaExp class ArrayLengthExp final : public UnaExp { public: + Expression lowering; void accept(Visitor *v) override { v->visit(this); } }; @@ -1027,6 +1028,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/dmd/expressionsem.d b/dmd/expressionsem.d index 389e7d0d338..a9b5cb97408 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -3926,6 +3926,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor printf("IdentifierExp::semantic('%s')\n", exp.ident.toChars()); } + if (exp.rvalue) + { + if (sc.setUnsafe(false, exp.loc, "moving variable `%s` with `__rvalue`", exp)) + { + setError(); + } + } scope (exit) result.rvalue = exp.rvalue; Dsymbol scopesym; @@ -4120,16 +4127,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(); } @@ -4421,7 +4440,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(); @@ -4446,7 +4465,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(); @@ -4458,7 +4477,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(); @@ -4905,6 +4924,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 @@ -5909,11 +5929,28 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { if (TypeFunction tf = exp.f ? cast(TypeFunction)exp.f.type : null) { - result.rvalue = tf.isRvalue; - if (tf.isRvalue && !tf.isRef) + if (tf.isRvalue) + { + if(!tf.isRef) + { + error(exp.f.loc, "`__rvalue` only valid on functions that return by `ref`"); + setError(); + } + else if (sc.setUnsafe(false, exp.loc, "calling `__rvalue`-annotated function `%s`", exp.f)) + { + setError(); + } + else + { + result.rvalue = true; + } + } + else if (exp.rvalue && tf.isRef) { - error(exp.f.loc, "`__rvalue` only valid on functions that return by `ref`"); - setError(); + if (sc.setUnsafe(false, exp.loc, "moving result of `ref` function `%s` with `__rvalue`", exp.f)) + { + setError(); + } } } } @@ -7317,6 +7354,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 @@ -8191,37 +8229,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; @@ -10619,7 +10627,12 @@ version (IN_LLVM) { 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; @@ -10661,7 +10674,6 @@ version (IN_LLVM) // Do not need to overwrite this.e2 goto Ltupleassign; } - Lnomatch: } /* Inside constructor, if this is the first assignment of object field, @@ -11265,25 +11277,30 @@ version (IN_LLVM) */ 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); @@ -11293,30 +11310,27 @@ version (IN_LLVM) 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()) @@ -11785,6 +11799,7 @@ version (IN_LLVM) res = new LoweredAssignExp(ae, res); res.type = ae.type; + res = res.checkGC(sc); return res; } @@ -12819,6 +12834,57 @@ version (IN_LLVM) 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) { @@ -15796,11 +15862,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 */ @@ -16759,11 +16826,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 @@ -16773,6 +16841,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; @@ -16818,15 +16887,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) { @@ -16842,7 +16915,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) { @@ -17494,7 +17567,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; @@ -17708,3 +17781,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/dmd/frontend.h b/dmd/frontend.h index b41539e1303..987b5974e6f 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -96,6 +96,7 @@ class Import; class EnumDeclaration; class SymbolDeclaration; class AttribDeclaration; +class AlignDeclaration; class AnonDeclaration; class VisibilityDeclaration; class OverloadSet; @@ -553,14 +554,23 @@ class Dsymbol : public ASTNode { bool errors; PASS semanticRun; + bool deferred; + bool deferred2; + bool deferred3; BitFields() : errors(), - semanticRun((PASS)0u) + semanticRun((PASS)0u), + deferred(), + deferred2(), + deferred3() { } - BitFields(bool errors, PASS semanticRun = (PASS)0u) : + BitFields(bool errors, PASS semanticRun = (PASS)0u, bool deferred = false, bool deferred2 = false, bool deferred3 = false) : errors(errors), - semanticRun(semanticRun) + semanticRun(semanticRun), + deferred(deferred), + deferred2(deferred2), + deferred3(deferred3) {} }; @@ -568,6 +578,12 @@ class Dsymbol : public ASTNode bool errors(bool v); PASS semanticRun() const; PASS semanticRun(PASS v); + bool deferred() const; + bool deferred(bool v); + bool deferred2() const; + bool deferred2(bool v); + bool deferred3() const; + bool deferred3(bool v); private: uint8_t bitFields; public: @@ -620,7 +636,6 @@ class Dsymbol : public ASTNode virtual bool needThis(); virtual Visibility visible(); virtual Dsymbol* syntaxCopy(Dsymbol* s); - virtual bool hasPointers(); virtual void addObjcSymbols(Array* classes, Array* categories); virtual void addComment(const char* comment); const char* comment(); @@ -677,6 +692,7 @@ class Dsymbol : public ASTNode EnumDeclaration* isEnumDeclaration(); SymbolDeclaration* isSymbolDeclaration(); AttribDeclaration* isAttribDeclaration(); + AlignDeclaration* isAlignDeclaration(); AnonDeclaration* isAnonDeclaration(); CPPNamespaceDeclaration* isCPPNamespaceDeclaration(); VisibilityDeclaration* isVisibilityDeclaration(); @@ -1765,6 +1781,7 @@ class TemplateDeclaration final : public ScopeDsymbol bool isTrivialAliasSeq; bool isTrivialAlias; bool deprecated_; + bool isCmacro; Visibility visibility; TemplatePrevious* previous; Expression* lastConstraint; @@ -1841,7 +1858,6 @@ class TemplateMixin final : public TemplateInstance TypeQualified* tqual; TemplateInstance* syntaxCopy(Dsymbol* s) override; const char* kind() const override; - bool hasPointers() override; void accept(Visitor* v) override; }; @@ -2387,14 +2403,17 @@ class Expression : public ASTNode { bool parens; bool rvalue; + bool gcPassDone; BitFields() : parens(), - rvalue() + rvalue(), + gcPassDone() { } - BitFields(bool parens, bool rvalue = false) : + BitFields(bool parens, bool rvalue = false, bool gcPassDone = false) : parens(parens), - rvalue(rvalue) + rvalue(rvalue), + gcPassDone(gcPassDone) {} }; @@ -2402,6 +2421,8 @@ class Expression : public ASTNode bool parens(bool v); bool rvalue() const; bool rvalue(bool v); + bool gcPassDone() const; + bool gcPassDone(bool v); private: uint8_t bitFields; public: @@ -2785,6 +2806,7 @@ class CommaExp final : public BinExp public: const bool isGenerated; bool allowCommaExp; + Expression* originalExp; bool isLvalue() override; Optional toBool() override; void accept(Visitor* v) override; @@ -3621,6 +3643,7 @@ class StringExp final : public Expression uint8_t sz; bool committed; bool hexString; + bool cMacro; enum : char { NoPostfix = 0u }; static StringExp* create(Loc loc, const char* s); @@ -4860,6 +4883,7 @@ class TypeTag final : public Type Loc loc; TOK tok; structalign_t packalign; + Array* alignExps; Identifier* id; Type* base; Array* members; @@ -4929,7 +4953,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; }; @@ -5562,7 +5585,7 @@ struct UnionExp final char realexp[48LLU]; char complexexp[64LLU]; char symoffexp[56LLU]; - char stringexp[43LLU]; + char stringexp[44LLU]; char arrayliteralexp[40LLU]; char assocarrayliteralexp[48LLU]; char structliteralexp[64LLU]; @@ -6369,7 +6392,6 @@ class AggregateDeclaration : public ScopeDsymbol bool disableNew; Sizeok sizeok; virtual Scope* newScope(Scope* sc); - virtual void finalizeSize() = 0; uinteger_t size(Loc loc) final override; Type* getType() final override; bool isDeprecated() const final override; @@ -6434,7 +6456,6 @@ class AttribDeclaration : public Dsymbol public: Array* decl; const char* kind() const override; - bool hasPointers() final override; void addObjcSymbols(Array* classes, Array* categories) final override; void accept(Visitor* v) override; }; @@ -6611,7 +6632,6 @@ class Condition : public ASTNode Include inc; DYNCAST dyncast() const final override; virtual Condition* syntaxCopy() = 0; - virtual int32_t include(Scope* sc) = 0; virtual DebugCondition* isDebugCondition(); virtual VersionCondition* isVersionCondition(); virtual StaticIfCondition* isStaticIfCondition(); @@ -6640,7 +6660,6 @@ class DebugCondition final : public DVCondition { public: static void addGlobalIdent(const char* ident); - int32_t include(Scope* sc) override; DebugCondition* isDebugCondition() override; void accept(Visitor* v) override; }; @@ -6650,7 +6669,6 @@ class VersionCondition final : public DVCondition public: static void addGlobalIdent(const char* ident); static void addPredefinedGlobalIdent(const char* ident); - int32_t include(Scope* sc) override; VersionCondition* isVersionCondition() override; void accept(Visitor* v) override; }; @@ -6660,7 +6678,6 @@ class StaticIfCondition final : public Condition public: Expression* exp; StaticIfCondition* syntaxCopy() override; - int32_t include(Scope* sc) override; void accept(Visitor* v) override; StaticIfCondition* isStaticIfCondition() override; }; @@ -6720,13 +6737,11 @@ class ClassDeclaration : public AggregateDeclaration virtual bool isBaseOf(ClassDeclaration* cd, int32_t* poffset); bool isBaseInfoComplete() const; - void finalizeSize() final override; bool hasMonitor(); bool isCOMclass() const; virtual bool isCOMinterface() const; bool isCPPclass() const; virtual bool isCPPinterface() const; - bool isAbstract(); virtual int32_t vtblOffset() const; const char* kind() const override; void addObjcSymbols(Array* classes, Array* categories) final override; @@ -6844,7 +6859,6 @@ class OverDeclaration final : public Declaration bool equals(const RootObject* const o) const override; bool overloadInsert(Dsymbol* s) override; bool isOverloadable() const override; - Dsymbol* isUnique(); void accept(Visitor* v) override; }; @@ -6915,7 +6929,6 @@ class VarDeclaration : public Declaration bool isThreadlocal() final override; bool isCTFE(); bool isOverlappedWith(VarDeclaration* v); - bool hasPointers() final override; bool canTakeAddressOf(); bool needsScopeDtor(); Dsymbol* toAlias() final override; @@ -7455,13 +7468,12 @@ class StructDeclaration : public AggregateDeclaration static StructDeclaration* create(Loc loc, Identifier* id, bool inObject); StructDeclaration* syntaxCopy(Dsymbol* s) override; const char* kind() const override; - void finalizeSize() final override; bool isPOD(); bool hasCopyConstruction(); void accept(Visitor* v) override; uint32_t numArgTypes() const; Type* argType(uint32_t index); - bool hasRegularCtor(bool checkDisabled = false); + bool hasRegularCtor(bool ignoreDisabled = false); }; class UnionDeclaration final : public StructDeclaration @@ -7555,23 +7567,19 @@ class ImportAllVisitor : public Visitor void visit(StaticForeachDeclaration* _) override; }; -extern Array* include(Dsymbol* d, Scope* sc); - -class IncludeVisitor : public Visitor +class ConditionIncludeVisitor : public Visitor { public: using Visitor::visit; Scope* sc; Array* symbols; - IncludeVisitor(Scope* sc); + ConditionIncludeVisitor(Scope* sc); void visit(AttribDeclaration* ad) override; void visit(ConditionalDeclaration* cdc) override; void visit(StaticIfDeclaration* sif) override; void visit(StaticForeachDeclaration* sfd) override; }; -extern void addComment(Dsymbol* d, const char* comment); - class AddCommentVisitor : public Visitor { public: @@ -7584,12 +7592,6 @@ class AddCommentVisitor : public Visitor void visit(StaticForeachDeclaration* sfd) override; }; -extern bool hasStaticCtorOrDtor(Dsymbol* d); - -extern bool isFuncHidden(ClassDeclaration* cd, FuncDeclaration* fd); - -extern void lowerNonArrayAggregate(StaticForeach* sfe, Scope* sc); - class NrvoWalker final : public StatementRewriteWalker { public: @@ -7607,6 +7609,7 @@ class NOGCVisitor final : public StoppableVisitor public: using StoppableVisitor::visit; FuncDeclaration* f; + Scope* sc; bool checkOnly; bool err; bool nogcExceptions; @@ -8988,7 +8991,6 @@ struct Id final static Identifier* CMain; static Identifier* rt_init; static Identifier* _d_HookTraceImpl; - static Identifier* _d_arraysetlengthTImpl; static Identifier* _d_arraysetlengthT; static Identifier* _d_arraysetlengthTTrace; static Identifier* _d_arrayappendT; diff --git a/dmd/func.d b/dmd/func.d index c0b48bc69e8..3496deb8d0a 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -872,15 +872,13 @@ version (IN_LLVM) 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 @@ -1427,7 +1425,8 @@ extern (C++) final class CtorDeclaration : FuncDeclaration override const(char)* kind() const { - return isCpCtor ? "copy constructor" : "constructor"; + return isCpCtor ? "copy constructor" : + isMoveCtor ? "move constructor" : "constructor"; } override bool isVirtual() const diff --git a/dmd/funcsem.d b/dmd/funcsem.d index d51cfcbdd1c..33974c0b1bb 100644 --- a/dmd/funcsem.d +++ b/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) @@ -277,20 +288,6 @@ version (IN_LLVM) 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. @@ -318,7 +315,6 @@ version (IN_LLVM) 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, @@ -568,589 +564,699 @@ version (IN_LLVM) 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 + + /* Purity and safety can be inferred for some functions by examining + * the function body. + */ + if (funcdecl.canInferAttributes(sc)) + funcdecl.initInferAttributes(); + + // LDC relies on semanticRun variable not being reset here + if (!IN_LLVM || funcdecl.semanticRun < PASS.semanticdone) + 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) + { + const(char)* type = funcdecl.isMain() ? "main" : funcdecl.isWinMain() ? "winmain" : funcdecl.isDllMain() ? "dllmain" : cast(const(char)*)null; + Module mod = sc._module; + + if (type && mod) + { + 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 (funcdecl.storage_class & STC.abstract_) - cd.isabstract = ThreeState.yes; + if (funcdecl.fbody && sc._module.isRoot() && + (funcdecl.isMain() || funcdecl.isWinMain() || funcdecl.isDllMain() || funcdecl.isCMain())) + global.hasMainFunction = true; - // if static function, do not put in vtbl[] - if (!funcdecl.isVirtual()) + if (funcdecl.fbody && funcdecl.isMain() && sc._module.isRoot()) + { + // check if `_d_cmain` is defined + bool cmainTemplateExists() { - //printf("\tnot virtual\n"); - goto Ldone; + 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; } - // 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++) + // Only mixin `_d_cmain` if it is defined + if (cmainTemplateExists()) { - BaseClass* b = (*cd.baseclasses)[i]; - ClassDeclaration cbd = b.type.toBasetype().isClassHandle(); - if (!cbd) + // 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); - } - - L2: - objc.setSelector(funcdecl, sc); - objc.checkLinkage(funcdecl); - objc.addToClassMethodList(funcdecl, cd); - objc.setAsOptional(funcdecl, sc); + functionToBufferFull(cast(TypeFunction)(fd.type), buf1, + new Identifier(fd.toPrettyChars()), hgs, null); - /* 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()); - } - } - } - } + error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?", + funcdeclToChars, buf1.peekChars()); - 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 - - /* Purity and safety can be inferred for some functions by examining - * the function body. - */ - if (funcdecl.canInferAttributes(sc)) - funcdecl.initInferAttributes(); - - // LDC relies on semanticRun variable not being reset here - if (!IN_LLVM || funcdecl.semanticRun < PASS.semanticdone) - funcdecl.semanticRun = PASS.semanticdone; +L2: + objc.setSelector(funcdecl, sc); + objc.checkLinkage(funcdecl); + objc.addToClassMethodList(funcdecl, cd); + objc.setAsOptional(funcdecl, sc); - /* Save scope for possible later use (if we need the - * function internals) + /* Go through all the interface bases. + * Disallow overriding any final functions in the interface(s). */ - 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; } /***************************************** @@ -1664,13 +1770,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); } @@ -1690,7 +1800,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; @@ -1720,8 +1832,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()); @@ -1789,10 +1907,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; } } @@ -1810,6 +1933,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: @@ -3574,3 +3753,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/dmd/hdrgen.d b/dmd/hdrgen.d index faedec478a4..a3fa6a1e81c 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -2730,6 +2730,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 @@ -3258,9 +3264,13 @@ public: override void visit(DebugCondition c) { - buf.writestring("debug ("); - buf.writestring(c.ident.toString()); - buf.writeByte(')'); + buf.writestring("debug"); + if (c.ident) + { + buf.writestring(" ("); + buf.writestring(c.ident.toString()); + buf.writeByte(')'); + } } override void visit(VersionCondition c) diff --git a/dmd/iasmgcc.d b/dmd/iasmgcc.d index 3d6e6ab5b51..4d9a758bb47 100644 --- a/dmd/iasmgcc.d +++ b/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/dmd/id.d b/dmd/id.d index 9985d2c196b..3602efdf745 100644 --- a/dmd/id.d +++ b/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/dmd/imphint.d b/dmd/imphint.d index 382a0f37863..e22bcc8b123 100644 --- a/dmd/imphint.d +++ b/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/dmd/importc.d b/dmd/importc.d index 2f88a21c049..059de62b1f9 100644 --- a/dmd/importc.d +++ b/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/dmd/initsem.d b/dmd/initsem.d index 94aff2ac5ea..7247d747974 100644 --- a/dmd/initsem.d +++ b/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); @@ -398,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 { @@ -759,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; diff --git a/dmd/location.d b/dmd/location.d index 393ffb8a92d..daff06f3d2c 100644 --- a/dmd/location.d +++ b/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/dmd/main.d b/dmd/main.d index 43c5a621df5..4106dabd713 100644 --- a/dmd/main.d +++ b/dmd/main.d @@ -438,6 +438,7 @@ else Module._init(); Expression._init(); Objc._init(); + Loc._init(); reconcileLinkRunLib(params, files.length, target.obj_ext); version(CRuntime_Microsoft) diff --git a/dmd/mangle/package.d b/dmd/mangle/package.d index 3ad2c7d5794..cc797614ed0 100644 --- a/dmd/mangle/package.d +++ b/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/dmd/mtype.d b/dmd/mtype.d index e1d11484a52..924cb1edac2 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -2238,7 +2238,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; } @@ -3765,6 +3765,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 @@ -3774,7 +3775,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); @@ -3782,6 +3783,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/dmd/mtype.h b/dmd/mtype.h index 490bcf30012..62d20c1f16c 100644 --- a/dmd/mtype.h +++ b/dmd/mtype.h @@ -559,6 +559,8 @@ class TypeFunction final : public TypeNext 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/dmd/nogc.d b/dmd/nogc.d index f1494a409f6..5e3c164acbb 100644 --- a/dmd/nogc.d +++ b/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/dmd/nspace.d b/dmd/nspace.d index 0c93f0e7994..b8116343d6f 100644 --- a/dmd/nspace.d +++ b/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/dmd/nspace.h b/dmd/nspace.h index 7b4c302303d..782688b9de1 100644 --- a/dmd/nspace.h +++ b/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/dmd/optimize.d b/dmd/optimize.d index 66b8c6a4953..b13f8c64584 100644 --- a/dmd/optimize.d +++ b/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/dmd/parse.d b/dmd/parse.d index f7ac4b564e6..c57f1d3f7f7 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -1320,7 +1320,21 @@ 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; @@ -2759,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'; } @@ -4068,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"); @@ -7091,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; @@ -7106,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(); @@ -8250,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; @@ -8455,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); @@ -9054,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: @@ -9089,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: @@ -9124,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: @@ -9159,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) { @@ -9224,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); @@ -9256,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); @@ -9272,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); @@ -9286,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); @@ -9300,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); diff --git a/dmd/sarif.d b/dmd/sarif.d index ba2867874b8..f596b788b35 100644 --- a/dmd/sarif.d +++ b/dmd/sarif.d @@ -241,6 +241,11 @@ void generateSarifReport(bool executionSuccessful) nothrow string cleanedVersion = toolVersion[0 .. length]; + // strip trailing newlines + while (cleanedVersion.length > 0 && (cleanedVersion[$ - 1] == '\n' || cleanedVersion[$ - 1] == '\r')) + cleanedVersion = cleanedVersion[0 .. $ - 1]; + + // Build SARIF report ob.writestringln("{"); ob.level = 1; diff --git a/dmd/semantic2.d b/dmd/semantic2.d index 1c58e63936d..26f0fa8a254 100644 --- a/dmd/semantic2.d +++ b/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/dmd/semantic3.d b/dmd/semantic3.d index 3d37bf209ee..800aa6f8dd7 100644 --- a/dmd/semantic3.d +++ b/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/dmd/statementsem.d b/dmd/statementsem.d index c4ab94df7c8..88898f0b497 100644 --- a/dmd/statementsem.d +++ b/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; @@ -1710,7 +1710,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(); @@ -1898,7 +1898,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; @@ -1964,6 +1964,16 @@ version (IN_LLVM) 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; @@ -2621,7 +2631,7 @@ version (IN_LLVM) if (tbret && tbret.ty == Tvoid || convToVoid) { - if (!convToVoid) + if (!convToVoid && !texp.isTypeError()) { error(rs.loc, "cannot return non-void from `void` function"); errors = true; @@ -2654,7 +2664,7 @@ version (IN_LLVM) if (e0) { e0 = e0.optimize(WANTvalue); - e0 = checkGC(sc, e0); + e0 = e0.checkGC(sc); } } @@ -3080,7 +3090,7 @@ version (IN_LLVM) 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) @@ -3204,7 +3214,7 @@ version (IN_LLVM) 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_) @@ -3768,7 +3778,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/dmd/target.d b/dmd/target.d index 462f8cbaf3c..764a819c9bb 100644 --- a/dmd/target.d +++ b/dmd/target.d @@ -472,7 +472,7 @@ else // !IN_LLVM DoubleProperties.initialize(); RealProperties.initialize(); - isLP64 = isX86_64; + isLP64 = isX86_64 || isAArch64; // These have default values for 32 bit code, they get // adjusted for 64 bit code. diff --git a/dmd/template.h b/dmd/template.h index af910f4dd90..8d6c75a82a4 100644 --- a/dmd/template.h +++ b/dmd/template.h @@ -71,6 +71,7 @@ class TemplateDeclaration final : public ScopeDsymbol 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 @@ -288,7 +289,6 @@ class TemplateMixin final : public TemplateInstance TemplateMixin *syntaxCopy(Dsymbol *s) override; const char *kind() const override; - bool hasPointers() override; void accept(Visitor *v) override { v->visit(this); } }; diff --git a/dmd/templatesem.d b/dmd/templatesem.d index ac38b3d2ae8..f047b7d347d 100644 --- a/dmd/templatesem.d +++ b/dmd/templatesem.d @@ -190,7 +190,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; diff --git a/dmd/traits.d b/dmd/traits.d index 193e772dc21..98dc0533f38 100644 --- a/dmd/traits.d +++ b/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/dmd/typesem.d b/dmd/typesem.d index 0d99664b0f9..ada16b8f79b 100644 --- a/dmd/typesem.d +++ b/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); @@ -3289,7 +3316,7 @@ Type merge(Type type) goto default; case Tfunction: - if (!type.nextOf()) + if (!type.nextOf()) // don't merge if return type is unknown return type; goto default; @@ -3433,8 +3460,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)) @@ -3444,18 +3473,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) @@ -3463,30 +3495,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()) { @@ -3512,7 +3531,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()); } } @@ -6709,6 +6728,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()) @@ -6719,6 +6739,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/dmd/vsoptions.d b/dmd/vsoptions.d index d01eb336b19..6051cd9861a 100644 --- a/dmd/vsoptions.d +++ b/dmd/vsoptions.d @@ -195,7 +195,7 @@ version (IN_LLVM) { /* not needed */ } else * Params: * x64 = target architecture (x86 if false) * Returns: - * absolute path to cl.exe, just "cl.exe" if not found + * absolute path to cl.exe, and just "cl.exe" if not found */ const(char)* compilerPath(bool x64) { diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index f7558238d3a..7d24c08c339 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -281,7 +281,7 @@ void DtoCAssert(Module *M, Loc loc, LLValue *msg) { const auto fn = getCAssertFunction(loc, gIR->module); llvm::SmallVector args; - if (triple.isOSDarwin()) { + if (triple.isOSDarwin() || triple.isOSFreeBSD()) { const auto irFunc = gIR->func(); const auto funcName = irFunc && irFunc->decl ? irFunc->decl->toPrettyChars() : ""; diff --git a/gen/passes/SimplifyDRuntimeCalls.cpp b/gen/passes/SimplifyDRuntimeCalls.cpp index ebbe2e166f0..76ba728ace9 100644 --- a/gen/passes/SimplifyDRuntimeCalls.cpp +++ b/gen/passes/SimplifyDRuntimeCalls.cpp @@ -64,55 +64,6 @@ Value *LibCallOptimization::EmitMemCpy(Value *Dst, Value *Src, Value *Len, // Miscellaneous LibCall Optimizations //===----------------------------------------------------------------------===// -//===---------------------------------------===// -// '_d_arraysetlengthT'/'_d_arraysetlengthiT' Optimizations - -Value *ArraySetLengthOpt::CallOptimizer(Function *Callee, CallInst *CI, - IRBuilder<> &B) { - // Verify we have a reasonable prototype for _d_arraysetlength[i]T - const FunctionType *FT = Callee->getFunctionType(); - if (Callee->arg_size() != 4 || !isa(FT->getReturnType()) || - !isa(FT->getParamType(1)) || - FT->getParamType(1) != FT->getParamType(2) || - FT->getParamType(3) != FT->getReturnType()) { - return nullptr; - } - - // Whether or not this allocates is irrelevant if the result isn't used. - // Just delete if that's the case. - if (CI->use_empty()) { - return CI; - } - - Value *NewLen = CI->getOperand(1); - if (Constant *NewCst = dyn_cast(NewLen)) { - Value *Data = CI->getOperand(3); - - // For now, we just catch the simplest of cases. - // - // TODO: Implement a more general way to compare old and new - // lengths, to catch cases like "arr.length = arr.length - 1;" - // (But beware of unsigned overflow! For example, we can't - // safely transform that example if arr.length may be 0) - - // Setting length to 0 never reallocates, so replace by data argument - if (NewCst->isNullValue()) { - return Data; - } - - // If both lengths are constant integers, see if NewLen <= OldLen - Value *OldLen = CI->getOperand(2); - if (ConstantInt *OldInt = dyn_cast(OldLen)) { - if (ConstantInt *NewInt = dyn_cast(NewCst)) { - if (NewInt->getValue().ule(OldInt->getValue())) { - return Data; - } - } - } - } - return nullptr; -} - /// AllocationOpt - Common optimizations for various GC allocations. Value *AllocationOpt::CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { @@ -274,8 +225,6 @@ FunctionPass *createSimplifyDRuntimeCalls() { /// we know. void SimplifyDRuntimeCalls::InitOptimizations() { // Some array-related optimizations - Optimizations["_d_arraysetlengthT"] = &ArraySetLength; - Optimizations["_d_arraysetlengthiT"] = &ArraySetLength; Optimizations["_d_array_slice_copy"] = &ArraySliceCopy; /* Delete calls to runtime functions which aren't needed if their result is diff --git a/gen/passes/SimplifyDRuntimeCalls.h b/gen/passes/SimplifyDRuntimeCalls.h index 4311e6689ca..3344170fcad 100644 --- a/gen/passes/SimplifyDRuntimeCalls.h +++ b/gen/passes/SimplifyDRuntimeCalls.h @@ -39,11 +39,6 @@ class LLVM_LIBRARY_VISIBILITY LibCallOptimization { llvm::AliasAnalysis &AA, llvm::IRBuilder<> &B); }; -/// ArraySetLengthOpt - remove libcall for arr.length = N if N <= arr.length -struct LLVM_LIBRARY_VISIBILITY ArraySetLengthOpt : public LibCallOptimization { - llvm::Value *CallOptimizer(llvm::Function *Callee, llvm::CallInst *CI, - llvm::IRBuilder<> &B) override; -}; /// AllocationOpt - Common optimizations for various GC allocations. struct LLVM_LIBRARY_VISIBILITY AllocationOpt : public LibCallOptimization { llvm::Value *CallOptimizer(llvm::Function *Callee, llvm::CallInst *CI, @@ -62,7 +57,6 @@ struct LLVM_LIBRARY_VISIBILITY SimplifyDRuntimeCalls { llvm::StringMap Optimizations; // Array operations - ArraySetLengthOpt ArraySetLength; ArraySliceCopyOpt ArraySliceCopy; // GC allocations diff --git a/gen/runtime.cpp b/gen/runtime.cpp index cde90036f7a..ff10d1c3025 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -75,8 +75,6 @@ static void checkForImplicitGCCall(Loc loc, const char *name) { "_d_arrayappendcTX", "_d_arrayappendcd", "_d_arrayappendwd", - "_d_arraysetlengthT", - "_d_arraysetlengthiT", "_d_assocarrayliteralTX", "_d_callfinalizer", "_d_delarray_t", @@ -343,6 +341,8 @@ llvm::Function *getRuntimeFunction(Loc loc, llvm::Module &target, // C assert function: // OSX: void __assert_rtn(const char *func, const char *file, unsigned line, // const char *msg) +// FreeBSD: void __assert(const char *func, const char *file, int line, +// const char *msg) // Android: void __assert(const char *file, int line, const char *msg) // MSVC: void _assert(const char *msg, const char *file, unsigned line) // Solaris: void __assert_c99(const char *assertion, const char *filename, int line_num, @@ -378,8 +378,9 @@ static std::vector getCAssertFunctionParamTypes() { const auto voidPtr = Type::tvoidptr; const auto uint = Type::tuns32; - if (triple.isOSDarwin() || triple.isOSSolaris() || triple.isMusl() || - global.params.isUClibcEnvironment || triple.isGNUEnvironment()) { + if (triple.isOSDarwin() || triple.isOSFreeBSD() || triple.isOSSolaris() || + triple.isMusl() || global.params.isUClibcEnvironment || + triple.isGNUEnvironment()) { return {voidPtr, voidPtr, uint, voidPtr}; } if (triple.getEnvironment() == llvm::Triple::Android) { diff --git a/ir/irclass.cpp b/ir/irclass.cpp index b98b0022512..7e51208c66b 100644 --- a/ir/irclass.cpp +++ b/ir/irclass.cpp @@ -216,7 +216,7 @@ LLConstant *IrClass::getVtblInit() { FuncDeclaration *fd = dsym->isFuncDeclaration(); assert(fd && "vtbl entry not a function"); - if (cd->isAbstract() || (fd->isAbstract() && !fd->fbody)) { + if (isAbstract(cd) || (fd->isAbstract() && !fd->fbody)) { c = getNullPtr(); } else { // If inferring return type and semantic3 has not been run, do it now. @@ -321,14 +321,14 @@ unsigned buildClassinfoFlags(ClassDeclaration *cd) { break; } } - if (cd->isAbstract()) { + if (isAbstract(cd)) { flags |= ClassFlags::isAbstract; } for (ClassDeclaration *pc = cd; pc; pc = pc->baseClass) { if (pc->members) { for (Dsymbol *sm : *pc->members) { // printf("sm = %s %s\n", sm->kind(), sm->toChars()); - if (sm->hasPointers()) { + if (hasPointers(sm)) { return flags; } } diff --git a/runtime/druntime/src/core/checkedint.d b/runtime/druntime/src/core/checkedint.d index 9970968f379..e9b2f8086f8 100644 --- a/runtime/druntime/src/core/checkedint.d +++ b/runtime/druntime/src/core/checkedint.d @@ -906,6 +906,10 @@ unittest pragma(inline, true) uint mulu()(uint x, uint y, ref bool overflow) { + version (D_InlineAsm_X86) enum useAsm = true; + else version (D_InlineAsm_X86_64) enum useAsm = true; + else enum useAsm = false; + version (LDC) { if (!__ctfe) @@ -915,6 +919,24 @@ uint mulu()(uint x, uint y, ref bool overflow) return res.result; } } + else static if (useAsm) + { + if (!__ctfe) + { + uint r; + bool o; + asm pure nothrow @nogc @trusted + { + mov EAX, x; + mul y; // EDX:EAX = EAX * y + mov r, EAX; + setc o; + } + overflow |= o; + return r; + } + } + immutable ulong r = ulong(x) * ulong(y); if (r >> 32) overflow = true; @@ -946,6 +968,17 @@ unittest pragma(inline, true) ulong mulu()(ulong x, uint y, ref bool overflow) { + version (LDC_HasNativeI64Mul) + { + if (!__ctfe) + return mulu(x, ulong(y), overflow); + } + else version (D_InlineAsm_X86_64) + { + if (!__ctfe) + return mulu(x, ulong(y), overflow); + } + ulong r = x * y; if (x >> 32 && r / x != y) @@ -966,6 +999,24 @@ ulong mulu()(ulong x, ulong y, ref bool overflow) return res.result; } } + else version (D_InlineAsm_X86_64) + { + if (!__ctfe) + { + ulong r; + bool o; + asm pure nothrow @nogc @trusted + { + mov RAX, x; + mul y; // RDX:RAX = RAX * y + mov r, RAX; + setc o; + } + overflow |= o; + return r; + } + } + immutable ulong r = x * y; if ((x | y) >> 32 && x && diff --git a/runtime/druntime/src/core/int128.d b/runtime/druntime/src/core/int128.d index 90a10b71d2b..d05199ae0d6 100644 --- a/runtime/druntime/src/core/int128.d +++ b/runtime/druntime/src/core/int128.d @@ -40,6 +40,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; +} + version (LDC) { pragma(inline, true) @@ -533,6 +539,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. @@ -658,12 +713,6 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus) return quotient; } -version (X86_64) -{ - version (GNU) version = GNU_OR_LDC_X86_64; - version (LDC) version = GNU_OR_LDC_X86_64; -} - /**************************** * Unsigned divide 128-bit c1 / 64-bit c2. The result must fit in 64 bits. * The remainder after division is stored to modulus. diff --git a/runtime/druntime/src/core/internal/array/capacity.d b/runtime/druntime/src/core/internal/array/capacity.d index 10ce2c65c95..7824ffd67d0 100644 --- a/runtime/druntime/src/core/internal/array/capacity.d +++ b/runtime/druntime/src/core/internal/array/capacity.d @@ -9,64 +9,315 @@ */ 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 { - 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 : 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) { - version (DigitalMars) pragma(inline, false); - version (D_TypeInfo) + 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 +{ + 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) + { + 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 +326,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/runtime/druntime/src/core/internal/array/concatenation.d b/runtime/druntime/src/core/internal/array/concatenation.d index 13ec5fad40f..fab2a5a9b7c 100644 --- a/runtime/druntime/src/core/internal/array/concatenation.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/internal/array/construction.d b/runtime/druntime/src/core/internal/array/construction.d index 567de440fbd..acecc4f141b 100644 --- a/runtime/druntime/src/core/internal/array/construction.d +++ b/runtime/druntime/src/core/internal/array/construction.d @@ -346,6 +346,7 @@ T[] _d_newarrayUPureNothrow(T)(size_t length, bool isShared=false) pure nothrow T[] _d_newarrayU(T)(size_t length, bool isShared=false) @trusted { + import core.checkedint : mulu; import core.exception : onOutOfMemoryError; import core.internal.traits : Unqual; import core.internal.array.utils : __arrayAlloc; @@ -353,53 +354,24 @@ T[] _d_newarrayU(T)(size_t length, bool isShared=false) @trusted alias UnqT = Unqual!T; size_t elemSize = T.sizeof; - size_t arraySize; debug(PRINTF) printf("_d_newarrayU(length = x%zu, size = %zu)\n", length, elemSize); if (length == 0 || elemSize == 0) return null; - /+ LDC: don't blind the optimizer; core.checkedint.mulu is basically an intrinsic - version (D_InlineAsm_X86) + bool overflow = false; + const arraySize = mulu(elemSize, length, overflow); + if (!overflow) { - asm pure nothrow @nogc + if (auto arr = __arrayAlloc!UnqT(arraySize)) { - mov EAX, elemSize ; - mul EAX, length ; - mov arraySize, EAX ; - jnc Lcontinue ; + debug(PRINTF) printf("p = %p\n", arr.ptr); + return (cast(T*) arr.ptr)[0 .. length]; } } - else version (D_InlineAsm_X86_64) - { - asm pure nothrow @nogc - { - mov RAX, elemSize ; - mul RAX, length ; - mov arraySize, RAX ; - jnc Lcontinue ; - } - } - else+/ - { - import core.checkedint : mulu; - - bool overflow = false; - arraySize = mulu(elemSize, length, overflow); - if (!overflow) - goto Lcontinue; - } -Loverflow: onOutOfMemoryError(); assert(0); - -Lcontinue: - auto arr = __arrayAlloc!UnqT(arraySize); - if (!arr.ptr) - goto Loverflow; - debug(PRINTF) printf("p = %p\n", arr.ptr); - return (cast(T*) arr.ptr)[0 .. length]; } /// ditto @@ -506,7 +478,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); @@ -521,7 +493,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); @@ -603,7 +575,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/runtime/druntime/src/core/internal/array/utils.d b/runtime/druntime/src/core/internal/array/utils.d index deaae3f95da..1d105e6ebf1 100644 --- a/runtime/druntime/src/core/internal/array/utils.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/internal/lifetime.d b/runtime/druntime/src/core/internal/lifetime.d index a7446debae6..fd78de221d1 100644 --- a/runtime/druntime/src/core/internal/lifetime.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/stdc/fenv.d b/runtime/druntime/src/core/stdc/fenv.d index ce77d5c1e6b..7d42d5c8c02 100644 --- a/runtime/druntime/src/core/stdc/fenv.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/stdc/math.d b/runtime/druntime/src/core/stdc/math.d index e2efdb904b0..c35aed8545d 100644 --- a/runtime/druntime/src/core/stdc/math.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/bionic/err.d b/runtime/druntime/src/core/sys/bionic/err.d index e2756e10c91..a14f21bb1ec 100644 --- a/runtime/druntime/src/core/sys/bionic/err.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/bionic/string.d b/runtime/druntime/src/core/sys/bionic/string.d index 10a5610ac44..9430a7bab4e 100644 --- a/runtime/druntime/src/core/sys/bionic/string.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/darwin/err.d b/runtime/druntime/src/core/sys/darwin/err.d index d96c790f3b6..19b51626a16 100644 --- a/runtime/druntime/src/core/sys/darwin/err.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/darwin/string.d b/runtime/druntime/src/core/sys/darwin/string.d index ac988b58f0d..14bae215cde 100644 --- a/runtime/druntime/src/core/sys/darwin/string.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/dragonflybsd/err.d b/runtime/druntime/src/core/sys/dragonflybsd/err.d index c3693f85f5e..7f7cf9467fa 100644 --- a/runtime/druntime/src/core/sys/dragonflybsd/err.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/dragonflybsd/string.d b/runtime/druntime/src/core/sys/dragonflybsd/string.d index 1a85ba606a1..c15bb9268e5 100644 --- a/runtime/druntime/src/core/sys/dragonflybsd/string.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/freebsd/err.d b/runtime/druntime/src/core/sys/freebsd/err.d index 8937e0ec705..5cb443a6f8a 100644 --- a/runtime/druntime/src/core/sys/freebsd/err.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/freebsd/string.d b/runtime/druntime/src/core/sys/freebsd/string.d index 459e9115878..ba7b3c019d9 100644 --- a/runtime/druntime/src/core/sys/freebsd/string.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/linux/err.d b/runtime/druntime/src/core/sys/linux/err.d index c3752de5207..d346a0805ff 100644 --- a/runtime/druntime/src/core/sys/linux/err.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/linux/linux/if_packet.d b/runtime/druntime/src/core/sys/linux/linux/if_packet.d index b50b6a33914..6dd95808d61 100644 --- a/runtime/druntime/src/core/sys/linux/linux/if_packet.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/linux/netinet/in_.d b/runtime/druntime/src/core/sys/linux/netinet/in_.d index 1b428f5aecc..f3c23572fb2 100644 --- a/runtime/druntime/src/core/sys/linux/netinet/in_.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/linux/perf_event.d b/runtime/druntime/src/core/sys/linux/perf_event.d index 0ad072974d5..f8bedfb81bd 100644 --- a/runtime/druntime/src/core/sys/linux/perf_event.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/linux/sched.d b/runtime/druntime/src/core/sys/linux/sched.d index 5cd512e8263..0a940db65ed 100644 --- a/runtime/druntime/src/core/sys/linux/sched.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/linux/string.d b/runtime/druntime/src/core/sys/linux/string.d index a8da3982461..7288231730d 100644 --- a/runtime/druntime/src/core/sys/linux/string.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/linux/sys/syscall.d b/runtime/druntime/src/core/sys/linux/sys/syscall.d new file mode 100644 index 00000000000..9e313e15c93 --- /dev/null +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/linux/sys/time.d b/runtime/druntime/src/core/sys/linux/sys/time.d index 4b56229687c..9eb48f1c5ef 100644 --- a/runtime/druntime/src/core/sys/linux/sys/time.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/linux/syscall.d b/runtime/druntime/src/core/sys/linux/syscall.d new file mode 100644 index 00000000000..84d03e75fb1 --- /dev/null +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/linux/unistd.d b/runtime/druntime/src/core/sys/linux/unistd.d index 548870268db..3194ec2962c 100644 --- a/runtime/druntime/src/core/sys/linux/unistd.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/netbsd/err.d b/runtime/druntime/src/core/sys/netbsd/err.d index 44eb66adc2f..399ddea989a 100644 --- a/runtime/druntime/src/core/sys/netbsd/err.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/netbsd/string.d b/runtime/druntime/src/core/sys/netbsd/string.d index f1281da275b..d83d22d56dd 100644 --- a/runtime/druntime/src/core/sys/netbsd/string.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/netbsd/sys/featuretest.d b/runtime/druntime/src/core/sys/netbsd/sys/featuretest.d index 3901ea9703b..ded053a36e4 100644 --- a/runtime/druntime/src/core/sys/netbsd/sys/featuretest.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/openbsd/err.d b/runtime/druntime/src/core/sys/openbsd/err.d index b4676140e38..271f2c4bfc6 100644 --- a/runtime/druntime/src/core/sys/openbsd/err.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/openbsd/string.d b/runtime/druntime/src/core/sys/openbsd/string.d index 4480c94ac37..e0c33be9d67 100644 --- a/runtime/druntime/src/core/sys/openbsd/string.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/posix/netdb.d b/runtime/druntime/src/core/sys/posix/netdb.d index 70a5fe1901f..4713f4b4955 100644 --- a/runtime/druntime/src/core/sys/posix/netdb.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/posix/netinet/in_.d b/runtime/druntime/src/core/sys/posix/netinet/in_.d index 5818ee6e22b..09a4a5e07d1 100644 --- a/runtime/druntime/src/core/sys/posix/netinet/in_.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/posix/signal.d b/runtime/druntime/src/core/sys/posix/signal.d index e3d80fb0218..bdc68687d0f 100644 --- a/runtime/druntime/src/core/sys/posix/signal.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/posix/sys/ioctl.d b/runtime/druntime/src/core/sys/posix/sys/ioctl.d index caf3ebafb5a..27584d357c4 100644 --- a/runtime/druntime/src/core/sys/posix/sys/ioctl.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/posix/sys/select.d b/runtime/druntime/src/core/sys/posix/sys/select.d index bd342503252..c8a88bddc0c 100644 --- a/runtime/druntime/src/core/sys/posix/sys/select.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/posix/sys/socket.d b/runtime/druntime/src/core/sys/posix/sys/socket.d index 12824373d58..5bdc22294c1 100644 --- a/runtime/druntime/src/core/sys/posix/sys/socket.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/posix/sys/stat.d b/runtime/druntime/src/core/sys/posix/sys/stat.d index 328f620a42a..ab79a406750 100644 --- a/runtime/druntime/src/core/sys/posix/sys/stat.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/posix/sys/wait.d b/runtime/druntime/src/core/sys/posix/sys/wait.d index f6b0674a3b1..131a9400dcf 100644 --- a/runtime/druntime/src/core/sys/posix/sys/wait.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/solaris/err.d b/runtime/druntime/src/core/sys/solaris/err.d index f7876430150..03bdd7ecb98 100644 --- a/runtime/druntime/src/core/sys/solaris/err.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/windows/basetsd.d b/runtime/druntime/src/core/sys/windows/basetsd.d index 1e5a45427c7..d06bc5744ec 100644 --- a/runtime/druntime/src/core/sys/windows/basetsd.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/windows/commctrl.d b/runtime/druntime/src/core/sys/windows/commctrl.d index 073587f01c1..fcece45be46 100644 --- a/runtime/druntime/src/core/sys/windows/commctrl.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/windows/dde.d b/runtime/druntime/src/core/sys/windows/dde.d index 975c62e42f3..e4a75c5711a 100644 --- a/runtime/druntime/src/core/sys/windows/dde.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/windows/mmsystem.d b/runtime/druntime/src/core/sys/windows/mmsystem.d index 29c066e7c97..2ce75aa7888 100644 --- a/runtime/druntime/src/core/sys/windows/mmsystem.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/windows/ntdef.d b/runtime/druntime/src/core/sys/windows/ntdef.d index 160443312b4..e45d0effcd9 100644 --- a/runtime/druntime/src/core/sys/windows/ntdef.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/windows/ntsecapi.d b/runtime/druntime/src/core/sys/windows/ntsecapi.d index 77101f669b4..7088cb10202 100644 --- a/runtime/druntime/src/core/sys/windows/ntsecapi.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/windows/oleauto.d b/runtime/druntime/src/core/sys/windows/oleauto.d index f4bb40259ab..cc7b937a03a 100644 --- a/runtime/druntime/src/core/sys/windows/oleauto.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/windows/shlobj.d b/runtime/druntime/src/core/sys/windows/shlobj.d index bcd254b18ed..0e292d4c71d 100644 --- a/runtime/druntime/src/core/sys/windows/shlobj.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/windows/stat.d b/runtime/druntime/src/core/sys/windows/stat.d index 85ed24f93d8..dfc7d490c42 100644 --- a/runtime/druntime/src/core/sys/windows/stat.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/windows/threadaux.d b/runtime/druntime/src/core/sys/windows/threadaux.d index 5467f6a850b..bfbab7e8bf0 100644 --- a/runtime/druntime/src/core/sys/windows/threadaux.d +++ b/runtime/druntime/src/core/sys/windows/threadaux.d @@ -326,8 +326,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/runtime/druntime/src/core/sys/windows/vfw.d b/runtime/druntime/src/core/sys/windows/vfw.d index c0f22a9fb5b..313895f4acb 100644 --- a/runtime/druntime/src/core/sys/windows/vfw.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/windows/winbase.d b/runtime/druntime/src/core/sys/windows/winbase.d index 935c7c432cf..2c2905b6352 100644 --- a/runtime/druntime/src/core/sys/windows/winbase.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/windows/wincrypt.d b/runtime/druntime/src/core/sys/windows/wincrypt.d index cb52d9e717d..f068a3a7958 100644 --- a/runtime/druntime/src/core/sys/windows/wincrypt.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/sys/windows/winnt.d b/runtime/druntime/src/core/sys/windows/winnt.d index 2b9d28f5ddc..f93ae1e36b6 100644 --- a/runtime/druntime/src/core/sys/windows/winnt.d +++ b/runtime/druntime/src/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; @@ -1556,8 +1556,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; @@ -1920,10 +1920,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 @@ -1933,7 +1933,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; @@ -1949,9 +1949,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); @@ -3426,7 +3426,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) { @@ -3544,7 +3544,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; @@ -3589,8 +3589,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)); @@ -4154,7 +4154,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/runtime/druntime/src/core/sys/windows/winuser.d b/runtime/druntime/src/core/sys/windows/winuser.d index f6414440783..a7917b774f4 100644 --- a/runtime/druntime/src/core/sys/windows/winuser.d +++ b/runtime/druntime/src/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/runtime/druntime/src/core/volatile.d b/runtime/druntime/src/core/volatile.d index c134284f30e..a9a1cef5759 100644 --- a/runtime/druntime/src/core/volatile.d +++ b/runtime/druntime/src/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/runtime/druntime/src/importc.h b/runtime/druntime/src/importc.h index 2fd756418d8..d60fcfff75d 100644 --- a/runtime/druntime/src/importc.h +++ b/runtime/druntime/src/importc.h @@ -56,10 +56,10 @@ */ #define __fastcall -#define __forceinline +#define __forceinline __attribute__((always_inline)) #undef _Check_return_ //#define _Check_return_ -#define __pragma(x) +#define __pragma(x) _Pragma(#x) #undef _GLIBCXX_USE_FLOAT128 diff --git a/runtime/druntime/src/object.d b/runtime/druntime/src/object.d index 41dc03fed7b..392a2b0e531 100644 --- a/runtime/druntime/src/object.d +++ b/runtime/druntime/src/object.d @@ -2584,8 +2584,27 @@ class Throwable : Object * $(D Throwable) is thrown from inside a $(D catch) block. The originally * caught $(D Exception) will be chained to the new $(D Throwable) via this * field. + * + * If the 0 bit is set in this, it means the next exception is refcounted, + * meaning this object owns that object and should destroy it on + * destruction. + * + * WARNING: This means we are storing an interior pointer to the next in + * chain, to signify that the next in the chain is actually reference + * counted. We rely on the fact that a pointer to a Throwable is not 1-byte + * aligned. It is important to use a local field to indicate reference + * counting since we are not allowed to look at GC-allocated references + * inside the destructor. It is very important to store this as a void*, + * since optimizers can consider an unaligned pointer to not exist. */ - private Throwable nextInChain; + private void* _nextInChainPtr; + + private @property bool _nextIsRefcounted() @trusted scope pure nothrow @nogc const + { + if (__ctfe) + return false; + return (cast(size_t)_nextInChainPtr) & 1; + } private uint _refcount; // 0 : allocated by GC // 1 : allocated by _d_newThrowable() @@ -2598,24 +2617,36 @@ class Throwable : Object * caught $(D Exception) will be chained to the new $(D Throwable) via this * field. */ - @property inout(Throwable) next() @safe inout return scope pure nothrow @nogc { return nextInChain; } + @property inout(Throwable) next() @trusted inout return scope pure nothrow @nogc + { + if (__ctfe) + return cast(inout(Throwable)) _nextInChainPtr; + + return cast(inout(Throwable)) (_nextInChainPtr - _nextIsRefcounted); + } + /** * Replace next in chain with `tail`. * Use `chainTogether` instead if at all possible. */ - @property void next(Throwable tail) @safe scope pure nothrow @nogc + @property void next(Throwable tail) @trusted scope pure nothrow @nogc { + void* newTail = cast(void*)tail; if (tail && tail._refcount) + { ++tail._refcount; // increment the replacement *first* + ++newTail; // indicate ref counting is used + } - auto n = nextInChain; - nextInChain = null; // sever the tail before deleting it + auto n = next; + auto nrc = _nextIsRefcounted; + _nextInChainPtr = null; // sever the tail before deleting it - if (n && n._refcount) + if (nrc) _d_delThrowable(n); // now delete the old tail - nextInChain = tail; // and set the new tail + _nextInChainPtr = newTail; // and set the new tail } /** @@ -2634,7 +2665,7 @@ class Throwable : Object int opApply(scope int delegate(Throwable) dg) { int result = 0; - for (Throwable t = this; t; t = t.nextInChain) + for (Throwable t = this; t; t = t.next) { result = dg(t); if (result) @@ -2657,14 +2688,12 @@ class Throwable : Object return e2; if (!e2) return e1; - if (e2.refcount()) - ++e2.refcount(); - for (auto e = e1; 1; e = e.nextInChain) + for (auto e = e1; 1; e = e.next) { - if (!e.nextInChain) + if (!e.next) { - e.nextInChain = e2; + e.next = e2; break; } } @@ -2674,9 +2703,7 @@ class Throwable : Object @nogc @safe pure nothrow this(string msg, Throwable nextInChain = null) { this.msg = msg; - this.nextInChain = nextInChain; - if (nextInChain && nextInChain._refcount) - ++nextInChain._refcount; + this.next = nextInChain; //this.info = _d_traceContext(); } @@ -2690,8 +2717,9 @@ class Throwable : Object @trusted nothrow ~this() { - if (nextInChain && nextInChain._refcount) - _d_delThrowable(nextInChain); + if (_nextIsRefcounted) + _d_delThrowable(next); + // handle owned traceinfo if (infoDeallocator !is null) { @@ -2820,7 +2848,7 @@ class Exception : Throwable auto e = new Exception("msg"); assert(e.file == __FILE__); assert(e.line == __LINE__ - 2); - assert(e.nextInChain is null); + assert(e._nextInChainPtr is null); assert(e.msg == "msg"); } @@ -2828,7 +2856,7 @@ class Exception : Throwable auto e = new Exception("msg", new Exception("It's an Exception!"), "hello", 42); assert(e.file == "hello"); assert(e.line == 42); - assert(e.nextInChain !is null); + assert(e._nextInChainPtr !is null); assert(e.msg == "msg"); } @@ -2836,7 +2864,7 @@ class Exception : Throwable auto e = new Exception("msg", "hello", 42, new Exception("It's an Exception!")); assert(e.file == "hello"); assert(e.line == 42); - assert(e.nextInChain !is null); + assert(e._nextInChainPtr !is null); assert(e.msg == "msg"); } @@ -2903,7 +2931,7 @@ class Error : Throwable auto e = new Error("msg"); assert(e.file is null); assert(e.line == 0); - assert(e.nextInChain is null); + assert(e._nextInChainPtr is null); assert(e.msg == "msg"); assert(e.bypassedException is null); } @@ -2912,7 +2940,7 @@ class Error : Throwable auto e = new Error("msg", new Exception("It's an Exception!")); assert(e.file is null); assert(e.line == 0); - assert(e.nextInChain !is null); + assert(e._nextInChainPtr !is null); assert(e.msg == "msg"); assert(e.bypassedException is null); } @@ -2921,7 +2949,7 @@ class Error : Throwable auto e = new Error("msg", "hello", 42, new Exception("It's an Exception!")); assert(e.file == "hello"); assert(e.line == 42); - assert(e.nextInChain !is null); + assert(e._nextInChainPtr !is null); assert(e.msg == "msg"); assert(e.bypassedException is null); } @@ -3961,9 +3989,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 @@ -3978,7 +4008,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); } /// @@ -4017,7 +4050,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); + } } /// @@ -4752,6 +4790,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; @@ -4765,7 +4804,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/runtime/druntime/src/rt/lifetime.d b/runtime/druntime/src/rt/lifetime.d index 892a036a724..7c95bf62993 100644 --- a/runtime/druntime/src/rt/lifetime.d +++ b/runtime/druntime/src/rt/lifetime.d @@ -353,119 +353,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. @@ -488,43 +375,19 @@ extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure noth if (length == 0 || size == 0) return null; - version (D_InlineAsm_X86) - { - asm pure nothrow @nogc - { - mov EAX,size ; - mul EAX,length ; - mov size,EAX ; - jnc Lcontinue ; - } - } - else version (D_InlineAsm_X86_64) + bool overflow = false; + size = mulu(size, length, overflow); + if (!overflow) { - asm pure nothrow @nogc + if (auto ptr = GC.malloc(size, __typeAttrs(tinext) | BlkAttr.APPENDABLE, tinext)) { - mov RAX,size ; - mul RAX,length ; - mov size,RAX ; - jnc Lcontinue ; + debug(PRINTF) printf(" p = %p\n", ptr); + return ptr[0 .. length]; } } - else - { - bool overflow = false; - size = mulu(size, length, overflow); - if (!overflow) - goto Lcontinue; - } -Loverflow: + onOutOfMemoryError(); assert(0); -Lcontinue: - - auto ptr = GC.malloc(size, __typeAttrs(tinext) | BlkAttr.APPENDABLE, tinext); - if (!ptr) - goto Loverflow; - debug(PRINTF) printf(" p = %p\n", ptr); - return ptr[0 .. length]; } /// ditto @@ -781,259 +644,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/runtime/druntime/src/rt/minfo.d b/runtime/druntime/src/rt/minfo.d index 6e9cd1c8fe1..6f096744127 100644 --- a/runtime/druntime/src/rt/minfo.d +++ b/runtime/druntime/src/rt/minfo.d @@ -492,7 +492,10 @@ struct ModuleGroup if (!bt(ctordone, idx)) { if (!processMod(idx)) + { + .free(ctors); return false; + } } } diff --git a/runtime/druntime/src/rt/tracegc.d b/runtime/druntime/src/rt/tracegc.d index 61947471ade..0c4cfc7f7da 100644 --- a/runtime/druntime/src/rt/tracegc.d +++ b/runtime/druntime/src/rt/tracegc.d @@ -28,8 +28,6 @@ extern (C) void* _d_assocarrayliteralTX(const TypeInfo_AssociativeArray ti, extern (C) byte[] _d_arrayappendcTX(const TypeInfo ti, return scope ref byte[] px, size_t n); extern (C) void[] _d_arrayappendcd(ref byte[] x, dchar c); extern (C) void[] _d_arrayappendwd(ref byte[] x, dchar c); -extern (C) void[] _d_arraysetlengthT(const TypeInfo ti, size_t newlength, void[]* p); -extern (C) void[] _d_arraysetlengthiT(const TypeInfo ti, size_t newlength, void[]* p); extern (C) void* _d_allocmemory(size_t sz); // From GC.BlkInfo_. We cannot import it from core.memory.GC because .stringof diff --git a/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp b/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp index 0053d15aaa0..c610fbdbd72 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp @@ -14,8 +14,6 @@ bytes allocated, allocations, type, function, file:line 16 1 float profilegc.main src/profilegc.d:17 16 1 int profilegc.main src/profilegc.d:13 16 1 int profilegc.main src/profilegc.d:14 - 16 1 uint[] profilegc.main src/profilegc.d:15 - 16 1 uint[] profilegc.main src/profilegc.d:18 16 1 int[] profilegc.main src/profilegc.d:22 16 1 int[] profilegc.main src/profilegc.d:37 16 1 wchar[] profilegc.main src/profilegc.d:35 diff --git a/runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp b/runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp index 97c1aaa253a..7cc4c6de661 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp @@ -6,8 +6,6 @@ bytes allocated, allocations, type, function, file:line 48 1 float[] profilegc.main src/profilegc.d:42 48 1 int[] profilegc.main src/profilegc.d:41 32 1 C profilegc.main src/profilegc.d:12 - 32 1 ulong[] profilegc.main src/profilegc.d:15 - 32 1 ulong[] profilegc.main src/profilegc.d:18 32 1 void[] profilegc.main src/profilegc.d:55 16 1 char[] profilegc.main src/profilegc.d:34 16 1 char[] profilegc.main src/profilegc.d:36 diff --git a/runtime/druntime/test/profile/myprofilegc.log.linux.32.exp b/runtime/druntime/test/profile/myprofilegc.log.linux.32.exp index 2dc8e5ccf3c..c610fbdbd72 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.linux.32.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.linux.32.exp @@ -16,6 +16,4 @@ bytes allocated, allocations, type, function, file:line 16 1 int profilegc.main src/profilegc.d:14 16 1 int[] profilegc.main src/profilegc.d:22 16 1 int[] profilegc.main src/profilegc.d:37 - 16 1 uint[] profilegc.main src/profilegc.d:15 - 16 1 uint[] profilegc.main src/profilegc.d:18 16 1 wchar[] profilegc.main src/profilegc.d:35 diff --git a/runtime/druntime/test/profile/myprofilegc.log.linux.64.exp b/runtime/druntime/test/profile/myprofilegc.log.linux.64.exp index 97c1aaa253a..7cc4c6de661 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.linux.64.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.linux.64.exp @@ -6,8 +6,6 @@ bytes allocated, allocations, type, function, file:line 48 1 float[] profilegc.main src/profilegc.d:42 48 1 int[] profilegc.main src/profilegc.d:41 32 1 C profilegc.main src/profilegc.d:12 - 32 1 ulong[] profilegc.main src/profilegc.d:15 - 32 1 ulong[] profilegc.main src/profilegc.d:18 32 1 void[] profilegc.main src/profilegc.d:55 16 1 char[] profilegc.main src/profilegc.d:34 16 1 char[] profilegc.main src/profilegc.d:36 diff --git a/runtime/druntime/test/profile/myprofilegc.log.osx.32.exp b/runtime/druntime/test/profile/myprofilegc.log.osx.32.exp index 1cea04ecedb..e5db24779ee 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.osx.32.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.osx.32.exp @@ -14,8 +14,6 @@ bytes allocated, allocations, type, function, file:line 16 1 float profilegc.main src/profilegc.d:17 16 1 int profilegc.main src/profilegc.d:13 16 1 int profilegc.main src/profilegc.d:14 - 16 1 uint[] profilegc.main src/profilegc.d:15 - 16 1 uint[] profilegc.main src/profilegc.d:18 16 1 int[] profilegc.main src/profilegc.d:22 16 1 int[] profilegc.main src/profilegc.d:37 16 1 wchar[] profilegc.main src/profilegc.d:35 diff --git a/runtime/druntime/test/profile/myprofilegc.log.osx.64.exp b/runtime/druntime/test/profile/myprofilegc.log.osx.64.exp index 97c1aaa253a..7cc4c6de661 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.osx.64.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.osx.64.exp @@ -6,8 +6,6 @@ bytes allocated, allocations, type, function, file:line 48 1 float[] profilegc.main src/profilegc.d:42 48 1 int[] profilegc.main src/profilegc.d:41 32 1 C profilegc.main src/profilegc.d:12 - 32 1 ulong[] profilegc.main src/profilegc.d:15 - 32 1 ulong[] profilegc.main src/profilegc.d:18 32 1 void[] profilegc.main src/profilegc.d:55 16 1 char[] profilegc.main src/profilegc.d:34 16 1 char[] profilegc.main src/profilegc.d:36 diff --git a/runtime/druntime/test/profile/myprofilegc.log.windows.32.exp b/runtime/druntime/test/profile/myprofilegc.log.windows.32.exp index cf29c52048f..91cfedb3588 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.windows.32.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.windows.32.exp @@ -16,6 +16,4 @@ bytes allocated, allocations, type, function, file:line 16 1 int profilegc.main src\profilegc.d:14 16 1 int[] profilegc.main src\profilegc.d:22 16 1 int[] profilegc.main src\profilegc.d:37 - 16 1 uint[] profilegc.main src\profilegc.d:15 - 16 1 uint[] profilegc.main src\profilegc.d:18 16 1 wchar[] profilegc.main src\profilegc.d:35 diff --git a/runtime/druntime/test/profile/myprofilegc.log.windows.64.exp b/runtime/druntime/test/profile/myprofilegc.log.windows.64.exp index 631c404941e..80fff943113 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.windows.64.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.windows.64.exp @@ -6,8 +6,6 @@ bytes allocated, allocations, type, function, file:line 48 1 float[] profilegc.main src\profilegc.d:42 48 1 int[] profilegc.main src\profilegc.d:41 32 1 C profilegc.main src\profilegc.d:12 - 32 1 ulong[] profilegc.main src\profilegc.d:15 - 32 1 ulong[] profilegc.main src\profilegc.d:18 32 1 void[] profilegc.main src\profilegc.d:55 16 1 char[] profilegc.main src\profilegc.d:34 16 1 char[] profilegc.main src\profilegc.d:36 diff --git a/runtime/phobos b/runtime/phobos index 983294523d0..380b88d2172 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit 983294523d02c9b48130902c805bce7af085de70 +Subproject commit 380b88d21727073d11da479f55a15038948b0d52 diff --git a/tests/dmd/compilable/alignas.c b/tests/dmd/compilable/alignas.c index 1631ab61e21..623a2f83940 100644 --- a/tests/dmd/compilable/alignas.c +++ b/tests/dmd/compilable/alignas.c @@ -3,10 +3,10 @@ int printf(const char *, ...); _Alignas(4) _Alignas(8) _Alignas(0) int x = 5; -//_Static_assert(_Alignof(x) == 8, "in"); +_Static_assert(_Alignof(x) == 8, "in"); _Alignas(int) short y = 6; -//_Static_assert(_Alignof(y) == 4, "in"); +_Static_assert(_Alignof(y) == 4, "in"); struct S { diff --git a/tests/dmd/compilable/extra-files/header1.d b/tests/dmd/compilable/extra-files/header1.d index ee698f16dcf..abee4c53eef 100644 --- a/tests/dmd/compilable/extra-files/header1.d +++ b/tests/dmd/compilable/extra-files/header1.d @@ -627,3 +627,5 @@ interface I12344 { int i12344(int x) in(x > 0) out(result) {assert(result > 0);}; } + +debug enum issue21406 = 1; diff --git a/tests/dmd/compilable/extra-files/header1.di b/tests/dmd/compilable/extra-files/header1.di index 3e25efb488c..22480f4c7a3 100644 --- a/tests/dmd/compilable/extra-files/header1.di +++ b/tests/dmd/compilable/extra-files/header1.di @@ -564,4 +564,8 @@ interface I12344 assert(result > 0); } ; +} +debug +{ + enum issue21406 = 1; } \ No newline at end of file diff --git a/tests/dmd/compilable/extra-files/header1i.di b/tests/dmd/compilable/extra-files/header1i.di index ee37e60ef36..2b5b09a41c6 100644 --- a/tests/dmd/compilable/extra-files/header1i.di +++ b/tests/dmd/compilable/extra-files/header1i.di @@ -727,4 +727,8 @@ interface I12344 assert(result > 0); } ; +} +debug +{ + enum issue21406 = 1; } \ No newline at end of file diff --git a/tests/dmd/compilable/extra-files/test21331.d b/tests/dmd/compilable/extra-files/test21331.d new file mode 100644 index 00000000000..59f30d1f1c3 --- /dev/null +++ b/tests/dmd/compilable/extra-files/test21331.d @@ -0,0 +1,17 @@ +struct S(alias fun) { + int foo() { + int r = fun(0); + static foreach (i; 0..2) + r += (x => 2)(0); + return r; + } +} + +int bar() { + int r; + static foreach (i; 0..2) + r += S!(x => 1)().foo(); + return r; +} + +// nm test21331.o | grep __lambda_L5_C19 diff --git a/tests/dmd/compilable/extra-files/test21359a.d b/tests/dmd/compilable/extra-files/test21359a.d new file mode 100644 index 00000000000..b52d9db5cda --- /dev/null +++ b/tests/dmd/compilable/extra-files/test21359a.d @@ -0,0 +1,3 @@ +void registerAll() { + import test21359b; +} diff --git a/tests/dmd/compilable/extra-files/test21359b.d b/tests/dmd/compilable/extra-files/test21359b.d new file mode 100644 index 00000000000..f9aca7fdb63 --- /dev/null +++ b/tests/dmd/compilable/extra-files/test21359b.d @@ -0,0 +1,11 @@ +struct SumType(Types...) +{ + static foreach (T; Types) + T values_; +} + +SumType!(string[int]) convertObserver; + +void hackAroundLinkerError() { + auto t = typeid(const(immutable(char)[][])); +} diff --git a/tests/dmd/compilable/extra-files/vcg-ast.d.cg b/tests/dmd/compilable/extra-files/vcg-ast.d.cg index c60768ee542..a28e4571135 100644 --- a/tests/dmd/compilable/extra-files/vcg-ast.d.cg +++ b/tests/dmd/compilable/extra-files/vcg-ast.d.cg @@ -106,6 +106,8 @@ template imported() import imported = imports.vcg_ast_import; } alias myImport = vcg_ast_import; +enum bool compiles = true; +enum bool isexp = true; R!int { struct _R diff --git a/tests/dmd/compilable/imports/cstuff3.c b/tests/dmd/compilable/imports/cstuff3.c index f6aaf3b2a4a..fb78ec76bca 100644 --- a/tests/dmd/compilable/imports/cstuff3.c +++ b/tests/dmd/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/tests/dmd/compilable/imports/imp18127a.c b/tests/dmd/compilable/imports/imp18127a.c new file mode 100644 index 00000000000..cd173151dbf --- /dev/null +++ b/tests/dmd/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/tests/dmd/compilable/imports/imp18127b.c b/tests/dmd/compilable/imports/imp18127b.c new file mode 100644 index 00000000000..cd173151dbf --- /dev/null +++ b/tests/dmd/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/tests/dmd/compilable/imports/imp20344.c b/tests/dmd/compilable/imports/imp20344.c new file mode 100644 index 00000000000..56ac79c930c --- /dev/null +++ b/tests/dmd/compilable/imports/imp20344.c @@ -0,0 +1,2 @@ +// https://github.com/dlang/dmd/issues/20334 +#define X "X" diff --git a/tests/dmd/compilable/imports/imp20499.c b/tests/dmd/compilable/imports/imp20499.c new file mode 100644 index 00000000000..7ae74906f73 --- /dev/null +++ b/tests/dmd/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/tests/dmd/compilable/nested_struct_20499.c b/tests/dmd/compilable/nested_struct_20499.c new file mode 100644 index 00000000000..ec83abde172 --- /dev/null +++ b/tests/dmd/compilable/nested_struct_20499.c @@ -0,0 +1,61 @@ +// https://github.com/dlang/dmd/issues/20499 + + +struct Outer { + struct __attribute__((aligned(8))) { + int x; + } n; + enum {A}; + enum {B} b; +}; + +struct Outer2 { + struct __attribute__((aligned(8))) Nested { + int x; + } n; +}; + +const int x = A; +const int y = B; + +struct Outer o = {3}; +_Static_assert(_Alignof(typeof(o.n)) == 8, ""); +_Static_assert(_Alignof(struct Outer) == 8, ""); +_Static_assert(_Alignof(struct Outer2) == 8, ""); +_Static_assert(_Alignof(struct Nested) == 8, ""); + +void test(void){ + struct Outer { + struct __attribute__((aligned(16))) { + int x; + } n; + enum {A=2}; + enum {B=3} b; + }; + + struct Outer2 { + struct __attribute__((aligned(16))) Nested { + int x; + } n; + }; + + const int x = A; + const int y = B; + + struct Outer o = {3}; + _Static_assert(_Alignof(typeof(o.n)) == 16, ""); + _Static_assert(_Alignof(struct Outer) == 16, ""); + _Static_assert(_Alignof(struct Outer2) == 16, ""); + _Static_assert(_Alignof(struct Nested) == 16, ""); +} + +void test2(void){ + const int x = A; + const int y = B; + + struct Outer o = {3}; + _Static_assert(_Alignof(typeof(o.n)) == 8, ""); + _Static_assert(_Alignof(struct Outer) == 8, ""); + _Static_assert(_Alignof(struct Outer2) == 8, ""); + _Static_assert(_Alignof(struct Nested) == 8, ""); +} diff --git a/tests/dmd/compilable/struct_decls_20499.c b/tests/dmd/compilable/struct_decls_20499.c new file mode 100644 index 00000000000..27f342db4dd --- /dev/null +++ b/tests/dmd/compilable/struct_decls_20499.c @@ -0,0 +1,287 @@ +// https://github.com/dlang/dmd/issues/20499 + +// +// attribute((aligned())) is so we can tell if attributes are being applied. +// +typedef struct __attribute__((aligned(8))) S { + int x, y; +} S; +_Static_assert(sizeof(struct S) == 8, "sizeof(S)"); +_Static_assert(_Alignof(struct S) == 8, "_Alignof(S)"); + +typedef struct __attribute__((aligned(8))) Foo { + int x, y; +} *pFoo, Foo, FooB; + +_Static_assert(sizeof(struct Foo) == sizeof(struct S), "sizeof(Foo)"); +_Static_assert(_Alignof(struct Foo) == _Alignof(struct S), "_Alignof(Foo)"); +_Static_assert(sizeof(Foo) == sizeof(struct S), "sizeof(Foo)"); +_Static_assert(_Alignof(Foo) == _Alignof(struct S), "_Alignof(Foo)"); +_Static_assert(sizeof(FooB) == sizeof(struct S), "sizeof(FooB)"); +_Static_assert(_Alignof(FooB) == _Alignof(struct S), "_Alignof(FooB)"); + +pFoo pf; +_Static_assert(sizeof(*pf) == sizeof(struct S), "sizeof(*pf)"); +_Static_assert(_Alignof(typeof(*pf)) == _Alignof(struct S), "_Alignof(*pf)"); + +typedef struct __attribute__((aligned(8))) { + int x, y; +} Baz, *pBaz, BazB; +_Static_assert(sizeof(Baz) == sizeof(struct S), "sizeof(Baz)"); +_Static_assert(sizeof(BazB) == sizeof(struct S), "sizeof(BazB)"); +_Static_assert(_Alignof(Baz) == _Alignof(struct S), "_Alignof(Baz)"); +_Static_assert(_Alignof(BazB) == _Alignof(struct S), "_Alignof(BazB)"); + +pBaz pb; +_Static_assert(sizeof(*pb) == sizeof(struct S), "sizeof(*pb)"); +_Static_assert(_Alignof(typeof(*pb)) == _Alignof(struct S), "_Alignof(*pb)"); + +typedef struct __attribute__((aligned(8))) { + int x, y; +} *pTux; +pTux pt; +_Static_assert(sizeof(*pt) == sizeof(struct S), "sizeof(*pt)"); +_Static_assert(_Alignof(typeof(*pt)) == _Alignof(struct S), "_Alignof(*pt)"); + +typedef struct __attribute__((aligned(8))) { + int x, y; +} Qux; +_Static_assert(sizeof(Qux) == sizeof(struct S), "sizeof(FooB)"); +_Static_assert(_Alignof(Qux) == _Alignof(struct S), "_Alignof(FooB)"); + +struct Bar { + struct S foo; +}; +_Static_assert(sizeof(struct Bar) == sizeof(struct S), "sizeof(Bar)"); +_Static_assert(_Alignof(struct Bar) == _Alignof(struct S), "_Alignof(Bar)"); + +typedef struct __attribute__((aligned(8))) { + int x, y; +} *pLux; +pLux pl; +_Static_assert(sizeof(*pl) == sizeof(struct S), "sizeof(*pl)"); +_Static_assert(_Alignof(typeof(*pl)) == _Alignof(struct S), "_Alignof(*pl)"); + + +typedef struct __attribute__((aligned(8))) { + int x, y; +} ****pWux; +pWux pw; +_Static_assert(sizeof(****pw) == sizeof(struct S), "sizeof(****pw)"); +_Static_assert(_Alignof(typeof(****pw)) == _Alignof(struct S), "_Alignof(****pw)"); + +struct __attribute__((aligned(8))) { + int x, y; +} f; +_Static_assert(sizeof(f) == sizeof(struct S), "sizeof(f)"); +_Static_assert(_Alignof(typeof(f)) == _Alignof(struct S), "_Alignof(f)"); + +struct __attribute__((aligned(8))) { + int x, y; +} fa[3]; +_Static_assert(sizeof(fa[0]) == sizeof(struct S), "sizeof(fa[0])"); +_Static_assert(_Alignof(typeof(fa[0])) == _Alignof(struct S), "_Alignof(fa[0])"); + +void locals(void){ + // function local version + // Use different values so we know we aren't just using globals + typedef struct __attribute__((aligned(16))) S { + int x, y[7]; + } S; + _Static_assert(sizeof(struct S) == 32, "sizeof(S)"); + _Static_assert(_Alignof(struct S) == 16, "_Alignof(S)"); + + typedef struct __attribute__((aligned(16))) Foo { + int x, y[7]; + } *pFoo, Foo, FooB; + + _Static_assert(sizeof(struct Foo) == sizeof(struct S), "sizeof(Foo)"); + _Static_assert(_Alignof(struct Foo) == _Alignof(struct S), "_Alignof(Foo)"); + _Static_assert(sizeof(Foo) == sizeof(struct S), "sizeof(Foo)"); + _Static_assert(_Alignof(Foo) == _Alignof(struct S), "_Alignof(Foo)"); + _Static_assert(sizeof(FooB) == sizeof(struct S), "sizeof(FooB)"); + _Static_assert(_Alignof(FooB) == _Alignof(struct S), "_Alignof(FooB)"); + + pFoo pf; + _Static_assert(sizeof(*pf) == sizeof(struct S), "sizeof(*pf)"); + _Static_assert(_Alignof(typeof(*pf)) == _Alignof(struct S), "_Alignof(*pf)"); + + typedef struct __attribute__((aligned(16))) { + int x, y[7]; + } Baz, *pBaz, BazB; + _Static_assert(sizeof(Baz) == sizeof(struct S), "sizeof(Baz)"); + _Static_assert(sizeof(BazB) == sizeof(struct S), "sizeof(BazB)"); + _Static_assert(_Alignof(Baz) == _Alignof(struct S), "_Alignof(Baz)"); + _Static_assert(_Alignof(BazB) == _Alignof(struct S), "_Alignof(BazB)"); + + + pBaz pb; + _Static_assert(sizeof(*pb) == sizeof(struct S), "sizeof(*pb)"); + _Static_assert(_Alignof(typeof(*pb)) == _Alignof(struct S), "_Alignof(*pb)"); + + + typedef struct __attribute__((aligned(16))) { + int x, y[7]; + } *pTux; + pTux pt; + _Static_assert(sizeof(*pt) == sizeof(struct S), "sizeof(*pt)"); + _Static_assert(_Alignof(typeof(*pt)) == _Alignof(struct S), "_Alignof(*pt)"); + + + typedef struct __attribute__((aligned(16))) { + int x, y[7]; + } Qux; + _Static_assert(sizeof(Qux) == sizeof(struct S), "sizeof(FooB)"); + _Static_assert(_Alignof(Qux) == _Alignof(struct S), "_Alignof(FooB)"); + + struct Bar { + struct S foo; + }; + _Static_assert(sizeof(struct Bar) == sizeof(struct S), "sizeof(Bar)"); + _Static_assert(_Alignof(struct Bar) == _Alignof(struct S), "_Alignof(Bar)"); + + typedef struct __attribute__((aligned(16))) { + int x, y[7]; + } *pLux; + pLux pl; + _Static_assert(sizeof(*pl) == sizeof(struct S), "sizeof(*pl)"); + _Static_assert(_Alignof(typeof(*pl)) == _Alignof(struct S), "_Alignof(*pl)"); + + + typedef struct __attribute__((aligned(16))) { + int x, y[7]; + } ****pWux; + pWux pw; + _Static_assert(sizeof(****pw) == sizeof(struct S), "sizeof(****pw)"); + _Static_assert(_Alignof(typeof(****pw)) == _Alignof(struct S), "_Alignof(****pw)"); + + struct __attribute__((aligned(16))) { + int x, y[7]; + } f; + _Static_assert(sizeof(f) == sizeof(struct S), "sizeof(f)"); + _Static_assert(_Alignof(typeof(f)) == _Alignof(struct S), "_Alignof(f)"); + // Verify shadowing works + { + typedef struct __attribute__((aligned(32))) S { + int x, y[15]; + } S; + _Static_assert(sizeof(struct S) == 64, "sizeof(S)"); + _Static_assert(_Alignof(struct S) == 32, "_Alignof(S)"); + + typedef struct __attribute__((aligned(32))) Foo { + int x, y[15]; + } *pFoo, Foo, FooB; + + _Static_assert(sizeof(struct Foo) == sizeof(struct S), "sizeof(Foo)"); + _Static_assert(_Alignof(struct Foo) == _Alignof(struct S), "_Alignof(Foo)"); + _Static_assert(sizeof(Foo) == sizeof(struct S), "sizeof(Foo)"); + _Static_assert(_Alignof(Foo) == _Alignof(struct S), "_Alignof(Foo)"); + _Static_assert(sizeof(FooB) == sizeof(struct S), "sizeof(FooB)"); + _Static_assert(_Alignof(FooB) == _Alignof(struct S), "_Alignof(FooB)"); + + pFoo pf; + _Static_assert(sizeof(*pf) == sizeof(struct S), "sizeof(*pf)"); + _Static_assert(_Alignof(typeof(*pf)) == _Alignof(struct S), "_Alignof(*pf)"); + + typedef struct __attribute__((aligned(32))) { + int x, y[15]; + } Baz, *pBaz, BazB; + _Static_assert(sizeof(Baz) == sizeof(struct S), "sizeof(Baz)"); + _Static_assert(sizeof(BazB) == sizeof(struct S), "sizeof(BazB)"); + _Static_assert(_Alignof(Baz) == _Alignof(struct S), "_Alignof(Baz)"); + _Static_assert(_Alignof(BazB) == _Alignof(struct S), "_Alignof(BazB)"); + + + pBaz pb; + _Static_assert(sizeof(*pb) == sizeof(struct S), "sizeof(*pb)"); + _Static_assert(_Alignof(typeof(*pb)) == _Alignof(struct S), "_Alignof(*pb)"); + + + typedef struct __attribute__((aligned(32))) { + int x, y[15]; + } *pTux; + pTux pt; + _Static_assert(sizeof(*pt) == sizeof(struct S), "sizeof(*pt)"); + _Static_assert(_Alignof(typeof(*pt)) == _Alignof(struct S), "_Alignof(*pt)"); + + + typedef struct __attribute__((aligned(32))) { + int x, y[15]; + } Qux; + _Static_assert(sizeof(Qux) == sizeof(struct S), "sizeof(FooB)"); + _Static_assert(_Alignof(Qux) == _Alignof(struct S), "_Alignof(FooB)"); + + struct Bar { + struct S foo; + }; + _Static_assert(sizeof(struct Bar) == sizeof(struct S), "sizeof(Bar)"); + _Static_assert(_Alignof(struct Bar) == _Alignof(struct S), "_Alignof(Bar)"); + + typedef struct __attribute__((aligned(32))) { + int x, y[15]; + } *pLux; + pLux pl; + _Static_assert(sizeof(*pl) == sizeof(struct S), "sizeof(*pl)"); + _Static_assert(_Alignof(typeof(*pl)) == _Alignof(struct S), "_Alignof(*pl)"); + + + typedef struct __attribute__((aligned(32))) { + int x, y[15]; + } ****pWux; + pWux pw; + _Static_assert(sizeof(****pw) == sizeof(struct S), "sizeof(****pw)"); + _Static_assert(_Alignof(typeof(****pw)) == _Alignof(struct S), "_Alignof(****pw)"); + + struct __attribute__((aligned(32))) { + int x, y[15]; + } f; + _Static_assert(sizeof(f) == sizeof(struct S), "sizeof(f)"); + _Static_assert(_Alignof(typeof(f)) == _Alignof(struct S), "_Alignof(f)"); + } +} + +void globals(void){ + _Static_assert(sizeof(struct S) == 8, "sizeof(S)"); + _Static_assert(_Alignof(struct S) == 8, "_Alignof(S)"); + + _Static_assert(sizeof(struct Foo) == sizeof(struct S), "sizeof(Foo)"); + _Static_assert(_Alignof(struct Foo) == _Alignof(struct S), "_Alignof(Foo)"); + _Static_assert(sizeof(Foo) == sizeof(struct S), "sizeof(Foo)"); + _Static_assert(_Alignof(Foo) == _Alignof(struct S), "_Alignof(Foo)"); + _Static_assert(sizeof(FooB) == sizeof(struct S), "sizeof(FooB)"); + _Static_assert(_Alignof(FooB) == _Alignof(struct S), "_Alignof(FooB)"); + + pFoo pf; + _Static_assert(sizeof(*pf) == sizeof(struct S), "sizeof(*pf)"); + _Static_assert(_Alignof(typeof(*pf)) == _Alignof(struct S), "_Alignof(*pf)"); + + _Static_assert(sizeof(Baz) == sizeof(struct S), "sizeof(Baz)"); + _Static_assert(sizeof(BazB) == sizeof(struct S), "sizeof(BazB)"); + _Static_assert(_Alignof(Baz) == _Alignof(struct S), "_Alignof(Baz)"); + _Static_assert(_Alignof(BazB) == _Alignof(struct S), "_Alignof(BazB)"); + + pBaz pb; + _Static_assert(sizeof(*pb) == sizeof(struct S), "sizeof(*pb)"); + _Static_assert(_Alignof(typeof(*pb)) == _Alignof(struct S), "_Alignof(*pb)"); + + pTux pt; + _Static_assert(sizeof(*pt) == sizeof(struct S), "sizeof(*pt)"); + _Static_assert(_Alignof(typeof(*pt)) == _Alignof(struct S), "_Alignof(*pt)"); + + _Static_assert(sizeof(Qux) == sizeof(struct S), "sizeof(FooB)"); + _Static_assert(_Alignof(Qux) == _Alignof(struct S), "_Alignof(FooB)"); + + _Static_assert(sizeof(struct Bar) == sizeof(struct S), "sizeof(Bar)"); + _Static_assert(_Alignof(struct Bar) == _Alignof(struct S), "_Alignof(Bar)"); + + pLux pl; + _Static_assert(sizeof(*pl) == sizeof(struct S), "sizeof(*pl)"); + _Static_assert(_Alignof(typeof(*pl)) == _Alignof(struct S), "_Alignof(*pl)"); + + + pWux pw; + _Static_assert(sizeof(****pw) == sizeof(struct S), "sizeof(****pw)"); + _Static_assert(_Alignof(typeof(****pw)) == _Alignof(struct S), "_Alignof(****pw)"); + Foo foo = {1, 2, 3}; + struct Foo foo2 = {1, 2, 3}; +} diff --git a/tests/dmd/compilable/test18127.d b/tests/dmd/compilable/test18127.d new file mode 100644 index 00000000000..35e6bdc5b17 --- /dev/null +++ b/tests/dmd/compilable/test18127.d @@ -0,0 +1,4 @@ +// https://github.com/dlang/dmd/issues/18127 + +import imports.imp18127a; +import imports.imp18127b; diff --git a/tests/dmd/compilable/test20344.d b/tests/dmd/compilable/test20344.d new file mode 100644 index 00000000000..26ee9a3269e --- /dev/null +++ b/tests/dmd/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/tests/dmd/compilable/test20423.c b/tests/dmd/compilable/test20423.c new file mode 100644 index 00000000000..6311c2a5f1f --- /dev/null +++ b/tests/dmd/compilable/test20423.c @@ -0,0 +1,18 @@ +// https://github.com/dlang/dmd/issues/20423 +#include +#include +#include + +void foo(double * pm, ...) { + va_list ap; + double * targ; + va_start(ap, pm); + for (int i=1; ; i++) { + va_arg(ap, int); + targ = va_arg(ap, double*); + if (targ == NULL) { + break; + } + } + va_end(ap); +} diff --git a/tests/dmd/compilable/test20472.c b/tests/dmd/compilable/test20472.c new file mode 100644 index 00000000000..aae7e073807 --- /dev/null +++ b/tests/dmd/compilable/test20472.c @@ -0,0 +1,12 @@ +// https://github.com/dlang/dmd/issues/20472 +typedef struct { + char c; +} stuff; + +char test20472(void) +{ + stuff s[1]; + s->c = 1; + return s->c; +} +_Static_assert(test20472() == 1, "1"); diff --git a/tests/dmd/compilable/test20499.d b/tests/dmd/compilable/test20499.d new file mode 100644 index 00000000000..9e9e1d27128 --- /dev/null +++ b/tests/dmd/compilable/test20499.d @@ -0,0 +1,2 @@ +// https://github.com/dlang/dmd/issues/20499 +import imports.imp20499; diff --git a/tests/dmd/compilable/test20502.c b/tests/dmd/compilable/test20502.c new file mode 100644 index 00000000000..c3a44fb4cc2 --- /dev/null +++ b/tests/dmd/compilable/test20502.c @@ -0,0 +1,10 @@ +// https://github.com/dlang/dmd/issues/20502 +struct mg_str { + +}; + +void mg_str_s() { + +} + +#define mg_str(s) mg_str_s(s) diff --git a/tests/dmd/compilable/test20963.c b/tests/dmd/compilable/test20963.c new file mode 100644 index 00000000000..a5aead13d25 --- /dev/null +++ b/tests/dmd/compilable/test20963.c @@ -0,0 +1,12 @@ +// https://github.com/dlang/dmd/issues/20963 + +void cdind() { + struct ABC { + int y; + } *p; + + { + struct ABC { int x; } abc; + abc.x = 1; + } +} diff --git a/tests/dmd/compilable/test21150.c b/tests/dmd/compilable/test21150.c new file mode 100644 index 00000000000..c536d363e56 --- /dev/null +++ b/tests/dmd/compilable/test21150.c @@ -0,0 +1,77 @@ +// https://github.com/dlang/dmd/issues/21150 + +struct S +{ + char z[16][256]; +} __attribute__((aligned(_Alignof(unsigned int)))); +_Static_assert(_Alignof(struct S) == _Alignof(unsigned int), "S"); + +struct T { + _Static_assert(1, ""); + char x; +} __attribute__((aligned(_Alignof(struct S)))); + +_Static_assert(_Alignof(struct T) == _Alignof(unsigned int), "T"); + + +struct __attribute__ ((aligned(8))) Q { + short f[3]; +}; +_Static_assert(sizeof(struct Q) == 8, "Q1"); +_Static_assert(_Alignof(struct Q) == 8, "Q2"); + + +struct __attribute__ ((aligned(8))) R { + short f[3]; + char c; +}; +_Static_assert(sizeof(struct R) == 8, "R1"); +_Static_assert(_Alignof(struct R) == 8, "R2"); + +struct C { + unsigned _Alignas(2) _Alignas(4) char c; +} +__attribute__((aligned(8))); + +_Static_assert(_Alignof(struct C)==8, "C"); + +struct __attribute__((aligned(4))) D { + unsigned char c; +} +__attribute__((aligned(8))); + +_Static_assert(_Alignof(struct D)==8, "D"); +// +// Interaction of aligned() and packed +// +#include + struct Spacked { + unsigned a; + unsigned long long b; + } __attribute__((aligned(4), packed)); +_Static_assert(_Alignof(struct Spacked) == 4, "Spacked"); +_Static_assert(_Alignof(struct Spacked) == 4, "Spacked"); +_Static_assert(offsetof(struct Spacked, a) == 0, "Spacked.a"); +_Static_assert(offsetof(struct Spacked, b) == sizeof(unsigned), "Spacked.b"); +_Static_assert(sizeof(struct Spacked) == sizeof(unsigned) + sizeof(unsigned long long), "sizeof(Spacked)"); + +struct __attribute__((aligned(4))) Spacked2 { + unsigned a; + unsigned long long b; +} __attribute__((packed)); +_Static_assert(_Alignof(struct Spacked2) == 4, "Spacked2"); +_Static_assert(offsetof(struct Spacked2, a) == 0, "Spacked2.a"); +_Static_assert(offsetof(struct Spacked2, b) == sizeof(unsigned), "Spacked2.b"); +_Static_assert(sizeof(struct Spacked2) == sizeof(unsigned) + sizeof(unsigned long long), "sizeof(Spacked2)"); + +#pragma pack(push) +#pragma pack(1) +struct __attribute__((aligned(4))) Spacked3 { + unsigned a; + unsigned long long b; +}; +#pragma pack(pop) +_Static_assert(_Alignof(struct Spacked3) == 4, "Spacked3"); +_Static_assert(offsetof(struct Spacked3, a) == 0, "Spacked3.a"); +_Static_assert(offsetof(struct Spacked3, b) == sizeof(unsigned), "Spacked3.b"); +_Static_assert(sizeof(struct Spacked3) == sizeof(unsigned) + sizeof(unsigned long long), "sizeof(Spacked3)"); diff --git a/tests/dmd/compilable/test21225.c b/tests/dmd/compilable/test21225.c new file mode 100644 index 00000000000..45eb5cd92f3 --- /dev/null +++ b/tests/dmd/compilable/test21225.c @@ -0,0 +1,7 @@ +// https://github.com/dlang/dmd/issues/21225 +void x(void){ +} +#define x 3 + +typedef struct Foo {int y; } foo; +#define foo 3 diff --git a/tests/dmd/compilable/test21267.c b/tests/dmd/compilable/test21267.c new file mode 100644 index 00000000000..6bc355f2321 --- /dev/null +++ b/tests/dmd/compilable/test21267.c @@ -0,0 +1,4 @@ +// https://github.com/dlang/dmd/issues/21267 +static inline __forceinline int square(int x) { return x * x; } + +int doSquare(int x) { return square(x); } diff --git a/tests/dmd/compilable/test21271.c b/tests/dmd/compilable/test21271.c new file mode 100644 index 00000000000..732fa8b75d4 --- /dev/null +++ b/tests/dmd/compilable/test21271.c @@ -0,0 +1,16 @@ +// https://github.com/dlang/dmd/issues/21271 +#define PUSH __pragma(pack(push)) +#define PACK __pragma(pack(1)) +#define POP __pragma(pack(pop)) + +PUSH +PACK +struct S21271_1 { + int x; +}; +_Static_assert(_Alignof(struct S21271_1)==1, "1"); +POP +struct S21271_2 { + int x; +}; +_Static_assert(_Alignof(struct S21271_2)==_Alignof(int), "2"); diff --git a/tests/dmd/compilable/test21331.sh b/tests/dmd/compilable/test21331.sh new file mode 100755 index 00000000000..855e563134f --- /dev/null +++ b/tests/dmd/compilable/test21331.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +objfile="${OUTPUT_BASE}${OBJ}" +$DMD -c -m${MODEL} -of${objfile} ${EXTRA_FILES}/${TEST_NAME}.d + +nm ${objfile} | grep -E '16__lambda_L13_C17.+15__lambda_L5_C19' +nm ${objfile} | grep -E '16__lambda_L13_C17.+17__lambda_L5_C19_1' +nm ${objfile} | grep -E '18__lambda_L13_C17_1.+15__lambda_L5_C19' +nm ${objfile} | grep -E '18__lambda_L13_C17_1.+17__lambda_L5_C19_1' + +rm_retry ${objfile} diff --git a/tests/dmd/compilable/test21359.sh b/tests/dmd/compilable/test21359.sh new file mode 100755 index 00000000000..fd309dfa537 --- /dev/null +++ b/tests/dmd/compilable/test21359.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +objfile="${OUTPUT_BASE}${OBJ}" +$DMD -c -m${MODEL} -allinst -of${objfile} ${EXTRA_FILES}/${TEST_NAME}a.d -I${EXTRA_FILES} + +# This test is brittle and might break in the future. +# For now, ensure a specific AA TypeInfo isn't defined multiple times, as happened with DMD v2.111.0. + +# LDC: different TypeInfo emission strategy, test doesn't apply +exit 0 + +mangled_sym='_D14TypeInfo_HiAya6__initZ' +num_typeinfo_syms=$(nm --defined-only ${objfile} | grep -F ${mangled_sym} | wc -l) +if [[ "${num_typeinfo_syms}" -ne 1 ]]; then + echo "Expected 1 '${mangled_sym}' symbol definition but got: ${num_typeinfo_syms}" + exit 1 +fi + +rm_retry ${objfile} diff --git a/tests/dmd/compilable/test21416.d b/tests/dmd/compilable/test21416.d new file mode 100644 index 00000000000..e24f7292945 --- /dev/null +++ b/tests/dmd/compilable/test21416.d @@ -0,0 +1,17 @@ +// https://github.com/dlang/dmd/issues/21416 + +struct S +{ + @disable this(ref S); +} + +ref id(ref S s) => s; + +S* p; +void foo(S s) { } + +void main() +{ + S s; + foo(__rvalue(id(s))); +} diff --git a/tests/dmd/compilable/test21476.d b/tests/dmd/compilable/test21476.d new file mode 100644 index 00000000000..a2e307eebdd --- /dev/null +++ b/tests/dmd/compilable/test21476.d @@ -0,0 +1,13 @@ +// https://github.com/dlang/dmd/issues/21476 + +struct S21476 +{ + string field; + this(ref return scope S21476); + this(return scope S21476); +} + +void test21476() +{ + auto o = S21476("aoe"); +} diff --git a/tests/dmd/compilable/test3004.d b/tests/dmd/compilable/test3004.d index cbab9c72d3c..49bcf53a8e1 100644 --- a/tests/dmd/compilable/test3004.d +++ b/tests/dmd/compilable/test3004.d @@ -2,7 +2,7 @@ /* REQUIRED_ARGS: -ignore -v LDC: additionally exclude 'GC stats' line -TRANSFORM_OUTPUT: remove_lines("^(predefs|binary|version|config|DFLAG|parse|import|semantic|entry|library|function object|function core|GC stats|\s*$)") +TRANSFORM_OUTPUT: remove_lines("^(predefs|binary|version|config|DFLAG|parse|import|\(imported|semantic|entry|library|function object|function core|GC stats|\s*$)") TEST_OUTPUT: --- pragma GNU_attribute (__error) diff --git a/tests/dmd/compilable/testcstuff1.c b/tests/dmd/compilable/testcstuff1.c index a05c986fbb6..551e102f3f9 100644 --- a/tests/dmd/compilable/testcstuff1.c +++ b/tests/dmd/compilable/testcstuff1.c @@ -333,6 +333,7 @@ void test4(int i) _Static_assert(sizeof 3 == 4, "ok"); _Static_assert(sizeof(3) == 4, "ok"); _Static_assert(_Alignof(int) == 4, "ok"); + _Static_assert(_Alignof 3 == 4, "ok"); _Static_assert((int)3 == 3, "ok"); _Static_assert(sizeof p[0] == 4, "ok"); _Static_assert(1 && 2, "ok"); @@ -402,8 +403,9 @@ void* tests3() int tests4() { - struct S { int b; } a, *p; - a.b = 3; + struct S { int b; } a, *p, b[1]; + b->b = 3; + a.b = b->b; p = &a; return p->b; } diff --git a/tests/dmd/compilable/testcstuff3.d b/tests/dmd/compilable/testcstuff3.d index 89228a9bc4a..08aa3b03d11 100644 --- a/tests/dmd/compilable/testcstuff3.d +++ b/tests/dmd/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/tests/dmd/compilable/uda_lambda.d b/tests/dmd/compilable/uda_lambda.d new file mode 100644 index 00000000000..df331747a7f --- /dev/null +++ b/tests/dmd/compilable/uda_lambda.d @@ -0,0 +1,3 @@ +enum UDA; +int fun() @UDA => 7; +static assert(fun() == 7); diff --git a/tests/dmd/compilable/vcg-ast.d b/tests/dmd/compilable/vcg-ast.d index 50f78cb72be..81b1a2d4958 100644 --- a/tests/dmd/compilable/vcg-ast.d +++ b/tests/dmd/compilable/vcg-ast.d @@ -76,3 +76,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/tests/dmd/fail_compilation/alignedext.i b/tests/dmd/fail_compilation/alignedext.i index eae3137ce47..55c8477e0b7 100644 --- a/tests/dmd/fail_compilation/alignedext.i +++ b/tests/dmd/fail_compilation/alignedext.i @@ -2,13 +2,10 @@ --- fail_compilation/alignedext.i(10): Error: __decspec(align(123)) must be an integer positive power of 2 and be <= 8,192 fail_compilation/alignedext.i(11): Error: __decspec(align(16384)) must be an integer positive power of 2 and be <= 8,192 -fail_compilation/alignedext.i(13): Error: __attribute__((aligned(123))) must be an integer positive power of 2 and be <= 32,768 -fail_compilation/alignedext.i(14): Error: __attribute__((aligned(65536))) must be an integer positive power of 2 and be <= 32,768 + + --- */ typedef struct __declspec(align(123)) S { int a; } S; struct __declspec(align(16384)) T { int a; }; - -typedef struct __attribute__((aligned(123))) U { int a; } S; -struct __attribute__((aligned(65536))) V { int a; }; diff --git a/tests/dmd/fail_compilation/alignedext2.i b/tests/dmd/fail_compilation/alignedext2.i new file mode 100644 index 00000000000..a0950ca9fec --- /dev/null +++ b/tests/dmd/fail_compilation/alignedext2.i @@ -0,0 +1,9 @@ +/* TEST_OUTPUT: +--- +fail_compilation/alignedext2.i(8): Error: alignment must be an integer positive power of 2, not 0x7b +fail_compilation/alignedext2.i(9): Error: alignment must be an integer positive power of 2, not 0x10000 +--- +*/ + +typedef struct __attribute__((aligned(123))) U { int a; } S; +struct __attribute__((aligned(65536))) V { int a; }; diff --git a/tests/dmd/fail_compilation/b23686.d b/tests/dmd/fail_compilation/b23686.d index 4c2a5bd026d..5838f5c8e10 100644 --- a/tests/dmd/fail_compilation/b23686.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/checkimports2.d b/tests/dmd/fail_compilation/checkimports2.d index 44c237f144f..56e28e1ce7b 100644 --- a/tests/dmd/fail_compilation/checkimports2.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/diag10405.d b/tests/dmd/fail_compilation/diag10405.d deleted file mode 100644 index 28da8af93ad..00000000000 --- a/tests/dmd/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/tests/dmd/fail_compilation/diag20888.d b/tests/dmd/fail_compilation/diag20888.d index 84af42533fc..d030a98ec2c 100644 --- a/tests/dmd/fail_compilation/diag20888.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/diag23384.d b/tests/dmd/fail_compilation/diag23384.d index 1fa4da5ffb9..9cb17c00d74 100644 --- a/tests/dmd/fail_compilation/diag23384.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/diag9679.d b/tests/dmd/fail_compilation/diag9679.d index 22e94e57596..50b8717adf3 100644 --- a/tests/dmd/fail_compilation/diag9679.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/diag_ptr_conversion.d b/tests/dmd/fail_compilation/diag_ptr_conversion.d new file mode 100644 index 00000000000..ea144b2c9db --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/enum_auto_increment.d b/tests/dmd/fail_compilation/enum_auto_increment.d new file mode 100644 index 00000000000..9c04e9a324f --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/fail109.d b/tests/dmd/fail_compilation/fail109.d index 003e65f9b80..94f951f9f95 100644 --- a/tests/dmd/fail_compilation/fail109.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/fail11714.d b/tests/dmd/fail_compilation/fail11714.d index abc47087ffa..f36f3e5831e 100644 --- a/tests/dmd/fail_compilation/fail11714.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/fail15361.d b/tests/dmd/fail_compilation/fail15361.d index 8e5f9800a81..aec716556a4 100644 --- a/tests/dmd/fail_compilation/fail15361.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/fail15616b.d b/tests/dmd/fail_compilation/fail15616b.d index 4b209685ca4..4cbd591cbf8 100644 --- a/tests/dmd/fail_compilation/fail15616b.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/fail16.d b/tests/dmd/fail_compilation/fail16.d index 4602d3de3bd..ce021a95b85 100644 --- a/tests/dmd/fail_compilation/fail16.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/fail163.d b/tests/dmd/fail_compilation/fail163.d index 7f8f028fa52..590bf23931c 100644 --- a/tests/dmd/fail_compilation/fail163.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/fail18219.d b/tests/dmd/fail_compilation/fail18219.d index bf4b189f6eb..f5fc27f1a89 100644 --- a/tests/dmd/fail_compilation/fail18219.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/fail19103.d b/tests/dmd/fail_compilation/fail19103.d index c1abd0df90a..7780fe691e4 100644 --- a/tests/dmd/fail_compilation/fail19103.d +++ b/tests/dmd/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:/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/tests/dmd/fail_compilation/fail196.d b/tests/dmd/fail_compilation/fail196.d index 78c596390b5..a5d4499f3ff 100644 --- a/tests/dmd/fail_compilation/fail196.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/fail21414.d b/tests/dmd/fail_compilation/fail21414.d new file mode 100644 index 00000000000..d07b2e2cbd3 --- /dev/null +++ b/tests/dmd/fail_compilation/fail21414.d @@ -0,0 +1,47 @@ +// https://github.com/dlang/dmd/issues/21414 + +/* REQUIRED_ARGS: -o- +TEST_OUTPUT: +--- +fail_compilation/fail21414.d(42): Error: moving variable `__rvalue(s)` with `__rvalue` is not allowed in a `@safe` function +fail_compilation/fail21414.d(42): Error: moving variable `__rvalue(s)` with `__rvalue` is not allowed in a `@safe` function +fail_compilation/fail21414.d(44): Error: calling `__rvalue`-annotated function `unsafeMove` is not allowed in a `@safe` function +fail_compilation/fail21414.d(44): Error: calling `__rvalue`-annotated function `unsafeMove` is not allowed in a `@safe` function +fail_compilation/fail21414.d(46): Error: moving result of `ref` function `id` with `__rvalue` is not allowed in a `@safe` function +fail_compilation/fail21414.d(46): Error: moving result of `ref` function `id` with `__rvalue` is not allowed in a `@safe` function +--- +*/ + +@safe: + +struct S +{ + int x; + this(int x) + { + this.x = x; + } + ~this() { } + this(S s) { } +} + +void foo(S s, immutable(S) t) +{ + assert(t.x == 2); + s.x = 3; + assert(t.x == 2); +} + +ref unsafeMove(T)(ref T arg) __rvalue => arg; + +ref id(T)(return ref T arg) => arg; + +void main() +{ + auto s = S(2); + foo(__rvalue(s), __rvalue(s)); + auto t = S(2); + foo(unsafeMove(t), unsafeMove(t)); + auto u = S(2); + foo(__rvalue(id(u)), __rvalue(id(u))); +} diff --git a/tests/dmd/fail_compilation/fail21547.d b/tests/dmd/fail_compilation/fail21547.d index 7a6a44a4a13..440a301de51 100644 --- a/tests/dmd/fail_compilation/fail21547.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/fail23439.d b/tests/dmd/fail_compilation/fail23439.d index b070e581a4a..6f16bc13436 100644 --- a/tests/dmd/fail_compilation/fail23439.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/fail305.d b/tests/dmd/fail_compilation/fail305.d deleted file mode 100644 index aef1624a07c..00000000000 --- a/tests/dmd/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/tests/dmd/fail_compilation/fail336.d b/tests/dmd/fail_compilation/fail336.d index 9df207120b3..8fb9857d4dc 100644 --- a/tests/dmd/fail_compilation/fail336.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/fail347.d b/tests/dmd/fail_compilation/fail347.d index c56acf5642c..996990bd400 100644 --- a/tests/dmd/fail_compilation/fail347.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/fail41.d b/tests/dmd/fail_compilation/fail41.d deleted file mode 100644 index 6d893950539..00000000000 --- a/tests/dmd/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/tests/dmd/fail_compilation/fail98.d b/tests/dmd/fail_compilation/fail98.d index 7541d3718c7..20b18d19db5 100644 --- a/tests/dmd/fail_compilation/fail98.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/fail_pretty_errors.d b/tests/dmd/fail_compilation/fail_pretty_errors.d index 79242b163ee..ebd36a7cc1d 100644 --- a/tests/dmd/fail_compilation/fail_pretty_errors.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/failcontracts.d b/tests/dmd/fail_compilation/failcontracts.d index b6c3bc906a1..749d98f9bd0 100644 --- a/tests/dmd/fail_compilation/failcontracts.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/failcstuff3.c b/tests/dmd/fail_compilation/failcstuff3.c index f54c942d446..dd07c3e165b 100644 --- a/tests/dmd/fail_compilation/failcstuff3.c +++ b/tests/dmd/fail_compilation/failcstuff3.c @@ -1,7 +1,7 @@ // check importAll analysis of C files /* TEST_OUTPUT: --- -fail_compilation/failcstuff3.c(54): Error: union `failcstuff3.S22061` conflicts with struct `failcstuff3.S22061` at fail_compilation/failcstuff3.c(50) +fail_compilation/failcstuff3.c(54): Error: redeclaration of `S22061` --- */ diff --git a/tests/dmd/fail_compilation/finalswitch_verbose.d b/tests/dmd/fail_compilation/finalswitch_verbose.d index 4bf5d46f841..90e2ca7b5b4 100644 --- a/tests/dmd/fail_compilation/finalswitch_verbose.d +++ b/tests/dmd/fail_compilation/finalswitch_verbose.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/finalswitch_verbose.d(40): Error: missing cases for `enum` members in `final switch`: diff --git a/tests/dmd/fail_compilation/fix19613.d b/tests/dmd/fail_compilation/fix19613.d new file mode 100644 index 00000000000..beca56fd709 --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/fix20075.d b/tests/dmd/fail_compilation/fix20075.d new file mode 100644 index 00000000000..00f229d326b --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/fix20318.d b/tests/dmd/fail_compilation/fix20318.d new file mode 100644 index 00000000000..f3203000127 --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/fix20867.d b/tests/dmd/fail_compilation/fix20867.d new file mode 100644 index 00000000000..0ccad098031 --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/fix21042.d b/tests/dmd/fail_compilation/fix21042.d new file mode 100644 index 00000000000..b2b224e5196 --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/fix21165.d b/tests/dmd/fail_compilation/fix21165.d new file mode 100644 index 00000000000..1d38013b4df --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/fix21166.d b/tests/dmd/fail_compilation/fix21166.d new file mode 100644 index 00000000000..24dbf8b4675 --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/hidden_ctor.d b/tests/dmd/fail_compilation/hidden_ctor.d new file mode 100644 index 00000000000..8d6e6959f29 --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/ice11153.d b/tests/dmd/fail_compilation/ice11153.d index 826bd8cd7ec..936d987c152 100644 --- a/tests/dmd/fail_compilation/ice11153.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/ice19755.d b/tests/dmd/fail_compilation/ice19755.d index 6d60fc43c1b..2770676294c 100644 --- a/tests/dmd/fail_compilation/ice19755.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/imports/imp18127a.c b/tests/dmd/fail_compilation/imports/imp18127a.c new file mode 100644 index 00000000000..2ef629e3b5b --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/imports/imp18127b.c b/tests/dmd/fail_compilation/imports/imp18127b.c new file mode 100644 index 00000000000..3cbbf7a9a63 --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/lookup.d b/tests/dmd/fail_compilation/lookup.d index fe752f2f4d7..db7eedab30a 100644 --- a/tests/dmd/fail_compilation/lookup.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/mixinprop.d b/tests/dmd/fail_compilation/mixinprop.d index db8bf5968dd..103c6b2a047 100644 --- a/tests/dmd/fail_compilation/mixinprop.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/named_arguments_error.d b/tests/dmd/fail_compilation/named_arguments_error.d index 125ebcc926e..761e1d4c78c 100644 --- a/tests/dmd/fail_compilation/named_arguments_error.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/named_arguments_ifti_error.d b/tests/dmd/fail_compilation/named_arguments_ifti_error.d index 6d8a70a2c46..a73fd3cb2e6 100644 --- a/tests/dmd/fail_compilation/named_arguments_ifti_error.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/nogc3.d b/tests/dmd/fail_compilation/nogc3.d index 17daa96358b..f1a469b5445 100644 --- a/tests/dmd/fail_compilation/nogc3.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/nonvoid_return.d b/tests/dmd/fail_compilation/nonvoid_return.d new file mode 100644 index 00000000000..bcced1b9bff --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/noreturn2.d b/tests/dmd/fail_compilation/noreturn2.d index ec6bd3ebce9..b49417436a5 100644 --- a/tests/dmd/fail_compilation/noreturn2.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/powinline.d b/tests/dmd/fail_compilation/powinline.d new file mode 100644 index 00000000000..11ebacd16aa --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/retscope3.d b/tests/dmd/fail_compilation/retscope3.d index 438fdd76e1b..8802469de2c 100644 --- a/tests/dmd/fail_compilation/retscope3.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/seq_assign.d b/tests/dmd/fail_compilation/seq_assign.d new file mode 100644 index 00000000000..560bc344242 --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/test15989.d b/tests/dmd/fail_compilation/test15989.d index 38ca3312672..85b74bfad58 100644 --- a/tests/dmd/fail_compilation/test15989.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/test18127.d b/tests/dmd/fail_compilation/test18127.d new file mode 100644 index 00000000000..ec0487cd892 --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/test19661.d b/tests/dmd/fail_compilation/test19661.d index 369c0a86249..712721487ca 100644 --- a/tests/dmd/fail_compilation/test19661.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/test20414.c b/tests/dmd/fail_compilation/test20414.c new file mode 100644 index 00000000000..90fff588f9b --- /dev/null +++ b/tests/dmd/fail_compilation/test20414.c @@ -0,0 +1,15 @@ +/* TEST_OUTPUT: +--- +fail_compilation/test20414.c(1): Error: `size_t` is not defined, perhaps `#include ` ? +fail_compilation/test20414.c(2): Error: `ptrdiff_t` is not defined, perhaps `#include ` ? +fail_compilation/test20414.c(3): Error: `NULL` is not defined, perhaps `#include ` is needed? +fail_compilation/test20414.c(5): Error: undefined identifier `fooo`, did you mean function `foo`? +--- +*/ + +#line 1 +size_t x; +ptrdiff_t pd; +void *p = NULL; +void foo(void); +void (*fp)(void) = &fooo; diff --git a/tests/dmd/fail_compilation/test20489.d b/tests/dmd/fail_compilation/test20489.d new file mode 100644 index 00000000000..1cd5350959c --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/test21241.d b/tests/dmd/fail_compilation/test21241.d new file mode 100644 index 00000000000..cb0d80e74cb --- /dev/null +++ b/tests/dmd/fail_compilation/test21241.d @@ -0,0 +1,23 @@ +/* +REQUIRED_ARGS: runnable/imports/imp21241a.c runnable/imports/imp21241b.c +*/ +// https://github.com/dlang/dmd/issues/21241 + +/* LDC: no 'fix' for LDC (moved from runnable/ to fail_compilation/); make sure a warning is emitted instead + see https://github.com/ldc-developers/ldc/pull/4949#issuecomment-2972894481 +REQUIRED_ARGS: -w +TEST_OUTPUT: +--- +runnable/imports/imp21241a.c(3): Warning: skipping definition of function `imp21241a.foo` due to previous definition for the same mangled name: foo +--- +*/ + +import imp21241a; +import imp21241b; + +void main(){ + int x = getA(); + assert(x==aValue); + x = getB(); + assert(x==bValue); +} diff --git a/tests/dmd/fail_compilation/test21317.d b/tests/dmd/fail_compilation/test21317.d new file mode 100644 index 00000000000..39b3963799e --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/test22246.c b/tests/dmd/fail_compilation/test22246.c deleted file mode 100644 index ff719133963..00000000000 --- a/tests/dmd/fail_compilation/test22246.c +++ /dev/null @@ -1,17 +0,0 @@ -/* TEST_OUTPUT: ---- -fail_compilation/test22246.c(106): Error: argument to `_Alignof` must be a type ---- -*/ - -// https://issues.dlang.org/show_bug.cgi?id=22246 - -#line 100 - -struct S { int m; }; - -int test() -{ - struct S s; - return _Alignof(s); -} diff --git a/tests/dmd/fail_compilation/test23003.c b/tests/dmd/fail_compilation/test23003.c index 3a5d92d7836..df4c46fc877 100644 --- a/tests/dmd/fail_compilation/test23003.c +++ b/tests/dmd/fail_compilation/test23003.c @@ -1,6 +1,6 @@ /* TEST_OUTPUT: --- -fail_compilation/test23003.c(101): Error: undefined identifier `size_t` +fail_compilation/test23003.c(101): Error: `size_t` is not defined, perhaps `#include ` ? fail_compilation/test23003.c(102): Error: undefined identifier `object` --- */ diff --git a/tests/dmd/fail_compilation/testrvaluecpctor.d b/tests/dmd/fail_compilation/testrvaluecpctor.d index 1173d14480d..a0ade760fe5 100644 --- a/tests/dmd/fail_compilation/testrvaluecpctor.d +++ b/tests/dmd/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/tests/dmd/fail_compilation/uda_lambda.d b/tests/dmd/fail_compilation/uda_lambda.d new file mode 100644 index 00000000000..bd3ff49e0e3 --- /dev/null +++ b/tests/dmd/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/tests/dmd/fail_compilation/union_conv.d b/tests/dmd/fail_compilation/union_conv.d index f08809c4850..134da36ecdb 100644 --- a/tests/dmd/fail_compilation/union_conv.d +++ b/tests/dmd/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/tests/dmd/runnable/exe1.c b/tests/dmd/runnable/exe1.c index da797e2e87a..221294989b6 100644 --- a/tests/dmd/runnable/exe1.c +++ b/tests/dmd/runnable/exe1.c @@ -1244,7 +1244,6 @@ void cdind() assert(cbptr->nextread == 4); } -#if 0 // TODO ImportC { struct ABC { char a,b,*l_text; } abc; static struct { int w_doto; struct ABC *w_dotp; } curw,*curwp; @@ -1255,7 +1254,6 @@ void cdind() c = curwp->w_dotp->l_text[curwp->w_doto]&0xFF; assert(c == '2'); } -#endif } void logexp() diff --git a/tests/dmd/runnable/exe2.c b/tests/dmd/runnable/exe2.c new file mode 100644 index 00000000000..9967602d659 --- /dev/null +++ b/tests/dmd/runnable/exe2.c @@ -0,0 +1,1405 @@ +/*_ exe2.c Tue Sep 5 1989 Modified by: Walter Bright */ +/* Check out operator precedence and control structures. */ +/* Check out cgelem.c */ + +#include +#include +#include +#include +#include + +void switches() +{ int a,b,c; + + a = 3; + b = 2; + switch(5) + { case 1: + assert(0); + break; + case 2: + assert(0); + break; + default: + b = 4; + break; + } + switch (a) + { b = 5; + } + assert(b == 4); + switch (a) + { default: + a = 4; + } + assert(a == 4); + switch (a) + { case 4: + a--; + break; + default: + assert(0); + } + switch (a) + { case 3: + case 4: + a++; + break; + } + assert(a == 4); + switch (a) + { case 3: + case 5: + case 6: + assert(0); + case 4: + break; + } + switch (a) + { case 47: + case 146: + case -9878: + default: + assert(0); + case 4: + break; + } + switch (3) + { case 1: + case 2: + default: + assert(0); + case 3: + break; + } + switch (a) + { case 1: + case 4: + if (a == 4) + case 2: + break; + else + default: + assert(0); + case 3: + break; + } +} + +void bigswitch() +{ + int i; + unsigned u; + + i=1231; + switch ( i ) + { + default: printf(" default case\n"); break; + case 1231: printf(" case 1\n"); return; + case 2131: printf(" case 2\n"); break; + case 3222: printf(" case 3\n"); break; + case 4323: printf(" case 4\n"); break; + case 5423: printf(" case 5\n"); break; + case 6143: printf(" case 6\n"); break; + case 7234: printf(" case 7\n"); break; + case 8432: printf(" case 8\n"); break; + case 9432: printf(" case 9\n"); break; + case 1034: printf(" case10\n"); break; + case 1143: printf(" case11\n"); break; + case 1224: printf(" case12\n"); break; + case 1354: printf(" case13\n"); break; + case 1436: printf(" case14\n"); break; + case 1546: printf(" case15\n"); break; + case 1676: printf(" case16\n"); break; + case 1723: printf(" case17\n"); break; + case 1887: printf(" case18\n"); break; + case 1923: printf(" case19\n"); break; + case 2045: printf(" case20\n"); break; + case 2123: printf(" case21\n"); break; + case 2245: printf(" case22\n"); break; + case 2354: printf(" case23\n"); break; + case 2423: printf(" case24\n"); break; + case 2534: printf(" case25\n"); break; + case 2645: printf(" case26\n"); break; + case 2756: printf(" case27\n"); break; + case 2867: printf(" case28\n"); break; + case 2978: printf(" case29\n"); break; + case 3045: printf(" case30\n"); break; + case 3134: printf(" case31\n"); break; + case 3223: printf(" case32\n"); break; + case 3345: printf(" case33\n"); break; + case 3456: printf(" case34\n"); break; + case 3556: printf(" case35\n"); break; + case 3634: printf(" case36\n"); break; + case 3723: printf(" case37\n"); break; + case 3865: printf(" case38\n"); break; + case 3976: printf(" case39\n"); break; + case 4087: printf(" case40\n"); break; + case 4154: printf(" case41\n"); break; + case 4298: printf(" case42\n"); break; + case 4343: printf(" case43\n"); break; + case 4456: printf(" case44\n"); break; + case 4545: printf(" case45\n"); break; + case 4634: printf(" case46\n"); break; + case 4723: printf(" case47\n"); break; + case 4865: printf(" case48\n"); break; + case 4976: printf(" case49\n"); break; + case 5087: printf(" case50\n"); break; + case 5198: printf(" case51\n"); break; + case 5265: printf(" case52\n"); break; + case 5378: printf(" case53\n"); break; + case 5498: printf(" case54\n"); break; + case 5509: printf(" case55\n"); break; + case 5676: printf(" case56\n"); break; + case 5734: printf(" case57\n"); break; + case 5823: printf(" case58\n"); break; + case 5934: printf(" case59\n"); break; + case 6045: printf(" case60\n"); break; + case 6167: printf(" case61\n"); break; + case 6278: printf(" case62\n"); break; + case 6398: printf(" case63\n"); break; + case 6465: printf(" case64\n"); break; + case 6554: printf(" case65\n"); break; + case 6643: printf(" case66\n"); break; + case 6732: printf(" case67\n"); break; + case 6843: printf(" case68\n"); break; + case 6956: printf(" case69\n"); break; + case 7076: printf(" case70\n"); break; + case 7187: printf(" case71\n"); break; + case 7298: printf(" case72\n"); break; + case 7309: printf(" case73\n"); break; + case 7489: printf(" case74\n"); break; + case 7565: printf(" case75\n"); break; + case 7654: printf(" case76\n"); break; + case 7734: printf(" case77\n"); break; + case 7845: printf(" case78\n"); break; + case 7976: printf(" case79\n"); break; + case 8000: + case 8001: + case 8002: + case 8003: + case 8004: + case 8005: + case 8006: + case 8007: + case 8008: + case 8009: + case 8010: + case 8011: + case 8012: + case 8013: + case 8014: + case 8015: + case 8016: + case 8017: + case 8018: + case 8019: + case 8020: + case 8021: + case 8022: + case 8023: + case 8024: + case 8025: + case 8026: + case 8027: + case 8028: + case 8029: + case 8030: + case 8031: + case 8032: + case 8033: + case 8034: + case 8035: + case 8036: + case 8037: + case 8038: + case 8039: + case 8040: + case 8041: + case 8042: + case 8043: + case 8044: + case 8045: + case 8046: + case 8047: + case 8048: + case 8049: + case 8050: + case 8051: + case 8052: + case 8053: + case 8054: + case 8055: + case 8056: + case 8057: + case 8058: + case 8059: + case 8060: + case 8061: + case 8062: + case 8063: + case 8064: + case 8065: + case 8066: + case 8067: + case 8068: + case 8069: + case 8070: + case 8071: + case 8072: + case 8073: + case 8074: + case 8075: + case 8076: + case 8077: + case 8078: + case 8079: + case 8080: + case 8081: + case 8082: + case 8083: + case 8084: + case 8085: + case 8086: + case 8087: + case 8088: + case 8089: + case 8090: + case 8091: + case 8092: + case 8093: + case 8094: + case 8095: + case 8096: + case 8097: + case 8098: + case 8099: + case 8100: + case 8101: + case 8102: + case 8103: + case 8104: + case 8105: + case 8106: + case 8107: + case 8108: + case 8109: + case 8110: + case 8111: + case 8112: + case 8113: + case 8114: + case 8115: + case 8116: + case 8117: + case 8118: + case 8119: + case 8120: + case 8121: + case 8122: + case 8123: + case 8124: + case 8125: + case 8126: + case 8127: + case 8128: + case 8129: + case 8130: + case 8131: + case 8132: + case 8133: + case 8134: + case 8135: + case 8136: + case 8137: + case 8138: + case 8139: + case 8140: + case 8141: + case 8142: + case 8143: + case 8144: + case 8145: + case 8146: + case 8147: + case 8148: + case 8149: + case 8150: + case 8151: + case 8152: + case 8153: + case 8154: + case 8155: + case 8156: + case 8157: + case 8158: + case 8159: + case 8160: + case 8161: + case 8162: + case 8163: + case 8164: + case 8165: + case 8166: + case 8167: + case 8168: + case 8169: + case 8170: + case 8171: + case 8172: + case 8173: + case 8174: + case 8175: + case 8176: + case 8177: + case 8178: + case 8179: + printf("other cases\n"); + break; + } + assert(0); +} + +/*******************************************/ + +void bigswitch2() +{ + int i; + + i = atoi("-1"); + switch (i) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + case 38: + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + case 58: + case 59: + case 60: + case 61: + case 62: + case 63: + case 64: + case 65: + case 66: + case 67: + case 68: + case 69: + case 70: + case 71: + case 72: + case 73: + case 74: + case 75: + case 76: + case 77: + case 78: + case 79: + case 80: + case 81: + case 82: + case 83: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + case 90: + case 91: + case 92: + case 93: + case 94: + case 95: + case 96: + case 97: + case 98: + case 99: + case 100: + case 101: + case 102: + case 103: + case 104: + case 105: + case 106: + case 107: + case 108: + case 109: + case 110: + case 111: + case 112: + case 113: + case 114: + case 115: + case 116: + case 117: + case 118: + case 119: + case 120: + case 121: + case 122: + case 123: + case 124: + case 125: + case 126: + case 127: + case 128: + case 129: + case 130: + case 131: + case 132: + case 133: + case 134: + case 135: + case 136: + case 137: + case 138: + case 139: + case 140: + case 141: + case 142: + case 143: + case 144: + case 145: + case 146: + case 147: + case 148: + case 149: + case 150: + case 151: + case 152: + case 153: + case 154: + case 155: + case 156: + case 157: + case 158: + case 159: + case 160: + case 161: + case 162: + case 163: + case 164: + case 165: + case 166: + case 167: + case 168: + case 169: + case 170: + case 171: + case 172: + case 173: + case 174: + case 175: + case 176: + case 177: + case 178: + case 179: + case 180: + case 181: + case 182: + case 183: + case 184: + case 185: + case 186: + case 187: + case 188: + case 189: + case 190: + case 191: + case 192: + case 193: + case 194: + case 195: + case 196: + case 197: + case 198: + case 199: + case 200: + case 201: + case 202: + case 203: + case 204: + case 205: + case 206: + case 207: + case 208: + case 209: + case 210: + case 211: + case 212: + case 213: + case 214: + case 215: + case 216: + case 217: + case 218: + case 219: + case 220: + case 221: + case 222: + case 223: + case 224: + case 225: + case 226: + case 227: + case 228: + case 229: + case 230: + case 231: + case 232: + case 233: + case 234: + case 235: + case 236: + case 237: + case 238: + case 239: + case 240: + case 241: + case 242: + case 243: + case 244: + case 245: + case 246: + case 247: + case 248: + case 249: + case 250: + case 251: + case 252: + case 253: + case 254: + case 255: + case 256: + case 257: + case 258: + case 259: + assert(0); + default: + break; + } +} + +/*******************************************/ +/* Test switch (long) */ + +long testlsw1(long l) +{ + switch (l) + { case 0x10001: l++; break; + case 0x10002: l += 2; break; + case 0x10003: l += 3; break; + case 0x24004: l += 4; break; + default: l += 5; break; + } + return l; +} + +long testlsw2(long l) +{ + switch (l) + { case 0x10001: l++; break; + case 0x10002: l += 2; break; + case 0x10003: l += 3; break; + case 0x14004: l += 4; break; + default: l += 5; break; + } + return l; +} + +long testlsw3(long l) +{ + switch (l) + { case 0x10001: l++; break; + case 0x10002: l += 2; break; + case 0x10003: l += 3; break; + case 0x10004: l += 4; break; + default: l += 5; break; + } + return l; +} + +long testlsw4(long l) +{ + switch (l) + { case -2: l++; break; + case -1: l += 2; break; + case 0: l += 3; break; + case 1: l += 4; break; + default: l += 5; break; + } + return l; +} + +long testlsw5(long l) +{ + switch (l) + { case 0xFFFF: l++; break; + case 0x10000: l += 2; break; + case 0x10001: l += 3; break; + case 0x10002: l += 4; break; + default: l += 5; break; + } + return l; +} + +long testlsw6(long l) +{ + switch (l) + { case 0x10001: l++; break; + case 0x10002: l += 2; break; + case 0x24004: l += 4; break; + default: l += 5; break; + } + return l; +} + +long testlsw7(long l) +{ + switch (l) + { case 0x10001: l++; break; + case 0x10002: l += 2; break; + case 0x14004: l += 4; break; + default: l += 5; break; + } + return l; +} + +void testlswitch() +{ + assert(testlsw1(0x10001) == 0x10002); + assert(testlsw1(0x10002) == 0x10004); + assert(testlsw1(0x24004) == 0x24004 + 4); + assert(testlsw1(0) == 5); + + assert(testlsw2(0x10001) == 0x10002); + assert(testlsw2(0x10002) == 0x10004); + assert(testlsw2(0x14004) == 0x14004 + 4); + assert(testlsw2(6) == 11); + + assert(testlsw3(0x10001) == 0x10002); + assert(testlsw3(0x10002) == 0x10004); + assert(testlsw3(0x10004) == 0x10004 + 4); + assert(testlsw3(6) == 11); + + assert(testlsw4(-2) == -2 + 1); + assert(testlsw4(-1) == -1 + 2); + assert(testlsw4(0) == 0 + 3); + assert(testlsw4(1) == 1 + 4); + assert(testlsw4(6) == 11); + + assert(testlsw5(0xFFFF) == (long)0xFFFF + 1); + assert(testlsw5(0x10000) == 0x10000 + 2); + assert(testlsw5(0x10001) == 0x10001 + 3); + assert(testlsw5(0x10002) == 0x10002 + 4); + assert(testlsw5(6) == 11); + + assert(testlsw6(0x10001) == 0x10002); + assert(testlsw6(0x10002) == 0x10004); + assert(testlsw6(0x24004) == 0x24004 + 4); + assert(testlsw6(0) == 5); + + assert(testlsw7(0x10001) == 0x10002); + assert(testlsw7(0x10002) == 0x10004); + assert(testlsw7(0x14004) == 0x14004 + 4); + assert(testlsw7(6) == 11); +} + +/*******************************************/ + +void cgelem() +{ int a,b; + + a = (37,38); + assert(a == 38); + b = (a,50); + assert(b == 50); + b = (50,a); + assert(b == 38); + { + int *i; + int j; + + j = 5; + i = (int *)(-(long)j); + } +} + +/* The following is exe8.c with alignment */ + +#define bug(text,name,p) {printf("\n%s name (%%p) = %p\n",("text"),(name));} + +typedef struct { + char var1[10]; + struct { + char var2[2]; + char var3[3]; + char var4[4]; + char var5[5]; + char var6; + } inner; +} TYPE1; + +struct { + char var1[10]; + struct { + char var2[2]; + char var3[3]; + char var4[4]; +#if c_plusplus + typedef const volatile int asdkfj(const i); +#endif + char var5[5]; + char var6; + } inner; +} str2; + +TYPE1 buf1, *buf1p = &buf1; +TYPE1 arr[3]; + +typedef union +{ char var[7]; +} TYPE2; + +TYPE2 buf2, *buf2p = &buf2; + +void alignment() /* always compiled without -a */ +{ + TYPE1 *buf1p2; + TYPE2 *buf2p2; + + bug(should be 26:,(void*)sizeof(TYPE1),d) +#if __INTSIZE == 4 + printf("TYPE1 = %d\n",sizeof(TYPE1)); + assert(sizeof(TYPE1) == 25); +#else + assert(sizeof(TYPE1) == 25); +#endif + + buf1p2 = buf1p + 1; + assert(buf1p2 == (TYPE1 *) ((char *) buf1p + sizeof(TYPE1))); + buf1p2 = buf1p + sizeof(TYPE1); + assert((buf1p2 - buf1p) == sizeof(TYPE1)); + + buf2p2 = buf2p + 1; + assert(buf2p2 == (TYPE2 *) ((char *) buf2p + sizeof(TYPE2))); + buf2p2 = buf2p + sizeof(TYPE2); + assert((buf2p2 - buf2p) == sizeof(TYPE2)); + + bug(should be 1:,(void*)sizeof(buf1p->inner.var6),d) + assert(sizeof(buf1p->inner.var6) == 1); + + bug(should be 10:,(void*)sizeof(buf1p->var1),d) + assert(sizeof(buf1p->var1) == 10); + bug(should be 1:,(void*)sizeof(buf1.var1[2]),d) + assert(sizeof(buf1.var1[2]) == 1); + bug(should be 10:,(void*)sizeof(str2.var1),d) + assert(sizeof(str2.var1) == 10); + + bug(should be 5:,(void*)sizeof(buf1p->inner.var5),d) + assert(sizeof(buf1p->inner.var5) == 5); + bug(should be 1:,(void*)sizeof(*buf1.inner.var5),d) + assert(sizeof(*buf1.inner.var5) == 1); + bug(should be 5:,(void*)sizeof(str2.inner.var5),d) + assert(sizeof(str2.inner.var5) == 5); + + /* ideally, this should be true to match hardware structs */ + bug(should be 78 when compiled without -a:,(void*)sizeof(arr),d) + /*printf("%d\n",sizeof(arr));*/ +#if __INTSIZE == 4 + assert(sizeof(arr) == 75); +#else + assert(sizeof(arr) == 75); +#endif +} + +void preprocessor() +{ int i = 0; +#if 1 + i = 3; +#elif 0 + assert(0); +#else + assert(0); +#endif + assert(i == 3); + +#if 0 + assert(0); +#elif 1 + i = 4; +#else + assert(0); +#endif + assert(i == 4); + +#if 0 + assert(0); +#elif 0 + assert(0); +#else + i = 5; +#endif + assert(i == 5); +} + +/********** COMPILE-ONLY CODE *****************/ + +typedef struct linechg_ + { int lineseen : 1; + int firstchg :15; + int lastchg; + } LINECHG; + +struct welement_ { int a,b; }; + +typedef struct window_ + { struct welement_ **winmap; + + int wm_top, + wm_left, + sw_top, + sw_left, + rows, + cols, + maxrows, + maxcols, + curs_row, + curs_col; + char def_atrb; + struct window_ *owner, + *parent; + struct linechg_ *line; + } WINDOW; + +void scrollup(winptr,amt) + WINDOW *winptr; + int amt; +{ + LINECHG *wline; + int row, maxrow, midrow, + col, maxcol, + top, left, + moveamt; + + left = winptr->sw_left; + midrow = winptr->rows; + wline = winptr->owner->line; + + for (row = 0; row < midrow; row++) + { int x; + memmove(&winptr->winmap[row+amt][left],&x,0); + if (wline[row].firstchg > left) + wline[row].firstchg = left; + } +} + +/***************** COMPILE-ONLY TESTS *******************/ + +int in_bug() +{ + return(0); +label: + return(0); + goto label; +} + +#if 0 // doesn't work with ImportC +#ifndef __cplusplus +void proto1() +{ int proto2(); + + /* this exposed bugs in automatic prototype generation */ + proto2(proto2(1,2),3); +} + + +int proto2(a,b) +{ +} +#endif +#endif + +/* Bug in circular definition of unnamed struct. Happens during */ +/* automatic prototype generation when function is called. */ +typedef struct { + int (*tra_setfn)(); + +} TRANSACTION; + +int vread(xdesc) +TRANSACTION *xdesc; +{ + (*(xdesc->tra_setfn))(xdesc); +} + +/********* COMPILE ONLY ***********/ + +typedef int ValFunc(int *); +ValFunc *fptr; + +typedef enum { a, b, } Type; +typedef enum { x, } asd; + +/********* COMPILE ONLY ***********/ + +typedef struct +{ + char names[10][10]; +} NAMES; + +NAMES *xx; + +void fooblah() +{ int i; + if (i == 1 && xx->names[0]) + ++i; +} + +/********* COMPILE ONLY ***********/ + +struct WBUF { + int a; +}; + +void dumpall() +{ + struct WBUF **wia; + int i; + + if (wia[i] ++) { + } +} + +/********* COMPILE ONLY ***********/ + +int xread() +{ int total; + + (void) 0; + return(total); +} + +/********* COMPILE ONLY ***********/ + +int funxc(c) +unsigned char c; +{ +} + +int (*f)(int) = funxc; + +/********* COMPILE ONLY ***********/ + +union two_halves { + struct { + unsigned rh,lh; + } v1; + } ; + +union memory_word { + union two_halves hh; + } ; + +union memory_word *n_mem(int x, ...) +{ +} + +void get_node() +{ + static unsigned q; + static long t; +#define new_mem(x) (n_mem(x)) +#define link(x) ((union two_halves *)new_mem(x))->v1.rh +#define info(x) ((union two_halves *)new_mem(x))->v1.lh + link(((union two_halves *)new_mem(q + 1))->v1.lh + 1) = t; + link(info(q + 1) + 1) = t; + } + +#undef new_mem +double new_mem(); + +/********* COMPILE ONLY ***********/ + +struct INT_DATA +{ int abc,def; +}; + +int funcdata(struct INT_DATA *pd) +{ + return 1; +} + +/**************************************/ + +void testbyte(int x) +{ + if ((x & 0xFF) == 0) + return; + assert(0); +} + +/**************************************/ + +void testbyte2(int x) +{ char c = x & 0xFF; + + if (c == 0) + return; + assert(0); +} + +/**************************************/ + +char *mem_malloc() +{ static char abc[10]; + return abc; +} + +void internal_symbol() +{ + char rmatrix[50]; + int msize = 0; + char *r; + + r = (msize) ? mem_malloc() : rmatrix; + assert(r == rmatrix); +} + +/**************************************/ + +void testtrans() +{ long trans_gimage(long,int); + long def; + long abc = 0x12345678; + +#if __INTSIZE == 2 + def = trans_gimage((long)(void *)(&abc) - 2,5); + assert(def == abc); +#endif +} + +long trans_gimage(tree, obj) +long tree; +int obj; +{ long obspec; + +#if __INTSIZE == 2 + obspec = (*(long *)(tree+2)); +#endif + return obspec; +} + +/**************************************/ + +int abcdef; /* tentative definition */ + +void testinit() +{ + assert(abcdef == 5); +} + +int abcdef = 5; + +/**************************************/ + +void testautoinit() +{ + struct A { int a,b,c; }; + struct A a = { 4,5,6 }; + int i = { 1 }; + int array[3] = { 8,9,10 }; + + assert(a.a == 4 && a.b == 5 && a.c == 6); + assert(i == 1); + assert(array[0] == 8 && array[1] == 9 && array[2] == 10); +} + +/********* COMPILE ONLY ***********/ + +struct foo +{ + char *name; + void (*dummy)(); +}; + +void lollygag() +{ + ; +} + +struct foo names[] = +{ {"lollygag",lollygag, }, + {"lollygag",lollygag }, + {"lollygag", }, + {"lollygag" }, + "lollygag",lollygag, + 0 +}; + +/********* COMPILE ONLY ***********/ + +int dg_displaybox[4]; +typedef struct ENTRY entry_t; +static entry_t *cmdline_entry; + +void cmdline_msg(entry_t *e) +{ int clip[4]; + + memcpy(clip,dg_displaybox,sizeof(int[4])); +} + +void t_cursor_toggle() +{ static int on = 1; + + cmdline_msg(on ? 0L : cmdline_entry); +} + +/********* COMPILE ONLY ***********/ + +void f2(work_out,p) +int *work_out; +char *p; +{ + long l; + +#if __INTSIZE == 2 + l = (long)((char *)(work_out+45)); + *((char *) ((long) p + 0L)) = '\0'; +#endif +} + +/********* COMPILE ONLY ***********/ + +/* Linkage rules from ANSI C draft */ + +int i1 = 1; +static int i2 = 2; +extern int i3 = 3; +int i4; +static int i5; + +#if 0 // errors with ImportC +int i1; +/*int i2;*/ /* should generate error message */ +int i3; +int i4; +/*int i5;*/ /* should generate error message */ +#endif + +#if 0 // errors with ImportC +extern int i1; +extern int i2; +extern int i3; +extern int i4; +extern int i5; +#endif + +/********* COMPILE ONLY ***********/ + +/* Test short circuit evaluation in preprocessor */ +#define as 0 +#if as != 0 && 4 / as +#endif +#if as == 0 || 4 / as +#endif +#if as ? 4 / as : 3 +#endif +#if !as ? 3 : 4 / as +#endif + +/********* COMPILE ONLY ***********/ + +typedef struct { + char ch; + char *ptr; +} THING; + +THING *testasdfasd(ep, fp) +THING *ep, *fp; +{ + THING te[1]; + + *te = *fp; + *fp = *ep; +#ifndef __cplusplus + *ep = *te; +#endif + return ep; +} + +/********* COMPILE ONLY ***********/ + +static void cb() +{ + unsigned *p; + int i; + + (void) ( p [(i >> 5 ) + 1] |= 1 << (i & 31) ) ; +} + +/********* COMPILE ONLY ***********/ + +void junk() {} + +void joes_bug(char *ptr, char cc) +{ + do + { + do + { + cc++; + } while (!cc && ptr); + } while (!cc && ptr); + + while (!cc) + junk (); +} + +/********* COMPILE ONLY ***********/ + +#if 0 + +#if __INTSIZE == 2 || __cplusplus +#define MK_FP(seg,offset) \ + ((void *)(((unsigned long)(seg)<<16) | (unsigned)(offset))) +#else +extern void *MK_FP(unsigned short,unsigned long); +#endif + +void abuf(int i) +{ + char *fp = (char *)MK_FP(0xb800,0x0000); + char *fp2 = (char *)MK_FP(0xb000,0x0000); + + for (i = 0; i < 100; i++) + { + fp2[i] = fp[i]; + *(fp + i + 1) = *(fp2 + i + 1); + } + + { + char *fp = (char *)MK_FP(0xb800,0x0000); + fp[i] = 0; + } +} + +#endif + +/***************************************/ + +void testc() +{ /* Had some trouble with elbitwise() */ + struct TESTC + { struct TESTC *next; + unsigned char a,b; + signed char c,d; + }; + + struct TESTC c; + struct TESTC *p; + + p = &c; + c.next = 0; + c.a = 0xF1; + c.b = 0x7F; + c.c = 0xF3; + c.d = 0xD7; + + assert(p->a == 0xF1); + assert((p->b & 0xF0) == 0x70); + assert((p->c & 0xF0) == 0xF0); + assert(p->c == (~0xF | 3)); +} + +/***************************************/ + +int main() +{ + int a=3,b=2,c,d=1,e; + int i; + extern int exintg; + + printf("Test file '%s'\n",__FILE__); + c = a > b ? a : b; + assert(c == 3); + + e = d > c ? d : a < b ? a : b; + assert(e == 2); + if (e != 2) + goto a; + + i = 0 ? a ^= 1 | 1 : 100; + assert(i == 100); + + switches(); + bigswitch(); + testlswitch(); + cgelem(); + alignment(); + preprocessor(); + testbyte((int) 0xFF00); + internal_symbol(); + testtrans(); + testinit(); + testautoinit(); + testc(); + printf("SUCCESS\n"); + exit(EXIT_SUCCESS); +a: assert(0); +} diff --git a/tests/dmd/runnable/exe3.c b/tests/dmd/runnable/exe3.c new file mode 100644 index 00000000000..89543d8f95b --- /dev/null +++ b/tests/dmd/runnable/exe3.c @@ -0,0 +1,1048 @@ +/*_ exe3.c Mon Nov 20 1989 Modified by: Walter Bright */ +/* Copyright (C) 1986-1989 by Walter Bright */ +/* All Rights Reserved */ +/* Test basic floating point operations */ + +#include +#include +#include +#include +#include +//#include + +int _8087 = 0; + +/************************************************/ + +#if 0 // does not have fltpnt.h +static unsigned long nanarray[2] = {1,0x7FF80000 }; +#define DNANQ (*(double *)nanarray) + +static unsigned long nansarray[2] = {1,0x7FF00000 }; +#define DNANS (*(double *)nansarray) + +static unsigned long infinityarray[2] = {0,0x7FF00000 }; +#define DINFINITY (*(double *)infinityarray) + +static unsigned long subnormalarray[2] = {1,0x00000000 }; +#define DSUBNORMAL (*(double *)subnormalarray) + +static unsigned long fnanarray = 0x7FC00001; +#define FNANQ (*(double *)fnanarray) + +static unsigned long fnansarray = 0x7F800001; +#define FNANS (*(double *)fnansarray) + +static unsigned long finfinityarray = 0x7F800000; +#define FINFINITY (*(double *)finfinityarray) + +static unsigned long fsubnormalarray = 0x00000001; +#define FSUBNORMAL (*(double *)fsubnormalarray) + + +void testclassify() +{ +printf("%d, %lx, %lx\n",fpclassify(DNANQ),nanarray[0],nanarray[1]); + assert(fpclassify(DNANQ) == FP_NANQ); +// assert(fpclassify(DNANS) == FP_NANS); + assert(fpclassify(DINFINITY) == FP_INFINITE); + assert(fpclassify(0.0) == FP_ZERO); + assert(fpclassify(0.1) == FP_NORMAL); + assert(fpclassify(DSUBNORMAL) == FP_SUBNORMAL); + +#if 0 + assert(fpclassify(FNANQ) == FP_NANQ); + assert(fpclassify(FNANS) == FP_NANS); + assert(fpclassify(FINFINITY) == FP_INFINITE); + assert(fpclassify(0.0f) == FP_ZERO); + assert(fpclassify(0.1f) == FP_NORMAL); + assert(fpclassify(FSUBNORMAL) == FP_SUBNORMAL); +#endif +} +#endif + +/************************************************/ + +const double abc1 = 2.0; + +void testflt() +{ double a,b,c,*pa,*pb; + float f; + int i; + long l; + + a = 3; + b = 4; + /*printf("a = %g, b = %g\n",a,b);*/ + assert(a + b == 7); + assert(a - b == -1); + assert(a * b == 12); + assert(a / b == .75); + i = a; + assert(i == 3); + a = i; + assert(a == 3.); + l = b; + assert(l == 4); + b = l; + assert(b == 4.); + assert(a < b); + assert(a <= b); + assert(b > a); + assert(b >= a); + assert(a != b); + b = -b; + assert(a > b); + assert(a >= b); + assert(b < a); + assert(b <= a); + a = -b; + assert(a != b); + a = 1024; /* look at second word */ + b = 1025; + assert(a < b); + assert(a <= b); + assert(b > a); + assert(b >= a); + assert(a != b); + b = -b; + assert(a > b); + assert(a >= b); + assert(b < a); + assert(b <= a); + a = -b; + assert(a != b); + + assert(a > 1); + assert(a > 100); + assert(a > fabs(100)); + + a = 4567; + f = a; + assert(f == 4567.); + b = f; + assert(b == a); + + a = -3.1415926; + b = -57.3e-10; + printf("a = %e, b = %e\n",a,b); + + a = 5; + b = a++; + assert(b == 5); + assert(a == 6); + pa = &a; + pb = &b; + *pb = (*pa)++; + assert(b == 6); + assert(a == 7); + assert(a > *pb); +} + +/************************************************/ + +void dblops() +{ + double a,b,c,d; + + a = 0; b = 5; + assert(a * b == 0); + assert(b * a == 0); + assert(a + b == 5); + assert(b + a == 5); + assert(a - b == -5); + assert(b - a == 5); + assert(a / b == 0); + assert((a ? b : a * 3) == 0); + assert((b ? b + 2 : a) == 7); + + a = 1; b = 2; + assert(a + b == 3); + assert(a - b == -1); + assert(a * b == 2); + assert(a / b == .5); + + a = 1; + c = a++; assert(c == 1); + c = a--; assert(c == 2); + c = ++a; assert(c == 2); + c = --a; assert(c == 1); + assert(a--); + assert(!a++); + assert((c = a--) != 0); + assert((c = a++) == 0); + assert((c = --a) == 0); + assert((c = ++a) != 0); + + a = 0; + c = -a; + assert(c == 0); + assert(c >= 0); + assert(c <= 0); + assert(c <= 1); + assert(c < 1); + assert(c >= -1); + assert(c > -1); + + a = 1024; + b = 1025; + assert(a != b); + assert(a < b); + assert(a <= b); + assert(b > a); + assert(b >= a); +} + +void fltops() +{ + float a,b,c,d; + + a = 0; b = 5; + assert(a * b == 0); + assert(b * a == 0); + assert(a + b == 5); + assert(b + a == 5); + assert(a - b == -5); + assert(b - a == 5); + assert(a / b == 0); + assert((a ? b : a * 3) == 0); + assert((b ? b + 2 : a) == 7); + + a = 1; b = 2; + assert(a + b == 3); + assert(a - b == -1); + assert(a * b == 2); + assert(a / b == .5); + + a = 1; + c = a++; assert(c == 1); + c = a--; assert(c == 2); + c = ++a; assert(c == 2); + c = --a; assert(c == 1); + assert(a--); + assert(!a++); + assert((c = a--) != 0); + assert((c = a++) == 0); + assert((c = --a) == 0); + assert((c = ++a) != 0); + + a = 0; + c = -a; + assert(c == 0); + assert(c >= 0); + assert(c <= 0); + assert(c <= 1); + assert(c < 1); + assert(c >= -1); + assert(c > -1); + + a = 1024; + b = 1025; + assert(a != b); + assert(a < b); + assert(a <= b); + assert(b > a); + assert(b >= a); +} + +float intfloat() +{ int i = 7; + + return (float) i; +} + +float intfloat2() +{ static int i = 8; + + return i; +} + +void conversions() +{ + void fcse(double,double,double); + double d; + float f; + signed char sc; + unsigned char uc; + short i; + unsigned short ui; + long l; + unsigned long ul; + +#define X(x,val) x= val;d=x;assert(fabs(d- val)<.01);x=d;assert(x == val); + + X(f,64); + X(uc,53); + X(sc,-23); + X(uc,230); + X(i,30000); + X(i,30000L); + X(ui,50000); + X(ui,50000L); + X(l,100000); +#if !__OS2__ + X(ul,0xFFFFF000L); +#endif + +#undef X + + f = 7.5; + fcse(-f,f,-f); + + /* Test rounding (should truncate towards 0) */ + d = 5.9; + i = d; + assert(i == 5); + ui = d; + assert(ui == 5); + l = d; + assert(l == 5); + + d = -5.9; + i = d; + assert(i == -5); + ui = d; + printf("ui == %d\n",ui); + /*assert(ui == 0);*/ /* not implemented correctly yet */ + l = d; + assert(l == -5); + + d = 32767; + i = d; + printf("i == %d\n",i); + assert(i == 32767); + d = -32768; + i = d; + printf("i == %d\n",i); + assert(i == -32768); + d = 65535; + ui = d; + printf("ui == %d\n",ui); + assert(ui == 65535); + + { + double xhi,xki; + + xhi=1.5; + xki=(unsigned)xhi; + assert(xki == 1); + xki=(long)xhi; + assert(xki == 1); + xki=(int)xhi; + assert(xki == 1); + } + assert(intfloat() == 7); + assert(intfloat2() == 8); + + { + long l; + unsigned long ul; + double d,ud; + + + l = 0x7FFFFFFF; + ul = l + 1; + d = l; + ud = ul; + /*printf("d = %g, ud = %g, ud-d = %g\n",d,ud,ud - d);*/ + assert(d + 1 == ud); + l = d; + ul = ud; + assert(l + 1 == ul); + } + { + long l; + unsigned long ul; + float d,ud; + + + l = 0x7FFFFFFF; + ul = l + 1; + d = l; + ud = ul; + /*printf("d = %g, ud = %g, ud-d = %g\n",d,ud,ud - d);*/ +// assert(d + 1 == ud); +// l = d; +// ul = ud; +// assert(l == ul); + } + { + unsigned long x = 0xFFFFFFFF; + + x = x * 0.838096515; + assert(x == 0xD68D7E41); + } +} + +void fcse(f1,f2,f3) +double f1,f2,f3; // float should work, too, but doesn't +{ + + assert(f1 == -7.5); + assert(f2 == 7.5); + assert(f3 == f1); +} + +void initializations() +{ static float f1 = 1, f2 = (double) 2, f3 = 3., f4 = (int) 4.2; + float f5 = 5, f6 = (double) 6, f7 = 7., f8 = (int) 8.2; + static struct S { int a; char b,c; float d; char e; int f; char g;} + s = {1,2,3,4,5,6,7}; + + assert(f1 == 1); + assert(f2 == 2); + assert(f3 == 3); + assert(f4 == 4); + assert(f5 == 5); + assert(f6 == 6); + assert(f7 == 7); + assert(f8 == 8); + + assert(s.a == 1); + assert(s.b == 2); + assert(s.c == 3); + assert(s.d == 4); + assert(s.e == 5); + assert(s.f == 6); + assert(s.g == 7); +} + +void floats() +{ float f,*pf; + double d,*pd; + float x = 5,y = 6,z = 7; + + x = z * y; + z = z * 10; + y = y * 10; + assert(x == 42); + assert(z == 70); + assert(y == 60); + + f = 15.; + pf = &f; + assert(f == fabs(*pf)); + assert(*pf == fabs(f)); + assert(f + f == 30.); + d = 8; + *pf = d; + d = *pf; + assert(d == 8); + ++f; + assert(f == 9); + --f; + assert(f == 8); + + f = 0.0; + pf = &f; + *pf += exp(1.0); + assert(f == *pf); + + d = 0.0; + pd = &d; + *pd += exp(1.0); + assert(d == *pd); +} + +#if 0 +double fabs(x) +double x; +{ return (x < 0) ? -x : x; } +#endif + +void comsubs() +{ double a,b[3]; + int i; + + b[2] = 6.0; + i = 2; + a = b[i] - b[i]; + assert(a == 0); +} + +/***********************************************/ + +#if __cplusplus +int para1(char *,char *,char **); +#endif + +void parameters() +{ static char a[] = "abcd"; + char *b = "efg"; + char *c[1]; + + c[0] = "hij"; + para1(a,b,c); +} + +int para1(a,b,c) +char a[],*b,*c[]; +{ + assert(*a == 'a' && a[1] == 'b'); + assert(*b == 'e' && b[1] == 'f'); + assert(**c == 'h' && c[0][1] == 'i'); + return 0; +} + +/***********************************************/ + +#if __cplusplus +int funcp(float *pf1,float *pf2,char *pc1); +int func2(double,double,int); +#endif +void func3(float,float,char); +void func4(double,double,int); + +void parameters2() +{ + func2(1.0,2.0,0x1234); + func3(1.0,2.0,(char)0x1234); + func4(1.0,2.0,0x1234); +} + +int func2(f1,f2,c1) +float f1,f2; +char c1; +{ + assert(c1 == 0x34); + assert(f1 == 1.0); + assert(f2 == 2.0); + funcp(&f1,&f2,&c1); + return 0; +} + +void func3(float f1,float f2,char c1) +{ + assert(c1 == 0x34); + assert(f1 == 1.0); + assert(f2 == 2.0); + funcp(&f1,&f2,&c1); +} + +void func4(f1,f2,c1) +double f1,f2; int c1; //float f1,f2; char c1; this should work, bug in ImportC +{ +// assert(c1 == 0x34); // bug in ImportC + assert(f1 == 1.0); + assert(f2 == 2.0); +} + + +int funcp(float *pf1,float *pf2,char *pc1) +{ + assert(*pc1 == 0x34); + assert(*pf1 == 1.0); + assert(*pf2 == 2.0); + return 0; +} + +/***********************************************/ + +void scoping() +{{ + int a,b; + + a = 1; + b = 2; + assert(a == 1); + assert(b == 2); + {{ int c,d; + + c = 3; + d = 4; + assert(a == 1); + assert(b == 2); + assert(c == 3); + assert(d == 4); + }} + {{ int e,f; + + e = 5; + f = 6; + assert(a == 1); + assert(b == 2); + assert(e == 5); + assert(f == 6); + }} + assert(a == 1); + assert(b == 2); +}} + +/* Test handling of overflow of 8087 stack */ + +int smooth(buf,c,x) +int buf[][3]; +double c[]; +int x; +{ + int tmp; + + tmp = + c[2] * 1 + c[1] * 2 + c[2] * 3 + + c[1] * 4 + c[0] * 5 + c[1] * 6 + + c[2] * 7 + c[1] * 8 + c[2] * 9; + + return tmp; +} + +void overflow() +{ + static double c[3] = {0.2,0.1,0.1}; + static int buf[3][3] = {1,2,3, + 4,5,6, + 7,8,9}; + int i; + + /*printf("i = %d, status = b%b\n",i,_status87());*/ +#if !(M_UNIX || M_XENIX) + i = smooth(buf,c,1); + assert(i == 5); +#endif + /*printf("i = %d, status = b%b\n",i,_status87());*/ +} + +void testsave87() +{ + double r,q,u; + q = -16; + r = 0; + u=q/(r ? fabs(q) : -fabs(q)); + assert(u == 1); +} + +/****************** COMPILE-ONLY TESTS *****************/ + +double ViewingTrans[4][2][3]; + +void ApplyViewingTrans(Location, World, Screen) +int Location; +int World[]; +int Screen[]; +{ double d; + + Screen[0] = 200; + d = ((double) Screen[0]); +} + +/************/ + +char *p(in) +float in; +{ + char *errmess=""; + float xpos = 2.5,j,k; + short trans = 0; + + if ( in+xpos > (trans ? j : k) ) + errmess = "x axis length negative or too long"; + return( errmess ); +} + +/****************** + * Don't link in library routine. + */ + +double exp(arg) +double arg; +{ + atof("1.2345"); /* destroy all registers */ + return 2.718; +} + +/******************** COMPILE ONLY **********************/ + +double midexp() +{ + static double s=0; + return s=s++; +} + +/***************************************/ + +float ff() { return 6; } + +double dd() +{ + return ff() + ff(); +} + +void testfltto87() +{ + assert(dd() == 12.); +} + +/***************************************/ + +int ysizedec; +int ysize2; +int ysize; + +double testfr(); + +void testfrd( void ) { + ysize=(int)(testfr()); + ysizedec=ysize - 1; + ysize2=ysize / 2; + assert(ysize2 == 50); +} + +double testfr() { return 100.23456; } + +/***************************************/ + +#if __ZTC__ >= 0x220 + +double pascal fltretp(double x) +{ + if (x < 0) + return x + 1; + else + return x; +} + +float _fortran fltretf(float x) +{ + if (x < 0) + { x--; + return x; + } + else + return x; +} + +void testfltret() +{ + assert(fltretp(-5) == -4); + assert(fltretf(-5) == -6); +} + +#else +#define testfltret() +#endif + +/***************************************/ + +void testhex() +{ +#if __ZTC__ >= 0x220 + double d; + static long dx[2] = { 0x789abcdf,0x3ff23456 }; + + d = 0x1.23456789ABCDEFp0; + printf("d = %g, %08lx%08lx\n",d,((long*)&d)[1],((long*)&d)[0]); + assert(d == *(double *)dx); + + d = 0x1.23456789ABCDEFp2; + printf("d = %g, %08lx%08lx\n",d,((long*)&d)[1],((long*)&d)[0]); + + d = 0x1p-23; + printf("d = %g, %08lx%08lx\n",d,((long*)&d)[1],((long*)&d)[0]); + assert(d == FLT_EPSILON); + + assert(0x1.FFFFFEp127 == 0x.FFFFFFp128); + assert(FLT_MAX == 0x1.FFFFFEp127); + assert(FLT_MIN == 0x1p-126); +#endif +} + +/***************************************/ + +void testdashf() +{ + double q; + + q=1; + + assert(q == 1); + if (q==1) printf("OK: q == 1 \n"); + + if (q>=1) printf("OK: q >= 1 \n"); + else assert(0); +} + +/***************************************/ + +void testfabsf() +{ float x,y; + + y = 10; + x = 10; + assert(fabsf(x) == y); + x = -x; + assert(fabsf(x) == y); + x = fabs(x * 2); + assert(fabsf(x) == 20); +} + +/***************************************/ + +void testfabs() +{ double x,y; + + y = 10; + x = 10; + assert(fabs(x) == y); + x = -x; + assert(fabs(x) == y); + x = fabs(x * 2); + assert(fabs(x) == 20); +} + +/***************************************/ + +void testfabsl() +{ long double x,y; + + y = 10; + x = 10; + assert(fabsl(x) == y); + x = -x; + assert(fabsl(x) == y); + x = fabs(x * 2); + assert(fabsl(x) == 20); +} + +/***************************************/ + +void testassert0(double x) { assert(x == 0); } + +double afunc() {return 1;} +double bfunc() {return 2;} +double cfunc() {return 3;} +int ifunc() {return 1;}; + +void testf() +{ + double result; + + result = afunc()-(cfunc()-bfunc()); + //printf("afunc()-(cfunc()-bfunc())=%f (should be 0)\n",result); + testassert0(result); + result = afunc()-ifunc(); + testassert0(result); + //printf("afunc()-ifunc()=%f (should be 0)\n",result); +} + +/***************************************/ + +void testcln() +{ +#if __ZTC__ >= 0x310 + static double x = 3; + int pjv; + + pjv = -x != 0; + assert(pjv == 1); +#endif +} + +/***************************************/ + +#define ABS(a) ((a) <0 ? -(a) : (a)) +void testabsm() +{ + double a=0; + if (ABS(a) == 0.0) + {} + else + assert(0); +} + +/***************************************/ + +float txx() +{ + float x; + return x/1000; /* compile only */ +} + +/***************************************/ + +void func635(double d) {} + +void test635(void) +{ + float x; + + for (x = 0; x<5.0; x+=1.0) { + func635( 2.0 <= (3.0 < x ? 3.0 : x) ? (3.0 < x ? 3.0 : x) + : 2.0 ); + } +} + +/***************************************/ + +double vnormi_(double *a, long n) +{ + double max, t; + + max = fabs(*a); + while (--n) + if ((t = fabs(*(++a))) > max) + max = t; + + return max; +} + +static double d[2]; + +void testdbl87() +{ + long i,m; + double err; + + m = 2; + + d[0] = 0; + d[1] = 0; + + printf("Start tests...\n\n"); + + err = vnormi_(d,m); + if (err != 0.0) + assert(0); + else + printf("norm(x) is O.K. !\n"); + + printf("d[0] = %lf, d[1] = %lf\n", d[0], d[1]); +} + +/***************************************/ + +double xxx() { return 1; } + +void testmn() +{ + int i = 1; + + if ((double)(int)xxx() != xxx()) + i--; + assert(i == 1); +} + +/***************************************/ + +void testfdivp() +{ +#if !__INLINE_8087 + double x = 4195835.0; + double y = 3145727.0; + double z; + + z = x - (x / y) * y; + assert(z < 1.0); +#endif +} + +/***************************************/ + +void tidy() +{ +#if 0 && __SC__ >= 0x750 + double x = INFINITY; + + if( (0.0 * x) == 0.0 ){ + assert(0); + } + + if( (0 * x) == 0.0 ){ + assert(0); + } + + if( !isnan(0.0 * x) ){ + assert(0); + } + + if( !isnan(0 * x) ){ + assert(0); + } +#endif +} + +/***************************************/ + +void RealExpression(long double v1, long double v2, long double v3) +{ + assert(v1 == 0); + assert(v2 == 1); + assert(v3 == 37); +} + +void NegExpconstFold(long double x) +{ + RealExpression(0,x,37); +} + +void testld() +{ + long double x = 2.0; + long double y = 4.0; + + x /= y; + assert(x == 0.5); + NegExpconstFold(1); +} + +/***************************************/ + +void testdbl99() +{ + double d; + + d = 08.5; + printf("d = %g\n", d); + assert(d == 8.5); + d = 09.; + printf("d = %g\n", d); + assert(d == 9); + d = 09e0; + printf("d = %g\n", d); + assert(d == 9); +} + +/***************************************/ + +int main() +{ + printf("File %s\n",__FILE__); + + printf("_8087 = %d\n",_8087); + while (1) + { printf(_8087 ? "with 8087\n" : "without 8087\n"); + + //testclassify(); +// testflt(); https://github.com/dlang/dmd/issues/21142 + dblops(); + fltops(); + conversions(); + initializations(); + floats(); + comsubs(); + parameters(); + parameters2(); + scoping(); + overflow(); + testsave87(); + testfltto87(); + testfrd(); + testfltret(); + testhex(); + testfabsf(); + testfabs(); + testfabsl(); + testf(); + testcln(); + testabsm(); + test635(); + testdbl87(); + testmn(); + tidy(); + if (_8087 == 0) + break; + _8087 -= _8087; + } + testld(); + testdbl99(); + printf("SUCCESS\n"); + return EXIT_SUCCESS; +} diff --git a/tests/dmd/runnable/extra-files/hello-profile-postscript.sh b/tests/dmd/runnable/extra-files/hello-profile-postscript.sh index d986ba5939a..68391c04a2a 100755 --- a/tests/dmd/runnable/extra-files/hello-profile-postscript.sh +++ b/tests/dmd/runnable/extra-files/hello-profile-postscript.sh @@ -2,10 +2,11 @@ source tools/common_funcs.sh -# strip out Dmain since it's symbol differs between windows and non-windows +# strip out Dmain since its symbol differs between Windows and non-Windows # strip out _d_arraycatnTX and _d_arraysetlengthT since they are part of the # lowering of the array concatenation operator -grep -Ev 'Dmain|_d_arraycatnTX|_d_arraysetlengthT' ${OUTPUT_BASE}.d.trace.def > ${OUTPUT_BASE}.d.trace.def2 +# strip out __arrayAlloc since its mangled name differs on x86 vs x86_64 +grep -Ev 'Dmain|_d_arraycatnTX|_d_arraysetlengthT|__arrayAlloc' ${OUTPUT_BASE}.d.trace.def > ${OUTPUT_BASE}.d.trace.def2 diff -up --strip-trailing-cr ${EXTRA_FILES}/${TEST_NAME}.d.trace.def ${OUTPUT_BASE}.d.trace.def2 diff --git a/tests/dmd/runnable/extra-files/hello-profile.d.trace.def b/tests/dmd/runnable/extra-files/hello-profile.d.trace.def index ab04b4ec542..cb6678d5282 100644 --- a/tests/dmd/runnable/extra-files/hello-profile.d.trace.def +++ b/tests/dmd/runnable/extra-files/hello-profile.d.trace.def @@ -1,3 +1,3 @@ - -FUNCTIONS - _D5hello8showargsFAAyaZv + +FUNCTIONS + _D5hello8showargsFAAyaZv diff --git a/tests/dmd/runnable/imports/imp21241a.c b/tests/dmd/runnable/imports/imp21241a.c new file mode 100644 index 00000000000..6a40949fcfe --- /dev/null +++ b/tests/dmd/runnable/imports/imp21241a.c @@ -0,0 +1,9 @@ +// https://github.com/dlang/dmd/issues/21241 +enum {aValue=1}; +static int foo(void){ + return aValue; +} + +int getA(void){ + return foo(); +} diff --git a/tests/dmd/runnable/imports/imp21241b.c b/tests/dmd/runnable/imports/imp21241b.c new file mode 100644 index 00000000000..4808fb6b97d --- /dev/null +++ b/tests/dmd/runnable/imports/imp21241b.c @@ -0,0 +1,9 @@ +// https://github.com/dlang/dmd/issues/21241 +enum {bValue=2}; +static int foo(void){ + return bValue; +} + +int getB(void){ + return foo(); +} diff --git a/tests/dmd/runnable/placenew.d b/tests/dmd/runnable/placenew.d index d90d10a5e74..834a1f76bcb 100644 --- a/tests/dmd/runnable/placenew.d +++ b/tests/dmd/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/tests/dmd/runnable/powinline.d b/tests/dmd/runnable/powinline.d new file mode 100644 index 00000000000..92d1c04e556 --- /dev/null +++ b/tests/dmd/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/tests/dmd/runnable/structinit.c b/tests/dmd/runnable/structinit.c index dd0b242627d..2ee8debc695 100644 --- a/tests/dmd/runnable/structinit.c +++ b/tests/dmd/runnable/structinit.c @@ -201,6 +201,30 @@ void test8() assert(s8.leaf.state == 50); } +/**************************************/ +// https://github.com/dlang/dmd/issues/21210 + +struct Sa {int x, y;}; +struct Sb { + struct Sa v[1]; +}; +struct Sb s9 = {0}; + +void test9() +{ + struct Sb v = {1}; + __check(v.v[0].x == 1); + __check(v.v[0].y == 0); + struct Sb v2[1] = {1}; + __check(v2[0].v[0].x == 1); + __check(v2[0].v[0].y == 0); + struct Sb v3[2] = {1, 2, 3, 4}; + __check(v3[0].v[0].x == 1); + __check(v3[0].v[0].y == 2); + __check(v3[1].v[0].x == 3); + __check(v3[1].v[0].y == 4); +} + /**************************************/ int main() @@ -213,5 +237,6 @@ int main() test6(); test7(); test8(); + test9(); return 0; } diff --git a/tests/dmd/runnable/testinvariant.d b/tests/dmd/runnable/testinvariant.d index f39ef0f864c..2d64bc2efef 100644 --- a/tests/dmd/runnable/testinvariant.d +++ b/tests/dmd/runnable/testinvariant.d @@ -229,8 +229,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() { @@ -239,4 +283,5 @@ void main() test16384(); test13113(); test13147(); + test20924(); } diff --git a/tests/dmd/runnable/testpdb.d b/tests/dmd/runnable/testpdb.d index 9be563b98b7..745031ea7c1 100644 --- a/tests/dmd/runnable/testpdb.d +++ b/tests/dmd/runnable/testpdb.d @@ -6,6 +6,9 @@ import core.time; import core.demangle; import ldc.attributes; +version(LDC) version(X86_64) version = LDC_X86_64; +version(LDC_X86_64) version(D_Optimized) version = LDC_X86_64_Optimized; + @optStrategy("none") // LDC void main(string[] args) { @@ -72,8 +75,12 @@ void main(string[] args) test20253(session, globals); + test21384(session, globals); + test18147(session, globals); + test21382(session, globals); + source.Release(); session.Release(); globals.Release(); @@ -464,6 +471,94 @@ void test20253(IDiaSession session, IDiaSymbol globals) assert(false, "code range of check20253 overlaps with func20253"); } +/////////////////////////////////////////////// +// https://github.com/dlang/dmd/issues/21384 +int sum21384(int a, int b, int c) +{ + int s = a + b + c; + return s; +} + +struct S21384 +{ + long x, y; +} + +S21384 makeS21384(int a, int b) +{ + S21384 s = S21384(a, b); + return s; +} + +class T21384 +{ + S21384 genS21384(int a, int b) + { + S21384 s = S21384(a, b); + return s; + } +} + +void testVar(IDiaSymbol var, string name, DWORD kind, string msg) +{ + BSTR varname; + var.get_name(&varname) == S_OK || assert(false, "testpdb.sum21384: vars[0]: no name"); + scope(exit) SysFreeString(varname); + auto vname = toUTF8(varname[0..wcslen(varname)]); + vname == name || assert(false, msg ~ " name " ~ vname ~ ", expected " ~ name); + + DWORD vkind; + var.get_dataKind(&vkind) == S_OK || assert(false, msg ~ " cannot retrieve data kind"); + vkind == kind || assert(false, msg ~ " unexpected data kind"); +} + +DWORD getFuncVars(IDiaSymbol globals, const(wchar)* func, IDiaSymbol[] vars) +{ + IDiaSymbol funcSym = searchSymbol(globals, func); + funcSym || assert(false, "testpdb.sum21384 not found"); + + auto sfunc = toUTF8(func[0..wcslen(func)]); + IDiaEnumSymbols pEnumSymbols; + HRESULT hr = funcSym.findChildrenEx(SymTagEnum.SymTagData, NULL, NameSearchOptions.nsNone, &pEnumSymbols); + hr == S_OK && pEnumSymbols || assert(false, sfunc ~ ": no children found"); + + DWORD fetched; + hr = pEnumSymbols.Next(cast(uint)vars.length, vars.ptr, &fetched); + hr == S_OK || assert(false, sfunc ~ ": failed to fetch any vars"); + return fetched; +} + +void test21384(IDiaSession session, IDiaSymbol globals) +{ + IDiaSymbol[5] vars; + DWORD cnt = getFuncVars(globals, "testpdb.sum21384", vars[]); + cnt == 4 || assert(false, "testpdb.sum21384: failed to fetch 4 vars"); + + testVar(vars[0], "a", DataKind.DataIsParam, "testpdb.sum21384: arg1:"); + testVar(vars[1], "b", DataKind.DataIsParam, "testpdb.sum21384: arg2:"); + testVar(vars[2], "c", DataKind.DataIsParam, "testpdb.sum21384: arg3:"); + testVar(vars[3], "s", DataKind.DataIsLocal, "testpdb.sum21384: local:"); + + // LDC: extra var with enabled optimizations for make/genS21384() on x86_64 + version (LDC_X86_64_Optimized) enum numExtraVarsWithEnabledOptimizations = 1; + else enum numExtraVarsWithEnabledOptimizations = 0; + + cnt = getFuncVars(globals, "testpdb.makeS21384", vars[]) - numExtraVarsWithEnabledOptimizations; + cnt == 3 || assert(false, "testpdb.makeS21384: failed to fetch 3 vars"); + + testVar(vars[0], "a", DataKind.DataIsParam, "testpdb.makeS21384: arg1:"); + testVar(vars[1], "b", DataKind.DataIsParam, "testpdb.makeS21384: arg2:"); + testVar(vars[2], "s", DataKind.DataIsLocal, "testpdb.makeS21384: hidden:"); + + cnt = getFuncVars(globals, "testpdb.T21384.genS21384", vars[]) - numExtraVarsWithEnabledOptimizations; + cnt == 4 || assert(false, "testpdb.T21384.genS21384: failed to fetch 4 vars"); + + testVar(vars[0], "this", DataKind.DataIsObjectPtr, "testpdb.T21384.genS21384: this:"); + testVar(vars[1], "a", DataKind.DataIsParam, "testpdb.T21384.genS21384: arg1:"); + testVar(vars[2], "b", DataKind.DataIsParam, "testpdb.T21384.genS21384: arg2:"); + testVar(vars[3], "s", DataKind.DataIsLocal, "testpdb.T21384.genS21384: hidden:"); +} + /////////////////////////////////////////////// // https://issues.dlang.org/show_bug.cgi?id=18147 string genMembers18147() @@ -555,6 +650,35 @@ void test18147(IDiaSession session, IDiaSymbol globals) } // !LDC } +// https://github.com/dlang/dmd/issues/21382 +class Dsym21382 +{ + final int finalFun() { return 7; } + int virtualFun() { return 13; } +} + +void test21382(IDiaSession session, IDiaSymbol globals) +{ + IDiaSymbol dSym = searchSymbol(globals, "testpdb.Dsym21382"); + dSym || assert(false, "testpdb.Dsym21382 not found"); + + version (LDC_X86_64) + { + // FIXME: no methods + } + else + { + BOOL virt; + IDiaSymbol finalSym = searchSymbol(dSym, "finalFun"); + finalSym || assert(false, "testpdb.Dsym21382.finalFun not found"); + finalSym.get_virtual(&virt) == S_OK && !virt || assert(false, "testpdb.Dsym21382.finalFun is virtual"); + + IDiaSymbol virtualSym = searchSymbol(dSym, "virtualFun"); + virtualSym || assert(false, "testpdb.Dsym21382.virtualFun not found"); + virtualSym.get_virtual(&virt) == S_OK && virt || assert(false, "testpdb.Dsym21382.virtualFun is virtual"); + } +} + /////////////////////////////////////////////// import core.stdc.stdio; import core.stdc.wchar_;