Expand Up
@@ -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) \
Expand Down
Expand Up
@@ -91,6 +96,8 @@
X(ThrowExpr) \
X(UUIDOfExpr) \
X(BoolExpr) \
X(StringLiteral) \
X(LambdaExpr) \
X(IntegerCastExpr) \
X(IntegerLiteral) \
X(FloatLiteral) \
Expand Down
Expand Up
@@ -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;
Expand Down
Expand Up
@@ -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 <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.
Expand Down
Expand Up
@@ -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 <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);
}
};
Expand Down
Expand Up
@@ -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 <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;
Expand Down
Expand Up
@@ -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,
Expand Down
Expand Up
@@ -2167,18 +2375,49 @@ 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>.
PODSmallVector<ForwardTemplateReference *, 4 > ForwardTemplateRefs;
bool TryToParseTemplateArgs = true ;
bool PermitForwardTemplateReferences = false ;
bool ParsingLambdaParams = false ;
size_t ParsingLambdaParamsAtLevel = (size_t )-1 ;
unsigned NumSyntheticTemplateParameters[3 ] = {};
Alloc ASTAllocator;
Expand All
@@ -2193,9 +2432,10 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
Names.clear ();
Subs.clear ();
TemplateParams.clear ();
ParsingLambdaParams = false ;
ParsingLambdaParamsAtLevel = ( size_t )- 1 ;
TryToParseTemplateArgs = true ;
PermitForwardTemplateReferences = false ;
NumSyntheticTemplateParameters = {};
ASTAllocator.reset ();
}
Expand Down
Expand Up
@@ -2253,6 +2493,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 ();
Expand Down
Expand Up
@@ -2301,9 +2542,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 ;
Expand Down
Expand Up
@@ -2470,30 +2712,73 @@ 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 (' _' ))
return nullptr ;
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 ();
Expand Down
Expand Up
@@ -3949,6 +4234,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>
Expand Down
Expand Up
@@ -4020,6 +4306,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
Expand All
@@ -4036,7 +4335,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
return make<IntegerCastExpr>(T, N);
}
if (consumeIf (' E' ))
return T ;
return make<LambdaExpr>(T) ;
return nullptr ;
}
}
Expand Down
Expand Up
@@ -5062,11 +5361,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))
Expand All
@@ -5076,15 +5386,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 ;
Expand All
@@ -5094,9 +5400,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
Expand Down
Expand Up
@@ -5153,8 +5528,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' )) {
Expand All
@@ -5172,7 +5550,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 )
Expand Down