@@ -721,6 +721,23 @@ DemangledTypeNode DemangleGNU3::DemangleType()
721721 substitute = true ;
722722 break ;
723723 }
724+ case ' u' :
725+ {
726+ // Vendor extended type: u <source-name> [<template-args>]
727+ // e.g. u14__remove_cvref, u20__remove_reference_t
728+ string extName = DemangleSourceName ();
729+ if (m_reader.Peek () == ' I' )
730+ {
731+ m_reader.Consume ();
732+ vector<string> targs;
733+ DemangleTemplateArgs (targs);
734+ if (!targs.empty ())
735+ extName += GetTemplateString (targs);
736+ }
737+ type = CreateUnknownType (extName);
738+ substitute = true ;
739+ break ;
740+ }
724741 case ' v' : type = DemangledTypeNode::VoidType (); break ;
725742 case ' w' : type = DemangledTypeNode::IntegerType (4 , false , " wchar_t" ); break ; // TODO: verify
726743 case ' b' : type = DemangledTypeNode::BoolType (); break ;
@@ -786,7 +803,7 @@ DemangledTypeNode DemangleGNU3::DemangleType()
786803 }
787804 case ' t' :
788805 case ' T' :
789- type = CreateUnknownType (DemangleExpression ());
806+ type = CreateUnknownType (" decltype( " + DemangleExpression () + " ) " );
790807 if (m_reader.Read () != ' E' )
791808 throw DemangleException ();
792809 break ;
@@ -1716,13 +1733,12 @@ string DemangleGNU3::DemangleExpression()
17161733 char elm;
17171734 if (elm2 == ' L' )
17181735 {
1719- // fL case requires a valid function substitute frame
1720- if (m_functionSubstitute.size () == 0 )
1721- throw DemangleException ();
1736+ // fL <L-1 num> p <CV> [<prm-2 num>] _
1737+ // When listNumber is out of range (e.g. fL used inside a decltype return
1738+ // type before function params are known), the fallback paths below produce
1739+ // a placeholder string "fp" / "fpN".
17221740 listNumber = DemangleNumber () + 1 ;
1723- if (listNumber < 0 ||
1724- (uint64_t )listNumber >= (uint64_t )m_functionSubstitute.size () ||
1725- m_reader.Read () != ' p' )
1741+ if (listNumber < 0 || m_reader.Read () != ' p' )
17261742 throw DemangleException ();
17271743 }
17281744 DemangleCVQualifiers (cnst, vltl, rstrct);
@@ -2334,9 +2350,24 @@ DemangledTypeNode DemangleGNU3::DemangleSymbol(QualifiedName& varName)
23342350 case ' A' : // TODO hidden alias
23352351 LogWarn (" Unsupported demangle type: hidden alias\n " );
23362352 throw DemangleException ();
2337- case ' R' : // TODO reference temporaries
2338- LogWarn (" Unsupported demangle type: reference temporary\n " );
2339- throw DemangleException ();
2353+ case ' R' : // GR <object name> [<seq-id>] _ # reference temporary
2354+ {
2355+ // <object name> is a <name> production (nested, local, or unscoped).
2356+ // For local names (Z prefix), DemangleLocalName consumes the trailing '_'
2357+ // as a zero-discriminator, so we only consume '_' if it's still present.
2358+ DemangledTypeNode nameNode = DemangleName ();
2359+ // Consume optional base-36 seq-id (digits + uppercase A-Z) before '_'.
2360+ string seqId;
2361+ while (m_reader.Length () > 0 && m_reader.Peek () != ' _' )
2362+ seqId += m_reader.Read ();
2363+ if (m_reader.Length () > 0 )
2364+ m_reader.Consume (); // consume '_'
2365+ string result = " reference_temporary_for_" + nameNode.GetString ();
2366+ if (!seqId.empty ())
2367+ result += " [" + seqId + " ]" ;
2368+ varName.push_back (result);
2369+ return DemangledTypeNode::NamedType (UnknownNamedTypeClass, varName);
2370+ }
23402371 case ' T' : // transaction clone: GTt<encoding> (safe) or GTn<encoding> (non-safe)
23412372 {
23422373 // consume the 't' (transaction-safe) or 'n' (non-transaction-safe) qualifier
@@ -2889,6 +2920,27 @@ bool DemangleGNU3Static::DemangleStringGNU3(Architecture* arch, const string& na
28892920 }
28902921 }
28912922
2923+ // Handle macOS thread-local variable initializer suffix: $tlv$init
2924+ // E.g. __ZL9recursive$tlv$init -> demangle "__ZL9recursive" then annotate.
2925+ static const string tlvInitSuffix = " $tlv$init" ;
2926+ if (name.size () > tlvInitSuffix.size () &&
2927+ name.compare (name.size () - tlvInitSuffix.size (), tlvInitSuffix.size (), tlvInitSuffix) == 0 )
2928+ {
2929+ string base = name.substr (0 , name.size () - tlvInitSuffix.size ());
2930+ Ref<Type> baseType;
2931+ QualifiedName baseName;
2932+ if (DemangleStringGNU3 (arch, base, baseType, baseName))
2933+ {
2934+ outVarName = baseName;
2935+ if (outVarName.size () > 0 )
2936+ outVarName[outVarName.size () - 1 ] += " $tlv$init" ;
2937+ else
2938+ outVarName.push_back (" $tlv$init" );
2939+ outType = baseType;
2940+ return true ;
2941+ }
2942+ }
2943+
28922944 string encoding = name;
28932945 string header;
28942946 bool foundHeader = DemangleGlobalHeader (encoding, header);
0 commit comments