Skip to content

Commit 339ce9d

Browse files
plafosseclaude
andcommitted
GNU3 Demangler: fix undefined evaluation order in expression builders
Sequence reader-advancing calls into named locals before concatenating to avoid undefined evaluation order in operator+ chains (caused wrong output on MSVC/x86_64 GCC where operands evaluated right-to-left). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 1743bba commit 339ce9d

File tree

1 file changed

+25
-7
lines changed

1 file changed

+25
-7
lines changed

demangler/gnu3/demangle_gnu3.cpp

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,10 +1093,14 @@ string DemangleGNU3::DemanglePrimaryExpression()
10931093
case 'j': out = DemangleNumberAsString() + "u"; break; // unsigned int
10941094
break;
10951095
default:
1096+
{
10961097
m_reader.UnRead(1);
1097-
out = "(" + DemangleTypeString() + ")" + DemangleNumberAsString();
1098+
const string castType = DemangleTypeString();
1099+
const string castVal = DemangleNumberAsString();
1100+
out = "(" + castType + ")" + castVal;
10981101
break;
10991102
}
1103+
}
11001104
if (m_reader.Read() != 'E')
11011105
throw DemangleException();
11021106

@@ -1410,7 +1414,9 @@ QualifiedName DemangleGNU3::DemangleBaseUnresolvedName()
14101414
if (str == "on")
14111415
{
14121416
m_reader.Consume(); m_reader.Consume(); // skip 'o','n' prefix
1413-
out.push_back(GetOperator(m_reader.Read(), m_reader.Read()));
1417+
char op1 = m_reader.Read();
1418+
char op2 = m_reader.Read();
1419+
out.push_back(GetOperator(op1, op2));
14141420
if (m_reader.Peek() == 'I')
14151421
{
14161422
m_reader.Consume();
@@ -1583,7 +1589,12 @@ string DemangleGNU3::DemangleExpression()
15831589
case hash('s','c'):
15841590
case hash('c','c'):
15851591
case hash('r','c'):
1586-
return GetOperator(elm1, elm2) + "<" + DemangleTypeString() + ">(" + DemangleExpression() + ")";
1592+
{
1593+
const string op = GetOperator(elm1, elm2);
1594+
const string castType = DemangleTypeString();
1595+
const string castExpr = DemangleExpression();
1596+
return op + "<" + castType + ">(" + castExpr + ")";
1597+
}
15871598
case hash('t','i'):
15881599
case hash('t','e'):
15891600
case hash('s','t'):
@@ -1667,9 +1678,12 @@ string DemangleGNU3::DemangleExpression()
16671678
case hash('n','a'): // new []
16681679
return gs + DemangleUnaryPrefixType(GetOperator(elm1, elm2));
16691680
case hash('q','u'): // ternary
1670-
return DemangleExpression() + "?" +
1671-
DemangleExpression() + ":" +
1672-
DemangleExpression();
1681+
{
1682+
const string cond = DemangleExpression();
1683+
const string then_expr = DemangleExpression();
1684+
const string else_expr = DemangleExpression();
1685+
return cond + "?" + then_expr + ":" + else_expr;
1686+
}
16731687
case hash('c','l'): // ()
16741688
{
16751689
const string callable = DemangleExpression();
@@ -1702,7 +1716,11 @@ string DemangleGNU3::DemangleExpression()
17021716
return out;
17031717
}
17041718
case hash('t','l'): //type {expression}
1705-
return DemangleTypeString() + " {" + DemangleExpressionList() + "}";
1719+
{
1720+
const string tlType = DemangleTypeString();
1721+
const string tlExprs = DemangleExpressionList();
1722+
return tlType + " {" + tlExprs + "}";
1723+
}
17061724
case hash('i', 'l'): //{expr-list}, braced-init-list in any other context
17071725
out = DemangleExpression();
17081726
if (m_reader.Read() != 'E')

0 commit comments

Comments
 (0)