When pretty-printing a declaration of a pack, put the ellipsis before the name
being declared, not at the end. When pretty-printing a non-type template parameter, put the name of the parameter in the middle of the type, not at the end. llvm-svn: 213718
This commit is contained in:
parent
f98b00c33e
commit
a4bb292095
|
@ -87,6 +87,7 @@ namespace {
|
|||
void PrintTemplateParameters(const TemplateParameterList *Params,
|
||||
const TemplateArgumentList *Args = nullptr);
|
||||
void prettyPrintAttributes(Decl *D);
|
||||
void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -197,6 +198,17 @@ void DeclPrinter::prettyPrintAttributes(Decl *D) {
|
|||
}
|
||||
}
|
||||
|
||||
void DeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) {
|
||||
// Normally, a PackExpansionType is written as T[3]... (for instance, as a
|
||||
// template argument), but if it is the type of a declaration, the ellipsis
|
||||
// is placed before the name being declared.
|
||||
if (auto *PET = T->getAs<PackExpansionType>()) {
|
||||
Pack = true;
|
||||
T = PET->getPattern();
|
||||
}
|
||||
T.print(Out, Policy, (Pack ? "..." : "") + DeclName);
|
||||
}
|
||||
|
||||
void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
|
||||
this->Indent();
|
||||
Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
|
||||
|
@ -647,7 +659,6 @@ void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
|
|||
Out << *D << ":";
|
||||
}
|
||||
|
||||
|
||||
void DeclPrinter::VisitVarDecl(VarDecl *D) {
|
||||
if (!Policy.SuppressSpecifiers) {
|
||||
StorageClass SC = D->getStorageClass();
|
||||
|
@ -675,7 +686,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
|
|||
QualType T = D->getTypeSourceInfo()
|
||||
? D->getTypeSourceInfo()->getType()
|
||||
: D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
|
||||
T.print(Out, Policy, D->getName());
|
||||
printDeclType(T, D->getName());
|
||||
Expr *Init = D->getInit();
|
||||
if (!Policy.SuppressInitializers && Init) {
|
||||
bool ImplicitInit = false;
|
||||
|
@ -830,7 +841,7 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
|
|||
Out << "class ";
|
||||
|
||||
if (TTP->isParameterPack())
|
||||
Out << "... ";
|
||||
Out << "...";
|
||||
|
||||
Out << *TTP;
|
||||
|
||||
|
@ -843,15 +854,10 @@ void DeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
|
|||
};
|
||||
} else if (const NonTypeTemplateParmDecl *NTTP =
|
||||
dyn_cast<NonTypeTemplateParmDecl>(Param)) {
|
||||
Out << NTTP->getType().getAsString(Policy);
|
||||
|
||||
if (NTTP->isParameterPack() && !isa<PackExpansionType>(NTTP->getType()))
|
||||
Out << "...";
|
||||
|
||||
if (IdentifierInfo *Name = NTTP->getIdentifier()) {
|
||||
Out << ' ';
|
||||
Out << Name->getName();
|
||||
}
|
||||
StringRef Name;
|
||||
if (IdentifierInfo *II = NTTP->getIdentifier())
|
||||
Name = II->getName();
|
||||
printDeclType(NTTP->getType(), Name, NTTP->isParameterPack());
|
||||
|
||||
if (Args) {
|
||||
Out << " = ";
|
||||
|
|
|
@ -39,6 +39,18 @@ void baz() {
|
|||
// CHECK1: template <int A, typename B> B bar()
|
||||
// CHECK2: template <int A, typename B> B bar()
|
||||
|
||||
// CHECK1-LABEL: template <typename ...T> struct A {
|
||||
// CHECK1-NEXT: template <T ...x[3]> struct B {
|
||||
template <typename ...T> struct A {
|
||||
template <T ...x[3]> struct B {};
|
||||
};
|
||||
|
||||
// CHECK1-LABEL: template <typename ...T> void f(T ...[3]) {
|
||||
// CHECK1-NEXT: A<T [3]...> a;
|
||||
template <typename ...T> void f(T ...[3]) {
|
||||
A<T [3]...> a;
|
||||
}
|
||||
|
||||
namespace test2 {
|
||||
void func(int);
|
||||
void func(float);
|
||||
|
|
|
@ -15,7 +15,7 @@ decltype(4.5_baz) operator"" _baz(char);
|
|||
// CHECK: const char *operator "" _quux(const char *);
|
||||
const char *operator"" _quux(const char *);
|
||||
|
||||
// CHECK: template <char...> const char *operator "" _fritz();
|
||||
// CHECK: template <char ...> const char *operator "" _fritz();
|
||||
template<char...> const char *operator"" _fritz();
|
||||
|
||||
// CHECK: const char *p1 = "bar1"_foo;
|
||||
|
|
|
@ -544,6 +544,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl10) {
|
|||
"};",
|
||||
constructorDecl(ofClass(hasName("A"))).bind("id"),
|
||||
"A<T...>(const A<T...> &a)"));
|
||||
// WRONG; Should be: "A(const A<T...> &a);"
|
||||
}
|
||||
|
||||
TEST(DeclPrinter, TestCXXConstructorDecl11) {
|
||||
|
@ -553,8 +554,8 @@ TEST(DeclPrinter, TestCXXConstructorDecl11) {
|
|||
" A(T&&... ts) : T(ts)... {}"
|
||||
"};",
|
||||
constructorDecl(ofClass(hasName("A"))).bind("id"),
|
||||
"A<T...>(T &&ts...) : T(ts)..."));
|
||||
// WRONG; Should be: "A(T&&... ts) : T(ts)..."
|
||||
"A<T...>(T &&...ts) : T(ts)..."));
|
||||
// WRONG; Should be: "A(T &&...ts) : T(ts)... {}"
|
||||
}
|
||||
|
||||
TEST(DeclPrinter, TestCXXDestructorDecl1) {
|
||||
|
@ -1011,8 +1012,8 @@ TEST(DeclPrinter, TestClassTemplateDecl10) {
|
|||
"template<typename... T>"
|
||||
"struct A { int a; };",
|
||||
classTemplateDecl(hasName("A")).bind("id"),
|
||||
"template <typename ... T> struct A {\n}"));
|
||||
// Should be: with semicolon, with { ... }, without spaces before '...'
|
||||
"template <typename ...T> struct A {\n}"));
|
||||
// Should be: with semicolon, with { ... }
|
||||
}
|
||||
|
||||
TEST(DeclPrinter, TestClassTemplateDecl11) {
|
||||
|
@ -1020,8 +1021,8 @@ TEST(DeclPrinter, TestClassTemplateDecl11) {
|
|||
"template<typename... T>"
|
||||
"struct A : public T... { int a; };",
|
||||
classTemplateDecl(hasName("A")).bind("id"),
|
||||
"template <typename ... T> struct A : public T... {\n}"));
|
||||
// Should be: with semicolon, with { ... }, without spaces before '...'
|
||||
"template <typename ...T> struct A : public T... {\n}"));
|
||||
// Should be: with semicolon, with { ... }
|
||||
}
|
||||
|
||||
TEST(DeclPrinter, TestClassTemplatePartialSpecializationDecl1) {
|
||||
|
@ -1080,9 +1081,7 @@ TEST(DeclPrinter, TestFunctionTemplateDecl3) {
|
|||
"template<typename... T>"
|
||||
"void A(T... a);",
|
||||
functionTemplateDecl(hasName("A")).bind("id"),
|
||||
"template <typename ... T> void A(T a...)"));
|
||||
// WRONG; Should be: "template <typename ... T> void A(T... a)"
|
||||
// (not "T a...")
|
||||
"template <typename ...T> void A(T ...a)"));
|
||||
// Should be: with semicolon.
|
||||
}
|
||||
|
||||
|
@ -1239,7 +1238,7 @@ TEST(DeclPrinter, TestTemplateArgumentList13) {
|
|||
"};",
|
||||
"A",
|
||||
"Z<T...> A"));
|
||||
// Should be: with semicolon, without extra space in "> >"
|
||||
// Should be: with semicolon
|
||||
}
|
||||
|
||||
TEST(DeclPrinter, TestTemplateArgumentList14) {
|
||||
|
@ -1251,7 +1250,7 @@ TEST(DeclPrinter, TestTemplateArgumentList14) {
|
|||
"};",
|
||||
"A",
|
||||
"Z<Y<T>...> A"));
|
||||
// Should be: with semicolon, without extra space in "> >"
|
||||
// Should be: with semicolon
|
||||
}
|
||||
|
||||
TEST(DeclPrinter, TestTemplateArgumentList15) {
|
||||
|
@ -1262,7 +1261,7 @@ TEST(DeclPrinter, TestTemplateArgumentList15) {
|
|||
"};",
|
||||
"A",
|
||||
"Z<sizeof...(T)> A"));
|
||||
// Should be: with semicolon, without extra space in "> >"
|
||||
// Should be: with semicolon
|
||||
}
|
||||
|
||||
TEST(DeclPrinter, TestObjCMethod1) {
|
||||
|
|
Loading…
Reference in New Issue