@@ -1267,6 +1267,19 @@ DemangledTypeNode DemangleGNU3::DemangleUnqualifiedName()
12671267 outType = CreateUnknownType (m_lastName);
12681268 outType.SetNameType (ConstructorNameType);
12691269 break ;
1270+ case hash (' C' ,' I' ): // Inheriting constructor: CI1 <type> or CI2 <type>
1271+ {
1272+ char kind = m_reader.Read (); // '1' or '2'
1273+ if (kind != ' 1' && kind != ' 2' )
1274+ throw DemangleException ();
1275+ // Save m_lastName: parsing the inherited-class type will overwrite it
1276+ string savedLastName = m_lastName;
1277+ DemangleType ();
1278+ m_lastName = savedLastName;
1279+ outType = CreateUnknownType (m_lastName);
1280+ outType.SetNameType (ConstructorNameType);
1281+ break ;
1282+ }
12701283 case hash (' D' ,' 0' ): // Destructor
12711284 case hash (' D' ,' 1' ):
12721285 case hash (' D' ,' 2' ):
@@ -1804,33 +1817,25 @@ string DemangleGNU3::DemangleExpression()
18041817 // - the template instantiation (name + args) as another candidate
18051818 // This mirrors how the compiler builds the substitution table during encoding.
18061819 bool hadTemplateArgs = false ;
1807- string accumulated; // full path built so far (for sub table entries)
18081820 do
18091821 {
18101822 hadTemplateArgs = false ;
18111823 const string segName = DemangleSourceName ();
1812- accumulated += (accumulated.empty () ? segName : " ::" + segName);
1813- // Push the bare name as a substitution candidate (e.g. "QMetaTypeId2")
1814- PushType (CreateUnknownType (accumulated));
18151824 out += segName;
18161825 if (m_reader.Peek () == ' I' )
18171826 {
18181827 vector<string> args;
18191828 m_reader.Consume ();
18201829 DemangleTemplateArgs (args); // consumes the trailing 'E'
1821- const string tmplStr = GetTemplateString (args);
1822- accumulated += tmplStr;
1823- // Push the template instantiation (e.g. "QMetaTypeId2<T>") as a
1824- // substitution candidate so that later SX_ refs resolve correctly.
1825- PushType (CreateUnknownType (accumulated));
1826- out += tmplStr;
1830+ out += GetTemplateString (args);
18271831 hadTemplateArgs = true ;
18281832 }
18291833 out += " ::" ;
18301834 }while (!hadTemplateArgs && m_reader.Peek () != ' E' );
1831- // Consume the qualifier-list 'E' only if it wasn't already consumed
1832- // as the template-args terminator.
1833- if (!hadTemplateArgs)
1835+ // Consume qualifier-list 'E' if present. GCC sometimes omits it when
1836+ // the last qualifier had template-args whose 'E' served double duty,
1837+ // so check rather than unconditionally consuming.
1838+ if (m_reader.Peek () == ' E' )
18341839 m_reader.Consume ();
18351840 out += DemangleBaseUnresolvedName ().GetString ();
18361841 return out;
@@ -1980,6 +1985,10 @@ DemangledTypeNode DemangleGNU3::DemangleNestedName(bool* allTypeTemplateArgs)
19801985 size_t startSize = m_templateSubstitute.size ();
19811986 switch (m_reader.Read ())
19821987 {
1988+ case ' M' : // <data-member-prefix>: closure/lambda inside a data member initializer
1989+ // 'M' follows the member name and marks that subsequent components are
1990+ // scoped inside that data member. Just consume it; the name is already captured.
1991+ continue ;
19831992 case ' S' : // <substitution>
19841993 newType = DemangleSubstitution ();
19851994 substitute = false ;
@@ -2297,20 +2306,37 @@ DemangledTypeNode DemangleGNU3::DemangleSymbol(QualifiedName& varName)
22972306 peekChar == ' x' || peekChar == ' y' || peekChar == ' Y' );
22982307 // 'z'/'Z' are ambiguous: also used as Z-local-name prefix in guard variables
22992308 // (e.g. _ZGVZN1A1BEvE1A = guard variable for A::B()::A).
2300- // Disambiguate by verifying the Vector ABI pattern: <isa><mask(M|N)><vlen(digits)><vparam or _>.
2309+ // Disambiguate by verifying the full Vector ABI parameter pattern:
2310+ // <isa><mask(M|N)><vlen(digits)><vparams><'_'> where vparams are only
2311+ // from {v, l, u, R, L, s, 0-9} and are immediately followed by '_'.
2312+ // A guard variable's inner symbol would have source-name chars (e.g. 'm', 'a', etc.)
2313+ // that don't appear in valid vparameter sequences.
23012314 if (!isVectorABI && (peekChar == ' z' || peekChar == ' Z' ))
23022315 {
2303- _STD_STRING ahead = m_reader.PeekString (8 );
2316+ _STD_STRING ahead = m_reader.PeekString (32 );
23042317 if (ahead.size () >= 3 && (ahead[1 ] == ' M' || ahead[1 ] == ' N' ))
23052318 {
23062319 size_t pos = 2 ;
23072320 while (pos < ahead.size () && isdigit ((unsigned char )ahead[pos]))
23082321 pos++;
2309- if (pos > 2 )
2322+ if (pos > 2 ) // had at least one vlen digit
23102323 {
2311- char after = (pos < ahead.size ()) ? ahead[pos] : ' \0 ' ;
2312- isVectorABI = (after == ' _' || after == ' v' || after == ' l' ||
2313- after == ' u' || after == ' R' || after == ' L' );
2324+ // Scan through vparameter chars; valid ones are v/l/u/R/L and
2325+ // optional stride digits/'s'. Anything else means guard variable.
2326+ bool allVparam = true ;
2327+ while (pos < ahead.size () && ahead[pos] != ' _' )
2328+ {
2329+ char c = ahead[pos];
2330+ if (c == ' v' || c == ' l' || c == ' u' || c == ' R' ||
2331+ c == ' L' || c == ' s' || isdigit ((unsigned char )c))
2332+ pos++;
2333+ else
2334+ {
2335+ allVparam = false ;
2336+ break ;
2337+ }
2338+ }
2339+ isVectorABI = allVparam && pos < ahead.size () && ahead[pos] == ' _' ;
23142340 }
23152341 }
23162342 }
0 commit comments