From af93db2cbfd24d5da40ed2951f5b9b05bf3d565c Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Tue, 10 Mar 2026 15:35:26 -0400 Subject: GNU3 Demangler: fix substitution tracking, expressions, and type names Substitution table and scoping: - Fix generic lambda auto parameters: save/replace m_templateSubstitute with 'auto' placeholders for lambda-local T_/T0_/T1_ resolution - Fix local-name template scoping with m_inLocalName flag - Fix substitution table off-by-one for all-type template args - Fix pointer-to-member type (case 'M'): set substitute=true per ABI - Fix multi-character seq-id parsing (S10_, S11_, etc.) - Fix DemangleUnresolvedType decltype (DT/Dt) prefix consumption - Add forward template ref support for cv conversion operators - Fix sr qualifier-list PushType and conditional E handling - Fix multi-level sr scope resolution without N prefix - Fix sr + unscoped template substitution table tracking - Fix I...E argument pack handling (GCC I...E vs J...E) - Fix Dp pack expansion to show '...' for concrete types Expression formatting: - Fix L_Z embedded mangled name template scope isolation - Handle LZE function address template args - cl expression: callable(args) format with function substitute tracking - dt/pt expressions: obj.member and obj->member directly - fp_/fp_ placeholders in decltype return types - Fix fL function-param scope validation - Fix DemangleBaseUnresolvedName 'on' prefix consumption Type names (Itanium ABI spec compliance): - x/y: "long long"/"unsigned long long" - a: "signed char" (distinct from 'c' = "char") - n/o: "__int128"/"unsigned __int128" - g: "__float128" via FloatType altName - Dd/Df/De: "decimal64"/"decimal32"/"decimal128" - Dh: "_Float16" - Dp: always show "..." for pack expansion - Fix 'n' literal: __int128 not __uint128 - Fix dot extension spacing Cleanup: - Remove unused NextIsOneOf, ReadUntil, DemangleInitializer - Guard GetRaw/GetTemplateType/PrintTables behind GNUDEMANGLE_DEBUG - Remove unreachable GetNameType C/D cases - Remove dead BinaryExpression "." check Co-Authored-By: Claude Opus 4.6 (1M context) --- demangler/gnu3/demangle_gnu3.h | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'demangler/gnu3/demangle_gnu3.h') diff --git a/demangler/gnu3/demangle_gnu3.h b/demangler/gnu3/demangle_gnu3.h index 2e46e05d..8ee0fca6 100644 --- a/demangler/gnu3/demangle_gnu3.h +++ b/demangler/gnu3/demangle_gnu3.h @@ -51,10 +51,10 @@ public: DemangleGNU3Reader(const _STD_STRING& data); void Reset(const _STD_STRING& data); _STD_STRING PeekString(size_t count=1); - bool NextIsOneOf(const _STD_STRING& list); +#ifdef GNUDEMANGLE_DEBUG _STD_STRING GetRaw(); +#endif _STD_STRING ReadString(size_t count=1); - _STD_STRING ReadUntil(char sentinal); size_t Length() const { return m_data.length() - m_offset; } @@ -109,6 +109,17 @@ class DemangleGNU3 bool m_shouldDeleteReader; bool m_topLevel; bool m_isOperatorOverload; + // Forward template reference support (for cv conversion operator types). + // When m_permitForwardTemplateRefs is true, DemangleTemplateSubstitution() + // returns a placeholder instead of throwing for out-of-bounds template params. + // m_pendingForwardRefs records which param indices have placeholders so that + // ResolveForwardTemplateRefs() can patch them once template args are known. + bool m_permitForwardTemplateRefs; + bool m_inLocalName; + struct ForwardRef { size_t index; }; + _STD_VECTOR m_pendingForwardRefs; + void ResolveForwardTemplateRefs(DemangledTypeNode& type, const _STD_VECTOR<_STD_STRING>& args); + static _STD_STRING ForwardRefPlaceholder(size_t index); enum SymbolType { Function, FunctionWithReturn, Data, VTable, Rtti, Name}; BN::QualifiedName DemangleBaseUnresolvedName(); DemangledTypeNode DemangleUnresolvedType(); @@ -121,7 +132,6 @@ class DemangleGNU3 DemangledTypeNode DemangleUnqualifiedName(); _STD_STRING DemangleSourceName(); _STD_STRING DemangleNumberAsString(); - _STD_STRING DemangleInitializer(); _STD_STRING DemangleExpression(); _STD_STRING DemanglePrimaryExpression(); DemangledTypeNode DemangleName(); @@ -129,14 +139,13 @@ class DemangleGNU3 void DemangleCVQualifiers(bool& cnst, bool& vltl, bool& rstrct); DemangledTypeNode DemangleSubstitution(); - const DemangledTypeNode& DemangleTemplateSubstitution(); - void DemangleTemplateArgs(_STD_VECTOR<_STD_STRING>& args); + DemangledTypeNode DemangleTemplateSubstitution(); + void DemangleTemplateArgs(_STD_VECTOR<_STD_STRING>& args, bool* hadNonTypeArg = nullptr); DemangledTypeNode DemangleFunction(bool cnst, bool vltl); DemangledTypeNode DemangleType(); int64_t DemangleNumber(); - DemangledTypeNode DemangleNestedName(); + DemangledTypeNode DemangleNestedName(bool* allTypeTemplateArgs = nullptr); void PushTemplateType(const DemangledTypeNode& type); - const DemangledTypeNode& GetTemplateType(size_t ref); void PushType(const DemangledTypeNode& type); const DemangledTypeNode& GetType(size_t ref); @@ -144,12 +153,16 @@ class DemangleGNU3 DemangledTypeNode CreateUnknownType(const _STD_STRING& s); static void ExtendTypeName(DemangledTypeNode& type, const _STD_STRING& extend); +#ifdef GNUDEMANGLE_DEBUG + const DemangledTypeNode& GetTemplateType(size_t ref); + void PrintTables(); +#endif + public: DemangleGNU3(BN::Architecture* arch, const _STD_STRING& mangledName); void Reset(BN::Architecture* arch, const _STD_STRING& mangledName); DemangledTypeNode DemangleSymbol(BN::QualifiedName& varName); BN::QualifiedName GetVarName() const { return m_varName; } - void PrintTables(); }; -- cgit v1.3.1