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.

llvm-svn: 371274
This commit is contained in:
Richard Smith 2019-09-07 00:11:53 +00:00
parent 4bbe85c5d4
commit 0e881b9f5d
3 changed files with 420 additions and 30 deletions

View File

@ -2435,7 +2435,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
ParsingLambdaParamsAtLevel = (size_t)-1;
TryToParseTemplateArgs = true;
PermitForwardTemplateReferences = false;
NumSyntheticTemplateParameters = {};
for (int I = 0; I != 3; ++I)
NumSyntheticTemplateParameters[I] = 0;
ASTAllocator.reset();
}

View File

@ -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<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(Params, Count); }
template<typename Fn> 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 @@ 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 Alloc> struct AbstractManglingParser {
// 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 Alloc> 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 <typename Derived, typename Alloc> 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 <typename Derived, typename Alloc> 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 <typename Derived, typename Alloc> 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<Derived, Alloc>::parseUnqualifiedName(NameState *State) {
// <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>::parseUnnamedTypeName(NameState *) {
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, Alloc>::parseConversionExpr() {
// ::= 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, Alloc>::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<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, Alloc>::parseExprPrimary() {
return make<IntegerCastExpr>(T, N);
}
if (consumeIf('E'))
return T;
return make<LambdaExpr>(T);
return nullptr;
}
}
@ -5062,11 +5362,22 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
// <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, Alloc>::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<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, Alloc>::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<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>::parseTemplateArgs(bool TagTemplates) {
// <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>::parseTemplateArgs(bool TagTemplates) {
if (!TableEntry)
return nullptr;
}
TemplateParams.push_back(TableEntry);
TemplateParams.back()->push_back(TableEntry);
} else {
Node *Arg = getDerived().parseTemplateArg();
if (Arg == nullptr)

View File

@ -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");