[demangler] Support for dependent elaborate type specifiers.
git-svn-id: https://llvm.org/svn/llvm-project/libcxxabi/trunk@324969 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/src/cxa_demangle.cpp b/src/cxa_demangle.cpp
index 49b3e12..5faf0ae 100644
--- a/src/cxa_demangle.cpp
+++ b/src/cxa_demangle.cpp
@@ -165,6 +165,7 @@
KQualType,
KConversionOperatorType,
KPostfixQualifiedType,
+ KElaboratedTypeSpefType,
KNameType,
KAbiTagAttr,
KObjCProtoName,
@@ -443,6 +444,22 @@
void printLeft(OutputStream &s) const override { s += Name; }
};
+class ElaboratedTypeSpefType : public Node {
+ StringView Kind;
+ Node *Child;
+public:
+ ElaboratedTypeSpefType(StringView Kind_, Node *Child_)
+ : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {
+ ParameterPackSize = Child->ParameterPackSize;
+ }
+
+ void printLeft(OutputStream &S) const override {
+ S += Kind;
+ S += ' ';
+ Child->print(S);
+ }
+};
+
class AbiTagAttr final : public Node {
const Node* Base;
StringView Tag;
@@ -2235,8 +2252,22 @@
// ::= Tu <name> # dependent elaborated type specifier using 'union'
// ::= Te <name> # dependent elaborated type specifier using 'enum'
Node *Db::parseClassEnumType() {
- // FIXME: try to parse the elaborated type specifiers here!
- return legacyParse<parse_name>();
+ StringView ElabSpef;
+ if (consumeIf("Ts"))
+ ElabSpef = "struct";
+ else if (consumeIf("Tu"))
+ ElabSpef = "union";
+ else if (consumeIf("Te"))
+ ElabSpef = "enum";
+
+ Node *Name = legacyParse<parse_name>();
+ if (Name == nullptr)
+ return nullptr;
+
+ if (!ElabSpef.empty())
+ return make<ElaboratedTypeSpefType>(ElabSpef, Name);
+
+ return Name;
}
// <qualified-type> ::= <qualifiers> <type>
@@ -2495,6 +2526,12 @@
}
// ::= <template-param>
case 'T': {
+ // This could be an elaborate type specifier on a <class-enum-type>.
+ if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
+ Result = parseClassEnumType();
+ break;
+ }
+
Result = legacyParse<parse_template_param>();
if (Result == nullptr)
return nullptr;
diff --git a/test/test_demangle.pass.cpp b/test/test_demangle.pass.cpp
index c66161d..e28f1ec 100644
--- a/test/test_demangle.pass.cpp
+++ b/test/test_demangle.pass.cpp
@@ -29658,7 +29658,11 @@
{"_ZNK5test81XIiE3barIiEEDTcl3fooIT_EEEv", "decltype(foo<int>()) test8::X<int>::bar<int>() const"},
// Multiple qualifiers on the same type should all get the same entry in the substitution table.
- {"_Z1fPU3AS1KiS0_", "f(int const AS1*, int const AS1*)"}
+ {"_Z1fPU3AS1KiS0_", "f(int const AS1*, int const AS1*)"},
+
+ {"_ZN6test471fINS_1SEEEvPTsNT_1cE", "void test47::f<test47::S>(struct test47::S::c*)"},
+ {"_ZN6test481fINS_1SEEEvPTuNT_1uE", "void test48::f<test48::S>(union test48::S::u*)"},
+ {"_ZN6test451fINS_1SEEEvPTeNT_1eE", "void test45::f<test45::S>(enum test45::S::e*)"},
};
const unsigned N = sizeof(cases) / sizeof(cases[0]);