diff options
author | Hamza Sood <hamza_sood@me.com> | 2019-05-04 10:49:46 +0000 |
---|---|---|
committer | Hamza Sood <hamza_sood@me.com> | 2019-05-04 10:49:46 +0000 |
commit | 8205a814a691bfa62fed911b58b0a306ab5efe31 (patch) | |
tree | cbd4d43e2edb58be4b532986547b842cf2be207c /clang/lib/AST | |
parent | 9c32fa1b1f60ea95e627a485b7a8e766ba3e622c (diff) | |
download | bcm5719-llvm-8205a814a691bfa62fed911b58b0a306ab5efe31.tar.gz bcm5719-llvm-8205a814a691bfa62fed911b58b0a306ab5efe31.zip |
[c++20] Implement P0428R2 - Familiar template syntax for generic lambdas
Differential Revision: https://reviews.llvm.org/D36527
llvm-svn: 359967
Diffstat (limited to 'clang/lib/AST')
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 19 | ||||
-rw-r--r-- | clang/lib/AST/DeclPrinter.cpp | 46 | ||||
-rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 4 | ||||
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 24 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 11 | ||||
-rw-r--r-- | clang/lib/AST/TypePrinter.cpp | 14 |
6 files changed, 101 insertions, 17 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 9946d16a858..b9ecdc65720 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1421,13 +1421,30 @@ void CXXRecordDecl::getCaptureFields( TemplateParameterList * CXXRecordDecl::getGenericLambdaTemplateParameterList() const { - if (!isLambda()) return nullptr; + if (!isGenericLambda()) return nullptr; CXXMethodDecl *CallOp = getLambdaCallOperator(); if (FunctionTemplateDecl *Tmpl = CallOp->getDescribedFunctionTemplate()) return Tmpl->getTemplateParameters(); return nullptr; } +ArrayRef<NamedDecl *> +CXXRecordDecl::getLambdaExplicitTemplateParameters() const { + TemplateParameterList *List = getGenericLambdaTemplateParameterList(); + if (!List) + return {}; + + assert(std::is_partitioned(List->begin(), List->end(), + [](const NamedDecl *D) { return !D->isImplicit(); }) + && "Explicit template params should be ordered before implicit ones"); + + const auto ExplicitEnd = std::lower_bound(List->begin(), List->end(), false, + [](const NamedDecl *D, bool) { + return !D->isImplicit(); + }); + return llvm::makeArrayRef(List->begin(), ExplicitEnd); +} + Decl *CXXRecordDecl::getLambdaContextDecl() const { assert(isLambda() && "Not a lambda closure type!"); ExternalASTSource *Source = getParentASTContext().getExternalSource(); diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 36c5d10f718..78a7afdbf09 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -15,6 +15,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -105,7 +106,8 @@ namespace { void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D); void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D); - void printTemplateParameters(const TemplateParameterList *Params); + void printTemplateParameters(const TemplateParameterList *Params, + bool OmitTemplateKW = false); void printTemplateArguments(const TemplateArgumentList &Args, const TemplateParameterList *Params = nullptr); void prettyPrintAttributes(Decl *D); @@ -126,6 +128,18 @@ void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy, Printer.Visit(const_cast<Decl*>(this)); } +void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context, + bool OmitTemplateKW) const { + print(Out, Context, Context.getPrintingPolicy(), OmitTemplateKW); +} + +void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context, + const PrintingPolicy &Policy, + bool OmitTemplateKW) const { + DeclPrinter Printer(Out, Policy, Context); + Printer.printTemplateParameters(this, OmitTemplateKW); +} + static QualType GetBaseType(QualType T) { // FIXME: This should be on the Type class! QualType BaseType = T; @@ -1002,25 +1016,35 @@ void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { Visit(*D->decls_begin()); } -void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params) { +void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params, + bool OmitTemplateKW) { assert(Params); - Out << "template <"; + if (!OmitTemplateKW) + Out << "template "; + Out << '<'; - for (unsigned i = 0, e = Params->size(); i != e; ++i) { - if (i != 0) + bool NeedComma = false; + for (const Decl *Param : *Params) { + if (Param->isImplicit()) + continue; + + if (NeedComma) Out << ", "; + else + NeedComma = true; - const Decl *Param = Params->getParam(i); if (auto TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { if (TTP->wasDeclaredWithTypename()) - Out << "typename "; + Out << "typename"; else - Out << "class "; + Out << "class"; if (TTP->isParameterPack()) - Out << "..."; + Out << " ..."; + else if (!TTP->getName().empty()) + Out << ' '; Out << *TTP; @@ -1045,7 +1069,9 @@ void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params) { } } - Out << "> "; + Out << '>'; + if (!OmitTemplateKW) + Out << ' '; } void DeclPrinter::printTemplateArguments(const TemplateArgumentList &Args, diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 5f9d0e7623d..b1ce1674014 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -1204,7 +1204,11 @@ CXXMethodDecl *LambdaExpr::getCallOperator() const { TemplateParameterList *LambdaExpr::getTemplateParameterList() const { CXXRecordDecl *Record = getLambdaClass(); return Record->getGenericLambdaTemplateParameterList(); +} +ArrayRef<NamedDecl *> LambdaExpr::getExplicitTemplateParameters() const { + const CXXRecordDecl *Record = getLambdaClass(); + return Record->getLambdaExplicitTemplateParameters(); } CompoundStmt *LambdaExpr::getBody() const { diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 3357756466f..1eb5460dd61 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -486,6 +486,7 @@ private: const AbiTagList *AdditionalAbiTags); void mangleBlockForPrefix(const BlockDecl *Block); void mangleUnqualifiedBlock(const BlockDecl *Block); + void mangleTemplateParamDecl(const NamedDecl *Decl); void mangleLambda(const CXXRecordDecl *Lambda); void mangleNestedName(const NamedDecl *ND, const DeclContext *DC, const AbiTagList *AdditionalAbiTags, @@ -1372,7 +1373,8 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // <unnamed-type-name> ::= <closure-type-name> // // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ - // <lambda-sig> ::= <parameter-type>+ # Parameter types or 'v' for 'void'. + // <lambda-sig> ::= <template-param-decl>* <parameter-type>+ + // # Parameter types or 'v' for 'void'. if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) { if (Record->isLambda() && Record->getLambdaManglingNumber()) { assert(!AdditionalAbiTags && @@ -1678,6 +1680,24 @@ void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) { Out << '_'; } +// <template-param-decl> +// ::= Ty # template type parameter +// ::= Tn <type> # template non-type parameter +// ::= Tt <template-param-decl>* E # template template parameter +void CXXNameMangler::mangleTemplateParamDecl(const NamedDecl *Decl) { + if (isa<TemplateTypeParmDecl>(Decl)) { + Out << "Ty"; + } else if (auto *Tn = dyn_cast<NonTypeTemplateParmDecl>(Decl)) { + Out << "Tn"; + mangleType(Tn->getType()); + } else if (auto *Tt = dyn_cast<TemplateTemplateParmDecl>(Decl)) { + Out << "Tt"; + for (auto *Param : *Tt->getTemplateParameters()) + mangleTemplateParamDecl(Param); + Out << "E"; + } +} + void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { // If the context of a closure type is an initializer for a class member // (static or nonstatic), it is encoded in a qualified name with a final @@ -1705,6 +1725,8 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { } Out << "Ul"; + for (auto *D : Lambda->getLambdaExplicitTemplateParameters()) + mangleTemplateParamDecl(D); const FunctionProtoType *Proto = Lambda->getLambdaTypeInfo()->getType()-> getAs<FunctionProtoType>(); mangleBareFunctionType(Proto, /*MangleReturnType=*/false, diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index acf19aaaf41..71270220382 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -1900,8 +1900,14 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { } OS << ']'; + if (!Node->getExplicitTemplateParameters().empty()) { + Node->getTemplateParameterList()->print( + OS, Node->getLambdaClass()->getASTContext(), + /*OmitTemplateKW*/true); + } + if (Node->hasExplicitParameters()) { - OS << " ("; + OS << '('; CXXMethodDecl *Method = Node->getCallOperator(); NeedComma = false; for (const auto *P : Method->parameters()) { @@ -1936,9 +1942,8 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) { } // Print the body. - CompoundStmt *Body = Node->getBody(); OS << ' '; - PrintStmt(Body); + PrintRawCompoundStmt(Node->getBody()); } void StmtPrinter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *Node) { diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 82a2fa09c76..85045324974 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1217,8 +1217,18 @@ void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T, raw_ostream &OS) { if (IdentifierInfo *Id = T->getIdentifier()) OS << Id->getName(); - else - OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex(); + else { + bool IsLambdaAutoParam = false; + if (auto D = T->getDecl()) { + if (auto M = dyn_cast_or_null<CXXMethodDecl>(D->getDeclContext())) + IsLambdaAutoParam = D->isImplicit() && M->getParent()->isLambda(); + } + + if (IsLambdaAutoParam) + OS << "auto"; + else + OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex(); + } spaceBeforePlaceHolder(OS); } |