From 6b6cb515dace99947c58ddaa97ceffe3ca8600c4 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Sat, 7 Sep 2019 09:16:13 -0400 Subject: [PATCH] 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");