From d661273ee900c1a5cac5b57433f47ed9cef9a7e9 Mon Sep 17 00:00:00 2001 From: "Richard (Rikki) Andrew Cattermole" Date: Tue, 2 Jul 2024 12:34:27 +1200 Subject: [PATCH 01/15] Document template instance duplication status as part of its field documentation. (#16643) --- compiler/src/dmd/dtemplate.d | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/compiler/src/dmd/dtemplate.d b/compiler/src/dmd/dtemplate.d index 2bf7ad17a766..37ddbd27a5aa 100644 --- a/compiler/src/dmd/dtemplate.d +++ b/compiler/src/dmd/dtemplate.d @@ -3653,7 +3653,22 @@ extern (C++) class TemplateInstance : ScopeDsymbol Dsymbol tempdecl; // referenced by foo.bar.abc Dsymbol enclosing; // if referencing local symbols, this is the context Dsymbol aliasdecl; // !=null if instance is an alias for its sole member - TemplateInstance inst; // refer to existing instance + + /** + If this is not null and it has a value that is not the current object, + then this field points to an existing template instance + and that object has been duplicated into us. + + If this object is a duplicate, + the ``memberOf`` field will be set to a root module (passed on CLI). + + This information is useful to deduplicate analysis that may occur + after semantic 3 has completed. + + See_Also: memberOf + */ + TemplateInstance inst; + ScopeDsymbol argsym; // argument symbol table size_t hash; // cached result of toHash() @@ -3665,7 +3680,15 @@ extern (C++) class TemplateInstance : ScopeDsymbol TemplateInstances* deferred; - Module memberOf; // if !null, then this TemplateInstance appears in memberOf.members[] + /** + If this is not null then this template instance appears in a root module's members. + + Note: This is not useful for determining duplication status of this template instance. + Use the field ``inst`` for determining if a template instance has been duplicated into this object. + + See_Also: inst + */ + Module memberOf; // Used to determine the instance needs code generation. // Note that these are inaccurate until semantic analysis phase completed. From ec75b677b43f2444eef0f6983344764898645726 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Tue, 2 Jul 2024 19:31:34 +0200 Subject: [PATCH 02/15] Fix Bugzilla 24599 - Wrongly elided TypeInfo emission (#15868) Reverting #14844, which caused such missing TypeInfos, *and* making sure the special TypeInfo members are fully analyzed and ready for codegen (otherwise hitting an assertion for the real-world project). --- compiler/src/dmd/expressionsem.d | 12 +----------- compiler/src/dmd/frontend.h | 2 +- compiler/src/dmd/todt.d | 7 +++++++ compiler/src/dmd/typinf.d | 5 ++--- compiler/src/dmd/typinf.h | 2 +- compiler/src/tests/cxxfrontend.cc | 2 +- compiler/test/runnable/test23650.d | 13 ------------- compiler/test/runnable/test24599.d | 24 ++++++++++++++++++++++++ 8 files changed, 37 insertions(+), 30 deletions(-) delete mode 100644 compiler/test/runnable/test23650.d create mode 100644 compiler/test/runnable/test24599.d diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index ad702dc2c6b3..f1e30ad825f9 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -7194,17 +7194,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // Handle this in the glue layer Expression e = new TypeidExp(exp.loc, ta); - bool genObjCode = true; - - // https://issues.dlang.org/show_bug.cgi?id=23650 - // We generate object code for typeinfo, required - // by typeid, only if in non-speculative context - if (sc.traitsCompiles) - { - genObjCode = false; - } - - e.type = getTypeInfoType(exp.loc, ta, sc, genObjCode); + e.type = getTypeInfoType(exp.loc, ta, sc); semanticTypeInfo(sc, ta); if (ea) diff --git a/compiler/src/dmd/frontend.h b/compiler/src/dmd/frontend.h index 0c6b01d91b49..677373f461f7 100644 --- a/compiler/src/dmd/frontend.h +++ b/compiler/src/dmd/frontend.h @@ -7596,7 +7596,7 @@ struct Target final extern Target target; -extern Type* getTypeInfoType(const Loc& loc, Type* t, Scope* sc, bool genObjCode = true); +extern Type* getTypeInfoType(const Loc& loc, Type* t, Scope* sc); class SemanticTimeTransitiveVisitor : public SemanticTimePermissiveVisitor { diff --git a/compiler/src/dmd/todt.d b/compiler/src/dmd/todt.d index 4bfa0f1b88cc..667cd198cac5 100644 --- a/compiler/src/dmd/todt.d +++ b/compiler/src/dmd/todt.d @@ -1441,6 +1441,13 @@ private extern (C++) class TypeInfoDtVisitor : Visitor /* ti.toObjFile() won't get called. So, store these * member functions into object file in here. */ + + if (sd.semanticRun < PASS.semantic3done) + { + import dmd.semantic3 : semanticTypeInfoMembers; + semanticTypeInfoMembers(sd); + } + if (sd.xeq && sd.xeq != StructDeclaration.xerreq) toObjFile(sd.xeq, global.params.multiobj); if (sd.xcmp && sd.xcmp != StructDeclaration.xerrcmp) diff --git a/compiler/src/dmd/typinf.d b/compiler/src/dmd/typinf.d index 201ea9602663..98d4287b8db5 100644 --- a/compiler/src/dmd/typinf.d +++ b/compiler/src/dmd/typinf.d @@ -100,14 +100,13 @@ bool genTypeInfo(Expression e, const ref Loc loc, Type torig, Scope* sc) * loc = the location for reporting line nunbers in errors * t = the type to get the type of the `TypeInfo` object for * sc = the scope - * genObjCode = if true, object code will be generated for the obtained TypeInfo * Returns: * The type of the `TypeInfo` object associated with `t` */ -extern (C++) Type getTypeInfoType(const ref Loc loc, Type t, Scope* sc, bool genObjCode = true) +extern (C++) Type getTypeInfoType(const ref Loc loc, Type t, Scope* sc) { assert(t.ty != Terror); - if (genTypeInfo(null, loc, t, sc) && genObjCode) + if (genTypeInfo(null, loc, t, sc)) { // Find module that will go all the way to an object file Module m = sc._module.importedFrom; diff --git a/compiler/src/dmd/typinf.h b/compiler/src/dmd/typinf.h index dd9572aab42f..6414ecdd36ac 100644 --- a/compiler/src/dmd/typinf.h +++ b/compiler/src/dmd/typinf.h @@ -22,4 +22,4 @@ namespace dmd bool isSpeculativeType(Type *t); bool builtinTypeInfo(Type *t); } -Type *getTypeInfoType(const Loc &loc, Type *t, Scope *sc, bool genObjCode = true); +Type *getTypeInfoType(const Loc &loc, Type *t, Scope *sc); diff --git a/compiler/src/tests/cxxfrontend.cc b/compiler/src/tests/cxxfrontend.cc index 532a6297425d..eaf4a36936d3 100644 --- a/compiler/src/tests/cxxfrontend.cc +++ b/compiler/src/tests/cxxfrontend.cc @@ -1865,7 +1865,7 @@ void template_h(TemplateParameter *tp, Scope *sc, TemplateParameters *tps, void typinf_h(Expression *e, const Loc &loc, Type *t, Scope *sc) { dmd::genTypeInfo(e, loc, t, sc); - ::getTypeInfoType(loc, t, sc, false); + ::getTypeInfoType(loc, t, sc); dmd::isSpeculativeType(t); dmd::builtinTypeInfo(t); } diff --git a/compiler/test/runnable/test23650.d b/compiler/test/runnable/test23650.d deleted file mode 100644 index 3ce8f5f0759b..000000000000 --- a/compiler/test/runnable/test23650.d +++ /dev/null @@ -1,13 +0,0 @@ -// https://issues.dlang.org/show_bug.cgi?id=23650 - -__gshared int x; - -void main() -{ - - static assert(__traits(compiles, - { - struct S { int *p = &x; } - auto t = typeid(S); - })); -} diff --git a/compiler/test/runnable/test24599.d b/compiler/test/runnable/test24599.d new file mode 100644 index 000000000000..257773846ebf --- /dev/null +++ b/compiler/test/runnable/test24599.d @@ -0,0 +1,24 @@ +module mod; + +struct Variable +{ + size_t toHash() const { return 0; } +} + +enum hasInoutConstruction(T) = __traits(compiles, { struct S { T a; } }); + +struct Algebraic(T) +{ + static if (hasInoutConstruction!T) + { + } +} + +Algebraic!Variable foo(); + +struct S +{ + Variable[] symbols; +} + +void main() {} From 6d3ee445504c61bf7c531420b3f77c34b7a9702e Mon Sep 17 00:00:00 2001 From: "Richard (Rikki) Andrew Cattermole" Date: Mon, 8 Jul 2024 14:00:50 +1200 Subject: [PATCH 03/15] Reorganize backend build files to match target and make more similar per line (#16672) --- compiler/src/build.d | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/compiler/src/build.d b/compiler/src/build.d index 8516d01e150c..3b1f7cdc2de9 100755 --- a/compiler/src/build.d +++ b/compiler/src/build.d @@ -1581,10 +1581,12 @@ auto sourceFiles() cparse.d "), backendHeaders: fileArray(env["C"], " - cc.d cdef.d cgcv.d code.d cv4.d dt.d el.d global.d - obj.d oper.d rtlsym.d x86/code_x86.d iasm.d codebuilder.d - ty.d type.d mach.d mscoff.d dwarf.d dwarf2.d x86/xmm.d - dlist.d melf.d + cc.d cdef.d cgcv.d code.d dt.d el.d global.d + obj.d oper.d rtlsym.d iasm.d codebuilder.d + ty.d type.d dlist.d + dwarf.d dwarf2.d cv4.d + melf.d mscoff.d mach.d + x86/code_x86.d x86/xmm.d "), }; foreach (member; __traits(allMembers, DmdSources)) @@ -1620,13 +1622,16 @@ auto sourceFiles() "), backend: fileArray(env["C"], " bcomplex.d evalu8.d divcoeff.d dvec.d go.d gsroa.d glocal.d gdag.d gother.d gflow.d - dout.d inliner.d - gloop.d cgelem.d cgcs.d ee.d x86/cod4.d x86/cod5.d eh.d x86/nteh.d blockopt.d mem.d cg.d x86/cgreg.d - dtype.d debugprint.d fp.d symbol.d symtab.d elem.d dcode.d cgsched.d x86/cg87.d x86/cgxmm.d x86/cgcod.d x86/cod1.d x86/cod2.d - x86/cod3.d cv8.d dcgcv.d pdata.d util2.d var.d backconfig.d drtlsym.d dwarfeh.d ptrntab.d - dvarstats.d dwarfdbginf.d cgen.d goh.d barray.d cgcse.d elpicpie.d - machobj.d elfobj.d mscoffobj.d filespec.d aarray.d x86/disasm86.d arm/disasmarm.d arm/instr.d - arm/cod1.d arm/cod2.d arm/cod3.d arm/cod4.d + dout.d inliner.d eh.d filespec.d cgobj.d aarray.d + gloop.d compress.d cgelem.d cgcs.d ee.d blockopt.d mem.d cg.d + dtype.d debugprint.d fp.d symbol.d symtab.d elem.d dcode.d cgsched.d + pdata.d util2.d var.d backconfig.d drtlsym.d ptrntab.d + dvarstats.d cgen.d goh.d barray.d cgcse.d elpicpie.d + dwarfeh.d dwarfdbginf.d cv8.d dcgcv.d + machobj.d elfobj.d mscoffobj.d + x86/nteh.d x86/cgreg.d x86/cg87.d x86/cgxmm.d x86/disasm86.d + x86/cgcod.d x86/cod1.d x86/cod2.d x86/cod3.d x86/cod4.d x86/cod5.d + arm/disasmarm.d arm/instr.d " ), }; From 255b676071f6cf45e9ec7472b3127159f56f054e Mon Sep 17 00:00:00 2001 From: Dennis Date: Tue, 16 Jul 2024 13:22:02 +0200 Subject: [PATCH 04/15] Remove redundant suggestions on linker errors (#16711) --- compiler/src/dmd/link.d | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/src/dmd/link.d b/compiler/src/dmd/link.d index 7ac403ba942c..0be14612365f 100644 --- a/compiler/src/dmd/link.d +++ b/compiler/src/dmd/link.d @@ -1426,8 +1426,8 @@ void parseLinkerOutput(const(char)[] linkerOutput, ErrorSink eSink) return s; } - bool missingSymbols = false; - bool missingDfunction = false; + bool missingCSymbols = false; + bool missingDsymbols = false; bool missingMain = false; void missingSymbol(const(char)[] name, const(char)[] referencedFrom) @@ -1437,11 +1437,12 @@ void parseLinkerOutput(const(char)[] linkerOutput, ErrorSink eSink) name = name[1 .. $]; // MS LINK prepends underscore to the existing one auto sym = demangle(name); - missingSymbols = true; if (sym == "main") missingMain = true; - if (sym != name) - missingDfunction = true; + else if (sym != name) + missingDsymbols = true; + else + missingCSymbols = true; eSink.error(Loc.initial, "undefined reference to `%.*s`", cast(int) sym.length, sym.ptr); if (referencedFrom.length > 0) @@ -1513,10 +1514,9 @@ void parseLinkerOutput(const(char)[] linkerOutput, ErrorSink eSink) if (missingMain) eSink.errorSupplemental(Loc.initial, "perhaps define a `void main() {}` function or use the `-main` switch"); - - if (missingDfunction) + else if (missingDsymbols) eSink.errorSupplemental(Loc.initial, "perhaps `.d` files need to be added on the command line, or use `-i` to compile imports"); - else if (missingSymbols) + else if (missingCSymbols) eSink.errorSupplemental(Loc.initial, "perhaps a library needs to be added with the `-L` flag or `pragma(lib, ...)`"); } From c6390bb45cedae3c95d682f64c6dd73bf98352f6 Mon Sep 17 00:00:00 2001 From: Dennis Date: Mon, 22 Jul 2024 10:00:31 +0200 Subject: [PATCH 05/15] Fix bugzilla 24337 - Segfault when printing an int[] cast from a string (#16729) --- compiler/src/dmd/dsymbolsem.d | 2 +- compiler/src/dmd/expressionsem.d | 36 ++++++++++++++++-------- compiler/src/dmd/pragmasem.d | 29 ++++++------------- compiler/src/dmd/statementsem.d | 2 +- compiler/src/dmd/typesem.d | 2 +- compiler/test/compilable/staticforeach.d | 4 +-- compiler/test/compilable/test24337.d | 11 ++++++++ compiler/test/runnable/test13613.d | 2 +- 8 files changed, 50 insertions(+), 38 deletions(-) create mode 100644 compiler/test/compilable/test24337.d diff --git a/compiler/src/dmd/dsymbolsem.d b/compiler/src/dmd/dsymbolsem.d index 76fe6ca490b0..cb8df89596f6 100644 --- a/compiler/src/dmd/dsymbolsem.d +++ b/compiler/src/dmd/dsymbolsem.d @@ -1832,7 +1832,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor { //printf("MixinDeclaration::compileIt(loc = %d) %s\n", cd.loc.linnum, cd.exp.toChars()); OutBuffer buf; - if (expressionsToString(buf, sc, cd.exps)) + if (expressionsToString(buf, sc, cd.exps, cd.loc, null, true)) return null; const errors = global.errors; diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index f1e30ad825f9..3e4a2fdd4dac 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -140,16 +140,26 @@ private bool isNeedThisScope(Scope* sc, Declaration d) * buf = append generated string to buffer * sc = context * exps = array of Expressions + * loc = location of the pragma / mixin where this conversion was requested, for supplemental error + * fmt = format string for supplemental error. May contain 1 `%s` which prints the faulty expression + * expandTuples = whether tuples should be expanded rather than printed as tuple syntax * Returns: * true on error */ -bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps) +bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps, + Loc loc, const(char)* fmt, bool expandTuples) { if (!exps) return false; foreach (ex; *exps) { + bool error() + { + if (loc != Loc.initial && fmt) + errorSupplemental(loc, fmt, ex.toChars()); + return true; + } if (!ex) continue; auto sc2 = sc.startCTFE(); @@ -162,15 +172,16 @@ bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps) // allowed to contain types as well as expressions auto e4 = ctfeInterpretForPragmaMsg(e3); if (!e4 || e4.op == EXP.error) - return true; + return error(); // expand tuple - if (auto te = e4.isTupleExp()) - { - if (expressionsToString(buf, sc, te.exps)) - return true; - continue; - } + if (expandTuples) + if (auto te = e4.isTupleExp()) + { + if (expressionsToString(buf, sc, te.exps, loc, fmt, true)) + return error(); + continue; + } // char literals exp `.toStringExp` return `null` but we cant override it // because in most contexts we don't want the conversion to succeed. IntegerExp ie = e4.isIntegerExp(); @@ -181,9 +192,11 @@ bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps) e4 = new ArrayLiteralExp(ex.loc, tsa, ie); } - if (StringExp se = e4.toStringExp()) + StringExp se = e4.toStringExp(); + + if (se && se.type.nextOf().ty.isSomeChar) buf.writestring(se.toUTF8(sc).peekString()); - else + else if (!(se && se.len == 0)) // don't print empty array literal `[]` buf.writestring(e4.toString()); } return false; @@ -336,6 +349,7 @@ StringExp toUTF8(StringExp se, Scope* sc) Expression e = castTo(se, sc, Type.tchar.arrayOf()); e = e.optimize(WANTvalue); auto result = e.isStringExp(); + assert(result); assert(result.sz == 1); return result; } @@ -7694,7 +7708,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor private Expression compileIt(MixinExp exp, Scope *sc) { OutBuffer buf; - if (expressionsToString(buf, sc, exp.exps)) + if (expressionsToString(buf, sc, exp.exps, exp.loc, null, true)) return null; uint errors = global.errors; diff --git a/compiler/src/dmd/pragmasem.d b/compiler/src/dmd/pragmasem.d index 679033c410da..405b7654ffa6 100644 --- a/compiler/src/dmd/pragmasem.d +++ b/compiler/src/dmd/pragmasem.d @@ -557,32 +557,19 @@ private uint setMangleOverride(Dsymbol s, const(char)[] sym) private bool pragmaMsgSemantic(Loc loc, Scope* sc, Expressions* args) { import dmd.tokens; + import dmd.common.outbuffer; if (!args) return true; - foreach (arg; *args) - { - sc = sc.startCTFE(); - auto e = arg.expressionSemantic(sc); - e = resolveProperties(sc, e); - sc = sc.endCTFE(); - // pragma(msg) is allowed to contain types as well as expressions - e = ctfeInterpretForPragmaMsg(e); - if (e.op == EXP.error) - { - errorSupplemental(loc, "while evaluating `pragma(msg, %s)`", arg.toChars()); - return false; - } - if (auto se = e.toStringExp()) - { - const slice = se.toUTF8(sc).peekString(); - fprintf(stderr, "%.*s", cast(int)slice.length, slice.ptr); - } - else - fprintf(stderr, "%s", e.toChars()); + OutBuffer buf; + if (expressionsToString(buf, sc, args, loc, "while evaluating `pragma(msg, %s)`", false)) + return false; + else + { + buf.writestring("\n"); + fprintf(stderr, buf.extractChars); } - fprintf(stderr, "\n"); return true; } diff --git a/compiler/src/dmd/statementsem.d b/compiler/src/dmd/statementsem.d index a73bd5ebdf3a..78dd105f49aa 100644 --- a/compiler/src/dmd/statementsem.d +++ b/compiler/src/dmd/statementsem.d @@ -4803,7 +4803,7 @@ private Statements* flatten(Statement statement, Scope* sc) OutBuffer buf; - if (expressionsToString(buf, sc, cs.exps)) + if (expressionsToString(buf, sc, cs.exps, cs.loc, null, true)) return errorStatements(); const errors = global.errors; diff --git a/compiler/src/dmd/typesem.d b/compiler/src/dmd/typesem.d index f947dd33174e..bfc12a066966 100644 --- a/compiler/src/dmd/typesem.d +++ b/compiler/src/dmd/typesem.d @@ -7853,7 +7853,7 @@ Expression getMaxMinValue(EnumDeclaration ed, const ref Loc loc, Identifier id) RootObject compileTypeMixin(TypeMixin tm, ref const Loc loc, Scope* sc) { OutBuffer buf; - if (expressionsToString(buf, sc, tm.exps)) + if (expressionsToString(buf, sc, tm.exps, tm.loc, null, true)) return null; const errors = global.errors; diff --git a/compiler/test/compilable/staticforeach.d b/compiler/test/compilable/staticforeach.d index ce9eb74a1ef0..5b23446f89b8 100644 --- a/compiler/test/compilable/staticforeach.d +++ b/compiler/test/compilable/staticforeach.d @@ -117,8 +117,8 @@ foo2 T2 TestStaticForeach2 issue22007 -1 2 '3' -2 3 '4' +1 2 3 +2 3 4 0 1 1 2 2 3 diff --git a/compiler/test/compilable/test24337.d b/compiler/test/compilable/test24337.d new file mode 100644 index 000000000000..a31f665f3527 --- /dev/null +++ b/compiler/test/compilable/test24337.d @@ -0,0 +1,11 @@ +/* +TEST_OUTPUT: +--- +"ab"w x"11223344556677" +--- +*/ +// https://issues.dlang.org/show_bug.cgi?id=24337 + +immutable ushort[] y = cast(immutable ushort[]) "ab"w; +immutable ulong[] z = x"00 11 22 33 44 55 66 77"; +pragma(msg, y, " ", z); diff --git a/compiler/test/runnable/test13613.d b/compiler/test/runnable/test13613.d index ea57df4e9159..1382f00a1780 100644 --- a/compiler/test/runnable/test13613.d +++ b/compiler/test/runnable/test13613.d @@ -4,9 +4,9 @@ /* TEST_OUTPUT: --- -CT x.offsetof = < CT y.offsetof = < 0 > y +CT x.offsetof = < 0 > x --- */ From 24b7c415efbf96c251113cbc1813fcaee1992f06 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 21 Jul 2024 16:33:56 +0200 Subject: [PATCH 06/15] Add BitFieldStyle.Gcc_Clang_ARM Required for 32-bit ARM, and non-Apple 64-bit ARM targets. The only difference to `Gcc_Clang` is that anonymous and 0-length bit-fields do contribute to the aggregate alignment. Caught by existing proper C interop tests in runnable_cxx/testbitfields.d on such targets. The hardcoded bad tests in runnable/{bitfieldsposix64.c,dbitfieldsposix64.d} however now fail after the fix, on such targets again. --- compiler/src/dmd/dsymbolsem.d | 82 ++++++++++++++++------------------- compiler/src/dmd/frontend.h | 1 + compiler/src/dmd/target.d | 3 ++ compiler/src/dmd/target.h | 3 ++ compiler/src/dmd/todt.d | 1 + 5 files changed, 45 insertions(+), 45 deletions(-) diff --git a/compiler/src/dmd/dsymbolsem.d b/compiler/src/dmd/dsymbolsem.d index cb8df89596f6..ebb400e0bb48 100644 --- a/compiler/src/dmd/dsymbolsem.d +++ b/compiler/src/dmd/dsymbolsem.d @@ -7113,12 +7113,23 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor error(bfd.loc, "bit field width %d is larger than type", bfd.fieldWidth); const style = target.c.bitFieldStyle; + if (style != TargetC.BitFieldStyle.MS && + style != TargetC.BitFieldStyle.Gcc_Clang && + style != TargetC.BitFieldStyle.Gcc_Clang_ARM) + { + assert(0, "unsupported bit-field style"); + } + + const isMicrosoftStyle = style == TargetC.BitFieldStyle.MS; + const contributesToAggregateAlignment = !anon || style != TargetC.BitFieldStyle.Gcc_Clang; void startNewField() { if (log) printf("startNewField()\n"); uint alignsize; - if (style == TargetC.BitFieldStyle.Gcc_Clang) + if (isMicrosoftStyle) + alignsize = memsize; // not memalignsize + else { if (bfd.fieldWidth > 32) alignsize = memalignsize; @@ -7129,15 +7140,13 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor else alignsize = 1; } - else - alignsize = memsize; // not memalignsize uint dummy; bfd.offset = placeField(bfd.loc, fieldState.offset, memsize, alignsize, bfd.alignment, ad.structsize, - (anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? dummy : ad.alignsize, + contributesToAggregateAlignment ? ad.alignsize : dummy, isunion); fieldState.inFlight = true; @@ -7146,45 +7155,30 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor fieldState.fieldSize = memsize; } - if (style == TargetC.BitFieldStyle.Gcc_Clang) + if (ad.alignsize == 0) + ad.alignsize = 1; + if (!isMicrosoftStyle && contributesToAggregateAlignment && ad.alignsize < memalignsize) + ad.alignsize = memalignsize; + + if (bfd.fieldWidth == 0) { - if (bfd.fieldWidth == 0) + if (!isMicrosoftStyle && !isunion) { - if (!isunion) - { - // Use type of zero width field to align to next field - fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1); - ad.structsize = fieldState.offset; - } - - fieldState.inFlight = false; - return; + // Use type of zero width field to align to next field + fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1); + ad.structsize = fieldState.offset; } - - if (ad.alignsize == 0) - ad.alignsize = 1; - if (!anon && - ad.alignsize < memalignsize) - ad.alignsize = memalignsize; - } - else if (style == TargetC.BitFieldStyle.MS) - { - if (ad.alignsize == 0) - ad.alignsize = 1; - if (bfd.fieldWidth == 0) + else if (isMicrosoftStyle && fieldState.inFlight && !isunion) { - if (fieldState.inFlight && !isunion) - { - // documentation says align to next int - //const alsz = cast(uint)Type.tint32.size(); - const alsz = memsize; // but it really does this - fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1); - ad.structsize = fieldState.offset; - } - - fieldState.inFlight = false; - return; + // documentation says align to next int + //const alsz = cast(uint)Type.tint32.size(); + const alsz = memsize; // but it really does this + fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1); + ad.structsize = fieldState.offset; } + + fieldState.inFlight = false; + return; } if (!fieldState.inFlight) @@ -7192,7 +7186,7 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor //printf("not in flight\n"); startNewField(); } - else if (style == TargetC.BitFieldStyle.Gcc_Clang) + else if (!isMicrosoftStyle) { // If the bit-field spans more units of alignment than its type // and is at the alignment boundary, start a new field at the @@ -7217,7 +7211,7 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor } } } - else if (style == TargetC.BitFieldStyle.MS) + else { if (memsize != fieldState.fieldSize || fieldState.bitOffset + bfd.fieldWidth > fieldState.fieldSize * 8) @@ -7226,14 +7220,14 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor startNewField(); } } - else - assert(0); bfd.offset = fieldState.fieldOffset; bfd.bitOffset = fieldState.bitOffset; const pastField = bfd.bitOffset + bfd.fieldWidth; - if (style == TargetC.BitFieldStyle.Gcc_Clang) + if (isMicrosoftStyle) + fieldState.fieldSize = memsize; + else { auto size = (pastField + 7) / 8; fieldState.fieldSize = size; @@ -7247,8 +7241,6 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor else ad.structsize = bfd.offset + size; } - else - fieldState.fieldSize = memsize; //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize); //print(fieldState); diff --git a/compiler/src/dmd/frontend.h b/compiler/src/dmd/frontend.h index 677373f461f7..4d4f0be6fd7f 100644 --- a/compiler/src/dmd/frontend.h +++ b/compiler/src/dmd/frontend.h @@ -5892,6 +5892,7 @@ struct TargetC final Unspecified = 0u, MS = 1u, Gcc_Clang = 2u, + Gcc_Clang_ARM = 3u, }; bool crtDestructorsSupported; diff --git a/compiler/src/dmd/target.d b/compiler/src/dmd/target.d index 0495dba1a6c5..4ac8befed726 100644 --- a/compiler/src/dmd/target.d +++ b/compiler/src/dmd/target.d @@ -1392,6 +1392,9 @@ struct TargetC /// https://docs.microsoft.com/en-us/cpp/c-language/c-bit-fields?view=msvc-160 /// https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160 Gcc_Clang, /// gcc and clang + Gcc_Clang_ARM, /// Like `Gcc_Clang`, except that anonymous and 0-length bit fields contribute + /// to the aggregate alignment. Used for 32 & 64 bit ARM targets, except for + /// Apple ARM64. } bool crtDestructorsSupported = true; /// Not all platforms support crt_destructor ubyte boolsize; /// size of a C `_Bool` type diff --git a/compiler/src/dmd/target.h b/compiler/src/dmd/target.h index 2284b8322e7b..252783285a31 100644 --- a/compiler/src/dmd/target.h +++ b/compiler/src/dmd/target.h @@ -65,6 +65,9 @@ struct TargetC // https://docs.microsoft.com/en-us/cpp/c-language/c-bit-fields?view=msvc-160 // https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160 Gcc_Clang, // gcc and clang + Gcc_Clang_ARM, // Like `Gcc_Clang`, except that anonymous and 0-length bit fields contribute + // to the aggregate alignment. Used for 32 & 64 bit ARM targets, except for + // Apple ARM64. }; uint8_t crtDestructorsSupported; // Not all platforms support crt_destructor diff --git a/compiler/src/dmd/todt.d b/compiler/src/dmd/todt.d index 667cd198cac5..74aa131ed311 100644 --- a/compiler/src/dmd/todt.d +++ b/compiler/src/dmd/todt.d @@ -956,6 +956,7 @@ private void membersToDt(AggregateDeclaration ad, ref DtBuilder dtb, switch (target.c.bitFieldStyle) { case TargetC.BitFieldStyle.Gcc_Clang: + case TargetC.BitFieldStyle.Gcc_Clang_ARM: bitFieldSize = (bf.bitOffset + bf.fieldWidth + 7) / 8; break; From 203c242d56d08284f2d9c60e884bee36529a9900 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Mon, 22 Jul 2024 17:09:41 +0200 Subject: [PATCH 07/15] [refactor to `TargetC.contributesToAggregateAlignment(BitFieldDeclaration)` hook] --- compiler/src/dmd/dsymbolsem.d | 8 ++------ compiler/src/dmd/frontend.h | 2 +- compiler/src/dmd/target.d | 23 ++++++++++++++++++++--- compiler/src/dmd/target.h | 6 +++--- compiler/src/dmd/todt.d | 1 - 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/compiler/src/dmd/dsymbolsem.d b/compiler/src/dmd/dsymbolsem.d index ebb400e0bb48..e7e054930cc1 100644 --- a/compiler/src/dmd/dsymbolsem.d +++ b/compiler/src/dmd/dsymbolsem.d @@ -7113,15 +7113,11 @@ private extern(C++) class SetFieldOffsetVisitor : Visitor error(bfd.loc, "bit field width %d is larger than type", bfd.fieldWidth); const style = target.c.bitFieldStyle; - if (style != TargetC.BitFieldStyle.MS && - style != TargetC.BitFieldStyle.Gcc_Clang && - style != TargetC.BitFieldStyle.Gcc_Clang_ARM) - { + if (style != TargetC.BitFieldStyle.MS && style != TargetC.BitFieldStyle.Gcc_Clang) assert(0, "unsupported bit-field style"); - } const isMicrosoftStyle = style == TargetC.BitFieldStyle.MS; - const contributesToAggregateAlignment = !anon || style != TargetC.BitFieldStyle.Gcc_Clang; + const contributesToAggregateAlignment = target.c.contributesToAggregateAlignment(bfd); void startNewField() { diff --git a/compiler/src/dmd/frontend.h b/compiler/src/dmd/frontend.h index 4d4f0be6fd7f..2654e33a54e4 100644 --- a/compiler/src/dmd/frontend.h +++ b/compiler/src/dmd/frontend.h @@ -5892,7 +5892,6 @@ struct TargetC final Unspecified = 0u, MS = 1u, Gcc_Clang = 2u, - Gcc_Clang_ARM = 3u, }; bool crtDestructorsSupported; @@ -5905,6 +5904,7 @@ struct TargetC final uint8_t wchar_tsize; Runtime runtime; BitFieldStyle bitFieldStyle; + bool contributesToAggregateAlignment(BitFieldDeclaration* bfd); TargetC() : crtDestructorsSupported(true), boolsize(), diff --git a/compiler/src/dmd/target.d b/compiler/src/dmd/target.d index 4ac8befed726..da06609cba34 100644 --- a/compiler/src/dmd/target.d +++ b/compiler/src/dmd/target.d @@ -1373,6 +1373,8 @@ extern (C++) struct Target */ struct TargetC { + import dmd.declaration : BitFieldDeclaration; + enum Runtime : ubyte { Unspecified, @@ -1392,9 +1394,6 @@ struct TargetC /// https://docs.microsoft.com/en-us/cpp/c-language/c-bit-fields?view=msvc-160 /// https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160 Gcc_Clang, /// gcc and clang - Gcc_Clang_ARM, /// Like `Gcc_Clang`, except that anonymous and 0-length bit fields contribute - /// to the aggregate alignment. Used for 32 & 64 bit ARM targets, except for - /// Apple ARM64. } bool crtDestructorsSupported = true; /// Not all platforms support crt_destructor ubyte boolsize; /// size of a C `_Bool` type @@ -1465,6 +1464,24 @@ struct TargetC crtDestructorsSupported = false; } } + + /** + * Indicates whether the specified bit-field contributes to the alignment + * of the containing aggregate. + * E.g., (not all) ARM ABIs do NOT ignore anonymous (incl. 0-length) + * bit-fields. + */ + extern (C++) bool contributesToAggregateAlignment(BitFieldDeclaration bfd) + { + if (bitFieldStyle == BitFieldStyle.MS) + return true; + if (bitFieldStyle == BitFieldStyle.Gcc_Clang) + { + // sufficient for DMD's currently supported architectures + return !bfd.isAnonymous(); + } + assert(0); + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/compiler/src/dmd/target.h b/compiler/src/dmd/target.h index 252783285a31..1a9837ff4c70 100644 --- a/compiler/src/dmd/target.h +++ b/compiler/src/dmd/target.h @@ -16,6 +16,7 @@ #include "globals.h" #include "tokens.h" +class BitFieldDeclaration; class ClassDeclaration; class Dsymbol; class Expression; @@ -65,9 +66,6 @@ struct TargetC // https://docs.microsoft.com/en-us/cpp/c-language/c-bit-fields?view=msvc-160 // https://docs.microsoft.com/en-us/cpp/cpp/cpp-bit-fields?view=msvc-160 Gcc_Clang, // gcc and clang - Gcc_Clang_ARM, // Like `Gcc_Clang`, except that anonymous and 0-length bit fields contribute - // to the aggregate alignment. Used for 32 & 64 bit ARM targets, except for - // Apple ARM64. }; uint8_t crtDestructorsSupported; // Not all platforms support crt_destructor @@ -80,6 +78,8 @@ struct TargetC uint8_t wchar_tsize; // size of a C 'wchar_t' type Runtime runtime; BitFieldStyle bitFieldStyle; // different C compilers do it differently + + bool contributesToAggregateAlignment(BitFieldDeclaration *bfd); }; struct TargetCPP diff --git a/compiler/src/dmd/todt.d b/compiler/src/dmd/todt.d index 74aa131ed311..667cd198cac5 100644 --- a/compiler/src/dmd/todt.d +++ b/compiler/src/dmd/todt.d @@ -956,7 +956,6 @@ private void membersToDt(AggregateDeclaration ad, ref DtBuilder dtb, switch (target.c.bitFieldStyle) { case TargetC.BitFieldStyle.Gcc_Clang: - case TargetC.BitFieldStyle.Gcc_Clang_ARM: bitFieldSize = (bf.bitOffset + bf.fieldWidth + 7) / 8; break; From fa4083d0a7700533cad9eeacb6984d580775462f Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Mon, 5 Aug 2024 18:46:57 +0300 Subject: [PATCH 08/15] Fix Bugzilla Issue 24687 - [REG2.110] Cannot cast string-imports to select overload anymore --- compiler/src/dmd/dcast.d | 2 +- compiler/test/compilable/import_exp.d | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/compiler/src/dmd/dcast.d b/compiler/src/dmd/dcast.d index f54484f981ea..34b120b34125 100644 --- a/compiler/src/dmd/dcast.d +++ b/compiler/src/dmd/dcast.d @@ -705,7 +705,7 @@ MATCH implicitConvTo(Expression e, Type t) return MATCH.nomatch; m = MATCH.constant; } - if (e.hexString && tn.isIntegral && (tn.size == e.sz || (!e.committed && (e.len % tn.size) == 0))) + if (e.type != t && e.hexString && tn.isIntegral && (tn.size == e.sz || (!e.committed && (e.len % tn.size) == 0))) { m = MATCH.convert; return m; diff --git a/compiler/test/compilable/import_exp.d b/compiler/test/compilable/import_exp.d index 014d0f65f6f9..d29fc67ed66e 100644 --- a/compiler/test/compilable/import_exp.d +++ b/compiler/test/compilable/import_exp.d @@ -34,3 +34,11 @@ enum expectedStart = "module imports.imp16088;"; immutable ubyte[] s0 = import("imp16088.d"); static assert(s0[0 .. expectedStart.length] == "module imports.imp16088;"); + +// https://issues.dlang.org/show_bug.cgi?id=24687 + +void foo(string path); +void foo(const(ubyte[]) data); + +void bar1() { foo(import("imp16088.d")); } // matches both +void bar2() { foo(cast(const(ubyte[])) import("imp16088.d")); } // matches both! From 0521685c2ed67f0c67a787cc0aef508fac5860e8 Mon Sep 17 00:00:00 2001 From: Dennis Date: Tue, 13 Aug 2024 23:23:09 +0200 Subject: [PATCH 09/15] Also make deprecationSupplemental adhere to error limit (#16779) Co-authored-by: Dennis Korpel --- compiler/src/dmd/errors.d | 7 +++++-- compiler/test/compilable/deprecationlimit.d | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/src/dmd/errors.d b/compiler/src/dmd/errors.d index 5ff9a05ff868..6c1584998772 100644 --- a/compiler/src/dmd/errors.d +++ b/compiler/src/dmd/errors.d @@ -570,8 +570,11 @@ extern (C++) void verrorReportSupplemental(const ref Loc loc, const(char)* forma goto case ErrorKind.error; else if (global.params.useDeprecated == DiagnosticReporting.inform && !global.gag) { - info.headerColor = Classification.deprecation; - verrorPrint(format, ap, info); + if (global.params.v.errorLimit == 0 || global.deprecations <= global.params.v.errorLimit) + { + info.headerColor = Classification.deprecation; + verrorPrint(format, ap, info); + } } break; diff --git a/compiler/test/compilable/deprecationlimit.d b/compiler/test/compilable/deprecationlimit.d index dcdc9e118ca5..8ee7ab650fbf 100644 --- a/compiler/test/compilable/deprecationlimit.d +++ b/compiler/test/compilable/deprecationlimit.d @@ -18,5 +18,5 @@ void main() f(); f(); f(); - f(); + static assert("1"); // also surpress deprecationSupplemental } From 0527e66f09fdca60e833f4c035ad9e78de94c870 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Tue, 13 Aug 2024 22:29:43 +0200 Subject: [PATCH 10/15] Fix bugzilla 24699 - [REG2.108] No short-circuit evaluation of mixing template bool argument --- compiler/src/dmd/dtemplate.d | 6 ++++++ compiler/test/compilable/compile1.d | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/compiler/src/dmd/dtemplate.d b/compiler/src/dmd/dtemplate.d index 37ddbd27a5aa..3f1a4bfb27cb 100644 --- a/compiler/src/dmd/dtemplate.d +++ b/compiler/src/dmd/dtemplate.d @@ -4505,9 +4505,15 @@ extern (C++) class TemplateInstance : ScopeDsymbol // The arguments are not treated as part of a default argument, // because they are evaluated at compile time. + const inCondition = !!(sc.flags & SCOPE.condition); + // For master branch: const inCondition = sc.condition; sc = sc.push(); sc.inDefaultArg = false; + // https://issues.dlang.org/show_bug.cgi?id=24699 + sc.flags |= SCOPE.condition * inCondition; + // For master branch: sc.condition = inCondition; + for (size_t j = 0; j < tiargs.length; j++) { RootObject o = (*tiargs)[j]; diff --git a/compiler/test/compilable/compile1.d b/compiler/test/compilable/compile1.d index 4678eb533864..676108f68cfa 100644 --- a/compiler/test/compilable/compile1.d +++ b/compiler/test/compilable/compile1.d @@ -623,6 +623,11 @@ static assert (__traits(compiles, false && error) == false); int f11042a3()() if (__traits(compiles, true || error) == false) { return 0; } enum x11042a3 = f11042a3(); int f11042b3()() if (__traits(compiles, false && error) == false) { return 0; } enum x11042b3 = f11042b3(); +// https://issues.dlang.org/show_bug.cgi?id=24699 +enum T24699(bool cond) = cond; +enum b24699a = T24699!(true || error); +enum b24699b = T24699!(false && error); + /***************************************************/ // https://issues.dlang.org/show_bug.cgi?id=11554 From 38bdda7b3cc259469fc0cbc320889d8fcf922666 Mon Sep 17 00:00:00 2001 From: Dennis Date: Sat, 31 Aug 2024 15:20:35 +0200 Subject: [PATCH 11/15] Fix bugzilla 24731 - IFTI cannot handle integer expressions (#16822) --- compiler/src/dmd/dtemplate.d | 10 +++++----- compiler/src/dmd/expression.d | 2 +- compiler/test/runnable/ifti.d | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/compiler/src/dmd/dtemplate.d b/compiler/src/dmd/dtemplate.d index 3f1a4bfb27cb..b50fd444fe44 100644 --- a/compiler/src/dmd/dtemplate.d +++ b/compiler/src/dmd/dtemplate.d @@ -1695,7 +1695,9 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, ref TemplateParameters pa edim = s ? getValue(s) : getValue(e); } } - if (tp && tp.matchArg(sc, t.dim, i, ¶meters, dedtypes, null) || edim && edim.toInteger() == t.dim.toInteger()) + if ((tp && tp.matchArg(sc, t.dim, i, ¶meters, dedtypes, null)) || + (edim && edim.isIntegerExp() && edim.toInteger() == t.dim.toInteger()) + ) { result = deduceType(t.next, sc, tparam.nextOf(), parameters, dedtypes, wm); return; @@ -4505,14 +4507,12 @@ extern (C++) class TemplateInstance : ScopeDsymbol // The arguments are not treated as part of a default argument, // because they are evaluated at compile time. - const inCondition = !!(sc.flags & SCOPE.condition); - // For master branch: const inCondition = sc.condition; + const inCondition = sc.condition; sc = sc.push(); sc.inDefaultArg = false; // https://issues.dlang.org/show_bug.cgi?id=24699 - sc.flags |= SCOPE.condition * inCondition; - // For master branch: sc.condition = inCondition; + sc.condition = inCondition; for (size_t j = 0; j < tiargs.length; j++) { diff --git a/compiler/src/dmd/expression.d b/compiler/src/dmd/expression.d index 71a9dbb71c89..3c79b02caa02 100644 --- a/compiler/src/dmd/expression.d +++ b/compiler/src/dmd/expression.d @@ -455,7 +455,7 @@ extern (C++) abstract class Expression : ASTNode dinteger_t toInteger() { //printf("Expression %s\n", EXPtoString(op).ptr); - if (!type.isTypeError()) + if (!type || !type.isTypeError()) error(loc, "integer constant expression expected instead of `%s`", toChars()); return 0; } diff --git a/compiler/test/runnable/ifti.d b/compiler/test/runnable/ifti.d index 0c94946c8b36..293b8198d7fb 100644 --- a/compiler/test/runnable/ifti.d +++ b/compiler/test/runnable/ifti.d @@ -72,6 +72,20 @@ class Tst(TST, int v = 2) { class Y : Tst!(float) {} +// https://issues.dlang.org/show_bug.cgi?id=24731 +void test24731() +{ + static int solve(size_t N)(ref double[N+1][N]) + { + return N; + } + + double[3][2] m; + assert(solve(m) == 2); + assert(solve!2(m) == 2); +} + + void main() { Tst!(int) t = new Tst!(int); Y u = new Y; @@ -113,4 +127,5 @@ void main() { printf("%g\n", i); } + test24731(); } From dad89380e145f14d832bb93cc14a862e54badcfb Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Wed, 11 Sep 2024 16:04:08 +0300 Subject: [PATCH 12/15] Fix Bugzilla Issue 24760 - ICE on variadic after default argument --- compiler/src/dmd/typesem.d | 4 +++- compiler/test/compilable/test24760.d | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 compiler/test/compilable/test24760.d diff --git a/compiler/src/dmd/typesem.d b/compiler/src/dmd/typesem.d index bfc12a066966..c6306021c8cf 100644 --- a/compiler/src/dmd/typesem.d +++ b/compiler/src/dmd/typesem.d @@ -836,7 +836,9 @@ extern (D) MATCH callMatch(TypeFunction tf, Type tthis, ArgumentList argumentLis L1: if (parameterList.varargs == VarArg.typesafe && u + 1 == nparams) // if last varargs param { - auto trailingArgs = args[u .. $]; + Expression[] trailingArgs; + if (args.length >= u) + trailingArgs = args[u .. $]; if (auto vmatch = matchTypeSafeVarArgs(tf, p, trailingArgs, pMessage)) return vmatch < match ? vmatch : match; // Error message was already generated in `matchTypeSafeVarArgs` diff --git a/compiler/test/compilable/test24760.d b/compiler/test/compilable/test24760.d new file mode 100644 index 000000000000..7c84848a6fe9 --- /dev/null +++ b/compiler/test/compilable/test24760.d @@ -0,0 +1,4 @@ +// https://issues.dlang.org/show_bug.cgi?id=24760 + +long f(int e = 0, uint[] optional...) => optional.length; +long f0() => f(); // compiler segfaults From 6d07a4724d4806ec003d517f94bf7979b361674c Mon Sep 17 00:00:00 2001 From: Dennis Date: Thu, 3 Oct 2024 13:46:41 +0200 Subject: [PATCH 13/15] Fix bugzilla 24790 - -vcg-ast ICE on lowered assign exp (#16914) Co-authored-by: Dennis Korpel --- compiler/src/dmd/parse.d | 1 + compiler/test/compilable/vcg-ast-arraylength.d | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/compiler/src/dmd/parse.d b/compiler/src/dmd/parse.d index 4fbc3725a7dd..2285f9ae852a 100644 --- a/compiler/src/dmd/parse.d +++ b/compiler/src/dmd/parse.d @@ -9774,6 +9774,7 @@ immutable PREC[EXP.max + 1] precedence = EXP.assign : PREC.assign, EXP.construct : PREC.assign, EXP.blit : PREC.assign, + EXP.loweredAssignExp : PREC.assign, EXP.addAssign : PREC.assign, EXP.minAssign : PREC.assign, EXP.concatenateAssign : PREC.assign, diff --git a/compiler/test/compilable/vcg-ast-arraylength.d b/compiler/test/compilable/vcg-ast-arraylength.d index 8fdd7808f7b8..8c44421c6173 100644 --- a/compiler/test/compilable/vcg-ast-arraylength.d +++ b/compiler/test/compilable/vcg-ast-arraylength.d @@ -23,4 +23,9 @@ void main() static assert(is(typeof(a.length = 0) == size_t)); static assert(is(typeof(a.length = f.length = 0) == size_t)); + + // https://issues.dlang.org/show_bug.cgi?id=24790 + struct S { int[] payload; } + S s; + s.payload.length += 3; } From 9bd107812b73538436c73242fd13cda114a8b70a Mon Sep 17 00:00:00 2001 From: Dennis Date: Thu, 3 Oct 2024 13:47:19 +0200 Subject: [PATCH 14/15] Fix bugzilla 24764 - ICE when -vcg-ast prints imported invariant (#16917) Co-authored-by: Dennis Korpel --- compiler/src/dmd/hdrgen.d | 4 ++-- .../test/compilable/extra-files/vcg-ast.d.cg | 22 ++++++++++++++++++- .../test/compilable/imports/vcg_ast_import.d | 4 ++++ compiler/test/compilable/vcg-ast.d | 12 ++++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 compiler/test/compilable/imports/vcg_ast_import.d diff --git a/compiler/src/dmd/hdrgen.d b/compiler/src/dmd/hdrgen.d index e3f1dc283f70..18eac8f857eb 100644 --- a/compiler/src/dmd/hdrgen.d +++ b/compiler/src/dmd/hdrgen.d @@ -1858,9 +1858,9 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) if (stcToBuffer(buf, d.storage_class)) buf.writeByte(' '); buf.writestring("invariant"); - if(auto es = d.fbody.isExpStatement()) + auto es = d.fbody.isExpStatement(); + if (es && es.exp && es.exp.op == EXP.assert_) { - assert(es.exp && es.exp.op == EXP.assert_); buf.writestring(" ("); (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, hgs); buf.writestring(");"); diff --git a/compiler/test/compilable/extra-files/vcg-ast.d.cg b/compiler/test/compilable/extra-files/vcg-ast.d.cg index 9f36634bd05b..7cf31cb91264 100644 --- a/compiler/test/compilable/extra-files/vcg-ast.d.cg +++ b/compiler/test/compilable/extra-files/vcg-ast.d.cg @@ -100,6 +100,12 @@ void main() values(); return 0; } +import imports.vcg_ast_import; +template imported() +{ + import imported = imports.vcg_ast_import; +} +alias myImport = vcg_ast_import; R!int { struct _R @@ -126,6 +132,21 @@ mixin _d_cmain!(); } } } +imported!() +{ + import object; + struct O + { + invariant + { + } + invariant + { + __invariant0(); + } + } + +} RTInfo!(C) { enum immutable(void)* RTInfo = null; @@ -150,4 +171,3 @@ RTInfo!(_R) enum immutable(void)* RTInfo = null; } - diff --git a/compiler/test/compilable/imports/vcg_ast_import.d b/compiler/test/compilable/imports/vcg_ast_import.d new file mode 100644 index 000000000000..a2064c0d175b --- /dev/null +++ b/compiler/test/compilable/imports/vcg_ast_import.d @@ -0,0 +1,4 @@ +struct O +{ + invariant() {} +} diff --git a/compiler/test/compilable/vcg-ast.d b/compiler/test/compilable/vcg-ast.d index 4a7b8bc33c48..9197441affea 100644 --- a/compiler/test/compilable/vcg-ast.d +++ b/compiler/test/compilable/vcg-ast.d @@ -2,6 +2,7 @@ REQUIRED_ARGS: -vcg-ast -o- PERMUTE_ARGS: OUTPUT_FILES: compilable/vcg-ast.d.cg +EXTRA_FILES: imports/vcg_ast_import.d TEST_OUTPUT_FILE: extra-files/vcg-ast.d.cg */ @@ -63,3 +64,14 @@ void main() { values!wchar_t; } + +// https://issues.dlang.org/show_bug.cgi?id=24764 + +import imports.vcg_ast_import; + +template imported() +{ + import imported = imports.vcg_ast_import; +} + +alias myImport = imported!(); From fcb836021cd4e08325620bcc04befad9c4b859fc Mon Sep 17 00:00:00 2001 From: Dennis Date: Fri, 4 Oct 2024 01:47:09 +0200 Subject: [PATCH 15/15] =?UTF-8?q?Fix=20bugzilla=2024431=20-=20dmd=20-vcg-a?= =?UTF-8?q?st=20crashes=20printing=20failed=20template=20in=E2=80=A6=20(#1?= =?UTF-8?q?6916)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/src/dmd/hdrgen.d | 4 +- compiler/test/compilable/vcg_ast_compilable.d | 69 +++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 compiler/test/compilable/vcg_ast_compilable.d diff --git a/compiler/src/dmd/hdrgen.d b/compiler/src/dmd/hdrgen.d index 18eac8f857eb..8c4f0e4355c7 100644 --- a/compiler/src/dmd/hdrgen.d +++ b/compiler/src/dmd/hdrgen.d @@ -1720,10 +1720,10 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) //printf("FuncDeclaration::toCBuffer() '%s'\n", f.toChars()); if (stcToBuffer(buf, f.storage_class)) buf.writeByte(' '); + typeToBuffer(f.type, f.ident, buf, hgs); auto tf = f.type.isTypeFunction(); - typeToBuffer(tf, f.ident, buf, hgs); - if (hgs.hdrgen) + if (hgs.hdrgen && tf) { // if the return type is missing (e.g. ref functions or auto) // https://issues.dlang.org/show_bug.cgi?id=20090 diff --git a/compiler/test/compilable/vcg_ast_compilable.d b/compiler/test/compilable/vcg_ast_compilable.d new file mode 100644 index 000000000000..e84846dfbe18 --- /dev/null +++ b/compiler/test/compilable/vcg_ast_compilable.d @@ -0,0 +1,69 @@ +/* +REQUIRED_ARGS: -vcg-ast -o- +OUTPUT_FILES: compilable/vcg_ast_compilable.d.cg +TEST_OUTPUT: +--- +=== compilable/vcg_ast_compilable.d.cg +import object; +auto binaryFun(E)(E b) +{ + return 'a' == b; +} +void find(Element)(Element needle) if (is(typeof(binaryFun(needle)))) +{ +} +void find()(string needle) +{ +} +void splitter() +{ + find(3); + find(""); +} +binaryFun!int +{ + auto pure nothrow @nogc @safe bool binaryFun(int b) + { + return 97 == b; + } + +} +find!int +{ + pure nothrow @nogc @safe void find(int needle) + { + } + +} +binaryFun!string +{ + auto _error_ binaryFun + { + __error__ + } + +} +find!() +{ + pure nothrow @nogc @safe void find(string needle) + { + } + +} +--- +*/ + +// https://issues.dlang.org/show_bug.cgi?id=24431 +auto binaryFun(E)(E b) +{ + return 'a' == b; +} + +void find(Element)(Element needle) if (is(typeof(binaryFun(needle)))) { } +void find()(string needle) { } + +void splitter() +{ + find!int(3); + find!()(""); +}