diff options
| author | Peter LaFosse <peter@vector35.com> | 2026-03-26 22:59:52 -0400 |
|---|---|---|
| committer | Peter LaFosse <peter@vector35.com> | 2026-03-27 08:11:54 -0400 |
| commit | 339ce9d5b3a1b6e116c7cd43349a3d935959ee35 (patch) | |
| tree | eca25eabcdf99463ea51579d82dbbab3cfe87929 /demangler/gnu3 | |
| parent | 1743bbaa43911306229a8ecf0c0184f8eb79f435 (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.cpp | 32 |
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') |
