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 <teodor.dutu@gmail.com>
This commit is contained in:
Teodor Dutu 2024-02-19 19:45:18 +02:00 committed by Nicholas Wilson
parent a61180db7b
commit 2423b93798
2 changed files with 39 additions and 21 deletions

View file

@ -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);

View file

@ -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"]);
}