summaryrefslogtreecommitdiff
path: root/demangler/gnu3
diff options
context:
space:
mode:
authorPeter LaFosse <peter@vector35.com>2026-03-26 22:59:52 -0400
committerPeter LaFosse <peter@vector35.com>2026-03-27 08:11:54 -0400
commit339ce9d5b3a1b6e116c7cd43349a3d935959ee35 (patch)
treeeca25eabcdf99463ea51579d82dbbab3cfe87929 /demangler/gnu3
parent1743bbaa43911306229a8ecf0c0184f8eb79f435 (diff)
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>
Diffstat (limited to 'demangler/gnu3')
-rw-r--r--demangler/gnu3/demangle_gnu3.cpp32
1 files changed, 25 insertions, 7 deletions
diff --git a/demangler/gnu3/demangle_gnu3.cpp b/demangler/gnu3/demangle_gnu3.cpp
index e06d4bcd..27054433 100644
--- a/demangler/gnu3/demangle_gnu3.cpp
+++ b/demangler/gnu3/demangle_gnu3.cpp
@@ -1093,10 +1093,14 @@ string DemangleGNU3::DemanglePrimaryExpression()
case 'j': out = DemangleNumberAsString() + "u"; break; // unsigned int
break;
default:
+ {
m_reader.UnRead(1);
- out = "(" + DemangleTypeString() + ")" + DemangleNumberAsString();
+ const string castType = DemangleTypeString();
+ const string castVal = DemangleNumberAsString();
+ out = "(" + castType + ")" + castVal;
break;
}
+ }
if (m_reader.Read() != 'E')
throw DemangleException();
@@ -1410,7 +1414,9 @@ QualifiedName DemangleGNU3::DemangleBaseUnresolvedName()
if (str == "on")
{
m_reader.Consume(); m_reader.Consume(); // skip 'o','n' prefix
- out.push_back(GetOperator(m_reader.Read(), m_reader.Read()));
+ char op1 = m_reader.Read();
+ char op2 = m_reader.Read();
+ out.push_back(GetOperator(op1, op2));
if (m_reader.Peek() == 'I')
{
m_reader.Consume();
@@ -1583,7 +1589,12 @@ string DemangleGNU3::DemangleExpression()
case hash('s','c'):
case hash('c','c'):
case hash('r','c'):
- return GetOperator(elm1, elm2) + "<" + DemangleTypeString() + ">(" + DemangleExpression() + ")";
+ {
+ const string op = GetOperator(elm1, elm2);
+ const string castType = DemangleTypeString();
+ const string castExpr = DemangleExpression();
+ return op + "<" + castType + ">(" + castExpr + ")";
+ }
case hash('t','i'):
case hash('t','e'):
case hash('s','t'):
@@ -1667,9 +1678,12 @@ string DemangleGNU3::DemangleExpression()
case hash('n','a'): // new []
return gs + DemangleUnaryPrefixType(GetOperator(elm1, elm2));
case hash('q','u'): // ternary
- return DemangleExpression() + "?" +
- DemangleExpression() + ":" +
- DemangleExpression();
+ {
+ const string cond = DemangleExpression();
+ const string then_expr = DemangleExpression();
+ const string else_expr = DemangleExpression();
+ return cond + "?" + then_expr + ":" + else_expr;
+ }
case hash('c','l'): // ()
{
const string callable = DemangleExpression();
@@ -1702,7 +1716,11 @@ string DemangleGNU3::DemangleExpression()
return out;
}
case hash('t','l'): //type {expression}
- return DemangleTypeString() + " {" + DemangleExpressionList() + "}";
+ {
+ const string tlType = DemangleTypeString();
+ const string tlExprs = DemangleExpressionList();
+ return tlType + " {" + tlExprs + "}";
+ }
case hash('i', 'l'): //{expr-list}, braced-init-list in any other context
out = DemangleExpression();
if (m_reader.Read() != 'E')