[demangler] All <qualifiers> on one type should share one entry in the substitution table.
Previously, both <extended-qualifier>s and <CV-qualifiers> got their own entries.
git-svn-id: https://llvm.org/svn/llvm-project/libcxxabi/trunk@324968 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/src/cxa_demangle.cpp b/src/cxa_demangle.cpp
index 01724cc..49b3e12 100644
--- a/src/cxa_demangle.cpp
+++ b/src/cxa_demangle.cpp
@@ -1977,6 +1977,7 @@
Node *parseArrayType();
Node *parsePointerToMemberType();
Node *parseClassEnumType();
+ Node *parseQualifiedType(bool &AppliesToFunction);
// FIXME: remove this when all the parse_* functions have been rewritten.
template <const char *(*parse_fn)(const char *, const char *, Db &)>
@@ -2238,6 +2239,52 @@
return legacyParse<parse_name>();
}
+// <qualified-type> ::= <qualifiers> <type>
+// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
+// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
+Node *Db::parseQualifiedType(bool &AppliesToFunction) {
+ if (consumeIf('U')) {
+ StringView Qual = parseBareSourceName();
+ if (Qual.empty())
+ return nullptr;
+
+ // FIXME parse the optional <template-args> here!
+
+ // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
+ if (Qual.startsWith("objcproto")) {
+ StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
+ StringView Proto;
+ {
+ SwapAndRestore<const char *> SaveFirst(First, ProtoSourceName.begin()),
+ SaveLast(Last, ProtoSourceName.end());
+ Proto = parseBareSourceName();
+ }
+ if (Proto.empty())
+ return nullptr;
+ Node *Child = parseQualifiedType(AppliesToFunction);
+ if (Child == nullptr)
+ return nullptr;
+ return make<ObjCProtoName>(Child, Proto);
+ }
+
+ Node *Child = parseQualifiedType(AppliesToFunction);
+ if (Child == nullptr)
+ return nullptr;
+ return make<VendorExtQualType>(Child, Qual);
+ }
+
+ Qualifiers Quals = parseCVQualifiers();
+ AppliesToFunction = look() == 'F';
+ Node *Ty = parseType();
+ if (Ty == nullptr)
+ return nullptr;
+ if (Quals != QualNone) {
+ return AppliesToFunction ?
+ make<FunctionQualType>(Ty, Quals) : make<QualType>(Ty, Quals);
+ }
+ return Ty;
+}
+
// <type> ::= <builtin-type>
// ::= <qualified-type>
// ::= <function-type>
@@ -2265,18 +2312,10 @@
// ::= <qualified-type>
case 'r':
case 'V':
- case 'K': {
- Qualifiers Q = parseCVQualifiers();
- bool AppliesToFunction = look() == 'F';
-
- Node *Child = parseType();
- if (Child == nullptr)
- return nullptr;
-
- if (AppliesToFunction)
- Result = make<FunctionQualType>(Child, Q);
- else
- Result = make<QualType>(Child, Q);
+ case 'K':
+ case 'U': {
+ bool AppliesToFunction = false;
+ Result = parseQualifiedType(AppliesToFunction);
// Itanium C++ ABI 5.1.5.3:
// For the purposes of substitution, the CV-qualifiers and ref-qualifier
@@ -2285,39 +2324,6 @@
return Result;
break;
}
- // <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
- case 'U': {
- // FIXME: We should fold this into the cvr qualifier parsing above. This
- // currently adds too many entries into the substitution table if multiple
- // qualifiers are present on the same type, as all the qualifiers on a type
- // should just get one entry in the substitution table.
- ++First;
- StringView Qual = parseBareSourceName();
- if (Qual.empty())
- return nullptr;
-
- // FIXME parse the optional <template-args> here!
-
- Result = parseType();
- if (Result == nullptr)
- return nullptr;
-
- // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
- if (Qual.startsWith("objcproto")) {
- StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
- StringView Proto;
- {
- SwapAndRestore<const char *> SaveFirst(First, ProtoSourceName.begin()),
- SaveLast(Last, ProtoSourceName.end());
- Proto = parseBareSourceName();
- }
- if (Proto.empty())
- return nullptr;
- Result = make<ObjCProtoName>(Result, Proto);
- } else
- Result = make<VendorExtQualType>(Result, Qual);
- break;
- }
// <builtin-type> ::= v # void
case 'v':
++First;