From 4809f0e2f3c1e49d69c80452caa3de3e272876a1 Mon Sep 17 00:00:00 2001 From: Manu Evans Date: Mon, 10 Mar 2025 21:06:29 +1000 Subject: [PATCH 001/113] Accept __rvalue attribute on ref functions; which will force the result to be treated as __rvalue. (dlang/dmd!20946) This is essential to implement `move`, `forward`, etc. --- dmd/expressionsem.d | 15 ++++++++++++++- dmd/frontend.h | 11 ++++++++--- dmd/mtype.d | 4 ++++ dmd/parse.d | 4 ++++ 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 81c1c5bda4..83f28be96a 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -5893,6 +5893,19 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor printf("CallExp::semantic() %s\n", exp.toChars()); } + scope (exit) + { + if (TypeFunction tf = exp.f ? cast(TypeFunction)exp.f.type : null) + { + result.rvalue = tf.isRvalue; + if (tf.isRvalue && !tf.isRef) + { + error(exp.f.loc, "`__rvalue` only valid on functions that return by `ref`"); + setError(); + } + } + } + Objects* tiargs = null; // initial list of template arguments Expression ethis = null; Type tthis = null; @@ -10839,7 +10852,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } } - else if (sd.hasMoveCtor && !e2x.isCallExp() && !e2x.isStructLiteralExp()) + else if (sd.hasMoveCtor && (!e2x.isCallExp() || e2x.rvalue) && !e2x.isStructLiteralExp()) { // #move /* The !e2x.isCallExp() is because it is already an rvalue diff --git a/dmd/frontend.h b/dmd/frontend.h index dd39b74672..557d9bb7f3 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -4596,6 +4596,7 @@ class TypeFunction final : public TypeNext bool isInOutQual; bool isCtor; bool isReturnScope; + bool isRvalue; BitFields() : isNothrow(), isNogc(), @@ -4610,10 +4611,11 @@ class TypeFunction final : public TypeNext isInOutParam(), isInOutQual(), isCtor(), - isReturnScope() + isReturnScope(), + isRvalue() { } - BitFields(bool isNothrow, bool isNogc = false, bool isProperty = false, bool isRef = false, bool isReturn = false, bool isScopeQual = false, bool isReturnInferred = false, bool isScopeInferred = false, bool isLive = false, bool incomplete = false, bool isInOutParam = false, bool isInOutQual = false, bool isCtor = false, bool isReturnScope = false) : + BitFields(bool isNothrow, bool isNogc = false, bool isProperty = false, bool isRef = false, bool isReturn = false, bool isScopeQual = false, bool isReturnInferred = false, bool isScopeInferred = false, bool isLive = false, bool incomplete = false, bool isInOutParam = false, bool isInOutQual = false, bool isCtor = false, bool isReturnScope = false, bool isRvalue = false) : isNothrow(isNothrow), isNogc(isNogc), isProperty(isProperty), @@ -4627,7 +4629,8 @@ class TypeFunction final : public TypeNext isInOutParam(isInOutParam), isInOutQual(isInOutQual), isCtor(isCtor), - isReturnScope(isReturnScope) + isReturnScope(isReturnScope), + isRvalue(isRvalue) {} }; @@ -4660,6 +4663,8 @@ class TypeFunction final : public TypeNext bool isCtor(bool v); bool isReturnScope() const; bool isReturnScope(bool v); + bool isRvalue() const; + bool isRvalue(bool v); private: uint16_t bitFields; public: diff --git a/dmd/mtype.d b/dmd/mtype.d index 63663dca99..5ba866c9e5 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -2488,6 +2488,7 @@ extern (C++) final class TypeFunction : TypeNext bool isInOutQual; /// inout on the qualifier bool isCtor; /// the function is a constructor bool isReturnScope; /// `this` is returned by value + bool isRvalue; /// returned reference should be treated as rvalue } import dmd.common.bitfields : generateBitFields; @@ -2531,6 +2532,8 @@ extern (C++) final class TypeFunction : TypeNext this.isScopeQual = true; if (stc & STC.scopeinferred) this.isScopeInferred = true; + if (stc & STC.rvalue) + this.isRvalue = true; this.trust = TRUST.default_; if (stc & STC.safe) @@ -2567,6 +2570,7 @@ extern (C++) final class TypeFunction : TypeNext t.isScopeQual = isScopeQual; t.isReturnInferred = isReturnInferred; t.isScopeInferred = isScopeInferred; + t.isRvalue = isRvalue; t.isInOutParam = isInOutParam; t.isInOutQual = isInOutQual; t.trust = trust; diff --git a/dmd/parse.d b/dmd/parse.d index d75597ed3c..3d25464fc5 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -1422,6 +1422,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer stc = STC.scope_; break; + case TOK.rvalue: + stc = STC.rvalue; + break; + case TOK.at: { AST.Expressions* udas = null; From a5806ae802087fdf38fe6e3a85a2fd5e7fa2b426 Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Tue, 11 Mar 2025 02:30:29 +0200 Subject: [PATCH 002/113] Fix dlang/dmd!17481 - free ctors before returning (dlang/dmd!20975) --- runtime/druntime/src/rt/minfo.d | 3 +++ 1 file changed, 3 insertions(+) diff --git a/runtime/druntime/src/rt/minfo.d b/runtime/druntime/src/rt/minfo.d index 6e9cd1c8fe..6f09674412 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; + } } } From 5180c2b6f9d2992b1d8d2bd3d643b725029d6405 Mon Sep 17 00:00:00 2001 From: Matthew Qiu <93230055+MatthewQiu-5@users.noreply.github.com> Date: Tue, 11 Mar 2025 19:33:53 -0400 Subject: [PATCH 003/113] Extracted Condition.include to visitor in expressionsem (dlang/dmd!20977) --- dmd/cond.d | 116 +----------------------------------- dmd/cond.h | 4 -- dmd/dsymbolsem.d | 8 +-- dmd/expressionsem.d | 140 ++++++++++++++++++++++++++++++++++++++++++++ dmd/frontend.h | 10 ++-- 5 files changed, 150 insertions(+), 128 deletions(-) diff --git a/dmd/cond.d b/dmd/cond.d index 19c6fe3d5c..9e562b6b9c 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 174a8fb9aa..0afa042f9d 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/dsymbolsem.d b/dmd/dsymbolsem.d index de5e4bda26..54165857fd 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -7533,12 +7533,12 @@ private extern(C++) class NewScopeVisitor : Visitor extern(C++) Dsymbols* include(Dsymbol d, Scope* sc) { - scope icv = new IncludeVisitor(sc); + scope icv = new ConditionIncludeVisitor(sc); d.accept(icv); return icv.symbols; } -extern(C++) class IncludeVisitor : Visitor +extern(C++) class ConditionIncludeVisitor : Visitor { alias visit = typeof(super).visit; Scope* sc; @@ -7570,7 +7570,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) @@ -8056,7 +8056,7 @@ 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; + Dsymbols* d = dmd.expressionsem.include(cd.condition, null) ? cd.decl : cd.elsedecl; result = Dsymbol.oneMembers(d, *ps, ident); } else diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 83f28be96a..45675efd7c 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -17672,3 +17672,143 @@ extern(D) void lowerArrayAggregate(StaticForeach sfe, Scope* sc) sfe.aggrfe.aggr = sfe.aggrfe.aggr.optimize(WANTvalue); sfe.aggrfe.aggr = sfe.aggrfe.aggr.ctfeInterpret(); } + +extern(C++) 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 557d9bb7f3..9e07b7236f 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -6574,7 +6574,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(); @@ -6603,7 +6602,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; }; @@ -6613,7 +6611,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; }; @@ -6623,7 +6620,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; }; @@ -7520,13 +7516,13 @@ class ImportAllVisitor : public Visitor 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; @@ -7553,6 +7549,8 @@ extern bool isFuncHidden(ClassDeclaration* cd, FuncDeclaration* fd); extern void lowerNonArrayAggregate(StaticForeach* sfe, Scope* sc); +extern int32_t include(Condition* c, Scope* sc); + class NrvoWalker final : public StatementRewriteWalker { public: From 8afc932d430015e0e8c8a08407ec8195323562dc Mon Sep 17 00:00:00 2001 From: Nicholas Wilson Date: Thu, 13 Mar 2025 07:22:15 +0800 Subject: [PATCH 004/113] fixup `mtype.h` for dlang/dmd!20946 (dlang/dmd!20971) --- dmd/mtype.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dmd/mtype.h b/dmd/mtype.h index 4d1938f4a7..4d303acf3c 100644 --- a/dmd/mtype.h +++ b/dmd/mtype.h @@ -554,6 +554,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; From d24493c99ef2dff370dd9c3c9b2eaa97c881ad48 Mon Sep 17 00:00:00 2001 From: Abul Hossain Khan <140191921+abulgit@users.noreply.github.com> Date: Thu, 13 Mar 2025 16:06:45 +0530 Subject: [PATCH 005/113] Fixes the invariant not called on extern(C++) classes issue (dlang/dmd!20981) --- dmd/func.d | 6 ++-- tests/dmd/runnable/testinvariant.d | 47 +++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/dmd/func.d b/dmd/func.d index 25987a7819..88e7aeea95 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -820,15 +820,13 @@ extern (C++) class FuncDeclaration : Declaration bool addPreInvariant() { auto ad = isThis(); - ClassDeclaration cd = ad ? ad.isClassDeclaration() : null; - return (ad && !(cd && cd.isCPPclass()) && global.params.useInvariants == CHECKENABLE.on && (visibility.kind == Visibility.Kind.protected_ || visibility.kind == Visibility.Kind.public_ || visibility.kind == Visibility.Kind.export_) && !this.isNaked()); + return (ad && global.params.useInvariants == CHECKENABLE.on && (visibility.kind == Visibility.Kind.protected_ || visibility.kind == Visibility.Kind.public_ || visibility.kind == Visibility.Kind.export_) && !this.isNaked()); } bool addPostInvariant() { auto ad = isThis(); - ClassDeclaration cd = ad ? ad.isClassDeclaration() : null; - return (ad && !(cd && cd.isCPPclass()) && ad.inv && global.params.useInvariants == CHECKENABLE.on && (visibility.kind == Visibility.Kind.protected_ || visibility.kind == Visibility.Kind.public_ || visibility.kind == Visibility.Kind.export_) && !this.isNaked()); + return (ad && ad.inv && global.params.useInvariants == CHECKENABLE.on && (visibility.kind == Visibility.Kind.protected_ || visibility.kind == Visibility.Kind.public_ || visibility.kind == Visibility.Kind.export_) && !this.isNaked()); } override const(char)* kind() const diff --git a/tests/dmd/runnable/testinvariant.d b/tests/dmd/runnable/testinvariant.d index 0ce8557191..11b8829b9f 100644 --- a/tests/dmd/runnable/testinvariant.d +++ b/tests/dmd/runnable/testinvariant.d @@ -228,8 +228,52 @@ void test16384() assert(s == "needs to be thrown2"); } - /***************************************************/ +// Fix: https://github.com/dlang/dmd/issues/20924 (invariant not called on extern(C++) classes) + +extern(C++) class C +{ + invariant { assert(0); } + void f() {} +} + +extern(D) class D +{ + invariant { assert(0); } + void f() {} +} + +void test20924() +{ + import core.exception : AssertError; + // Test extern(C++) class invariant + try + { + auto c = new C(); + c.f(); // Trigger invariant + assert(false, "Failed: invariant in extern(C++) class not checked"); + } + catch (AssertError e) + { + // Expected behavior - invariant was checked + return; + } + assert(0, "Invariant in extern(C++) class was not checked"); + + // Test extern(D) class invariant + try + { + auto d = new D(); + d.f(); // Trigger invariant + assert(false, "Failed: invariant in extern(D) class not checked"); + } + catch (AssertError e) + { + // Expected behavior - invariant was checked + return; + } + assert(0, "Invariant in extern(D) class was not checked"); +} void main() { @@ -238,4 +282,5 @@ void main() test16384(); test13113(); test13147(); + test20924(); } From 0f7e85c6dc6b824b26d5c9a9df8b0f6fd1ce1c86 Mon Sep 17 00:00:00 2001 From: Abul Hossain Khan <140191921+abulgit@users.noreply.github.com> Date: Fri, 14 Mar 2025 16:39:40 +0530 Subject: [PATCH 006/113] Fix dlang/dmd!20318 Compiler should explain why implicit conversion to mutable fails (dlang/dmd!20984) --- dmd/dcast.d | 18 ++++++++++ tests/dmd/fail_compilation/fix20318.d | 46 +++++++++++++++++++++++++ tests/dmd/fail_compilation/union_conv.d | 2 +- 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/fail_compilation/fix20318.d diff --git a/dmd/dcast.d b/dmd/dcast.d index ff987a3e25..39559eb0ff 100644 --- a/dmd/dcast.d +++ b/dmd/dcast.d @@ -149,6 +149,24 @@ 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); + + // 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) + { + auto sym = e.type.isTypeStruct().sym; + sym.determineTypeProperties(); + if (sym.hasPointerField) + { + const char* typeStr = sym.isUnionDeclaration() ? "union" : "struct"; + 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], typeStr, sym.toChars()); + return ErrorExp.get(); + } + } + error(e.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", e.toErrMsg(), ts[0], ts[1]); } diff --git a/tests/dmd/fail_compilation/fix20318.d b/tests/dmd/fail_compilation/fix20318.d new file mode 100644 index 0000000000..f320300012 --- /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/union_conv.d b/tests/dmd/fail_compilation/union_conv.d index f08809c485..134da36ecd 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 --- */ From 5730e234d276dc23a09a9cb21c120f0a91da3a71 Mon Sep 17 00:00:00 2001 From: Dennis Date: Sat, 15 Mar 2025 09:23:37 +0100 Subject: [PATCH 007/113] Reset global Loc table in initDMD (dlang/dmd!20995) --- dmd/location.d | 18 ++++++++++++++---- dmd/main.d | 1 + 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/dmd/location.d b/dmd/location.d index 403e155dc6..a26c0ecc8d 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: @@ -272,9 +281,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) @@ -286,7 +293,7 @@ private size_t fileTableIndex(uint index) nothrow @nogc i--; } - lastI = i; + lastFileTableIndex = i; return i; } @@ -459,3 +466,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 2d77d72575..2ad7e003b3 100644 --- a/dmd/main.d +++ b/dmd/main.d @@ -376,6 +376,7 @@ private int tryMain(size_t argc, const(char)** argv, ref Param params) Module._init(); Expression._init(); Objc._init(); + Loc._init(); reconcileLinkRunLib(params, files.length, target.obj_ext); version(CRuntime_Microsoft) From ec3a53498a829f3a4be8459be103f1e3d4fd852c Mon Sep 17 00:00:00 2001 From: Dennis Date: Sun, 16 Mar 2025 00:57:51 +0100 Subject: [PATCH 008/113] Improve Fix dlang/dmd!20318 Compiler should explain why implicit conversion to mutable fails (dlang/dmd!21003) --- dmd/dcast.d | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/dmd/dcast.d b/dmd/dcast.d index 39559eb0ff..829b4f1db1 100644 --- a/dmd/dcast.d +++ b/dmd/dcast.d @@ -154,17 +154,12 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t) // 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.mod == MODFlags.const_ && t.mod == 0 && e.type.hasPointers) { auto sym = e.type.isTypeStruct().sym; - sym.determineTypeProperties(); - if (sym.hasPointerField) - { - const char* typeStr = sym.isUnionDeclaration() ? "union" : "struct"; - 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], typeStr, sym.toChars()); - return ErrorExp.get(); - } + 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(); } error(e.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", From d5b8de8394e10a87c4635cc6778181a92ee52e7e Mon Sep 17 00:00:00 2001 From: Abul Hossain Khan <140191921+abulgit@users.noreply.github.com> Date: Sun, 16 Mar 2025 05:30:27 +0530 Subject: [PATCH 009/113] Fix dlang/dmd!20075 - Improve error message for immutable constructor type mismatch (dlang/dmd!20990) --- dmd/funcsem.d | 10 +++++++-- tests/dmd/fail_compilation/fix20075.d | 21 +++++++++++++++++++ tests/dmd/fail_compilation/testrvaluecpctor.d | 2 +- 3 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 tests/dmd/fail_compilation/fix20075.d diff --git a/dmd/funcsem.d b/dmd/funcsem.d index 269a2000bf..e70cffb321 100644 --- a/dmd/funcsem.d +++ b/dmd/funcsem.d @@ -1713,8 +1713,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()); diff --git a/tests/dmd/fail_compilation/fix20075.d b/tests/dmd/fail_compilation/fix20075.d new file mode 100644 index 0000000000..00f229d326 --- /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/testrvaluecpctor.d b/tests/dmd/fail_compilation/testrvaluecpctor.d index 1173d14480..a0ade760fe 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)` --- From 3e6745c0d95aab129f4fe099c994f1d7672445f5 Mon Sep 17 00:00:00 2001 From: Paul Backus Date: Sun, 16 Mar 2025 20:31:39 -0400 Subject: [PATCH 010/113] Don't parse lambda as UDA without parentheses (dlang/dmd!21009) This brings the compiler's behavior in line with the language spec. Fixes dlang/dlang.org#4137 --- dmd/parse.d | 16 +++++++++++++++- tests/dmd/compilable/uda_lambda.d | 3 +++ tests/dmd/fail_compilation/uda_lambda.d | 7 +++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/compilable/uda_lambda.d create mode 100644 tests/dmd/fail_compilation/uda_lambda.d diff --git a/dmd/parse.d b/dmd/parse.d index 3d25464fc5..33f2a1e116 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -1319,7 +1319,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; diff --git a/tests/dmd/compilable/uda_lambda.d b/tests/dmd/compilable/uda_lambda.d new file mode 100644 index 0000000000..df331747a7 --- /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/fail_compilation/uda_lambda.d b/tests/dmd/fail_compilation/uda_lambda.d new file mode 100644 index 0000000000..bd3ff49e0e --- /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; From 889d65510b3be12ff69c08d8a8baefe930ecce55 Mon Sep 17 00:00:00 2001 From: Abul Hossain Khan <140191921+abulgit@users.noreply.github.com> Date: Tue, 18 Mar 2025 05:58:57 +0530 Subject: [PATCH 011/113] Fix : Improved error message on override mismatch (dlang/dmd!21023) --- dmd/funcsem.d | 37 ++++++++++++++++++++++++++ tests/dmd/fail_compilation/test20489.d | 20 ++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 tests/dmd/fail_compilation/test20489.d diff --git a/dmd/funcsem.d b/dmd/funcsem.d index e70cffb321..71d3dfa5f0 100644 --- a/dmd/funcsem.d +++ b/dmd/funcsem.d @@ -983,6 +983,43 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl) error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?", funcdeclToChars, buf1.peekChars()); + + // Supplemental error for parameter scope differences + auto tf1 = cast(TypeFunction)funcdecl.type; + auto tf2 = cast(TypeFunction)fd.type; + + if (tf1 && tf2) + { + auto params1 = tf1.parameterList; + auto params2 = tf2.parameterList; + + if (params1.length == params2.length) + { + bool hasScopeDifference = false; + + for (size_t i = 0; i < params1.length; i++) + { + auto p1 = params1[i]; + auto p2 = params2[i]; + + if ((p1.storageClass & STC.scope_) == (p2.storageClass & STC.scope_)) + continue; + + if (!(p2.storageClass & STC.scope_)) + continue; + + 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)); + } + } + } } } else diff --git a/tests/dmd/fail_compilation/test20489.d b/tests/dmd/fail_compilation/test20489.d new file mode 100644 index 0000000000..1cd5350959 --- /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; } +} From 208cd2351f8d1290d49da668215d8b3493cd3042 Mon Sep 17 00:00:00 2001 From: Shivang Shukla Date: Tue, 18 Mar 2025 14:09:32 +0530 Subject: [PATCH 012/113] Refactor: Remove Unused Hooks in dinterpret.d (dlang/dmd!21022) - Removed references to _d_arrayappendcTX, _d_newThrowable, and _d_arrayappendT. - Ensured test cases pass after deletion. - Left _d_arrayctor and _d_arraysetctor untouched for future semantic phase changes. --- dmd/dinterpret.d | 61 ------------------------------------------------ 1 file changed, 61 deletions(-) diff --git a/dmd/dinterpret.d b/dmd/dinterpret.d index 17c5b649a7..641e8a0420 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)) @@ -5001,61 +4995,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; From 9fc5bad6376cdeb076410d0ad5f1849b6f5b5179 Mon Sep 17 00:00:00 2001 From: Dennis Date: Tue, 18 Mar 2025 14:54:40 +0100 Subject: [PATCH 013/113] Move ImportC enum semantic to importc.d (dlang/dmd!21027) Co-authored-by: Dennis Korpel --- dmd/enumsem.d | 109 +---------------------------------------------- dmd/importc.d | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 107 deletions(-) diff --git a/dmd/enumsem.d b/dmd/enumsem.d index 30dfeb3450..842c79e576 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) { @@ -229,112 +229,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) { diff --git a/dmd/importc.d b/dmd/importc.d index 6a85e96841..2e0060b41c 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; @@ -638,3 +644,113 @@ 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; + ed.semanticRun = PASS.semanticdone; + return; +} From 915ec9d668018a3eb8968c4ea45590bb3f90ab97 Mon Sep 17 00:00:00 2001 From: Abul Hossain Khan <140191921+abulgit@users.noreply.github.com> Date: Thu, 20 Mar 2025 21:13:37 +0530 Subject: [PATCH 014/113] Fix: Prevent ICE on final switch forward referencing its enum (dlang/dmd!21001) * Fix: Prevent ICE on final switch forward referencing its enum * more simpler approach * moved the enum member analysis * Move enum number analysis to sementic2 * WhiteSpace Remove * Remove Redundant Code in enumsem --- dmd/enumsem.d | 4 ++++ dmd/statementsem.d | 10 ++++++++++ tests/dmd/fail_compilation/fix20867.d | 20 ++++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 tests/dmd/fail_compilation/fix20867.d diff --git a/dmd/enumsem.d b/dmd/enumsem.d index 842c79e576..fe9f38266f 100644 --- a/dmd/enumsem.d +++ b/dmd/enumsem.d @@ -240,6 +240,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) diff --git a/dmd/statementsem.d b/dmd/statementsem.d index 04d0b40265..19b4b043eb 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -1959,6 +1959,16 @@ Statement statementSemanticVisit(Statement s, Scope* sc) ed = ds.isEnumDeclaration(); // typedef'ed enum if (!ed && te && ((ds = te.toDsymbol(sc)) !is null)) ed = ds.isEnumDeclaration(); + + // Circular references + // Check if enum semantic analysis is not yet complete + if (ed && ed.semanticRun < PASS.semantic2done) + { + error(ss.loc, "cannot use `final switch` on enum `%s` while it is being defined", ed.toChars()); + sc.pop(); + return setError(); + } + if (ed && ss.cases.length < ed.members.length) { int missingMembers = 0; diff --git a/tests/dmd/fail_compilation/fix20867.d b/tests/dmd/fail_compilation/fix20867.d new file mode 100644 index 0000000000..0ccad09803 --- /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; + } () +} From 99d1d3784358d00937dfca90cf2f1e228daf94b1 Mon Sep 17 00:00:00 2001 From: Dennis Date: Fri, 21 Mar 2025 15:48:21 +0100 Subject: [PATCH 015/113] Merge stable (dlang/dmd!21048) * bump VERSION to v2.110.0 * purge changelog * bump VERSION to v2.111.0-beta.1 * Accept __rvalue attribute on ref functions; which will force the result to be treated as __rvalue. (dlang/dmd!20946) This is essential to implement `move`, `forward`, etc. * memoryerror.d: Fix AnySupported version condition (dlang/dmd!20983) * Fix dlang/dmd!20982 - wrong line number in iasmgcc (dlang/dmd!20993) * Move genCfunc to cxxfrontend (dlang/dmd!20992) * druntime: Fix compilation of rt.cover on Android (dlang/dmd!21015) * Expose SourceLoc to C++ interface (dlang/dmd!20980) * [stable] C++ header fixes for declaration, expression, and typinf (dlang/dmd!21016) Seen either from compilation errors or missing symbols at link time. * C++ headers: Add 3 Declaration bitfield setters/getters required by LDC * druntime: Add module declaration to rt.invariant, to prevent conflicts with user-provided invariant.d (dlang/dmd!21017) * Fix dlang/dmd!21020 - Indexing a *cast* AA yields no lvalue anymore (dlang/dmd!21029) * Add C++23 to CppStdRevision enum (dlang/dmd!21043) * Improve UFCS/property error message (dlang/dmd!21046) --------- Co-authored-by: Manu Evans Co-authored-by: Martin Kinkelin Co-authored-by: Iain Buclaw Co-authored-by: Martin Kinkelin --- dmd/cli.d | 3 ++ dmd/cxxfrontend.d | 26 ++++++++++++++ dmd/declaration.h | 9 +++-- dmd/expression.d | 1 + dmd/expression.h | 1 + dmd/frontend.h | 22 ++++++++++-- dmd/func.d | 4 +-- dmd/globals.d | 1 + dmd/globals.h | 12 ++++++- dmd/iasmgcc.d | 3 +- dmd/location.d | 8 ++++- dmd/mars.d | 3 ++ dmd/typesem.d | 14 ++++++-- dmd/typinf.h | 4 +++ runtime/druntime/Makefile | 2 +- runtime/druntime/src/core/stdcpp/xutility.d | 1 + runtime/druntime/src/etc/linux/memoryerror.d | 2 +- runtime/druntime/src/rt/cover.d | 5 ++- .../src/rt/{invariant.d => invariant_.d} | 9 ++--- tests/dmd/fail_compilation/fail347.d | 4 +-- tests/dmd/fail_compilation/ufcs.d | 36 +++++++++++-------- tests/dmd/runnable/test21020.d | 11 ++++++ 22 files changed, 141 insertions(+), 40 deletions(-) rename runtime/druntime/src/rt/{invariant.d => invariant_.d} (70%) create mode 100644 tests/dmd/runnable/test21020.d diff --git a/dmd/cli.d b/dmd/cli.d index 861d5a4f22..771f1be6d0 100644 --- a/dmd/cli.d +++ b/dmd/cli.d @@ -359,6 +359,8 @@ dmd -cov -unittest myprog.d Sets `__traits(getTargetInfo, \"cppStd\")` to `201703`) $(LI $(I c++20): Use C++20 name mangling, Sets `__traits(getTargetInfo, \"cppStd\")` to `202002`) + $(LI $(I c++23): Use C++23 name mangling, + Sets `__traits(getTargetInfo, \"cppStd\")` to `202302`) )", ), Option("extern-std=[h|help|?]", @@ -1122,6 +1124,7 @@ struct CLIUsage =c++14 Sets `__traits(getTargetInfo, \"cppStd\")` to `201402` =c++17 Sets `__traits(getTargetInfo, \"cppStd\")` to `201703` =c++20 Sets `__traits(getTargetInfo, \"cppStd\")` to `202002` + =c++23 Sets `__traits(getTargetInfo, \"cppStd\")` to `202302` "; /// Options supported by -HC diff --git a/dmd/cxxfrontend.d b/dmd/cxxfrontend.d index 8c6df58d9e..b3d5942696 100644 --- a/dmd/cxxfrontend.d +++ b/dmd/cxxfrontend.d @@ -16,6 +16,7 @@ import dmd.astenums; import dmd.attrib; import dmd.common.outbuffer : OutBuffer; import dmd.dclass : ClassDeclaration; +import dmd.declaration : TypeInfoDeclaration; import dmd.denum : EnumDeclaration; import dmd.dmodule /*: Module*/; import dmd.dscope : Scope; @@ -276,6 +277,19 @@ bool fill(StructDeclaration sd, Loc loc, return dmd.expressionsem.fill(sd, loc, elements, ctorinit); } +/*********************************************************** + * func.d + */ +FuncDeclaration genCfunc(Parameters* fparams, Type treturn, const(char)* name, StorageClass stc = STC.none) +{ + return FuncDeclaration.genCfunc(fparams, treturn, name, cast(STC) stc); +} + +FuncDeclaration genCfunc(Parameters* fparams, Type treturn, Identifier id, StorageClass stc = STC.none) +{ + return FuncDeclaration.genCfunc(fparams, treturn, id, cast(STC) stc); +} + /*********************************************************** * funcsem.d */ @@ -715,6 +729,18 @@ bool builtinTypeInfo(Type t) return dmd.typinf.builtinTypeInfo(t); } +Type makeNakedAssociativeArray(TypeAArray t) +{ + import dmd.typinf; + return dmd.typinf.makeNakedAssociativeArray(t); +} + +TypeInfoDeclaration getTypeInfoAssocArrayDeclaration(TypeAArray t, Scope* sc) +{ + import dmd.typinf; + return dmd.typinf.getTypeInfoAssocArrayDeclaration(t, sc); +} + version (IN_LLVM) { /*********************************************************** diff --git a/dmd/declaration.h b/dmd/declaration.h index 63fdc9b69a..c7e4552608 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -37,6 +37,8 @@ namespace dmd bool checkClosure(FuncDeclaration* fd); MATCH leastAsSpecialized(FuncDeclaration *f, FuncDeclaration *g, Identifiers *names); PURE isPure(FuncDeclaration *f); + FuncDeclaration *genCfunc(Parameters *args, Type *treturn, const char *name, StorageClass stc=0); + FuncDeclaration *genCfunc(Parameters *args, Type *treturn, Identifier *id, StorageClass stc=0); } //enum STC : ulong from astenums.d: @@ -126,6 +128,10 @@ class Declaration : public Dsymbol short inuse; // used to detect cycles uint8_t bitFields; + LINK _linkage() const; + LINK _linkage(LINK v); + bool noUnderscore() const; + const char *kind() const override; uinteger_t size(Loc loc) override final; @@ -726,9 +732,6 @@ class FuncDeclaration : public Declaration bool hasNestedFrameRefs(); ParameterList getParameterList(); - static FuncDeclaration *genCfunc(Parameters *args, Type *treturn, const char *name, StorageClass stc=0); - static FuncDeclaration *genCfunc(Parameters *args, Type *treturn, Identifier *id, StorageClass stc=0); - virtual FuncDeclaration *toAliasFunc() { return this; } void accept(Visitor *v) override { v->visit(this); } }; diff --git a/dmd/expression.d b/dmd/expression.d index ef5c0b09eb..4bf1f9f25f 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -3632,6 +3632,7 @@ extern (C++) final class CastExp : UnaExp if (rvalue || !e1.isLvalue()) return false; return (to.ty == Tsarray && (e1.type.ty == Tvector || e1.type.ty == Tsarray)) || + (to.ty == Taarray && e1.type.ty == Taarray) || e1.type.mutableOf.unSharedOf().equals(to.mutableOf().unSharedOf()); } diff --git a/dmd/expression.h b/dmd/expression.h index 64acb8d2ad..3c8d90dd7e 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -40,6 +40,7 @@ class OverloadSet; class StringExp; class InterpExp; class LoweredAssignExp; +class StaticForeach; #ifdef IN_GCC typedef union tree_node Symbol; #else diff --git a/dmd/frontend.h b/dmd/frontend.h index 9e07b7236f..49b57c1592 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -377,6 +377,22 @@ enum class MessageStyle : uint8_t sarif = 2u, }; +struct SourceLoc final +{ + _d_dynamicArray< const char > filename; + uint32_t line; + uint32_t column; + uint32_t fileOffset; + const char* toChars(bool showColumns = Loc::showColumns, MessageStyle messageStyle = Loc::messageStyle) const; + SourceLoc() : + filename(), + line(), + column(), + fileOffset() + { + } +}; + struct Loc final { private: @@ -390,7 +406,8 @@ struct Loc final uint32_t linnum() const; const char* filename() const; const char* toChars(bool showColumns = Loc::showColumns, MessageStyle messageStyle = Loc::messageStyle) const; - bool equals(const Loc& loc) const; + SourceLoc toSourceLoc() const; + bool equals(Loc loc) const; Loc() : index(0u) { @@ -4052,8 +4069,6 @@ class FuncDeclaration : public Declaration bool needsClosure(); bool hasNestedFrameRefs(); ParameterList getParameterList(); - static FuncDeclaration* genCfunc(Array* fparams, Type* treturn, const char* name, STC stc = (STC)0LLU); - static FuncDeclaration* genCfunc(Array* fparams, Type* treturn, Identifier* id, STC stc = (STC)0LLU); virtual FuncDeclaration* toAliasFunc(); void accept(Visitor* v) override; }; @@ -6219,6 +6234,7 @@ enum class CppStdRevision : uint32_t cpp14 = 201402u, cpp17 = 201703u, cpp20 = 202002u, + cpp23 = 202302u, }; enum class CHECKENABLE : uint8_t diff --git a/dmd/func.d b/dmd/func.d index 88e7aeea95..50479f78c8 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -1004,12 +1004,12 @@ extern (C++) class FuncDeclaration : Declaration /********************************** * Generate a FuncDeclaration for a runtime library function. */ - static FuncDeclaration genCfunc(Parameters* fparams, Type treturn, const(char)* name, STC stc = STC.none) + extern(D) static FuncDeclaration genCfunc(Parameters* fparams, Type treturn, const(char)* name, STC stc = STC.none) { return genCfunc(fparams, treturn, Identifier.idPool(name[0 .. strlen(name)]), stc); } - static FuncDeclaration genCfunc(Parameters* fparams, Type treturn, Identifier id, STC stc = STC.none) + extern(D) static FuncDeclaration genCfunc(Parameters* fparams, Type treturn, Identifier id, STC stc = STC.none) { FuncDeclaration fd; TypeFunction tf; diff --git a/dmd/globals.d b/dmd/globals.d index 4a637b519c..900c554e5f 100644 --- a/dmd/globals.d +++ b/dmd/globals.d @@ -62,6 +62,7 @@ enum CppStdRevision : uint cpp14 = 2014_02, cpp17 = 2017_03, cpp20 = 2020_02, + cpp23 = 2023_02, } /// Trivalent boolean to represent the state of a `revert`able change diff --git a/dmd/globals.h b/dmd/globals.h index 3e2de5cdf8..69fe709f4b 100644 --- a/dmd/globals.h +++ b/dmd/globals.h @@ -73,7 +73,8 @@ enum CppStdRevision CppStdRevisionCpp11 = 201103, CppStdRevisionCpp14 = 201402, CppStdRevisionCpp17 = 201703, - CppStdRevisionCpp20 = 202002 + CppStdRevisionCpp20 = 202002, + CppStdRevisionCpp23 = 202302, }; /// Trivalent boolean to represent the state of a `revert`able change @@ -413,6 +414,14 @@ typedef unsigned long long uinteger_t; #endif // file location +struct SourceLoc +{ + DString filename; + uint32_t line; + uint32_t column; + uint32_t fileOffset; +}; + struct Loc { private: @@ -438,6 +447,7 @@ struct Loc uint32_t charnum() const; uint32_t linnum() const; const char *filename() const; + SourceLoc toSourceLoc() const; const char *toChars( bool showColumns = Loc::showColumns, diff --git a/dmd/iasmgcc.d b/dmd/iasmgcc.d index f338ccc8de..f8ebf8fbbb 100644 --- a/dmd/iasmgcc.d +++ b/dmd/iasmgcc.d @@ -55,7 +55,8 @@ public Statement gccAsmSemantic(GccAsmStatement s, Scope* sc) *ptoklist = null; } p.token = *toklist; - p.scanloc = s.loc; + p.baseLoc.startLine = s.loc.linnum; + p.linnum = s.loc.linnum; // Parse the gcc asm statement. const errors = global.errors; diff --git a/dmd/location.d b/dmd/location.d index a26c0ecc8d..7a579b278f 100644 --- a/dmd/location.d +++ b/dmd/location.d @@ -133,6 +133,12 @@ nothrow: return this.index - locFileTable[i].startIndex; } + /// Returns: this location as a SourceLoc + extern (C++) SourceLoc toSourceLoc() const @nogc @safe + { + return SourceLoc(this); + } + /** * Checks for equivalence by comparing the filename contents (not the pointer) and character location. * @@ -140,7 +146,7 @@ nothrow: * - Uses case-insensitive comparison on Windows * - Ignores `charnum` if `Columns` is false. */ - extern (C++) bool equals(ref const(Loc) loc) const + extern (C++) bool equals(Loc loc) const { SourceLoc lhs = SourceLoc(this); SourceLoc rhs = SourceLoc(loc); diff --git a/dmd/mars.d b/dmd/mars.d index 1b499a47c1..17d6965f53 100644 --- a/dmd/mars.d +++ b/dmd/mars.d @@ -1143,6 +1143,9 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param case "c++20": params.cplusplus = CppStdRevision.cpp20; break; + case "c++23": + params.cplusplus = CppStdRevision.cpp23; + break; default: error("switch `%s` is invalid", p); params.help.externStd = true; diff --git a/dmd/typesem.d b/dmd/typesem.d index 65bad387ef..c5a3b83379 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -3444,8 +3444,16 @@ Expression getProperty(Type t, Scope* scope_, Loc loc, Identifier ident, int fla auto s2 = scope_.search_correct(ident); // UFCS if (s2 && s2.isFuncDeclaration) - errorSupplemental(loc, "did you mean %s `%s`?", - s2.kind(), s2.toChars()); + { + 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()); + } + else + errorSupplemental(s2.loc, "did you mean %s `%s`?", + s2.kind(), s2.toChars()); + } else if (src.type.ty == Tpointer) { // structPtr.field @@ -3454,7 +3462,7 @@ Expression getProperty(Type t, Scope* scope_, Loc loc, Identifier ident, int fla { if (auto s3 = as.search_correct(ident)) { - errorSupplemental(loc, "did you mean %s `%s`?", + errorSupplemental(s3.loc, "did you mean %s `%s`?", s3.kind(), s3.toChars()); } } diff --git a/dmd/typinf.h b/dmd/typinf.h index ea42538573..c34494da2f 100644 --- a/dmd/typinf.h +++ b/dmd/typinf.h @@ -14,6 +14,8 @@ class Expression; class Type; +class TypeAArray; +class TypeInfoDeclaration; struct Scope; namespace dmd @@ -21,5 +23,7 @@ namespace dmd bool genTypeInfo(Expression *e, Loc loc, Type *torig, Scope *sc); bool isSpeculativeType(Type *t); bool builtinTypeInfo(Type *t); + Type *makeNakedAssociativeArray(TypeAArray *t); + TypeInfoDeclaration *getTypeInfoAssocArrayDeclaration(TypeAArray *t, Scope *sc); } Type *getTypeInfoType(Loc loc, Type *t, Scope *sc); diff --git a/runtime/druntime/Makefile b/runtime/druntime/Makefile index 2efde5c940..2c022c6997 100644 --- a/runtime/druntime/Makefile +++ b/runtime/druntime/Makefile @@ -479,7 +479,7 @@ TESTS_EXTRACTOR=$(ROOT)/tests_extractor$(DOTEXE) BETTERCTESTS_DIR=$(ROOT)/betterctests # macro that returns the module name given the src path -moduleName=$(subst rt.invariant,invariant,$(subst object_,object,$(subst /,.,$(1)))) +moduleName=$(subst /,.,$(1)) $(ROOT)/unittest/% : $(ROOT)/unittest/test_runner$(DOTEXE) @mkdir -p $(dir $@) diff --git a/runtime/druntime/src/core/stdcpp/xutility.d b/runtime/druntime/src/core/stdcpp/xutility.d index 5e2e711ba6..f93df68deb 100644 --- a/runtime/druntime/src/core/stdcpp/xutility.d +++ b/runtime/druntime/src/core/stdcpp/xutility.d @@ -35,6 +35,7 @@ enum CppStdRevision : uint cpp14 = 201402, cpp17 = 201703, cpp20 = 202002, + cpp23 = 202302, } /** diff --git a/runtime/druntime/src/etc/linux/memoryerror.d b/runtime/druntime/src/etc/linux/memoryerror.d index 31e1d83796..b44a7f6d68 100644 --- a/runtime/druntime/src/etc/linux/memoryerror.d +++ b/runtime/druntime/src/etc/linux/memoryerror.d @@ -40,7 +40,7 @@ version (linux) version (MemoryErrorSupported) version = AnySupported; -else version (MemoryErrorSupported) +else version (MemoryAssertSupported) version = AnySupported; version (AnySupported): diff --git a/runtime/druntime/src/rt/cover.d b/runtime/druntime/src/rt/cover.d index 7bc5ffbf11..0b1902104c 100644 --- a/runtime/druntime/src/rt/cover.d +++ b/runtime/druntime/src/rt/cover.d @@ -27,7 +27,7 @@ else version (Posix) { import core.stdc.stdio : fopen; import core.sys.posix.fcntl : O_CREAT, O_RDWR, open, S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR; - import core.sys.posix.unistd : F_LOCK, ftruncate, lockf; + import core.sys.posix.unistd : ftruncate; } else static assert(0, "Unsupported platform"); @@ -487,7 +487,10 @@ void lockFile(int fd) flock(fd, LOCK_EX); // exclusive lock } else version (Posix) + { + import core.sys.posix.unistd : F_LOCK, lockf; lockf(fd, F_LOCK, 0); // exclusive lock + } else version (Windows) { OVERLAPPED off; diff --git a/runtime/druntime/src/rt/invariant.d b/runtime/druntime/src/rt/invariant_.d similarity index 70% rename from runtime/druntime/src/rt/invariant.d rename to runtime/druntime/src/rt/invariant_.d index e536196e8c..2a64dc89da 100644 --- a/runtime/druntime/src/rt/invariant.d +++ b/runtime/druntime/src/rt/invariant_.d @@ -4,15 +4,10 @@ * Copyright: Copyright Digital Mars 2007 - 2010. * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). * Authors: Walter Bright - * Source: $(DRUNTIMESRC rt/_invariant.d) - */ - -/* Copyright Digital Mars 2007 - 2010. - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE or copy at - * http://www.boost.org/LICENSE_1_0.txt) + * Source: $(DRUNTIMESRC rt/_invariant_.d) */ +module rt.invariant_; /** * diff --git a/tests/dmd/fail_compilation/fail347.d b/tests/dmd/fail_compilation/fail347.d index e495ba257e..c56acf5642 100644 --- a/tests/dmd/fail_compilation/fail347.d +++ b/tests/dmd/fail_compilation/fail347.d @@ -5,10 +5,10 @@ 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(29): did you mean variable `foo`? +fail_compilation/fail347.d(20): did you mean variable `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/fail347.d(31): did you mean function `strlen`? +fail_compilation/imports/fail347a.d(3): did you mean function `strlen`? --- */ diff --git a/tests/dmd/fail_compilation/ufcs.d b/tests/dmd/fail_compilation/ufcs.d index 3a92a691e2..87efbcf65c 100644 --- a/tests/dmd/fail_compilation/ufcs.d +++ b/tests/dmd/fail_compilation/ufcs.d @@ -1,23 +1,28 @@ /* TEST_OUTPUT: --- -fail_compilation/ufcs.d(26): Error: no property `regularF` for `s` of type `S` -fail_compilation/ufcs.d(26): the following error occured while looking for a UFCS match -fail_compilation/ufcs.d(26): Error: function `regularF` is not callable using argument types `(S)` -fail_compilation/ufcs.d(26): expected 0 argument(s), not 1 -fail_compilation/ufcs.d(31): `ufcs.regularF()` declared here -fail_compilation/ufcs.d(27): Error: no property `templateF` for `s` of type `S` -fail_compilation/ufcs.d(27): the following error occured while looking for a UFCS match -fail_compilation/ufcs.d(27): Error: template `templateF` is not callable using argument types `!()(S)` -fail_compilation/ufcs.d(32): Candidate is: `templateF()()` -fail_compilation/ufcs.d(28): Error: no property `templateO` for `s` of type `S` -fail_compilation/ufcs.d(28): the following error occured while looking for a UFCS match -fail_compilation/ufcs.d(28): Error: none of the overloads of template `ufcs.templateO` are callable using argument types `!()(S)` -fail_compilation/ufcs.d(34): Candidates are: `templateO()(int x)` -fail_compilation/ufcs.d(35): `templateO()(float y)` +fail_compilation/ufcs.d(31): Error: no property `regularF` for `s` of type `S` +fail_compilation/ufcs.d(31): the following error occured while looking for a UFCS match +fail_compilation/ufcs.d(31): Error: function `regularF` is not callable using argument types `(S)` +fail_compilation/ufcs.d(31): expected 0 argument(s), not 1 +fail_compilation/ufcs.d(39): `ufcs.regularF()` declared here +fail_compilation/ufcs.d(32): Error: no property `templateF` for `s` of type `S` +fail_compilation/ufcs.d(32): the following error occured while looking for a UFCS match +fail_compilation/ufcs.d(32): Error: template `templateF` is not callable using argument types `!()(S)` +fail_compilation/ufcs.d(40): Candidate is: `templateF()()` +fail_compilation/ufcs.d(33): Error: no property `templateO` for `s` of type `S` +fail_compilation/ufcs.d(33): the following error occured while looking for a UFCS match +fail_compilation/ufcs.d(33): Error: none of the overloads of template `ufcs.templateO` are callable using argument types `!()(S)` +fail_compilation/ufcs.d(42): Candidates are: `templateO()(int x)` +fail_compilation/ufcs.d(43): `templateO()(float y)` +fail_compilation/ufcs.d(36): Error: no property `local` for `s` of type `ufcs.S` +fail_compilation/ufcs.d(35): cannot call function `local` with UFCS because it is not declared at module scope +fail_compilation/ufcs.d(26): struct `S` defined here --- */ + + struct S { } void f() @@ -26,6 +31,9 @@ void f() s.regularF(); s.templateF(); s.templateO(); + + void local(S) {} + s.local(); } void regularF(); diff --git a/tests/dmd/runnable/test21020.d b/tests/dmd/runnable/test21020.d new file mode 100644 index 0000000000..484db30a56 --- /dev/null +++ b/tests/dmd/runnable/test21020.d @@ -0,0 +1,11 @@ +// https://github.com/dlang/dmd/issues/21020 + +shared struct Queue { + int[int] map; +} + +void main() { + auto queue = Queue(); + (cast(int[int]) queue.map)[1] = 2; + assert(queue.map[1] == 2); +} From db58c84a4bf016fc9323b05a06cf7914745335f4 Mon Sep 17 00:00:00 2001 From: Dennis Date: Fri, 21 Mar 2025 23:36:00 +0100 Subject: [PATCH 016/113] Remove redundant GC allocation for _d_newarraymTX.dims (dlang/dmd!21051) --- runtime/druntime/src/core/internal/array/construction.d | 4 ++-- runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp | 2 -- runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp | 2 -- runtime/druntime/test/profile/myprofilegc.log.linux.32.exp | 2 -- runtime/druntime/test/profile/myprofilegc.log.linux.64.exp | 2 -- runtime/druntime/test/profile/myprofilegc.log.osx.32.exp | 2 -- runtime/druntime/test/profile/myprofilegc.log.osx.64.exp | 2 -- runtime/druntime/test/profile/myprofilegc.log.windows.32.exp | 2 -- runtime/druntime/test/profile/myprofilegc.log.windows.64.exp | 2 -- 9 files changed, 2 insertions(+), 18 deletions(-) diff --git a/runtime/druntime/src/core/internal/array/construction.d b/runtime/druntime/src/core/internal/array/construction.d index 40e5a61bbd..722aed46d1 100644 --- a/runtime/druntime/src/core/internal/array/construction.d +++ b/runtime/druntime/src/core/internal/array/construction.d @@ -505,7 +505,7 @@ version (D_ProfileGC) * Returns: * newly allocated array */ -Tarr _d_newarraymTX(Tarr : U[], T, U)(size_t[] dims, bool isShared=false) @trusted +Tarr _d_newarraymTX(Tarr : U[], T, U)(scope size_t[] dims, bool isShared=false) @trusted { debug(PRINTF) printf("_d_newarraymTX(dims.length = %zd)\n", dims.length); @@ -602,7 +602,7 @@ version (D_ProfileGC) /** * TraceGC wrapper around $(REF _d_newarraymT, core,internal,array,construction). */ - Tarr _d_newarraymTXTrace(Tarr : U[], T, U)(size_t[] dims, bool isShared=false, string file = __FILE__, int line = __LINE__, string funcname = __FUNCTION__) @trusted + Tarr _d_newarraymTXTrace(Tarr : U[], T, U)(scope size_t[] dims, bool isShared=false, string file = __FILE__, int line = __LINE__, string funcname = __FUNCTION__) @trusted { version (D_TypeInfo) { diff --git a/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp b/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp index 0053d15aaa..c610fbdbd7 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 97c1aaa253..7cc4c6de66 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 2dc8e5ccf3..c610fbdbd7 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 97c1aaa253..7cc4c6de66 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 1cea04eced..e5db24779e 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 97c1aaa253..7cc4c6de66 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 cf29c52048..91cfedb358 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 631c404941..80fff94311 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 From 2c09d763402926e065cbe6f0bfa9f2e0b9c214a6 Mon Sep 17 00:00:00 2001 From: Dennis Date: Sat, 22 Mar 2025 00:40:34 +0100 Subject: [PATCH 017/113] Fix dlang/dmd!21052 - Missing @nogc check for enum variable initialization (dlang/dmd!21053) --- dmd/nogc.d | 2 +- tests/dmd/fail_compilation/nogc3.d | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/dmd/nogc.d b/dmd/nogc.d index 30e469da82..b1a7b5f034 100644 --- a/dmd/nogc.d +++ b/dmd/nogc.d @@ -119,7 +119,7 @@ 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; diff --git a/tests/dmd/fail_compilation/nogc3.d b/tests/dmd/fail_compilation/nogc3.d index 17daa96358..e7186c72bd 100644 --- a/tests/dmd/fail_compilation/nogc3.d +++ b/tests/dmd/fail_compilation/nogc3.d @@ -94,3 +94,20 @@ 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']; +} From d21a84286a92f7a5f9a1c77ec991c202f2625691 Mon Sep 17 00:00:00 2001 From: Dennis Date: Sat, 22 Mar 2025 09:26:49 +0100 Subject: [PATCH 018/113] Fix dlang/dmd!21054 - No location for array literal sliced from init symbol (dlang/dmd!21055) --- dmd/mtype.d | 2 +- tests/dmd/fail_compilation/nogc3.d | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/dmd/mtype.d b/dmd/mtype.d index 5ba866c9e5..52d8b77cd4 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -2234,7 +2234,7 @@ extern (C++) final class TypeSArray : TypeArray auto elements = new Expressions(d); foreach (ref e; *elements) e = null; - auto ae = new ArrayLiteralExp(Loc.initial, this, elementinit, elements); + auto ae = new ArrayLiteralExp(loc, this, elementinit, elements); return ae; } diff --git a/tests/dmd/fail_compilation/nogc3.d b/tests/dmd/fail_compilation/nogc3.d index e7186c72bd..f1a469b544 100644 --- a/tests/dmd/fail_compilation/nogc3.d +++ b/tests/dmd/fail_compilation/nogc3.d @@ -111,3 +111,16 @@ void f() @nogc 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[]; +} From c1f5ecedc30b73e5a98fff27cc757f2eb7f1ba44 Mon Sep 17 00:00:00 2001 From: Dennis Date: Sat, 22 Mar 2025 22:59:00 +0100 Subject: [PATCH 019/113] Require adjacent auto ref return as well (dlang/dmd!21061) --- dmd/funcsem.d | 12 +++++++++++- tests/dmd/fail_compilation/diag9679.d | 19 +++++++++++-------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/dmd/funcsem.d b/dmd/funcsem.d index 71d3dfa5f0..0a8a574c59 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) @@ -313,7 +324,6 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl) sc = sc.push(); sc.stc |= funcdecl.storage_class & (STC.disable | STC.deprecated_); // forward to function type - TypeFunction tf = funcdecl.type.toTypeFunction(); if (sc.func) { /* If the nesting parent is pure without inference, diff --git a/tests/dmd/fail_compilation/diag9679.d b/tests/dmd/fail_compilation/diag9679.d index 22e94e5759..50b8717adf 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; } From dd4dd902770fdc7a7bb1500681ad07e1b6d1550f Mon Sep 17 00:00:00 2001 From: Dennis Date: Sat, 22 Mar 2025 23:03:20 +0100 Subject: [PATCH 020/113] Use errorSupplemental for long errors with 2 sentences (dlang/dmd!21060) --- dmd/dinterpret.d | 3 ++- dmd/initsem.d | 5 ++++- dmd/optimize.d | 3 ++- dmd/parse.d | 6 ++++-- dmd/semantic2.d | 16 +++++++++++++--- tests/dmd/fail_compilation/fail11714.d | 6 ++++-- tests/dmd/fail_compilation/fail15361.d | 3 ++- tests/dmd/fail_compilation/fail16.d | 5 +++-- tests/dmd/fail_compilation/fail23439.d | 3 ++- tests/dmd/fail_compilation/failcontracts.d | 17 +++++++++-------- tests/dmd/fail_compilation/ice11153.d | 5 +++-- tests/dmd/fail_compilation/test15989.d | 8 +++++--- tests/dmd/fail_compilation/test19661.d | 3 ++- 13 files changed, 55 insertions(+), 28 deletions(-) diff --git a/dmd/dinterpret.d b/dmd/dinterpret.d index 641e8a0420..b223975f38 100644 --- a/dmd/dinterpret.d +++ b/dmd/dinterpret.d @@ -3183,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; } diff --git a/dmd/initsem.d b/dmd/initsem.d index d37c85ad46..8737e0f646 100644 --- a/dmd/initsem.d +++ b/dmd/initsem.d @@ -394,7 +394,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 { diff --git a/dmd/optimize.d b/dmd/optimize.d index 7f2b030e5b..2e40f1826c 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 33f2a1e116..f031777238 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -4081,7 +4081,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"); @@ -8468,7 +8469,8 @@ 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); diff --git a/dmd/semantic2.d b/dmd/semantic2.d index 4b410a17ca..a1bb7e895b 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/tests/dmd/fail_compilation/fail11714.d b/tests/dmd/fail_compilation/fail11714.d index abc47087ff..f36f3e5831 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 8e5f9800a8..aec716556a 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/fail16.d b/tests/dmd/fail_compilation/fail16.d index 4602d3de3b..ce021a95b8 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/fail23439.d b/tests/dmd/fail_compilation/fail23439.d index b070e581a4..6f16bc1343 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/failcontracts.d b/tests/dmd/fail_compilation/failcontracts.d index b6c3bc906a..749d98f9bd 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/ice11153.d b/tests/dmd/fail_compilation/ice11153.d index 826bd8cd7e..936d987c15 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/test15989.d b/tests/dmd/fail_compilation/test15989.d index 38ca331267..85b74bfad5 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/test19661.d b/tests/dmd/fail_compilation/test19661.d index 369c0a8624..712721487c 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 --- */ From d086a1037b834c6d07c7406e4c6af1bb8d5a59ea Mon Sep 17 00:00:00 2001 From: Dennis Date: Sat, 22 Mar 2025 23:08:04 +0100 Subject: [PATCH 021/113] Refactor checkGC (dlang/dmd!21058) --- dmd/expression.d | 1 + dmd/expressionsem.d | 1 + dmd/frontend.h | 12 +++++++++--- dmd/nogc.d | 47 +++++++++++++++++++++------------------------ dmd/semantic3.d | 4 ++-- dmd/statementsem.d | 20 +++++++++---------- dmd/traits.d | 2 +- 7 files changed, 46 insertions(+), 41 deletions(-) diff --git a/dmd/expression.d b/dmd/expression.d index 4bf1f9f25f..a1d770a18f 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -306,6 +306,7 @@ extern (C++) abstract class Expression : ASTNode { bool parens; // if this is a parenthesized expression bool rvalue; // true if this is considered to be an rvalue, even if it is an lvalue + bool gcPassDone; // `checkGC` has been run on this expression } import dmd.common.bitfields; mixin(generateBitFields!(BitFields, ubyte)); diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 45675efd7c..fbfc5f6398 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -11762,6 +11762,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor res = new LoweredAssignExp(ae, res); res.type = ae.type; + res = res.checkGC(sc); return res; } diff --git a/dmd/frontend.h b/dmd/frontend.h index 49b57c1592..af651d4e5a 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -2368,14 +2368,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) {} }; @@ -2383,6 +2386,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: @@ -7584,6 +7589,7 @@ class NOGCVisitor final : public StoppableVisitor public: using StoppableVisitor::visit; FuncDeclaration* f; + Scope* sc; bool checkOnly; bool err; bool nogcExceptions; diff --git a/dmd/nogc.d b/dmd/nogc.d index b1a7b5f034..48f9110108 100644 --- a/dmd/nogc.d +++ b/dmd/nogc.d @@ -45,13 +45,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 +88,8 @@ public: */ private bool setGC(Expression e, const(char)* msg) { + if (sc.debug_) + return false; if (checkOnly) { err = true; @@ -208,9 +212,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 +224,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/semantic3.d b/dmd/semantic3.d index bfb8c75ea5..ccf931af8d 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 19b4b043eb..cb31b0fe1c 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; @@ -1709,7 +1709,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) // checkGC after optimizing the condition so that // compile time constants are reduced. - ifs.condition = checkGC(scd, ifs.condition); + ifs.condition = ifs.condition.checkGC(scd); // Save 'root' of two branches (then and else) at the point where it forks CtorFlow ctorflow_root = scd.ctorflow.clone(); @@ -1897,7 +1897,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (checkNonAssignmentArrayOp(ss.condition)) ss.condition = ErrorExp.get(); ss.condition = ss.condition.optimize(WANTvalue); - ss.condition = checkGC(sc, ss.condition); + ss.condition = ss.condition.checkGC(sc); if (ss.condition.op == EXP.error) conditionError = true; @@ -2636,7 +2636,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (e0) { e0 = e0.optimize(WANTvalue); - e0 = checkGC(sc, e0); + e0 = e0.checkGC(sc); } } @@ -3054,7 +3054,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) ss.exp = ss.exp.expressionSemantic(sc); ss.exp = resolveProperties(sc, ss.exp); ss.exp = ss.exp.optimize(WANTvalue); - ss.exp = checkGC(sc, ss.exp); + ss.exp = ss.exp.checkGC(sc); if (ss.exp.op == EXP.error) { if (ss._body) @@ -3178,7 +3178,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) ws.exp = ws.exp.expressionSemantic(sc); ws.exp = resolveProperties(sc, ws.exp); ws.exp = ws.exp.optimize(WANTvalue); - ws.exp = checkGC(sc, ws.exp); + ws.exp = ws.exp.checkGC(sc); if (ws.exp.op == EXP.error) return setError(); if (ws.exp.op == EXP.scope_) @@ -3740,7 +3740,7 @@ public bool throwSemantic(Loc loc, ref Expression exp, Scope* sc) exp = exp.expressionSemantic(sc); exp = resolveProperties(sc, exp); - exp = checkGC(sc, exp); + exp = exp.checkGC(sc); if (exp.isErrorExp()) return false; if (!exp.type.isNaked()) diff --git a/dmd/traits.d b/dmd/traits.d index 37363ffed9..732a5a32dc 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; } From cede53dcc78785229f36c894019d581465c1a8da Mon Sep 17 00:00:00 2001 From: Dennis Date: Sun, 23 Mar 2025 00:40:57 +0100 Subject: [PATCH 022/113] Don't raise "cannot return non-void" on Terror (dlang/dmd!21028) --- dmd/statementsem.d | 2 +- tests/dmd/fail_compilation/diag10405.d | 11 ------ tests/dmd/fail_compilation/diag20888.d | 10 +++--- tests/dmd/fail_compilation/fail305.d | 11 ------ tests/dmd/fail_compilation/fail41.d | 18 ---------- tests/dmd/fail_compilation/nonvoid_return.d | 37 +++++++++++++++++++++ 6 files changed, 43 insertions(+), 46 deletions(-) delete mode 100644 tests/dmd/fail_compilation/diag10405.d delete mode 100644 tests/dmd/fail_compilation/fail305.d delete mode 100644 tests/dmd/fail_compilation/fail41.d create mode 100644 tests/dmd/fail_compilation/nonvoid_return.d diff --git a/dmd/statementsem.d b/dmd/statementsem.d index cb31b0fe1c..4c36055f6a 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -2603,7 +2603,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (tbret && tbret.ty == Tvoid || convToVoid) { - if (!convToVoid) + if (!convToVoid && !texp.isTypeError()) { error(rs.loc, "cannot return non-void from `void` function"); errors = true; diff --git a/tests/dmd/fail_compilation/diag10405.d b/tests/dmd/fail_compilation/diag10405.d deleted file mode 100644 index 28da8af93a..0000000000 --- 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 84af42533f..d030a98ec2 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/fail305.d b/tests/dmd/fail_compilation/fail305.d deleted file mode 100644 index aef1624a07..0000000000 --- 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/fail41.d b/tests/dmd/fail_compilation/fail41.d deleted file mode 100644 index 6d89395053..0000000000 --- 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/nonvoid_return.d b/tests/dmd/fail_compilation/nonvoid_return.d new file mode 100644 index 0000000000..bcced1b9bf --- /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; From 5cd3d0e69bad24da979175c22d88d5c38c6f98a0 Mon Sep 17 00:00:00 2001 From: Dennis Date: Sun, 23 Mar 2025 01:35:43 +0100 Subject: [PATCH 023/113] Fix dlang/dmd!20901: can escape stack pointer through indexed array literal (dlang/dmd!21063) --- dmd/dcast.d | 8 -------- dmd/nogc.d | 8 ++++++++ tests/dmd/fail_compilation/retscope3.d | 10 ++++++++++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/dmd/dcast.d b/dmd/dcast.d index 829b4f1db1..a4276a43e2 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; @@ -2728,13 +2727,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/nogc.d b/dmd/nogc.d index 48f9110108..a5d9c68aa7 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; @@ -127,6 +128,13 @@ public: 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"); } diff --git a/tests/dmd/fail_compilation/retscope3.d b/tests/dmd/fail_compilation/retscope3.d index 438fdd76e1..8802469de2 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; +} From b64b1d22d77feac5a2e95e7fab25dfc85d70c828 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sun, 23 Mar 2025 21:47:29 +0000 Subject: [PATCH 024/113] Fix hidden base constructor supplemental message (dlang/dmd!21069) Fixes dlang/dmd!21068. Also say base class *constructor* in supplemental message. --- dmd/funcsem.d | 13 ++++++++---- tests/dmd/fail_compilation/diag23384.d | 4 ++-- tests/dmd/fail_compilation/hidden_ctor.d | 27 ++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 tests/dmd/fail_compilation/hidden_ctor.d diff --git a/dmd/funcsem.d b/dmd/funcsem.d index 0a8a574c59..a8b46d84c2 100644 --- a/dmd/funcsem.d +++ b/dmd/funcsem.d @@ -1835,10 +1835,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; } } diff --git a/tests/dmd/fail_compilation/diag23384.d b/tests/dmd/fail_compilation/diag23384.d index 1fa4da5ffb..9cb17c00d7 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/hidden_ctor.d b/tests/dmd/fail_compilation/hidden_ctor.d new file mode 100644 index 0000000000..8d6e6959f2 --- /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!"); +} From b8c8277afaf803a22382c6656bce97e3a1375b44 Mon Sep 17 00:00:00 2001 From: Abhay Pratap Date: Mon, 24 Mar 2025 04:42:13 +0530 Subject: [PATCH 025/113] Refactored memcpy calls to D slices (dlang/dmd!21062) * Refactored memcpy calls to D slices * Added .DS_Store to .gitignore --- dmd/cparse.d | 10 +++++----- dmd/parse.d | 15 +++++++-------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/dmd/cparse.d b/dmd/cparse.d index 6899468c5e..6a81fdf315 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -832,8 +832,8 @@ final class CParser(AST) : Parser!AST const len2 = token.len; len = len1 + len2; auto s2 = cast(char*)mem.xmalloc_noscan(len * char.sizeof); - memcpy(s2, s, len1 * char.sizeof); - memcpy(s2 + len1, token.ustring, len2 * char.sizeof); + s2[0 .. len1] = s[0 .. len1]; + s2[len1 .. len1 + len2] = token.ustring[0 .. len2]; s = s2; } else @@ -3511,12 +3511,12 @@ final class CParser(AST) : Parser!AST case TOK.colonColon: // treat as two separate : tokens for iasmgcc *ptoklist = allocateToken(); - memcpy(*ptoklist, &token, Token.sizeof); + **ptoklist = this.token; (*ptoklist).value = TOK.colon; ptoklist = &(*ptoklist).next; *ptoklist = allocateToken(); - memcpy(*ptoklist, &token, Token.sizeof); + **ptoklist = this.token; (*ptoklist).value = TOK.colon; ptoklist = &(*ptoklist).next; @@ -3526,7 +3526,7 @@ final class CParser(AST) : Parser!AST default: *ptoklist = allocateToken(); - memcpy(*ptoklist, &token, Token.sizeof); + **ptoklist = this.token; ptoklist = &(*ptoklist).next; *ptoklist = null; nextToken(); diff --git a/dmd/parse.d b/dmd/parse.d index f031777238..2ba970c12e 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -2772,7 +2772,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'; } @@ -7105,12 +7105,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; @@ -7120,7 +7120,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(); @@ -8264,9 +8264,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; @@ -8473,7 +8472,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer 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); From e436dd20d431f2c5f0905afd709989ed83639b6f Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Mon, 24 Mar 2025 01:11:14 +0100 Subject: [PATCH 026/113] [druntime] core.int128: Don't support/test invalid shift-by values >= 128 This enables using (LLVM/gcc) intrinsics for shifts, for which such inputs are undefined behavior, as for builtin types. --- runtime/druntime/src/core/int128.d | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/runtime/druntime/src/core/int128.d b/runtime/druntime/src/core/int128.d index 27c8b99d2c..6b502fa1a6 100644 --- a/runtime/druntime/src/core/int128.d +++ b/runtime/druntime/src/core/int128.d @@ -189,10 +189,8 @@ Cent sar1(Cent c) */ pure Cent shl(Cent c, uint n) +in (n < Ubits * 2) { - if (n >= Ubits * 2) - return Zero; - if (n >= Ubits) { c.hi = c.lo << (n - Ubits); @@ -216,10 +214,8 @@ Cent shl(Cent c, uint n) */ pure Cent shr(Cent c, uint n) +in (n < Ubits * 2) { - if (n >= Ubits * 2) - return Zero; - if (n >= Ubits) { c.lo = c.hi >> (n - Ubits); @@ -243,18 +239,13 @@ Cent shr(Cent c, uint n) */ pure Cent sar(Cent c, uint n) +in (n < Ubits * 2) { const signmask = -(c.hi >> (Ubits - 1)); const signshift = (Ubits * 2) - n; c = shr(c, n); - // Sign extend all bits beyond the precision of Cent. - if (n >= Ubits * 2) - { - c.hi = signmask; - c.lo = signmask; - } - else if (signshift >= Ubits * 2) + if (signshift == Ubits * 2) { } else if (signshift >= Ubits) @@ -317,6 +308,8 @@ pure Cent rol(Cent c, uint n) { n &= Ubits * 2 - 1; + if (n == 0) + return c; Cent l = shl(c, n); Cent r = shr(c, Ubits * 2 - n); return or(l, r); @@ -334,6 +327,8 @@ pure Cent ror(Cent c, uint n) { n &= Ubits * 2 - 1; + if (n == 0) + return c; Cent r = shr(c, n); Cent l = shl(c, Ubits * 2 - n); return or(r, l); @@ -893,18 +888,14 @@ unittest assert(shl(C10,0) == C10); assert(shl(C10,Ubits) == C10_0); assert(shl(C10,1) == C20); - assert(shl(C10,Ubits * 2) == C0); assert(shr(C10_0,0) == C10_0); assert(shr(C10_0,Ubits) == C10); assert(shr(C10_0,Ubits - 1) == C20); assert(shr(C10_0,Ubits + 1) == C5); - assert(shr(C10_0,Ubits * 2) == C0); assert(sar(C10_0,0) == C10_0); assert(sar(C10_0,Ubits) == C10); assert(sar(C10_0,Ubits - 1) == C20); assert(sar(C10_0,Ubits + 1) == C5); - assert(sar(C10_0,Ubits * 2) == C0); - assert(sar(Cm1,Ubits * 2) == Cm1); assert(shl1(C10) == C20); assert(shr1(C10_0) == C5_0); @@ -961,4 +952,6 @@ unittest assert(rol(ror(C7_9, 5), 5) == C7_9); assert(rol(C7_9, 1) == rol1(C7_9)); assert(ror(C7_9, 1) == ror1(C7_9)); + assert(rol(C7_9, 0) == C7_9); + assert(ror(C7_9, 0) == C7_9); } From 4b80c0e1732edd24e79e331c53514d355619e489 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Mon, 24 Mar 2025 01:20:28 +0100 Subject: [PATCH 027/113] [druntime] core.int128: Extract nested udivmod128_64 as udivmod overload --- runtime/druntime/src/core/int128.d | 129 ++++++++++++++++------------- 1 file changed, 70 insertions(+), 59 deletions(-) diff --git a/runtime/druntime/src/core/int128.d b/runtime/druntime/src/core/int128.d index 6b502fa1a6..aa1f0441b4 100644 --- a/runtime/druntime/src/core/int128.d +++ b/runtime/druntime/src/core/int128.d @@ -485,63 +485,6 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus) // Based on "Unsigned Doubleword Division" in Hacker's Delight import core.bitop; - // Divides a 128-bit dividend by a 64-bit divisor. - // The result must fit in 64 bits. - static U udivmod128_64(Cent c1, U c2, out U modulus) - { - // We work in base 2^^32 - enum base = 1UL << 32; - enum divmask = (1UL << (Ubits / 2)) - 1; - enum divshift = Ubits / 2; - - // Check for overflow and divide by 0 - if (c1.hi >= c2) - { - modulus = 0UL; - return ~0UL; - } - - // Computes [num1 num0] / den - static uint udiv96_64(U num1, uint num0, U den) - { - // Extract both digits of the denominator - const den1 = cast(uint)(den >> divshift); - const den0 = cast(uint)(den & divmask); - // Estimate ret as num1 / den1, and then correct it - U ret = num1 / den1; - const t2 = (num1 % den1) * base + num0; - const t1 = ret * den0; - if (t1 > t2) - ret -= (t1 - t2 > den) ? 2 : 1; - return cast(uint)ret; - } - - // Determine the normalization factor. We multiply c2 by this, so that its leading - // digit is at least half base. In binary this means just shifting left by the number - // of leading zeros, so that there's a 1 in the MSB. - // We also shift number by the same amount. This cannot overflow because c1.hi < c2. - const shift = (Ubits - 1) - bsr(c2); - c2 <<= shift; - U num2 = c1.hi; - num2 <<= shift; - num2 |= (c1.lo >> (-shift & 63)) & (-cast(I)shift >> 63); - c1.lo <<= shift; - - // Extract the low digits of the numerator (after normalizing) - const num1 = cast(uint)(c1.lo >> divshift); - const num0 = cast(uint)(c1.lo & divmask); - - // Compute q1 = [num2 num1] / c2 - const q1 = udiv96_64(num2, num1, c2); - // Compute the true (partial) remainder - const rem = num2 * base + num1 - q1 * c2; - // Compute q0 = [rem num0] / c2 - const q0 = udiv96_64(rem, num0, c2); - - modulus = (rem * base + num0 - q0 * c2) >> shift; - return (cast(U)q1 << divshift) | q0; - } - // Special cases if (!tst(c2)) { @@ -571,7 +514,7 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus) if (q1) c1.hi = c1.hi % c2.lo; Cent rem; - const q0 = udivmod128_64(c1, c2.lo, rem.lo); + const q0 = udivmod(c1, c2.lo, rem.lo); modulus = rem; const Cent ret = { lo:q0, hi:q1 }; return ret; @@ -592,7 +535,7 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus) // Get quotient from divide unsigned operation. U rem_ignored; - const Cent q1 = { lo:udivmod128_64(u1, v1, rem_ignored) }; + const Cent q1 = { lo:udivmod(u1, v1, rem_ignored) }; // Undo normalization and division of c1 by 2. Cent quotient = shr(shl(q1, shift), 63); @@ -619,6 +562,74 @@ Cent udivmod(Cent c1, Cent c2, out Cent modulus) return quotient; } +/**************************** + * Unsigned divide 128-bit c1 / 64-bit c2. The result must fit in 64 bits. + * The remainder after division is stored to modulus. + * Params: + * c1 = dividend + * c2 = divisor + * modulus = set to c1 % c2 + * Returns: + * quotient c1 / c2 + */ +pure +U udivmod(Cent c1, U c2, out U modulus) +{ + import core.bitop; + + // We work in base 2^^32 + enum base = 1UL << 32; + enum divmask = (1UL << (Ubits / 2)) - 1; + enum divshift = Ubits / 2; + + // Check for overflow and divide by 0 + if (c1.hi >= c2) + { + modulus = 0UL; + return ~0UL; + } + + // Computes [num1 num0] / den + static uint udiv96_64(U num1, uint num0, U den) + { + // Extract both digits of the denominator + const den1 = cast(uint)(den >> divshift); + const den0 = cast(uint)(den & divmask); + // Estimate ret as num1 / den1, and then correct it + U ret = num1 / den1; + const t2 = (num1 % den1) * base + num0; + const t1 = ret * den0; + if (t1 > t2) + ret -= (t1 - t2 > den) ? 2 : 1; + return cast(uint)ret; + } + + // Determine the normalization factor. We multiply c2 by this, so that its leading + // digit is at least half base. In binary this means just shifting left by the number + // of leading zeros, so that there's a 1 in the MSB. + // We also shift number by the same amount. This cannot overflow because c1.hi < c2. + const shift = (Ubits - 1) - bsr(c2); + c2 <<= shift; + U num2 = c1.hi; + num2 <<= shift; + num2 |= (c1.lo >> (-shift & 63)) & (-cast(I)shift >> 63); + c1.lo <<= shift; + + // Extract the low digits of the numerator (after normalizing) + const num1 = cast(uint)(c1.lo >> divshift); + const num0 = cast(uint)(c1.lo & divmask); + + // Compute q1 = [num2 num1] / c2 + const q1 = udiv96_64(num2, num1, c2); + // Compute the true (partial) remainder + const rem = num2 * base + num1 - q1 * c2; + // Compute q0 = [rem num0] / c2 + const q0 = udiv96_64(rem, num0, c2); + + modulus = (rem * base + num0 - q0 * c2) >> shift; + return (cast(U)q1 << divshift) | q0; +} + /**************************** * Signed divide c1 / c2. From 46f184e29ad1c6bab6d315bc866bfabf737b7206 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Mon, 24 Mar 2025 01:22:58 +0100 Subject: [PATCH 028/113] [druntime] core.int128: Optimize new udivmod overload via inline asm on x86_64 --- runtime/druntime/src/core/int128.d | 40 +++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/runtime/druntime/src/core/int128.d b/runtime/druntime/src/core/int128.d index aa1f0441b4..562cfc0093 100644 --- a/runtime/druntime/src/core/int128.d +++ b/runtime/druntime/src/core/int128.d @@ -562,6 +562,12 @@ 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. @@ -577,6 +583,39 @@ U udivmod(Cent c1, U c2, out U modulus) { import core.bitop; + if (!__ctfe) + { + version (GNU_OR_LDC_X86_64) + { + U ret = void; + asm pure @trusted nothrow @nogc + { + "divq %4" + : "=a"(ret), "=d"(modulus) + : "a"(c1.lo), "d"(c1.hi), "r"(c2) + : "cc"; + } + return ret; + } + else version (D_InlineAsm_X86_64) + { + const lo = c1.lo; + const hi = c1.hi; + U mod = void; + U ret = void; + asm pure @trusted nothrow @nogc + { + mov RAX, lo; + mov RDX, hi; + div c2; + mov mod, RDX; // DMD bug: cannot use modulus directly + mov ret, RAX; + } + modulus = mod; + return ret; + } + } + // We work in base 2^^32 enum base = 1UL << 32; enum divmask = (1UL << (Ubits / 2)) - 1; @@ -918,7 +957,6 @@ unittest assert(udiv(C10,C2) == C5); assert(udivmod(C10,C2, modulus) == C5); assert(modulus == C0); assert(udivmod(C10,C3, modulus) == C3); assert(modulus == C1); - assert(udivmod(C10,C0, modulus) == Cm1); assert(modulus == C0); assert(udivmod(C2,C90_30, modulus) == C0); assert(modulus == C2); assert(udiv(mul(C90_30, C2), C2) == C90_30); assert(udiv(mul(C90_30, C2), C90_30) == C2); From 7e58a76fe37dff7d65564e4a350a079773449bd2 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Tue, 25 Mar 2025 03:15:39 +0100 Subject: [PATCH 029/113] [druntime] core.int128: Add 64-bit mul() overload and optimize via inline asm on x86_64 --- runtime/druntime/src/core/int128.d | 61 +++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/runtime/druntime/src/core/int128.d b/runtime/druntime/src/core/int128.d index 562cfc0093..b1247891e6 100644 --- a/runtime/druntime/src/core/int128.d +++ b/runtime/druntime/src/core/int128.d @@ -36,6 +36,12 @@ else else private enum Cent_alignment = (size_t.sizeof * 2); } +version (X86_64) +{ + version (GNU) version = GNU_OR_LDC_X86_64; + version (LDC) version = GNU_OR_LDC_X86_64; +} + /** * 128 bit integer type. * See_also: $(REF Int128, std,int128). @@ -453,6 +459,55 @@ Cent mul(Cent c1, Cent c2) return ret; } +/**************************** + * Multiply 64-bit operands u1 * u2 in 128-bit precision. + * Params: + * u1 = operand 1 + * u2 = operand 2 + * Returns: + * u1 * u2 in 128-bit precision + */ +pure +Cent mul(ulong u1, ulong u2) +{ + if (!__ctfe) + { + version (GNU_OR_LDC_X86_64) + { + Cent ret = void; + asm pure @trusted nothrow @nogc + { + "mulq %3" + : "=a"(ret.lo), "=d"(ret.hi) + : "a"(u1), "r"(u2) + : "cc"; + } + return ret; + } + else version (D_InlineAsm_X86_64) + { + U lo = void; + U hi = void; + asm pure @trusted nothrow @nogc + { + mov RAX, u1; + mul u2; + mov lo, RAX; + mov hi, RDX; + } + return Cent(lo: lo, hi: hi); + } + } + + return mul(Cent(lo: u1), Cent(lo: u2)); +} + +unittest +{ + assert(mul(3, 42) == Cent(lo: 126)); + assert(mul(1L << 60, 1 << 10) == Cent(hi: 1 << 6)); +} + /**************************** * Unsigned divide c1 / c2. @@ -562,12 +617,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. From 8b6c788fdeeb77b0689eb8b3ab6bfd33fa31dc2b Mon Sep 17 00:00:00 2001 From: Samrendra Pratap Singh <153061395+solo-source@users.noreply.github.com> Date: Tue, 25 Mar 2025 15:55:34 +0530 Subject: [PATCH 030/113] Fix dlang#18262 - Fix expected error message for enum auto-increment (dlang/dmd!21067) * Fix dlang#18262 - Resolved special enum case and other conflicts * Fix dlang#18262 - Resolved Special Enum case and failing test. * Fix dlang#18262 - Resolved special enum case and other failing tests --- dmd/enumsem.d | 15 +++++++++++++++ .../dmd/fail_compilation/enum_auto_increment.d | 18 ++++++++++++++++++ tests/dmd/fail_compilation/fail109.d | 14 ++++++-------- tests/dmd/fail_compilation/fail98.d | 5 ++++- 4 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 tests/dmd/fail_compilation/enum_auto_increment.d diff --git a/dmd/enumsem.d b/dmd/enumsem.d index fe9f38266f..829b42da2a 100644 --- a/dmd/enumsem.d +++ b/dmd/enumsem.d @@ -524,6 +524,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/tests/dmd/fail_compilation/enum_auto_increment.d b/tests/dmd/fail_compilation/enum_auto_increment.d new file mode 100644 index 0000000000..9c04e9a324 --- /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 003e65f9b8..94f951f9f9 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/fail98.d b/tests/dmd/fail_compilation/fail98.d index 7541d3718c..20b18d19db 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 --- */ From 50a7c14fbe758a2264294aa3631db87c7507b8e9 Mon Sep 17 00:00:00 2001 From: Dennis Date: Wed, 26 Mar 2025 08:43:36 +0100 Subject: [PATCH 031/113] Improve 'no property' error suggestions for pointers (dlang/dmd!21087) --- dmd/typesem.d | 40 +++++++++------------- tests/dmd/fail_compilation/checkimports2.d | 10 +++--- tests/dmd/fail_compilation/fail18219.d | 11 +++--- tests/dmd/fail_compilation/fail19103.d | 4 +-- tests/dmd/fail_compilation/fail347.d | 8 ++--- tests/dmd/fail_compilation/ice19755.d | 5 +-- tests/dmd/fail_compilation/lookup.d | 10 +++--- tests/dmd/fail_compilation/mixinprop.d | 4 +-- 8 files changed, 46 insertions(+), 46 deletions(-) diff --git a/dmd/typesem.d b/dmd/typesem.d index c5a3b83379..1906867c53 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -3418,8 +3418,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)) @@ -3429,18 +3431,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) @@ -3448,30 +3453,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()) { @@ -3497,7 +3489,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()); } } diff --git a/tests/dmd/fail_compilation/checkimports2.d b/tests/dmd/fail_compilation/checkimports2.d index 44c237f144..56e28e1ce7 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/fail18219.d b/tests/dmd/fail_compilation/fail18219.d index bf4b189f6e..f5fc27f1a8 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 c1abd0df90..e617249ed7 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:druntime/import/core/stdc/stdio.d$($n$): did you mean `core.stdc.stdio.puts`? --- */ - void main() { (new C).puts("OK."); // Error: no property puts for type test.C, did you mean core.stdc.stdio.puts(T...)(T args)? diff --git a/tests/dmd/fail_compilation/fail347.d b/tests/dmd/fail_compilation/fail347.d index c56acf5642..996990bd40 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/ice19755.d b/tests/dmd/fail_compilation/ice19755.d index 6d60fc43c1..2770676294 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/lookup.d b/tests/dmd/fail_compilation/lookup.d index fe752f2f4d..db7eedab30 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 db8bf5968d..103c6b2a04 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() From a057d3ec83607c9ab454f190dfc7a2191f78adf6 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Wed, 26 Mar 2025 10:28:07 +0000 Subject: [PATCH 032/113] Fix error when struct initializer isn't accepted (dlang/dmd!21086) * Fix error when struct initializer isn't accepted * Rename StructDeclaration.hasRegularCtor parameter to ignoreDisabled checkDisabled detected disabled ctors when it was false, which was confusing! * Update tests --- dmd/aggregate.h | 2 +- dmd/dstruct.d | 9 ++++----- dmd/frontend.h | 2 +- dmd/initsem.d | 5 ++++- tests/dmd/fail_compilation/fail21547.d | 6 ++++-- tests/dmd/fail_compilation/fail336.d | 3 ++- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/dmd/aggregate.h b/dmd/aggregate.h index 82f8aeca08..2a81162aef 100644 --- a/dmd/aggregate.h +++ b/dmd/aggregate.h @@ -196,7 +196,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 diff --git a/dmd/dstruct.d b/dmd/dstruct.d index d1df6f5e42..1896e37edf 100644 --- a/dmd/dstruct.d +++ b/dmd/dstruct.d @@ -399,13 +399,12 @@ extern (C++) class StructDeclaration : AggregateDeclaration * is not disabled. * * Params: - * checkDisabled = if the struct has a regular - non-disabled constructor + * ignoreDisabled = true to ignore disabled constructors * Returns: * true, if the struct has a regular (optionally, * not disabled) constructor, false otherwise. */ - final bool hasRegularCtor(bool checkDisabled = false) + final bool hasRegularCtor(bool ignoreDisabled = false) { if (!ctor) return false; @@ -415,7 +414,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration { if (auto td = s.isTemplateDeclaration()) { - if (checkDisabled && td.onemember) + if (ignoreDisabled && td.onemember) { if (auto ctorDecl = td.onemember.isCtorDeclaration()) { @@ -428,7 +427,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration } if (auto ctorDecl = s.isCtorDeclaration()) { - if (!ctorDecl.isCpCtor && (!checkDisabled || !(ctorDecl.storage_class & STC.disable))) + if (!ctorDecl.isCpCtor && (!ignoreDisabled || !(ctorDecl.storage_class & STC.disable))) { result = true; return 1; diff --git a/dmd/frontend.h b/dmd/frontend.h index af651d4e5a..6b95c82b45 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -7441,7 +7441,7 @@ class StructDeclaration : public AggregateDeclaration 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 diff --git a/dmd/initsem.d b/dmd/initsem.d index 8737e0f646..4e0284b8c5 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); diff --git a/tests/dmd/fail_compilation/fail21547.d b/tests/dmd/fail_compilation/fail21547.d index 7a6a44a4a1..440a301de5 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/fail336.d b/tests/dmd/fail_compilation/fail336.d index 9df207120b..8fb9857d4d 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 }` --- */ From 5ab21f75e572f6ed5c692900ea28883783cd50e9 Mon Sep 17 00:00:00 2001 From: Abul Hossain Khan <140191921+abulgit@users.noreply.github.com> Date: Thu, 27 Mar 2025 01:02:01 +0530 Subject: [PATCH 033/113] Optimize Loc Lookups (dlang/dmd!21088) --- dmd/location.d | 109 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 2 deletions(-) diff --git a/dmd/location.d b/dmd/location.d index 7a579b278f..9a396f37e8 100644 --- a/dmd/location.d +++ b/dmd/location.d @@ -366,6 +366,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) { @@ -421,8 +426,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) { @@ -430,7 +488,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; } @@ -443,10 +504,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) { @@ -454,7 +556,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; } From b6f5e77148d9d641b6822d9c661d39d8bb567683 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Thu, 27 Mar 2025 01:20:38 -0700 Subject: [PATCH 034/113] size_t was wrong, sign extension omitted (dlang/dmd!21093) --- dmd/target.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmd/target.d b/dmd/target.d index f52bcc57b8..5f6c178fb4 100644 --- a/dmd/target.d +++ b/dmd/target.d @@ -433,7 +433,7 @@ extern (C++) struct Target 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. From dc1be4d4f3bc1e1cb923e622b677f387b7c1b8e0 Mon Sep 17 00:00:00 2001 From: Abul Hossain Khan <140191921+abulgit@users.noreply.github.com> Date: Fri, 28 Mar 2025 14:43:12 +0530 Subject: [PATCH 035/113] Improve fix: dlang/dmd!20867 ICE on final switch forward referencing its enum. (dlang/dmd!21097) * Mark C enums as semantic2done to prevent segfaults in final switch * Added corresponding test case --- dmd/importc.d | 4 +++- tests/dmd/compilable/imports/cstuff3.c | 13 +++++++++++++ tests/dmd/compilable/testcstuff3.d | 19 +++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/dmd/importc.d b/dmd/importc.d index 2e0060b41c..d4631f0294 100644 --- a/dmd/importc.d +++ b/dmd/importc.d @@ -751,6 +751,8 @@ void cEnumSemantic(Scope* sc, EnumDeclaration ed) } ed.memtype = commonType; - ed.semanticRun = PASS.semanticdone; + // 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/tests/dmd/compilable/imports/cstuff3.c b/tests/dmd/compilable/imports/cstuff3.c index f6aaf3b2a4..fb78ec76bc 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/testcstuff3.d b/tests/dmd/compilable/testcstuff3.d index 89228a9bc4..08aa3b03d1 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"); +} From 8f710e1b66d3dccec071379de4b7f5fd94e50f5f Mon Sep 17 00:00:00 2001 From: Dennis Date: Fri, 28 Mar 2025 23:31:49 +0100 Subject: [PATCH 036/113] Turn macro translations into template functions (dlang/dmd!21108) --- runtime/druntime/src/core/stdc/math.d | 36 ++-- .../src/core/sys/linux/linux/if_packet.d | 2 +- .../druntime/src/core/sys/linux/netinet/in_.d | 14 +- runtime/druntime/src/core/sys/linux/sched.d | 30 +-- .../druntime/src/core/sys/linux/sys/time.d | 8 +- runtime/druntime/src/core/sys/posix/netdb.d | 20 +- .../druntime/src/core/sys/posix/netinet/in_.d | 202 +++++++++--------- runtime/druntime/src/core/sys/posix/signal.d | 16 +- .../druntime/src/core/sys/posix/sys/ioctl.d | 10 +- .../druntime/src/core/sys/posix/sys/select.d | 104 ++++----- .../druntime/src/core/sys/posix/sys/socket.d | 14 +- .../druntime/src/core/sys/posix/sys/stat.d | 162 +++++++------- .../druntime/src/core/sys/posix/sys/wait.d | 152 ++++++------- .../druntime/src/core/sys/windows/basetsd.d | 38 ++-- .../druntime/src/core/sys/windows/commctrl.d | 4 +- runtime/druntime/src/core/sys/windows/dde.d | 60 +++--- .../druntime/src/core/sys/windows/mmsystem.d | 26 +-- runtime/druntime/src/core/sys/windows/ntdef.d | 8 +- .../druntime/src/core/sys/windows/ntsecapi.d | 2 +- .../druntime/src/core/sys/windows/oleauto.d | 2 +- .../druntime/src/core/sys/windows/shlobj.d | 146 ++++++------- runtime/druntime/src/core/sys/windows/stat.d | 10 +- .../druntime/src/core/sys/windows/threadaux.d | 4 +- runtime/druntime/src/core/sys/windows/vfw.d | 138 ++++++------ .../druntime/src/core/sys/windows/winbase.d | 16 +- .../druntime/src/core/sys/windows/wincrypt.d | 10 +- runtime/druntime/src/core/sys/windows/winnt.d | 46 ++-- .../druntime/src/core/sys/windows/winuser.d | 12 +- 28 files changed, 646 insertions(+), 646 deletions(-) diff --git a/runtime/druntime/src/core/stdc/math.d b/runtime/druntime/src/core/stdc/math.d index 1f384f9cbd..5b78d6f61f 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/linux/linux/if_packet.d b/runtime/druntime/src/core/sys/linux/linux/if_packet.d index b50b6a3391..6dd95808d6 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 1b428f5aec..f3c23572fb 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/sched.d b/runtime/druntime/src/core/sys/linux/sched.d index 5cd512e826..0a940db65e 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/sys/time.d b/runtime/druntime/src/core/sys/linux/sys/time.d index 4b56229687..9eb48f1c5e 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/posix/netdb.d b/runtime/druntime/src/core/sys/posix/netdb.d index 70a5fe1901..4713f4b495 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 5818ee6e22..09a4a5e07d 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 e3d80fb021..81fb9d22ac 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 diff --git a/runtime/druntime/src/core/sys/posix/sys/ioctl.d b/runtime/druntime/src/core/sys/posix/sys/ioctl.d index caf3ebafb5..27584d357c 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 bd34250325..c8a88bddc0 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 12824373d5..5bdc22294c 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 328f620a42..ab79a40675 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 f6b0674a3b..131a9400dc 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/windows/basetsd.d b/runtime/druntime/src/core/sys/windows/basetsd.d index 1e5a45427c..d06bc5744e 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 073587f01c..fcece45be4 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 975c62e42f..e4a75c5711 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 29c066e7c9..2ce75aa788 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 160443312b..e45d0effcd 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 77101f669b..7088cb1020 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 f4bb40259a..cc7b937a03 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 bcd254b18e..0e292d4c71 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 85ed24f93d..dfc7d490c4 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 dae8896d4b..40b833c1aa 100644 --- a/runtime/druntime/src/core/sys/windows/threadaux.d +++ b/runtime/druntime/src/core/sys/windows/threadaux.d @@ -311,8 +311,8 @@ struct thread_aux enum TEB_offset_TlsSlots = 0xE10; enum TEB_offset_TlsExpansionSlots = 0xF94; } - void* tlsSlotsAdr(void** teb) { return cast(void*) teb + TEB_offset_TlsSlots; } - ref void* tlsExpansionSlots(void** teb) { return *cast(void**)(cast(void*) teb + TEB_offset_TlsExpansionSlots); } + void* tlsSlotsAdr()(void** teb) { return cast(void*) teb + TEB_offset_TlsSlots; } + ref void* tlsExpansionSlots()(void** teb) { return *cast(void**)(cast(void*) teb + TEB_offset_TlsExpansionSlots); } import core.stdc.string; void*[64] slots = void; diff --git a/runtime/druntime/src/core/sys/windows/vfw.d b/runtime/druntime/src/core/sys/windows/vfw.d index c0f22a9fb5..313895f4ac 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 935c7c432c..2c2905b635 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 cb52d9e717..f068a3a795 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 ca4a903fb6..097a2b6fd4 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; @@ -1555,8 +1555,8 @@ const TCHAR[] enum IMAGE_ORDINAL_FLAG32 = 0x80000000; -ulong IMAGE_ORDINAL64(ulong Ordinal) { return Ordinal & 0xFFFF; } -uint IMAGE_ORDINAL32(uint Ordinal) { return Ordinal & 0xFFFF; } +ulong IMAGE_ORDINAL64()(ulong Ordinal) { return Ordinal & 0xFFFF; } +uint IMAGE_ORDINAL32()(uint Ordinal) { return Ordinal & 0xFFFF; } bool IMAGE_SNAP_BY_ORDINAL32(uint Ordinal) { return (Ordinal & IMAGE_ORDINAL_FLAG32) != 0; @@ -1919,10 +1919,10 @@ static if (_WIN32_WINNT >= 0x501) { } // Macros -BYTE BTYPE(BYTE x) { return cast(BYTE) (x & N_BTMASK); } -bool ISPTR(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT); } -bool ISFCN(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT); } -bool ISARY(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_ARRAY << N_BTSHFT); } +BYTE BTYPE()(BYTE x) { return cast(BYTE) (x & N_BTMASK); } +bool ISPTR()(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT); } +bool ISFCN()(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT); } +bool ISARY()(uint x) { return (x & N_TMASK) == (IMAGE_SYM_DTYPE_ARRAY << N_BTSHFT); } bool ISTAG(uint x) { return x == IMAGE_SYM_CLASS_STRUCT_TAG || x == IMAGE_SYM_CLASS_UNION_TAG @@ -1932,7 +1932,7 @@ uint INCREF(uint x) { return ((x & ~N_BTMASK) << N_TSHIFT) | (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT) | (x & N_BTMASK); } -uint DECREF(uint x) { return ((x >>> N_TSHIFT) & ~N_BTMASK) | (x & N_BTMASK); } +uint DECREF()(uint x) { return ((x >>> N_TSHIFT) & ~N_BTMASK) | (x & N_BTMASK); } enum DWORD TLS_MINIMUM_AVAILABLE = 64; @@ -1948,9 +1948,9 @@ enum ULONG /* Although these are semantically boolean, they are documented and * implemented to return ULONG; this behaviour is preserved for compatibility */ -ULONG IsReparseTagMicrosoft(ULONG x) { return x & 0x80000000; } -ULONG IsReparseTagHighLatency(ULONG x) { return x & 0x40000000; } -ULONG IsReparseTagNameSurrogate(ULONG x) { return x & 0x20000000; } +ULONG IsReparseTagMicrosoft()(ULONG x) { return x & 0x80000000; } +ULONG IsReparseTagHighLatency()(ULONG x) { return x & 0x40000000; } +ULONG IsReparseTagNameSurrogate()(ULONG x) { return x & 0x20000000; } bool IsReparseTagValid(ULONG x) { return !(x & ~IO_REPARSE_TAG_VALID_VALUES) && (x > IO_REPARSE_TAG_RESERVED_RANGE); @@ -3380,7 +3380,7 @@ struct IMAGE_RESOURCE_DIRECTORY_ENTRY { uint NameOffset() { return Name & 0x7FFFFFFF; } bool NameIsString() { return cast(bool)(Name & 0x80000000); } - uint OffsetToDirectory() { return OffsetToData & 0x7FFFFFFF; } + uint OffsetToDirectory()() { return OffsetToData & 0x7FFFFFFF; } bool DataIsDirectory() { return cast(bool)(OffsetToData & 0x80000000); } uint NameOffset(uint n) { @@ -3498,7 +3498,7 @@ struct IMAGE_CE_RUNTIME_FUNCTION_ENTRY { +/ uint FuncLen() { return (_bf >> 8) & 0x3FFFFF; } bool ThirtyTwoBit() { return cast(bool)(_bf & 0x40000000); } - bool ExceptionFlag() { return cast(bool)(_bf & 0x80000000); } + bool ExceptionFlag()() { return cast(bool)(_bf & 0x80000000); } uint FuncLen(uint f) { _bf = (_bf & ~0x3FFFFF00) | ((f & 0x3FFFFF) << 8); return f & 0x3FFFFF; @@ -3543,8 +3543,8 @@ struct FPO_DATA { ubyte cbRegs() { return cast(ubyte)(_bf & 0x07); } bool fHasSEH() { return cast(bool)(_bf & 0x08); } bool fUseBP() { return cast(bool)(_bf & 0x10); } - bool reserved() { return cast(bool)(_bf & 0x20); } - ubyte cbFrame() { return cast(ubyte)(_bf >> 6); } + bool reserved()() { return cast(bool)(_bf & 0x20); } + ubyte cbFrame()() { return cast(ubyte)(_bf >> 6); } ubyte cbRegs(ubyte c) { _bf = cast(ubyte) ((_bf & ~0x07) | (c & 0x07)); @@ -4108,7 +4108,7 @@ struct PROCESSOR_POWER_POLICY_INFO { uint _bf; bool AllowDemotion() { return cast(bool)(_bf & 1); } - bool AllowPromotion() { return cast(bool)(_bf & 2); } + bool AllowPromotion()() { return cast(bool)(_bf & 2); } bool AllowDemotion(bool a) { _bf = (_bf & ~1) | a; return a; } bool AllowPromotion(bool a) { _bf = (_bf & ~2) | (a << 1); return a; } diff --git a/runtime/druntime/src/core/sys/windows/winuser.d b/runtime/druntime/src/core/sys/windows/winuser.d index f641444078..a7917b774f 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); From 46333a8d5d22bf6d5f4bdcf7b18ee78188f9a1aa Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 29 Mar 2025 01:36:10 +0100 Subject: [PATCH 037/113] Fix dlang/dmd!21105: Is-expressions should not generate unnecessary code for lowerings (dlang/dmd!21106) treat as if compiling with __traits(compiles) --- dmd/dscope.d | 2 +- dmd/expressionsem.d | 1 + tests/dmd/compilable/extra-files/vcg-ast.d.cg | 2 ++ tests/dmd/compilable/vcg-ast.d | 11 +++++++++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/dmd/dscope.d b/dmd/dscope.d index 70829f5f36..1a6fd4f1cf 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/expressionsem.d b/dmd/expressionsem.d index fbfc5f6398..063c19456f 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -7304,6 +7304,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 diff --git a/tests/dmd/compilable/extra-files/vcg-ast.d.cg b/tests/dmd/compilable/extra-files/vcg-ast.d.cg index e10394169f..d7b062fba8 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/vcg-ast.d b/tests/dmd/compilable/vcg-ast.d index 9197441aff..bcb7256723 100644 --- a/tests/dmd/compilable/vcg-ast.d +++ b/tests/dmd/compilable/vcg-ast.d @@ -75,3 +75,14 @@ template imported() } alias myImport = imported!(); + +// https://github.com/dlang/dmd/issues/21105 + +enum compiles = __traits(compiles,{ + int[] arr; + arr ~= 1; +}); +enum isexp = is(typeof({ + int[] arr; + arr ~= 1; +})); From 6c00ee1dca1b1ac0ba5b992a59f3f48aa47bcd69 Mon Sep 17 00:00:00 2001 From: Dennis Date: Sat, 29 Mar 2025 13:57:10 +0100 Subject: [PATCH 038/113] Fix dlang/dmd!21024 - Optimize x^^c expressions (dlang/dmd!21082) (dlang/dmd!21115) * Fix dlang/dmd!21024 - Optimize x^^c expressions Reason for the *magic* constraint c<8 on inlining x^^c: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/x86_64/fpu/e_powl.S;h=47f129f34d368d7c67b8e5f2462b36b0bebb7621;hb=HEAD#l136 * Fix poor assumption about expression state * Restrict optimization to floating point expressions * Generalize optimization to any scalar data type * Fix segfault on x^^c where x is a single member anonymous enum DMD segfaulted on compiling the unittests in std/algorithm/sorting.o, the unittest that caused the segfault can be reduced to: enum real Two = 2.0; auto _ = Two^^3; I'm not sure why copying the anonymous enum into a `const` variable causes the compiler to segfault. * Add tests to x^^c inlining optimization * Fix missing type for e1 ^^ -1 to 1 / e1 rewrite * Move rewrites from constant folding to expression semantic and restrict them to [-1, 2] * Improve error message for the x^^2 rewrite. Before: ex.d(4): Error: can implicitly convert expression `(const const(double) __powtmp2 = x + 5.0;) , __powtmp2 * ...` of type `double` to `int` int y = ( x + 5 ) ^^ 2; ^ and after: ex.d(4): Error: cannot implicitly convert expression `(x + 5.0) ^^ 2L` of type `double` to `int` int y = ( x + 5 ) ^^ 2; ^ * Update C++ frontend header to match change in `CommaExp` * Address code review feedback --------- Co-authored-by: Fares A. Bakhit --- dmd/expression.d | 9 +++++ dmd/expression.h | 1 + dmd/expressionsem.d | 52 ++++++++++++++++++++++++++ dmd/frontend.h | 1 + dmd/hdrgen.d | 6 +++ tests/dmd/fail_compilation/powinline.d | 38 +++++++++++++++++++ tests/dmd/runnable/powinline.d | 44 ++++++++++++++++++++++ 7 files changed, 151 insertions(+) create mode 100644 tests/dmd/fail_compilation/powinline.d create mode 100644 tests/dmd/runnable/powinline.d diff --git a/dmd/expression.d b/dmd/expression.d index a1d770a18f..63150bb483 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -3852,6 +3852,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 { @@ -3859,6 +3862,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 3c8d90dd7e..4a232fe7ae 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -990,6 +990,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 063c19456f..195cede3b7 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -12798,6 +12798,58 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } + // Inline the expression, if possible. + PowExp pe = cast(PowExp)e; + if (pe.e1.type.isScalar() && pe.e2.isIntegerExp()) + { + Expression one; + if (pe.e1.type.isIntegral()) { + one = new IntegerExp(e.loc, 1, pe.e1.type); + } else { + one = new RealExp(e.loc, CTFloat.one, pe.e1.type); + } + + const expo = cast(sinteger_t)pe.e2.toInteger(); + // Replace e1 ^^ -1 with 1 / e1 + if (expo == -1) + { + Expression ex = new DivExp(exp.loc, one, pe.e1); + ex = ex.expressionSemantic(sc); + result = ex; + return; + } + // Replace e1 ^^ 0 with 1 + else if (expo == 0) + { + Expression ex = one; + ex.loc = exp.loc; + 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) { diff --git a/dmd/frontend.h b/dmd/frontend.h index 6b95c82b45..fb0b6ac54b 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -2771,6 +2771,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; diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index d33bff1c6d..9b53114d6b 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -2724,6 +2724,12 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt void visitComma(CommaExp e) { + if (e.originalExp !is null) + { + e.originalExp.expressionPrettyPrint(buf, hgs); + return; + } + // CommaExp is generated by the compiler so it shouldn't // appear in error messages or header files. // For now, this treats the case where the compiler diff --git a/tests/dmd/fail_compilation/powinline.d b/tests/dmd/fail_compilation/powinline.d new file mode 100644 index 0000000000..11ebacd16a --- /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/runnable/powinline.d b/tests/dmd/runnable/powinline.d new file mode 100644 index 0000000000..7ec512c526 --- /dev/null +++ b/tests/dmd/runnable/powinline.d @@ -0,0 +1,44 @@ +/* +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); +} + +extern(C) void main() +{ + test1(); + test2(); + test3(); + printf("Success\n"); +} From 7489ac0f847be895d4a9de537954a69620a86bc6 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sat, 29 Mar 2025 18:55:30 +0100 Subject: [PATCH 039/113] pow: Ensure side effects are evaluated in e1^^0 rewrite --- dmd/expressionsem.d | 5 ++--- tests/dmd/runnable/powinline.d | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 195cede3b7..7ea0969fab 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -12818,11 +12818,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor result = ex; return; } - // Replace e1 ^^ 0 with 1 + // Replace e1 ^^ 0 with (e1, 1) else if (expo == 0) { - Expression ex = one; - ex.loc = exp.loc; + Expression ex = new CommaExp(exp.loc, pe.e1, one, exp); ex = ex.expressionSemantic(sc); result = ex; return; diff --git a/tests/dmd/runnable/powinline.d b/tests/dmd/runnable/powinline.d index 7ec512c526..92d1c04e55 100644 --- a/tests/dmd/runnable/powinline.d +++ b/tests/dmd/runnable/powinline.d @@ -35,10 +35,30 @@ void test3() 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"); } From 24e3c4a07188f8cb8fc3aa75b6a105141edb7e1b Mon Sep 17 00:00:00 2001 From: Dennis Date: Mon, 31 Mar 2025 15:54:53 +0200 Subject: [PATCH 040/113] merge stable (dlang/dmd!21127) * bump VERSION to v2.110.0 * purge changelog * bump VERSION to v2.111.0-beta.1 * Accept __rvalue attribute on ref functions; which will force the result to be treated as __rvalue. (dlang/dmd!20946) This is essential to implement `move`, `forward`, etc. * memoryerror.d: Fix AnySupported version condition (dlang/dmd!20983) * Fix dlang/dmd!20982 - wrong line number in iasmgcc (dlang/dmd!20993) * Move genCfunc to cxxfrontend (dlang/dmd!20992) * druntime: Fix compilation of rt.cover on Android (dlang/dmd!21015) * Expose SourceLoc to C++ interface (dlang/dmd!20980) * [stable] C++ header fixes for declaration, expression, and typinf (dlang/dmd!21016) Seen either from compilation errors or missing symbols at link time. * C++ headers: Add 3 Declaration bitfield setters/getters required by LDC * druntime: Add module declaration to rt.invariant, to prevent conflicts with user-provided invariant.d (dlang/dmd!21017) * Fix dlang/dmd!21020 - Indexing a *cast* AA yields no lvalue anymore (dlang/dmd!21029) * Add C++23 to CppStdRevision enum (dlang/dmd!21043) * Improve UFCS/property error message (dlang/dmd!21046) * bump VERSION to v2.111.0-rc.1 * Fix dlang/dmd!21045 - import __stdin causes compilation to pause while reading from stdin (dlang/dmd!21047) Moves the special handling of reading from stdin out of the semantic routines to the DMD driver itself. All references to `__stdin.d` have also been removed from the frontend implementation. * Update source code and coverage links (dlang/dmd!21111) * Fix dlang/dmd!21024 - Optimize x^^c expressions (dlang/dmd!21082) * Fix dlang/dmd!21024 - Optimize x^^c expressions Reason for the *magic* constraint c<8 on inlining x^^c: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/x86_64/fpu/e_powl.S;h=47f129f34d368d7c67b8e5f2462b36b0bebb7621;hb=HEAD#l136 * Fix poor assumption about expression state * Restrict optimization to floating point expressions * Generalize optimization to any scalar data type * Fix segfault on x^^c where x is a single member anonymous enum DMD segfaulted on compiling the unittests in std/algorithm/sorting.o, the unittest that caused the segfault can be reduced to: enum real Two = 2.0; auto _ = Two^^3; I'm not sure why copying the anonymous enum into a `const` variable causes the compiler to segfault. * Add tests to x^^c inlining optimization * Fix missing type for e1 ^^ -1 to 1 / e1 rewrite * Move rewrites from constant folding to expression semantic and restrict them to [-1, 2] * Improve error message for the x^^2 rewrite. Before: ex.d(4): Error: can implicitly convert expression `(const const(double) __powtmp2 = x + 5.0;) , __powtmp2 * ...` of type `double` to `int` int y = ( x + 5 ) ^^ 2; ^ and after: ex.d(4): Error: cannot implicitly convert expression `(x + 5.0) ^^ 2L` of type `double` to `int` int y = ( x + 5 ) ^^ 2; ^ * Update C++ frontend header to match change in `CommaExp` * Address code review feedback Co-authored-by: Dennis Korpel --------- Co-authored-by: Dennis Korpel * Revert "Fix dlang/dmd!21024 - Optimize x^^c expressions (dlang/dmd!21082)" (dlang/dmd!21114) This reverts commit 601bef533244166f1f114d424e6d3b3f8119d697. * bump VERSION to v2.111.0 * purge changelog * Strip trailing newline off sarif version --------- Co-authored-by: Manu Evans Co-authored-by: Martin Kinkelin Co-authored-by: Iain Buclaw Co-authored-by: Martin Kinkelin Co-authored-by: Fares A. Bakhit --- dmd/access.d | 4 +- dmd/aggregate.d | 4 +- dmd/aliasthis.d | 4 +- dmd/argtypes_aarch64.d | 4 +- dmd/argtypes_sysv_x64.d | 4 +- dmd/argtypes_x86.d | 4 +- dmd/arrayop.d | 4 +- dmd/arraytypes.d | 4 +- dmd/ast_node.d | 4 +- dmd/astenums.d | 4 +- dmd/asttypename.d | 4 +- dmd/attrib.d | 4 +- dmd/attribsem.d | 4 +- dmd/blockexit.d | 4 +- dmd/builtin.d | 4 +- dmd/canthrow.d | 4 +- dmd/chkformat.d | 4 +- dmd/cli.d | 4 +- dmd/clone.d | 4 +- dmd/common/bitfields.d | 4 +- dmd/common/charactertables.d | 4 +- dmd/common/charactertables.h | 2 +- dmd/common/file.d | 4 +- dmd/common/int128.d | 4 +- dmd/common/outbuffer.d | 4 +- dmd/common/smallbuffer.d | 4 +- dmd/compiler.d | 4 +- dmd/cond.d | 4 +- dmd/console.d | 4 +- dmd/constfold.d | 4 +- dmd/cparse.d | 4 +- dmd/ctfeexpr.d | 4 +- dmd/ctorflow.d | 4 +- dmd/cxxfrontend.d | 4 +- dmd/dcast.d | 4 +- dmd/dclass.d | 4 +- dmd/declaration.d | 4 +- dmd/delegatize.d | 4 +- dmd/denum.d | 4 +- dmd/deps.d | 4 +- dmd/dimport.d | 4 +- dmd/dinterpret.d | 4 +- dmd/dmacro.d | 4 +- dmd/dmodule.d | 12 +--- dmd/doc.d | 4 +- dmd/dscope.d | 4 +- dmd/dstruct.d | 4 +- dmd/dsymbol.d | 4 +- dmd/dsymbolsem.d | 4 +- dmd/dtemplate.d | 4 +- dmd/dtoh.d | 4 +- dmd/dversion.d | 4 +- dmd/entity.d | 4 +- dmd/enumsem.d | 4 +- dmd/errors.d | 4 +- dmd/errorsink.d | 4 +- dmd/escape.d | 4 +- dmd/expression.d | 4 +- dmd/expressionsem.d | 4 +- dmd/file_manager.d | 59 +++---------------- dmd/frontend.h | 5 +- dmd/func.d | 4 +- dmd/funcsem.d | 4 +- dmd/globals.d | 5 +- dmd/globals.h | 1 + dmd/gluelayer.d | 4 +- dmd/hdrgen.d | 4 +- dmd/iasmgcc.d | 4 +- dmd/id.d | 4 +- dmd/identifier.d | 4 +- dmd/impcnvtab.d | 4 +- dmd/imphint.d | 4 +- dmd/importc.d | 4 +- dmd/init.d | 4 +- dmd/initsem.d | 4 +- dmd/inline.d | 4 +- dmd/inlinecost.d | 4 +- dmd/intrange.d | 4 +- dmd/json.d | 4 +- dmd/lambdacomp.d | 4 +- dmd/lexer.d | 4 +- dmd/location.d | 4 +- dmd/main.d | 6 +- dmd/mangle/basic.d | 4 +- dmd/mangle/cpp.d | 4 +- dmd/mangle/cppwin.d | 4 +- dmd/mangle/package.d | 4 +- dmd/mars.d | 79 ++++++++++++++++++++++++-- dmd/mtype.d | 4 +- dmd/mustuse.d | 4 +- dmd/nogc.d | 4 +- dmd/nspace.d | 4 +- dmd/ob.d | 4 +- dmd/objc.d | 4 +- dmd/opover.d | 4 +- dmd/optimize.d | 4 +- dmd/parse.d | 4 +- dmd/pragmasem.d | 4 +- dmd/printast.d | 4 +- dmd/root/aav.d | 4 +- dmd/root/array.d | 4 +- dmd/root/bitarray.d | 4 +- dmd/root/complex.d | 4 +- dmd/root/ctfloat.d | 4 +- dmd/root/file.d | 4 +- dmd/root/filename.d | 4 +- dmd/root/hash.d | 4 +- dmd/root/man.d | 4 +- dmd/root/optional.d | 4 +- dmd/root/optional.h | 4 +- dmd/root/port.d | 4 +- dmd/root/region.d | 4 +- dmd/root/rmem.d | 4 +- dmd/root/speller.d | 4 +- dmd/root/string.d | 4 +- dmd/root/stringtable.d | 4 +- dmd/root/utf.d | 4 +- dmd/rootobject.d | 4 +- dmd/safe.d | 4 +- dmd/sarif.d | 9 ++- dmd/semantic2.d | 4 +- dmd/semantic3.d | 4 +- dmd/sideeffect.d | 4 +- dmd/statement.d | 4 +- dmd/statementsem.d | 4 +- dmd/staticassert.d | 4 +- dmd/staticcond.d | 4 +- dmd/stmtstate.d | 4 +- dmd/target.d | 4 +- dmd/templateparamsem.d | 4 +- dmd/templatesem.d | 4 +- dmd/timetrace.d | 4 +- dmd/tokens.d | 4 +- dmd/traits.d | 4 +- dmd/typesem.d | 4 +- dmd/typinf.d | 4 +- dmd/utils.d | 4 +- dmd/visitor/foreachvar.d | 4 +- dmd/visitor/package.d | 4 +- dmd/visitor/postorder.d | 4 +- dmd/visitor/statement_rewrite_walker.d | 4 +- dmd/vsoptions.d | 4 +- tests/dmd/fail_compilation/fail21045.d | 12 ++++ 143 files changed, 380 insertions(+), 342 deletions(-) create mode 100644 tests/dmd/fail_compilation/fail21045.d diff --git a/dmd/access.d b/dmd/access.d index df04216323..eaaa288cb4 100644 --- a/dmd/access.d +++ b/dmd/access.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/access.d, _access.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/access.d, _access.d) * Documentation: https://dlang.org/phobos/dmd_access.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/access.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/access.d */ module dmd.access; diff --git a/dmd/aggregate.d b/dmd/aggregate.d index 25a8771f3b..51d6fc4595 100644 --- a/dmd/aggregate.d +++ b/dmd/aggregate.d @@ -7,9 +7,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/aggregate.d, _aggregate.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/aggregate.d, _aggregate.d) * Documentation: https://dlang.org/phobos/dmd_aggregate.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/aggregate.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/aggregate.d */ module dmd.aggregate; diff --git a/dmd/aliasthis.d b/dmd/aliasthis.d index aec18694c0..632cf95e80 100644 --- a/dmd/aliasthis.d +++ b/dmd/aliasthis.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/aliasthis.d, _aliasthis.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/aliasthis.d, _aliasthis.d) * Documentation: https://dlang.org/phobos/dmd_aliasthis.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/aliasthis.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/aliasthis.d */ module dmd.aliasthis; diff --git a/dmd/argtypes_aarch64.d b/dmd/argtypes_aarch64.d index a2e185f91b..545f11edfb 100644 --- a/dmd/argtypes_aarch64.d +++ b/dmd/argtypes_aarch64.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Martin Kinkelin * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/argtypes_aarch64.d, _argtypes_aarch64.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/argtypes_aarch64.d, _argtypes_aarch64.d) * Documentation: https://dlang.org/phobos/dmd_argtypes_aarch64.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/argtypes_aarch64.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/argtypes_aarch64.d */ module dmd.argtypes_aarch64; diff --git a/dmd/argtypes_sysv_x64.d b/dmd/argtypes_sysv_x64.d index e9f0cf857e..9cd4e514a6 100644 --- a/dmd/argtypes_sysv_x64.d +++ b/dmd/argtypes_sysv_x64.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Martin Kinkelin * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/argtypes_sysv_x64.d, _argtypes_sysv_x64.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/argtypes_sysv_x64.d, _argtypes_sysv_x64.d) * Documentation: https://dlang.org/phobos/dmd_argtypes_sysv_x64.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/argtypes_sysv_x64.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/argtypes_sysv_x64.d */ module dmd.argtypes_sysv_x64; diff --git a/dmd/argtypes_x86.d b/dmd/argtypes_x86.d index 62fdf88d5c..9f5adcf21b 100644 --- a/dmd/argtypes_x86.d +++ b/dmd/argtypes_x86.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/argtypes_x86.d, _argtypes_x86.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/argtypes_x86.d, _argtypes_x86.d) * Documentation: https://dlang.org/phobos/dmd_argtypes_x86.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/argtypes_x86.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/argtypes_x86.d */ module dmd.argtypes_x86; diff --git a/dmd/arrayop.d b/dmd/arrayop.d index 3129eb513a..7d25e18512 100644 --- a/dmd/arrayop.d +++ b/dmd/arrayop.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/arrayop.d, _arrayop.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/arrayop.d, _arrayop.d) * Documentation: https://dlang.org/phobos/dmd_arrayop.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/arrayop.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/arrayop.d */ module dmd.arrayop; diff --git a/dmd/arraytypes.d b/dmd/arraytypes.d index e09fb43a1b..2cd446ea5e 100644 --- a/dmd/arraytypes.d +++ b/dmd/arraytypes.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/arraytypes.d, _arraytypes.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/arraytypes.d, _arraytypes.d) * Documentation: https://dlang.org/phobos/dmd_arraytypes.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/arraytypes.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/arraytypes.d */ module dmd.arraytypes; diff --git a/dmd/ast_node.d b/dmd/ast_node.d index 3f2b221236..ad49169947 100644 --- a/dmd/ast_node.d +++ b/dmd/ast_node.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ast_node.d, _ast_node.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/ast_node.d, _ast_node.d) * Documentation: https://dlang.org/phobos/dmd_ast_node.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/ast_node.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/ast_node.d */ module dmd.ast_node; diff --git a/dmd/astenums.d b/dmd/astenums.d index 2bbf1e0d26..b71b6c40ae 100644 --- a/dmd/astenums.d +++ b/dmd/astenums.d @@ -3,9 +3,9 @@ * * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/astenums.d, _astenums.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/astenums.d, _astenums.d) * Documentation: https://dlang.org/phobos/dmd_astenums.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/astenums.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/astenums.d */ module dmd.astenums; diff --git a/dmd/asttypename.d b/dmd/asttypename.d index fabc12eb32..8642288f58 100644 --- a/dmd/asttypename.d +++ b/dmd/asttypename.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Stefan Koch * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/asttypename.d, _asttypename.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/asttypename.d, _asttypename.d) * Documentation: https://dlang.org/phobos/dmd_asttypename.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/asttypename.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/asttypename.d */ module dmd.asttypename; diff --git a/dmd/attrib.d b/dmd/attrib.d index 7135c28fb9..1bfe7902a9 100644 --- a/dmd/attrib.d +++ b/dmd/attrib.d @@ -17,9 +17,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/attrib.d, _attrib.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/attrib.d, _attrib.d) * Documentation: https://dlang.org/phobos/dmd_attrib.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/attrib.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/attrib.d */ module dmd.attrib; diff --git a/dmd/attribsem.d b/dmd/attribsem.d index 78a3b475a3..bc966bb8eb 100644 --- a/dmd/attribsem.d +++ b/dmd/attribsem.d @@ -17,9 +17,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/attribsem.d, _attrib.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/attribsem.d, _attrib.d) * Documentation: https://dlang.org/phobos/dmd_attribsem.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/attribsem.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/attribsem.d */ module dmd.attribsem; diff --git a/dmd/blockexit.d b/dmd/blockexit.d index 32012d41db..ae2f12f323 100644 --- a/dmd/blockexit.d +++ b/dmd/blockexit.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/blockexit.d, _blockexit.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/blockexit.d, _blockexit.d) * Documentation: https://dlang.org/phobos/dmd_blockexit.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/blockexit.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/blockexit.d */ module dmd.blockexit; diff --git a/dmd/builtin.d b/dmd/builtin.d index bb4425cd70..17e69b2e1d 100644 --- a/dmd/builtin.d +++ b/dmd/builtin.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/builtin.d, _builtin.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/builtin.d, _builtin.d) * Documentation: https://dlang.org/phobos/dmd_builtin.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/builtin.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/builtin.d */ module dmd.builtin; diff --git a/dmd/canthrow.d b/dmd/canthrow.d index a209a0ce77..96acf05529 100644 --- a/dmd/canthrow.d +++ b/dmd/canthrow.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/canthrow.d, _canthrow.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/canthrow.d, _canthrow.d) * Documentation: https://dlang.org/phobos/dmd_canthrow.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/canthrow.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/canthrow.d */ module dmd.canthrow; diff --git a/dmd/chkformat.d b/dmd/chkformat.d index a16605ef6a..8b2d5b4dd4 100644 --- a/dmd/chkformat.d +++ b/dmd/chkformat.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/chkformat.d, _chkformat.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/chkformat.d, _chkformat.d) * Documentation: https://dlang.org/phobos/dmd_chkformat.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/chkformat.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/chkformat.d */ module dmd.chkformat; diff --git a/dmd/cli.d b/dmd/cli.d index 771f1be6d0..9e231f1c78 100644 --- a/dmd/cli.d +++ b/dmd/cli.d @@ -8,9 +8,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cli.d, _cli.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cli.d, _cli.d) * Documentation: https://dlang.org/phobos/dmd_cli.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/cli.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/cli.d */ module dmd.cli; diff --git a/dmd/clone.d b/dmd/clone.d index 9121517e3e..a21f5a05be 100644 --- a/dmd/clone.d +++ b/dmd/clone.d @@ -5,9 +5,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/clone.d, _clone.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/clone.d, _clone.d) * Documentation: https://dlang.org/phobos/dmd_clone.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/clone.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/clone.d */ module dmd.clone; diff --git a/dmd/common/bitfields.d b/dmd/common/bitfields.d index a157f122ae..72cb3e7d91 100644 --- a/dmd/common/bitfields.d +++ b/dmd/common/bitfields.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Dennis Korpel * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/bitfields.d, common/bitfields.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/bitfields.d, common/bitfields.d) * Documentation: https://dlang.org/phobos/dmd_common_bitfields.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/bitfields.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/common/bitfields.d */ module dmd.common.bitfields; diff --git a/dmd/common/charactertables.d b/dmd/common/charactertables.d index 9358667116..7df5234904 100644 --- a/dmd/common/charactertables.d +++ b/dmd/common/charactertables.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://cattermole.co.nz, Richard (Rikki) Andrew Cattermole) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/charactertables.d, common/charactertables.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/charactertables.d, common/charactertables.d) * Documentation: https://dlang.org/phobos/dmd_common_charactertables.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/charactertables.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/common/charactertables.d */ module dmd.common.charactertables; diff --git a/dmd/common/charactertables.h b/dmd/common/charactertables.h index 2c21767da7..b38409e302 100644 --- a/dmd/common/charactertables.h +++ b/dmd/common/charactertables.h @@ -6,7 +6,7 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://cattermole.co.nz, Richard (Rikki) Andrew Cattermole) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/charactertables.d, common/charactertables.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/charactertables.h, common/charactertables.d) */ #pragma once diff --git a/dmd/common/file.d b/dmd/common/file.d index 66238f7829..1b01a28229 100644 --- a/dmd/common/file.d +++ b/dmd/common/file.d @@ -7,9 +7,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/file.d, common/_file.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/file.d, common/_file.d) * Documentation: https://dlang.org/phobos/dmd_common_file.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/file.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/common/file.d */ module dmd.common.file; diff --git a/dmd/common/int128.d b/dmd/common/int128.d index 011bf40506..aaf38c5157 100644 --- a/dmd/common/int128.d +++ b/dmd/common/int128.d @@ -5,9 +5,9 @@ * Copyright: Copyright (C) 2022-2025 by The D Language Foundation, All Rights Reserved * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Authors: Walter Bright - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/int128.d, root/_int128.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/int128.d, root/_int128.d) * Documentation: https://dlang.org/phobos/dmd_common_int128.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/int128.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/common/int128.d */ module dmd.common.int128; diff --git a/dmd/common/outbuffer.d b/dmd/common/outbuffer.d index c0ac098502..01fc377400 100644 --- a/dmd/common/outbuffer.d +++ b/dmd/common/outbuffer.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/outbuffer.d, root/_outbuffer.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/outbuffer.d, root/_outbuffer.d) * Documentation: https://dlang.org/phobos/dmd_root_outbuffer.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/outbuffer.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/common/outbuffer.d */ module dmd.common.outbuffer; diff --git a/dmd/common/smallbuffer.d b/dmd/common/smallbuffer.d index a5674820c4..65adec68f4 100644 --- a/dmd/common/smallbuffer.d +++ b/dmd/common/smallbuffer.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/smallbuffer.d, common/_smallbuffer.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/smallbuffer.d, common/_smallbuffer.d) * Documentation: https://dlang.org/phobos/dmd_common_smallbuffer.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/smallbuffer + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/common/smallbuffer.d */ module dmd.common.smallbuffer; diff --git a/dmd/compiler.d b/dmd/compiler.d index 562870a8a4..1f043352c4 100644 --- a/dmd/compiler.d +++ b/dmd/compiler.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/compiler.d, _compiler.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/compiler.d, _compiler.d) * Documentation: https://dlang.org/phobos/dmd_compiler.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/compiler.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/compiler.d */ module dmd.compiler; diff --git a/dmd/cond.d b/dmd/cond.d index 9e562b6b9c..31c01f1853 100644 --- a/dmd/cond.d +++ b/dmd/cond.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cond.d, _cond.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cond.d, _cond.d) * Documentation: https://dlang.org/phobos/dmd_cond.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/cond.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/cond.d */ module dmd.cond; diff --git a/dmd/console.d b/dmd/console.d index 801103eded..29dc9fb300 100644 --- a/dmd/console.d +++ b/dmd/console.d @@ -5,9 +5,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/console.d, _console.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/console.d, _console.d) * Documentation: https://dlang.org/phobos/dmd_console.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/console.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/console.d */ module dmd.console; diff --git a/dmd/constfold.d b/dmd/constfold.d index 0e07bfaf63..fad9c9ac44 100644 --- a/dmd/constfold.d +++ b/dmd/constfold.d @@ -8,9 +8,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/constfold.d, _constfold.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/constfold.d, _constfold.d) * Documentation: https://dlang.org/phobos/dmd_constfold.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/constfold.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/constfold.d */ module dmd.constfold; diff --git a/dmd/cparse.d b/dmd/cparse.d index 6a81fdf315..c7650c6c51 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cparse.d, _cparse.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cparse.d, _cparse.d) * Documentation: https://dlang.org/phobos/dmd_cparse.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/cparse.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/cparse.d */ module dmd.cparse; diff --git a/dmd/ctfeexpr.d b/dmd/ctfeexpr.d index 007e693105..2f577cea92 100644 --- a/dmd/ctfeexpr.d +++ b/dmd/ctfeexpr.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ctfeexpr.d, _ctfeexpr.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/ctfeexpr.d, _ctfeexpr.d) * Documentation: https://dlang.org/phobos/dmd_ctfeexpr.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/ctfeexpr.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/ctfeexpr.d */ module dmd.ctfeexpr; diff --git a/dmd/ctorflow.d b/dmd/ctorflow.d index 3cf9c6917c..e604700e1f 100644 --- a/dmd/ctorflow.d +++ b/dmd/ctorflow.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ctorflow.d, _ctorflow.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/ctorflow.d, _ctorflow.d) * Documentation: https://dlang.org/phobos/dmd_ctorflow.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/ctorflow.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/ctorflow.d */ module dmd.ctorflow; diff --git a/dmd/cxxfrontend.d b/dmd/cxxfrontend.d index b3d5942696..234b6523af 100644 --- a/dmd/cxxfrontend.d +++ b/dmd/cxxfrontend.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cxxfrontend.d, _cxxfrontend.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cxxfrontend.d, _cxxfrontend.d) * Documentation: https://dlang.org/phobos/dmd_cxxfrontend.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/cxxfrontend.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/cxxfrontend.d */ module dmd.cxxfrontend; diff --git a/dmd/dcast.d b/dmd/dcast.d index a4276a43e2..1f9126069f 100644 --- a/dmd/dcast.d +++ b/dmd/dcast.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dcast.d, _dcast.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dcast.d, _dcast.d) * Documentation: https://dlang.org/phobos/dmd_dcast.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dcast.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/dcast.d */ module dmd.dcast; diff --git a/dmd/dclass.d b/dmd/dclass.d index 50a1235e3e..80d39fac42 100644 --- a/dmd/dclass.d +++ b/dmd/dclass.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dclass.d, _dclass.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dclass.d, _dclass.d) * Documentation: https://dlang.org/phobos/dmd_dclass.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dclass.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/dclass.d */ module dmd.dclass; diff --git a/dmd/declaration.d b/dmd/declaration.d index e64acb2379..4510927da7 100644 --- a/dmd/declaration.d +++ b/dmd/declaration.d @@ -5,9 +5,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/declaration.d, _declaration.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/declaration.d, _declaration.d) * Documentation: https://dlang.org/phobos/dmd_declaration.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/declaration.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/declaration.d */ module dmd.declaration; diff --git a/dmd/delegatize.d b/dmd/delegatize.d index fa84db1c84..344130b5e3 100644 --- a/dmd/delegatize.d +++ b/dmd/delegatize.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/delegatize.d, _delegatize.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/delegatize.d, _delegatize.d) * Documentation: https://dlang.org/phobos/dmd_delegatize.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/delegatize.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/delegatize.d */ module dmd.delegatize; diff --git a/dmd/denum.d b/dmd/denum.d index 401a7a1587..e1a4ab6d6a 100644 --- a/dmd/denum.d +++ b/dmd/denum.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/denum.d, _denum.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/denum.d, _denum.d) * Documentation: https://dlang.org/phobos/dmd_denum.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/denum.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/denum.d * References: https://dlang.org/spec/enum.html */ diff --git a/dmd/deps.d b/dmd/deps.d index 1399e6f796..d62d670938 100644 --- a/dmd/deps.d +++ b/dmd/deps.d @@ -24,9 +24,9 @@ * * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/deps.d, makedeps.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/deps.d, makedeps.d) * Documentation: https://dlang.org/phobos/dmd_deps.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/deps.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/deps.d */ module dmd.deps; diff --git a/dmd/dimport.d b/dmd/dimport.d index 38f86d36e5..bbd74a4da2 100644 --- a/dmd/dimport.d +++ b/dmd/dimport.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dimport.d, _dimport.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dimport.d, _dimport.d) * Documentation: https://dlang.org/phobos/dmd_dimport.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dimport.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/dimport.d */ module dmd.dimport; diff --git a/dmd/dinterpret.d b/dmd/dinterpret.d index b223975f38..543c0e22e3 100644 --- a/dmd/dinterpret.d +++ b/dmd/dinterpret.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dinterpret.d, _dinterpret.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dinterpret.d, _dinterpret.d) * Documentation: https://dlang.org/phobos/dmd_dinterpret.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dinterpret.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/dinterpret.d */ module dmd.dinterpret; diff --git a/dmd/dmacro.d b/dmd/dmacro.d index af3d5dd6f3..307b43fb63 100644 --- a/dmd/dmacro.d +++ b/dmd/dmacro.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dmacro.d, _dmacro.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dmacro.d, _dmacro.d) * Documentation: https://dlang.org/phobos/dmd_dmacro.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dmacro.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/dmacro.d */ module dmd.dmacro; diff --git a/dmd/dmodule.d b/dmd/dmodule.d index 6c7416856a..0e0070aab5 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dmodule.d, _dmodule.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dmodule.d, _dmodule.d) * Documentation: https://dlang.org/phobos/dmd_dmodule.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dmodule.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/dmodule.d */ module dmd.dmodule; @@ -58,12 +58,10 @@ import dmd.visitor; version (Windows) { - import core.sys.windows.winbase : getpid = GetCurrentProcessId; enum PathSeparator = '\\'; } else version (Posix) { - import core.sys.posix.unistd : getpid; enum PathSeparator = '/'; } else @@ -577,12 +575,6 @@ extern (C++) final class Module : Package else { const(char)[] argdoc; - OutBuffer buf; - if (arg == "__stdin.d") - { - buf.printf("__stdin_%d.d", getpid()); - arg = buf[]; - } if (global.params.preservePaths) argdoc = arg; else diff --git a/dmd/doc.d b/dmd/doc.d index f3ca53fc11..dc4a0b9ace 100644 --- a/dmd/doc.d +++ b/dmd/doc.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/doc.d, _doc.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/doc.d, _doc.d) * Documentation: https://dlang.org/phobos/dmd_doc.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/doc.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/doc.d */ module dmd.doc; diff --git a/dmd/dscope.d b/dmd/dscope.d index 1a6fd4f1cf..c70e7d381b 100644 --- a/dmd/dscope.d +++ b/dmd/dscope.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dscope.d, _dscope.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dscope.d, _dscope.d) * Documentation: https://dlang.org/phobos/dmd_dscope.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dscope.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/dscope.d */ module dmd.dscope; diff --git a/dmd/dstruct.d b/dmd/dstruct.d index 1896e37edf..4c7011bc6a 100644 --- a/dmd/dstruct.d +++ b/dmd/dstruct.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dstruct.d, _dstruct.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dstruct.d, _dstruct.d) * Documentation: https://dlang.org/phobos/dmd_dstruct.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dstruct.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/dstruct.d */ module dmd.dstruct; diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index 3e40dbef61..74ca9cbda4 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dsymbol.d, _dsymbol.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dsymbol.d, _dsymbol.d) * Documentation: https://dlang.org/phobos/dmd_dsymbol.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dsymbol.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/dsymbol.d */ module dmd.dsymbol; diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 54165857fd..fb7d608da5 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -5,9 +5,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dsymbolsem.d, _dsymbolsem.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dsymbolsem.d, _dsymbolsem.d) * Documentation: https://dlang.org/phobos/dmd_dsymbolsem.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dsymbolsem.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/dsymbolsem.d */ module dmd.dsymbolsem; diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 3efe77d88f..2158895745 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -31,9 +31,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dtemplate.d, _dtemplate.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dtemplate.d, _dtemplate.d) * Documentation: https://dlang.org/phobos/dmd_dtemplate.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dtemplate.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/dtemplate.d */ module dmd.dtemplate; diff --git a/dmd/dtoh.d b/dmd/dtoh.d index efc71ad075..3946c25c9f 100644 --- a/dmd/dtoh.d +++ b/dmd/dtoh.d @@ -5,9 +5,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dtohd, _dtoh.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dtoh.d, _dtoh.d) * Documentation: https://dlang.org/phobos/dmd_dtoh.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dtoh.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/dtoh.d */ module dmd.dtoh; diff --git a/dmd/dversion.d b/dmd/dversion.d index 6be7528c59..26528e9f51 100644 --- a/dmd/dversion.d +++ b/dmd/dversion.d @@ -7,9 +7,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dversion.d, _dversion.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/dversion.d, _dversion.d) * Documentation: https://dlang.org/phobos/dmd_dversion.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dversion.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/dversion.d */ module dmd.dversion; diff --git a/dmd/entity.d b/dmd/entity.d index 6457a62e1d..a70029b374 100644 --- a/dmd/entity.d +++ b/dmd/entity.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/entity.d, _entity.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/entity.d, _entity.d) * Documentation: https://dlang.org/phobos/dmd_entity.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/entity.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/entity.d */ module dmd.entity; diff --git a/dmd/enumsem.d b/dmd/enumsem.d index 829b42da2a..d79fb3723e 100644 --- a/dmd/enumsem.d +++ b/dmd/enumsem.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/enumsem.d, _enumsem.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/enumsem.d, _enumsem.d) * Documentation: https://dlang.org/phobos/dmd_enumsem.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/enumsem.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/enumsem.d */ module dmd.enumsem; diff --git a/dmd/errors.d b/dmd/errors.d index ae90c1002a..68bfa60a16 100644 --- a/dmd/errors.d +++ b/dmd/errors.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/errors.d, _errors.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/errors.d, _errors.d) * Documentation: https://dlang.org/phobos/dmd_errors.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/errors.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/errors.d */ module dmd.errors; diff --git a/dmd/errorsink.d b/dmd/errorsink.d index 5514449115..5793ef1c0e 100644 --- a/dmd/errorsink.d +++ b/dmd/errorsink.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 2023-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/errorsink.d, _errorsink.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/errorsink.d, _errorsink.d) * Documentation: https://dlang.org/phobos/dmd_errorsink.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/errorsink.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/errorsink.d */ module dmd.errorsink; diff --git a/dmd/escape.d b/dmd/escape.d index 719ac4b52c..a0c5472375 100644 --- a/dmd/escape.d +++ b/dmd/escape.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/escape.d, _escape.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/escape.d, _escape.d) * Documentation: https://dlang.org/phobos/dmd_escape.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/escape.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/escape.d */ module dmd.escape; diff --git a/dmd/expression.d b/dmd/expression.d index 63150bb483..8cb28cc208 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/expression.d, _expression.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/expression.d, _expression.d) * Documentation: https://dlang.org/phobos/dmd_expression.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/expression.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/expression.d */ module dmd.expression; diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 7ea0969fab..a300311bf1 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/expressionsem.d, _expressionsem.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/expressionsem.d, _expressionsem.d) * Documentation: https://dlang.org/phobos/dmd_expressionsem.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/expressionsem.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/expressionsem.d */ module dmd.expressionsem; diff --git a/dmd/file_manager.d b/dmd/file_manager.d index fc7824f039..2ccb1d2549 100644 --- a/dmd/file_manager.d +++ b/dmd/file_manager.d @@ -3,9 +3,9 @@ * * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/file_manager.d, _file_manager.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/file_manager.d, _file_manager.d) * Documentation: https://dlang.org/phobos/dmd_file_manager.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/file_manager.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/file_manager.d */ module dmd.file_manager; @@ -16,7 +16,6 @@ import dmd.root.stringtable : StringTable; import dmd.root.file : File, Buffer; import dmd.root.filename : FileName, isDirSeparator; import dmd.root.string : toDString; -import dmd.errors; import dmd.globals; import dmd.identifier; import dmd.location; @@ -184,9 +183,6 @@ nothrow: scope(exit) FileName.free(sdi.ptr); const sd = FileName.forceExt(filename, mars_ext); - // Special file name representing `stdin`, always assume its presence - if (sd == "__stdin.d") - return sd; if (checkLocal && FileName.exists(sd) == 1) return sd; scope(exit) FileName.free(sd.ptr); @@ -312,20 +308,12 @@ nothrow: if (auto val = files.lookup(name)) // if `name` is cached return val.value; // return its contents - OutBuffer buf; - if (name == "__stdin.d") // special name for reading from stdin - { - if (readFromStdin(buf)) - fatal(); - } - else - { - if (FileName.exists(name) != 1) // if not an ordinary file - return null; + if (FileName.exists(name) != 1) // if not an ordinary file + return null; - if (File.read(name, buf)) - return null; // failed - } + OutBuffer buf; + if (File.read(name, buf)) + return null; // failed buf.write32(0); // terminating dchar 0 @@ -351,36 +339,3 @@ nothrow: return val == null ? null : val.value; } } - -private bool readFromStdin(ref OutBuffer sink) nothrow -{ - import core.stdc.stdio; - import dmd.errors; - - enum BufIncrement = 128 * 1024; - - for (size_t j; 1; ++j) - { - char[] buffer = sink.allocate(BufIncrement); - - // Fill up buffer - size_t filled = 0; - do - { - filled += fread(buffer.ptr + filled, 1, buffer.length - filled, stdin); - if (ferror(stdin)) - { - import core.stdc.errno; - error(Loc.initial, "cannot read from stdin, errno = %d", errno); - return true; - } - if (feof(stdin)) // successful completion - { - sink.setsize(j * BufIncrement + filled); - return false; - } - } while (filled < BufIncrement); - } - - assert(0); -} diff --git a/dmd/frontend.h b/dmd/frontend.h index fb0b6ac54b..f1dc48f2f4 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -8417,6 +8417,7 @@ struct ImportPathInfo final struct Param final { bool obj; + bool readStdin; bool multiobj; bool trace; bool tracegc; @@ -8504,6 +8505,7 @@ struct Param final bool parsingUnittestsRequired(); Param() : obj(true), + readStdin(), multiobj(), trace(), tracegc(), @@ -8582,8 +8584,9 @@ struct Param final timeTraceFile() { } - Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool vcg_ast = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting useWarnings = (DiagnosticReporting)2u, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = true, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool useGC = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, Help help = Help(), Verbose v = Verbose(), FeatureState useDIP25 = (FeatureState)2u, FeatureState useDIP1000 = (FeatureState)0u, bool ehnogc = false, bool useDIP1021 = false, FeatureState fieldwise = (FeatureState)0u, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)0u, FeatureState safer = (FeatureState)0u, FeatureState noSharedAccess = (FeatureState)0u, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)0u, FeatureState systemVariables = (FeatureState)0u, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, CLIIdentifierTable dIdentifierTable = (CLIIdentifierTable)0u, CLIIdentifierTable cIdentifierTable = (CLIIdentifierTable)0u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array imppath = Array(), Array fileImppath = Array(), _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), bool debugEnabled = false, bool run = false, Array runargs = Array(), Array cppswitches = Array(), const char* cpp = nullptr, Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}, bool fullyQualifiedObjectFiles = false, bool timeTrace = false, uint32_t timeTraceGranularityUs = 500u, const char* timeTraceFile = nullptr) : + Param(bool obj, bool readStdin = false, bool multiobj = false, bool trace = false, bool tracegc = false, bool vcg_ast = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting useWarnings = (DiagnosticReporting)2u, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = true, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool useGC = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, Help help = Help(), Verbose v = Verbose(), FeatureState useDIP25 = (FeatureState)2u, FeatureState useDIP1000 = (FeatureState)0u, bool ehnogc = false, bool useDIP1021 = false, FeatureState fieldwise = (FeatureState)0u, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)0u, FeatureState safer = (FeatureState)0u, FeatureState noSharedAccess = (FeatureState)0u, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)0u, FeatureState systemVariables = (FeatureState)0u, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, CLIIdentifierTable dIdentifierTable = (CLIIdentifierTable)0u, CLIIdentifierTable cIdentifierTable = (CLIIdentifierTable)0u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array imppath = Array(), Array fileImppath = Array(), _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), bool debugEnabled = false, bool run = false, Array runargs = Array(), Array cppswitches = Array(), const char* cpp = nullptr, Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}, bool fullyQualifiedObjectFiles = false, bool timeTrace = false, uint32_t timeTraceGranularityUs = 500u, const char* timeTraceFile = nullptr) : obj(obj), + readStdin(readStdin), multiobj(multiobj), trace(trace), tracegc(tracegc), diff --git a/dmd/func.d b/dmd/func.d index 50479f78c8..6a573810a4 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -11,9 +11,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/func.d, _func.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/func.d, _func.d) * Documentation: https://dlang.org/phobos/dmd_func.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/func.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/func.d */ module dmd.func; diff --git a/dmd/funcsem.d b/dmd/funcsem.d index a8b46d84c2..8a46dda270 100644 --- a/dmd/funcsem.d +++ b/dmd/funcsem.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/funcsem.d, _funcsem.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/funcsem.d, _funcsem.d) * Documentation: https://dlang.org/phobos/dmd_funcsem.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/funcsem.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/funcsem.d */ module dmd.funcsem; diff --git a/dmd/globals.d b/dmd/globals.d index 900c554e5f..624738e4e4 100644 --- a/dmd/globals.d +++ b/dmd/globals.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/globals.d, _globals.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/globals.d, _globals.d) * Documentation: https://dlang.org/phobos/dmd_globals.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/globals.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/globals.d */ module dmd.globals; @@ -160,6 +160,7 @@ extern (C++) struct ImportPathInfo { extern (C++) struct Param { bool obj = true; // write object file + bool readStdin; // saw "-" on command line, read source file from stdin bool multiobj; // break one object file into multiple ones bool trace; // insert profiling hooks bool tracegc; // instrument calls to 'new' diff --git a/dmd/globals.h b/dmd/globals.h index 69fe709f4b..59952a2c10 100644 --- a/dmd/globals.h +++ b/dmd/globals.h @@ -168,6 +168,7 @@ struct ImportPathInfo struct Param { d_bool obj; // write object file + d_bool readStdin; // read source file from stdin d_bool multiobj; // break one object file into multiple ones d_bool trace; // insert profiling hooks d_bool tracegc; // instrument calls to 'new' diff --git a/dmd/gluelayer.d b/dmd/gluelayer.d index 8dca303579..ba7c1e922c 100644 --- a/dmd/gluelayer.d +++ b/dmd/gluelayer.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/gluelayer.d, _gluelayer.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/gluelayer.d, _gluelayer.d) * Documentation: https://dlang.org/phobos/dmd_gluelayer.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/gluelayer.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/gluelayer.d */ module dmd.gluelayer; diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index 9b53114d6b..97e348350b 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/hdrgen.d, _hdrgen.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/hdrgen.d, _hdrgen.d) * Documentation: https://dlang.org/phobos/dmd_hdrgen.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/hdrgen.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/hdrgen.d */ module dmd.hdrgen; diff --git a/dmd/iasmgcc.d b/dmd/iasmgcc.d index f8ebf8fbbb..3d6e6ab5b5 100644 --- a/dmd/iasmgcc.d +++ b/dmd/iasmgcc.d @@ -4,9 +4,9 @@ * Copyright (C) 2018-2025 by The D Language Foundation, All Rights Reserved * Authors: Iain Buclaw * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/iasmgcc.d, _iasmgcc.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/iasmgcc.d, _iasmgcc.d) * Documentation: https://dlang.org/phobos/dmd_iasmgcc.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/iasmgcc.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/iasmgcc.d */ module dmd.iasmgcc; diff --git a/dmd/id.d b/dmd/id.d index 93db559be3..e1c22f2f04 100644 --- a/dmd/id.d +++ b/dmd/id.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/id.d, _id.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/id.d, _id.d) * Documentation: https://dlang.org/phobos/dmd_id.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/id.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/id.d */ module dmd.id; diff --git a/dmd/identifier.d b/dmd/identifier.d index 2cb1b44103..c213597eb0 100644 --- a/dmd/identifier.d +++ b/dmd/identifier.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/identifier.d, _identifier.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/identifier.d, _identifier.d) * Documentation: https://dlang.org/phobos/dmd_identifier.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/identifier.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/identifier.d */ module dmd.identifier; diff --git a/dmd/impcnvtab.d b/dmd/impcnvtab.d index cadb079aa5..b2ab919f1b 100644 --- a/dmd/impcnvtab.d +++ b/dmd/impcnvtab.d @@ -9,9 +9,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/impcnvtab.d, _impcnvtab.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/impcnvtab.d, _impcnvtab.d) * Documentation: https://dlang.org/phobos/dmd_impcnvtab.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/impcnvtab.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/impcnvtab.d */ module dmd.impcnvtab; diff --git a/dmd/imphint.d b/dmd/imphint.d index c01cb6c946..382a0f3786 100644 --- a/dmd/imphint.d +++ b/dmd/imphint.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/imphint.d, _imphint.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/imphint.d, _imphint.d) * Documentation: https://dlang.org/phobos/dmd_imphint.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/imphint.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/imphint.d */ module dmd.imphint; diff --git a/dmd/importc.d b/dmd/importc.d index d4631f0294..72808a67f7 100644 --- a/dmd/importc.d +++ b/dmd/importc.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 2021-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/importc.d, _importc.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/importc.d, _importc.d) * Documentation: https://dlang.org/phobos/dmd_importc.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/importc.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/importc.d */ module dmd.importc; diff --git a/dmd/init.d b/dmd/init.d index 39699c24cb..55fb6f3485 100644 --- a/dmd/init.d +++ b/dmd/init.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/init.d, _init.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/init.d, _init.d) * Documentation: https://dlang.org/phobos/dmd_init.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/init.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/init.d */ module dmd.init; diff --git a/dmd/initsem.d b/dmd/initsem.d index 4e0284b8c5..a4633a604e 100644 --- a/dmd/initsem.d +++ b/dmd/initsem.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/initsem.d, _initsem.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/initsem.d, _initsem.d) * Documentation: https://dlang.org/phobos/dmd_initsem.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/initsem.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/initsem.d */ module dmd.initsem; diff --git a/dmd/inline.d b/dmd/inline.d index 1781ce94f3..ce7a4786a8 100644 --- a/dmd/inline.d +++ b/dmd/inline.d @@ -7,9 +7,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/inline.d, _inline.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/inline.d, _inline.d) * Documentation: https://dlang.org/phobos/dmd_inline.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/inline.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/inline.d */ module dmd.inline; diff --git a/dmd/inlinecost.d b/dmd/inlinecost.d index 2b80d4cffc..599808164f 100644 --- a/dmd/inlinecost.d +++ b/dmd/inlinecost.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/inlinecost.d, _inlinecost.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/inlinecost.d, _inlinecost.d) * Documentation: https://dlang.org/phobos/dmd_inlinecost.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/inlinecost.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/inlinecost.d */ module dmd.inlinecost; diff --git a/dmd/intrange.d b/dmd/intrange.d index 8a2caaa300..f68e302f74 100644 --- a/dmd/intrange.d +++ b/dmd/intrange.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/intrange.d, _intrange.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/intrange.d, _intrange.d) * Documentation: https://dlang.org/phobos/dmd_intrange.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/intrange.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/intrange.d */ module dmd.intrange; diff --git a/dmd/json.d b/dmd/json.d index bbc62d7347..080870aa47 100644 --- a/dmd/json.d +++ b/dmd/json.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/json.d, _json.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/json.d, _json.d) * Documentation: https://dlang.org/phobos/dmd_json.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/json.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/json.d */ module dmd.json; diff --git a/dmd/lambdacomp.d b/dmd/lambdacomp.d index 944abb5237..9f9fd77b7e 100644 --- a/dmd/lambdacomp.d +++ b/dmd/lambdacomp.d @@ -8,9 +8,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/lamdbacomp.d, _lambdacomp.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/lambdacomp.d, _lambdacomp.d) * Documentation: https://dlang.org/phobos/dmd_lambdacomp.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/lambdacomp.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/lambdacomp.d */ module dmd.lambdacomp; diff --git a/dmd/lexer.d b/dmd/lexer.d index 4d0a222060..63313ac2ed 100644 --- a/dmd/lexer.d +++ b/dmd/lexer.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/lexer.d, _lexer.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/lexer.d, _lexer.d) * Documentation: https://dlang.org/phobos/dmd_lexer.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/lexer.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/lexer.d */ module dmd.lexer; diff --git a/dmd/location.d b/dmd/location.d index 9a396f37e8..ca895e21ac 100644 --- a/dmd/location.d +++ b/dmd/location.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/location.d, _location.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/location.d, _location.d) * Documentation: https://dlang.org/phobos/dmd_location.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/location.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/location.d */ module dmd.location; diff --git a/dmd/main.d b/dmd/main.d index 2ad7e003b3..918848b103 100644 --- a/dmd/main.d +++ b/dmd/main.d @@ -9,9 +9,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/main.d, _main.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/main.d, _main.d) * Documentation: https://dlang.org/phobos/dmd_main.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/main.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/main.d */ module dmd.main; @@ -353,7 +353,7 @@ private int tryMain(size_t argc, const(char)** argv, ref Param params) { fatal(); } - if (files.length == 0) + if (files.length == 0 && !params.readStdin) { if (params.jsonFieldFlags) { diff --git a/dmd/mangle/basic.d b/dmd/mangle/basic.d index cb92b6f7a3..263dd5ed46 100644 --- a/dmd/mangle/basic.d +++ b/dmd/mangle/basic.d @@ -3,9 +3,9 @@ * * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/basicmangle.d, _basicmangle.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/mangle/basic.d, _basicmangle.d) * Documentation: https://dlang.org/phobos/dmd_basicmangle.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/basicmangle.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/mangle/basic.d */ module dmd.mangle.basic; diff --git a/dmd/mangle/cpp.d b/dmd/mangle/cpp.d index 3ab42e2d9d..7e9f0205d1 100644 --- a/dmd/mangle/cpp.d +++ b/dmd/mangle/cpp.d @@ -7,9 +7,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cppmangle.d, _cppmangle.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/mangle/cpp.d, _cppmangle.d) * Documentation: https://dlang.org/phobos/dmd_cppmangle.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/cppmangle.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/mangle/cpp.d * * References: * Follows Itanium C++ ABI 1.86 section 5.1 diff --git a/dmd/mangle/cppwin.d b/dmd/mangle/cppwin.d index d3c87ad11b..900f98a53a 100644 --- a/dmd/mangle/cppwin.d +++ b/dmd/mangle/cppwin.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cppmanglewin.d, _cppmanglewin.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/mangle/cppwin.d, _cppmanglewin.d) * Documentation: https://dlang.org/phobos/dmd_cppmanglewin.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/cppmanglewin.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/mangle/cppwin.d */ module dmd.mangle.cppwin; diff --git a/dmd/mangle/package.d b/dmd/mangle/package.d index d630d6a9a0..3ad2c7d579 100644 --- a/dmd/mangle/package.d +++ b/dmd/mangle/package.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dmangle.d, _dmangle.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/mangle/package.d, _dmangle.d) * Documentation: https://dlang.org/phobos/dmd_dmangle.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dmangle.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/mangle/package.d * References: https://dlang.org/blog/2017/12/20/ds-newfangled-name-mangling/ */ diff --git a/dmd/mars.d b/dmd/mars.d index 17d6965f53..f9689f56dd 100644 --- a/dmd/mars.d +++ b/dmd/mars.d @@ -7,9 +7,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/mars.d, _mars.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/mars.d, _mars.d) * Documentation: https://dlang.org/phobos/dmd_mars.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/mars.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/mars.d */ module dmd.mars; @@ -59,6 +59,13 @@ import dmd.semantic3; import dmd.target; import dmd.utils; +version (Windows) + import core.sys.windows.winbase : getpid = GetCurrentProcessId; +else version (Posix) + import core.sys.posix.unistd : getpid; +else + static assert(0); + /** * Print DMD's logo on stdout */ @@ -1734,7 +1741,7 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param break; } if (runarg == "-") - files.push("__stdin.d"); + params.readStdin = true; else files.push(arguments[i + 1]); params.runargs.setDim(length - 1); @@ -1751,7 +1758,7 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param } } else if (p[1] == '\0') - files.push("__stdin.d"); + params.readStdin = true; else { Lerror: @@ -1937,10 +1944,38 @@ bool createModules(ref Strings files, ref Strings libmodules, ref Param params, modules.push(m); if (firstmodule) { - global.params.objfiles.push(m.objfile.toChars()); + params.objfiles.push(m.objfile.toChars()); firstmodule = false; } } + + // Special module representing `stdin` + if (params.readStdin) + { + Module m; + if (createModule("__stdin.d", libmodules, params, target, eSink, m)) + return true; + if (m is null) + return false; + + modules.push(m); + + // Set the source file contents of the module + OutBuffer buf; + buf.readFromStdin(); + m.src = cast(ubyte[])buf.extractSlice(); + + // Give unique outfile name + OutBuffer namebuf; + namebuf.printf("__stdin_%d", getpid()); + + auto filename = FileName.forceExt(namebuf.extractSlice(), target.obj_ext); + m.objfile = FileName(filename); + + if (firstmodule) + params.objfiles.push(m.objfile.toChars()); + } + return false; } @@ -1959,3 +1994,37 @@ Module moduleWithEmptyMain() result.semantic3(null); return result; } + +private void readFromStdin(ref OutBuffer sink) nothrow +{ + import core.stdc.stdio; + import dmd.errors; + + enum BufIncrement = 128 * 1024; + + for (size_t j; 1; ++j) + { + char[] buffer = sink.allocate(BufIncrement + 16); + + // Fill up buffer + size_t filled = 0; + do + { + filled += fread(buffer.ptr + filled, 1, buffer.length - filled, stdin); + if (ferror(stdin)) + { + import core.stdc.errno; + error(Loc.initial, "cannot read from stdin, errno = %d", errno); + fatal(); + } + if (feof(stdin)) // successful completion + { + memset(buffer.ptr + filled, '\0', 16); + sink.setsize(j * BufIncrement + filled); + return; + } + } while (filled < BufIncrement); + } + + assert(0); +} diff --git a/dmd/mtype.d b/dmd/mtype.d index 52d8b77cd4..e0af692bcc 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/mtype.d, _mtype.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/mtype.d, _mtype.d) * Documentation: https://dlang.org/phobos/dmd_mtype.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/mtype.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/mtype.d */ module dmd.mtype; diff --git a/dmd/mustuse.d b/dmd/mustuse.d index 005a6c074c..fab9723636 100644 --- a/dmd/mustuse.d +++ b/dmd/mustuse.d @@ -3,9 +3,9 @@ * * Copyright: Copyright (C) 2022-2025 by The D Language Foundation, All Rights Reserved * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/mustuse.d, _mustuse.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/mustuse.d, _mustuse.d) * Documentation: https://dlang.org/phobos/dmd_mustuse.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/mustuse.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/mustuse.d */ module dmd.mustuse; diff --git a/dmd/nogc.d b/dmd/nogc.d index a5d9c68aa7..5e3c164acb 100644 --- a/dmd/nogc.d +++ b/dmd/nogc.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/nogc.d, _nogc.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/nogc.d, _nogc.d) * Documentation: https://dlang.org/phobos/dmd_nogc.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/nogc.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/nogc.d */ module dmd.nogc; diff --git a/dmd/nspace.d b/dmd/nspace.d index 4a21770c4b..0c93f0e799 100644 --- a/dmd/nspace.d +++ b/dmd/nspace.d @@ -39,9 +39,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/nspace.d, _nspace.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/nspace.d, _nspace.d) * Documentation: https://dlang.org/phobos/dmd_nspace.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/nspace.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/nspace.d */ module dmd.nspace; diff --git a/dmd/ob.d b/dmd/ob.d index 870e8e7b13..099f811589 100644 --- a/dmd/ob.d +++ b/dmd/ob.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ob.d, _ob.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/ob.d, _ob.d) * Documentation: https://dlang.org/phobos/dmd_escape.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/ob.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/ob.d * References: https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md Argument Ownership and Function Calls */ diff --git a/dmd/objc.d b/dmd/objc.d index 4626f22ee2..32878b57af 100644 --- a/dmd/objc.d +++ b/dmd/objc.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/objc.d, _objc.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/objc.d, _objc.d) * Documentation: https://dlang.org/phobos/dmd_objc.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/objc.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/objc.d */ module dmd.objc; diff --git a/dmd/opover.d b/dmd/opover.d index 06b9e82cf0..7baaeaa7fc 100644 --- a/dmd/opover.d +++ b/dmd/opover.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/opover.d, _opover.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/opover.d, _opover.d) * Documentation: https://dlang.org/phobos/dmd_opover.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/opover.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/opover.d */ module dmd.opover; diff --git a/dmd/optimize.d b/dmd/optimize.d index 2e40f1826c..b13f8c6458 100644 --- a/dmd/optimize.d +++ b/dmd/optimize.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/optimize.d, _optimize.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/optimize.d, _optimize.d) * Documentation: https://dlang.org/phobos/dmd_optimize.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/optimize.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/optimize.d */ module dmd.optimize; diff --git a/dmd/parse.d b/dmd/parse.d index 2ba970c12e..c2d9a20944 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/parse.d, _parse.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/parse.d, _parse.d) * Documentation: https://dlang.org/phobos/dmd_parse.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/parse.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/parse.d */ module dmd.parse; diff --git a/dmd/pragmasem.d b/dmd/pragmasem.d index a7299a0e9b..44597740a2 100644 --- a/dmd/pragmasem.d +++ b/dmd/pragmasem.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/pragmasem.d, _pragmasem.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/pragmasem.d, _pragmasem.d) * Documentation: https://dlang.org/phobos/dmd_pragmasem.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/pragmasem.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/pragmasem.d */ module dmd.pragmasem; diff --git a/dmd/printast.d b/dmd/printast.d index 281851e0f2..5e4c9f787f 100644 --- a/dmd/printast.d +++ b/dmd/printast.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/printast.d, _printast.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/printast.d, _printast.d) * Documentation: https://dlang.org/phobos/dmd_printast.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/printast.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/printast.d */ module dmd.printast; diff --git a/dmd/root/aav.d b/dmd/root/aav.d index 80b1d636b2..014d4a579c 100644 --- a/dmd/root/aav.d +++ b/dmd/root/aav.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/aav.d, root/_aav.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/aav.d, root/_aav.d) * Documentation: https://dlang.org/phobos/dmd_root_aav.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/aav.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/aav.d */ module dmd.root.aav; diff --git a/dmd/root/array.d b/dmd/root/array.d index f36947e396..a80fc804cb 100644 --- a/dmd/root/array.d +++ b/dmd/root/array.d @@ -5,9 +5,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/array.d, root/_array.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/array.d, root/_array.d) * Documentation: https://dlang.org/phobos/dmd_root_array.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/array.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/array.d */ module dmd.root.array; diff --git a/dmd/root/bitarray.d b/dmd/root/bitarray.d index b977602087..b5adaa8903 100644 --- a/dmd/root/bitarray.d +++ b/dmd/root/bitarray.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/bitarray.d, root/_bitarray.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/bitarray.d, root/_bitarray.d) * Documentation: https://dlang.org/phobos/dmd_root_array.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/bitarray.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/bitarray.d */ module dmd.root.bitarray; diff --git a/dmd/root/complex.d b/dmd/root/complex.d index 710d0e9018..777c103ae9 100644 --- a/dmd/root/complex.d +++ b/dmd/root/complex.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/complex.d, _complex.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/complex.d, _complex.d) * Documentation: https://dlang.org/phobos/dmd_root_complex.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/complex.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/complex.d */ module dmd.root.complex; diff --git a/dmd/root/ctfloat.d b/dmd/root/ctfloat.d index 84ff85b24a..39ab18f922 100644 --- a/dmd/root/ctfloat.d +++ b/dmd/root/ctfloat.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/ctfloat.d, root/_ctfloat.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/ctfloat.d, root/_ctfloat.d) * Documentation: https://dlang.org/phobos/dmd_root_ctfloat.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/ctfloat.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/ctfloat.d */ module dmd.root.ctfloat; diff --git a/dmd/root/file.d b/dmd/root/file.d index 7accc61089..2046e5930c 100644 --- a/dmd/root/file.d +++ b/dmd/root/file.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/file.d, root/_file.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/file.d, root/_file.d) * Documentation: https://dlang.org/phobos/dmd_root_file.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/file.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/file.d */ module dmd.root.file; diff --git a/dmd/root/filename.d b/dmd/root/filename.d index 602e62cb84..5ad07750b3 100644 --- a/dmd/root/filename.d +++ b/dmd/root/filename.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/filename.d, root/_filename.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/filename.d, root/_filename.d) * Documentation: https://dlang.org/phobos/dmd_root_filename.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/filename.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/filename.d */ module dmd.root.filename; diff --git a/dmd/root/hash.d b/dmd/root/hash.d index 0852a9f779..d327f4b258 100644 --- a/dmd/root/hash.d +++ b/dmd/root/hash.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Martin Nowak, Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/hash.d, root/_hash.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/hash.d, root/_hash.d) * Documentation: https://dlang.org/phobos/dmd_root_hash.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/hash.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/hash.d */ module dmd.root.hash; diff --git a/dmd/root/man.d b/dmd/root/man.d index b88a12dcc2..2ec7de7615 100644 --- a/dmd/root/man.d +++ b/dmd/root/man.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/man.d, root/_man.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/man.d, root/_man.d) * Documentation: https://dlang.org/phobos/dmd_root_man.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/man.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/man.d */ module dmd.root.man; diff --git a/dmd/root/optional.d b/dmd/root/optional.d index 8602bcf3b8..2b518eb8b1 100644 --- a/dmd/root/optional.d +++ b/dmd/root/optional.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/optional.d, root/_optional.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/optional.d, root/_optional.d) * Documentation: https://dlang.org/phobos/dmd_root_optional.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/optional.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/optional.d */ module dmd.root.optional; diff --git a/dmd/root/optional.h b/dmd/root/optional.h index e01a612659..12891f879b 100644 --- a/dmd/root/optional.h +++ b/dmd/root/optional.h @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/optional.h, root/_optional.h) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/optional.h, root/_optional.h) * Documentation: https://dlang.org/phobos/dmd_root_optional.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/optional.h + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/optional.h */ #include "dcompat.h" // for d_bool diff --git a/dmd/root/port.d b/dmd/root/port.d index fd3af0aabe..c96ac86fd0 100644 --- a/dmd/root/port.d +++ b/dmd/root/port.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/port.d, root/_port.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/port.d, root/_port.d) * Documentation: https://dlang.org/phobos/dmd_root_port.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/port.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/port.d */ module dmd.root.port; diff --git a/dmd/root/region.d b/dmd/root/region.d index 3928a5569e..a8efbca1e6 100644 --- a/dmd/root/region.d +++ b/dmd/root/region.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 2019-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/region.d, root/_region.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/region.d, root/_region.d) * Documentation: https://dlang.org/phobos/dmd_root_region.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/region.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/region.d */ module dmd.root.region; diff --git a/dmd/root/rmem.d b/dmd/root/rmem.d index 8fa0b08136..32d22d3beb 100644 --- a/dmd/root/rmem.d +++ b/dmd/root/rmem.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/rmem.d, root/_rmem.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/rmem.d, root/_rmem.d) * Documentation: https://dlang.org/phobos/dmd_root_rmem.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/rmem.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/rmem.d */ module dmd.root.rmem; diff --git a/dmd/root/speller.d b/dmd/root/speller.d index e984a9e985..a2151106d0 100644 --- a/dmd/root/speller.d +++ b/dmd/root/speller.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/speller.d, root/_speller.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/speller.d, root/_speller.d) * Documentation: https://dlang.org/phobos/dmd_root_speller.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/speller.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/speller.d */ module dmd.root.speller; diff --git a/dmd/root/string.d b/dmd/root/string.d index 252ed77ff8..369a79be66 100644 --- a/dmd/root/string.d +++ b/dmd/root/string.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/string.d, root/_string.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/string.d, root/_string.d) * Documentation: https://dlang.org/phobos/dmd_root_string.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/string.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/string.d */ module dmd.root.string; diff --git a/dmd/root/stringtable.d b/dmd/root/stringtable.d index b40e7dfece..c7a2c8c56d 100644 --- a/dmd/root/stringtable.d +++ b/dmd/root/stringtable.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/stringtable.d, root/_stringtable.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/stringtable.d, root/_stringtable.d) * Documentation: https://dlang.org/phobos/dmd_root_stringtable.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/stringtable.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/stringtable.d */ module dmd.root.stringtable; diff --git a/dmd/root/utf.d b/dmd/root/utf.d index ede1fd8678..5b2c42f4ee 100644 --- a/dmd/root/utf.d +++ b/dmd/root/utf.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/utf.d, _utf.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/root/utf.d, _utf.d) * Documentation: https://dlang.org/phobos/dmd_root_utf.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/root/utf.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/root/utf.d */ module dmd.root.utf; diff --git a/dmd/rootobject.d b/dmd/rootobject.d index 8b8a13caaa..71b36a4375 100644 --- a/dmd/rootobject.d +++ b/dmd/rootobject.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/rootobject.d, _rootobject.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/rootobject.d, _rootobject.d) * Documentation: https://dlang.org/phobos/dmd_rootobject.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/rootobject.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/rootobject.d */ module dmd.rootobject; diff --git a/dmd/safe.d b/dmd/safe.d index 3f83d50ff8..3be9efecc2 100644 --- a/dmd/safe.d +++ b/dmd/safe.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/safe.d, _safe.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/safe.d, _safe.d) * Documentation: https://dlang.org/phobos/dmd_safe.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/safe.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/safe.d */ module dmd.safe; diff --git a/dmd/sarif.d b/dmd/sarif.d index c404eebe21..f596b788b3 100644 --- a/dmd/sarif.d +++ b/dmd/sarif.d @@ -4,8 +4,8 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/sarif.d, sarif.d) - * Coverage: $(LINK2 https://codecov.io/gh/dlang/dmd/src/master/src/dmd/sarif.d, Code Coverage) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/sarif.d, sarif.d) + * Coverage: $(LINK2 https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/sarif.d, Code Coverage) * * Description: * - This module generates SARIF reports for DMD errors, warnings, and messages. @@ -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 a1bb7e895b..26f0fa8a25 100644 --- a/dmd/semantic2.d +++ b/dmd/semantic2.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/semantic2.d, _semantic2.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/semantic2.d, _semantic2.d) * Documentation: https://dlang.org/phobos/dmd_semantic2.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/semantic2.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/semantic2.d */ module dmd.semantic2; diff --git a/dmd/semantic3.d b/dmd/semantic3.d index ccf931af8d..bafb2e7d87 100644 --- a/dmd/semantic3.d +++ b/dmd/semantic3.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/semantic3.d, _semantic3.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/semantic3.d, _semantic3.d) * Documentation: https://dlang.org/phobos/dmd_semantic3.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/semantic3.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/semantic3.d */ module dmd.semantic3; diff --git a/dmd/sideeffect.d b/dmd/sideeffect.d index 8f905caceb..5984466d3b 100644 --- a/dmd/sideeffect.d +++ b/dmd/sideeffect.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/sideeffect.d, _sideeffect.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/sideeffect.d, _sideeffect.d) * Documentation: https://dlang.org/phobos/dmd_sideeffect.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/sideeffect.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/sideeffect.d */ module dmd.sideeffect; diff --git a/dmd/statement.d b/dmd/statement.d index 602d3a6629..2ade0a9a9b 100644 --- a/dmd/statement.d +++ b/dmd/statement.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/statement.d, _statement.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/statement.d, _statement.d) * Documentation: https://dlang.org/phobos/dmd_statement.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/statement.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/statement.d */ module dmd.statement; diff --git a/dmd/statementsem.d b/dmd/statementsem.d index 4c36055f6a..523ed7b397 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/statementsem.d, _statementsem.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/statementsem.d, _statementsem.d) * Documentation: https://dlang.org/phobos/dmd_statementsem.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/statementsem.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/statementsem.d */ module dmd.statementsem; diff --git a/dmd/staticassert.d b/dmd/staticassert.d index 495241e107..52ded559e5 100644 --- a/dmd/staticassert.d +++ b/dmd/staticassert.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/staticassert.d, _staticassert.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/staticassert.d, _staticassert.d) * Documentation: https://dlang.org/phobos/dmd_staticassert.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/staticassert.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/staticassert.d */ module dmd.staticassert; diff --git a/dmd/staticcond.d b/dmd/staticcond.d index 288cfdc5fb..c2e87c7bf3 100644 --- a/dmd/staticcond.d +++ b/dmd/staticcond.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/staticcond.d, _staticcond.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/staticcond.d, _staticcond.d) * Documentation: https://dlang.org/phobos/dmd_staticcond.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/staticcond.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/staticcond.d */ module dmd.staticcond; diff --git a/dmd/stmtstate.d b/dmd/stmtstate.d index fe53d80211..1c1fd080ee 100644 --- a/dmd/stmtstate.d +++ b/dmd/stmtstate.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/stmtstate.d, _stmtstate.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/stmtstate.d, _stmtstate.d) * Documentation: https://dlang.org/phobos/dmd_stmtstate.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/stmtstate.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/stmtstate.d */ module dmd.stmtstate; diff --git a/dmd/target.d b/dmd/target.d index 5f6c178fb4..1228f80c06 100644 --- a/dmd/target.d +++ b/dmd/target.d @@ -18,9 +18,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/target.d, _target.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/target.d, _target.d) * Documentation: https://dlang.org/phobos/dmd_target.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/target.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/target.d */ module dmd.target; diff --git a/dmd/templateparamsem.d b/dmd/templateparamsem.d index e7a40a0dc4..561181a2cc 100644 --- a/dmd/templateparamsem.d +++ b/dmd/templateparamsem.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/templateparamsem.d, _templateparamsem.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/templateparamsem.d, _templateparamsem.d) * Documentation: https://dlang.org/phobos/dmd_templateparamsem.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/templateparamsem.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/templateparamsem.d */ module dmd.templateparamsem; diff --git a/dmd/templatesem.d b/dmd/templatesem.d index 17526e604c..e5efce4a8b 100644 --- a/dmd/templatesem.d +++ b/dmd/templatesem.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/templatesem.d, _templatesem.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/templatesem.d, _templatesem.d) * Documentation: https://dlang.org/phobos/dmd_templatesem.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/templatesem.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/templatesem.d */ module dmd.templatesem; diff --git a/dmd/timetrace.d b/dmd/timetrace.d index 2c9c89aee7..b921ac433d 100644 --- a/dmd/timetrace.d +++ b/dmd/timetrace.d @@ -9,9 +9,9 @@ This file is originally from LDC (the LLVM D compiler). Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved Authors: Johan Engelen, Max Haughton, Dennis Korpel License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) -Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/timetrace.d, common/_timetrace.d) +Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/timetrace.d, common/_timetrace.d) Documentation: https://dlang.org/phobos/dmd_common_timetrace.html -Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/timetrace.d +Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/timetrace.d */ module dmd.timetrace; diff --git a/dmd/tokens.d b/dmd/tokens.d index 3a6e14c487..a10620772a 100644 --- a/dmd/tokens.d +++ b/dmd/tokens.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/tokens.d, _tokens.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/tokens.d, _tokens.d) * Documentation: https://dlang.org/phobos/dmd_tokens.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/tokens.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/tokens.d */ module dmd.tokens; diff --git a/dmd/traits.d b/dmd/traits.d index 732a5a32dc..8cce1732e8 100644 --- a/dmd/traits.d +++ b/dmd/traits.d @@ -6,9 +6,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/traits.d, _traits.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/traits.d, _traits.d) * Documentation: https://dlang.org/phobos/dmd_traits.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/traits.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/traits.d */ module dmd.traits; diff --git a/dmd/typesem.d b/dmd/typesem.d index 1906867c53..71575477a1 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/typesem.d, _typesem.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/typesem.d, _typesem.d) * Documentation: https://dlang.org/phobos/dmd_typesem.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/typesem.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/typesem.d */ module dmd.typesem; diff --git a/dmd/typinf.d b/dmd/typinf.d index f774f8636b..38ba6e48e4 100644 --- a/dmd/typinf.d +++ b/dmd/typinf.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/typinf.d, _typinf.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/typinf.d, _typinf.d) * Documentation: https://dlang.org/phobos/dmd_typinf.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/typinf.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/typinf.d */ module dmd.typinf; diff --git a/dmd/utils.d b/dmd/utils.d index e20b86f03c..bfa197aca3 100644 --- a/dmd/utils.d +++ b/dmd/utils.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/utils.d, _utils.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/utils.d, _utils.d) * Documentation: https://dlang.org/phobos/dmd_utils.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/utils.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/utils.d */ module dmd.utils; diff --git a/dmd/visitor/foreachvar.d b/dmd/visitor/foreachvar.d index d170206ead..80611d6f26 100644 --- a/dmd/visitor/foreachvar.d +++ b/dmd/visitor/foreachvar.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/foreachvar.d, _foreachvar.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/visitor/foreachvar.d, _foreachvar.d) * Documentation: https://dlang.org/phobos/dmd_foreachvar.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/foreachvar.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/visitor/foreachvar.d */ module dmd.visitor.foreachvar; diff --git a/dmd/visitor/package.d b/dmd/visitor/package.d index 64e251492e..50b5a54520 100644 --- a/dmd/visitor/package.d +++ b/dmd/visitor/package.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/visitor.d, _visitor.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/visitor/package.d, _visitor.d) * Documentation: https://dlang.org/phobos/dmd_visitor.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/visitor.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/visitor/package.d */ module dmd.visitor; diff --git a/dmd/visitor/postorder.d b/dmd/visitor/postorder.d index 731e682ce0..22549da45d 100644 --- a/dmd/visitor/postorder.d +++ b/dmd/visitor/postorder.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/apply.d, _apply.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/visitor/postorder.d, _apply.d) * Documentation: https://dlang.org/phobos/dmd_apply.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/apply.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/visitor/postorder.d */ module dmd.visitor.postorder; diff --git a/dmd/visitor/statement_rewrite_walker.d b/dmd/visitor/statement_rewrite_walker.d index 6700414b57..25e4c736bb 100644 --- a/dmd/visitor/statement_rewrite_walker.d +++ b/dmd/visitor/statement_rewrite_walker.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/statement_rewrite_walker.d, _statement_rewrite_walker.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/visitor/statement_rewrite_walker.d, _statement_rewrite_walker.d) * Documentation: https://dlang.org/phobos/dmd_statement_rewrite_walker.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/statement_rewrite_walker.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/visitor/statement_rewrite_walker.d */ module dmd.visitor.statement_rewrite_walker; diff --git a/dmd/vsoptions.d b/dmd/vsoptions.d index 0727dc059b..ccc3c60ce8 100644 --- a/dmd/vsoptions.d +++ b/dmd/vsoptions.d @@ -4,9 +4,9 @@ * Copyright: Copyright (C) 1999-2025 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/link.d, _vsoptions.d) + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/vsoptions.d, _vsoptions.d) * Documentation: https://dlang.org/phobos/dmd_vsoptions.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/vsoptions.d + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/vsoptions.d */ module dmd.vsoptions; diff --git a/tests/dmd/fail_compilation/fail21045.d b/tests/dmd/fail_compilation/fail21045.d new file mode 100644 index 0000000000..c43eda3f97 --- /dev/null +++ b/tests/dmd/fail_compilation/fail21045.d @@ -0,0 +1,12 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/fail21045.d(12): Error: unable to read module `__stdin` +fail_compilation/fail21045.d(12): Expected '__stdin.d' or '__stdin/package.d' in one of the following import paths: +import path[0] = fail_compilation +import path[1] = $p:druntime/import$ +import path[2] = $p:phobos$ +--- +*/ + +import __stdin; From 2d9a48acd949be071750eebba58540a3c1504973 Mon Sep 17 00:00:00 2001 From: Samrendra Pratap Singh <153061395+solo-source@users.noreply.github.com> Date: Tue, 1 Apr 2025 04:45:15 +0530 Subject: [PATCH 041/113] Improve error message when cl.exe is missing on Windows (dlang/dmd!21120) --- dmd/vsoptions.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmd/vsoptions.d b/dmd/vsoptions.d index ccc3c60ce8..4537109920 100644 --- a/dmd/vsoptions.d +++ b/dmd/vsoptions.d @@ -191,7 +191,7 @@ extern(C++) struct VSOptions * 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) { From f6fdb904031449361090bd1c646d9210c2bf3b56 Mon Sep 17 00:00:00 2001 From: Matthew Qiu <93230055+MatthewQiu-5@users.noreply.github.com> Date: Wed, 2 Apr 2025 04:37:36 -0400 Subject: [PATCH 042/113] Extracted ClassDeclaration.isAbstract to dsymbolsem (dlang/dmd!21131) --- dmd/aggregate.h | 1 - dmd/cxxfrontend.d | 6 +++ dmd/dclass.d | 103 +--------------------------------------------- dmd/declaration.h | 1 + dmd/dsymbolsem.d | 98 +++++++++++++++++++++++++++++++++++++++++++ dmd/frontend.h | 3 +- 6 files changed, 108 insertions(+), 104 deletions(-) diff --git a/dmd/aggregate.h b/dmd/aggregate.h index 2a81162aef..b8629c8d66 100644 --- a/dmd/aggregate.h +++ b/dmd/aggregate.h @@ -293,7 +293,6 @@ class ClassDeclaration : public AggregateDeclaration 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/cxxfrontend.d b/dmd/cxxfrontend.d index 234b6523af..67a174d66b 100644 --- a/dmd/cxxfrontend.d +++ b/dmd/cxxfrontend.d @@ -192,6 +192,12 @@ Dsymbol vtblSymbol(ClassDeclaration cd) return dmd.dsymbolsem.vtblSymbol(cd); } +bool isAbstract(ClassDeclaration cd) +{ + import dmd.dsymbolsem; + return dmd.dsymbolsem.isAbstract(cd); +} + /*********************************************************** * dtemplate.d */ diff --git a/dmd/dclass.d b/dmd/dclass.d index 80d39fac42..48f464c328 100644 --- a/dmd/dclass.d +++ b/dmd/dclass.d @@ -23,7 +23,7 @@ import dmd.gluelayer; import dmd.declaration; import dmd.dscope; import dmd.dsymbol; -import dmd.dsymbolsem : dsymbolSemantic, addMember, setFieldOffset; +import dmd.dsymbolsem : setFieldOffset; import dmd.errors; import dmd.func; import dmd.id; @@ -33,7 +33,6 @@ import dmd.mtype; import dmd.objc; import dmd.root.rmem; import dmd.target; -import dmd.typesem : covariant, immutableOf, sarrayOf; import dmd.visitor; /*********************************************************** @@ -757,106 +756,6 @@ extern (C++) class ClassDeclaration : AggregateDeclaration return false; } - /**************************************** - */ - final bool isAbstract() - { - enum log = false; - if (isabstract != ThreeState.none) - return isabstract == ThreeState.yes; - - if (log) printf("isAbstract(%s)\n", toChars()); - - bool no() { if (log) printf("no\n"); isabstract = ThreeState.no; return false; } - bool yes() { if (log) printf("yes\n"); isabstract = ThreeState.yes; return true; } - - if (storage_class & STC.abstract_ || _scope && _scope.stc & STC.abstract_) - return yes(); - - if (errors) - return no(); - - /* https://issues.dlang.org/show_bug.cgi?id=11169 - * Resolve forward references to all class member functions, - * and determine whether this class is abstract. - */ - static int func(Dsymbol s, void*) - { - auto fd = s.isFuncDeclaration(); - if (!fd) - return 0; - if (fd.storage_class & STC.static_) - return 0; - - if (fd.isAbstract()) - return 1; - return 0; - } - - // opaque class is not abstract if it is not declared abstract - if (!members) - return no(); - - for (size_t i = 0; i < members.length; i++) - { - auto s = (*members)[i]; - if (s.apply(&func, null)) - { - return yes(); - } - } - - /* If the base class is not abstract, then this class cannot - * be abstract. - */ - if (!isInterfaceDeclaration() && (!baseClass || !baseClass.isAbstract())) - return no(); - - /* If any abstract functions are inherited, but not overridden, - * then the class is abstract. Do this by checking the vtbl[]. - * Need to do semantic() on class to fill the vtbl[]. - */ - this.dsymbolSemantic(null); - - /* The next line should work, but does not because when ClassDeclaration.dsymbolSemantic() - * is called recursively it can set PASS.semanticdone without finishing it. - */ - //if (semanticRun < PASS.semanticdone) - { - /* Could not complete semantic(). Try running semantic() on - * each of the virtual functions, - * which will fill in the vtbl[] overrides. - */ - static int virtualSemantic(Dsymbol s, void*) - { - auto fd = s.isFuncDeclaration(); - if (fd && !(fd.storage_class & STC.static_) && !fd.isUnitTestDeclaration()) - fd.dsymbolSemantic(null); - return 0; - } - - for (size_t i = 0; i < members.length; i++) - { - auto s = (*members)[i]; - s.apply(&virtualSemantic,null); - } - } - - /* Finally, check the vtbl[] - */ - foreach (i; 1 .. vtbl.length) - { - auto fd = vtbl[i].isFuncDeclaration(); - //if (fd) printf("\tvtbl[%d] = [%s] %s\n", i, fd.loc.toChars(), fd.toPrettyChars()); - if (!fd || fd.isAbstract()) - { - return yes(); - } - } - - return no(); - } - /**************************************** * Determine if slot 0 of the vtbl[] is reserved for something else. * For class objects, yes, this is where the classinfo ptr goes. diff --git a/dmd/declaration.h b/dmd/declaration.h index c7e4552608..d27ed584bb 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: diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index fb7d608da5..32ea2c33aa 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -8210,3 +8210,101 @@ Dsymbol vtblSymbol(ClassDeclaration cd) } return cd.vtblsym; } + +extern(C++) 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(); +} diff --git a/dmd/frontend.h b/dmd/frontend.h index f1dc48f2f4..3ce96d6b0f 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -6707,7 +6707,6 @@ class ClassDeclaration : public AggregateDeclaration 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; @@ -7569,6 +7568,8 @@ extern bool hasStaticCtorOrDtor(Dsymbol* d); extern bool isFuncHidden(ClassDeclaration* cd, FuncDeclaration* fd); +extern bool isAbstract(ClassDeclaration* cd); + extern void lowerNonArrayAggregate(StaticForeach* sfe, Scope* sc); extern int32_t include(Condition* c, Scope* sc); From b47099879f1a1210dab45e41713b76a6c4a4e87d Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 4 Apr 2025 16:58:48 -0700 Subject: [PATCH 043/113] add exe2.c exe3.c Import C test files (dlang/dmd!21146) --- tests/dmd/runnable/exe2.c | 1405 +++++++++++++++++++++++++++++++++++++ tests/dmd/runnable/exe3.c | 1048 +++++++++++++++++++++++++++ 2 files changed, 2453 insertions(+) create mode 100644 tests/dmd/runnable/exe2.c create mode 100644 tests/dmd/runnable/exe3.c diff --git a/tests/dmd/runnable/exe2.c b/tests/dmd/runnable/exe2.c new file mode 100644 index 0000000000..9967602d65 --- /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 0000000000..89543d8f95 --- /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; +} From 732278fa9ac267bc66ac9b3d58218b881951ff84 Mon Sep 17 00:00:00 2001 From: Matthew Qiu <93230055+MatthewQiu-5@users.noreply.github.com> Date: Fri, 4 Apr 2025 21:08:06 -0400 Subject: [PATCH 044/113] Extracted AggregateDeclaration.finalizeSize into a visitor in dsymbolsem (dlang/dmd!21139) --- dmd/aggregate.d | 2 - dmd/aggregate.h | 3 - dmd/dclass.d | 111 ---------------------- dmd/dstruct.d | 121 ------------------------ dmd/dsymbolsem.d | 242 +++++++++++++++++++++++++++++++++++++++++++++++ dmd/frontend.h | 3 - 6 files changed, 242 insertions(+), 240 deletions(-) diff --git a/dmd/aggregate.d b/dmd/aggregate.d index 51d6fc4595..6359674d44 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 b8629c8d66..d89755cea2 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? @@ -172,7 +171,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); @@ -287,7 +285,6 @@ 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; diff --git a/dmd/dclass.d b/dmd/dclass.d index 48f464c328..51ac939ade 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 : setFieldOffset; import dmd.errors; import dmd.func; import dmd.id; @@ -495,116 +494,6 @@ extern (C++) class ClassDeclaration : AggregateDeclaration return null; } - final override void finalizeSize() - { - assert(sizeok != Sizeok.done); - - // Set the offsets of the fields and determine the size of the class - if (baseClass) - { - assert(baseClass.sizeok == Sizeok.done); - - alignsize = baseClass.alignsize; - if (classKind == ClassKind.cpp) - structsize = target.cpp.derivedClassOffset(baseClass); - else - structsize = baseClass.structsize; - } - else if (classKind == ClassKind.objc) - structsize = 0; // no hidden member for an Objective-C class - else if (isInterfaceDeclaration()) - { - if (interfaces.length == 0) - { - alignsize = target.ptrsize; - structsize = target.ptrsize; // allow room for __vptr - } - } - else - { - alignsize = target.ptrsize; - structsize = target.ptrsize; // allow room for __vptr - if (hasMonitor()) - structsize += target.ptrsize; // allow room for __monitor - } - - //printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok); - size_t bi = 0; // index into vtblInterfaces[] - - /**** - * Runs through the inheritance graph to set the BaseClass.offset fields. - * Recursive in order to account for the size of the interface classes, if they are - * more than just interfaces. - * Params: - * cd = interface to look at - * baseOffset = offset of where cd will be placed - * Returns: - * subset of instantiated size used by cd for interfaces - */ - uint membersPlace(ClassDeclaration cd, uint baseOffset) - { - //printf(" membersPlace(%s, %d)\n", cd.toChars(), baseOffset); - uint offset = baseOffset; - - foreach (BaseClass* b; cd.interfaces) - { - if (b.sym.sizeok != Sizeok.done) - b.sym.finalizeSize(); - assert(b.sym.sizeok == Sizeok.done); - - if (!b.sym.alignsize) - b.sym.alignsize = target.ptrsize; - offset = alignmember(structalign_t(cast(ushort)b.sym.alignsize), b.sym.alignsize, offset); - assert(bi < vtblInterfaces.length); - - BaseClass* bv = (*vtblInterfaces)[bi]; - if (b.sym.interfaces.length == 0) - { - //printf("\tvtblInterfaces[%d] b=%p b.sym = %s, offset = %d\n", bi, bv, bv.sym.toChars(), offset); - bv.offset = offset; - ++bi; - // All the base interfaces down the left side share the same offset - for (BaseClass* b2 = bv; b2.baseInterfaces.length; ) - { - b2 = &b2.baseInterfaces[0]; - b2.offset = offset; - //printf("\tvtblInterfaces[%d] b=%p sym = %s, offset = %d\n", bi, b2, b2.sym.toChars(), b2.offset); - } - } - membersPlace(b.sym, offset); - //printf(" %s size = %d\n", b.sym.toChars(), b.sym.structsize); - offset += b.sym.structsize; - if (alignsize < b.sym.alignsize) - alignsize = b.sym.alignsize; - } - return offset - baseOffset; - } - - structsize += membersPlace(this, structsize); - - if (isInterfaceDeclaration()) - { - sizeok = Sizeok.done; - return; - } - - // FIXME: Currently setFieldOffset functions need to increase fields - // to calculate each variable offsets. It can be improved later. - fields.setDim(0); - - FieldState fieldState; - fieldState.offset = structsize; - foreach (s; *members) - { - s.setFieldOffset(this, &fieldState, false); - } - - sizeok = Sizeok.done; - - // Calculate fields[i].overlapped - checkOverlappedFields(); - } - /************** * Returns: true if there's a __monitor field */ diff --git a/dmd/dstruct.d b/dmd/dstruct.d index 4c7011bc6a..ca9b63260c 100644 --- a/dmd/dstruct.d +++ b/dmd/dstruct.d @@ -151,127 +151,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration return "struct"; } - override final void finalizeSize() - { - //printf("StructDeclaration::finalizeSize() %s, sizeok = %d\n", toChars(), sizeok); - assert(sizeok != Sizeok.done); - - if (sizeok == Sizeok.inProcess) - { - return; - } - sizeok = Sizeok.inProcess; - - //printf("+StructDeclaration::finalizeSize() %s, fields.length = %d, sizeok = %d\n", toChars(), fields.length, sizeok); - - fields.setDim(0); // workaround - - // Set the offsets of the fields and determine the size of the struct - FieldState fieldState; - bool isunion = isUnionDeclaration() !is null; - for (size_t i = 0; i < members.length; i++) - { - Dsymbol s = (*members)[i]; - s.setFieldOffset(this, &fieldState, isunion); - if (type.ty == Terror) - { - errorSupplemental(s.loc, "error on member `%s`", s.toPrettyChars); - errors = true; - return; - } - } - - if (structsize == 0) - { - hasNoFields = true; - alignsize = 1; - - // A fine mess of what size a zero sized struct should be - final switch (classKind) - { - case ClassKind.d: - case ClassKind.cpp: - structsize = 1; - break; - - case ClassKind.c: - case ClassKind.objc: - if (target.c.bitFieldStyle == TargetC.BitFieldStyle.MS) - { - /* Undocumented MS behavior for: - * struct S { int :0; }; - */ - structsize = 4; - } - else - structsize = 0; - break; - } - } - - // Round struct size up to next alignsize boundary. - // This will ensure that arrays of structs will get their internals - // aligned properly. - if (alignment.isDefault() || alignment.isPack()) - structsize = (structsize + alignsize - 1) & ~(alignsize - 1); - else - structsize = (structsize + alignment.get() - 1) & ~(alignment.get() - 1); - - sizeok = Sizeok.done; - - //printf("-StructDeclaration::finalizeSize() %s, fields.length = %d, structsize = %d\n", toChars(), cast(int)fields.length, cast(int)structsize); - - if (errors) - return; - - // Calculate fields[i].overlapped - if (checkOverlappedFields()) - { - errors = true; - return; - } - - // Determine if struct is all zeros or not - zeroInit = true; - auto lastOffset = -1; - foreach (vd; fields) - { - // First skip zero sized fields - if (vd.type.size(vd.loc) == 0) - continue; - - // only consider first sized member of an (anonymous) union - if (vd.overlapped && vd.offset == lastOffset) - continue; - lastOffset = vd.offset; - - if (vd._init) - { - if (vd._init.isVoidInitializer()) - /* Treat as 0 for the purposes of putting the initializer - * in the BSS segment, or doing a mass set to 0 - */ - continue; - - // Examine init to see if it is all 0s. - auto exp = vd.getConstInitializer(); - if (!exp || !_isZeroInit(exp)) - { - zeroInit = false; - break; - } - } - else if (!vd.type.isZeroInit(loc)) - { - zeroInit = false; - break; - } - } - - - argTypes = target.toArgTypes(type); - } - /// Compute cached type properties for `TypeStruct` extern(D) final void determineTypeProperties() { diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 32ea2c33aa..d76c7e0384 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -8308,3 +8308,245 @@ extern(C++) bool isAbstract(ClassDeclaration cd) return no(); } + +void finalizeSize(AggregateDeclaration ad) +{ + scope v = new FinalizeSizeVisitor(); + ad.accept(v); +} + +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); + } +} diff --git a/dmd/frontend.h b/dmd/frontend.h index 3ce96d6b0f..48db7c663d 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -6354,7 +6354,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; @@ -6701,7 +6700,6 @@ 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; @@ -7435,7 +7433,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() final override; bool isPOD(); bool hasCopyConstruction(); void accept(Visitor* v) override; From ee7b950f58839183a525cad46de330658c797813 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sat, 5 Apr 2025 03:08:43 +0200 Subject: [PATCH 045/113] dmd: Remove all public C++ functions (dlang/dmd!21149) These are all exposed under a dmd namespace (dlang/dmd!16155) --- dmd/dsymbol.h | 3 --- dmd/dsymbolsem.d | 10 +++++----- dmd/expression.h | 1 - dmd/expressionsem.d | 4 ++-- dmd/frontend.h | 14 -------------- 5 files changed, 7 insertions(+), 25 deletions(-) diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index 558d156088..b942e75e97 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -428,7 +428,4 @@ 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); } diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index d76c7e0384..f3abfe83b4 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -7531,7 +7531,7 @@ private extern(C++) class NewScopeVisitor : Visitor } -extern(C++) Dsymbols* include(Dsymbol d, Scope* sc) +Dsymbols* include(Dsymbol d, Scope* sc) { scope icv = new ConditionIncludeVisitor(sc); d.accept(icv); @@ -7891,7 +7891,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); @@ -8108,7 +8108,7 @@ private extern(C++) class OneMemberVisitor : Visitor * Return true if any of the members are static ctors or static dtors, or if * any members have members that are. */ -extern(C++) bool hasStaticCtorOrDtor(Dsymbol d) +bool hasStaticCtorOrDtor(Dsymbol d) { scope v = new HasStaticCtorOrDtor(); d.accept(v); @@ -8162,7 +8162,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()); @@ -8211,7 +8211,7 @@ Dsymbol vtblSymbol(ClassDeclaration cd) return cd.vtblsym; } -extern(C++) bool isAbstract(ClassDeclaration cd) +bool isAbstract(ClassDeclaration cd) { enum log = false; if (cd.isabstract != ThreeState.none) diff --git a/dmd/expression.h b/dmd/expression.h index 4a232fe7ae..14dc7ad4ec 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -51,7 +51,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); diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index a300311bf1..d12f442889 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -17511,7 +17511,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; @@ -17726,7 +17726,7 @@ extern(D) void lowerArrayAggregate(StaticForeach sfe, Scope* sc) sfe.aggrfe.aggr = sfe.aggrfe.aggr.ctfeInterpret(); } -extern(C++) int include(Condition c, Scope* sc) +int include(Condition c, Scope* sc) { scope v = new IncludeVisitor(sc); c.accept(v); diff --git a/dmd/frontend.h b/dmd/frontend.h index 48db7c663d..8c232a3437 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -7532,8 +7532,6 @@ class ImportAllVisitor : public Visitor void visit(StaticForeachDeclaration* _) override; }; -extern Array* include(Dsymbol* d, Scope* sc); - class ConditionIncludeVisitor : public Visitor { public: @@ -7547,8 +7545,6 @@ class ConditionIncludeVisitor : public Visitor void visit(StaticForeachDeclaration* sfd) override; }; -extern void addComment(Dsymbol* d, const char* comment); - class AddCommentVisitor : public Visitor { public: @@ -7561,16 +7557,6 @@ class AddCommentVisitor : public Visitor void visit(StaticForeachDeclaration* sfd) override; }; -extern bool hasStaticCtorOrDtor(Dsymbol* d); - -extern bool isFuncHidden(ClassDeclaration* cd, FuncDeclaration* fd); - -extern bool isAbstract(ClassDeclaration* cd); - -extern void lowerNonArrayAggregate(StaticForeach* sfe, Scope* sc); - -extern int32_t include(Condition* c, Scope* sc); - class NrvoWalker final : public StatementRewriteWalker { public: From 817b25362e0aaedc9b634adf2b273305092fa61d Mon Sep 17 00:00:00 2001 From: Abul Hossain Khan <140191921+abulgit@users.noreply.github.com> Date: Mon, 7 Apr 2025 11:39:25 +0530 Subject: [PATCH 046/113] Improve override suggestions to exclude final methods (dlang/dmd!21138) --- dmd/funcsem.d | 40 +++++++++++++++++++++++++++ tests/dmd/fail_compilation/fix19613.d | 16 +++++++++++ 2 files changed, 56 insertions(+) create mode 100644 tests/dmd/fail_compilation/fix19613.d diff --git a/dmd/funcsem.d b/dmd/funcsem.d index 8a46dda270..3daafa3f07 100644 --- a/dmd/funcsem.d +++ b/dmd/funcsem.d @@ -986,6 +986,46 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl) 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); + + // 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) + { + Dsymbol nonFinalAlt = null; + + 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 { functionToBufferFull(cast(TypeFunction)(fd.type), buf1, diff --git a/tests/dmd/fail_compilation/fix19613.d b/tests/dmd/fail_compilation/fix19613.d new file mode 100644 index 0000000000..beca56fd70 --- /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) {} +} From 36071f8ef3d7b49693305f1da9b209a7299c2591 Mon Sep 17 00:00:00 2001 From: Nayaab Zameer <148606115+nybzmr@users.noreply.github.com> Date: Tue, 8 Apr 2025 05:04:52 +0530 Subject: [PATCH 047/113] Moved the _isZeroInit function out from dstruct.d into dsymbolsem.d (dlang/dmd!21172) --- dmd/dstruct.d | 90 ----------------------------------------------- dmd/dsymbolsem.d | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 90 deletions(-) diff --git a/dmd/dstruct.d b/dmd/dstruct.d index ca9b63260c..59c33baf77 100644 --- a/dmd/dstruct.d +++ b/dmd/dstruct.d @@ -318,96 +318,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration } } -/********************************** - * Determine if exp is all binary zeros. - * Params: - * exp = expression to check - * Returns: - * true if it's all binary 0 - */ -bool _isZeroInit(Expression exp) -{ - switch (exp.op) - { - case EXP.int64: - return exp.toInteger() == 0; - - case EXP.null_: - return true; - - case EXP.structLiteral: - { - auto sle = exp.isStructLiteralExp(); - if (sle.sd.isNested()) - return false; - const isCstruct = sle.sd.isCsymbol(); // C structs are default initialized to all zeros - foreach (i; 0 .. sle.sd.fields.length) - { - auto field = sle.sd.fields[i]; - if (field.type.size(field.loc)) - { - auto e = sle.elements && i < sle.elements.length ? (*sle.elements)[i] : null; - if (e ? !_isZeroInit(e) - : !isCstruct && !field.type.isZeroInit(field.loc)) - return false; - } - } - return true; - } - - case EXP.arrayLiteral: - { - auto ale = cast(ArrayLiteralExp)exp; - - const dim = ale.elements ? ale.elements.length : 0; - - if (ale.type.toBasetype().ty == Tarray) // if initializing a dynamic array - return dim == 0; - - foreach (i; 0 .. dim) - { - if (!_isZeroInit(ale[i])) - return false; - } - - /* Note that true is returned for all T[0] - */ - return true; - } - - case EXP.string_: - { - auto se = cast(StringExp)exp; - - if (se.type.toBasetype().ty == Tarray) // if initializing a dynamic array - return se.len == 0; - - foreach (i; 0 .. se.len) - { - if (se.getIndex(i) != 0) - return false; - } - return true; - } - - case EXP.vector: - { - auto ve = cast(VectorExp) exp; - return _isZeroInit(ve.e1); - } - - case EXP.float64: - case EXP.complex80: - { - import dmd.root.ctfloat : CTFloat; - return (exp.toReal() is CTFloat.zero) && - (exp.toImaginary() is CTFloat.zero); - } - - default: - return false; - } -} /*********************************************************** * Unions are a variation on structs. diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index f3abfe83b4..bde34ac242 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -8315,6 +8315,97 @@ void finalizeSize(AggregateDeclaration ad) 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; From 1a5d3da32fbbf8944f1701b6a8ebddf1e0c7bb8e Mon Sep 17 00:00:00 2001 From: Matthew Qiu <93230055+MatthewQiu-5@users.noreply.github.com> Date: Tue, 8 Apr 2025 03:42:52 -0400 Subject: [PATCH 048/113] Moved OverDeclaration.isUnique to funcsem (dlang/dmd!21174) --- dmd/declaration.d | 21 +-------------------- dmd/frontend.h | 1 - dmd/funcsem.d | 19 +++++++++++++++++++ 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/dmd/declaration.d b/dmd/declaration.d index 4510927da7..35047da4d6 100644 --- a/dmd/declaration.d +++ b/dmd/declaration.d @@ -27,7 +27,7 @@ import dmd.dtemplate; import dmd.errors; import dmd.expression; import dmd.func; -import dmd.funcsem : overloadApply, getLevelAndCheck; +import dmd.funcsem : getLevelAndCheck; import dmd.globals; import dmd.gluelayer; import dmd.hdrgen; @@ -783,25 +783,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); diff --git a/dmd/frontend.h b/dmd/frontend.h index 8c232a3437..1cf43835cc 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -6822,7 +6822,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; }; diff --git a/dmd/funcsem.d b/dmd/funcsem.d index 3daafa3f07..f21fe181d1 100644 --- a/dmd/funcsem.d +++ b/dmd/funcsem.d @@ -3664,3 +3664,22 @@ 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; +} From f40fe8b2c79272cf3a2e7e2b53e98b790286a70c Mon Sep 17 00:00:00 2001 From: Matthew Qiu <93230055+MatthewQiu-5@users.noreply.github.com> Date: Tue, 8 Apr 2025 04:20:01 -0400 Subject: [PATCH 049/113] Extracted Dsymbol.hasPointers to visitor in dsymbolsem (dlang/dmd!21140) --- dmd/attrib.d | 5 ----- dmd/attrib.h | 1 - dmd/cxxfrontend.d | 6 ++++++ dmd/declaration.d | 6 ------ dmd/declaration.h | 1 - dmd/dstruct.d | 3 ++- dmd/dsymbol.d | 9 --------- dmd/dsymbol.h | 2 +- dmd/dsymbolsem.d | 49 +++++++++++++++++++++++++++++++++++++++++++++++ dmd/dtemplate.d | 6 ------ dmd/frontend.h | 5 ----- dmd/nspace.d | 6 ------ dmd/nspace.h | 1 - dmd/template.h | 1 - dmd/typesem.d | 2 ++ 15 files changed, 60 insertions(+), 43 deletions(-) diff --git a/dmd/attrib.d b/dmd/attrib.d index 1bfe7902a9..a03e7bbdc0 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 ef37e0adec..24d91abc62 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/cxxfrontend.d b/dmd/cxxfrontend.d index 67a174d66b..6bd3e32eee 100644 --- a/dmd/cxxfrontend.d +++ b/dmd/cxxfrontend.d @@ -198,6 +198,12 @@ bool isAbstract(ClassDeclaration cd) return dmd.dsymbolsem.isAbstract(cd); } +bool hasPointers(Dsymbol d) +{ + import dmd.dsymbolsem; + return dmd.dsymbolsem.hasPointers(d); +} + /*********************************************************** * dtemplate.d */ diff --git a/dmd/declaration.d b/dmd/declaration.d index 35047da4d6..4a1ec9f048 100644 --- a/dmd/declaration.d +++ b/dmd/declaration.d @@ -1035,12 +1035,6 @@ extern (C++) class VarDeclaration : Declaration vbitoffset < bitoffset + tbitsize; } - override final bool hasPointers() - { - //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty); - return (!isDataseg() && type.hasPointers()); - } - /************************************* * Return true if we can take the address of this variable. */ diff --git a/dmd/declaration.h b/dmd/declaration.h index d27ed584bb..874d702123 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -298,7 +298,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/dstruct.d b/dmd/dstruct.d index 59c33baf77..5aef3585ca 100644 --- a/dmd/dstruct.d +++ b/dmd/dstruct.d @@ -158,13 +158,14 @@ extern (C++) class StructDeclaration : AggregateDeclaration return; foreach (vd; fields) { + import dmd.dsymbolsem : hasPointers; if (vd.storage_class & STC.ref_ || vd.hasPointers()) { hasPointerField = true; hasUnsafeBitpatterns = true; } - if (vd._init && vd._init.isVoidInitializer() && vd.type.hasPointers()) + if (vd._init && vd._init.isVoidInitializer() && vd.hasPointers()) hasVoidInitPointers = true; if (vd.storage_class & STC.system || vd.type.hasUnsafeBitpatterns()) diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index 74ca9cbda4..1b584eafaf 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -963,15 +963,6 @@ extern (C++) class Dsymbol : ASTNode 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) { } diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index b942e75e97..77e7dabcb6 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -243,7 +243,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); @@ -428,4 +427,5 @@ namespace dmd Dsymbols *include(Dsymbol *d, Scope *sc); void setScope(Dsymbol *d, Scope *sc); void importAll(Dsymbol *d, Scope *sc); + bool hasPointers(Dsymbol *d); } diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index bde34ac242..bf0731c185 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); @@ -8641,3 +8643,50 @@ private extern(C++) class FinalizeSizeVisitor : Visitor 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; + } +} diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 2158895745..8c94856053 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -5490,12 +5490,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/frontend.h b/dmd/frontend.h index 1cf43835cc..ce1e3d37ff 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -618,7 +618,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(); @@ -1822,7 +1821,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; }; @@ -4916,7 +4914,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; }; @@ -6418,7 +6415,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; }; @@ -6892,7 +6888,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; diff --git a/dmd/nspace.d b/dmd/nspace.d index 0c93f0e799..b8116343d6 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 7b4c302303..782688b9de 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/template.h b/dmd/template.h index 5576965ce4..da754e8a7d 100644 --- a/dmd/template.h +++ b/dmd/template.h @@ -284,7 +284,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/typesem.d b/dmd/typesem.d index 71575477a1..9b706d162c 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -6686,6 +6686,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()) @@ -6696,6 +6697,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()) From 1222542fb10a9f3e1b23c07b7bd0722a82d35cec Mon Sep 17 00:00:00 2001 From: drpriver Date: Tue, 8 Apr 2025 19:59:26 -0700 Subject: [PATCH 050/113] Fix dlang/dmd!21150 - ImportC: alignment value expected, not _Alignof (dlang/dmd!21180) The gnu attribute aligned() allows specifying the alignment of an entire struct, mostly as a syntatic convenience. This attribute allows compile-time integer expressions, but the parser was trying to evaluate them ahead of time by checking for an integer literal. Instead we need to preserve the expression and defer it to a later semantic stage. Accomplish this by emulating the behavior by specifying the alignment of the first member of the struct. I didn't change how __declspec(align(#)) parses as from the documentation it seems to only allow integer literals. Some light testing with cl.exe gives syntax errors when trying to use _Alignof() in that position. --- dmd/cparse.d | 86 ++++++++++++++++-------- dmd/dsymbol.d | 1 + dmd/frontend.h | 2 + tests/dmd/compilable/test21150.c | 43 ++++++++++++ tests/dmd/fail_compilation/alignedext.i | 7 +- tests/dmd/fail_compilation/alignedext2.i | 9 +++ 6 files changed, 114 insertions(+), 34 deletions(-) create mode 100644 tests/dmd/compilable/test21150.c create mode 100644 tests/dmd/fail_compilation/alignedext2.i diff --git a/dmd/cparse.d b/dmd/cparse.d index c7650c6c51..3ad7ed093c 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -1913,10 +1913,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: @@ -1960,8 +1964,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) { @@ -2474,7 +2478,7 @@ final class CParser(AST) : Parser!AST else break; } - t = cparseStruct(sloc, structOrUnion, tagSpecifier.packalign, symbols); + t = cparseStruct(sloc, structOrUnion, tagSpecifier, symbols); tkwx = TKW.xtag; break; } @@ -2536,6 +2540,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; @@ -3620,26 +3625,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) { @@ -3978,9 +3975,10 @@ 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 Specifier specifier, ref AST.Dsymbols* symbols) { Identifier tag; + auto packalign = specifier.packalign; if (token.value == TOK.identifier) { @@ -4013,7 +4011,7 @@ final class CParser(AST) : Parser!AST /* GNU Extensions * Parse the postfix gnu-attributes (opt) */ - Specifier specifier; + specifier.packalign = structalign_t(); if (token.value == TOK.__attribute__) cparseGnuAttributes(specifier); if (!specifier.packalign.isUnknown) @@ -4022,11 +4020,40 @@ final class CParser(AST) : Parser!AST 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); } } + if (specifier.alignExps && specifier.alignExps.length) + { + // Align the entire struct by aligning the first member. + if (members) + { + foreach (ref d; (*members)[]) + { + // skip possible static assert declarations + if (d.isStaticAssert()) continue; + + if (AST.AlignDeclaration ad = d.isAlignDeclaration()) + { + foreach (exp; *specifier.alignExps) + ad.exps.push(exp); + break; + } + else + { + auto decls = new AST.Dsymbols(1); + (*decls)[0] = d; + d = new AST.AlignDeclaration(d.loc, specifier.alignExps, decls); + break; + } + } + } + } } else if (!tag) error("missing tag `identifier` after `%s`", Token.toChars(structOrUnion)); @@ -4178,8 +4205,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); } @@ -5155,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 } diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index 1b584eafaf..d2c1f8b308 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -1226,6 +1226,7 @@ extern (C++) class Dsymbol : ASTNode return null; } } + inout(AlignDeclaration) isAlignDeclaration() inout { return dsym == DSYM.alignDeclaration ? cast(inout(AlignDeclaration)) cast(void*) this : null; } inout(AnonDeclaration) isAnonDeclaration() inout { return dsym == DSYM.anonDeclaration ? cast(inout(AnonDeclaration)) cast(void*) this : null; } inout(CPPNamespaceDeclaration) isCPPNamespaceDeclaration() inout { return dsym == DSYM.cppNamespaceDeclaration ? cast(inout(CPPNamespaceDeclaration)) cast(void*) this : null; } inout(VisibilityDeclaration) isVisibilityDeclaration() inout { return dsym == DSYM.visibilityDeclaration ? cast(inout(VisibilityDeclaration)) cast(void*) this : null; } diff --git a/dmd/frontend.h b/dmd/frontend.h index ce1e3d37ff..44a370492c 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; @@ -674,6 +675,7 @@ class Dsymbol : public ASTNode EnumDeclaration* isEnumDeclaration(); SymbolDeclaration* isSymbolDeclaration(); AttribDeclaration* isAttribDeclaration(); + AlignDeclaration* isAlignDeclaration(); AnonDeclaration* isAnonDeclaration(); CPPNamespaceDeclaration* isCPPNamespaceDeclaration(); VisibilityDeclaration* isVisibilityDeclaration(); diff --git a/tests/dmd/compilable/test21150.c b/tests/dmd/compilable/test21150.c new file mode 100644 index 0000000000..7f193b528f --- /dev/null +++ b/tests/dmd/compilable/test21150.c @@ -0,0 +1,43 @@ +// 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"); diff --git a/tests/dmd/fail_compilation/alignedext.i b/tests/dmd/fail_compilation/alignedext.i index eae3137ce4..55c8477e0b 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 0000000000..a0950ca9fe --- /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; }; From 6e4276acc48c613d1f18cc9b5d50bcfd7956eae7 Mon Sep 17 00:00:00 2001 From: drpriver Date: Wed, 9 Apr 2025 02:58:14 -0700 Subject: [PATCH 051/113] ImportC: can't access members in static array (dlang/dmd!21185) Fixes https://github.com/dlang/dmd/issues/20472 Arrays in C implicitly convert to a pointer to their first member, so do the implicit conversion when using them in an arrow member lookup. --- dmd/importc.d | 6 ++++++ tests/dmd/compilable/test20472.c | 12 ++++++++++++ tests/dmd/compilable/testcstuff1.c | 5 +++-- 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 tests/dmd/compilable/test20472.c diff --git a/dmd/importc.d b/dmd/importc.d index 72808a67f7..dcd6bb1d40 100644 --- a/dmd/importc.d +++ b/dmd/importc.d @@ -126,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()) diff --git a/tests/dmd/compilable/test20472.c b/tests/dmd/compilable/test20472.c new file mode 100644 index 0000000000..aae7e07380 --- /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/testcstuff1.c b/tests/dmd/compilable/testcstuff1.c index d57ae9d81d..db0f59058f 100644 --- a/tests/dmd/compilable/testcstuff1.c +++ b/tests/dmd/compilable/testcstuff1.c @@ -398,8 +398,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; } From 82098854e91f706541f247e4b41574edbd0a0211 Mon Sep 17 00:00:00 2001 From: drpriver Date: Wed, 9 Apr 2025 16:16:54 -0700 Subject: [PATCH 052/113] ImportC: improve error message for size_t (dlang/dmd!21187) Resolves: https://github.com/dlang/dmd/issues/20414 Add some hints for common missing includes. --- dmd/expressionsem.d | 30 ++++++++++++++++------- dmd/imphint.d | 24 +++++++++++++++++++ dmd/typesem.d | 33 +++++++++++++++++--------- tests/dmd/fail_compilation/test20414.c | 15 ++++++++++++ tests/dmd/fail_compilation/test23003.c | 2 +- 5 files changed, 83 insertions(+), 21 deletions(-) create mode 100644 tests/dmd/fail_compilation/test20414.c diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index d12f442889..61ef350bde 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -4116,16 +4116,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(); } diff --git a/dmd/imphint.d b/dmd/imphint.d index 382a0f3786..e22bcc8b12 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/typesem.d b/dmd/typesem.d index 9b706d162c..59f22fa778 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(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; diff --git a/tests/dmd/fail_compilation/test20414.c b/tests/dmd/fail_compilation/test20414.c new file mode 100644 index 0000000000..90fff588f9 --- /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/test23003.c b/tests/dmd/fail_compilation/test23003.c index 3a5d92d783..df4c46fc87 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` --- */ From 28dff4fb03c423297a703e299b49af8ead0ea24c Mon Sep 17 00:00:00 2001 From: drpriver Date: Wed, 9 Apr 2025 16:20:50 -0700 Subject: [PATCH 053/113] ImportC: allow `_Alignof expression` (dlang/dmd!21181) Resolves https://github.com/dlang/dmd/issues/20434 Allowing this gnu/clang extension actually removes lines of code as we can unify the parsing and semantics of `_Alignof` and `sizeof` and have the normal D machinery handle the difference later. --- dmd/cparse.d | 26 ++++----------------- dmd/expressionsem.d | 32 +------------------------- tests/dmd/compilable/alignas.c | 4 ++-- tests/dmd/compilable/testcstuff1.c | 1 + tests/dmd/fail_compilation/test22246.c | 17 -------------- 5 files changed, 9 insertions(+), 71 deletions(-) delete mode 100644 tests/dmd/fail_compilation/test22246.c diff --git a/dmd/cparse.d b/dmd/cparse.d index 3ad7ed093c..f3b863c324 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -982,6 +982,7 @@ final class CParser(AST) : Parser!AST * sizeof unary-expression * sizeof ( type-name ) * _Alignof ( type-name ) + * _Alignof unary-expression // gcc extension * * unary-operator: * & * + - ~ ! @@ -1044,8 +1045,10 @@ final class CParser(AST) : Parser!AST e = new AST.ComExp(loc, e); break; + case TOK._Alignof: case TOK.sizeof_: { + Identifier id = token.value == TOK.sizeof_? Id.__sizeof : Id.__xalignof; nextToken(); if (token.value == TOK.leftParenthesis) { @@ -1084,7 +1087,7 @@ final class CParser(AST) : Parser!AST e = cparseUnaryExp(); } - e = new AST.DotIdExp(loc, e, Id.__sizeof); + e = new AST.DotIdExp(loc, e, id); break; } @@ -1096,17 +1099,6 @@ final class CParser(AST) : Parser!AST e = cparseCastExp(); break; - case TOK._Alignof: - { - nextToken(); - check(TOK.leftParenthesis); - auto t = cparseTypeName(); - check(TOK.rightParenthesis); - e = new AST.TypeExp(loc, t); - e = new AST.DotIdExp(loc, e, Id.__xalignof); - break; - } - default: e = cparsePostfixExp(e); break; @@ -5025,6 +5017,7 @@ final class CParser(AST) : Parser!AST return false; break; + case TOK._Alignof: case TOK.sizeof_: t = peek(t); if (t.value == TOK.leftParenthesis) @@ -5042,15 +5035,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. diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 61ef350bde..e5f9e301a2 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -8191,37 +8191,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; diff --git a/tests/dmd/compilable/alignas.c b/tests/dmd/compilable/alignas.c index 1631ab61e2..623a2f8394 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/testcstuff1.c b/tests/dmd/compilable/testcstuff1.c index db0f59058f..5b92f507fd 100644 --- a/tests/dmd/compilable/testcstuff1.c +++ b/tests/dmd/compilable/testcstuff1.c @@ -329,6 +329,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"); diff --git a/tests/dmd/fail_compilation/test22246.c b/tests/dmd/fail_compilation/test22246.c deleted file mode 100644 index ff71913396..0000000000 --- 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); -} From 38da1d3db676ae5704f75295426e9a901948bae2 Mon Sep 17 00:00:00 2001 From: drpriver Date: Thu, 10 Apr 2025 14:08:10 -0700 Subject: [PATCH 054/113] =?UTF-8?q?Fix=2020334:=20ImportC:=20enums=20creat?= =?UTF-8?q?ed=20from=20string=20literal=20#defines=20don=E2=80=99t=20impli?= =?UTF-8?q?citly=20convert=20to=20const(char)*=20in=20D.=20(dlang/dmd!2119?= =?UTF-8?q?3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/dlang/dmd/issues/20334 After preprocessing, #defines in C code that are just string literals are converted into D enums. As these are collected for use in D code, they should behave like D string literals and not C string literals. --- dmd/cparse.d | 2 +- dmd/expression.d | 5 ++++- dmd/expression.h | 1 + dmd/expressionsem.d | 6 +++--- dmd/frontend.h | 3 ++- tests/dmd/compilable/imports/imp20344.c | 2 ++ tests/dmd/compilable/test20344.d | 14 ++++++++++++++ 7 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 tests/dmd/compilable/imports/imp20344.c create mode 100644 tests/dmd/compilable/test20344.d diff --git a/dmd/cparse.d b/dmd/cparse.d index f3b863c324..9ef2abc5eb 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -6193,7 +6193,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; diff --git a/dmd/expression.d b/dmd/expression.d index 8cb28cc208..9207a0942d 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -1406,6 +1406,8 @@ extern (C++) final class StringExp : Expression /// If the string is parsed from a hex string literal bool hexString = false; + /// If the string is from a collected C macro + bool cMacro = false; enum char NoPostfix = 0; @@ -1417,13 +1419,14 @@ extern (C++) final class StringExp : Expression this.sz = 1; // work around LDC bug #1286 } - extern (D) this(Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix = NoPostfix) scope + extern (D) this(Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix = NoPostfix, bool cMacro = false) scope { super(loc, EXP.string_); this.string = cast(char*)string.ptr; // note that this.string should be const this.len = len; this.sz = sz; this.postfix = postfix; + this.cMacro = cMacro; } static StringExp create(Loc loc, const(char)* s) diff --git a/dmd/expression.h b/dmd/expression.h index 14dc7ad4ec..9bd0c7994d 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -353,6 +353,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); diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index e5f9e301a2..d97f96e653 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -4429,7 +4429,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(); @@ -4454,7 +4454,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(); @@ -4466,7 +4466,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(); diff --git a/dmd/frontend.h b/dmd/frontend.h index 44a370492c..85f946061b 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -3608,6 +3608,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); @@ -5548,7 +5549,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]; diff --git a/tests/dmd/compilable/imports/imp20344.c b/tests/dmd/compilable/imports/imp20344.c new file mode 100644 index 0000000000..56ac79c930 --- /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/test20344.d b/tests/dmd/compilable/test20344.d new file mode 100644 index 0000000000..26ee9a3269 --- /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); +} From 69afcee7fb618ecb9a9bc2e89e4c50c556f14aa6 Mon Sep 17 00:00:00 2001 From: drpriver Date: Thu, 10 Apr 2025 14:10:31 -0700 Subject: [PATCH 055/113] ImportC: va_arg fails in working C code (dlang/dmd!21186) Fixes https://github.com/dlang/dmd/issues/20423 Ultimate cause of this issue was that va_arg was being shadowed by the collected template-like macros. As va_arg is not a normal function (it takes a type as a parameter), this interfered with the cparser's rewrite of va_arg to a call to the single argument template version in core.stdc.stdarg. --- dmd/cparse.d | 20 ++++++++++++++++---- tests/dmd/compilable/test20423.c | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 tests/dmd/compilable/test20423.c diff --git a/dmd/cparse.d b/dmd/cparse.d index 9ef2abc5eb..e852dfd4c2 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -6085,6 +6085,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); @@ -6096,6 +6104,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(); @@ -6341,10 +6356,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/tests/dmd/compilable/test20423.c b/tests/dmd/compilable/test20423.c new file mode 100644 index 0000000000..6311c2a5f1 --- /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); +} From 62ba6c2b38af72355a8cfe62f5dcc157dd80a443 Mon Sep 17 00:00:00 2001 From: Nicholas Wilson Date: Fri, 11 Apr 2025 16:38:16 +0800 Subject: [PATCH 056/113] [NFC] outline class function semantic analysis out of `funcDeclarationSemantic` (dlang/dmd!21182) This closes over several `goto`s whose target labels are now contained completely within the outlined code. --- dmd/funcsem.d | 1097 +++++++++++++++++++++++++------------------------ 1 file changed, 558 insertions(+), 539 deletions(-) diff --git a/dmd/funcsem.d b/dmd/funcsem.d index f21fe181d1..a7fc488fca 100644 --- a/dmd/funcsem.d +++ b/dmd/funcsem.d @@ -283,20 +283,6 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl) if (!funcdecl.originalType) funcdecl.originalType = funcdecl.type.syntaxCopy(); - static TypeFunction getFunctionType(FuncDeclaration fd) - { - if (auto tf = fd.type.isTypeFunction()) - return tf; - - if (!fd.type.isTypeError()) - { - .error(fd.loc, "%s `%s` `%s` must be a function instead of `%s`", fd.kind, fd.toPrettyChars, fd.toChars(), fd.type.toChars()); - fd.type = Type.terror; - } - fd.errors = true; - return null; - } - if (sc.inCfile) { /* C11 allows a function to be declared with a typedef, D does not. @@ -573,664 +559,697 @@ void funcDeclarationSemantic(Scope* sc, FuncDeclaration funcdecl) if (ClassDeclaration cd = parent.isClassDeclaration()) { - parent = cd = objc.getParent(funcdecl, cd); + switch (classFuncSemantic(cd, funcdecl, parent, sc, f)) + { + case 0: break; + case 1: goto Ldone; + case 2: return; + default: assert(0); + } + } + else if (funcdecl.isOverride() && !parent.isTemplateInstance()) + .error(funcdecl.loc, "%s `%s` `override` only applies to class member functions", funcdecl.kind, funcdecl.toPrettyChars); - if (funcdecl.isCtorDeclaration()) + if (auto ti = parent.isTemplateInstance) + { + objc.setSelector(funcdecl, sc); + objc.setAsOptional(funcdecl, sc); + } + + 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()); + } } + } - if (funcdecl.storage_class & STC.abstract_) - cd.isabstract = ThreeState.yes; + funcdecl.checkMain(); // Check main() parameters and return type - // if static function, do not put in vtbl[] - if (!funcdecl.isVirtual()) + /* Purity and safety can be inferred for some functions by examining + * the function body. + */ + if (funcdecl.canInferAttributes(sc)) + funcdecl.initInferAttributes(); + + funcdecl.semanticRun = PASS.semanticdone; + + /* Save scope for possible later use (if we need the + * function internals) + */ + funcdecl._scope = sc.copy(); + funcdecl._scope.setNoFree(); + + __gshared bool printedMain = false; // semantic might run more than once + if (global.params.v.verbose && !printedMain) + { + const(char)* type = funcdecl.isMain() ? "main" : funcdecl.isWinMain() ? "winmain" : funcdecl.isDllMain() ? "dllmain" : cast(const(char)*)null; + Module mod = sc._module; + + if (type && mod) { - //printf("\tnot virtual\n"); - goto Ldone; + printedMain = true; + auto name = mod.srcfile.toChars(); + auto path = FileName.searchPath(global.importPaths, name, true); + message("entry %-10s\t%s", type, path ? path : name); } - // Suppress further errors if the return type is an error - if (funcdecl.type.nextOf() == Type.terror) - goto Ldone; + } - bool may_override = false; - for (size_t i = 0; i < cd.baseclasses.length; i++) + if (funcdecl.fbody && sc._module.isRoot() && + (funcdecl.isMain() || funcdecl.isWinMain() || funcdecl.isDllMain() || funcdecl.isCMain())) + global.hasMainFunction = true; + + if (funcdecl.fbody && funcdecl.isMain() && sc._module.isRoot()) + { + // check if `_d_cmain` is defined + bool cmainTemplateExists() + { + Dsymbol pscopesym; + auto rootSymbol = sc.search(funcdecl.loc, Id.empty, pscopesym); + if (auto moduleSymbol = rootSymbol.search(funcdecl.loc, Id.object)) + if (moduleSymbol.search(funcdecl.loc, Id.CMain)) + return true; + + return false; + } + + // Only mixin `_d_cmain` if it is defined + if (cmainTemplateExists()) + { + // add `mixin _d_cmain!();` to the declaring module + auto tqual = new TypeIdentifier(funcdecl.loc, Id.CMain); + auto tm = new TemplateMixin(funcdecl.loc, null, tqual, null); + sc._module.members.push(tm); + } + } + + assert(funcdecl.type.ty != Terror || funcdecl.errors); + + // semantic for parameters' UDAs + foreach (i, param; f.parameterList) + { + if (param && param.userAttribDecl) + param.userAttribDecl.dsymbolSemantic(sc); + } +} + +/** + Returns: + 0 if semantic analysis in `funcDeclarationSemantic` should continue as normal + 1 if it should skip over some analysis and `goto Ldone;` + 2 if `funcDeclarationSemantic` should return early because of forward refernce error or + the derived class cd doesn't have its vtbl[] allocated yet + */ +private int classFuncSemantic(ClassDeclaration cd, FuncDeclaration funcdecl, + ref Dsymbol parent, Scope* sc, TypeFunction f) +{ + parent = cd = objc.getParent(funcdecl, cd); + + if (funcdecl.isCtorDeclaration()) + { + return 1; + } + + if (funcdecl.storage_class & STC.abstract_) + cd.isabstract = ThreeState.yes; + + // if static function, do not put in vtbl[] + if (!funcdecl.isVirtual()) + { + //printf("\tnot virtual\n"); + return 1; + } + // Suppress further errors if the return type is an error + if (funcdecl.type.nextOf() == Type.terror) + return 1; + + bool may_override = false; + for (size_t i = 0; i < cd.baseclasses.length; i++) + { + BaseClass* b = (*cd.baseclasses)[i]; + ClassDeclaration cbd = b.type.toBasetype().isClassHandle(); + if (!cbd) + continue; + for (size_t j = 0; j < cbd.vtbl.length; j++) { - BaseClass* b = (*cd.baseclasses)[i]; - ClassDeclaration cbd = b.type.toBasetype().isClassHandle(); - if (!cbd) + 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 - */ - 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. + /* Only need to have a tintro if the vptr + * offsets differ */ - - 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 if (fd.isFinalFunc()) + // 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) { - // 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); + Dsymbol nonFinalAlt = null; - // 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) + auto overloadableSyms = cdparent.symtab.lookup(fd.ident); + if (overloadableSyms) { - Dsymbol nonFinalAlt = null; - - auto overloadableSyms = cdparent.symtab.lookup(fd.ident); - if (overloadableSyms) + // Check each overload to find one that's not final + overloadApply(overloadableSyms, (Dsymbol s) { - // Check each overload to find one that's not final - overloadApply(overloadableSyms, (Dsymbol s) + if (auto funcAlt = s.isFuncDeclaration()) { - if (auto funcAlt = s.isFuncDeclaration()) + if (funcAlt != fd && !funcAlt.isFinalFunc()) { - if (funcAlt != fd && !funcAlt.isFinalFunc()) - { - nonFinalAlt = funcAlt; - return 1; - } + 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()); } + 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 - { - functionToBufferFull(cast(TypeFunction)(fd.type), buf1, - new Identifier(fd.toPrettyChars()), hgs, null); + } + else + { + functionToBufferFull(cast(TypeFunction)(fd.type), buf1, + new Identifier(fd.toPrettyChars()), hgs, null); - error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?", - funcdeclToChars, buf1.peekChars()); + error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?", + funcdeclToChars, buf1.peekChars()); - // Supplemental error for parameter scope differences - auto tf1 = cast(TypeFunction)funcdecl.type; - auto tf2 = cast(TypeFunction)fd.type; + // Supplemental error for parameter scope differences + auto tf1 = cast(TypeFunction)funcdecl.type; + auto tf2 = cast(TypeFunction)fd.type; - if (tf1 && tf2) + if (tf1 && tf2) + { + auto params1 = tf1.parameterList; + auto params2 = tf2.parameterList; + + if (params1.length == params2.length) { - auto params1 = tf1.parameterList; - auto params2 = tf2.parameterList; + bool hasScopeDifference = false; - if (params1.length == params2.length) + for (size_t i = 0; i < params1.length; i++) { - bool hasScopeDifference = false; - - for (size_t i = 0; i < params1.length; i++) - { - auto p1 = params1[i]; - auto p2 = params2[i]; + auto p1 = params1[i]; + auto p2 = params2[i]; - if ((p1.storageClass & STC.scope_) == (p2.storageClass & STC.scope_)) - continue; + if ((p1.storageClass & STC.scope_) == (p2.storageClass & STC.scope_)) + continue; - if (!(p2.storageClass & STC.scope_)) - continue; + if (!(p2.storageClass & STC.scope_)) + continue; - 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 (!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)); } } - } - } - 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); - - /* 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 `%s`?", + funcdeclToChars, s.kind, s.toPrettyChars()); + errorSupplemental(funcdecl.loc, "Functions are the only declarations that may be overridden"); } } - - 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); - - 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); - } - - } - 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); + else + .error(funcdecl.loc, "%s `%s` does not override any function", funcdecl.kind, funcdecl.toPrettyChars); } - objc.validateSelector(funcdecl); - objc.validateOptional(funcdecl); - // Reflect this.type to f because it could be changed by findVtblIndex - f = funcdecl.type.toTypeFunction(); +L2: + objc.setSelector(funcdecl, sc); + objc.checkLinkage(funcdecl); + objc.addToClassMethodList(funcdecl, cd); + objc.setAsOptional(funcdecl, sc); -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. + /* Go through all the interface bases. + * Disallow overriding any final functions in the interface(s). */ - if (funcdecl.isVirtual()) + foreach (b; cd.interfaces) { - if (auto ti = parent.isTemplateInstance()) + if (b.sym) { - // Take care of nested templates - while (1) + if (auto s = search_function(b.sym, funcdecl.ident)) { - 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()); + 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()); + } } } } - 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(); - - 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.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; + 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); - return false; - } - - // Only mixin `_d_cmain` if it is defined - if (cmainTemplateExists()) - { - // add `mixin _d_cmain!();` to the declaring module - auto tqual = new TypeIdentifier(funcdecl.loc, Id.CMain); - auto tm = new TemplateMixin(funcdecl.loc, null, tqual, null); - sc._module.members.push(tm); - } + 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; } /***************************************** From 945d2aebe065bf746b9a0cfe7e9207f3ceb06ddb Mon Sep 17 00:00:00 2001 From: fossdd Date: Sat, 12 Apr 2025 12:01:30 +0200 Subject: [PATCH 057/113] druntime: add support for musl RISCV64 (dlang/dmd!21213) Based on https://git.musl-libc.org/cgit/musl/tree/arch/riscv64/bits?h=v1.2.5 --- runtime/druntime/src/core/stdc/fenv.d | 5 +++++ runtime/druntime/src/core/sys/posix/signal.d | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/runtime/druntime/src/core/stdc/fenv.d b/runtime/druntime/src/core/stdc/fenv.d index ce77d5c1e6..7d42d5c8c0 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/sys/posix/signal.d b/runtime/druntime/src/core/sys/posix/signal.d index 81fb9d22ac..bdc68687d0 100644 --- a/runtime/druntime/src/core/sys/posix/signal.d +++ b/runtime/druntime/src/core/sys/posix/signal.d @@ -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"); From 3f3cd80514cae38534a4056ffa2cf8dd2e6107c0 Mon Sep 17 00:00:00 2001 From: drpriver Date: Sat, 12 Apr 2025 04:17:24 -0700 Subject: [PATCH 058/113] Fix dlang/dmd!21210 - ImportC: Initializing struct containing array with = {0} fails (dlang/dmd!21211) Fixes https://github.com/dlang/dmd/issues/21210 --- dmd/initsem.d | 8 ++++++-- tests/dmd/runnable/structinit.c | 25 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/dmd/initsem.d b/dmd/initsem.d index a4633a604e..4719acb756 100644 --- a/dmd/initsem.d +++ b/dmd/initsem.d @@ -761,9 +761,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/tests/dmd/runnable/structinit.c b/tests/dmd/runnable/structinit.c index dd0b242627..2ee8debc69 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; } From 605cadf5fe0a8116ce5ca17d80695fd4548a0b6e Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 12 Apr 2025 05:21:01 -0700 Subject: [PATCH 059/113] fix dlang/dmd!21161 placement new fails on default-init struct (dlang/dmd!21212) --- tests/dmd/runnable/placenew.d | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/dmd/runnable/placenew.d b/tests/dmd/runnable/placenew.d index d90d10a5e7..9b5a3a4fb3 100644 --- a/tests/dmd/runnable/placenew.d +++ b/tests/dmd/runnable/placenew.d @@ -93,6 +93,21 @@ 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); +} + +/*************************************************/ + int main() { test1(); @@ -101,6 +116,7 @@ int main() test4(); test5(); test6(); + test7(); return 0; } From 732ddbf4832d92b92d9ec60795112dc76f66f833 Mon Sep 17 00:00:00 2001 From: drpriver Date: Sat, 12 Apr 2025 15:55:56 -0700 Subject: [PATCH 060/113] ImportC: Fix interaction of aligned and packed structs (dlang/dmd!21204) Previous iteration of this did not properly account for the interaction of aligned and packed and would even segfault on a null access in such a case. This version properly handles that interaction by aligning the struct itself instead of the first member and not forcing the struct alignment to 1 if it is packed. --- dmd/cparse.d | 95 ++++++++++++-------------------- dmd/frontend.h | 1 + dmd/mtype.d | 4 +- tests/dmd/compilable/test21150.c | 34 ++++++++++++ 4 files changed, 73 insertions(+), 61 deletions(-) diff --git a/dmd/cparse.d b/dmd/cparse.d index e852dfd4c2..86f85e34ce 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -1775,7 +1775,7 @@ final class CParser(AST) : Parser!AST 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()) + if (!tt.alignExps && !tt.packalign.isUnknown()) { // saw `struct __declspec(align(N)) Tag ...` auto st = stag.isStructDeclaration(); @@ -1785,7 +1785,13 @@ final class CParser(AST) : Parser!AST tt.members = null; if (!symbols) symbols = new AST.Dsymbols(); - auto stags = applySpecifier(stag, specifier); + 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); return stags; } @@ -2452,25 +2458,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, symbols); + t = cparseStruct(sloc, structOrUnion, symbols); tkwx = TKW.xtag; break; } @@ -3940,7 +3928,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); } /************************************* @@ -3967,10 +3955,26 @@ final class CParser(AST) : Parser!AST * Returns: * type of the struct */ - private AST.Type cparseStruct(Loc loc, TOK structOrUnion, ref Specifier specifier, 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; - auto packalign = specifier.packalign; if (token.value == TOK.identifier) { @@ -3985,7 +3989,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; @@ -4003,13 +4007,10 @@ final class CParser(AST) : Parser!AST /* GNU Extensions * Parse the postfix gnu-attributes (opt) */ - specifier.packalign = structalign_t(); 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 @@ -4017,33 +4018,7 @@ final class CParser(AST) : Parser!AST auto decls = new AST.Dsymbols(1); (*decls)[0] = d; - d = new AST.AlignDeclaration(d.loc, specifier.packalign, decls); - } - } - if (specifier.alignExps && specifier.alignExps.length) - { - // Align the entire struct by aligning the first member. - if (members) - { - foreach (ref d; (*members)[]) - { - // skip possible static assert declarations - if (d.isStaticAssert()) continue; - - if (AST.AlignDeclaration ad = d.isAlignDeclaration()) - { - foreach (exp; *specifier.alignExps) - ad.exps.push(exp); - break; - } - else - { - auto decls = new AST.Dsymbols(1); - (*decls)[0] = d; - d = new AST.AlignDeclaration(d.loc, specifier.alignExps, decls); - break; - } - } + d = new AST.AlignDeclaration(d.loc, tagSpecifier.packalign, decls); } } } @@ -4051,14 +4026,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); } /************************************* diff --git a/dmd/frontend.h b/dmd/frontend.h index e072f2c91f..caff0d3310 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -4850,6 +4850,7 @@ class TypeTag final : public Type Loc loc; TOK tok; structalign_t packalign; + Array* alignExps; Identifier* id; Type* base; Array* members; diff --git a/dmd/mtype.d b/dmd/mtype.d index e0af692bcc..9b46b26b4f 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -3761,6 +3761,7 @@ extern (C++) final class TypeTag : Type Loc loc; /// location of declaration TOK tok; /// TOK.struct_, TOK.union_, TOK.enum_ structalign_t packalign; /// alignment of struct/union fields + Expressions* alignExps; /// alignment of struct itself Identifier id; /// tag name identifier Type base; /// base type for enums otherwise null Dsymbols* members; /// members of struct, null if none @@ -3770,7 +3771,7 @@ extern (C++) final class TypeTag : Type /// struct S { int a; } s1, *s2; MOD mod; /// modifiers to apply after type is resolved (only MODFlags.const_ at the moment) - extern (D) this(Loc loc, TOK tok, Identifier id, structalign_t packalign, Type base, Dsymbols* members) @safe + extern (D) this(Loc loc, TOK tok, Identifier id, structalign_t packalign, Expressions* alignExps, Type base, Dsymbols* members) @safe { //printf("TypeTag ctor %s %p\n", id ? id.toChars() : "null".ptr, this); super(Ttag); @@ -3778,6 +3779,7 @@ extern (C++) final class TypeTag : Type this.tok = tok; this.id = id; this.packalign = packalign; + this.alignExps = alignExps; this.base = base; this.members = members; this.mod = 0; diff --git a/tests/dmd/compilable/test21150.c b/tests/dmd/compilable/test21150.c index 7f193b528f..c536d363e5 100644 --- a/tests/dmd/compilable/test21150.c +++ b/tests/dmd/compilable/test21150.c @@ -41,3 +41,37 @@ struct __attribute__((aligned(4))) D { __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)"); From 7418e512cd00b9673c6233c08906b225d1d886ea Mon Sep 17 00:00:00 2001 From: Emily Date: Sun, 13 Apr 2025 02:23:30 +0200 Subject: [PATCH 061/113] Changed author name to new one (dlang/dmd!21217) I have changed my name and would not like to have anything public associated with my old name. Signed-off-by: Emily --- runtime/druntime/src/core/sys/bionic/err.d | 2 +- runtime/druntime/src/core/sys/bionic/string.d | 2 +- runtime/druntime/src/core/sys/darwin/err.d | 2 +- runtime/druntime/src/core/sys/darwin/string.d | 2 +- runtime/druntime/src/core/sys/dragonflybsd/err.d | 2 +- runtime/druntime/src/core/sys/dragonflybsd/string.d | 2 +- runtime/druntime/src/core/sys/freebsd/err.d | 2 +- runtime/druntime/src/core/sys/freebsd/string.d | 2 +- runtime/druntime/src/core/sys/linux/err.d | 2 +- runtime/druntime/src/core/sys/linux/string.d | 2 +- runtime/druntime/src/core/sys/netbsd/err.d | 2 +- runtime/druntime/src/core/sys/netbsd/string.d | 2 +- runtime/druntime/src/core/sys/netbsd/sys/featuretest.d | 2 +- runtime/druntime/src/core/sys/openbsd/err.d | 2 +- runtime/druntime/src/core/sys/openbsd/string.d | 2 +- runtime/druntime/src/core/sys/solaris/err.d | 2 +- runtime/druntime/src/core/volatile.d | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/runtime/druntime/src/core/sys/bionic/err.d b/runtime/druntime/src/core/sys/bionic/err.d index e2756e10c9..a14f21bb1e 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 10a5610ac4..9430a7bab4 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 d96c790f3b..19b51626a1 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 ac988b58f0..14bae215cd 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 c3693f85f5..7f7cf9467f 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 1a85ba606a..c15bb9268e 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 8937e0ec70..5cb443a6f8 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 459e911587..ba7b3c019d 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 c3752de520..d346a0805f 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/string.d b/runtime/druntime/src/core/sys/linux/string.d index a8da398246..7288231730 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/netbsd/err.d b/runtime/druntime/src/core/sys/netbsd/err.d index 44eb66adc2..399ddea989 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 f1281da275..d83d22d56d 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 3901ea9703..ded053a36e 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 b4676140e3..271f2c4bfc 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 4480c94ac3..e0c33be9d6 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/solaris/err.d b/runtime/druntime/src/core/sys/solaris/err.d index f787643015..03bdd7ecb9 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/volatile.d b/runtime/druntime/src/core/volatile.d index 1703450c65..76ce3879e0 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) */ From 16f7ceaab8e71dbeb2d1304bb251a1130e852357 Mon Sep 17 00:00:00 2001 From: drpriver Date: Sun, 13 Apr 2025 23:35:20 -0700 Subject: [PATCH 062/113] =?UTF-8?q?Fix=2018127=20-=20ImportC:=20redeclarat?= =?UTF-8?q?ion=20of=20struct=20in=20different=20translation=20unit=20doesn?= =?UTF-8?q?=E2=80=99t=20check=20compatibility=20(dlang/dmd!21224)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/dlang/dmd/issues/18127 When merging struct definitions from different C imports, check that the structs are actually compatible according to the C rules. If they are not, issue an error. --- dmd/dsymbolsem.d | 244 +++++++++++++++++- tests/dmd/compilable/imports/imp18127a.c | 74 ++++++ tests/dmd/compilable/imports/imp18127b.c | 74 ++++++ tests/dmd/compilable/test18127.d | 4 + .../dmd/fail_compilation/imports/imp18127a.c | 83 ++++++ .../dmd/fail_compilation/imports/imp18127b.c | 80 ++++++ tests/dmd/fail_compilation/test18127.d | 106 ++++++++ 7 files changed, 661 insertions(+), 4 deletions(-) create mode 100644 tests/dmd/compilable/imports/imp18127a.c create mode 100644 tests/dmd/compilable/imports/imp18127b.c create mode 100644 tests/dmd/compilable/test18127.d create mode 100644 tests/dmd/fail_compilation/imports/imp18127a.c create mode 100644 tests/dmd/fail_compilation/imports/imp18127b.c create mode 100644 tests/dmd/fail_compilation/test18127.d diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index bf0731c185..7127ffc9b3 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -3091,10 +3091,18 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor StructDeclaration sym = ts.sym; if (sd.isCsymbol() && sym.isCsymbol()) { - /* This is two structs imported from different C files. - * Just ignore sd, the second one. The first one will always - * be found when going through the type. - */ + + if (!isCCompatible(sd, sym)) + { + // Already issued an error. + errorSupplemental(sd.loc, "C %ss with the same name from different imports are merged", sd.kind); + } + else { + /* This is two structs imported from different C files. + * Just ignore sd, the second one. The first one will always + * be found when going through the type. + */ + } } else { @@ -3134,6 +3142,234 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor //printf("-StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok); } + // + // Checks if two structs are compatible + // Implements the rules according to C23 6.2.7 + // + static bool isCCompatible(StructDeclaration a, StructDeclaration b) + { + // Get the name of a type, while avoiding exposing "__tagXXX" anonymous structs + static const(char)* typeName(Type t) + { + if (TypeStruct ts = t.isTypeStruct()) + { + if (ts.sym.ident.toString().startsWith("__tag")) + return ts.sym.isUnionDeclaration() ? "(anonymous union)".ptr: "(anonymous struct)".ptr; + } + return t.toChars(); + } + + void incompatError() + { + .error(a.loc, "%s `%s` already exists with an incompatible definition.", + a.kind, typeName(a.type)); + errorSupplemental(b.loc, "previously declared here"); + } + + + // For recursive calls into unnamed structs (so Type.equals() doesn't work). + static bool isCCompatibleUnnamedStruct(Type a, Type b) + { + TypeStruct ats = a.isTypeStruct(); + if (!ats) return false; + TypeStruct bts = b.isTypeStruct(); + if (!bts) return false; + // Hack, anonymous structs within a struct are given + // an anonymous id starting with __tag. + if (!ats.sym.ident.toString().startsWith("__tag")) + return false; + if (!bts.sym.ident.toString().startsWith("__tag")) + return false; + return isCCompatible(ats.sym, bts.sym); + } + + if (a.fields.length != b.fields.length) + { + incompatError(); + errorSupplemental(a.loc, "`%s` has %zu field(s) while `%s` has %zu field(s)", + a.toPrettyChars(), a.fields.length, b.toPrettyChars(), b.fields.length); + return false; + } + // both are structs or both are unions + if ((a.isUnionDeclaration() is null) != (b.isUnionDeclaration() is null)) + { + incompatError(); + errorSupplemental(a.loc, "`%s` is a %s while `%s` is a %s", + a.toPrettyChars(), a.kind, b.toPrettyChars(), b.kind); + return false; + } + if (a.alignment != b.alignment) + { + incompatError(); + errorSupplemental(a.loc, "`%s` has different alignment or packing", a.toPrettyChars()); + if (a.alignment.isDefault() && ! b.alignment.isDefault()) + { + errorSupplemental(a.loc, "`%s` alignment: default", a.toPrettyChars()); + errorSupplemental(b.loc, "`%s` alignment: %u", + b.toPrettyChars(), cast(uint)b.alignment.get()); + } + else if (!a.alignment.isDefault() && b.alignment.isDefault()) + { + errorSupplemental(a.loc, "`%s` alignment: %u", + a.toPrettyChars(), cast(uint)a.alignment.get()); + errorSupplemental(b.loc, "`%s` alignment: default", + b.toPrettyChars()); + } + else if (a.alignment.get() != b.alignment.get()) + { + errorSupplemental(a.loc, "`%s` alignment: %u", + a.toPrettyChars(), cast(uint)a.alignment.get()); + errorSupplemental(b.loc, "`%s` alignment: %u", + b.toPrettyChars(), cast(uint)b.alignment.get()); + } + if (a.alignment.isPack() != b.alignment.isPack()) + { + errorSupplemental(a.loc, "`%s` packed: %s", + a.toPrettyChars(), a.alignment.isPack()?"true".ptr:"false".ptr); + errorSupplemental(b.loc, "`%s` packed: %s", + b.toPrettyChars(), b.alignment.isPack()?"true".ptr:"false".ptr); + } + return false; + } + foreach (size_t i, VarDeclaration a_field; a.fields[]) + { + VarDeclaration b_field = b.fields[i]; + // + // — there shall be a one-to-one correspondence between + // their members such that each pair of corresponding + // members are declared with compatible types; + // + if (!a_field.type.equals(b_field.type) && !isCCompatibleUnnamedStruct(a_field.type, b_field.type)) + { + // Already errored, just bail + incompatError(); + if (a_field.type.isTypeError()) return false; + if (b_field.type.isTypeError()) return false; + + errorSupplemental(a_field.loc, "Field %zu differs in type", i); + errorSupplemental(a_field.loc, "typeof(%s): %s", + a_field.toChars(), typeName(a_field.type)); + errorSupplemental(b_field.loc, "typeof(%s): %s", + b_field.toChars(), typeName(b_field.type)); + return false; + } + // + // — if one member of the pair is declared with an + // alignment specifier, the second is declared with an + // equivalent alignment specifier; + // + if (a_field.alignment != b_field.alignment) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in alignment or packing", i); + if (a_field.alignment.isDefault() && ! b_field.alignment.isDefault()) + { + errorSupplemental(a_field.loc, "`%s.%s` alignment: default", + a.toPrettyChars(),a_field.toChars()); + errorSupplemental(b_field.loc, "`%s.%s` alignment: %u", + b.toPrettyChars(), b_field.toChars(), cast(uint)b_field.alignment.get()); + } + else if (!a_field.alignment.isDefault() && b_field.alignment.isDefault()) + { + errorSupplemental(a_field.loc, "`%s.%s` alignment: %u", + a.toPrettyChars(), a_field.toChars(), cast(uint)a_field.alignment.get()); + errorSupplemental(b_field.loc, "`%s.%s` alignment: default", + b.toPrettyChars(), b_field.toChars()); + } + else if (a_field.alignment.get() != b_field.alignment.get()) + { + errorSupplemental(a_field.loc, "`%s.%s` alignment: %u", + a.toPrettyChars(), a_field.toChars(), + cast(uint)a_field.alignment.get()); + errorSupplemental(b_field.loc, "`%s.%s` alignment: %u", + b.toPrettyChars(), b_field.toChars(), + cast(uint)b_field.alignment.get()); + } + if (a_field.alignment.isPack() != b_field.alignment.isPack()) + { + errorSupplemental(a_field.loc, "`%s.%s` packed: %s", + a.toPrettyChars(), a_field.toChars(), + a_field.alignment.isPack()?"true".ptr:"false".ptr); + errorSupplemental(b_field.loc, "`%s.%s` packed: %s", + b.toPrettyChars(), b_field.toChars(), + b_field.alignment.isPack()?"true".ptr:"false".ptr); + } + return false; + } + // + // - and, if one member of the pair is declared with a + // name, the second is declared with the same name. + // + if (a_field.ident.isAnonymous()) + { + if (!b_field.ident.isAnonymous()) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in name", i); + errorSupplemental(a_field.loc, "(anonymous)", a_field.ident.toChars()); + errorSupplemental(b_field.loc, "%s", b_field.ident.toChars()); + return false; + } + } + else if (b_field.ident.isAnonymous()) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in name", i); + errorSupplemental(a_field.loc, "%s", a_field.ident.toChars()); + errorSupplemental(b_field.loc, "(anonymous)"); + return false; + } + else if (a_field.ident != b_field.ident) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in name", i); + errorSupplemental(a_field.loc, "%s", a_field.ident.toChars()); + errorSupplemental(b_field.loc, "%s", b_field.ident.toChars()); + return false; + } + + // + // For two structures or unions, corresponding bit-fields shall have the same widths. + // + BitFieldDeclaration bfa = a_field.isBitFieldDeclaration(); + BitFieldDeclaration bfb = b_field.isBitFieldDeclaration(); + if ((bfa is null) != (bfb is null)) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in being a bitfield", i); + if (bfa is null) + { + errorSupplemental(a_field.loc, "`%s.%s` is not a bitfield", + a.toPrettyChars(), a_field.toChars()); + errorSupplemental(b_field.loc, "`%s.%s` is a bitfield", + b.toPrettyChars(), b_field.toChars()); + } + else if (bfb is null) + { + errorSupplemental(a_field.loc, "`%s.%s` *is a bitfield", + a.toPrettyChars(), a_field.toChars()); + errorSupplemental(b_field.loc, "`%s.%s` is not a bitfield", + b.toPrettyChars(), b_field.toChars()); + } + return false; + } + if (bfa !is null && bfb !is null) + { + if (bfa.fieldWidth != bfb.fieldWidth) + { + incompatError(); + errorSupplemental(a_field.loc, "Field %zu differs in bitfield width", i); + errorSupplemental(a_field.loc, "`%s.%s`: %u", + a.toPrettyChars(), a_field.toChars(), bfa.fieldWidth); + errorSupplemental(b_field.loc, "`%s.%s`: %u", + b.toPrettyChars(), b_field.toChars(), bfb.fieldWidth); + return false; + } + } + } + return true; + } + void interfaceSemantic(ClassDeclaration cd) { cd.vtblInterfaces = new BaseClasses(); diff --git a/tests/dmd/compilable/imports/imp18127a.c b/tests/dmd/compilable/imports/imp18127a.c new file mode 100644 index 0000000000..cd173151db --- /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 0000000000..cd173151db --- /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/test18127.d b/tests/dmd/compilable/test18127.d new file mode 100644 index 0000000000..35e6bdc5b1 --- /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/fail_compilation/imports/imp18127a.c b/tests/dmd/fail_compilation/imports/imp18127a.c new file mode 100644 index 0000000000..2ef629e3b5 --- /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 0000000000..3cbbf7a9a6 --- /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/test18127.d b/tests/dmd/fail_compilation/test18127.d new file mode 100644 index 0000000000..ec0487cd89 --- /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; From 51dab5b2c36915308831722c82f9edc559921398 Mon Sep 17 00:00:00 2001 From: Abul Hossain Khan <140191921+abulgit@users.noreply.github.com> Date: Mon, 14 Apr 2025 13:38:52 +0530 Subject: [PATCH 063/113] Report correct location for undefined identifiers in function return types (dlang/dmd!21223) --- dmd/typesem.d | 2 +- tests/dmd/fail_compilation/b23686.d | 2 +- tests/dmd/fail_compilation/fix21165.d | 10 ++++++++++ tests/dmd/fail_compilation/noreturn2.d | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 tests/dmd/fail_compilation/fix21165.d diff --git a/dmd/typesem.d b/dmd/typesem.d index 1485132f68..05fc8f8cb3 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -181,7 +181,7 @@ private void resolveHelper(TypeQualified mt, Loc loc, Scope* sc, Dsymbol s, Dsym (id == Id._super && sc.getClassScope())) error(loc, "undefined identifier `%s`, did you mean `typeof(%s)`?", p, p); else - error(loc, "undefined identifier `%s`", p); + error(mt.loc, "undefined identifier `%s`", p); } else { if (const n = cIncludeHint(id.toString())) diff --git a/tests/dmd/fail_compilation/b23686.d b/tests/dmd/fail_compilation/b23686.d index 4c2a5bd026..5838f5c8e1 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/fix21165.d b/tests/dmd/fail_compilation/fix21165.d new file mode 100644 index 0000000000..ad8f586d9e --- /dev/null +++ b/tests/dmd/fail_compilation/fix21165.d @@ -0,0 +1,10 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/fix21165.d(9): Error: undefined identifier `foo` +--- +*/ + +// Test case from Issue #21165 +foo +f() {} diff --git a/tests/dmd/fail_compilation/noreturn2.d b/tests/dmd/fail_compilation/noreturn2.d index ec6bd3ebce..b49417436a 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` --- +/ From 701b9554473273894a8ed4f532e3313e17b07c49 Mon Sep 17 00:00:00 2001 From: drpriver Date: Mon, 14 Apr 2025 01:37:38 -0700 Subject: [PATCH 064/113] Fix 21225: ImportC: macro interpreted as an enum conflicts with function (dlang/dmd!21228) Fixes https://github.com/dlang/dmd/issues/21225 Don't let C macro variable declarations shadow any symbol. --- dmd/importc.d | 2 +- tests/dmd/compilable/test21225.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/compilable/test21225.c diff --git a/dmd/importc.d b/dmd/importc.d index dcd6bb1d40..d3381dc858 100644 --- a/dmd/importc.d +++ b/dmd/importc.d @@ -548,7 +548,7 @@ Dsymbol handleSymbolRedeclarations(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsy auto vd2 = s2.isVarDeclaration(); // existing declaration if (vd && vd.isCmacro()) - return vd2; + return s2; assert(!(vd2 && vd2.isCmacro())); diff --git a/tests/dmd/compilable/test21225.c b/tests/dmd/compilable/test21225.c new file mode 100644 index 0000000000..45eb5cd92f --- /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 From 4482b136f3e582393c7242d2850d550937df21ae Mon Sep 17 00:00:00 2001 From: Abul Hossain Khan <140191921+abulgit@users.noreply.github.com> Date: Tue, 15 Apr 2025 02:47:17 +0530 Subject: [PATCH 065/113] Add Testcases For other Fixed issues (dlang/dmd!21231) --- tests/dmd/fail_compilation/fix21165.d | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/dmd/fail_compilation/fix21165.d b/tests/dmd/fail_compilation/fix21165.d index ad8f586d9e..1d38013b4d 100644 --- a/tests/dmd/fail_compilation/fix21165.d +++ b/tests/dmd/fail_compilation/fix21165.d @@ -1,10 +1,30 @@ /* TEST_OUTPUT: --- -fail_compilation/fix21165.d(9): Error: undefined identifier `foo` +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; From ee168981425abcf048fb412f0f371df07e009bcb Mon Sep 17 00:00:00 2001 From: drpriver Date: Tue, 15 Apr 2025 00:31:21 -0700 Subject: [PATCH 066/113] Fix dlang/dmd!20499 - [ImportC] typedef struct with name as a pointer cannot be used with struct name (dlang/dmd!21232) Fixes https://github.com/dlang/dmd/issues/20499 Fixes https://github.com/dlang/dmd/issues/20963 ImportC deferred declaring "tagged" types (structs/unions/enums) until after it saw a possible typedef so that the identifier for a typedef declaration like: typedef struct { int x; } Foo; would give the struct the name Foo. In several circumstances, this led to tagged types not being declared. Resolve this by chasing down those circumstances. Also, there were other circumstances where types weren't being correctly declared which caused other issues. Lock those down. --- dmd/cparse.d | 150 ++++++----- tests/dmd/compilable/imports/imp20499.c | 8 + tests/dmd/compilable/nested_struct_20499.c | 61 +++++ tests/dmd/compilable/struct_decls_20499.c | 287 +++++++++++++++++++++ tests/dmd/compilable/test20499.d | 2 + tests/dmd/compilable/test20963.c | 12 + tests/dmd/fail_compilation/failcstuff3.c | 2 +- tests/dmd/runnable/exe1.c | 2 - 8 files changed, 456 insertions(+), 68 deletions(-) create mode 100644 tests/dmd/compilable/imports/imp20499.c create mode 100644 tests/dmd/compilable/nested_struct_20499.c create mode 100644 tests/dmd/compilable/struct_decls_20499.c create mode 100644 tests/dmd/compilable/test20499.d create mode 100644 tests/dmd/compilable/test20963.c diff --git a/dmd/cparse.d b/dmd/cparse.d index 86f85e34ce..fd5074f5bf 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -1720,6 +1720,34 @@ final class CParser(AST) : Parser!AST /********************************* Declaration Parser ***************************/ //{ + void declareTag(AST.TypeTag tt, ref Specifier specifier, bool generate_enum_id = false) + { + if (!tt.id && (generate_enum_id || tt.tok != TOK.enum_)) tt.id = Identifier.generateId("__tag"); + /* `struct tag;` and `struct tag { ... };` + * always result in a declaration in the current scope + */ + auto stag = (tt.tok == TOK.struct_) ? new AST.StructDeclaration(tt.loc, tt.id, false) : + (tt.tok == TOK.union_) ? new AST.UnionDeclaration(tt.loc, tt.id) : + new AST.EnumDeclaration(tt.loc, tt.id, tt.base); + if (!tt.alignExps && !tt.packalign.isUnknown()) + { + // saw `struct __declspec(align(N)) Tag ...` + auto st = stag.isStructDeclaration(); + st.alignment = tt.packalign; + } + stag.members = tt.members; + tt.members = null; + if (!symbols) + symbols = new AST.Dsymbols(); + AST.Dsymbol stags = stag; + if (tt.alignExps) + { + auto decls = new AST.Dsymbols(1); + (*decls)[0] = stags; + stags = new AST.AlignDeclaration(stags.loc, tt.alignExps, decls); + } + symbols.push(stags); + } /************************************* * C11 6.7 * declaration: @@ -1767,34 +1795,9 @@ final class CParser(AST) : Parser!AST specifier.packalign = this.packalign; auto tspec = cparseDeclarationSpecifiers(level, specifier); - AST.Dsymbol declareTag(AST.TypeTag tt, ref Specifier specifier) - { - /* `struct tag;` and `struct tag { ... };` - * always result in a declaration in the current scope - */ - auto stag = (tt.tok == TOK.struct_) ? new AST.StructDeclaration(tt.loc, tt.id, false) : - (tt.tok == TOK.union_) ? new AST.UnionDeclaration(tt.loc, tt.id) : - new AST.EnumDeclaration(tt.loc, tt.id, tt.base); - if (!tt.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); - 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 */ @@ -1820,12 +1823,13 @@ final class CParser(AST) : Parser!AST !tt.id && (tt.tok == TOK.struct_ || tt.tok == TOK.union_)) return; // legal but meaningless empty declaration, ignore it - auto stags = declareTag(tt, specifier); + if (tt.members || tt.tok != TOK.enum_) + declareTag(tt, specifier); if (0 && tt.tok == TOK.enum_) // C11 proscribes enums with no members, but we allow it { if (!tt.members) - error(tt.loc, "`enum %s` has no members", stags.toChars()); + error(tt.loc, "`enum %s` has no members", tt.toChars()); } return; } @@ -1838,6 +1842,15 @@ final class CParser(AST) : Parser!AST return; } + if (auto tt = tspec.isTypeTag()) + { + if (tt.id && tt.members) + { + // Valid tag decl with name and members, go ahead and declare it now. + declareTag(tt, specifier); + } + } + if (tspec && specifier.mod & MOD.xconst) { tspec = toConst(tspec); @@ -1954,7 +1967,7 @@ final class CParser(AST) : Parser!AST typedefTab.setDim(typedefTabLengthSave); symbols = symbolsSave; if (!symbols) - symbols = new AST.Dsymbols; // lazilly create it + symbols = new AST.Dsymbols; // lazily create it if (level != LVL.global && !tspec && !specifier.scw && !specifier.mod) error("declaration-specifier-seq required"); @@ -1975,38 +1988,33 @@ final class CParser(AST) : Parser!AST bool isalias = true; Identifier idt; - if (auto ts = dt.isTypeStruct()) - { - if (ts.sym.isAnonymous()) - { - // This is a typedef for an anonymous struct-or-union. - // Directly set the ident for the struct-or-union. - ts.sym.ident = id; - isalias = false; - } - idt = ts.sym.ident; - } - else if (auto te = dt.isTypeEnum()) - { - if (te.sym.isAnonymous()) - { - // This is a typedef for an anonymous enum. - te.sym.ident = id; - isalias = false; - } - idt = te.sym.ident; - } - else if (auto tt = dt.isTypeTag()) + if (auto tt = dt.isTypeTag()) { if (!tt.id && id) /* This applies for enums declared as * typedef enum {A} E; + * Or for similar structs and unions. */ tt.id = id; - Specifier spec; - declareTag(tt, spec); + if (tt.members) + { + Specifier spec; + declareTag(tt, spec); + } idt = tt.id; } + else if (auto tt = tspec.isTypeTag()) + { + // The unusual situation of an anonymous typedef struct where the + // first typedef can't be used as its name. + // Just declare it now so we can get a valid id. + if (!tt.id && tt.members) + { + Specifier spec; + declareTag(tt, spec, true); + idt = tt.id; + } + } if (isalias) { //printf("AliasDeclaration %s %s\n", id.toChars(), dt.toChars()); @@ -2035,6 +2043,16 @@ final class CParser(AST) : Parser!AST if (dt.ty == AST.Tvoid) error("`void` has no value"); + if (auto tt = tspec.isTypeTag()) + { + // Anonymous struct being used as a var decl type + if (!tt.id && tt.members && tt.tok != TOK.enum_) + { + Specifier spec; + declareTag(tt, spec); + } + } + AST.Initializer initializer; bool hasInitializer; if (token.value == TOK.assign) @@ -4097,7 +4115,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 @@ -4113,17 +4131,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) { diff --git a/tests/dmd/compilable/imports/imp20499.c b/tests/dmd/compilable/imports/imp20499.c new file mode 100644 index 0000000000..7ae74906f7 --- /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 0000000000..ec83abde17 --- /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 0000000000..27f342db4d --- /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/test20499.d b/tests/dmd/compilable/test20499.d new file mode 100644 index 0000000000..9e9e1d2712 --- /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/test20963.c b/tests/dmd/compilable/test20963.c new file mode 100644 index 0000000000..a5aead13d2 --- /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/fail_compilation/failcstuff3.c b/tests/dmd/fail_compilation/failcstuff3.c index f54c942d44..dd07c3e165 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/runnable/exe1.c b/tests/dmd/runnable/exe1.c index 104025f295..3f256810fa 100644 --- a/tests/dmd/runnable/exe1.c +++ b/tests/dmd/runnable/exe1.c @@ -1242,7 +1242,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; @@ -1253,7 +1252,6 @@ void cdind() c = curwp->w_dotp->l_text[curwp->w_doto]&0xFF; assert(c == '2'); } -#endif } void logexp() From 5b8a3e8b462e257fa8ec4160cab41b3f337786fa Mon Sep 17 00:00:00 2001 From: Abhay Pratap Date: Tue, 15 Apr 2025 15:33:44 +0530 Subject: [PATCH 067/113] dcast.d: Improve pointer conversion error messages (dlang/dmd!21221) --- dmd/dcast.d | 23 +++++++++++++++++-- .../fail_compilation/diag_ptr_conversion.d | 17 ++++++++++++++ tests/dmd/fail_compilation/fail163.d | 16 +++++++------ 3 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 tests/dmd/fail_compilation/diag_ptr_conversion.d diff --git a/dmd/dcast.d b/dmd/dcast.d index 1f9126069f..9e35dde296 100644 --- a/dmd/dcast.d +++ b/dmd/dcast.d @@ -161,8 +161,27 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t) return ErrorExp.get(); } - error(e.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", - e.toErrMsg(), ts[0], ts[1]); + // 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(); 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 0000000000..ea144b2c9d --- /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/fail163.d b/tests/dmd/fail_compilation/fail163.d index 7f8f028fa5..590bf23931 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() From cfa273737dff91de0e18687c7fec561dd83d06b4 Mon Sep 17 00:00:00 2001 From: Albert24GG Date: Tue, 15 Apr 2025 13:07:47 +0300 Subject: [PATCH 068/113] Templatize `_d_arraysetcapacity` hook (dlang/dmd!21143) --- .../src/core/internal/array/capacity.d | 137 ++++++++++++++++++ .../druntime/src/core/internal/array/utils.d | 25 ++++ runtime/druntime/src/core/internal/lifetime.d | 19 +++ runtime/druntime/src/object.d | 16 +- runtime/druntime/src/rt/lifetime.d | 113 --------------- 5 files changed, 194 insertions(+), 116 deletions(-) diff --git a/runtime/druntime/src/core/internal/array/capacity.d b/runtime/druntime/src/core/internal/array/capacity.d index 10ce2c65c9..f58b5571b7 100644 --- a/runtime/druntime/src/core/internal/array/capacity.d +++ b/runtime/druntime/src/core/internal/array/capacity.d @@ -9,6 +9,143 @@ */ module core.internal.array.capacity; +import core.attribute : weak; + +// for now, all GC array functions are not exposed via core.memory. +extern (C) +{ + size_t gc_reserveArrayCapacity(void[] slice, size_t request, bool atomic) nothrow pure; + bool gc_shrinkArrayUsed(void[] slice, size_t existingUsed, bool atomic) nothrow pure; +} + + +/** +Set the array capacity. + +If the array capacity isn't currently large enough +to hold the requested capacity (in number of elements), then the array is +resized/reallocated to the appropriate size. + +Pass in a requested capacity of 0 to get the current capacity. + +Params: + T = the type of the elements in the array (this should be unqualified) + newcapacity = requested new capacity + p = pointer to array to set. Its `length` is left unchanged. + isshared = true if the underlying data is shared + +Returns: the number of elements that can actually be stored once the resizing is done +*/ +size_t _d_arraysetcapacityPureNothrow(T)(size_t newcapacity, void[]* p, bool isshared) pure nothrow @trusted +do +{ + alias PureNothrowType = size_t function(size_t, void[]*, bool) pure nothrow @trusted; + return (cast(PureNothrowType) &_d_arraysetcapacity!T)(newcapacity, p, isshared); +} + +size_t _d_arraysetcapacity(T)(size_t newcapacity, void[]* p, bool isshared) @trusted +in +{ + assert(!(*p).length || (*p).ptr); +} +do +{ + import core.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; + version (D_InlineAsm_X86) + { + size_t reqsize = void; + + asm nothrow pure + { + mov EAX, newcapacity; + mul EAX, size; + mov reqsize, EAX; + jnc Lcontinue; + } + } + else version (D_InlineAsm_X86_64) + { + size_t reqsize = void; + + asm nothrow pure + { + 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!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) + 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!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; +} + // 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; diff --git a/runtime/druntime/src/core/internal/array/utils.d b/runtime/druntime/src/core/internal/array/utils.d index deaae3f95d..1d105e6ebf 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 a7446debae..fd78de221d 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/object.d b/runtime/druntime/src/object.d index e274fd30e8..0f978a36e1 100644 --- a/runtime/druntime/src/object.d +++ b/runtime/druntime/src/object.d @@ -3901,9 +3901,11 @@ private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr, assert(s == "abc"); } + // HACK: This is a lie. `_d_arraysetcapacity` is neither `nothrow` nor `pure`, but this lie is // necessary for now to prevent breaking code. -private extern (C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void[]* arrptr) pure nothrow; +import core.internal.array.capacity : _d_arraysetcapacityPureNothrow; +import core.internal.traits: Unqual; /** (Property) Gets the current _capacity of a slice. The _capacity is the size @@ -3918,7 +3920,10 @@ Note: The _capacity of a slice may be impacted by operations on other slices. */ @property size_t capacity(T)(T[] arr) pure nothrow @trusted { - return _d_arraysetcapacity(typeid(T[]), 0, cast(void[]*)&arr); + const isshared = is(T == shared); + alias Unqual_T = Unqual!T; + // The postblit of T may be impure, so we need to use the `pure nothrow` wrapper + return _d_arraysetcapacityPureNothrow!Unqual_T(0, cast(void[]*)&arr, isshared); } /// @@ -3957,7 +3962,12 @@ size_t reserve(T)(ref T[] arr, size_t newcapacity) pure nothrow @trusted if (__ctfe) return newcapacity; else - return _d_arraysetcapacity(typeid(T[]), newcapacity, cast(void[]*)&arr); + { + const isshared = is(T == shared); + alias Unqual_T = Unqual!T; + // The postblit of T may be impure, so we need to use the `pure nothrow` wrapper + return _d_arraysetcapacityPureNothrow!Unqual_T(newcapacity, cast(void[]*)&arr, isshared); + } } /// diff --git a/runtime/druntime/src/rt/lifetime.d b/runtime/druntime/src/rt/lifetime.d index f77d8b9c4e..8d6f116f16 100644 --- a/runtime/druntime/src/rt/lifetime.d +++ b/runtime/druntime/src/rt/lifetime.d @@ -313,119 +313,6 @@ void __doPostblit(void *ptr, size_t len, const TypeInfo ti) } } - -/** -Set the array capacity. - -If the array capacity isn't currently large enough -to hold the requested capacity (in number of elements), then the array is -resized/reallocated to the appropriate size. - -Pass in a requested capacity of 0 to get the current capacity. - -Params: - ti = type info of element type - newcapacity = requested new capacity - p = pointer to array to set. Its `length` is left unchanged. - -Returns: the number of elements that can actually be stored once the resizing is done -*/ -extern(C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void[]* p) @weak -in -{ - assert(ti); - assert(!(*p).length || (*p).ptr); -} -do -{ - auto isshared = typeid(ti) is typeid(TypeInfo_Shared); - auto tinext = unqualify(ti.next); - auto size = tinext.tsize; - version (D_InlineAsm_X86) - { - size_t reqsize = void; - - asm - { - mov EAX, newcapacity; - mul EAX, size; - mov reqsize, EAX; - jnc Lcontinue; - } - } - else version (D_InlineAsm_X86_64) - { - size_t reqsize = void; - - asm - { - mov RAX, newcapacity; - mul RAX, size; - mov reqsize, RAX; - jnc Lcontinue; - } - } - else - { - bool overflow = false; - size_t reqsize = mulu(size, newcapacity, overflow); - if (!overflow) - goto Lcontinue; - } -Loverflow: - onOutOfMemoryError(); - assert(0); -Lcontinue: - - // step 1, see if we can ensure the capacity is valid in-place - auto datasize = (*p).length * size; - auto curCapacity = gc_reserveArrayCapacity((*p).ptr[0 .. datasize], reqsize, isshared); - if (curCapacity != 0) - // in-place worked! - return curCapacity / size; - - if (reqsize <= datasize) - // requested size is less than array size, the current array satisfies - // the request. But this is not an appendable GC array, so return 0. - return 0; - - // step 2, if reserving in-place doesn't work, allocate a new array with at - // least the requested allocated size. - auto attrs = __typeAttrs(tinext, (*p).ptr) | BlkAttr.APPENDABLE; - auto ptr = GC.malloc(reqsize, attrs, tinext); - if (ptr is null) - goto Loverflow; - - // copy the data over. - // note that malloc will have initialized the data we did not request to 0. - memcpy(ptr, (*p).ptr, datasize); - - // handle postblit - __doPostblit(ptr, datasize, tinext); - - if (!(attrs & BlkAttr.NO_SCAN)) - { - // need to memset the newly requested data, except for the data that - // malloc returned that we didn't request. - void *endptr = ptr + reqsize; - void *begptr = ptr + datasize; - - // sanity check - assert(endptr >= begptr); - memset(begptr, 0, endptr - begptr); - } - - *p = ptr[0 .. (*p).length]; - - // set up the correct length. Note that we need to do this here, because - // the GC malloc will automatically set the used size to what we requested. - gc_shrinkArrayUsed(ptr[0 .. datasize], reqsize, isshared); - - curCapacity = gc_reserveArrayCapacity(ptr[0 .. datasize], 0, isshared); - assert(curCapacity); - return curCapacity / size; -} - /** Allocate an array with the garbage collector. From 4381109f8d97163079267f4427d8a54ef7ef38db Mon Sep 17 00:00:00 2001 From: Matthew Qiu <93230055+MatthewQiu-5@users.noreply.github.com> Date: Tue, 15 Apr 2025 07:30:15 -0400 Subject: [PATCH 069/113] Moved _foreach and indirect dep getLocalClasses from dmodule to dsymbolsem (dlang/dmd!21236) --- dmd/cxxfrontend.d | 11 ++++--- dmd/dmodule.d | 77 +---------------------------------------------- dmd/dsymbolsem.d | 74 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 81 deletions(-) diff --git a/dmd/cxxfrontend.d b/dmd/cxxfrontend.d index 6bd3e32eee..db828b5ce7 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); @@ -204,6 +199,12 @@ bool hasPointers(Dsymbol d) 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/dmodule.d b/dmd/dmodule.d index 0e0070aab5..1852210234 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; @@ -1306,83 +1306,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/dsymbolsem.d b/dmd/dsymbolsem.d index 7127ffc9b3..a6e731bf0a 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -8926,3 +8926,77 @@ private extern(C++) class HasPointersVisitor : Visitor 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); +} From dbbbf9ada8a53c12045a72103c289ca8bc669ab8 Mon Sep 17 00:00:00 2001 From: Matthew Qiu <93230055+MatthewQiu-5@users.noreply.github.com> Date: Tue, 15 Apr 2025 07:46:48 -0400 Subject: [PATCH 070/113] Moved VarDeclaration.checkNestedReference to funcsem (dlang/dmd!21237) --- dmd/declaration.d | 78 ----------------------------------------------- dmd/delegatize.d | 1 + dmd/funcsem.d | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 78 deletions(-) diff --git a/dmd/declaration.d b/dmd/declaration.d index 4a1ec9f048..25e5c31dcc 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 : getLevelAndCheck; import dmd.globals; import dmd.gluelayer; import dmd.hdrgen; @@ -1084,83 +1083,6 @@ extern (C++) class VarDeclaration : Declaration return e; } - /************************************ - * Check to see if this variable is actually in an enclosing function - * rather than the current one. - * Update nestedrefs[], closureVars[] and outerVars[]. - * Returns: true if error occurs. - */ - extern (D) final bool checkNestedReference(Scope* sc, Loc loc) - { - //printf("VarDeclaration::checkNestedReference() %s\n", toChars()); - if (sc.intypeof == 1 || sc.ctfe) - return false; - if (!parent || parent == sc.parent) - return false; - if (isDataseg() || (storage_class & STC.manifest)) - return false; - - // The current function - FuncDeclaration fdthis = sc.parent.isFuncDeclaration(); - if (!fdthis) - return false; // out of function scope - - Dsymbol p = toParent2(); - - // Function literals from fdthis to p must be delegates - ensureStaticLinkTo(fdthis, p); - - // The function that this variable is in - FuncDeclaration fdv = p.isFuncDeclaration(); - if (!fdv || fdv == fdthis) - return false; - - // Add fdthis to nestedrefs[] if not already there - if (!nestedrefs.contains(fdthis)) - nestedrefs.push(fdthis); - - //printf("\tfdv = %s\n", fdv.toChars()); - //printf("\tfdthis = %s\n", fdthis.toChars()); - if (loc.isValid()) - { - if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError) - return true; - } - - // Add this VarDeclaration to fdv.closureVars[] if not already there - if (!sc.intypeof && !sc.traitsCompiles && - // https://issues.dlang.org/show_bug.cgi?id=17605 - (fdv.skipCodegen || !fdthis.skipCodegen)) - { - if (!fdv.closureVars.contains(this)) - fdv.closureVars.push(this); - } - - if (!fdthis.outerVars.contains(this)) - fdthis.outerVars.push(this); - - //printf("fdthis is %s\n", fdthis.toChars()); - //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars()); - // __dollar creates problems because it isn't a real variable - // https://issues.dlang.org/show_bug.cgi?id=3326 - if (ident == Id.dollar) - { - .error(loc, "cannnot use `$` inside a function literal"); - return true; - } - if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759 - { - ExpInitializer ez = _init.isExpInitializer(); - assert(ez); - Expression e = ez.exp; - if (e.op == EXP.construct || e.op == EXP.blit) - e = (cast(AssignExp)e).e2; - return lambdaCheckForNestedRef(e, sc); - } - - return false; - } - override final Dsymbol toAlias() { //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym); diff --git a/dmd/delegatize.d b/dmd/delegatize.d index 344130b5e3..1f5dca66b5 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/funcsem.d b/dmd/funcsem.d index a7fc488fca..a02d9b7781 100644 --- a/dmd/funcsem.d +++ b/dmd/funcsem.d @@ -3702,3 +3702,80 @@ Dsymbol isUnique(OverDeclaration od) }); 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; +} From e9fb1c019bb8e07ce3675fc494d6957cecd983ce Mon Sep 17 00:00:00 2001 From: Matthew Qiu <93230055+MatthewQiu-5@users.noreply.github.com> Date: Tue, 15 Apr 2025 08:22:18 -0400 Subject: [PATCH 071/113] Moved Dsymbol.oneMembers to dsymbolsem (dlang/dmd!21238) --- dmd/dsymbol.d | 64 --------------------------------------- dmd/dsymbolsem.d | 77 ++++++++++++++++++++++++++++++++++++++++++----- dmd/dtemplate.d | 6 ++-- dmd/templatesem.d | 2 +- 4 files changed, 74 insertions(+), 75 deletions(-) diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index d2c1f8b308..7467112ad0 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; @@ -900,69 +899,6 @@ extern (C++) class Dsymbol : ASTNode assert(0); } - /***************************************** - * Same as Dsymbol::oneMember(), but look at an array of Dsymbols. - */ - extern (D) static bool oneMembers(Dsymbols* members, out Dsymbol ps, Identifier ident) - { - //printf("Dsymbol::oneMembers() %d\n", members ? members.length : 0); - Dsymbol s = null; - if (!members) - { - ps = null; - return true; - } - - for (size_t i = 0; i < members.length; i++) - { - Dsymbol sx = (*members)[i]; - bool x = sx.oneMember(ps, ident); //MYTODO: this temporarily creates a new dependency to dsymbolsem, will need to extract oneMembers() later - //printf("\t[%d] kind %s = %d, s = %p\n", i, sx.kind(), x, *ps); - if (!x) - { - //printf("\tfalse 1\n"); - assert(ps is null); - return false; - } - if (ps) - { - assert(ident); - if (!ps.ident || !ps.ident.equals(ident)) - continue; - if (!s) - s = ps; - else if (s.isOverloadable() && ps.isOverloadable()) - { - // keep head of overload set - FuncDeclaration f1 = s.isFuncDeclaration(); - FuncDeclaration f2 = ps.isFuncDeclaration(); - if (f1 && f2) - { - assert(!f1.isFuncAliasDeclaration()); - assert(!f2.isFuncAliasDeclaration()); - for (; f1 != f2; f1 = f1.overnext0) - { - if (f1.overnext0 is null) - { - f1.overnext0 = f2; - break; - } - } - } - } - else // more than one symbol - { - ps = null; - //printf("\tfalse 2\n"); - return false; - } - } - } - ps = s; // s is the one symbol, null if none - //printf("\ttrue\n"); - return true; - } - void addObjcSymbols(ClassDeclarations* classes, ClassDeclarations* categories) { } diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index a6e731bf0a..e93232f5b1 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -5141,7 +5141,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList if (tempinst.members.length) { Dsymbol s; - if (Dsymbol.oneMembers(tempinst.members, s, tempdecl.ident) && s) + if (oneMembers(tempinst.members, s, tempdecl.ident) && s) { //printf("tempdecl.ident = %s, s = `%s %s`\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars()); //printf("setting aliasdecl\n"); @@ -5186,7 +5186,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList if (tempinst.members.length) { Dsymbol s; - if (Dsymbol.oneMembers(tempinst.members, s, tempdecl.ident) && s) + if (oneMembers(tempinst.members, s, tempdecl.ident) && s) { if (!tempinst.aliasdecl || tempinst.aliasdecl != s) { @@ -8242,7 +8242,7 @@ private extern(C++) class OneMemberVisitor : Visitor override void visit(AttribDeclaration atb) { Dsymbols* d = atb.include(null); - result = Dsymbol.oneMembers(d, *ps, ident); + result = oneMembers(d, *ps, ident); } override void visit(StaticForeachDeclaration sfd) @@ -8265,7 +8265,7 @@ private extern(C++) class OneMemberVisitor : Visitor override void visit(StorageClassDeclaration scd) { - bool t = Dsymbol.oneMembers(scd.decl, *ps, ident); + bool t = oneMembers(scd.decl, *ps, ident); if (t && *ps) { /* This is to deal with the following case: @@ -8295,11 +8295,11 @@ private extern(C++) class OneMemberVisitor : Visitor if (cd.condition.inc != Include.notComputed) { Dsymbols* d = dmd.expressionsem.include(cd.condition, null) ? cd.decl : cd.elsedecl; - result = Dsymbol.oneMembers(d, *ps, ident); + 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; } @@ -8308,7 +8308,7 @@ private extern(C++) class OneMemberVisitor : Visitor override void visit(ScopeDsymbol sd) { if (sd.isAnonymous()) - result = Dsymbol.oneMembers(sd.members, *ps, ident); + result = oneMembers(sd.members, *ps, ident); else { // visit(Dsymbol dsym) *ps = sd; @@ -9000,3 +9000,66 @@ void getLocalClasses(Module mod, ref ClassDeclarations aclasses) _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 8c94856053..af225cca4f 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; @@ -639,7 +639,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol return; Dsymbol s; - if (!Dsymbol.oneMembers(members, s, ident) || !s) + if (!oneMembers(members, s, ident) || !s) return; onemember = s; @@ -5273,7 +5273,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol if (members.length) { Dsymbol sa; - if (Dsymbol.oneMembers(members, sa, tempdecl.ident) && sa) + if (oneMembers(members, sa, tempdecl.ident) && sa) aliasdecl = sa; } done = true; diff --git a/dmd/templatesem.d b/dmd/templatesem.d index e5efce4a8b..a2ef845974 100644 --- a/dmd/templatesem.d +++ b/dmd/templatesem.d @@ -188,7 +188,7 @@ void templateDeclarationSemantic(Scope* sc, TemplateDeclaration tempdecl) if (tempdecl.members) { Dsymbol s; - if (Dsymbol.oneMembers(tempdecl.members, s, tempdecl.ident) && s) + if (oneMembers(tempdecl.members, s, tempdecl.ident) && s) { tempdecl.onemember = s; s.parent = tempdecl; From a95a15195a11d561220d006f6bd11f7731bf5416 Mon Sep 17 00:00:00 2001 From: drpriver Date: Tue, 15 Apr 2025 16:27:33 -0700 Subject: [PATCH 072/113] Fix dlang/dmd!20502 - importc: macro conflicts with struct of same name (dlang/dmd!21234) Fixes https://github.com/dlang/dmd/issues/20502 Similar to VarDeclarations, don't let TemplateDeclarations from C defines shadow a real symbol. --- dmd/cparse.d | 2 ++ dmd/dtemplate.d | 1 + dmd/frontend.h | 1 + dmd/importc.d | 6 ++++++ dmd/template.h | 1 + tests/dmd/compilable/test20502.c | 10 ++++++++++ 6 files changed, 21 insertions(+) create mode 100644 tests/dmd/compilable/test20502.c diff --git a/dmd/cparse.d b/dmd/cparse.d index fd5074f5bf..cb066e1997 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -6057,6 +6057,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 */ diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index af225cca4f..fe398d6696 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -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 diff --git a/dmd/frontend.h b/dmd/frontend.h index caff0d3310..af5c773999 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -1749,6 +1749,7 @@ class TemplateDeclaration final : public ScopeDsymbol bool isTrivialAliasSeq; bool isTrivialAlias; bool deprecated_; + bool isCmacro; Visibility visibility; TemplatePrevious* previous; Expression* lastConstraint; diff --git a/dmd/importc.d b/dmd/importc.d index d3381dc858..059de62b1f 100644 --- a/dmd/importc.d +++ b/dmd/importc.d @@ -544,6 +544,12 @@ 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 diff --git a/dmd/template.h b/dmd/template.h index da754e8a7d..bfc4151480 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 diff --git a/tests/dmd/compilable/test20502.c b/tests/dmd/compilable/test20502.c new file mode 100644 index 0000000000..c3a44fb4cc --- /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) From 199a6ed3ae850297e90aed879e6e3f0a552113fd Mon Sep 17 00:00:00 2001 From: drpriver Date: Tue, 15 Apr 2025 19:13:50 -0700 Subject: [PATCH 073/113] Fix dlang/dmd!21241 - ImportC: wrong static function called after linking (dlang/dmd!21242) Fixes https://github.com/dlang/dmd/issues/21241 C Static functions were being given the same externally mangled name as their identifier, which caused only one to be picked when linking with linkers that supported that. Additionally, the dmd glue code was only outputting one of these static functions as a workaround for a different linker issue. Solve this by giving C static functions a unique name (by using D mangling) and adding an `isStatic()` check to the dmd glue hack. --- dmd/mangle/package.d | 6 +++++- tests/dmd/runnable/imports/imp21241a.c | 9 +++++++++ tests/dmd/runnable/imports/imp21241b.c | 9 +++++++++ tests/dmd/runnable/test21241.d | 13 +++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/runnable/imports/imp21241a.c create mode 100644 tests/dmd/runnable/imports/imp21241b.c create mode 100644 tests/dmd/runnable/test21241.d diff --git a/dmd/mangle/package.d b/dmd/mangle/package.d index 3ad2c7d579..cc797614ed 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/tests/dmd/runnable/imports/imp21241a.c b/tests/dmd/runnable/imports/imp21241a.c new file mode 100644 index 0000000000..6a40949fcf --- /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 0000000000..4808fb6b97 --- /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/test21241.d b/tests/dmd/runnable/test21241.d new file mode 100644 index 0000000000..c63011bcfa --- /dev/null +++ b/tests/dmd/runnable/test21241.d @@ -0,0 +1,13 @@ +/* +REQUIRED_ARGS: runnable/imports/imp21241a.c runnable/imports/imp21241b.c +*/ +// https://github.com/dlang/dmd/issues/21241 +import imp21241a; +import imp21241b; + +void main(){ + int x = getA(); + assert(x==aValue); + x = getB(); + assert(x==bValue); +} From 35733d738e10efc47aef4eaf1b5a0f2bbf5ea55a Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 16 Apr 2025 00:14:46 -0700 Subject: [PATCH 074/113] fix dlang/dmd!21203 Placement new does not count as initialization (dlang/dmd!21243) --- dmd/expressionsem.d | 30 +++++++++++++++++++----------- tests/dmd/runnable/placenew.d | 27 +++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index c1ece678f7..8ea9262998 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -4906,6 +4906,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 @@ -15806,11 +15807,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 */ @@ -16763,11 +16765,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 @@ -16777,6 +16780,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; @@ -16822,15 +16826,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) { @@ -16846,7 +16854,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) { diff --git a/tests/dmd/runnable/placenew.d b/tests/dmd/runnable/placenew.d index 9b5a3a4fb3..834a1f76bc 100644 --- a/tests/dmd/runnable/placenew.d +++ b/tests/dmd/runnable/placenew.d @@ -106,6 +106,32 @@ void test7() 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() @@ -117,6 +143,7 @@ int main() test5(); test6(); test7(); + test8(); return 0; } From 1bb562615e6c651cc0bc992b9cf620ee34b7b8b9 Mon Sep 17 00:00:00 2001 From: Abul Hossain Khan <140191921+abulgit@users.noreply.github.com> Date: Fri, 18 Apr 2025 04:54:30 +0530 Subject: [PATCH 075/113] Fix error location for binary operations to point at operator instead of first operand (dlang/dmd!21253) --- dmd/parse.d | 27 +++++++------------ tests/dmd/fail_compilation/fail196.d | 2 +- .../dmd/fail_compilation/fail_pretty_errors.d | 2 +- tests/dmd/fail_compilation/fix21166.d | 13 +++++++++ 4 files changed, 25 insertions(+), 19 deletions(-) create mode 100644 tests/dmd/fail_compilation/fix21166.d diff --git a/dmd/parse.d b/dmd/parse.d index c2d9a20944..574a0f230d 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -9068,11 +9068,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: @@ -9103,11 +9103,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: @@ -9138,11 +9138,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: @@ -9173,10 +9173,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) { @@ -9238,28 +9237,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); @@ -9270,12 +9267,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); @@ -9286,11 +9282,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); @@ -9300,11 +9295,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); @@ -9314,11 +9308,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/tests/dmd/fail_compilation/fail196.d b/tests/dmd/fail_compilation/fail196.d index 78c596390b..a5d4499f3f 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/fail_pretty_errors.d b/tests/dmd/fail_compilation/fail_pretty_errors.d index 79242b163e..ebd36a7cc1 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/fix21166.d b/tests/dmd/fail_compilation/fix21166.d new file mode 100644 index 0000000000..24dbf8b467 --- /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"; From f23bddb208b30ebe85cffd67fab50f58dbd4fb5e Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Fri, 18 Apr 2025 13:29:13 +0100 Subject: [PATCH 076/113] Fix wrong 'not an lvalue' error when assigning to sequence (dlang/dmd!21260) Fixes dlang/dmd!21259. --- dmd/expressionsem.d | 8 +++-- tests/dmd/fail_compilation/seq_assign.d | 43 +++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 tests/dmd/fail_compilation/seq_assign.d diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 8ea9262998..a638985464 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -10579,7 +10579,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { TupleDeclaration td = isAliasThisTuple(e2x); if (!td) - goto Lnomatch; + { + Lnomatch: + error(exp.loc, "cannot assign `%s` to expression sequence `%s`", + exp.e2.type.toChars(), exp.e1.type.toChars()); + return setError(); + } assert(exp.e1.type.ty == Ttuple); TypeTuple tt = cast(TypeTuple)exp.e1.type; @@ -10621,7 +10626,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // Do not need to overwrite this.e2 goto Ltupleassign; } - Lnomatch: } /* Inside constructor, if this is the first assignment of object field, diff --git a/tests/dmd/fail_compilation/seq_assign.d b/tests/dmd/fail_compilation/seq_assign.d new file mode 100644 index 0000000000..560bc34424 --- /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 +} From 2a9a3390b5f4cc225887ed0ce8fd0e4232ee03bf Mon Sep 17 00:00:00 2001 From: drpriver Date: Fri, 18 Apr 2025 17:43:01 -0700 Subject: [PATCH 077/113] Fix dlang/dmd!21267: ImportC: `__forceinline` ignored Fixes https://github.com/dlang/dmd/issues/21267 `__forceinline` is the same as `__attribute__((always_inline))`, so `#define` it to be the same. --- runtime/druntime/src/importc.h | 2 +- tests/dmd/compilable/test21267.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/compilable/test21267.c diff --git a/runtime/druntime/src/importc.h b/runtime/druntime/src/importc.h index dcca9ea5d4..9d8ceff4f0 100644 --- a/runtime/druntime/src/importc.h +++ b/runtime/druntime/src/importc.h @@ -56,7 +56,7 @@ */ #define __fastcall -#define __forceinline +#define __forceinline __attribute__((always_inline)) #undef _Check_return_ //#define _Check_return_ #define __pragma(x) diff --git a/tests/dmd/compilable/test21267.c b/tests/dmd/compilable/test21267.c new file mode 100644 index 0000000000..6bc355f232 --- /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); } From 5593c11c023d4a7aa0063d8b10bceb06bb4c5077 Mon Sep 17 00:00:00 2001 From: drpriver Date: Fri, 18 Apr 2025 22:02:47 -0700 Subject: [PATCH 078/113] Fix dlang/dmd!21271 - ImportC: incorrect compatibility macro for __pragma Fixes https://github.com/dlang/dmd/issues/21271 Redefine the compatibility macro in terms of C99's `_Pragma()` instead of ignoring it. Clang and GCC will replace `_Pragma()` with `#pragma` directives in the preprocessed output, while cl.exe will actually convert it back to `__pragma()`. This is still a better situation than before as ImportC partially supports `__pragma()`. --- runtime/druntime/src/importc.h | 2 +- tests/dmd/compilable/test21271.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/compilable/test21271.c diff --git a/runtime/druntime/src/importc.h b/runtime/druntime/src/importc.h index 9d8ceff4f0..cdcf830d20 100644 --- a/runtime/druntime/src/importc.h +++ b/runtime/druntime/src/importc.h @@ -59,7 +59,7 @@ #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/tests/dmd/compilable/test21271.c b/tests/dmd/compilable/test21271.c new file mode 100644 index 0000000000..732fa8b75d --- /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"); From fa40f6327ef7b4b3192c630874a71d1ea3026da9 Mon Sep 17 00:00:00 2001 From: abul Date: Sun, 20 Apr 2025 14:33:02 +0530 Subject: [PATCH 079/113] Template function named argument error messages --- dmd/funcsem.d | 70 +++++++++++++++++-- tests/dmd/fail_compilation/fix21042.d | 15 ++++ .../fail_compilation/named_arguments_error.d | 35 +++++----- .../named_arguments_ifti_error.d | 15 ++-- 4 files changed, 108 insertions(+), 27 deletions(-) create mode 100644 tests/dmd/fail_compilation/fix21042.d diff --git a/dmd/funcsem.d b/dmd/funcsem.d index a02d9b7781..3b7b3097c9 100644 --- a/dmd/funcsem.d +++ b/dmd/funcsem.d @@ -1763,13 +1763,17 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s, if (!od && !td.overnext) { .error(loc, "%s `%s` is not callable using argument types `!(%s)%s`", - td.kind(), td.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars()); + td.kind(), td.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars()); + + checkNamedArgErrorAndReport(td, argumentList, loc); } else { .error(loc, "none of the overloads of %s `%s.%s` are callable using argument types `!(%s)%s`", - td.kind(), td.parent.toPrettyChars(), td.ident.toChars(), - tiargsBuf.peekChars(), fargsBuf.peekChars()); + td.kind(), td.parent.toPrettyChars(), td.ident.toChars(), + tiargsBuf.peekChars(), fargsBuf.peekChars()); + + checkNamedArgErrorAndReport(td, argumentList, loc); } @@ -1789,7 +1793,9 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s, if (od) { .error(loc, "none of the overloads of `%s` are callable using argument types `!(%s)%s`", - od.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars()); + od.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars()); + + checkNamedArgErrorAndReportOverload(od, argumentList, loc); if (!global.gag || global.params.v.showGaggedErrors) printCandidates(loc, od, sc.isDeprecated()); return null; @@ -1920,6 +1926,62 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s, return null; } +/******************************************************** + * Check for named argument errors in template declarations and report them. + * Params: + * td = template declaration to check + * argumentList = arguments to check + * loc = location for error reporting + */ +private void checkNamedArgErrorAndReport(TemplateDeclaration td, ArgumentList argumentList, Loc loc) +{ + if (!argumentList.hasNames()) + 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.hasNames()) + 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: diff --git a/tests/dmd/fail_compilation/fix21042.d b/tests/dmd/fail_compilation/fix21042.d new file mode 100644 index 0000000000..b2b224e519 --- /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/named_arguments_error.d b/tests/dmd/fail_compilation/named_arguments_error.d index 125ebcc926..761e1d4c78 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 6d8a70a2c4..a73fd3cb2e 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)` --- */ From ad82e9e3bf9655925605efe35bf543056b70a578 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Mon, 14 Apr 2025 13:59:26 +0200 Subject: [PATCH 080/113] druntime: Move syscall bindings in perf_event to own module --- .../druntime/src/core/sys/linux/perf_event.d | 77 +--------------- .../druntime/src/core/sys/linux/sys/syscall.d | 90 +++++++++++++++++++ runtime/druntime/src/core/sys/linux/syscall.d | 14 +++ runtime/druntime/src/core/sys/linux/unistd.d | 5 ++ 4 files changed, 113 insertions(+), 73 deletions(-) create mode 100644 runtime/druntime/src/core/sys/linux/sys/syscall.d create mode 100644 runtime/druntime/src/core/sys/linux/syscall.d diff --git a/runtime/druntime/src/core/sys/linux/perf_event.d b/runtime/druntime/src/core/sys/linux/perf_event.d index 0ad072974d..f8bedfb81b 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/sys/syscall.d b/runtime/druntime/src/core/sys/linux/sys/syscall.d new file mode 100644 index 0000000000..26d516277f --- /dev/null +++ b/runtime/druntime/src/core/sys/linux/sys/syscall.d @@ -0,0 +1,90 @@ +/** + * 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; + +// +// List the numbers of the system calls the system knows. +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"); +} + +// +// Defines SYS_* names for the __NR_* numbers of known names. +enum SYS_perf_event_open = __NR_perf_event_open; 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 0000000000..84d03e75fb --- /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 548870268d..3194ec2962 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, ...); From 2344c0f42cc04e386247692c2882df39dca6caa4 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sat, 26 Apr 2025 00:53:51 +0200 Subject: [PATCH 081/113] Fix dlang/dmd!21298 - Missing string literal for gcc asm not always diagnosed (dlang/dmd!21305) Modifies the parser to only accept CTFE computed strings when the expression is surrounded by parentheses, so that it doesn't try to parse TOK.colon (`:`) as an AssignExpression. Closes: dlang/dmd!21298 --- dmd/iasmgcc.d | 53 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/dmd/iasmgcc.d b/dmd/iasmgcc.d index 3d6e6ab5b5..4d9a758bb4 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) From a08064cd2c0fdbd29c3951de336ef6d6f91c59c5 Mon Sep 17 00:00:00 2001 From: Vladimir Panteleev <108007295+VPanteleev-S7@users.noreply.github.com> Date: Sun, 27 Apr 2025 14:27:37 +0000 Subject: [PATCH 082/113] dmd.dmodule: Fix typo in addDeferredSemantic3 deduplication logic --- dmd/dmodule.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmd/dmodule.d b/dmd/dmodule.d index 1852210234..5bdde26a63 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -1022,7 +1022,7 @@ extern (C++) final class Module : Package extern (D) static void addDeferredSemantic3(Dsymbol s) { //printf("Module::addDeferredSemantic3('%s')\n", s.toChars()); - if (!deferred.contains(s)) + if (!deferred3.contains(s)) deferred3.push(s); } From ad10614ffb4488ccd90670cc56d16f68a732a09b Mon Sep 17 00:00:00 2001 From: Vladimir Panteleev <108007295+VPanteleev-S7@users.noreply.github.com> Date: Sun, 27 Apr 2025 14:27:56 +0000 Subject: [PATCH 083/113] Use internal bit flag for deferred semantics deduplication Fix an O(n^2) inefficiency in the Dsymbol deduplication logic in the addDeferredSemantic, addDeferredSemantic2 and addDeferredSemantic3 functions. The duplication check was added in 9ef1413a0d8380a3329eee508794618ff75af2cc. Unfortunately, one effect of this is that each Dsymbol insertion required a full linear scan of the Dsymbols array. In modules which cause a lot of templates to be instantiated, this can significantly impact compilation times. Resolve this by checking a new bit flag in Dsymbol as the mechanism for deduplication. Benchmarks with an internal motivating use case: Before: 27.05user 1.84system 0:29.00elapsed 99%CPU (0avgtext+0avgdata 7872684maxresident)k 0inputs+105216outputs (0major+1984500minor)pagefaults 0swaps After: 15.02user 1.81system 0:16.90elapsed 99%CPU (0avgtext+0avgdata 7873108maxresident)k 0inputs+102720outputs (0major+1985074minor)pagefaults 0swaps --- dmd/dmodule.d | 20 +++++++++++++++++--- dmd/dsymbol.d | 5 +++++ dmd/frontend.h | 21 ++++++++++++++++++--- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/dmd/dmodule.d b/dmd/dmodule.d index 5bdde26a63..eda3b5d536 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -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; @@ -1008,22 +1009,31 @@ extern (C++) final class Module : Package extern (D) static void addDeferredSemantic(Dsymbol s) { //printf("Module::addDeferredSemantic('%s')\n", s.toChars()); - if (!deferred.contains(s)) + if (!s.deferred) + { + s.deferred = true; deferred.push(s); + } } extern (D) static void addDeferredSemantic2(Dsymbol s) { //printf("Module::addDeferredSemantic2('%s')\n", s.toChars()); - if (!deferred2.contains(s)) + if (!s.deferred2) + { + s.deferred2 = true; deferred2.push(s); + } } extern (D) static void addDeferredSemantic3(Dsymbol s) { //printf("Module::addDeferredSemantic3('%s')\n", s.toChars()); - if (!deferred3.contains(s)) + if (!s.deferred3) + { + s.deferred3 = true; deferred3.push(s); + } } /****************************************** @@ -1057,6 +1067,8 @@ extern (C++) final class Module : Package todoalloc = todo; } memcpy(todo, deferred.tdata(), len * Dsymbol.sizeof); + foreach (Dsymbol s; Module.deferred[]) + s.deferred = false; deferred.setDim(0); foreach (i; 0..len) @@ -1082,6 +1094,7 @@ extern (C++) final class Module : Package for (size_t i = 0; i < a.length; i++) { Dsymbol s = (*a)[i]; + s.deferred2 = false; //printf("[%d] %s semantic2a\n", i, s.toPrettyChars()); s.semantic2(null); @@ -1099,6 +1112,7 @@ extern (C++) final class Module : Package for (size_t i = 0; i < a.length; i++) { Dsymbol s = (*a)[i]; + s.deferred3 = false; //printf("[%d] %s semantic3a\n", i, s.toPrettyChars()); s.semantic3(null); diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index 7467112ad0..e65068c762 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -343,6 +343,11 @@ extern (C++) class Dsymbol : ASTNode { bool errors; // this symbol failed to pass semantic() PASS semanticRun = PASS.initial; + + // Queued for deferred semantics: + bool deferred; // In Module.deferred + bool deferred2; // In Module.deferred2 + bool deferred3; // In Module.deferred3 } import dmd.common.bitfields; mixin(generateBitFields!(BitFields, ubyte)); diff --git a/dmd/frontend.h b/dmd/frontend.h index af5c773999..508db0a96a 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -554,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) {} }; @@ -569,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: From 4796f2a12116e54f9aa50ea4854ac1150e552400 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Sat, 15 Feb 2025 23:23:55 +0100 Subject: [PATCH 084/113] Fix dlang/dmd!20855: -v command line switch should show import sources --- dmd/dmodule.d | 2 ++ tests/dmd/compilable/test3004.d | 2 +- tests/dmd/fail_compilation/fail15616b.d | 2 +- tests/dmd/fail_compilation/finalswitch_verbose.d | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/dmd/dmodule.d b/dmd/dmodule.d index eda3b5d536..33539d4bf0 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -545,6 +545,8 @@ extern (C++) final class Module : Package } buf.printf("%s\t(%s)", ident.toChars(), m.srcfile.toChars()); message("import %s", buf.peekChars()); + if (loc != Loc.initial) + message("(imported from %s)", loc.toChars()); } if((m = m.parse()) is null) return null; diff --git a/tests/dmd/compilable/test3004.d b/tests/dmd/compilable/test3004.d index 23ec46f290..664452ef4e 100644 --- a/tests/dmd/compilable/test3004.d +++ b/tests/dmd/compilable/test3004.d @@ -1,7 +1,7 @@ // https://issues.dlang.org/show_bug.cgi?id=3004 /* REQUIRED_ARGS: -ignore -v -TRANSFORM_OUTPUT: remove_lines("^(predefs|binary|version|config|DFLAG|parse|import|semantic|entry|library|function object|function core|\s*$)") +TRANSFORM_OUTPUT: remove_lines("^(predefs|binary|version|config|DFLAG|parse|import|\(imported|semantic|entry|library|function object|function core|\s*$)") TEST_OUTPUT: --- pragma GNU_attribute (__error) diff --git a/tests/dmd/fail_compilation/fail15616b.d b/tests/dmd/fail_compilation/fail15616b.d index 4b209685ca..4cbd591cbf 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/finalswitch_verbose.d b/tests/dmd/fail_compilation/finalswitch_verbose.d index 4bf5d46f84..90e2ca7b5b 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`: From dffe7c608e6dc622eacafce5988fd2f4bd6cb7d5 Mon Sep 17 00:00:00 2001 From: Ay1nDas Date: Mon, 28 Apr 2025 00:50:11 +0530 Subject: [PATCH 085/113] Fix dlang/dmd!21317 : Wrong Location for error messages --- dmd/typesem.d | 20 +++++++++++-- tests/dmd/fail_compilation/test21317.d | 39 ++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 tests/dmd/fail_compilation/test21317.d diff --git a/dmd/typesem.d b/dmd/typesem.d index 05fc8f8cb3..ffbdfed6eb 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -1945,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) @@ -2748,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); diff --git a/tests/dmd/fail_compilation/test21317.d b/tests/dmd/fail_compilation/test21317.d new file mode 100644 index 0000000000..39b3963799 --- /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; From 346f28a17d3b140f1862be96bc9587a15eb1b40a Mon Sep 17 00:00:00 2001 From: Dennis Date: Wed, 30 Apr 2025 13:59:25 +0200 Subject: [PATCH 086/113] Document risks of the `-nothrow` flag (dlang/dmd!21316) --- dmd/cli.d | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/dmd/cli.d b/dmd/cli.d index 9e231f1c78..a2e3b106cf 100644 --- a/dmd/cli.d +++ b/dmd/cli.d @@ -658,8 +658,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", From f88e7ac6712ec5e0358b0002c9d567bca20b6467 Mon Sep 17 00:00:00 2001 From: Elias Batek Date: Fri, 25 Apr 2025 02:25:28 +0200 Subject: [PATCH 087/113] Fix dlang/dmd!21280 - Add `__NR_getrandom` aka `SYS_getrandom` --- .../druntime/src/core/sys/linux/sys/syscall.d | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/runtime/druntime/src/core/sys/linux/sys/syscall.d b/runtime/druntime/src/core/sys/linux/sys/syscall.d index 26d516277f..9e313e15c9 100644 --- a/runtime/druntime/src/core/sys/linux/sys/syscall.d +++ b/runtime/druntime/src/core/sys/linux/sys/syscall.d @@ -22,64 +22,100 @@ 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) - enum __NR_perf_event_open = 0x40000000 + 298; + { + 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"); @@ -87,4 +123,5 @@ else // // Defines SYS_* names for the __NR_* numbers of known names. +enum SYS_getrandom = __NR_getrandom; enum SYS_perf_event_open = __NR_perf_event_open; From 1404be277683ef7390f0c86541519eb312e9f864 Mon Sep 17 00:00:00 2001 From: shivangshukla7020 Date: Mon, 31 Mar 2025 18:14:28 +0530 Subject: [PATCH 088/113] Templatized arraysetlength{,i}T --- dmd/dsymbolsem.d | 2 +- dmd/expression.h | 1 + dmd/expressionsem.d | 28 +- dmd/frontend.h | 1 - dmd/id.d | 1 - .../src/core/internal/array/capacity.d | 264 ++++++++++++++---- .../src/core/internal/array/concatenation.d | 47 ++-- .../src/core/internal/array/construction.d | 2 +- runtime/druntime/src/object.d | 3 +- runtime/druntime/src/rt/lifetime.d | 253 ----------------- runtime/druntime/src/rt/tracegc.d | 2 - .../extra-files/hello-profile-postscript.sh | 5 +- .../extra-files/hello-profile.d.trace.def | 6 +- 13 files changed, 259 insertions(+), 356 deletions(-) diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index e93232f5b1..43fb0b72e4 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -4758,7 +4758,7 @@ private bool isDRuntimeHook(Identifier id) id == Id._d_arrayassign_l || id == Id._d_arrayassign_r || id == Id._d_arraysetassign || id == Id._d_arraysetctor || id == Id._d_arrayctor || - id == Id._d_arraysetlengthTImpl || id == Id._d_arraysetlengthT || + id == Id._d_arraysetlengthT || id == Id._d_arraysetlengthTTrace || id == Id._d_arrayappendT || id == Id._d_arrayappendTTrace || id == Id._d_arrayappendcTX; diff --git a/dmd/expression.h b/dmd/expression.h index 9bd0c7994d..8438196069 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -935,6 +935,7 @@ class SliceExp final : public UnaExp class ArrayLengthExp final : public UnaExp { public: + Expression lowering; void accept(Visitor *v) override { v->visit(this); } }; diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index a638985464..386d5c03ce 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -11229,25 +11229,30 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor */ if (auto ale = exp.e1.isArrayLengthExp()) { - // e1 is not an lvalue, but we let code generator handle it + // Ensure e1 is a modifiable lvalue auto ale1x = ale.e1.modifiableLvalueImpl(sc, exp.e1); if (ale1x.op == EXP.error) return setResult(ale1x); ale.e1 = ale1x; + // Ensure the element type has a valid constructor Type tn = ale.e1.type.toBasetype().nextOf(); checkDefCtor(ale.loc, tn); + // Choose correct GC hook Identifier hook = global.params.tracegc ? Id._d_arraysetlengthTTrace : Id._d_arraysetlengthT; - if (!verifyHookExist(exp.loc, *sc, Id._d_arraysetlengthTImpl, "resizing arrays")) + + // Verify the correct hook exists + if (!verifyHookExist(exp.loc, *sc, hook, "resizing arrays")) return setError(); exp.e2 = exp.e2.expressionSemantic(sc); auto lc = lastComma(exp.e2); lc = lc.optimize(WANTvalue); - // use slice expression when arr.length = 0 to avoid runtime call - if(lc.op == EXP.int64 && lc.toInteger() == 0) + + // Optimize case where arr.length = 0 + if (lc.op == EXP.int64 && lc.toInteger() == 0) { Expression se = new SliceExp(ale.loc, ale.e1, lc, lc); Expression as = new AssignExp(ale.loc, ale.e1, se); @@ -11257,30 +11262,27 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return setResult(res); } - if (!sc.needsCodegen()) // if compile time creature only + if (!sc.needsCodegen()) // Compile-time only case { exp.type = Type.tsize_t; return setResult(exp); } - // Lower to object._d_arraysetlengthTImpl!(typeof(e1))._d_arraysetlengthT{,Trace}(e1, e2) + // Ensure correct reference for _d_arraysetlengthT Expression id = new IdentifierExp(ale.loc, Id.empty); id = new DotIdExp(ale.loc, id, Id.object); - auto tiargs = new Objects(); - tiargs.push(ale.e1.type); - id = new DotTemplateInstanceExp(ale.loc, id, Id._d_arraysetlengthTImpl, tiargs); id = new DotIdExp(ale.loc, id, hook); id = id.expressionSemantic(sc); + // Generate call: _d_arraysetlengthT(e1, e2) auto arguments = new Expressions(); - arguments.push(ale.e1); - arguments.push(exp.e2); + arguments.push(ale.e1); // array + arguments.push(exp.e2); // new length Expression ce = new CallExp(ale.loc, id, arguments).expressionSemantic(sc); auto res = new LoweredAssignExp(exp, ce); - // if (global.params.verbose) - // message("lowered %s =>\n %s", exp.toChars(), res.toChars()); res.type = Type.tsize_t; + return setResult(res); } else if (auto se = exp.e1.isSliceExp()) diff --git a/dmd/frontend.h b/dmd/frontend.h index 508db0a96a..c21cf4e1bd 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -8972,7 +8972,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/id.d b/dmd/id.d index e1c22f2f04..2d10e6f991 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/runtime/druntime/src/core/internal/array/capacity.d b/runtime/druntime/src/core/internal/array/capacity.d index f58b5571b7..8c42c092af 100644 --- a/runtime/druntime/src/core/internal/array/capacity.d +++ b/runtime/druntime/src/core/internal/array/capacity.d @@ -9,16 +9,15 @@ */ module core.internal.array.capacity; -import core.attribute : weak; +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) -{ +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. @@ -146,64 +145,229 @@ Lcontinue: return curCapacity / size; } -// 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; +/** +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; -/* - * 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. - */ + // Cast the array to the unqualified type + auto unqual_arr = cast(UnqT[]) arr; -/// Implementation of `_d_arraysetlengthT` and `_d_arraysetlengthTTrace` -template _d_arraysetlengthTImpl(Tarr : T[], T) + // Call the implementation with the unqualified array and sharedness flag + size_t result = _d_arraysetlengthT_(unqual_arr, newlength, isShared); + + arr = cast(Tarr) unqual_arr; + // Return the result + return result; +} + +private size_t _d_arraysetlengthT_(Tarr : T[], T)(return ref scope Tarr arr, size_t newlength, bool isShared) @trusted { - private enum errorMessage = "Cannot resize arrays if compiling without support for runtime type information!"; - - /** - * Resize dynamic array - * Params: - * arr = the array that will be resized, taken as a reference - * newlength = new length of array - * Returns: - * The new length of the array - * Bugs: - * The safety level of this function is faked. It shows itself as `@trusted pure nothrow` to not break existing code. - */ - size_t _d_arraysetlengthT(return scope ref Tarr arr, size_t newlength) @trusted pure nothrow - { - version (DigitalMars) pragma(inline, false); - version (D_TypeInfo) + 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); + + ubyte overflow = 0; + + size_t newsize = void; + + version (D_InlineAsm_X86) + { + asm pure nothrow @nogc + { + mov EAX, sizeelem; + mul newlength; // EDX:EAX = EAX * newlength + mov newsize, EAX; + setc overflow; + } + } + else version (D_InlineAsm_X86_64) + { + asm pure nothrow @nogc { - auto ti = typeid(Tarr); + mov RAX, sizeelem; + mul newlength; // RDX:RAX = RAX * newlength + mov newsize, RAX; + setc overflow; + } + } + else + { + 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) + { + 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 (__traits(isZeroInit, T)) - ._d_arraysetlengthT(ti, newlength, cast(void[]*)&arr); - else - ._d_arraysetlengthiT(ti, newlength, cast(void[]*)&arr); + static if (hasEnabledPostblit) + __doPostblit!T((cast(T*) ptr)[0 .. newlength]); + } + + arr = (cast(T*) ptr)[0 .. newlength]; + return newlength; + } - return arr.length; + size_t oldsize = arr.length * sizeelem; + + 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]); + } } - version (D_ProfileGC) + // 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) { - import core.internal.array.utils : _d_HookTraceImpl; + 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]); + } + + arr = (cast(T*) newdata)[0 .. newlength]; + return newlength; +} - /** - * 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); +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 + { + alias Hook = _d_HookTraceImpl!(Tarr, _d_arraysetlengthT!Tarr, errorMessage); + return Hook(arr, newlength, file, line, func); } } +// @safe unittest remains intact @safe unittest { struct S @@ -212,13 +376,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 13ec5fad40..fab2a5a9b7 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 722aed46d1..76811ef3ff 100644 --- a/runtime/druntime/src/core/internal/array/construction.d +++ b/runtime/druntime/src/core/internal/array/construction.d @@ -520,7 +520,7 @@ Tarr _d_newarraymTX(Tarr : U[], T, U)(scope size_t[] dims, bool isShared=false) 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); diff --git a/runtime/druntime/src/object.d b/runtime/druntime/src/object.d index 0f978a36e1..e9838db4f3 100644 --- a/runtime/druntime/src/object.d +++ b/runtime/druntime/src/object.d @@ -4702,6 +4702,7 @@ version (D_ProfileGC) public import core.lifetime : _d_newitemTTrace; public import core.internal.array.construction : _d_newarrayTTrace; public import core.internal.array.construction : _d_newarraymTXTrace; + public import core.internal.array.capacity: _d_arraysetlengthTTrace; } public import core.internal.array.appending : _d_arrayappendcTX; public import core.internal.array.comparison : __cmp; @@ -4715,7 +4716,7 @@ public import core.internal.array.construction : _d_newarraymTX; public import core.internal.array.arrayassign : _d_arrayassign_l; public import core.internal.array.arrayassign : _d_arrayassign_r; public import core.internal.array.arrayassign : _d_arraysetassign; -public import core.internal.array.capacity: _d_arraysetlengthTImpl; +public import core.internal.array.capacity : _d_arraysetlengthT; public import core.internal.dassert: _d_assert_fail; diff --git a/runtime/druntime/src/rt/lifetime.d b/runtime/druntime/src/rt/lifetime.d index 8d6f116f16..3558976bd0 100644 --- a/runtime/druntime/src/rt/lifetime.d +++ b/runtime/druntime/src/rt/lifetime.d @@ -628,259 +628,6 @@ extern (C) void rt_finalizeFromGC(void* p, size_t size, uint attr, TypeInfo type } -/** -Resize a dynamic array by setting the `.length` property - -Newly created elements are initialized to their default value. - -Has two variants: -- `_d_arraysetlengthT` for arrays with elements that initialize to 0 -- `_d_arraysetlengthiT` for non-zero initializers retrieved from `TypeInfo` - ---- -void main() -{ - int[] a = [1, 2]; - a.length = 3; // gets lowered to `_d_arraysetlengthT(typeid(int[]), 3, &a)` -} ---- - -Params: - ti = `TypeInfo` of array - newlength = new value for the array's `.length` - p = pointer to array to update the `.length` of. - While it's cast to `void[]`, its `.length` is still treated as element length. -Returns: `*p` after being updated -*/ -extern (C) void[] _d_arraysetlengthT(const TypeInfo ti, size_t newlength, void[]* p) @weak -in -{ - assert(ti); - assert(!(*p).length || (*p).ptr); -} -do -{ - debug(PRINTF) - { - //printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength); - if (p) - printf("\tp.ptr = %p, p.length = %zd\n", (*p).ptr, (*p).length); - } - - if (newlength <= (*p).length) - { - *p = (*p)[0 .. newlength]; - return *p; - } - auto tinext = unqualify(ti.next); - size_t sizeelem = tinext.tsize; - - /* Calculate: newsize = newlength * sizeelem - */ - bool overflow = false; - version (D_InlineAsm_X86) - { - size_t newsize = void; - - asm pure nothrow @nogc - { - mov EAX, newlength; - mul EAX, sizeelem; - mov newsize, EAX; - setc overflow; - } - } - else version (D_InlineAsm_X86_64) - { - size_t newsize = void; - - asm pure nothrow @nogc - { - mov RAX, newlength; - mul RAX, sizeelem; - mov newsize, RAX; - setc overflow; - } - } - else - { - const size_t newsize = mulu(sizeelem, newlength, overflow); - } - if (overflow) - { - onOutOfMemoryError(); - assert(0); - } - - debug(PRINTF) printf("newsize = %zx, newlength = %zx\n", newsize, newlength); - - if (!(*p).ptr) - { - assert((*p).length == 0); - // pointer was null, need to allocate - auto ptr = GC.malloc(newsize, __typeAttrs(tinext) | BlkAttr.APPENDABLE, tinext); - if (ptr is null) - { - onOutOfMemoryError(); - assert(0); - } - memset(ptr, 0, newsize); - *p = ptr[0 .. newlength]; - return *p; - } - - const size_t size = (*p).length * sizeelem; - const isshared = typeid(ti) is typeid(TypeInfo_Shared); - - /* Attempt to extend past the end of the existing array. - * If not possible, allocate new space for entire array and copy. - */ - void* newdata = (*p).ptr; - if (!gc_expandArrayUsed(newdata[0 .. size], newsize, isshared)) - { - newdata = GC.malloc(newsize, __typeAttrs(tinext, (*p).ptr) | BlkAttr.APPENDABLE, tinext); - if (newdata is null) - { - onOutOfMemoryError(); - assert(0); - } - - newdata[0 .. size] = (*p).ptr[0 .. size]; - - // Do postblit processing, as we are making a copy. - __doPostblit(newdata, size, tinext); - } - - // Zero the unused portion of the newly allocated space - memset(newdata + size, 0, newsize - size); - - *p = newdata[0 .. newlength]; - return *p; -} - -/// ditto -extern (C) void[] _d_arraysetlengthiT(const TypeInfo ti, size_t newlength, void[]* p) @weak -in -{ - assert(!(*p).length || (*p).ptr); -} -do -{ - debug(PRINTF) - { - //printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength); - if (p) - printf("\tp.ptr = %p, p.length = %zd\n", (*p).ptr, (*p).length); - } - - if (newlength <= (*p).length) - { - *p = (*p)[0 .. newlength]; - return *p; - } - auto tinext = unqualify(ti.next); - size_t sizeelem = tinext.tsize; - - /* Calculate: newsize = newlength * sizeelem - */ - bool overflow = false; - version (D_InlineAsm_X86) - { - size_t newsize = void; - - asm pure nothrow @nogc - { - mov EAX, newlength; - mul EAX, sizeelem; - mov newsize, EAX; - setc overflow; - } - } - else version (D_InlineAsm_X86_64) - { - size_t newsize = void; - - asm pure nothrow @nogc - { - mov RAX, newlength; - mul RAX, sizeelem; - mov newsize, RAX; - setc overflow; - } - } - else - { - const size_t newsize = mulu(sizeelem, newlength, overflow); - } - if (overflow) - { - onOutOfMemoryError(); - assert(0); - } - - debug(PRINTF) printf("newsize = %zx, newlength = %zx\n", newsize, newlength); - - static void doInitialize(void *start, void *end, const void[] initializer) - { - if (initializer.length == 1) - { - memset(start, *(cast(ubyte*)initializer.ptr), end - start); - } - else - { - auto q = initializer.ptr; - immutable initsize = initializer.length; - for (; start < end; start += initsize) - { - memcpy(start, q, initsize); - } - } - } - - if (!(*p).ptr) - { - assert((*p).length == 0); - // pointer was null, need to allocate - auto ptr = GC.malloc(newsize, __typeAttrs(tinext) | BlkAttr.APPENDABLE, tinext); - if (ptr is null) - { - onOutOfMemoryError(); - assert(0); - } - doInitialize(ptr, ptr + newsize, tinext.initializer); - *p = ptr[0 .. newlength]; - return *p; - } - - const size_t size = (*p).length * sizeelem; - const isshared = typeid(ti) is typeid(TypeInfo_Shared); - - /* Attempt to extend past the end of the existing array. - * If not possible, allocate new space for entire array and copy. - */ - void* newdata = (*p).ptr; - if (!gc_expandArrayUsed(newdata[0 .. size], newsize, isshared)) - { - newdata = GC.malloc(newsize, __typeAttrs(tinext, (*p).ptr) | BlkAttr.APPENDABLE, tinext); - if (newdata is null) - { - onOutOfMemoryError(); - assert(0); - } - - newdata[0 .. size] = (*p).ptr[0 .. size]; - - // Do postblit processing, as we are making a copy. - __doPostblit(newdata, size, tinext); - } - - // Initialize the unused portion of the newly allocated space - doInitialize(newdata + size, newdata + newsize, tinext.initializer); - *p = newdata[0 .. newlength]; - return *p; -} - - /** Given an array of length `size` that needs to be expanded to `newlength`, compute a new capacity. diff --git a/runtime/druntime/src/rt/tracegc.d b/runtime/druntime/src/rt/tracegc.d index 5b8fbe976f..1dd9d25f3f 100644 --- a/runtime/druntime/src/rt/tracegc.d +++ b/runtime/druntime/src/rt/tracegc.d @@ -26,8 +26,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/tests/dmd/runnable/extra-files/hello-profile-postscript.sh b/tests/dmd/runnable/extra-files/hello-profile-postscript.sh index d986ba5939..68391c04a2 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 ab04b4ec54..cb6678d528 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 From 85c43b1815e6022516003a06ab7d2f0299dae76c Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Fri, 2 May 2025 11:46:46 +0200 Subject: [PATCH 089/113] Fix hasNames rename after merging master into stable --- dmd/funcsem.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dmd/funcsem.d b/dmd/funcsem.d index 92df75d4d1..10f6f154b2 100644 --- a/dmd/funcsem.d +++ b/dmd/funcsem.d @@ -1935,7 +1935,7 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s, */ private void checkNamedArgErrorAndReport(TemplateDeclaration td, ArgumentList argumentList, Loc loc) { - if (!argumentList.hasNames()) + if (!argumentList.hasArgNames()) return; auto tf = td.onemember ? td.onemember.isFuncDeclaration() : null; @@ -1957,7 +1957,7 @@ private void checkNamedArgErrorAndReport(TemplateDeclaration td, ArgumentList ar */ private void checkNamedArgErrorAndReportOverload(Dsymbol od, ArgumentList argumentList, Loc loc) { - if (!argumentList.hasNames()) + if (!argumentList.hasArgNames()) return; FuncDeclaration tf = null; From 6870aaf6b46d15c3f3e44daa2285f06110b274d0 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Tue, 6 May 2025 21:20:25 +0200 Subject: [PATCH 090/113] Fix C++ header regression after dlang/dmd!21297 --- dmd/declaration.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmd/declaration.h b/dmd/declaration.h index 874d702123..74ea20cb56 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -35,7 +35,7 @@ namespace dmd bool functionSemantic(FuncDeclaration* fd); bool functionSemantic3(FuncDeclaration* fd); bool checkClosure(FuncDeclaration* fd); - MATCH leastAsSpecialized(FuncDeclaration *f, FuncDeclaration *g, Identifiers *names); + MATCH leastAsSpecialized(FuncDeclaration *f, FuncDeclaration *g, ArgumentLabels *names); PURE isPure(FuncDeclaration *f); FuncDeclaration *genCfunc(Parameters *args, Type *treturn, const char *name, StorageClass stc=0); FuncDeclaration *genCfunc(Parameters *args, Type *treturn, Identifier *id, StorageClass stc=0); From c31789bee5434990c5b20fd268122cd1db5e8aa0 Mon Sep 17 00:00:00 2001 From: Rainer Date: Fri, 16 May 2025 15:04:28 +0200 Subject: [PATCH 091/113] fix issue dlang/dmd!21382: CodeView: final class functions are marked as virtual even though they are not in the vtbl isVirtual not good enough to check whether a function is virtual --- tests/dmd/runnable/testpdb.d | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/dmd/runnable/testpdb.d b/tests/dmd/runnable/testpdb.d index 8a1b10dfb9..b1709a1f71 100644 --- a/tests/dmd/runnable/testpdb.d +++ b/tests/dmd/runnable/testpdb.d @@ -53,6 +53,8 @@ void main(string[] args) test18147(session, globals); + test21382(session, globals); + source.Release(); session.Release(); globals.Release(); @@ -485,6 +487,28 @@ void test18147(IDiaSession session, IDiaSymbol globals) } +// 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"); + + 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_; From 69332a5fde0f6b1161e8734947cda00388f2b2ff Mon Sep 17 00:00:00 2001 From: Rainer Date: Sat, 17 May 2025 09:16:44 +0200 Subject: [PATCH 092/113] fix issue dlang/dmd!21384: function arguments are shown in the wrong order in a debugger set SFLhidden for hidden parameter reconstruct order in calcLexicalScope --- tests/dmd/runnable/testpdb.d | 86 ++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/tests/dmd/runnable/testpdb.d b/tests/dmd/runnable/testpdb.d index b1709a1f71..76c051788e 100644 --- a/tests/dmd/runnable/testpdb.d +++ b/tests/dmd/runnable/testpdb.d @@ -51,6 +51,8 @@ void main(string[] args) test20253(session, globals); + test21384(session, globals); + test18147(session, globals); test21382(session, globals); @@ -402,6 +404,90 @@ 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:"); + + cnt = getFuncVars(globals, "testpdb.makeS21384", vars[]); + 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[]); + 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() From 22dce4c8d781deffb4699f62a4805b07170f951c Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Mon, 19 May 2025 21:01:48 +0200 Subject: [PATCH 093/113] [stable] Fix dlang/dmd!21359 - Merge more types in `substWildTo()` (dlang/dmd!21361) [stable] Fix dlang/dmd!21359 - Merge more types in `substWildTo()` Signed-off-by: Rainer Schuetze Merged-on-behalf-of: Martin Kinkelin --- dmd/typesem.d | 2 +- tests/dmd/compilable/extra-files/test21359a.d | 3 +++ tests/dmd/compilable/extra-files/test21359b.d | 11 +++++++++++ tests/dmd/compilable/test21359.sh | 15 +++++++++++++++ 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/compilable/extra-files/test21359a.d create mode 100644 tests/dmd/compilable/extra-files/test21359b.d create mode 100755 tests/dmd/compilable/test21359.sh diff --git a/dmd/typesem.d b/dmd/typesem.d index ffbdfed6eb..6f1008cea5 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -7346,7 +7346,7 @@ Type substWildTo(Type type, uint mod) t = t.addMod(MODFlags.shared_); //printf("-Type.substWildTo t = %s\n", t.toChars()); - return t; + return t.merge(); } if (!tf.iswild && !(tf.mod & MODFlags.wild)) diff --git a/tests/dmd/compilable/extra-files/test21359a.d b/tests/dmd/compilable/extra-files/test21359a.d new file mode 100644 index 0000000000..b52d9db5cd --- /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 0000000000..f9aca7fdb6 --- /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/test21359.sh b/tests/dmd/compilable/test21359.sh new file mode 100755 index 0000000000..ed4719c1fe --- /dev/null +++ b/tests/dmd/compilable/test21359.sh @@ -0,0 +1,15 @@ +#!/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. +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} From 4615d727c9058121d8d76c550e7bdeb9bb9bdb9c Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Tue, 6 May 2025 19:03:02 +0200 Subject: [PATCH 094/113] Don't merge function types with unknown return type As that can cause a 'compatible' function type with resolved return type to wrongly get that deco. This is what happens with LDC for a particular test case as D v2.111 regression, causing an assertion in the frontend while generating a TypeInfo_Function for some TypeFunction, with `TypeFunction.next` being null (unknown return type). The relevant `genTypeInfo()` calls before the patch, in the format `genTypeInfo: (), ()`: ``` // const funcptr: TypeInfo_Const genTypeInfo: const(Algebraic!() function(Function) nothrow @system) (xPFNbC4util8FunctionZSQq__T9AlgebraicZQl), const(Algebraic!() function(Function) nothrow @system) (xPFNbC4util8FunctionZSQq__T9AlgebraicZQl) // mutable funcptr: TypeInfo_Pointer genTypeInfo: Algebraic!() function(Function) nothrow @system (PFNbC4util8FunctionZSQq__T9AlgebraicZQl), Algebraic!() function(Function) nothrow @system (PFNbC4util8FunctionZSQq__T9AlgebraicZQl) // function: TypeInfo_Function // NOTE the missing Algebraic return type in the decos, this is the bug genTypeInfo: nothrow @system Algebraic!()(Function) (FNbC4util8FunctionZ), nothrow @system (Function) (FNbC4util8FunctionZ) ``` With this patch: ``` genTypeInfo: const(Algebraic!() function(Function) nothrow @system) (xPFNbC4util8FunctionZSQq__T9AlgebraicZQl), const(Algebraic!() function(Function) nothrow @system) (xPFNbC4util8FunctionZSQq__T9AlgebraicZQl) genTypeInfo: Algebraic!() function(Function) nothrow @system (PFNbC4util8FunctionZSQq__T9AlgebraicZQl), Algebraic!() function(Function) nothrow @system (PFNbC4util8FunctionZSQq__T9AlgebraicZQl) genTypeInfo: nothrow @system Algebraic!()(Function) (FNbC4util8FunctionZSQq__T9AlgebraicZQl), nothrow @system Algebraic!()(Function) (FNbC4util8FunctionZSQq__T9AlgebraicZQl) ``` --- dmd/typesem.d | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dmd/typesem.d b/dmd/typesem.d index 6f1008cea5..ada16b8f79 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -3315,6 +3315,11 @@ Type merge(Type type) return type; goto default; + case Tfunction: + if (!type.nextOf()) // don't merge if return type is unknown + return type; + goto default; + default: if (type.nextOf() && !type.nextOf().deco) return type; From 6622d5c6d08c0972d0841b0abe6e280e64dc3b13 Mon Sep 17 00:00:00 2001 From: Steven Schveighoffer Date: Thu, 22 May 2025 06:25:45 -0400 Subject: [PATCH 095/113] Fix issue dlang/dmd!21397 - Refcounting with Throwable is unsound (dlang/dmd!21398) Fix issue dlang/dmd!21397 - Refcounting with Throwable is unsound Signed-off-by: Martin Kinkelin Merged-on-behalf-of: Martin Kinkelin --- dmd/dinterpret.d | 5 ++- runtime/druntime/src/object.d | 76 ++++++++++++++++++++++++----------- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/dmd/dinterpret.d b/dmd/dinterpret.d index 543c0e22e3..bdaaace6be 100644 --- a/dmd/dinterpret.d +++ b/dmd/dinterpret.d @@ -6703,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/runtime/druntime/src/object.d b/runtime/druntime/src/object.d index e9838db4f3..549f5e87f5 100644 --- a/runtime/druntime/src/object.d +++ b/runtime/druntime/src/object.d @@ -2535,8 +2535,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() @@ -2549,24 +2568,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 } /** @@ -2585,7 +2616,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) @@ -2608,14 +2639,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; } } @@ -2625,9 +2654,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(); } @@ -2641,8 +2668,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) { @@ -2771,7 +2799,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"); } @@ -2779,7 +2807,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"); } @@ -2787,7 +2815,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"); } @@ -2854,7 +2882,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); } @@ -2863,7 +2891,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); } @@ -2872,7 +2900,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); } From c93553597a4ce81bae4ebe1044e47b3c9e90ac1c Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Mon, 26 May 2025 02:00:01 +0200 Subject: [PATCH 096/113] fix dlang/dmd!21406: generating header with debug condition crashes compiler (dlang/dmd!21407) check for missing ident --- dmd/hdrgen.d | 10 +++++++--- tests/dmd/compilable/extra-files/header1.d | 2 ++ tests/dmd/compilable/extra-files/header1.di | 4 ++++ tests/dmd/compilable/extra-files/header1i.di | 4 ++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index 0f8c8c67b9..10f138be8b 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -3258,9 +3258,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/tests/dmd/compilable/extra-files/header1.d b/tests/dmd/compilable/extra-files/header1.d index ee698f16dc..abee4c53ee 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 3e25efb488..22480f4c7a 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 ee37e60ef3..2b5b09a41c 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 From 15b603e440ee09500a98ff4bd5f6cb9f3d5f787f Mon Sep 17 00:00:00 2001 From: Timon Gehr Date: Tue, 27 May 2025 20:37:49 +0200 Subject: [PATCH 097/113] fix dlang/dmd!21414: `__rvalue` must be `@system` --- dmd/expressionsem.d | 15 ++++++++++ tests/dmd/fail_compilation/fail21414.d | 41 ++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 tests/dmd/fail_compilation/fail21414.d diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 2576d7c0d0..0be35f5828 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -3921,6 +3921,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; @@ -5922,6 +5929,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor error(exp.f.loc, "`__rvalue` only valid on functions that return by `ref`"); setError(); } + if (result.rvalue) + { + if (sc.setUnsafe(false, exp.loc, "calling `__rvalue`-annotated function `%s`", exp.f)) + { + setError(); + } + } + } } diff --git a/tests/dmd/fail_compilation/fail21414.d b/tests/dmd/fail_compilation/fail21414.d new file mode 100644 index 0000000000..b407f17a37 --- /dev/null +++ b/tests/dmd/fail_compilation/fail21414.d @@ -0,0 +1,41 @@ +// https://github.com/dlang/dmd/issues/21414 + +/* REQUIRED_ARGS: -o- +TEST_OUTPUT: +--- +fail_compilation/fail21414.d(38): Error: moving variable `__rvalue(s)` with `__rvalue` is not allowed in a `@safe` function +fail_compilation/fail21414.d(38): Error: moving variable `__rvalue(s)` with `__rvalue` is not allowed in a `@safe` function +fail_compilation/fail21414.d(40): Error: calling `__rvalue`-annotated function `unsafeMove` is not allowed in a `@safe` function +fail_compilation/fail21414.d(40): Error: calling `__rvalue`-annotated function `unsafeMove` 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; + +void main() +{ + auto s = S(2); + foo(__rvalue(s), __rvalue(s)); + auto t = S(2); + foo(unsafeMove(t), unsafeMove(t)); +} From 3a738558296af6646fff098d880b46d72bdd83ed Mon Sep 17 00:00:00 2001 From: Timon Gehr Date: Tue, 27 May 2025 21:16:08 +0200 Subject: [PATCH 098/113] fix dlang/dmd!21416: `rvalue` ignored on call to `ref` function --- dmd/expressionsem.d | 23 ++++++++++++++++------- tests/dmd/compilable/test21416.d | 17 +++++++++++++++++ tests/dmd/fail_compilation/fail21414.d | 14 ++++++++++---- 3 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 tests/dmd/compilable/test21416.d diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 0be35f5828..9d86e41818 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -5923,20 +5923,29 @@ 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) { - error(exp.f.loc, "`__rvalue` only valid on functions that return by `ref`"); - setError(); + 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; + } } - if (result.rvalue) + else if (exp.rvalue && tf.isRef) { - if (sc.setUnsafe(false, exp.loc, "calling `__rvalue`-annotated function `%s`", exp.f)) + if (sc.setUnsafe(false, exp.loc, "moving result of `ref` function `%s` with `__rvalue`", exp.f)) { setError(); } } - } } diff --git a/tests/dmd/compilable/test21416.d b/tests/dmd/compilable/test21416.d new file mode 100644 index 0000000000..e24f729294 --- /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/fail_compilation/fail21414.d b/tests/dmd/fail_compilation/fail21414.d index b407f17a37..d07b2e2cbd 100644 --- a/tests/dmd/fail_compilation/fail21414.d +++ b/tests/dmd/fail_compilation/fail21414.d @@ -3,10 +3,12 @@ /* REQUIRED_ARGS: -o- TEST_OUTPUT: --- -fail_compilation/fail21414.d(38): Error: moving variable `__rvalue(s)` with `__rvalue` is not allowed in a `@safe` function -fail_compilation/fail21414.d(38): Error: moving variable `__rvalue(s)` with `__rvalue` is not allowed in a `@safe` function -fail_compilation/fail21414.d(40): Error: calling `__rvalue`-annotated function `unsafeMove` is not allowed in a `@safe` function -fail_compilation/fail21414.d(40): Error: calling `__rvalue`-annotated function `unsafeMove` 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(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 --- */ @@ -32,10 +34,14 @@ void foo(S s, immutable(S) t) 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))); } From 21bdb8c4339b40d84de24fc611ee3856e68291c4 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Wed, 4 Jun 2025 15:10:28 +0200 Subject: [PATCH 099/113] [stable] Try to fix dlang/dmd!21331 (dlang/dmd!21343) --- dmd/expressionsem.d | 2 +- dmd/identifier.d | 10 +++++----- tests/dmd/compilable/extra-files/test21331.d | 17 +++++++++++++++++ tests/dmd/compilable/test21331.sh | 11 +++++++++++ 4 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 tests/dmd/compilable/extra-files/test21331.d create mode 100755 tests/dmd/compilable/test21331.sh diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 9d86e41818..f18f61bde2 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -5709,7 +5709,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor symtab = sds.symtab; } assert(symtab); - Identifier id = Identifier.generateIdWithLoc(s, exp.loc, cast(string) toDString(sc.parent.toPrettyChars())); + Identifier id = Identifier.generateIdWithLoc(s, exp.loc, cast(const void*) sc.parent); exp.fd.ident = id; if (exp.td) exp.td.ident = id; diff --git a/dmd/identifier.d b/dmd/identifier.d index c213597eb0..92d3a8c795 100644 --- a/dmd/identifier.d +++ b/dmd/identifier.d @@ -221,7 +221,7 @@ nothrow: * Identifier (inside Identifier.idPool) with deterministic name based * on the source location. */ - extern (D) static Identifier generateIdWithLoc(string prefix, Loc loc, string parent = "") + extern (D) static Identifier generateIdWithLoc(string prefix, Loc loc, const void* parent = null) { // generate `_L_C` auto sl = SourceLoc(loc); @@ -248,14 +248,15 @@ nothrow: * directly, but that would unnecessary lengthen symbols names. See issue: * https://issues.dlang.org/show_bug.cgi?id=23722 */ - static struct Key { string locKey; string prefix; string parent; } + static struct Key { string locKey; string prefix; const(void)* parent; } __gshared uint[Key] counters; - string locKey = cast(string) (sl.filename ~ idBuf[]); + const locKey = cast(string) (sl.filename ~ idBuf[]); + const key = Key(locKey, prefix, parent); static if (__traits(compiles, counters.update(Key.init, () => 0u, (ref uint a) => 0u))) { // 2.082+ - counters.update(Key(locKey, prefix, parent), + counters.update(key, () => 1u, // insertion (ref uint counter) // update { @@ -267,7 +268,6 @@ nothrow: } else { - const key = Key(locKey, prefix, parent); if (auto pCounter = key in counters) { idBuf.writestring("_"); diff --git a/tests/dmd/compilable/extra-files/test21331.d b/tests/dmd/compilable/extra-files/test21331.d new file mode 100644 index 0000000000..59f30d1f1c --- /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/test21331.sh b/tests/dmd/compilable/test21331.sh new file mode 100755 index 0000000000..855e563134 --- /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} From 1b81435b709a1ed645750534108a5d2de2a12a47 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 7 Jun 2025 16:19:26 +0200 Subject: [PATCH 100/113] Bump LDC version, frontend version, Phobos --- CMakeLists.txt | 4 ++-- runtime/phobos | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 21aad6d367..1f34e1dea7 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/runtime/phobos b/runtime/phobos index 983294523d..380b88d217 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit 983294523d02c9b48130902c805bce7af085de70 +Subproject commit 380b88d21727073d11da479f55a15038948b0d52 From 9b2a80d9641ec328f6ec1d766a4e3f187a634a5a Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 7 Jun 2025 16:29:44 +0200 Subject: [PATCH 101/113] [little merge-fixes wrt. now free-standing functions] --- ir/irclass.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ir/irclass.cpp b/ir/irclass.cpp index b98b002251..7e51208c66 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; } } From d0996c98638474f4632c394cc4ef1ed80d2d8eb2 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 7 Jun 2025 17:10:42 +0200 Subject: [PATCH 102/113] Minimally adapt 2 new compiler tests for LDC --- tests/dmd/compilable/test21359.sh | 4 ++++ tests/dmd/fail_compilation/fail19103.d | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/dmd/compilable/test21359.sh b/tests/dmd/compilable/test21359.sh index ed4719c1fe..fd309dfa53 100755 --- a/tests/dmd/compilable/test21359.sh +++ b/tests/dmd/compilable/test21359.sh @@ -5,6 +5,10 @@ $DMD -c -m${MODEL} -allinst -of${objfile} ${EXTRA_FILES}/${TEST_NAME}a.d -I${EXT # 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 diff --git a/tests/dmd/fail_compilation/fail19103.d b/tests/dmd/fail_compilation/fail19103.d index e617249ed7..7780fe691e 100644 --- a/tests/dmd/fail_compilation/fail19103.d +++ b/tests/dmd/fail_compilation/fail19103.d @@ -6,7 +6,7 @@ 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` -$p:druntime/import/core/stdc/stdio.d$($n$): did you mean `core.stdc.stdio.puts`? +$p:/core/stdc/stdio.d$($n$): did you mean `core.stdc.stdio.puts`? --- */ void main() From 06f566d39e5284af715822f76a0ad828fa2b0035 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 7 Jun 2025 17:11:25 +0200 Subject: [PATCH 103/113] [eagerly fix little upstream druntime regressions] --- runtime/druntime/src/core/internal/array/capacity.d | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/runtime/druntime/src/core/internal/array/capacity.d b/runtime/druntime/src/core/internal/array/capacity.d index 8c42c092af..1de07eadc1 100644 --- a/runtime/druntime/src/core/internal/array/capacity.d +++ b/runtime/druntime/src/core/internal/array/capacity.d @@ -85,6 +85,8 @@ do } else { + import core.checkedint : mulu; + bool overflow = false; size_t reqsize = mulu(size, newcapacity, overflow); if (!overflow) @@ -222,7 +224,7 @@ private size_t _d_arraysetlengthT_(Tarr : T[], T)(return ref scope Tarr arr, siz enum hasPostblit = __traits(hasMember, T, "__postblit"); enum hasEnabledPostblit = hasPostblit && !__traits(isDisabled, T.__postblit); - ubyte overflow = 0; + bool overflow = false; size_t newsize = void; From 9d1145025e20c23b61e373f2ed085182c7bbcbed Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 7 Jun 2025 23:59:46 +0200 Subject: [PATCH 104/113] core.internal.array.capacity: Fix compile-error regressions on non-x86 archs (dlang/dmd!21432) --- runtime/druntime/src/core/internal/array/capacity.d | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/runtime/druntime/src/core/internal/array/capacity.d b/runtime/druntime/src/core/internal/array/capacity.d index 8c42c092af..1de07eadc1 100644 --- a/runtime/druntime/src/core/internal/array/capacity.d +++ b/runtime/druntime/src/core/internal/array/capacity.d @@ -85,6 +85,8 @@ do } else { + import core.checkedint : mulu; + bool overflow = false; size_t reqsize = mulu(size, newcapacity, overflow); if (!overflow) @@ -222,7 +224,7 @@ private size_t _d_arraysetlengthT_(Tarr : T[], T)(return ref scope Tarr arr, siz enum hasPostblit = __traits(hasMember, T, "__postblit"); enum hasEnabledPostblit = hasPostblit && !__traits(isDisabled, T.__postblit); - ubyte overflow = 0; + bool overflow = false; size_t newsize = void; From 65cf2b6a7a720624f87cb57d2a58792268037f23 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 8 Jun 2025 00:00:22 +0200 Subject: [PATCH 105/113] windows druntime/shared test: avoid spurious failures by building to folder 64, not to 64.obj (dlang/dmd!21401) (dlang/dmd!21433) this avoids concurrently creating the same file multiple times Co-authored-by: Rainer Schuetze --- runtime/druntime/test/shared/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime/test/shared/Makefile b/runtime/druntime/test/shared/Makefile index 674ecc4472..4c359b09a0 100644 --- a/runtime/druntime/test/shared/Makefile +++ b/runtime/druntime/test/shared/Makefile @@ -92,7 +92,7 @@ ifeq (windows,$(OS)) CC := cl OUTPUT_FLAG := /Fe # we additionally specify the .obj output path (/Fo) to prevent collisions - extra_cflags += /Fo$(OBJDIR) + extra_cflags += /Fo$(OBJDIR)/ endif # $(LINKDL) == -L-ldl => $(ldl) == -ldl From b4d04ce4cf5f72adb70663a73235740ff903d024 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 8 Jun 2025 13:29:36 +0200 Subject: [PATCH 106/113] core.checkedint: Optimize mulu() via x86 inline assembly --- runtime/druntime/src/core/checkedint.d | 51 ++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/runtime/druntime/src/core/checkedint.d b/runtime/druntime/src/core/checkedint.d index 9970968f37..e9b2f8086f 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 && From d1abd66147115724bd6386f21af3e2e4d1b7917d Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 8 Jun 2025 13:47:36 +0200 Subject: [PATCH 107/113] druntime: Avoid duplicate inline-asm optimizations in array helpers, use optimized core.checkedint.mulu() instead --- .../src/core/internal/array/capacity.d | 74 +++---------------- .../src/core/internal/array/construction.d | 42 ++--------- runtime/druntime/src/rt/lifetime.d | 38 ++-------- 3 files changed, 25 insertions(+), 129 deletions(-) diff --git a/runtime/druntime/src/core/internal/array/capacity.d b/runtime/druntime/src/core/internal/array/capacity.d index 1de07eadc1..7824ffd67d 100644 --- a/runtime/druntime/src/core/internal/array/capacity.d +++ b/runtime/druntime/src/core/internal/array/capacity.d @@ -49,6 +49,7 @@ in } do { + import core.checkedint : mulu; import core.exception : onOutOfMemoryError; import core.stdc.string : memcpy, memset; import core.internal.array.utils: __typeAttrs; @@ -59,43 +60,14 @@ do alias BlkAttr = GC.BlkAttr; auto size = T.sizeof; - version (D_InlineAsm_X86) - { - size_t reqsize = void; - asm nothrow pure - { - mov EAX, newcapacity; - mul EAX, size; - mov reqsize, EAX; - jnc Lcontinue; - } - } - else version (D_InlineAsm_X86_64) - { - size_t reqsize = void; - - asm nothrow pure - { - mov RAX, newcapacity; - mul RAX, size; - mov reqsize, RAX; - jnc Lcontinue; - } - } - else + bool overflow = false; + const reqsize = mulu(size, newcapacity, overflow); + if (overflow) { - import core.checkedint : mulu; - - bool overflow = false; - size_t reqsize = mulu(size, newcapacity, overflow); - if (!overflow) - goto Lcontinue; + onOutOfMemoryError(); + assert(0); } -Loverflow: - onOutOfMemoryError(); - assert(0); -Lcontinue: // step 1, see if we can ensure the capacity is valid in-place auto datasize = (*p).length * size; @@ -115,7 +87,10 @@ Lcontinue: static enum ti = typeid(T); auto ptr = GC.malloc(reqsize, attrs, ti); if (ptr is null) - goto Loverflow; + { + onOutOfMemoryError(); + assert(0); + } // copy the data over. // note that malloc will have initialized the data we did not request to 0. @@ -225,34 +200,7 @@ private size_t _d_arraysetlengthT_(Tarr : T[], T)(return ref scope Tarr arr, siz enum hasEnabledPostblit = hasPostblit && !__traits(isDisabled, T.__postblit); bool overflow = false; - - size_t newsize = void; - - version (D_InlineAsm_X86) - { - asm pure nothrow @nogc - { - mov EAX, sizeelem; - mul newlength; // EDX:EAX = EAX * newlength - mov newsize, EAX; - setc overflow; - } - } - else version (D_InlineAsm_X86_64) - { - asm pure nothrow @nogc - { - mov RAX, sizeelem; - mul newlength; // RDX:RAX = RAX * newlength - mov newsize, RAX; - setc overflow; - } - } - else - { - newsize = mulu(sizeelem, newlength, overflow); - } - + const newsize = mulu(sizeelem, newlength, overflow); if (overflow) { onOutOfMemoryError(); diff --git a/runtime/druntime/src/core/internal/array/construction.d b/runtime/druntime/src/core/internal/array/construction.d index 53dac44a54..acecc4f141 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 diff --git a/runtime/druntime/src/rt/lifetime.d b/runtime/druntime/src/rt/lifetime.d index 12950a72bc..7c95bf6299 100644 --- a/runtime/druntime/src/rt/lifetime.d +++ b/runtime/druntime/src/rt/lifetime.d @@ -375,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) + 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 EAX,size ; - mul EAX,length ; - mov size,EAX ; - jnc Lcontinue ; + debug(PRINTF) printf(" p = %p\n", ptr); + return ptr[0 .. length]; } } - else version (D_InlineAsm_X86_64) - { - asm pure nothrow @nogc - { - mov RAX,size ; - mul RAX,length ; - mov size,RAX ; - jnc Lcontinue ; - } - } - 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 From 88dad8423d36c24b07f34b2c6d3a8dfd4825065b Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 14 Jun 2025 18:42:35 +0200 Subject: [PATCH 108/113] Remove now-defunct LDC-specific set-array-length optimization The new templated function's signature isn't suited to adapt this existing optimization - the old length is in the by-ref passed slice, not a separate parameter anymore, so we can't trivially check for a constant. I guess its effect is negligible, plus the new template provides regular inlining opportunities, so just remove it. --- gen/passes/SimplifyDRuntimeCalls.cpp | 51 ---------------------------- gen/passes/SimplifyDRuntimeCalls.h | 6 ---- gen/runtime.cpp | 2 -- 3 files changed, 59 deletions(-) diff --git a/gen/passes/SimplifyDRuntimeCalls.cpp b/gen/passes/SimplifyDRuntimeCalls.cpp index 82af7c6dd1..bd1b356326 100644 --- a/gen/passes/SimplifyDRuntimeCalls.cpp +++ b/gen/passes/SimplifyDRuntimeCalls.cpp @@ -63,55 +63,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) { @@ -265,8 +216,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 4311e6689c..3344170fca 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 036b8af582..a7758db5ed 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", From fd4b0caa6efe632318eac35ada7a1b75c18f042d Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Mon, 16 Jun 2025 13:11:33 +0200 Subject: [PATCH 109/113] Adapt runnable/testpdb.d extensions for LDC --- tests/dmd/runnable/testpdb.d | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tests/dmd/runnable/testpdb.d b/tests/dmd/runnable/testpdb.d index 210dd0de5a..745031ea7c 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) { @@ -536,14 +539,18 @@ void test21384(IDiaSession session, IDiaSymbol globals) testVar(vars[2], "c", DataKind.DataIsParam, "testpdb.sum21384: arg3:"); testVar(vars[3], "s", DataKind.DataIsLocal, "testpdb.sum21384: local:"); - cnt = getFuncVars(globals, "testpdb.makeS21384", vars[]); + // 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[]); + 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:"); @@ -655,6 +662,12 @@ 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"); @@ -663,6 +676,7 @@ void test21382(IDiaSession session, IDiaSymbol globals) 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"); + } } /////////////////////////////////////////////// From 31dac3a8babdb5b3216e326ffb19ee8d81610292 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Mon, 16 Jun 2025 14:24:43 +0200 Subject: [PATCH 110/113] Adapt new runnable/test21241.d for LDC --- tests/dmd/fail_compilation/test21241.d | 23 +++++++++++++++++++++++ tests/dmd/runnable/test21241.d | 13 ------------- 2 files changed, 23 insertions(+), 13 deletions(-) create mode 100644 tests/dmd/fail_compilation/test21241.d delete mode 100644 tests/dmd/runnable/test21241.d diff --git a/tests/dmd/fail_compilation/test21241.d b/tests/dmd/fail_compilation/test21241.d new file mode 100644 index 0000000000..cb0d80e74c --- /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/runnable/test21241.d b/tests/dmd/runnable/test21241.d deleted file mode 100644 index c63011bcfa..0000000000 --- a/tests/dmd/runnable/test21241.d +++ /dev/null @@ -1,13 +0,0 @@ -/* -REQUIRED_ARGS: runnable/imports/imp21241a.c runnable/imports/imp21241b.c -*/ -// https://github.com/dlang/dmd/issues/21241 -import imp21241a; -import imp21241b; - -void main(){ - int x = getA(); - assert(x==aValue); - x = getB(); - assert(x==bValue); -} From f2ad34d5ddd38ffe9bb78424dd2cd663c9fc6a6a Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Mon, 16 Jun 2025 15:06:23 +0200 Subject: [PATCH 111/113] FreeBSD: Fix C assert runtime function signature Fixes dmd-testsuite's runnable/structinit.c, which imports assert.h, causing LDC to validate the signature. --- gen/llvmhelpers.cpp | 2 +- gen/runtime.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index f7558238d3..7d24c08c33 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/runtime.cpp b/gen/runtime.cpp index a7758db5ed..98fc51d459 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -341,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, @@ -376,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) { From 523e9d9e0aae6a7aea3f8c7e60fd6c3adeaa0cd1 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Fri, 27 Jun 2025 06:00:02 +0200 Subject: [PATCH 112/113] fix dlang/dmd!21476: Presence of move constructor causes overload error (dlang/dmd!21477) Move constructors were incorrectly being considered as regular constructors, which resulted in the test case failing with: ``` compilable/test21476.d(12): Error: none of the overloads of `this` are callable using argument types `(string)` auto o = S21476("aoe"); ^ compilable/test21476.d(6): Candidates are: `test21476.S21476.this(ref return scope S21476)` this(ref return scope S21476); ^ compilable/test21476.d(7): `test21476.S21476.this(return scope S21476)` this(return scope S21476); ^ ``` With this change, a struct literal is now used to construct the object. --- dmd/dstruct.d | 2 +- dmd/func.d | 3 ++- tests/dmd/compilable/test21476.d | 13 +++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 tests/dmd/compilable/test21476.d diff --git a/dmd/dstruct.d b/dmd/dstruct.d index 5aef3585ca..c6838f25a7 100644 --- a/dmd/dstruct.d +++ b/dmd/dstruct.d @@ -307,7 +307,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration } if (auto ctorDecl = s.isCtorDeclaration()) { - if (!ctorDecl.isCpCtor && (!ignoreDisabled || !(ctorDecl.storage_class & STC.disable))) + if (!ctorDecl.isCpCtor && !ctorDecl.isMoveCtor && (!ignoreDisabled || !(ctorDecl.storage_class & STC.disable))) { result = true; return 1; diff --git a/dmd/func.d b/dmd/func.d index 6a573810a4..ae563b8a08 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -1373,7 +1373,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/tests/dmd/compilable/test21476.d b/tests/dmd/compilable/test21476.d new file mode 100644 index 0000000000..a2e307eebd --- /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"); +} From 4ffe9d5ffb84da850006c027af0e15c663a772e4 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Mon, 28 Jul 2025 11:40:04 +0200 Subject: [PATCH 113/113] [add changelog entry] --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e75e67c922..35a331a152 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