From fc405deb41fb90e25c6859acd657a56f79ecd2eb Mon Sep 17 00:00:00 2001 From: shivaji Date: Tue, 24 Mar 2026 10:28:24 +0530 Subject: [PATCH 1/6] Fix Issue 21622: Ambiguous template without parentheses gives 'no effect' error --- compiler/src/dmd/sideeffect.d | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/compiler/src/dmd/sideeffect.d b/compiler/src/dmd/sideeffect.d index 2e579972d359..9661bfa39f5b 100644 --- a/compiler/src/dmd/sideeffect.d +++ b/compiler/src/dmd/sideeffect.d @@ -14,6 +14,8 @@ module dmd.sideeffect; import dmd.astenums; import dmd.declaration; import dmd.dscope; +import dmd.dsymbol; +import dmd.dtemplate; import dmd.errors; import dmd.expression; import dmd.expressionsem; @@ -294,6 +296,25 @@ bool discardValue(Expression e) // Assumption that error => no side effect case EXP.error: return true; + case EXP.overloadSet: + { + OverExp oe = cast(OverExp)e; + .error(e.loc, "`%s` matches multiple overloads", oe.vars.ident.toChars()); + return false; + } + case EXP.scope_: + { + ScopeExp se = cast(ScopeExp)e; + if (auto ti = se.sds.isTemplateInstance()) + { + if (ti.tempdecl && ti.tempdecl.isOverloadSet()) + { + .error(e.loc, "`%s` matches multiple overloads", ti.toChars()); + return false; + } + } + break; + } case EXP.variable: { VarDeclaration v = (cast(VarExp)e).var.isVarDeclaration(); From d5311bf92c8d05d2df93cc65a6606bb9c5d76073 Mon Sep 17 00:00:00 2001 From: shivaji Date: Tue, 24 Mar 2026 10:36:44 +0530 Subject: [PATCH 2/6] Add regression test for issue 21622 --- compiler/test/fail_compilation/issue21622.d | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 compiler/test/fail_compilation/issue21622.d diff --git a/compiler/test/fail_compilation/issue21622.d b/compiler/test/fail_compilation/issue21622.d new file mode 100644 index 000000000000..0c7ded405aa1 --- /dev/null +++ b/compiler/test/fail_compilation/issue21622.d @@ -0,0 +1,15 @@ +/* +REQUIRED_ARGS: +TEST_OUTPUT: +--- +fail_compilation/issue21622.d(14): Error: `issue21622.foo!0` matches multiple overloads +--- +*/ + +void foo(int i)() {} +void foo(int i)() {} + +void main() +{ + foo!0; +} From ba78e75e90b7a20ccbba705425c46aa86b1d3771 Mon Sep 17 00:00:00 2001 From: shivaji Date: Tue, 24 Mar 2026 10:52:42 +0530 Subject: [PATCH 3/6] Fix Issue 21294: Improve unhelpful error message with duplicate named argument in overload set --- compiler/src/dmd/funcsem.d | 77 +++++++++++++++------ compiler/test/fail_compilation/issue21294.d | 15 ++++ 2 files changed, 69 insertions(+), 23 deletions(-) create mode 100644 compiler/test/fail_compilation/issue21294.d diff --git a/compiler/src/dmd/funcsem.d b/compiler/src/dmd/funcsem.d index 31b6397ecf5a..4ca306d2fcc6 100644 --- a/compiler/src/dmd/funcsem.d +++ b/compiler/src/dmd/funcsem.d @@ -2015,18 +2015,20 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s, { if (!od && !td.overnext) { + if (checkNamedArgErrorAndReport(td, argumentList, loc)) + return null; + .error(loc, "%s `%s` is not callable using argument types `!(%s)%s`", td.kind(), td.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars()); - - checkNamedArgErrorAndReport(td, argumentList, loc); } else { + if (checkNamedArgErrorAndReport(td, argumentList, loc)) + return null; + .error(loc, "none of the overloads of %s `%s.%s` are callable using argument types `!(%s)%s`", td.kind(), td.parent.toPrettyChars(), td.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars()); - - checkNamedArgErrorAndReport(td, argumentList, loc); } @@ -2045,10 +2047,12 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s, if (od) { + if (checkNamedArgErrorAndReportOverload(od, argumentList, loc)) + return null; + .error(loc, "none of the overloads of `%s` are callable using argument types `!(%s)%s`", od.ident.toChars(), tiargsBuf.peekChars(), fargsBuf.peekChars()); - checkNamedArgErrorAndReportOverload(od, argumentList, loc); if (!global.gag || global.params.v.showGaggedErrors) printCandidates(loc, od, sc.isDeprecated()); return null; @@ -2185,11 +2189,13 @@ FuncDeclaration resolveFuncCall(Loc loc, Scope* sc, Dsymbol s, * td = template declaration to check * argumentList = arguments to check * loc = location for error reporting + * Returns: + * true if a primary error was reported */ -private void checkNamedArgErrorAndReport(TemplateDeclaration td, ArgumentList argumentList, Loc loc) +private bool checkNamedArgErrorAndReport(TemplateDeclaration td, ArgumentList argumentList, Loc loc) { if (!argumentList.hasArgNames()) - return; + return false; td.computeOneMember(); auto tf = td.onemember ? td.onemember.isFuncDeclaration() : null; if (tf && tf.type && tf.type.ty == Tfunction) @@ -2197,8 +2203,12 @@ private void checkNamedArgErrorAndReport(TemplateDeclaration td, ArgumentList ar OutBuffer buf; auto resolvedArgs = tf.type.isTypeFunction().resolveNamedArgs(argumentList, &buf); if (!resolvedArgs && buf.length) - .errorSupplemental(loc, "%s", buf.peekChars()); + { + .error(loc, "%s", buf.peekChars()); + return true; + } } + return false; } /****************************************** @@ -2207,35 +2217,56 @@ private void checkNamedArgErrorAndReport(TemplateDeclaration td, ArgumentList ar * od = overload declaration to check * argumentList = arguments to check * loc = location for error report + * Returns: + * true if a primary error was reported */ -private void checkNamedArgErrorAndReportOverload(Dsymbol od, ArgumentList argumentList, Loc loc) +private bool checkNamedArgErrorAndReportOverload(Dsymbol od, ArgumentList argumentList, Loc loc) { if (!argumentList.hasArgNames()) - return; + return false; + + const(char)[] commonError = null; + bool allSame = true; + bool anyError = false; - FuncDeclaration tf = null; overloadApply(od, (Dsymbol s) { - if (!tf) + TypeFunction tf = null; + if (auto fd = s.isFuncDeclaration()) + tf = fd.type.isTypeFunction(); + else if (auto td = s.isTemplateDeclaration()) + { + td.computeOneMember(); + if (td.onemember && td.onemember.isFuncDeclaration()) + tf = td.onemember.isFuncDeclaration().type.isTypeFunction(); + } + + if (tf) { - if (auto fd = s.isFuncDeclaration()) - tf = fd; - else if (auto td = s.isTemplateDeclaration()) + OutBuffer buf; + auto resolvedArgs = tf.resolveNamedArgs(argumentList, &buf); + if (!resolvedArgs && buf.length) + { + anyError = true; + const(char)[] currentError = buf.peekChars().toDString(); + if (commonError is null) + commonError = currentError; + else if (commonError != currentError) + allSame = false; + } + else { - td.computeOneMember(); - if (td.onemember) - tf = td.onemember.isFuncDeclaration(); + allSame = false; // This candidate matched (at least for named args) } } return 0; }); - if (tf && tf.type && tf.type.ty == Tfunction) + if (anyError && allSame && commonError !is null) { - OutBuffer buf; - auto resolvedArgs = tf.type.isTypeFunction().resolveNamedArgs(argumentList, &buf); - if (!resolvedArgs && buf.length) - .errorSupplemental(loc, "%s", buf.peekChars()); + .error(loc, "%s", commonError.ptr); + return true; } + return false; } /******************************************* diff --git a/compiler/test/fail_compilation/issue21294.d b/compiler/test/fail_compilation/issue21294.d new file mode 100644 index 000000000000..fa3faf9d66c6 --- /dev/null +++ b/compiler/test/fail_compilation/issue21294.d @@ -0,0 +1,15 @@ +/* +REQUIRED_ARGS: +TEST_OUTPUT: +--- +fail_compilation/issue21294.d(13): Error: parameter `a` assigned twice +--- +*/ + +void fun(int a) {} +void fun(int a, int b) {} + +void main() +{ + fun(a: 2, a: 4); +} From ffc57515470a7427abb335b31245f98e11a46252 Mon Sep 17 00:00:00 2001 From: shivaji Date: Tue, 24 Mar 2026 11:25:06 +0530 Subject: [PATCH 4/6] Fix compilation errors in sideeffect.d --- compiler/src/dmd/sideeffect.d | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/src/dmd/sideeffect.d b/compiler/src/dmd/sideeffect.d index 9661bfa39f5b..db2b66afac87 100644 --- a/compiler/src/dmd/sideeffect.d +++ b/compiler/src/dmd/sideeffect.d @@ -28,6 +28,7 @@ import dmd.init; import dmd.mtype; import dmd.tokens; import dmd.typesem; +import dmd.root.string : toDString; import dmd.visitor; import dmd.visitor.postorder; From 4ee23aa3b3bd89b5da454942efae65c4b8408a52 Mon Sep 17 00:00:00 2001 From: shivaji Date: Tue, 24 Mar 2026 11:25:18 +0530 Subject: [PATCH 5/6] Fix compilation errors in funcsem.d (strcmp and pointer fixes) --- compiler/src/dmd/funcsem.d | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/compiler/src/dmd/funcsem.d b/compiler/src/dmd/funcsem.d index 4ca306d2fcc6..cd6f1c438604 100644 --- a/compiler/src/dmd/funcsem.d +++ b/compiler/src/dmd/funcsem.d @@ -2225,7 +2225,7 @@ private bool checkNamedArgErrorAndReportOverload(Dsymbol od, ArgumentList argume if (!argumentList.hasArgNames()) return false; - const(char)[] commonError = null; + const(char)* commonError = null; bool allSame = true; bool anyError = false; @@ -2247,10 +2247,13 @@ private bool checkNamedArgErrorAndReportOverload(Dsymbol od, ArgumentList argume if (!resolvedArgs && buf.length) { anyError = true; - const(char)[] currentError = buf.peekChars().toDString(); + const(char)* currentError = buf.peekChars(); if (commonError is null) - commonError = currentError; - else if (commonError != currentError) + { + import dmd.root.rmem : mem; + commonError = mem.xstrdup(currentError); + } + else if (strcmp(commonError, currentError) != 0) allSame = false; } else @@ -2263,7 +2266,7 @@ private bool checkNamedArgErrorAndReportOverload(Dsymbol od, ArgumentList argume if (anyError && allSame && commonError !is null) { - .error(loc, "%s", commonError.ptr); + .error(loc, "%s", commonError); return true; } return false; From 848f0568c8576d421b157b96be8b786b14f6d8b5 Mon Sep 17 00:00:00 2001 From: shivaji Date: Tue, 24 Mar 2026 11:45:08 +0530 Subject: [PATCH 6/6] Fix compilation errors in funcsem.d (string concatenations) --- compiler/src/dmd/funcsem.d | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/compiler/src/dmd/funcsem.d b/compiler/src/dmd/funcsem.d index cd6f1c438604..07db9dc33e91 100644 --- a/compiler/src/dmd/funcsem.d +++ b/compiler/src/dmd/funcsem.d @@ -4057,16 +4057,14 @@ private void checkPrintfScanfSignature(FuncDeclaration funcdecl, TypeFunction f, const p = (funcdecl.printf ? Id.printf : Id.scanf).toChars(); if (!(f.linkage == LINK.c || f.linkage == LINK.cpp)) { - .error(funcdecl.loc, "`pragma(%s)` function `%s` must have `extern(C)` or `extern(C++)` linkage," - ~" not `extern(%s)`", + .error(funcdecl.loc, "`pragma(%s)` function `%s` must have `extern(C)` or `extern(C++)` linkage, not `extern(%s)`", p, funcdecl.toChars(), f.linkage.linkageToChars()); } if (f.parameterList.varargs == VarArg.variadic) { if (!(nparams >= 1 && isPointerToChar(f.parameterList[nparams - 1]))) { - .error(funcdecl.loc, "`pragma(%s)` function `%s` must have" - ~ " signature `%s %s([parameters...], const(char)*, ...)` not `%s`", + .error(funcdecl.loc, "`pragma(%s)` function `%s` must have signature `%s %s([parameters...], const(char)*, ...)` not `%s`", p, funcdecl.toChars(), f.next.toChars(), funcdecl.toChars(), funcdecl.type.toChars()); } } @@ -4074,8 +4072,7 @@ private void checkPrintfScanfSignature(FuncDeclaration funcdecl, TypeFunction f, { if(!(nparams >= 2 && isPointerToChar(f.parameterList[nparams - 2]) && isVa_list(f.parameterList[nparams - 1]))) - .error(funcdecl.loc, "`pragma(%s)` function `%s` must have"~ - " signature `%s %s([parameters...], const(char)*, va_list)`", + .error(funcdecl.loc, "`pragma(%s)` function `%s` must have signature `%s %s([parameters...], const(char)*, va_list)`", p, funcdecl.toChars(), f.next.toChars(), funcdecl.toChars()); } else