From 6a2fe78ba45b4fcd495f7ab340f784640b9daf01 Mon Sep 17 00:00:00 2001 From: Tim Schendekehl Date: Sun, 18 Feb 2024 23:35:00 +0100 Subject: [PATCH 01/18] Fix Bugzilla 20802 - Link failure with writefln (#16200) The issue is caused by compiling druntime/phobos and the application with different flags. The template instance for __switch_errorT is not included in the build of druntime/phobos, because they are compiled with -release. DMD will also not include it in an application compiled without -release, because it assumes, that it is already in druntime. See comment https://issues.dlang.org/show_bug.cgi?id=20802#c3 by Spoov. The template instance for __switch_errorT is now always instantiated in druntime, so it is part of the ABI of druntime. --- .../test/runnable/extra-files/link20802a.d | 8 +++++ .../test/runnable/extra-files/link20802b.d | 30 +++++++++++++++++++ compiler/test/runnable/link20802.sh | 14 +++++++++ druntime/src/core/exception.d | 13 ++++++++ 4 files changed, 65 insertions(+) create mode 100644 compiler/test/runnable/extra-files/link20802a.d create mode 100644 compiler/test/runnable/extra-files/link20802b.d create mode 100755 compiler/test/runnable/link20802.sh diff --git a/compiler/test/runnable/extra-files/link20802a.d b/compiler/test/runnable/extra-files/link20802a.d new file mode 100644 index 0000000000..3c52258ca4 --- /dev/null +++ b/compiler/test/runnable/extra-files/link20802a.d @@ -0,0 +1,8 @@ +import link20802b; +void main() +{ + // First test from https://issues.dlang.org/show_bug.cgi?id=20802#c3 + CodepointSet('a', 'z'); + dstring s; + decodeGrapheme(s); +} diff --git a/compiler/test/runnable/extra-files/link20802b.d b/compiler/test/runnable/extra-files/link20802b.d new file mode 100644 index 0000000000..333e8a29fc --- /dev/null +++ b/compiler/test/runnable/extra-files/link20802b.d @@ -0,0 +1,30 @@ +module link20802b; + +// First test from https://issues.dlang.org/show_bug.cgi?id=20802#c3 + +enum TransformRes { goOn } + +void writeAligned()() +{ + final switch (TransformRes.goOn) { case TransformRes.goOn: break; } +} + +struct GcPolicy {} +alias CodepointSet = InversionList!GcPolicy; +struct InversionList(SP=GcPolicy) +{ + this()(uint[] intervals...) + { + sanitize(); + } + + void sanitize() + { + writeAligned(); + } +} + +void decodeGrapheme(Input)(ref Input inp) +{ + final switch (TransformRes.goOn) { case TransformRes.goOn: break; } +} diff --git a/compiler/test/runnable/link20802.sh b/compiler/test/runnable/link20802.sh new file mode 100755 index 0000000000..f0a6674fbf --- /dev/null +++ b/compiler/test/runnable/link20802.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + + +dir=${RESULTS_DIR}${SEP}runnable + +libname=${OUTPUT_BASE}${LIBEXT} +exename=${OUTPUT_BASE}${EXE} + +$DMD -m${MODEL} -I${EXTRA_FILES} -lib -release -of${libname} ${EXTRA_FILES}${SEP}link20802b.d +$DMD -m${MODEL} -I${EXTRA_FILES} -of${exename} ${EXTRA_FILES}${SEP}link20802a.d ${libname} + +${exename} + +rm_retry ${OUTPUT_BASE}{${LIBEXT},${EXE},${OBJ}} diff --git a/druntime/src/core/exception.d b/druntime/src/core/exception.d index d2016b115f..6741ccefff 100644 --- a/druntime/src/core/exception.d +++ b/druntime/src/core/exception.d @@ -19,6 +19,19 @@ void __switch_errorT()(string file = __FILE__, size_t line = __LINE__) @trusted assert(0, "No appropriate switch clause found"); } +/* + * Make sure template __switch_errorT is always instantiated when building + * druntime. This works around https://issues.dlang.org/show_bug.cgi?id=20802. + * When druntime and phobos are compiled with -release, the instance for + * __switch_errorT is not needed. An application compiled with -release + * could need the instance for __switch_errorT, but the compiler would + * not generate code for it, because it assumes, that it was already + * generated for druntime. Always including the instance in a compiled + * druntime allows to use an application without -release with druntime + * with -release. + */ +private alias dummy__switch_errorT = __switch_errorT!(); + /** * Thrown on a range error. */ From 20385aba10703c11f984863d30fc0bb95e6653a9 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Mon, 19 Feb 2024 00:19:53 +0100 Subject: [PATCH 02/18] gha: Update cross-platform-actions to v0.23.0 --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3ebef1dab1..4846a5e215 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -171,18 +171,18 @@ jobs: freebsd_version: '13.2' host_dmd: dmd-2.095.0 name: ${{ matrix.job_name }} - runs-on: macos-latest + runs-on: ubuntu-latest timeout-minutes: 60 steps: - uses: actions/checkout@v4 with: fetch-depth: 50 - name: Run in VM - uses: cross-platform-actions/action@v0.22.0 + uses: cross-platform-actions/action@v0.23.0 with: operating_system: freebsd hypervisor: qemu - memory: 8G + memory: 12G sync_files: runner-to-vm version: ${{ matrix.freebsd_version }} shell: bash From de25658ec9b0b71bd09149df8f3a8208761e8097 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Mon, 19 Feb 2024 11:13:37 +0100 Subject: [PATCH 03/18] Fix unknown module location in processSource diagnostics --- compiler/src/dmd/dmodule.d | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/src/dmd/dmodule.d b/compiler/src/dmd/dmodule.d index 022231c125..e551ee6e5f 100644 --- a/compiler/src/dmd/dmodule.d +++ b/compiler/src/dmd/dmodule.d @@ -1388,6 +1388,7 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod) { enum SourceEncoding { utf16, utf32} enum Endian { little, big} + immutable loc = mod.getLoc(); /* * Convert a buffer from UTF32 to UTF8 @@ -1407,7 +1408,7 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod) if (buf.length & 3) { - .error(mod.loc, "%s `%s` odd length of UTF-32 char source %llu", + .error(loc, "%s `%s` odd length of UTF-32 char source %llu", mod.kind, mod.toPrettyChars, cast(ulong) buf.length); return null; } @@ -1424,7 +1425,7 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod) { if (u > 0x10FFFF) { - .error(mod.loc, "%s `%s` UTF-32 value %08x greater than 0x10FFFF", mod.kind, mod.toPrettyChars, u); + .error(loc, "%s `%s` UTF-32 value %08x greater than 0x10FFFF", mod.kind, mod.toPrettyChars, u); return null; } dbuf.writeUTF8(u); @@ -1454,7 +1455,7 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod) if (buf.length & 1) { - .error(mod.loc, "%s `%s` odd length of UTF-16 char source %llu", mod.kind, mod.toPrettyChars, cast(ulong) buf.length); + .error(loc, "%s `%s` odd length of UTF-16 char source %llu", mod.kind, mod.toPrettyChars, cast(ulong) buf.length); return null; } @@ -1474,13 +1475,13 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod) i++; if (i >= eBuf.length) { - .error(mod.loc, "%s `%s` surrogate UTF-16 high value %04x at end of file", mod.kind, mod.toPrettyChars, u); + .error(loc, "%s `%s` surrogate UTF-16 high value %04x at end of file", mod.kind, mod.toPrettyChars, u); return null; } const u2 = readNext(&eBuf[i]); if (u2 < 0xDC00 || 0xE000 <= u2) { - .error(mod.loc, "%s `%s` surrogate UTF-16 low value %04x out of range", mod.kind, mod.toPrettyChars, u2); + .error(loc, "%s `%s` surrogate UTF-16 low value %04x out of range", mod.kind, mod.toPrettyChars, u2); return null; } u = (u - 0xD7C0) << 10; @@ -1488,12 +1489,12 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod) } else if (u >= 0xDC00 && u <= 0xDFFF) { - .error(mod.loc, "%s `%s` unpaired surrogate UTF-16 value %04x", mod.kind, mod.toPrettyChars, u); + .error(loc, "%s `%s` unpaired surrogate UTF-16 value %04x", mod.kind, mod.toPrettyChars, u); return null; } else if (u == 0xFFFE || u == 0xFFFF) { - .error(mod.loc, "%s `%s` illegal UTF-16 value %04x", mod.kind, mod.toPrettyChars, u); + .error(loc, "%s `%s` illegal UTF-16 value %04x", mod.kind, mod.toPrettyChars, u); return null; } dbuf.writeUTF8(u); @@ -1552,7 +1553,6 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod) // It's UTF-8 if (buf[0] >= 0x80) { - auto loc = mod.getLoc(); .error(loc, "%s `%s` source file must start with BOM or ASCII character, not \\x%02X", mod.kind, mod.toPrettyChars, buf[0]); return null; } From a61180db7b6a005e2652768a8c4fd3226026a5dc Mon Sep 17 00:00:00 2001 From: Teodor Dutu Date: Fri, 16 Feb 2024 17:27:39 +0200 Subject: [PATCH 04/18] Revert the removal of `Expression.parens` Having this at the `Expression` level is useful to libdparse and will also help fix this regression https://issues.dlang.org/show_bug.cgi?id=24371 whose underlying issue is that the lowering doesn't take parentheses into account. This reverts the follwoing commits - 6e604e22b1e7f5f25ab2eb808a5691b2f7d3a9a0 - e60d027582d2fa6c9236db7da5ead4b47d6e3f87 - 71ffbe08c5fdfe91c11471b60a99a0f608cef628 --- compiler/src/dmd/astbase.d | 4 +-- compiler/src/dmd/expression.d | 4 +-- compiler/src/dmd/expression.h | 2 +- compiler/src/dmd/expressionsem.d | 39 +++++++++++++++----------- compiler/src/dmd/frontend.h | 9 +++--- compiler/src/dmd/importc.d | 7 ++--- compiler/src/dmd/parse.d | 48 +++++++++++--------------------- 7 files changed, 49 insertions(+), 64 deletions(-) diff --git a/compiler/src/dmd/astbase.d b/compiler/src/dmd/astbase.d index c224801ab9..14bd72cc25 100644 --- a/compiler/src/dmd/astbase.d +++ b/compiler/src/dmd/astbase.d @@ -4521,6 +4521,7 @@ struct ASTBase { EXP op; ubyte size; + ubyte parens; Type type; Loc loc; @@ -5099,8 +5100,6 @@ struct ASTBase extern (C++) final class TypeExp : Expression { - bool parens; - extern (D) this(const ref Loc loc, Type type) { super(loc, EXP.type, __traits(classInstanceSize, TypeExp)); @@ -5133,7 +5132,6 @@ struct ASTBase extern (C++) class IdentifierExp : Expression { Identifier ident; - bool parens; final extern (D) this(const ref Loc loc, Identifier ident) { diff --git a/compiler/src/dmd/expression.d b/compiler/src/dmd/expression.d index 41eeff923d..e9f59bd720 100644 --- a/compiler/src/dmd/expression.d +++ b/compiler/src/dmd/expression.d @@ -346,6 +346,7 @@ extern (C++) abstract class Expression : ASTNode Type type; // !=null means that semantic() has been run Loc loc; // file location const EXP op; // to minimize use of dynamic_cast + bool parens; // if this is a parenthesized expression extern (D) this(const ref Loc loc, EXP op) scope @safe { @@ -1341,7 +1342,6 @@ extern (C++) final class ComplexExp : Expression extern (C++) class IdentifierExp : Expression { Identifier ident; - bool parens; // if it appears as (identifier) extern (D) this(const ref Loc loc, Identifier ident) scope @safe { @@ -2423,8 +2423,6 @@ extern (C++) final class CompoundLiteralExp : Expression */ extern (C++) final class TypeExp : Expression { - bool parens; // if this is a parenthesized expression - extern (D) this(const ref Loc loc, Type type) @safe { super(loc, EXP.type); diff --git a/compiler/src/dmd/expression.h b/compiler/src/dmd/expression.h index 731f558049..58dda4ab66 100644 --- a/compiler/src/dmd/expression.h +++ b/compiler/src/dmd/expression.h @@ -86,6 +86,7 @@ public: Type *type; // !=NULL means that semantic() has been run Loc loc; // file location EXP op; // to minimize use of dynamic_cast + d_bool parens; // if this is a parenthesized expression size_t size() const; static void _init(); @@ -295,7 +296,6 @@ class IdentifierExp : public Expression { public: Identifier *ident; - d_bool parens; static IdentifierExp *create(const Loc &loc, Identifier *ident); bool isLvalue() override final; diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index 55dd4dd388..996213c65e 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -12196,25 +12196,30 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return result; } - void handleCatArgument(Expressions *arguments, Expression e) + void handleCatArgument(Expressions *arguments, Expression e, Type catType) { - if (auto ce = e.isCatExp()) - { - Expression lowering = ce.lowering; + auto tb = e.type.toBasetype(); - /* Skip `file`, `line`, and `funcname` if the hook of the parent - * `CatExp` is `_d_arraycatnTXTrace`. - */ - if (auto callExp = isRuntimeHook(lowering, hook)) + if (!e.parens || (catType.equals(tb) && (tb.ty == Tarray || tb.ty == Tsarray))) + if (auto ce = e.isCatExp()) { - if (hook == Id._d_arraycatnTX) - arguments.pushSlice((*callExp.arguments)[]); - else - arguments.pushSlice((*callExp.arguments)[3 .. $]); + Expression lowering = ce.lowering; + + /* Skip `file`, `line`, and `funcname` if the hook of the parent + * `CatExp` is `_d_arraycatnTXTrace`. + */ + if (auto callExp = isRuntimeHook(lowering, hook)) + { + if (hook == Id._d_arraycatnTX) + arguments.pushSlice((*callExp.arguments)[]); + else + arguments.pushSlice((*callExp.arguments)[3 .. $]); + } + + return; } - } - else - arguments.push(e); + + arguments.push(e); } auto arguments = new Expressions(); @@ -12227,8 +12232,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor arguments.push(new StringExp(exp.loc, funcname.toDString())); } - handleCatArgument(arguments, exp.e1); - handleCatArgument(arguments, exp.e2); + handleCatArgument(arguments, exp.e1, exp.type.toBasetype()); + handleCatArgument(arguments, exp.e2, exp.type.toBasetype()); Expression id = new IdentifierExp(exp.loc, Id.empty); id = new DotIdExp(exp.loc, id, Id.object); diff --git a/compiler/src/dmd/frontend.h b/compiler/src/dmd/frontend.h index 0534b64385..fe9c5fca08 100644 --- a/compiler/src/dmd/frontend.h +++ b/compiler/src/dmd/frontend.h @@ -2127,6 +2127,7 @@ public: Type* type; Loc loc; const EXP op; + bool parens; size_t size() const; static void _init(); static void deinitialize(); @@ -2615,7 +2616,6 @@ class IdentifierExp : public Expression { public: Identifier* ident; - bool parens; static IdentifierExp* create(const Loc& loc, Identifier* ident); bool isLvalue() final override; void accept(Visitor* v) override; @@ -3472,7 +3472,6 @@ public: class TypeExp final : public Expression { public: - bool parens; TypeExp* syntaxCopy() override; bool checkType() override; bool checkValue() override; @@ -5451,9 +5450,9 @@ struct UnionExp final private: union _AnonStruct_u { - char exp[29LLU]; + char exp[30LLU]; char integerexp[40LLU]; - char errorexp[29LLU]; + char errorexp[30LLU]; char realexp[48LLU]; char complexexp[64LLU]; char symoffexp[64LLU]; @@ -5462,7 +5461,7 @@ private: char assocarrayliteralexp[56LLU]; char structliteralexp[76LLU]; char compoundliteralexp[40LLU]; - char nullexp[29LLU]; + char nullexp[30LLU]; char dotvarexp[49LLU]; char addrexp[40LLU]; char indexexp[74LLU]; diff --git a/compiler/src/dmd/importc.d b/compiler/src/dmd/importc.d index 69a85ceec9..1761f73165 100644 --- a/compiler/src/dmd/importc.d +++ b/compiler/src/dmd/importc.d @@ -243,16 +243,15 @@ Expression castCallAmbiguity(Expression e, Scope* sc) case EXP.call: auto ce = (*pe).isCallExp(); - auto ie = ce.e1.isIdentifierExp(); - if (ie && ie.parens) + if (ce.e1.parens) { - ce.e1 = expressionSemantic(ie, sc); + ce.e1 = expressionSemantic(ce.e1, sc); if (ce.e1.op == EXP.type) { const numArgs = ce.arguments ? ce.arguments.length : 0; if (numArgs >= 1) { - ie.parens = false; + ce.e1.parens = false; Expression arg; foreach (a; (*ce.arguments)[]) { diff --git a/compiler/src/dmd/parse.d b/compiler/src/dmd/parse.d index a012e0c7c5..10a8520b97 100644 --- a/compiler/src/dmd/parse.d +++ b/compiler/src/dmd/parse.d @@ -7155,7 +7155,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer private void checkParens(TOK value, AST.Expression e) { - if (precedence[e.op] == PREC.rel) + if (precedence[e.op] == PREC.rel && !e.parens) error(e.loc, "`%s` must be surrounded by parentheses when next to operator `%s`", e.toChars(), Token.toChars(value)); } @@ -8576,6 +8576,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer // ( expression ) nextToken(); e = parseExpression(); + e.parens = true; check(loc, TOK.rightParenthesis); break; } @@ -8899,9 +8900,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer nextToken(); return AST.ErrorExp.get(); } - auto te = new AST.TypeExp(loc, t); - te.parens = true; - e = parsePostExp(te); + e = new AST.TypeExp(loc, t); + e.parens = true; + e = parsePostExp(e); } else if (token.value == TOK.leftParenthesis || token.value == TOK.plusPlus || token.value == TOK.minusMinus) @@ -9218,18 +9219,14 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer private AST.Expression parseAndExp() { Loc loc = token.loc; - bool parens = token.value == TOK.leftParenthesis; auto e = parseCmpExp(); while (token.value == TOK.and) { - if (!parens) - checkParens(TOK.and, e); - parens = nextToken() == TOK.leftParenthesis; + checkParens(TOK.and, e); + nextToken(); auto e2 = parseCmpExp(); - if (!parens) - checkParens(TOK.and, e2); + checkParens(TOK.and, e2); e = new AST.AndExp(loc, e, e2); - parens = true; // don't call checkParens() for And loc = token.loc; } return e; @@ -9237,42 +9234,32 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer private AST.Expression parseXorExp() { - Loc loc = token.loc; + const loc = token.loc; - bool parens = token.value == TOK.leftParenthesis; auto e = parseAndExp(); while (token.value == TOK.xor) { - if (!parens) - checkParens(TOK.xor, e); - parens = nextToken() == TOK.leftParenthesis; + checkParens(TOK.xor, e); + nextToken(); auto e2 = parseAndExp(); - if (!parens) - checkParens(TOK.xor, e2); + checkParens(TOK.xor, e2); e = new AST.XorExp(loc, e, e2); - parens = true; - loc = token.loc; } return e; } private AST.Expression parseOrExp() { - Loc loc = token.loc; + const loc = token.loc; - bool parens = token.value == TOK.leftParenthesis; auto e = parseXorExp(); while (token.value == TOK.or) { - if (!parens) - checkParens(TOK.or, e); - parens = nextToken() == TOK.leftParenthesis; + checkParens(TOK.or, e); + nextToken(); auto e2 = parseXorExp(); - if (!parens) - checkParens(TOK.or, e2); + checkParens(TOK.or, e2); e = new AST.OrExp(loc, e, e2); - parens = true; - loc = token.loc; } return e; } @@ -9323,7 +9310,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer AST.Expression parseAssignExp() { - bool parens = token.value == TOK.leftParenthesis; AST.Expression e; e = parseCondExp(); if (e is null) @@ -9332,7 +9318,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer // require parens for e.g. `t ? a = 1 : b = 2` void checkRequiredParens() { - if (e.op == EXP.question && !parens) + if (e.op == EXP.question && !e.parens) eSink.error(e.loc, "`%s` must be surrounded by parentheses when next to operator `%s`", e.toChars(), Token.toChars(token.value)); } From 2423b9379841cda4d1f6f5146a05dc5820225a7b Mon Sep 17 00:00:00 2001 From: Teodor Dutu Date: Mon, 19 Feb 2024 19:45:18 +0200 Subject: [PATCH 05/18] Fix Bugzilla Issue 24371 - String array concatenation does not respect operator precedence Rethink lowering logic to account for parentheses and operator associativity. Signed-off-by: Teodor Dutu --- compiler/src/dmd/expressionsem.d | 45 ++++++++++++++++-------------- compiler/test/runnable/test24371.d | 15 ++++++++++ 2 files changed, 39 insertions(+), 21 deletions(-) create mode 100644 compiler/test/runnable/test24371.d diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index 996213c65e..6cd282defa 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -12196,30 +12196,33 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return result; } - void handleCatArgument(Expressions *arguments, Expression e, Type catType) + void handleCatArgument(Expressions *arguments, Expression e, Type catType, bool isRightArg) { auto tb = e.type.toBasetype(); - if (!e.parens || (catType.equals(tb) && (tb.ty == Tarray || tb.ty == Tsarray))) - if (auto ce = e.isCatExp()) + if ((isRightArg && e.parens) || (!isRightArg && !tb.equals(catType))) + { + arguments.push(e); + return; + } + + if (auto ce = e.isCatExp()) + { + Expression lowering = ce.lowering; + + /* Skip `file`, `line`, and `funcname` if the hook of the parent + * `CatExp` is `_d_arraycatnTXTrace`. + */ + if (auto callExp = isRuntimeHook(lowering, hook)) { - Expression lowering = ce.lowering; - - /* Skip `file`, `line`, and `funcname` if the hook of the parent - * `CatExp` is `_d_arraycatnTXTrace`. - */ - if (auto callExp = isRuntimeHook(lowering, hook)) - { - if (hook == Id._d_arraycatnTX) - arguments.pushSlice((*callExp.arguments)[]); - else - arguments.pushSlice((*callExp.arguments)[3 .. $]); - } - - return; + if (hook == Id._d_arraycatnTX) + arguments.pushSlice((*callExp.arguments)[]); + else + arguments.pushSlice((*callExp.arguments)[3 .. $]); } - - arguments.push(e); + } + else + arguments.push(e); } auto arguments = new Expressions(); @@ -12232,8 +12235,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor arguments.push(new StringExp(exp.loc, funcname.toDString())); } - handleCatArgument(arguments, exp.e1, exp.type.toBasetype()); - handleCatArgument(arguments, exp.e2, exp.type.toBasetype()); + handleCatArgument(arguments, exp.e1, exp.type.toBasetype(), false); + handleCatArgument(arguments, exp.e2, exp.type.toBasetype(), true); Expression id = new IdentifierExp(exp.loc, Id.empty); id = new DotIdExp(exp.loc, id, Id.object); diff --git a/compiler/test/runnable/test24371.d b/compiler/test/runnable/test24371.d new file mode 100644 index 0000000000..885f9b8648 --- /dev/null +++ b/compiler/test/runnable/test24371.d @@ -0,0 +1,15 @@ +// https://issues.dlang.org/show_bug.cgi?id=24371 + +void main() +{ + assert("b" ~ "c" == "bc"); + assert(["a"] ~ "b" == ["a", "b"]); + assert(["a"] ~ ("b" ~ "c") == ["a", "bc"]); + + auto strArr = ["a"]; + assert(strArr ~ ("b" ~ "c") == ["a", "bc"]); + auto str = "c"; + assert(["a"] ~ ("b" ~ str) == ["a", "bc"]); + + assert(strArr ~ ("b" ~ str) == ["a", "bc"]); +} From 85b807cd2d911179be2f641412745f62b4e186b0 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Fri, 16 Feb 2024 20:38:25 +0100 Subject: [PATCH 06/18] GHA: Switch to old Xcode as workaround for macOS-13 jobs --- .github/workflows/main.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4846a5e215..208f41339f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -101,6 +101,13 @@ jobs: with: arch: ${{ env.MODEL == '64' && 'x64' || 'x86' }} + # FIXME: starting with Xcode 15: + # * https://issues.dlang.org/show_bug.cgi?id=24137 + # * https://issues.dlang.org/show_bug.cgi?id=24399 + - name: 'macOS 13: Switch to Xcode v14' + if: matrix.os == 'macos-13' + run: sudo xcode-select -switch /Applications/Xcode_14.3.1.app + - name: 'Posix: Install host compiler' if: runner.os != 'Windows' run: ci/run.sh install_host_compiler From 5197b62a1a3a53b6431a7f8fa67d288fb2dc3703 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Thu, 22 Feb 2024 00:50:08 +0100 Subject: [PATCH 07/18] Fix Bugzilla 24402 - OSX: Linker warning: pointer not aligned at __OBJC_PROTOCOL_$_Foo --- compiler/src/dmd/objc_glue.d | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/src/dmd/objc_glue.d b/compiler/src/dmd/objc_glue.d index 1812470675..db17af93d6 100644 --- a/compiler/src/dmd/objc_glue.d +++ b/compiler/src/dmd/objc_glue.d @@ -338,7 +338,7 @@ struct Segments immutable(char*) sectionName; immutable(char*) segmentName; immutable int flags; - immutable int alignment; + immutable int p2align; this(typeof(this.tupleof) tuple) @safe { @@ -388,7 +388,7 @@ struct Segments return segments[id] = Obj.getsegment( seg.sectionName, seg.segmentName, - seg.alignment, + seg.p2align, seg.flags ); } @@ -1159,7 +1159,7 @@ private: const symbolName = prefix ~ classDeclaration.objc.identifier.toString(); auto symbol = Symbols.getStatic(symbolName); symbol.Sseg = Segments[Segments.Id.const_]; - symbol.Salignment = 3; + symbol.Salignment = 8; symbol.Sdt = dtb.finish(); return symbol; @@ -1311,7 +1311,7 @@ struct ProtocolDeclaration symbol.Sseg = Segments[Segments.Id.protolist]; symbol.Sclass = SC.comdat; symbol.Sflags |= SFLhidden; - symbol.Salignment = 3; + symbol.Salignment = 8; auto dtb = DtBuilder(0); dtb.xoff(protocol, 0); @@ -1326,7 +1326,7 @@ struct ProtocolDeclaration symbol.Sseg = Segments[Segments.Id.data]; symbol.Sclass = SC.comdat; symbol.Sflags |= SFLhidden; - symbol.Salignment = 3; + symbol.Salignment = 8; auto dtb = DtBuilder(0); toDt(dtb); @@ -1478,7 +1478,7 @@ private: symbol.Sdt = dtb.finish(); symbol.Sseg = Segments[Segments.Id.const_]; - symbol.Salignment = 3; + symbol.Salignment = 8; return symbol; } @@ -1512,7 +1512,7 @@ private: symbol.Sdt = dtb.finish(); symbol.Sseg = Segments[Segments.Id.const_]; - symbol.Salignment = 3; + symbol.Salignment = 8; outdata(symbol); @@ -1546,7 +1546,7 @@ private: symbol.Sdt = dtb.finish(); symbol.Sseg = Segments[Segments.Id.const_]; - symbol.Salignment = 3; + symbol.Salignment = 8; outdata(symbol); From 53d3810128a043821be4f93c073598809a8dcbb9 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Thu, 22 Feb 2024 01:59:46 +0100 Subject: [PATCH 08/18] Fix Bugzilla 24137 - Link failure on macOS with symbol count from symbol table and dynamic symbol table differ --- compiler/src/dmd/backend/machobj.d | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/src/dmd/backend/machobj.d b/compiler/src/dmd/backend/machobj.d index 305c91991f..8308adccad 100644 --- a/compiler/src/dmd/backend/machobj.d +++ b/compiler/src/dmd/backend/machobj.d @@ -1426,6 +1426,7 @@ void MachObj_term(const(char)* objfilename) sym32.n_sect = sym.n_sect; fobjbuf.write(&sym32, sym32.sizeof); } + dysymtab_cmd.nundefsym++; symtab_cmd.nsyms++; } foffset += symtab_cmd.nsyms * (I64 ? nlist_64.sizeof : nlist.sizeof); From b40eb09ff80821a7e95fe989ca0063c5f84d132b Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Thu, 22 Feb 2024 10:05:29 +0100 Subject: [PATCH 09/18] Fix Bugzilla 20297 - Link warning: no platform load command found in object.o, assuming: macOS Co-authored-by: Jacob Carlborg --- compiler/src/dmd/backend/mach.d | 65 +++++++++++ compiler/src/dmd/backend/machobj.d | 176 ++++++++++++++++++++++++++++- 2 files changed, 239 insertions(+), 2 deletions(-) diff --git a/compiler/src/dmd/backend/mach.d b/compiler/src/dmd/backend/mach.d index 1686537942..a7078e2766 100644 --- a/compiler/src/dmd/backend/mach.d +++ b/compiler/src/dmd/backend/mach.d @@ -94,6 +94,12 @@ enum LC_SYMTAB = 2, LC_DYSYMTAB = 11, LC_SEGMENT_64 = 0x19, + + /// Build for MacOSX min OS version. + LC_VERSION_MIN_MACOSX = 0x24, + + /// Build for platform min OS version. + LC_BUILD_VERSION = 0x32, } struct load_command @@ -407,3 +413,62 @@ struct scattered_relocation_info int r_value; } + +/** + * The version_min_command contains the min OS version on which this binary was + * built to run. + */ +struct version_min_command +{ + /// + uint cmd = LC_VERSION_MIN_MACOSX; + + /// + uint cmdsize = typeof(this).sizeof; + + /// X.Y.Z is encoded in nibbles xxxx.yy.zz + uint version_; + + /// X.Y.Z is encoded in nibbles xxxx.yy.zz + uint sdk = 0; +} + +/** + * The `build_version_command` contains the min OS version on which this binary + * was built to run for its platform. + */ +struct build_version_command +{ + /// + uint cmd = LC_BUILD_VERSION; + + /// + uint cmdsize = typeof(this).sizeof; + + /// Platform + uint platform = PLATFORM_MACOS; + + /// X.Y.Z is encoded in nibbles xxxx.yy.zz + uint minos; + + /// X.Y.Z is encoded in nibbles xxxx.yy.zz + uint sdk = 0; + + /// Number of tool entries following this + uint ntools = 0; +} + +/// Known values for the platform field in `build_version_command` +enum +{ + PLATFORM_MACOS = 1, + PLATFORM_IOS = 2, + PLATFORM_TVOS = 3, + PLATFORM_WATCHOS = 4, + PLATFORM_BRIDGEOS = 5, + PLATFORM_MACCATALYST = 6, + PLATFORM_IOSSIMULATOR = 7, + PLATFORM_TVOSSIMULATOR = 8, + PLATFORM_WATCHOSSIMULATOR = 9, + PLATFORM_DRIVERKIT = 10 +} diff --git a/compiler/src/dmd/backend/machobj.d b/compiler/src/dmd/backend/machobj.d index 8308adccad..eb80c1b58c 100644 --- a/compiler/src/dmd/backend/machobj.d +++ b/compiler/src/dmd/backend/machobj.d @@ -699,6 +699,7 @@ void MachObj_term(const(char)* objfilename) * { sections } * symtab_command * dysymtab_command + * build_version_command/version_min_command * { segment contents } * { relocations } * symbol table @@ -706,6 +707,7 @@ void MachObj_term(const(char)* objfilename) * indirect symbol table */ + auto version_command = VersionCommand(operatingSystemVersion); uint foffset; uint headersize; uint sizeofcmds; @@ -719,9 +721,10 @@ void MachObj_term(const(char)* objfilename) header.cputype = CPU_TYPE_X86_64; header.cpusubtype = CPU_SUBTYPE_I386_ALL; header.filetype = MH_OBJECT; - header.ncmds = 3; + header.ncmds = 4; header.sizeofcmds = cast(uint)(segment_command_64.sizeof + (section_cnt - 1) * section_64.sizeof + + version_command.size + symtab_command.sizeof + dysymtab_command.sizeof); header.flags = MH_SUBSECTIONS_VIA_SYMBOLS; @@ -743,9 +746,10 @@ void MachObj_term(const(char)* objfilename) header.cputype = CPU_TYPE_I386; header.cpusubtype = CPU_SUBTYPE_I386_ALL; header.filetype = MH_OBJECT; - header.ncmds = 3; + header.ncmds = 4; header.sizeofcmds = cast(uint)(segment_command.sizeof + (section_cnt - 1) * section.sizeof + + version_command.size + symtab_command.sizeof + dysymtab_command.sizeof); header.flags = MH_SUBSECTIONS_VIA_SYMBOLS; @@ -1474,6 +1478,7 @@ void MachObj_term(const(char)* objfilename) fobjbuf.write(&segment_cmd, segment_cmd.sizeof); fobjbuf.write(SECbuf.buf + section.sizeof, cast(uint)((section_cnt - 1) * section.sizeof)); } + fobjbuf.write(version_command.data, version_command.size); fobjbuf.write(&symtab_cmd, symtab_cmd.sizeof); fobjbuf.write(&dysymtab_cmd, dysymtab_cmd.sizeof); fobjbuf.position(foffset, 0); @@ -2957,3 +2962,170 @@ int dwarf_eh_frame_fixup(int dfseg, targ_size_t offset, Symbol *s, targ_size_t v return I64 ? 8 : 4; } + + +private: + +/** + * Encapsulates the build_version_command/version_min_command load commands. + * + * For the 10.14 and later SDK, the `build_version_command` load command is used. + * For earlier versions, the `version_min_command` load command is used. + */ +const struct VersionCommand +{ + pure: + nothrow: + @nogc: + @safe: + + private + { + /** + * This is the absolute minimum supported version of macOS (64 bit) for DMD, + * as documented at: https://dlang.org/dmd-osx.html#requirements + * NOTE: Versions earlier than 10.7 do not support thread local storage. + */ + enum fallbackOSVersion = Version(10, 9).encode; + + /// The first minor version that uses the `build_version_command`. + enum firstMinorUsingBuildVersionCommand = 14; + + /// `true` if the `build_version_command` load command should be used. + bool useBuild; + + /// The `build_version_command` load command. + build_version_command buildVersionCommand; + + /// The `version_min_command` load command. + version_min_command versionMinCommand; + } + + /** + * Initializes the VersionCommand. + * + * Params: + * os = the version of the operating system + */ + this(Version os) + { + useBuild = os.minor >= firstMinorUsingBuildVersionCommand; + + const encodedOs = os.isValid ? os.encode : fallbackOSVersion; + + const build_version_command buildVersionCommand = { minos: encodedOs }; + const version_min_command versionMinCommand = { version_: encodedOs }; + + this.buildVersionCommand = buildVersionCommand; + this.versionMinCommand = versionMinCommand; + } + + /// Returns: the size of the load command. + size_t size() + { + return useBuild ? build_version_command.sizeof : version_min_command.sizeof; + } + + /// Returns: the data for the load command. + const(void)* data() return + { + return useBuild ? cast(const(void)*) &buildVersionCommand : cast(const(void)*) &versionMinCommand; + } +} + +/// Holds an operating system version or a SDK version. +immutable struct Version +{ + /// + int major; + + /// + int minor; + + /// + int build; + + /// Returns: `true` if the version is valid + bool isValid() pure nothrow @nogc @safe + { + return major >= 10 && major < 100 && + minor >= 0 && minor < 100 && + build >= 0 && build < 100; + } +} + +/** + * Returns the given version encoded as a single integer. + * + * Params: + * version_ = the version to encode. Needs to be a valid version + * (`version_.isValid`) + * + * Returns: the encoded version + */ +int encode(Version version_) pure @nogc @safe +in +{ + assert(version_.isValid); +} +do +{ + with (version_) + return major * 2^^16 + minor * 2^^8 + build * 2^^0; +} + +unittest +{ + assert(Version(10, 14, 0).encode == 0x0a0e00); + assert(Version(10, 14, 1).encode == 0x0a0e01); + assert(Version(10, 14, 6).encode == 0x0a0e06); + assert(Version(10, 14, 99).encode == 0x0a0e63); + + assert(Version(10, 15, 6).encode == 0x0a0f06); + + assert(Version(10, 16, 0).encode == 0x0a1000); + assert(Version(10, 16, 6).encode == 0x0a1006); + + assert(Version(10, 17, 0).encode == 0x0a1100); +} + +/// Returns: the version of the currently running operating system. +@trusted +Version operatingSystemVersion() +{ + if (const deploymentTarget = getenv("MACOSX_DEPLOYMENT_TARGET")) + { + const version_ = toVersion(deploymentTarget); + + if (version_.isValid) + return version_; + + error(null, 0, 0, "invalid version number in 'MACOSX_DEPLOYMENT_TARGET=%s'", deploymentTarget); + } + return Version(); +} + +/** + * Converts the given string to a `Version`. + * + * Params: + * str = the string to convert. Should have the format `XX.YY(.ZZ)`. Needs to + * be `\0` terminated. + * + * Returns: the converted `Version`. + */ +@trusted +Version toVersion(const char* str) @nogc +{ + import core.stdc.stdio : sscanf; + + if (!str) + return Version(); + + Version version_; + + with (version_) + str.sscanf("%d.%d.%d", &major, &minor, &build); + + return version_; +} From 6f2a6f919df2eb5ba03700e969495f8c53ddfdcb Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Thu, 22 Feb 2024 13:23:02 +0100 Subject: [PATCH 10/18] Fix Bugzilla 23517 - dmd with -g flag fails to link on macOS with unaligned pointer --- compiler/src/dmd/backend/dwarfdbginf.d | 15 ++++---- compiler/test/runnable/debug_info.d | 50 -------------------------- druntime/test/exceptions/Makefile | 8 ++--- 3 files changed, 12 insertions(+), 61 deletions(-) delete mode 100644 compiler/test/runnable/debug_info.d diff --git a/compiler/src/dmd/backend/dwarfdbginf.d b/compiler/src/dmd/backend/dwarfdbginf.d index 4e4907efd4..d2d0b4c5dc 100644 --- a/compiler/src/dmd/backend/dwarfdbginf.d +++ b/compiler/src/dmd/backend/dwarfdbginf.d @@ -16,15 +16,19 @@ Some generic information for debug info on macOS: The linker on macOS will remove any debug info, i.e. every section with the -`S_ATTR_DEBUG` flag, this includes everything in the `__DWARF` section. By using -the `S_REGULAR` flag the linker will not remove this section. This allows to get -the filenames and line numbers for backtraces from the executable. +`S_ATTR_DEBUG` flag, this includes everything in the `__DWARF` section. +Because of this, it is not possible to get filenames and line numbers for +backtraces from the executable alone. Normally the linker removes all the debug info but adds a reference to the object files. The debugger can then read the object files to get filename and line number information. It's also possible to use an additional tool that generates a separate `.dSYM` file. This file can then later be deployed with the application if debug info is needed when the application is deployed. + +Support in core.runtime for getting filename and line number for backtraces +from these `.dSYM` files will need to be investigated. +See: https://issues.dlang.org/show_bug.cgi?id=20510 */ module dmd.backend.dwarfdbginf; @@ -476,7 +480,7 @@ static if (1) { name = n; if (config.objfmt == OBJ_MACH) - flags = S_ATTR_DEBUG; + flags = S_REGULAR | S_ATTR_DEBUG; else flags = SHT_PROGBITS; } @@ -550,10 +554,7 @@ static if (1) debug_abbrev = Section("__debug_abbrev"); debug_info = Section("__debug_info"); debug_str = Section("__debug_str"); - // We use S_REGULAR to make sure the linker doesn't remove this section. Needed - // for filenames and line numbers in backtraces. debug_line = Section("__debug_line"); - debug_line.flags = S_REGULAR; } void elfDebugSectionsInit() { diff --git a/compiler/test/runnable/debug_info.d b/compiler/test/runnable/debug_info.d deleted file mode 100644 index 7853d9a3d9..0000000000 --- a/compiler/test/runnable/debug_info.d +++ /dev/null @@ -1,50 +0,0 @@ -// REQUIRED_ARGS: -g - -void main() -{ - version(OSX) testDebugLineMacOS(); -} - -version (OSX): - -struct mach_header; -struct mach_header_64; -struct section; -struct section_64; - -version (D_LP64) -{ - alias MachHeader = mach_header_64; - alias Section = section_64; -} - -else -{ - alias MachHeader = mach_header; - alias Section = section; -} - -extern (C) -{ - MachHeader* _dyld_get_image_header(uint image_index); - const(section)* getsectbynamefromheader(scope const mach_header* mhp, scope const char* segname, scope const char* sectname); - const(section_64)* getsectbynamefromheader_64(scope const mach_header_64* mhp, scope const char* segname, scope const char* sectname); -} - -const(Section)* getSectByNameFromHeader(MachHeader* mhp, in char* segname, in char* sectname) -{ - version (D_LP64) - return getsectbynamefromheader_64(mhp, segname, sectname); - else - return getsectbynamefromheader(mhp, segname, sectname); -} - -void testDebugLineMacOS() -{ - auto header = _dyld_get_image_header(0); - assert(header); - - auto section = getSectByNameFromHeader(header, "__DWARF", "__debug_line"); - // verify that the __debug_line section is present in the final executable - assert(section); -} diff --git a/druntime/test/exceptions/Makefile b/druntime/test/exceptions/Makefile index fd975327d9..230013cc65 100644 --- a/druntime/test/exceptions/Makefile +++ b/druntime/test/exceptions/Makefile @@ -20,7 +20,7 @@ ifeq ($(OS)-$(BUILD),dragonflybsd-debug) LINE_TRACE_DFLAGS:=-L--export-dynamic endif ifeq ($(OS)-$(BUILD),osx-debug) - TESTS+=line_trace line_trace_21656 long_backtrace_trunc cpp_demangle + TESTS+=line_trace line_trace_21656 cpp_demangle LINE_TRACE_DFLAGS:= endif ifeq ($(OS)-$(BUILD),windows-debug) @@ -42,7 +42,7 @@ $(ROOT)/line_trace.done: $(ROOT)/line_trace$(DOTEXE) @echo Testing line_trace $(QUIET)$(TIMELIMIT)$(ROOT)/line_trace $(RUN_ARGS) > $(ROOT)/line_trace.output # Use sed to canonicalize line_trace.output and compare against expected output in line_trace.exp - $(QUIET)$(SED) "s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/line_trace.output | $(DIFF) line_trace.exp - + $(QUIET)$(SED) "s|^.*/src/|src/|g; s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/line_trace.output | $(DIFF) line_trace.exp - @rm -f $(ROOT)/line_trace.output @touch $@ @@ -52,7 +52,7 @@ $(ROOT)/line_trace_21656.done: $(ROOT)/line_trace$(DOTEXE) @mkdir -p $(ROOT)/line_trace_21656 @touch $(ROOT)/line_trace_21656/line_trace $(QUIET)cd $(ROOT)/line_trace_21656 && PATH="..:$$PATH" $(TIMELIMIT)line_trace $(RUN_ARGS) > line_trace.output - $(QUIET)$(SED) "s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/line_trace_21656/line_trace.output | $(DIFF) line_trace.exp - + $(QUIET)$(SED) "s|^.*/src/|src/|g; s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/line_trace_21656/line_trace.output | $(DIFF) line_trace.exp - @rm -rf $(ROOT)/line_trace_21656 @touch $@ @@ -60,7 +60,7 @@ $(ROOT)/long_backtrace_trunc.done: $(ROOT)/long_backtrace_trunc$(DOTEXE) @echo Testing long_backtrace_trunc $(QUIET)$(TIMELIMIT)$(ROOT)/long_backtrace_trunc $(RUN_ARGS) > $(ROOT)/long_backtrace_trunc.output # Use sed to canonicalize long_backtrace_trunc.output and compare against expected output in long_backtrace_trunc.exp - $(QUIET)$(SED) "s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/long_backtrace_trunc.output | $(DIFF) long_backtrace_trunc.exp - + $(QUIET)$(SED) "s|^.*/src/|src/|g; s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/long_backtrace_trunc.output | $(DIFF) long_backtrace_trunc.exp - @rm -f $(ROOT)/long_backtrace_trunc.output @touch $@ From baf8ee195aef40afc10a5101ec80ff8e1792d2c4 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Thu, 22 Feb 2024 14:50:59 +0100 Subject: [PATCH 11/18] Fix Bugzilla 24401 - OSX: Linker error: GOT load reloc does not point to a movq instruction --- compiler/src/dmd/backend/machobj.d | 10 ++++------ compiler/test/runnable/issue24401.d | 6 ++++++ 2 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 compiler/test/runnable/issue24401.d diff --git a/compiler/src/dmd/backend/machobj.d b/compiler/src/dmd/backend/machobj.d index eb80c1b58c..f5718fa8f2 100644 --- a/compiler/src/dmd/backend/machobj.d +++ b/compiler/src/dmd/backend/machobj.d @@ -942,6 +942,8 @@ void MachObj_term(const(char)* objfilename) } // Put out relocation data + // See mach-o/reloc.h for some examples of what should be generated and when: + // https://github.com/apple-oss-distributions/xnu/blob/rel/xnu-10002/EXTERNAL_HEADERS/mach-o/x86_64/reloc.h mach_numbersyms(); for (int seg = 1; seg < SegData.length; seg++) { @@ -1053,12 +1055,8 @@ void MachObj_term(const(char)* objfilename) rel.r_type = X86_64_RELOC_SIGNED; else if ((s.Sfl == FLfunc || s.Sfl == FLextern || s.Sclass == SC.global || s.Sclass == SC.comdat || s.Sclass == SC.comdef) && r.rtype == RELaddr) - { - rel.r_type = X86_64_RELOC_GOT_LOAD; - if (seg == eh_frame_seg || - seg == except_table_seg) - rel.r_type = X86_64_RELOC_GOT; - } + rel.r_type = X86_64_RELOC_GOT; + rel.r_address = cast(int)r.offset; rel.r_symbolnum = s.Sxtrnnum; rel.r_pcrel = 1; diff --git a/compiler/test/runnable/issue24401.d b/compiler/test/runnable/issue24401.d new file mode 100644 index 0000000000..109d543a0b --- /dev/null +++ b/compiler/test/runnable/issue24401.d @@ -0,0 +1,6 @@ +// PERMUTE_ARGS: +// https://issues.dlang.org/show_bug.cgi?id=24401 +int main() +{ + return (() @trusted => 0)(); +} From 582bf08cb09ffe8f9c3c71953566a363b1caa6a3 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Thu, 22 Feb 2024 21:11:47 +0100 Subject: [PATCH 12/18] Fix Bugzilla 22556 - Invalid GOT load reloc with -O on MacOS --- compiler/test/runnable_cxx/test7925.d | 7 ------- 1 file changed, 7 deletions(-) diff --git a/compiler/test/runnable_cxx/test7925.d b/compiler/test/runnable_cxx/test7925.d index 2f52826bc4..2d0b023fe5 100644 --- a/compiler/test/runnable_cxx/test7925.d +++ b/compiler/test/runnable_cxx/test7925.d @@ -1,12 +1,5 @@ // EXTRA_CPP_SOURCES: cpp7925.cpp -/* -Exclude -O due to a codegen bug on OSX: -https://issues.dlang.org/show_bug.cgi?id=22556 - -PERMUTE_ARGS(osx): -inline -release -g -*/ - import core.vararg; extern(C++) class C1 From 6139abb2020da13f5d905c6dd204b41e39cc861c Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Thu, 22 Feb 2024 22:18:53 +0100 Subject: [PATCH 13/18] Fix Bugzilla 21047 - Linker error: GOT load reloc does not point to a movq instruction --- compiler/src/dmd/backend/cgelem.d | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/compiler/src/dmd/backend/cgelem.d b/compiler/src/dmd/backend/cgelem.d index 7e34fe7375..3e99f8fb31 100644 --- a/compiler/src/dmd/backend/cgelem.d +++ b/compiler/src/dmd/backend/cgelem.d @@ -5035,14 +5035,9 @@ private elem * el64_32(elem *e, goal_t goal) } break; - case OPmul: - if (config.exe & (EX_OSX | EX_OSX64)) // https://issues.dlang.org/show_bug.cgi?id=21047 - break; - else - goto case; - case OPadd: case OPmin: + case OPmul: case OPor: case OPand: case OPxor: From 985f64ba03ad2b5e210e8e555c6e59253188faaa Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Thu, 22 Feb 2024 09:34:23 +0100 Subject: [PATCH 14/18] Fix Bugzilla 24399 - Link failure on MacOS with address=0x0 points to section(2) with no content --- compiler/src/dmd/todt.d | 5 +++++ compiler/test/compilable/issue24399.d | 9 +++++++++ 2 files changed, 14 insertions(+) create mode 100644 compiler/test/compilable/issue24399.d diff --git a/compiler/src/dmd/todt.d b/compiler/src/dmd/todt.d index ca73e1e570..1b9aa8f957 100644 --- a/compiler/src/dmd/todt.d +++ b/compiler/src/dmd/todt.d @@ -92,6 +92,11 @@ extern (C++) void Initializer_toDt(Initializer init, ref DtBuilder dtb, bool isC if (tb.ty == Tvector) tb = (cast(TypeVector)tb).basetype; + if (ai.dim == 0 && tb.isZeroInit(ai.loc)) + { + dtb.nzeros(cast(uint)ai.type.size()); + return; + } Type tn = tb.nextOf().toBasetype(); //printf("\tdim = %d\n", ai.dim); diff --git a/compiler/test/compilable/issue24399.d b/compiler/test/compilable/issue24399.d new file mode 100644 index 0000000000..ae3e7442f5 --- /dev/null +++ b/compiler/test/compilable/issue24399.d @@ -0,0 +1,9 @@ +// REQUIRED_ARGS: -main +// LINK: +template rt_options() +{ + __gshared string[] rt_options = []; + string[] rt_options_tls = []; +} + +alias _ = rt_options!(); From 65db10cf920c3519553a2a499230c994d6db2f5c Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sat, 24 Feb 2024 01:29:10 +0100 Subject: [PATCH 15/18] Fix Bugzilla 24407 - OSX: ld: Assertion failed: (slot < _sideTableBuffer.size()), function addAtom --- .github/workflows/main.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 208f41339f..a5eedf72d5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -51,10 +51,12 @@ jobs: # macOS - job_name: macOS 13 x64, DMD (latest) os: macos-13 - host_dmd: dmd + # FIXME: Revert this back to "dmd" after 2.107.1 is released. + host_dmd: ldc - job_name: macOS 13 x64, DMD (coverage) os: macos-13 - host_dmd: dmd + # FIXME: Revert this back to "dmd" after 2.107.1 is released. + host_dmd: ldc coverage: true - job_name: macOS 12 x64, DMD (bootstrap) os: macos-12 @@ -101,12 +103,12 @@ jobs: with: arch: ${{ env.MODEL == '64' && 'x64' || 'x86' }} - # FIXME: starting with Xcode 15: - # * https://issues.dlang.org/show_bug.cgi?id=24137 - # * https://issues.dlang.org/show_bug.cgi?id=24399 - - name: 'macOS 13: Switch to Xcode v14' + # NOTE: Linker ICEs with Xcode 15.0.1 (default version on macos-13) + # * https://issues.dlang.org/show_bug.cgi?id=24407 + # Remove this step if the default gets changed to 15.1 in actions/runner-images. + - name: 'macOS 13: Switch to Xcode v15.1' if: matrix.os == 'macos-13' - run: sudo xcode-select -switch /Applications/Xcode_14.3.1.app + run: sudo xcode-select -switch /Applications/Xcode_15.1.app - name: 'Posix: Install host compiler' if: runner.os != 'Windows' From dd23837579e28e931b823315605ae7bc8e4f1608 Mon Sep 17 00:00:00 2001 From: Tim Schendekehl Date: Tue, 27 Feb 2024 13:11:05 +0100 Subject: [PATCH 16/18] Fix Bugzilla 24409 - DMD crash for CTFE in stompOverlappedFields (#16246) --- compiler/src/dmd/dinterpret.d | 2 +- compiler/test/compilable/issue24409.d | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 compiler/test/compilable/issue24409.d diff --git a/compiler/src/dmd/dinterpret.d b/compiler/src/dmd/dinterpret.d index eda91d1ea0..9603cad936 100644 --- a/compiler/src/dmd/dinterpret.d +++ b/compiler/src/dmd/dinterpret.d @@ -3783,7 +3783,7 @@ public: if (v is v2 || !v.isOverlappedWith(v2)) continue; auto e = (*sle.elements)[i]; - if (e.op != EXP.void_) + if (e !is null && e.op != EXP.void_) (*sle.elements)[i] = voidInitLiteral(e.type, v).copy(); } } diff --git a/compiler/test/compilable/issue24409.d b/compiler/test/compilable/issue24409.d new file mode 100644 index 0000000000..5d298df211 --- /dev/null +++ b/compiler/test/compilable/issue24409.d @@ -0,0 +1,17 @@ +static struct S +{ + union + { + int i; + long l; + } +} + +int f() +{ + S* r = new S(); + r.i = 5; + return r.i; +} + +enum X = f(); From c574385a58463d38118c6836ada6f86067282f21 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Wed, 28 Feb 2024 20:10:17 +0100 Subject: [PATCH 17/18] Fix Bugzilla 24422 - ImportC: ICE: Segfault in cparseFunctionDefinition --- compiler/src/dmd/cparse.d | 8 +++++++- compiler/test/fail_compilation/fail24422.c | 7 +++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 compiler/test/fail_compilation/fail24422.c diff --git a/compiler/src/dmd/cparse.d b/compiler/src/dmd/cparse.d index e0cdc87b7f..db9814d686 100644 --- a/compiler/src/dmd/cparse.d +++ b/compiler/src/dmd/cparse.d @@ -2132,7 +2132,7 @@ final class CParser(AST) : Parser!AST error("function identifier-list cannot end with `...`"); ft.parameterList.varargs = AST.VarArg.KRvariadic; // but C11 allows extra arguments auto plLength = pl.length; - if (symbols.length != plLength) + if (symbols && symbols.length != plLength) error(token.loc, "%d identifiers does not match %d declarations", cast(int)plLength, cast(int)symbols.length); /* Transfer the types and storage classes from symbols[] to pl[] @@ -2153,6 +2153,12 @@ final class CParser(AST) : Parser!AST if (p.type || !(p.storageClass & STC.parameter)) error("storage class and type are not allowed in identifier-list"); + if (!symbols) + { + // Error already given in cparseDeclaration + p.type = AST.Type.terror; + continue; + } foreach (s; (*symbols)[]) // yes, quadratic { auto ad = s.isAttribDeclaration(); diff --git a/compiler/test/fail_compilation/fail24422.c b/compiler/test/fail_compilation/fail24422.c new file mode 100644 index 0000000000..d148b492c3 --- /dev/null +++ b/compiler/test/fail_compilation/fail24422.c @@ -0,0 +1,7 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/fail24422.c(7): Error: type-specifier missing for declaration of `a` +--- +*/ +void f24422(a) a; { } From 5aad132632ebcd0bb5855611815673bdd4cd0d34 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Fri, 1 Mar 2024 21:47:30 +0000 Subject: [PATCH 18/18] bump VERSION to v2.107.1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 1880c9808c..ff56162fdd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.107.1-rc.1 +v2.107.1