From 3736bde2d6e5d62680e4dd619d0f3253ee9981d2 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 24 Jun 2019 22:06:03 +0200 Subject: [PATCH 01/10] make RELEASING say that dist.py should run on release branch --- RELEASING | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASING b/RELEASING index 61b2017..d799f1b 100644 --- a/RELEASING +++ b/RELEASING @@ -10,4 +10,4 @@ Push new release branch: # Push the 1.0.0.git change on master too: git checkout master; git push origin master 6. add binaries to https://github.com/nico/demumble/releases - build them with `./dist.py` + build them with `./dist.py` (on the release branch) From ffc0c4509fc2a674f5d0fb3a3f5d20ec61fe18c3 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 24 Jun 2019 22:09:44 +0200 Subject: [PATCH 02/10] move eu-strip comment in dist.py around --- dist.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist.py b/dist.py index c9a953e..cbe9413 100755 --- a/dist.py +++ b/dist.py @@ -34,6 +34,9 @@ clangxx = crsrc + '/third_party/llvm-build/Release+Asserts/bin/clang++' lldlink = crsrc + '/third_party/llvm-build/Release+Asserts/bin/lld-link' +# FIXME: https://chromium-review.googlesource.com/c/chromium/src/+/1214943 +# has a way to build eu-strip on macOS, which is arguably a smaller dep +# than llvm-strip. linux_strip = os.path.join(os.path.expanduser('~'), 'src/llvm-project/out/gn/bin/llvm-strip') @@ -70,9 +73,6 @@ def buildir(newdir): '-DCMAKE_SYSTEM_NAME=Linux', ], stdout=devnull) subprocess.check_call(['ninja', 'demumble']) - # FIXME: https://chromium-review.googlesource.com/c/chromium/src/+/1214943 - # has a way to build eu-strip on macOS, which is arguably a smaller dep - # than llvm-strip. subprocess.check_call([linux_strip, 'demumble']) subprocess.check_call(['zip', '-q9', 'demumble-linux.zip', 'demumble']) subprocess.check_call(['mv', 'demumble-linux.zip', '..']) From f1a071ed8ee03403eb7eafbfc785473850a54479 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 2 Sep 2019 21:06:51 -0400 Subject: [PATCH 03/10] mark '$' as valid posix mangling char Fixes #8. --- demumble.cc | 2 +- demumble_test.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/demumble.cc b/demumble.cc index deaea39..aa68e28 100644 --- a/demumble.cc +++ b/demumble.cc @@ -36,7 +36,7 @@ static void print_demangled(const char* format, const char* s) { static bool is_mangle_char_posix(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || - (c >= '0' && c <= '9') || c == '_'; + (c >= '0' && c <= '9') || c == '_' || c == '$'; } static bool is_mangle_char_win(char c) { diff --git a/demumble_test.py b/demumble_test.py index 3b35aed..2e0097b 100755 --- a/demumble_test.py +++ b/demumble_test.py @@ -37,6 +37,8 @@ ('demumble -mb < _Z1fv!foo_bar', '"f()" (_Z1fv)\n'), ('demumble --foo < bar', re.compile(".*unrecognized option `--foo'.*")), ('demumble -bx < bar', re.compile(".*unrecognized option `x' in `-bx'.*")), + ('demumble < _ZZ3fooiENK3$_0clEi', + 'foo(int)::$_0::operator()(int) const\n'), ] status = 0 From 9dc88879338a8d9d3d749f89dac83af8902fd56a Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 2 Sep 2019 21:13:28 -0400 Subject: [PATCH 04/10] rename is_mangle_char_posix to is_mangle_char_itanium No behavior change. --- demumble.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demumble.cc b/demumble.cc index aa68e28..835dbbe 100644 --- a/demumble.cc +++ b/demumble.cc @@ -34,7 +34,7 @@ static void print_demangled(const char* format, const char* s) { } } -static bool is_mangle_char_posix(char c) { +static bool is_mangle_char_itanium(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '$'; } @@ -116,7 +116,7 @@ int main(int argc, char* argv[]) { while (cur + n_sym != end && is_mangle_char_win(cur[n_sym])) ++n_sym; else if (is_plausible_itanium_prefix(cur)) - while (cur + n_sym != end && is_mangle_char_posix(cur[n_sym])) + while (cur + n_sym != end && is_mangle_char_itanium(cur[n_sym])) ++n_sym; else { if (print_mode == kPrintAll) From 6b6cb515dace99947c58ddaa97ceffe3ca8600c4 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Sat, 7 Sep 2019 09:16:13 -0400 Subject: [PATCH 05/10] Update LLVm lib/Demangle from r364133 to r371274 New: - [itanium] support C++2a char8_t - [itanium] support for C++20 lambda expression extensions Ran: cp ~/src/llvm-project/llvm/include/llvm/Demangle/*.h third_party/llvm/include/llvm/Demangle/ cp ~/src/llvm-project/llvm/lib/Demangle/*.cpp third_party/llvm/lib/Demangle/ cp ~/src/llvm-project/llvm/LICENSE.TXT third_party/llvm/LICENSE.txt Related to #8. --- .../include/llvm/Demangle/DemangleConfig.h | 7 - .../include/llvm/Demangle/ItaniumDemangle.h | 441 ++++++++++++++++-- .../llvm/Demangle/MicrosoftDemangleNodes.h | 2 + .../llvm/lib/Demangle/ItaniumDemangle.cpp | 10 + 4 files changed, 424 insertions(+), 36 deletions(-) diff --git a/third_party/llvm/include/llvm/Demangle/DemangleConfig.h b/third_party/llvm/include/llvm/Demangle/DemangleConfig.h index 73f89d3..b7b7dbd 100644 --- a/third_party/llvm/include/llvm/Demangle/DemangleConfig.h +++ b/third_party/llvm/include/llvm/Demangle/DemangleConfig.h @@ -15,13 +15,6 @@ #ifndef LLVM_DEMANGLE_COMPILER_H #define LLVM_DEMANGLE_COMPILER_H -#ifdef _MSC_VER -// snprintf is implemented in VS 2015 -#if _MSC_VER < 1900 -#define snprintf _snprintf_s -#endif -#endif - #ifndef __has_feature #define __has_feature(x) 0 #endif diff --git a/third_party/llvm/include/llvm/Demangle/ItaniumDemangle.h b/third_party/llvm/include/llvm/Demangle/ItaniumDemangle.h index ad1034f..c1efd7e 100644 --- a/third_party/llvm/include/llvm/Demangle/ItaniumDemangle.h +++ b/third_party/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -57,6 +57,11 @@ X(LocalName) \ X(VectorType) \ X(PixelVectorType) \ + X(SyntheticTemplateParamName) \ + X(TypeTemplateParamDecl) \ + X(NonTypeTemplateParamDecl) \ + X(TemplateTemplateParamDecl) \ + X(TemplateParamPackDecl) \ X(ParameterPack) \ X(TemplateArgumentPack) \ X(ParameterPackExpansion) \ @@ -91,6 +96,8 @@ X(ThrowExpr) \ X(UUIDOfExpr) \ X(BoolExpr) \ + X(StringLiteral) \ + X(LambdaExpr) \ X(IntegerCastExpr) \ X(IntegerLiteral) \ X(FloatLiteral) \ @@ -303,7 +310,7 @@ inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) { return Q1 = static_cast(Q1 | Q2); } -class QualType : public Node { +class QualType final : public Node { protected: const Qualifiers Quals; const Node *Child; @@ -964,6 +971,127 @@ class PixelVectorType final : public Node { } }; +enum class TemplateParamKind { Type, NonType, Template }; + +/// An invented name for a template parameter for which we don't have a +/// corresponding template argument. +/// +/// This node is created when parsing the for a lambda with +/// explicit template arguments, which might be referenced in the parameter +/// types appearing later in the . +class SyntheticTemplateParamName final : public Node { + TemplateParamKind Kind; + unsigned Index; + +public: + SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_) + : Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {} + + template void match(Fn F) const { F(Kind, Index); } + + void printLeft(OutputStream &S) const override { + switch (Kind) { + case TemplateParamKind::Type: + S += "$T"; + break; + case TemplateParamKind::NonType: + S += "$N"; + break; + case TemplateParamKind::Template: + S += "$TT"; + break; + } + if (Index > 0) + S << Index - 1; + } +}; + +/// A template type parameter declaration, 'typename T'. +class TypeTemplateParamDecl final : public Node { + Node *Name; + +public: + TypeTemplateParamDecl(Node *Name_) + : Node(KTypeTemplateParamDecl, Cache::Yes), Name(Name_) {} + + template void match(Fn F) const { F(Name); } + + void printLeft(OutputStream &S) const override { + S += "typename "; + } + + void printRight(OutputStream &S) const override { + Name->print(S); + } +}; + +/// A non-type template parameter declaration, 'int N'. +class NonTypeTemplateParamDecl final : public Node { + Node *Name; + Node *Type; + +public: + NonTypeTemplateParamDecl(Node *Name_, Node *Type_) + : Node(KNonTypeTemplateParamDecl, Cache::Yes), Name(Name_), Type(Type_) {} + + template void match(Fn F) const { F(Name, Type); } + + void printLeft(OutputStream &S) const override { + Type->printLeft(S); + if (!Type->hasRHSComponent(S)) + S += " "; + } + + void printRight(OutputStream &S) const override { + Name->print(S); + Type->printRight(S); + } +}; + +/// A template template parameter declaration, +/// 'template typename N'. +class TemplateTemplateParamDecl final : public Node { + Node *Name; + NodeArray Params; + +public: + TemplateTemplateParamDecl(Node *Name_, NodeArray Params_) + : Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_), + Params(Params_) {} + + template void match(Fn F) const { F(Name, Params); } + + void printLeft(OutputStream &S) const override { + S += "template<"; + Params.printWithComma(S); + S += "> typename "; + } + + void printRight(OutputStream &S) const override { + Name->print(S); + } +}; + +/// A template parameter pack declaration, 'typename ...T'. +class TemplateParamPackDecl final : public Node { + Node *Param; + +public: + TemplateParamPackDecl(Node *Param_) + : Node(KTemplateParamPackDecl, Cache::Yes), Param(Param_) {} + + template void match(Fn F) const { F(Param); } + + void printLeft(OutputStream &S) const override { + Param->printLeft(S); + S += "..."; + } + + void printRight(OutputStream &S) const override { + Param->printRight(S); + } +}; + /// An unexpanded parameter pack (either in the expression or type context). If /// this AST is correct, this node will have a ParameterPackExpansion node above /// it. @@ -1410,21 +1538,36 @@ class UnnamedTypeName : public Node { }; class ClosureTypeName : public Node { + NodeArray TemplateParams; NodeArray Params; StringView Count; public: - ClosureTypeName(NodeArray Params_, StringView Count_) - : Node(KClosureTypeName), Params(Params_), Count(Count_) {} + ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_, + StringView Count_) + : Node(KClosureTypeName), TemplateParams(TemplateParams_), + Params(Params_), Count(Count_) {} - template void match(Fn F) const { F(Params, Count); } + template void match(Fn F) const { + F(TemplateParams, Params, Count); + } + + void printDeclarator(OutputStream &S) const { + if (!TemplateParams.empty()) { + S += "<"; + TemplateParams.printWithComma(S); + S += ">"; + } + S += "("; + Params.printWithComma(S); + S += ")"; + } void printLeft(OutputStream &S) const override { S += "\'lambda"; S += Count; - S += "\'("; - Params.printWithComma(S); - S += ")"; + S += "\'"; + printDeclarator(S); } }; @@ -1902,6 +2045,38 @@ class BoolExpr : public Node { } }; +class StringLiteral : public Node { + const Node *Type; + +public: + StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {} + + template void match(Fn F) const { F(Type); } + + void printLeft(OutputStream &S) const override { + S += "\"<"; + Type->print(S); + S += ">\""; + } +}; + +class LambdaExpr : public Node { + const Node *Type; + + void printLambdaDeclarator(OutputStream &S) const; + +public: + LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {} + + template void match(Fn F) const { F(Type); } + + void printLeft(OutputStream &S) const override { + S += "[]"; + printLambdaDeclarator(S); + S += "{...}"; + } +}; + class IntegerCastExpr : public Node { // ty(integer) const Node *Ty; @@ -2034,6 +2209,39 @@ FOR_EACH_NODE_KIND(SPECIALIZATION) #undef FOR_EACH_NODE_KIND +inline void LambdaExpr::printLambdaDeclarator(OutputStream &S) const { + struct LambdaDeclaratorPrinter { + OutputStream &S; + void operator()(const ClosureTypeName *LambdaType) { + LambdaType->printDeclarator(S); + } + + // Walk through any qualifiers to find the lambda-expression. + void operator()(const SpecialName *Name) { + Name->match([&](StringView, const Node *Name) { Name->visit(*this); }); + } + void operator()(const NestedName *Name) { + Name->match([&](const Node *, const Node *Name) { Name->visit(*this); }); + } + void operator()(const LocalName *Name) { + Name->match([&](const Node *, const Node *Name) { Name->visit(*this); }); + } + void operator()(const QualifiedName *Name) { + Name->match([&](const Node *, const Node *Name) { Name->visit(*this); }); + } + void operator()(const GlobalQualifiedName *Name) { + Name->match([&](const Node *Child) { Child->visit(*this); }); + } + void operator()(const StdQualifiedName *Name) { + Name->match([&](const Node *Child) { Child->visit(*this); }); + } + void operator()(const Node *) { + // If we can't find the lambda type, just print '[]{...}'. + } + }; + return Type->visit(LambdaDeclaratorPrinter{S}); +} + template class PODSmallVector { static_assert(std::is_pod::value, @@ -2167,10 +2375,39 @@ template struct AbstractManglingParser { // table. PODSmallVector Subs; + using TemplateParamList = PODSmallVector; + + class ScopedTemplateParamList { + AbstractManglingParser *Parser; + size_t OldNumTemplateParamLists; + TemplateParamList Params; + + public: + ScopedTemplateParamList(AbstractManglingParser *Parser) + : Parser(Parser), + OldNumTemplateParamLists(Parser->TemplateParams.size()) { + Parser->TemplateParams.push_back(&Params); + } + ~ScopedTemplateParamList() { + assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists); + Parser->TemplateParams.dropBack(OldNumTemplateParamLists); + } + void push_back(Node *Param) { + Params.push_back(Param); + } + }; + // Template parameter table. Like the above, but referenced like "T42_". // This has a smaller size compared to Subs and Names because it can be // stored on the stack. - PODSmallVector TemplateParams; + TemplateParamList OuterTemplateParams; + + // Lists of template parameters indexed by template parameter depth, + // referenced like "TL2_4_". If nonempty, element 0 is always + // OuterTemplateParams; inner elements are always template parameter lists of + // lambda expressions. For a generic lambda with no explicit template + // parameter list, the corresponding parameter list pointer will be null. + PODSmallVector TemplateParams; // Set of unresolved forward references. These can occur in a // conversion operator's type, and are resolved in the enclosing . @@ -2178,7 +2415,9 @@ template struct AbstractManglingParser { bool TryToParseTemplateArgs = true; bool PermitForwardTemplateReferences = false; - bool ParsingLambdaParams = false; + size_t ParsingLambdaParamsAtLevel = (size_t)-1; + + unsigned NumSyntheticTemplateParameters[3] = {}; Alloc ASTAllocator; @@ -2193,9 +2432,11 @@ template struct AbstractManglingParser { Names.clear(); Subs.clear(); TemplateParams.clear(); - ParsingLambdaParams = false; + ParsingLambdaParamsAtLevel = (size_t)-1; TryToParseTemplateArgs = true; PermitForwardTemplateReferences = false; + for (int I = 0; I != 3; ++I) + NumSyntheticTemplateParameters[I] = 0; ASTAllocator.reset(); } @@ -2253,6 +2494,7 @@ template struct AbstractManglingParser { bool parseSeqId(size_t *Out); Node *parseSubstitution(); Node *parseTemplateParam(); + Node *parseTemplateParamDecl(); Node *parseTemplateArgs(bool TagTemplates = false); Node *parseTemplateArg(); @@ -2301,9 +2543,10 @@ template struct AbstractManglingParser { size_t E = ForwardTemplateRefs.size(); for (; I < E; ++I) { size_t Idx = ForwardTemplateRefs[I]->Index; - if (Idx >= TemplateParams.size()) + if (TemplateParams.empty() || !TemplateParams[0] || + Idx >= TemplateParams[0]->size()) return true; - ForwardTemplateRefs[I]->Ref = TemplateParams[Idx]; + ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx]; } ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin); return false; @@ -2470,7 +2713,12 @@ AbstractManglingParser::parseUnqualifiedName(NameState *State) { // ::= + # Parameter types or "v" if the lambda has no parameters template Node * -AbstractManglingParser::parseUnnamedTypeName(NameState *) { +AbstractManglingParser::parseUnnamedTypeName(NameState *State) { + // refer to the innermost . Clear out any + // outer args that we may have inserted into TemplateParams. + if (State != nullptr) + TemplateParams.clear(); + if (consumeIf("Ut")) { StringView Count = parseNumber(); if (!consumeIf('_')) @@ -2478,22 +2726,60 @@ AbstractManglingParser::parseUnnamedTypeName(NameState *) { return make(Count); } if (consumeIf("Ul")) { - NodeArray Params; - SwapAndRestore SwapParams(ParsingLambdaParams, true); + SwapAndRestore SwapParams(ParsingLambdaParamsAtLevel, + TemplateParams.size()); + ScopedTemplateParamList LambdaTemplateParams(this); + + size_t ParamsBegin = Names.size(); + while (look() == 'T' && + StringView("yptn").find(look(1)) != StringView::npos) { + Node *T = parseTemplateParamDecl(); + if (!T) + return nullptr; + LambdaTemplateParams.push_back(T); + Names.push_back(T); + } + NodeArray TempParams = popTrailingNodeArray(ParamsBegin); + + // FIXME: If TempParams is empty and none of the function parameters + // includes 'auto', we should remove LambdaTemplateParams from the + // TemplateParams list. Unfortunately, we don't find out whether there are + // any 'auto' parameters until too late in an example such as: + // + // template void f( + // decltype([](decltype([](T v) {}), + // auto) {})) {} + // template void f( + // decltype([](decltype([](T w) {}), + // int) {})) {} + // + // Here, the type of v is at level 2 but the type of w is at level 1. We + // don't find this out until we encounter the type of the next parameter. + // + // However, compilers can't actually cope with the former example in + // practice, and it's likely to be made ill-formed in future, so we don't + // need to support it here. + // + // If we encounter an 'auto' in the function parameter types, we will + // recreate a template parameter scope for it, but any intervening lambdas + // will be parsed in the 'wrong' template parameter depth. + if (TempParams.empty()) + TemplateParams.pop_back(); + if (!consumeIf("vE")) { - size_t ParamsBegin = Names.size(); do { Node *P = getDerived().parseType(); if (P == nullptr) return nullptr; Names.push_back(P); } while (!consumeIf('E')); - Params = popTrailingNodeArray(ParamsBegin); } + NodeArray Params = popTrailingNodeArray(ParamsBegin); + StringView Count = parseNumber(); if (!consumeIf('_')) return nullptr; - return make(Params, Count); + return make(TempParams, Params, Count); } if (consumeIf("Ub")) { (void)parseNumber(); @@ -3624,6 +3910,10 @@ Node *AbstractManglingParser::parseType() { case 's': First += 2; return make("char16_t"); + // ::= Du # char8_t (C++2a, not yet in the Itanium spec) + case 'u': + First += 2; + return make("char8_t"); // ::= Da # auto (in dependent new-expressions) case 'a': First += 2; @@ -3945,6 +4235,7 @@ Node *AbstractManglingParser::parseConversionExpr() { // ::= L E # floating literal // ::= L E # string literal // ::= L E # nullptr literal (i.e., "LDnE") +// ::= L E # lambda expression // FIXME: ::= L _ E # complex floating point literal (C 2000) // ::= L E # external name template @@ -4016,6 +4307,19 @@ Node *AbstractManglingParser::parseExprPrimary() { return R; } return nullptr; + case 'A': { + Node *T = getDerived().parseType(); + if (T == nullptr) + return nullptr; + // FIXME: We need to include the string contents in the mangling. + if (consumeIf('E')) + return make(T); + return nullptr; + } + case 'D': + if (consumeIf("DnE")) + return make("nullptr"); + return nullptr; case 'T': // Invalid mangled name per // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html @@ -4032,7 +4336,7 @@ Node *AbstractManglingParser::parseExprPrimary() { return make(T, N); } if (consumeIf('E')) - return T; + return make(T); return nullptr; } } @@ -5058,11 +5362,22 @@ Node *AbstractManglingParser::parseSubstitution() { // ::= T_ # first template parameter // ::= T _ +// ::= TL __ +// ::= TL _ _ template Node *AbstractManglingParser::parseTemplateParam() { if (!consumeIf('T')) return nullptr; + size_t Level = 0; + if (consumeIf('L')) { + if (parsePositiveInteger(&Level)) + return nullptr; + ++Level; + if (!consumeIf('_')) + return nullptr; + } + size_t Index = 0; if (!consumeIf('_')) { if (parsePositiveInteger(&Index)) @@ -5072,15 +5387,11 @@ Node *AbstractManglingParser::parseTemplateParam() { return nullptr; } - // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter list - // are mangled as the corresponding artificial template type parameter. - if (ParsingLambdaParams) - return make("auto"); - // If we're in a context where this refers to a // further ahead in the mangled name (currently just conversion // operator types), then we should only look it up in the right context. - if (PermitForwardTemplateReferences) { + // This can only happen at the outermost level. + if (PermitForwardTemplateReferences && Level == 0) { Node *ForwardRef = make(Index); if (!ForwardRef) return nullptr; @@ -5090,9 +5401,78 @@ Node *AbstractManglingParser::parseTemplateParam() { return ForwardRef; } - if (Index >= TemplateParams.size()) + if (Level >= TemplateParams.size() || !TemplateParams[Level] || + Index >= TemplateParams[Level]->size()) { + // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter + // list are mangled as the corresponding artificial template type parameter. + if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) { + // This will be popped by the ScopedTemplateParamList in + // parseUnnamedTypeName. + if (Level == TemplateParams.size()) + TemplateParams.push_back(nullptr); + return make("auto"); + } + return nullptr; - return TemplateParams[Index]; + } + + return (*TemplateParams[Level])[Index]; +} + +// ::= Ty # type parameter +// ::= Tn # non-type parameter +// ::= Tt * E # template parameter +// ::= Tp # parameter pack +template +Node *AbstractManglingParser::parseTemplateParamDecl() { + auto InventTemplateParamName = [&](TemplateParamKind Kind) { + unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++; + Node *N = make(Kind, Index); + if (N) TemplateParams.back()->push_back(N); + return N; + }; + + if (consumeIf("Ty")) { + Node *Name = InventTemplateParamName(TemplateParamKind::Type); + if (!Name) + return nullptr; + return make(Name); + } + + if (consumeIf("Tn")) { + Node *Name = InventTemplateParamName(TemplateParamKind::NonType); + if (!Name) + return nullptr; + Node *Type = parseType(); + if (!Type) + return nullptr; + return make(Name, Type); + } + + if (consumeIf("Tt")) { + Node *Name = InventTemplateParamName(TemplateParamKind::Template); + if (!Name) + return nullptr; + size_t ParamsBegin = Names.size(); + ScopedTemplateParamList TemplateTemplateParamParams(this); + while (!consumeIf("E")) { + Node *P = parseTemplateParamDecl(); + if (!P) + return nullptr; + Names.push_back(P); + } + NodeArray Params = popTrailingNodeArray(ParamsBegin); + return make(Name, Params); + } + + if (consumeIf("Tp")) { + Node *P = parseTemplateParamDecl(); + if (!P) + return nullptr; + return make(P); + } + + return nullptr; } // ::= # type or template @@ -5149,8 +5529,11 @@ AbstractManglingParser::parseTemplateArgs(bool TagTemplates) { // refer to the innermost . Clear out any // outer args that we may have inserted into TemplateParams. - if (TagTemplates) + if (TagTemplates) { TemplateParams.clear(); + TemplateParams.push_back(&OuterTemplateParams); + OuterTemplateParams.clear(); + } size_t ArgsBegin = Names.size(); while (!consumeIf('E')) { @@ -5168,7 +5551,7 @@ AbstractManglingParser::parseTemplateArgs(bool TagTemplates) { if (!TableEntry) return nullptr; } - TemplateParams.push_back(TableEntry); + TemplateParams.back()->push_back(TableEntry); } else { Node *Arg = getDerived().parseTemplateArg(); if (Arg == nullptr) diff --git a/third_party/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h b/third_party/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h index da9d9d5..3d47471 100644 --- a/third_party/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h +++ b/third_party/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h @@ -16,6 +16,8 @@ #include "llvm/Demangle/DemangleConfig.h" #include "llvm/Demangle/StringView.h" #include +#include +#include namespace llvm { namespace itanium_demangle { diff --git a/third_party/llvm/lib/Demangle/ItaniumDemangle.cpp b/third_party/llvm/lib/Demangle/ItaniumDemangle.cpp index 5c99c70..760d28b 100644 --- a/third_party/llvm/lib/Demangle/ItaniumDemangle.cpp +++ b/third_party/llvm/lib/Demangle/ItaniumDemangle.cpp @@ -174,6 +174,16 @@ struct DumpVisitor { return printStr("SpecialSubKind::iostream"); } } + void print(TemplateParamKind TPK) { + switch (TPK) { + case TemplateParamKind::Type: + return printStr("TemplateParamKind::Type"); + case TemplateParamKind::NonType: + return printStr("TemplateParamKind::NonType"); + case TemplateParamKind::Template: + return printStr("TemplateParamKind::Template"); + } + } void newLine() { printStr("\n"); From 3ee555c3950884b1a1aad242e37121b036a2679d Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 9 Sep 2019 20:11:10 -0400 Subject: [PATCH 06/10] Update LLVM lib/Demangle from r371274 to r371469 New: - [itanium] bug fixes for C++20 lambda expression extensions Ran: cp ~/src/llvm-project/llvm/include/llvm/Demangle/*.h third_party/llvm/include/llvm/Demangle/ cp ~/src/llvm-project/llvm/lib/Demangle/*.cpp third_party/llvm/lib/Demangle/ cp ~/src/llvm-project/llvm/LICENSE.TXT third_party/llvm/LICENSE.txt Related to #8. --- .../include/llvm/Demangle/ItaniumDemangle.h | 64 +++++-------------- 1 file changed, 16 insertions(+), 48 deletions(-) diff --git a/third_party/llvm/include/llvm/Demangle/ItaniumDemangle.h b/third_party/llvm/include/llvm/Demangle/ItaniumDemangle.h index c1efd7e..7784e84 100644 --- a/third_party/llvm/include/llvm/Demangle/ItaniumDemangle.h +++ b/third_party/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -2063,8 +2063,6 @@ class StringLiteral : public Node { class LambdaExpr : public Node { const Node *Type; - void printLambdaDeclarator(OutputStream &S) const; - public: LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {} @@ -2072,7 +2070,8 @@ class LambdaExpr : public Node { void printLeft(OutputStream &S) const override { S += "[]"; - printLambdaDeclarator(S); + if (Type->getKind() == KClosureTypeName) + static_cast(Type)->printDeclarator(S); S += "{...}"; } }; @@ -2209,39 +2208,6 @@ FOR_EACH_NODE_KIND(SPECIALIZATION) #undef FOR_EACH_NODE_KIND -inline void LambdaExpr::printLambdaDeclarator(OutputStream &S) const { - struct LambdaDeclaratorPrinter { - OutputStream &S; - void operator()(const ClosureTypeName *LambdaType) { - LambdaType->printDeclarator(S); - } - - // Walk through any qualifiers to find the lambda-expression. - void operator()(const SpecialName *Name) { - Name->match([&](StringView, const Node *Name) { Name->visit(*this); }); - } - void operator()(const NestedName *Name) { - Name->match([&](const Node *, const Node *Name) { Name->visit(*this); }); - } - void operator()(const LocalName *Name) { - Name->match([&](const Node *, const Node *Name) { Name->visit(*this); }); - } - void operator()(const QualifiedName *Name) { - Name->match([&](const Node *, const Node *Name) { Name->visit(*this); }); - } - void operator()(const GlobalQualifiedName *Name) { - Name->match([&](const Node *Child) { Child->visit(*this); }); - } - void operator()(const StdQualifiedName *Name) { - Name->match([&](const Node *Child) { Child->visit(*this); }); - } - void operator()(const Node *) { - // If we can't find the lambda type, just print '[]{...}'. - } - }; - return Type->visit(LambdaDeclaratorPrinter{S}); -} - template class PODSmallVector { static_assert(std::is_pod::value, @@ -2392,9 +2358,6 @@ template struct AbstractManglingParser { assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists); Parser->TemplateParams.dropBack(OldNumTemplateParamLists); } - void push_back(Node *Param) { - Params.push_back(Param); - } }; // Template parameter table. Like the above, but referenced like "T42_". @@ -2736,7 +2699,6 @@ AbstractManglingParser::parseUnnamedTypeName(NameState *State) { Node *T = parseTemplateParamDecl(); if (!T) return nullptr; - LambdaTemplateParams.push_back(T); Names.push_back(T); } NodeArray TempParams = popTrailingNodeArray(ParamsBegin); @@ -4324,20 +4286,26 @@ Node *AbstractManglingParser::parseExprPrimary() { // Invalid mangled name per // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html return nullptr; + case 'U': { + // FIXME: Should we support LUb... for block literals? + if (look(1) != 'l') + return nullptr; + Node *T = parseUnnamedTypeName(nullptr); + if (!T || !consumeIf('E')) + return nullptr; + return make(T); + } default: { // might be named type Node *T = getDerived().parseType(); if (T == nullptr) return nullptr; StringView N = parseNumber(); - if (!N.empty()) { - if (!consumeIf('E')) - return nullptr; - return make(T, N); - } - if (consumeIf('E')) - return make(T); - return nullptr; + if (N.empty()) + return nullptr; + if (!consumeIf('E')) + return nullptr; + return make(T, N); } } } From 02a96231c80321f39be1d9cc8a69d4bff1c42bcf Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 23 Sep 2019 09:15:06 -0400 Subject: [PATCH 07/10] Update LLVM lib/Demangle from r371469 to r372602 New: - [ms] demangle rtti descriptor names Ran: cp ~/src/llvm-project/llvm/include/llvm/Demangle/*.h third_party/llvm/include/llvm/Demangle/ cp ~/src/llvm-project/llvm/lib/Demangle/*.cpp third_party/llvm/lib/Demangle/ cp ~/src/llvm-project/llvm/LICENSE.TXT third_party/llvm/LICENSE.txt Related to #9. --- demumble_test.py | 1 + .../include/llvm/Demangle/MicrosoftDemangle.h | 1 + .../llvm/Demangle/MicrosoftDemangleNodes.h | 2 -- .../llvm/lib/Demangle/MicrosoftDemangle.cpp | 18 ++++++++++++++++++ .../lib/Demangle/MicrosoftDemangleNodes.cpp | 2 -- 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/demumble_test.py b/demumble_test.py index 2e0097b..2a6d9ab 100755 --- a/demumble_test.py +++ b/demumble_test.py @@ -39,6 +39,7 @@ ('demumble -bx < bar', re.compile(".*unrecognized option `x' in `-bx'.*")), ('demumble < _ZZ3fooiENK3$_0clEi', 'foo(int)::$_0::operator()(int) const\n'), + ('demumble .?AVNet@@', "class Net `RTTI Type Descriptor Name'\n"), ] status = 0 diff --git a/third_party/llvm/include/llvm/Demangle/MicrosoftDemangle.h b/third_party/llvm/include/llvm/Demangle/MicrosoftDemangle.h index 382e794..c6f2606 100644 --- a/third_party/llvm/include/llvm/Demangle/MicrosoftDemangle.h +++ b/third_party/llvm/include/llvm/Demangle/MicrosoftDemangle.h @@ -158,6 +158,7 @@ class Demangler { QualifiedNameNode *QN); SymbolNode *demangleDeclarator(StringView &MangledName); SymbolNode *demangleMD5Name(StringView &MangledName); + SymbolNode *demangleTypeinfoName(StringView &MangledName); VariableSymbolNode *demangleVariableEncoding(StringView &MangledName, StorageClass SC); diff --git a/third_party/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h b/third_party/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h index 3d47471..37abede 100644 --- a/third_party/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h +++ b/third_party/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h @@ -303,8 +303,6 @@ struct TypeNode : public Node { outputPost(OS, Flags); } - void outputQuals(bool SpaceBefore, bool SpaceAfter) const; - Qualifiers Quals = Q_None; }; diff --git a/third_party/llvm/lib/Demangle/MicrosoftDemangle.cpp b/third_party/llvm/lib/Demangle/MicrosoftDemangle.cpp index bf7d776..4be6e5a 100644 --- a/third_party/llvm/lib/Demangle/MicrosoftDemangle.cpp +++ b/third_party/llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -783,8 +783,26 @@ SymbolNode *Demangler::demangleMD5Name(StringView &MangledName) { return S; } +SymbolNode *Demangler::demangleTypeinfoName(StringView &MangledName) { + assert(MangledName.startsWith('.')); + MangledName.consumeFront('.'); + + TypeNode *T = demangleType(MangledName, QualifierMangleMode::Result); + if (Error || !MangledName.empty()) { + Error = true; + return nullptr; + } + return synthesizeVariable(Arena, T, "`RTTI Type Descriptor Name'"); +} + // Parser entry point. SymbolNode *Demangler::parse(StringView &MangledName) { + // Typeinfo names are strings stored in RTTI data. They're not symbol names. + // It's still useful to demangle them. They're the only demangled entity + // that doesn't start with a "?" but a ".". + if (MangledName.startsWith('.')) + return demangleTypeinfoName(MangledName); + if (MangledName.startsWith("??@")) return demangleMD5Name(MangledName); diff --git a/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp b/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp index 63ca475..10363dc 100644 --- a/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp +++ b/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp @@ -120,8 +120,6 @@ std::string Node::toString(OutputFlags Flags) const { return {OS.getBuffer()}; } -void TypeNode::outputQuals(bool SpaceBefore, bool SpaceAfter) const {} - void PrimitiveTypeNode::outputPre(OutputStream &OS, OutputFlags Flags) const { switch (PrimKind) { OUTPUT_ENUM_CLASS_VALUE(PrimitiveKind, Void, "void"); From 2c27bea3cc2ceb6e5e6b8fe1875f31d162c7685a Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 18 May 2020 16:10:47 -0400 Subject: [PATCH 08/10] Update LLVM lib/Demangle from r372602 / da298aa9 to 1c1fb359. New: - [itanium] fix demangling of enums with negative values - [itanium] support for 'this' expressions Ran: cp ~/src/llvm-project/llvm/include/llvm/Demangle/*.h third_party/llvm/include/llvm/Demangle/ cp ~/src/llvm-project/llvm/lib/Demangle/*.cpp third_party/llvm/lib/Demangle/ cp ~/src/llvm-project/llvm/LICENSE.TXT third_party/llvm/LICENSE.txt --- .../llvm/include/llvm/Demangle/Demangle.h | 9 +- .../include/llvm/Demangle/ItaniumDemangle.h | 113 +++++++----------- .../llvm/Demangle/MicrosoftDemangleNodes.h | 7 +- .../llvm/include/llvm/Demangle/Utility.h | 8 +- .../llvm/lib/Demangle/ItaniumDemangle.cpp | 14 +-- .../llvm/lib/Demangle/MicrosoftDemangle.cpp | 14 ++- .../lib/Demangle/MicrosoftDemangleNodes.cpp | 49 +++++--- 7 files changed, 106 insertions(+), 108 deletions(-) diff --git a/third_party/llvm/include/llvm/Demangle/Demangle.h b/third_party/llvm/include/llvm/Demangle/Demangle.h index 6fea7ef..7b85b9a 100644 --- a/third_party/llvm/include/llvm/Demangle/Demangle.h +++ b/third_party/llvm/include/llvm/Demangle/Demangle.h @@ -32,7 +32,14 @@ char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n, int *status); -enum MSDemangleFlags { MSDF_None = 0, MSDF_DumpBackrefs = 1 << 0 }; +enum MSDemangleFlags { + MSDF_None = 0, + MSDF_DumpBackrefs = 1 << 0, + MSDF_NoAccessSpecifier = 1 << 1, + MSDF_NoCallingConvention = 1 << 2, + MSDF_NoReturnType = 1 << 3, + MSDF_NoMemberType = 1 << 4, +}; char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n, int *status, MSDemangleFlags Flags = MSDF_None); diff --git a/third_party/llvm/include/llvm/Demangle/ItaniumDemangle.h b/third_party/llvm/include/llvm/Demangle/ItaniumDemangle.h index 7784e84..dcece38 100644 --- a/third_party/llvm/include/llvm/Demangle/ItaniumDemangle.h +++ b/third_party/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -98,7 +98,7 @@ X(BoolExpr) \ X(StringLiteral) \ X(LambdaExpr) \ - X(IntegerCastExpr) \ + X(EnumLiteral) \ X(IntegerLiteral) \ X(FloatLiteral) \ X(DoubleLiteral) \ @@ -607,48 +607,12 @@ class PointerToMemberType final : public Node { } }; -class NodeOrString { - const void *First; - const void *Second; - -public: - /* implicit */ NodeOrString(StringView Str) { - const char *FirstChar = Str.begin(); - const char *SecondChar = Str.end(); - if (SecondChar == nullptr) { - assert(FirstChar == SecondChar); - ++FirstChar, ++SecondChar; - } - First = static_cast(FirstChar); - Second = static_cast(SecondChar); - } - - /* implicit */ NodeOrString(Node *N) - : First(static_cast(N)), Second(nullptr) {} - NodeOrString() : First(nullptr), Second(nullptr) {} - - bool isString() const { return Second && First; } - bool isNode() const { return First && !Second; } - bool isEmpty() const { return !First && !Second; } - - StringView asString() const { - assert(isString()); - return StringView(static_cast(First), - static_cast(Second)); - } - - const Node *asNode() const { - assert(isNode()); - return static_cast(First); - } -}; - class ArrayType final : public Node { const Node *Base; - NodeOrString Dimension; + Node *Dimension; public: - ArrayType(const Node *Base_, NodeOrString Dimension_) + ArrayType(const Node *Base_, Node *Dimension_) : Node(KArrayType, /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::Yes), @@ -665,10 +629,8 @@ class ArrayType final : public Node { if (S.back() != ']') S += " "; S += "["; - if (Dimension.isString()) - S += Dimension.asString(); - else if (Dimension.isNode()) - Dimension.asNode()->print(S); + if (Dimension) + Dimension->print(S); S += "]"; Base->printRight(S); } @@ -934,10 +896,10 @@ class QualifiedName final : public Node { class VectorType final : public Node { const Node *BaseType; - const NodeOrString Dimension; + const Node *Dimension; public: - VectorType(const Node *BaseType_, NodeOrString Dimension_) + VectorType(const Node *BaseType_, Node *Dimension_) : Node(KVectorType), BaseType(BaseType_), Dimension(Dimension_) {} @@ -946,19 +908,17 @@ class VectorType final : public Node { void printLeft(OutputStream &S) const override { BaseType->print(S); S += " vector["; - if (Dimension.isNode()) - Dimension.asNode()->print(S); - else if (Dimension.isString()) - S += Dimension.asString(); + if (Dimension) + Dimension->print(S); S += "]"; } }; class PixelVectorType final : public Node { - const NodeOrString Dimension; + const Node *Dimension; public: - PixelVectorType(NodeOrString Dimension_) + PixelVectorType(const Node *Dimension_) : Node(KPixelVectorType), Dimension(Dimension_) {} template void match(Fn F) const { F(Dimension); } @@ -966,7 +926,7 @@ class PixelVectorType final : public Node { void printLeft(OutputStream &S) const override { // FIXME: This should demangle as "vector pixel". S += "pixel vector["; - S += Dimension.asString(); + Dimension->print(S); S += "]"; } }; @@ -2076,22 +2036,26 @@ class LambdaExpr : public Node { } }; -class IntegerCastExpr : public Node { +class EnumLiteral : public Node { // ty(integer) const Node *Ty; StringView Integer; public: - IntegerCastExpr(const Node *Ty_, StringView Integer_) - : Node(KIntegerCastExpr), Ty(Ty_), Integer(Integer_) {} + EnumLiteral(const Node *Ty_, StringView Integer_) + : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {} template void match(Fn F) const { F(Ty, Integer); } void printLeft(OutputStream &S) const override { - S += "("; + S << "("; Ty->print(S); - S += ")"; - S += Integer; + S << ")"; + + if (Integer[0] == 'n') + S << "-" << Integer.dropFront(1); + else + S << Integer; } }; @@ -2213,10 +2177,10 @@ class PODSmallVector { static_assert(std::is_pod::value, "T is required to be a plain old data type"); - T* First; - T* Last; - T* Cap; - T Inline[N]; + T* First = nullptr; + T* Last = nullptr; + T* Cap = nullptr; + T Inline[N] = {0}; bool isInline() const { return First == Inline; } @@ -3548,7 +3512,9 @@ Node *AbstractManglingParser::parseVectorType() { if (!consumeIf("Dv")) return nullptr; if (look() >= '1' && look() <= '9') { - StringView DimensionNumber = parseNumber(); + Node *DimensionNumber = make(parseNumber()); + if (!DimensionNumber) + return nullptr; if (!consumeIf('_')) return nullptr; if (consumeIf('p')) @@ -3573,7 +3539,7 @@ Node *AbstractManglingParser::parseVectorType() { Node *ElemType = getDerived().parseType(); if (!ElemType) return nullptr; - return make(ElemType, StringView()); + return make(ElemType, /*Dimension=*/nullptr); } // ::= Dt E # decltype of an id-expression or class member access (C++0x) @@ -3599,10 +3565,12 @@ Node *AbstractManglingParser::parseArrayType() { if (!consumeIf('A')) return nullptr; - NodeOrString Dimension; + Node *Dimension = nullptr; if (std::isdigit(look())) { - Dimension = parseNumber(); + Dimension = make(parseNumber()); + if (!Dimension) + return nullptr; if (!consumeIf('_')) return nullptr; } else if (!consumeIf('_')) { @@ -4100,8 +4068,11 @@ Qualifiers AbstractManglingParser::parseCVQualifiers() { // ::= fp _ # L == 0, second and later parameters // ::= fL p _ # L > 0, first parameter // ::= fL p _ # L > 0, second and later parameters +// ::= fpT # 'this' expression (not part of standard?) template Node *AbstractManglingParser::parseFunctionParam() { + if (consumeIf("fpT")) + return make("this"); if (consumeIf("fp")) { parseCVQualifiers(); StringView Num = parseNumber(); @@ -4261,7 +4232,13 @@ Node *AbstractManglingParser::parseExprPrimary() { return getDerived().template parseFloatingLiteral(); case 'e': ++First; +#if defined(__powerpc__) || defined(__s390__) + // Handle cases where long doubles encoded with e have the same size + // and representation as doubles. + return getDerived().template parseFloatingLiteral(); +#else return getDerived().template parseFloatingLiteral(); +#endif case '_': if (consumeIf("_Z")) { Node *R = getDerived().parseEncoding(); @@ -4300,12 +4277,12 @@ Node *AbstractManglingParser::parseExprPrimary() { Node *T = getDerived().parseType(); if (T == nullptr) return nullptr; - StringView N = parseNumber(); + StringView N = parseNumber(/*AllowNegative=*/true); if (N.empty()) return nullptr; if (!consumeIf('E')) return nullptr; - return make(T, N); + return make(T, N); } } } diff --git a/third_party/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h b/third_party/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h index 37abede..ec40eec 100644 --- a/third_party/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h +++ b/third_party/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h @@ -75,6 +75,9 @@ enum OutputFlags { OF_Default = 0, OF_NoCallingConvention = 1, OF_NoTagSpecifier = 2, + OF_NoAccessSpecifier = 4, + OF_NoMemberType = 8, + OF_NoReturnType = 16, }; // Types @@ -505,7 +508,7 @@ struct CustomTypeNode : public TypeNode { void outputPre(OutputStream &OS, OutputFlags Flags) const override; void outputPost(OutputStream &OS, OutputFlags Flags) const override; - IdentifierNode *Identifier; + IdentifierNode *Identifier = nullptr; }; struct NodeArrayNode : public Node { @@ -581,7 +584,7 @@ struct SpecialTableSymbolNode : public SymbolNode { void output(OutputStream &OS, OutputFlags Flags) const override; QualifiedNameNode *TargetName = nullptr; - Qualifiers Quals; + Qualifiers Quals = Qualifiers::Q_None; }; struct LocalStaticGuardVariableNode : public SymbolNode { diff --git a/third_party/llvm/include/llvm/Demangle/Utility.h b/third_party/llvm/include/llvm/Demangle/Utility.h index ec23859..04e1936 100644 --- a/third_party/llvm/include/llvm/Demangle/Utility.h +++ b/third_party/llvm/include/llvm/Demangle/Utility.h @@ -25,9 +25,9 @@ DEMANGLE_NAMESPACE_BEGIN // Stream that AST nodes write their string representation into after the AST // has been parsed. class OutputStream { - char *Buffer; - size_t CurrentPosition; - size_t BufferCapacity; + char *Buffer = nullptr; + size_t CurrentPosition = 0; + size_t BufferCapacity = 0; // Ensure there is at least n more positions in buffer. void grow(size_t N) { @@ -137,7 +137,7 @@ class OutputStream { char *getBuffer() { return Buffer; } char *getBufferEnd() { return Buffer + CurrentPosition - 1; } - size_t getBufferCapacity() { return BufferCapacity; } + size_t getBufferCapacity() const { return BufferCapacity; } }; template class SwapAndRestore { diff --git a/third_party/llvm/lib/Demangle/ItaniumDemangle.cpp b/third_party/llvm/lib/Demangle/ItaniumDemangle.cpp index 760d28b..fad9b6b 100644 --- a/third_party/llvm/lib/Demangle/ItaniumDemangle.cpp +++ b/third_party/llvm/lib/Demangle/ItaniumDemangle.cpp @@ -89,14 +89,6 @@ struct DumpVisitor { else printStr(""); } - void print(NodeOrString NS) { - if (NS.isNode()) - print(NS.asNode()); - else if (NS.isString()) - print(NS.asString()); - else - printStr("NodeOrString()"); - } void print(NodeArray A) { ++Depth; printStr("{"); @@ -115,13 +107,11 @@ struct DumpVisitor { // Overload used when T is exactly 'bool', not merely convertible to 'bool'. void print(bool B) { printStr(B ? "true" : "false"); } - template - typename std::enable_if::value>::type print(T N) { + template std::enable_if_t::value> print(T N) { fprintf(stderr, "%llu", (unsigned long long)N); } - template - typename std::enable_if::value>::type print(T N) { + template std::enable_if_t::value> print(T N) { fprintf(stderr, "%lld", (long long)N); } diff --git a/third_party/llvm/lib/Demangle/MicrosoftDemangle.cpp b/third_party/llvm/lib/Demangle/MicrosoftDemangle.cpp index 4be6e5a..c681d6e 100644 --- a/third_party/llvm/lib/Demangle/MicrosoftDemangle.cpp +++ b/third_party/llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -2179,7 +2179,7 @@ NodeArrayNode *Demangler::demangleFunctionParameterList(StringView &MangledName, NodeArrayNode * Demangler::demangleTemplateParameterList(StringView &MangledName) { - NodeList *Head; + NodeList *Head = nullptr; NodeList **Current = &Head; size_t Count = 0; @@ -2346,12 +2346,22 @@ char *llvm::microsoftDemangle(const char *MangledName, char *Buf, size_t *N, if (Flags & MSDF_DumpBackrefs) D.dumpBackReferences(); + OutputFlags OF = OF_Default; + if (Flags & MSDF_NoCallingConvention) + OF = OutputFlags(OF | OF_NoCallingConvention); + if (Flags & MSDF_NoAccessSpecifier) + OF = OutputFlags(OF | OF_NoAccessSpecifier); + if (Flags & MSDF_NoReturnType) + OF = OutputFlags(OF | OF_NoReturnType); + if (Flags & MSDF_NoMemberType) + OF = OutputFlags(OF | OF_NoMemberType); + if (D.Error) InternalStatus = demangle_invalid_mangled_name; else if (!initializeOutputStream(Buf, N, S, 1024)) InternalStatus = demangle_memory_alloc_failure; else { - AST->output(S, OF_Default); + AST->output(S, OF); S += '\0'; if (N != nullptr) *N = S.getCurrentPosition(); diff --git a/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp b/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp index 10363dc..9cee975 100644 --- a/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp +++ b/third_party/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp @@ -378,24 +378,28 @@ void LiteralOperatorIdentifierNode::output(OutputStream &OS, void FunctionSignatureNode::outputPre(OutputStream &OS, OutputFlags Flags) const { - if (FunctionClass & FC_Public) - OS << "public: "; - if (FunctionClass & FC_Protected) - OS << "protected: "; - if (FunctionClass & FC_Private) - OS << "private: "; - - if (!(FunctionClass & FC_Global)) { - if (FunctionClass & FC_Static) - OS << "static "; + if (!(Flags & OF_NoAccessSpecifier)) { + if (FunctionClass & FC_Public) + OS << "public: "; + if (FunctionClass & FC_Protected) + OS << "protected: "; + if (FunctionClass & FC_Private) + OS << "private: "; } - if (FunctionClass & FC_Virtual) - OS << "virtual "; - if (FunctionClass & FC_ExternC) - OS << "extern \"C\" "; + if (!(Flags & OF_NoMemberType)) { + if (!(FunctionClass & FC_Global)) { + if (FunctionClass & FC_Static) + OS << "static "; + } + if (FunctionClass & FC_Virtual) + OS << "virtual "; + + if (FunctionClass & FC_ExternC) + OS << "extern \"C\" "; + } - if (ReturnType) { + if (!(Flags & OF_NoReturnType) && ReturnType) { ReturnType->outputPre(OS, Flags); OS << " "; } @@ -438,7 +442,7 @@ void FunctionSignatureNode::outputPost(OutputStream &OS, else if (RefQualifier == FunctionRefQualifier::RValueReference) OS << " &&"; - if (ReturnType) + if (!(Flags & OF_NoReturnType) && ReturnType) ReturnType->outputPost(OS, Flags); } @@ -580,19 +584,26 @@ void FunctionSymbolNode::output(OutputStream &OS, OutputFlags Flags) const { } void VariableSymbolNode::output(OutputStream &OS, OutputFlags Flags) const { + const char *AccessSpec = nullptr; + bool IsStatic = true; switch (SC) { case StorageClass::PrivateStatic: - OS << "private: static "; + AccessSpec = "private"; break; case StorageClass::PublicStatic: - OS << "public: static "; + AccessSpec = "public"; break; case StorageClass::ProtectedStatic: - OS << "protected: static "; + AccessSpec = "protected"; break; default: + IsStatic = false; break; } + if (!(Flags & OF_NoAccessSpecifier) && AccessSpec) + OS << AccessSpec << ": "; + if (!(Flags & OF_NoMemberType) && IsStatic) + OS << "static "; if (Type) { Type->outputPre(OS, Flags); From 767b5dc862af0a2eae7609a2963d46fb84b8828a Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 18 May 2020 16:41:57 -0400 Subject: [PATCH 09/10] derust dist.py --- dist.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dist.py b/dist.py index cbe9413..b1be851 100755 --- a/dist.py +++ b/dist.py @@ -2,9 +2,9 @@ # Builds demumble for Mac, Linux, Windows. Must run on a Mac. # Needs a chromium checkout at ~/src/chrome/src that was synced with -# target_os=['win'] to get the Windows toolchain. You must run -# `build/linux/sysroot_scripts/install-sysroot.py --arch amd64` once to -# get the linux toolchain. +# target_os=['win'] to get the Windows toolchain, and to get lld. +# You must run `build/linux/sysroot_scripts/install-sysroot.py --arch amd64` +# once to get the linux toolchain. # Also needs a GN build of llvm at ~/src/llvm-project/out/gn for llvm-strip # for stripping the Linux binary. @@ -61,7 +61,7 @@ def buildir(newdir): devnull = open(os.devnull,"w") # Linux. -linux_sysroot = crsrc + '/build/linux/debian_jessie_amd64-sysroot' +linux_sysroot = crsrc + '/build/linux/debian_sid_amd64-sysroot' cflags = [ '--sysroot', linux_sysroot, '--target=x86_64-linux-gnu', ] ldflags = ['-fuse-ld=lld'] + cflags with buildir('buildlinux'): From fd9f64434ff9a2d24cd8222d446cd9a5b0010bdc Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 18 May 2020 16:44:17 -0400 Subject: [PATCH 10/10] mark this 1.2.2.git --- demumble.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demumble.cc b/demumble.cc index 835dbbe..3d282bc 100644 --- a/demumble.cc +++ b/demumble.cc @@ -6,7 +6,7 @@ #include "llvm/Demangle/Demangle.h" -const char kDemumbleVersion[] = "1.2.1.git"; +const char kDemumbleVersion[] = "1.2.2.git"; static int print_help(FILE* out) { fprintf(out,