Skip to content

Commit e010074

Browse files
plafosseclaude
andcommitted
Fix ABI tag (B <source-name>) handling in nested names and function names
In DemangleNestedName(), the previous code broke out of the parsing loop when it saw 'B' (an ABI tag prefix), leaving the 'E' nested-name terminator unconsumed and causing the remainder of the qualified name (e.g. constructor C1) to be lost. The fix: instead of breaking, consume all consecutive 'B <source-name>' sequences inline, appending "[abi:tag]" to the last name segment, then continue parsing the rest of the nested name normally. The m_lastName is saved and restored so that a following C1/D1 ctor/dtor still resolves to the class name rather than the ABI tag string. In DemangleFunction(), the old ad-hoc 'B' handler (which only recognized "cxx11" and set a wrong return type) is replaced with the same ABI-tag loop, allowing correct return-type detection for constructors/destructors with ABI-tagged names. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent c816816 commit e010074

1 file changed

Lines changed: 30 additions & 18 deletions

File tree

demangler/gnu3/demangle_gnu3.cpp

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1818,7 +1818,6 @@ DemangledTypeNode DemangleGNU3::DemangleNestedName()
18181818
DemangledTypeNode newType;
18191819
bool base = false;
18201820
bool isTemplate = false;
1821-
bool hasB = false;
18221821
//[<CV-qualifiers>]
18231822
DemangleCVQualifiers(cnst, vltl, rstrct);
18241823

@@ -1837,11 +1836,6 @@ DemangledTypeNode DemangleGNU3::DemangleNestedName()
18371836

18381837
while (m_reader.Peek() != 'E')
18391838
{
1840-
if (m_reader.Peek() == 'B')
1841-
{
1842-
hasB = true;
1843-
break;
1844-
}
18451839
isTemplate = false;
18461840
substitute = true;
18471841
size_t startSize = m_templateSubstitute.size();
@@ -1886,6 +1880,23 @@ DemangledTypeNode DemangleGNU3::DemangleNestedName()
18861880
type.SetNTR(type.GetNTRClass(), newName);
18871881
type.SetHasTemplateArguments(false);
18881882
}
1883+
// Consume any ABI tags (B <source-name>) following this name component.
1884+
// These appear as suffixes on <unqualified-name> in the Itanium ABI:
1885+
// <abi-tags> ::= <abi-tag> [<abi-tags>]
1886+
// <abi-tag> ::= B <source-name>
1887+
// We append them as "[abi:tag]" to the last name segment for display.
1888+
// Save/restore m_lastName so that a following C1/D1 ctor/dtor name
1889+
// still resolves to the class name, not the ABI tag string.
1890+
while (m_reader.Peek() == 'B')
1891+
{
1892+
m_reader.Consume();
1893+
string savedLastName = m_lastName;
1894+
string abiTag = DemangleSourceName();
1895+
m_lastName = savedLastName;
1896+
auto& segs = type.GetMutableTypeName();
1897+
if (!segs.empty())
1898+
segs.back() += "[abi:" + abiTag + "]";
1899+
}
18891900
if (substitute && m_reader.Peek() != 'E')
18901901
{
18911902
//Those template arguments were not the primary arguments so clear them from the sub listType
@@ -1897,8 +1908,7 @@ DemangledTypeNode DemangleGNU3::DemangleNestedName()
18971908
}
18981909
MyLogDebug("%s:: '%s'\n", __FUNCTION__, m_reader.GetRaw().c_str());
18991910
}
1900-
if (!hasB)
1901-
m_reader.Consume();
1911+
m_reader.Consume();
19021912

19031913
if (cnst || vltl || rstrct)
19041914
{
@@ -2426,18 +2436,20 @@ DemangledTypeNode DemangleGNU3::DemangleSymbol(QualifiedName& varName)
24262436
m_reader.Consume();
24272437
// TODO: If we get here we have a return type. What can we do with this info?
24282438
}
2429-
if (m_reader.Peek() == 'B')
2439+
// Consume any ABI tags on the function/data name (e.g. B5cxx11).
2440+
// For nested names these are already consumed inside DemangleNestedName();
2441+
// this handles the global-scope case.
2442+
while (m_reader.Peek() == 'B')
24302443
{
24312444
m_reader.Consume();
2432-
DemangledTypeNode t = DemangleUnqualifiedName();
2433-
2434-
if (t.GetString() == "cxx11")
2435-
{
2436-
static const QualifiedName stdCxx11StringName(vector<string>{"std", "cxx11", "string"});
2437-
returnType = CreateUnknownType(stdCxx11StringName);
2438-
}
2439-
}
2440-
else if (m_isOperatorOverload ||
2445+
string savedLastName = m_lastName;
2446+
string abiTag = DemangleSourceName();
2447+
m_lastName = savedLastName;
2448+
auto& segs = type.GetMutableTypeName();
2449+
if (!segs.empty())
2450+
segs.back() += "[abi:" + abiTag + "]";
2451+
}
2452+
if (m_isOperatorOverload ||
24412453
type.GetNameType() == ConstructorNameType ||
24422454
type.GetNameType() == DestructorNameType)
24432455
{

0 commit comments

Comments
 (0)