forked from OSchip/llvm-project
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:
parent
4bbe85c5d4
commit
0e881b9f5d
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue