[llvm] r371274 - Synchronize LLVM's copy of libc++abi's demangler with the libc++abi
Richard Smith via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 6 17:11:53 PDT 2019
Author: rsmith
Date: Fri Sep 6 17:11:53 2019
New Revision: 371274
URL: http://llvm.org/viewvc/llvm-project?rev=371274&view=rev
Log:
Synchronize LLVM's copy of libc++abi's demangler with the libc++abi
version after r371273.
Also fix a minor issue in r371273 that only surfaced after template
instantiation from LLVM's use of the demangler.
Modified:
llvm/trunk/include/llvm/Demangle/ItaniumDemangle.h
llvm/trunk/lib/Demangle/ItaniumDemangle.cpp
Modified: llvm/trunk/include/llvm/Demangle/ItaniumDemangle.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Demangle/ItaniumDemangle.h?rev=371274&r1=371273&r2=371274&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Demangle/ItaniumDemangle.h (original)
+++ llvm/trunk/include/llvm/Demangle/ItaniumDemangle.h Fri Sep 6 17:11:53 2019
@@ -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
return Q1 = static_cast<Qualifiers>(Q1 | Q2);
}
-class QualType : public Node {
+class QualType final : public Node {
protected:
const Qualifiers Quals;
const Node *Child;
@@ -964,6 +971,127 @@ public:
}
};
+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 <lambda-sig> for a lambda with
+/// explicit template arguments, which might be referenced in the parameter
+/// types appearing later in the <lambda-sig>.
+class SyntheticTemplateParamName final : public Node {
+ TemplateParamKind Kind;
+ unsigned Index;
+
+public:
+ SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_)
+ : Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {}
+
+ template<typename Fn> 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<typename Fn> 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<typename Fn> 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 T> 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<typename Fn> 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<typename Fn> 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 @@ public:
};
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<typename Fn> void match(Fn F) const {
+ F(TemplateParams, Params, Count);
+ }
- template<typename Fn> void match(Fn F) const { F(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 @@ public:
}
};
+class StringLiteral : public Node {
+ const Node *Type;
+
+public:
+ StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
+
+ template<typename Fn> 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<typename Fn> 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 T, size_t N>
class PODSmallVector {
static_assert(std::is_pod<T>::value,
@@ -2167,10 +2375,39 @@ template <typename Derived, typename All
// table.
PODSmallVector<Node *, 32> Subs;
+ using TemplateParamList = PODSmallVector<Node *, 8>;
+
+ 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<Node *, 8> 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<TemplateParamList *, 4> TemplateParams;
// Set of unresolved forward <template-param> references. These can occur in a
// conversion operator's type, and are resolved in the enclosing <encoding>.
@@ -2178,7 +2415,9 @@ template <typename Derived, typename All
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 <typename Derived, typename All
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 <typename Derived, typename All
bool parseSeqId(size_t *Out);
Node *parseSubstitution();
Node *parseTemplateParam();
+ Node *parseTemplateParamDecl();
Node *parseTemplateArgs(bool TagTemplates = false);
Node *parseTemplateArg();
@@ -2301,9 +2543,10 @@ template <typename Derived, typename All
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<Derived, Alloc>::
// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
template <typename Derived, typename Alloc>
Node *
-AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *) {
+AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
+ // <template-params> refer to the innermost <template-args>. 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<Derived, Alloc>::
return make<UnnamedTypeName>(Count);
}
if (consumeIf("Ul")) {
- NodeArray Params;
- SwapAndRestore<bool> SwapParams(ParsingLambdaParams, true);
+ SwapAndRestore<size_t> 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<typename T> void f(
+ // decltype([](decltype([]<typename T>(T v) {}),
+ // auto) {})) {}
+ // template<typename T> void f(
+ // decltype([](decltype([]<typename T>(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<ClosureTypeName>(Params, Count);
+ return make<ClosureTypeName>(TempParams, Params, Count);
}
if (consumeIf("Ub")) {
(void)parseNumber();
@@ -3949,6 +4235,7 @@ Node *AbstractManglingParser<Derived, Al
// ::= L <type> <value float> E # floating literal
// ::= L <string type> E # string literal
// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
+// ::= L <lambda type> E # lambda expression
// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
// ::= L <mangled-name> E # external name
template <typename Derived, typename Alloc>
@@ -4020,6 +4307,19 @@ Node *AbstractManglingParser<Derived, Al
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<StringLiteral>(T);
+ return nullptr;
+ }
+ case 'D':
+ if (consumeIf("DnE"))
+ return make<NameType>("nullptr");
+ return nullptr;
case 'T':
// Invalid mangled name per
// http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
@@ -4036,7 +4336,7 @@ Node *AbstractManglingParser<Derived, Al
return make<IntegerCastExpr>(T, N);
}
if (consumeIf('E'))
- return T;
+ return make<LambdaExpr>(T);
return nullptr;
}
}
@@ -5062,11 +5362,22 @@ Node *AbstractManglingParser<Derived, Al
// <template-param> ::= T_ # first template parameter
// ::= T <parameter-2 non-negative number> _
+// ::= TL <level-1> __
+// ::= TL <level-1> _ <parameter-2 non-negative number> _
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::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))
@@ -5076,15 +5387,11 @@ Node *AbstractManglingParser<Derived, Al
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<NameType>("auto");
-
// If we're in a context where this <template-param> refers to a
// <template-arg> 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<ForwardTemplateReference>(Index);
if (!ForwardRef)
return nullptr;
@@ -5094,9 +5401,78 @@ Node *AbstractManglingParser<Derived, Al
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<NameType>("auto");
+ }
+
return nullptr;
- return TemplateParams[Index];
+ }
+
+ return (*TemplateParams[Level])[Index];
+}
+
+// <template-param-decl> ::= Ty # type parameter
+// ::= Tn <type> # non-type parameter
+// ::= Tt <template-param-decl>* E # template parameter
+// ::= Tp <template-param-decl> # parameter pack
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
+ auto InventTemplateParamName = [&](TemplateParamKind Kind) {
+ unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
+ Node *N = make<SyntheticTemplateParamName>(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<TypeTemplateParamDecl>(Name);
+ }
+
+ if (consumeIf("Tn")) {
+ Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
+ if (!Name)
+ return nullptr;
+ Node *Type = parseType();
+ if (!Type)
+ return nullptr;
+ return make<NonTypeTemplateParamDecl>(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<TemplateTemplateParamDecl>(Name, Params);
+ }
+
+ if (consumeIf("Tp")) {
+ Node *P = parseTemplateParamDecl();
+ if (!P)
+ return nullptr;
+ return make<TemplateParamPackDecl>(P);
+ }
+
+ return nullptr;
}
// <template-arg> ::= <type> # type or template
@@ -5153,8 +5529,11 @@ AbstractManglingParser<Derived, Alloc>::
// <template-params> refer to the innermost <template-args>. 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')) {
@@ -5172,7 +5551,7 @@ AbstractManglingParser<Derived, Alloc>::
if (!TableEntry)
return nullptr;
}
- TemplateParams.push_back(TableEntry);
+ TemplateParams.back()->push_back(TableEntry);
} else {
Node *Arg = getDerived().parseTemplateArg();
if (Arg == nullptr)
Modified: llvm/trunk/lib/Demangle/ItaniumDemangle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Demangle/ItaniumDemangle.cpp?rev=371274&r1=371273&r2=371274&view=diff
==============================================================================
--- llvm/trunk/lib/Demangle/ItaniumDemangle.cpp (original)
+++ llvm/trunk/lib/Demangle/ItaniumDemangle.cpp Fri Sep 6 17:11:53 2019
@@ -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");
More information about the llvm-commits
mailing list