[DeclPrinter] Honor TerseOutput for constructors

Patch by Nikolai Kosjar!

Differential Revision: https://reviews.llvm.org/D39957

llvm-svn: 318365
This commit is contained in:
Alex Lorenz 2017-11-16 01:28:25 +00:00
parent fe059c782f
commit 35019dbe6b
3 changed files with 104 additions and 73 deletions

View File

@ -608,66 +608,69 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
}
if (CDecl) {
bool HasInitializerList = false;
for (const auto *BMInitializer : CDecl->inits()) {
if (BMInitializer->isInClassMemberInitializer())
continue;
if (!Policy.TerseOutput) {
bool HasInitializerList = false;
for (const auto *BMInitializer : CDecl->inits()) {
if (BMInitializer->isInClassMemberInitializer())
continue;
if (!HasInitializerList) {
Proto += " : ";
Out << Proto;
Proto.clear();
HasInitializerList = true;
} else
Out << ", ";
if (BMInitializer->isAnyMemberInitializer()) {
FieldDecl *FD = BMInitializer->getAnyMember();
Out << *FD;
} else {
Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy);
}
Out << "(";
if (!BMInitializer->getInit()) {
// Nothing to print
} else {
Expr *Init = BMInitializer->getInit();
if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
Init = Tmp->getSubExpr();
Init = Init->IgnoreParens();
Expr *SimpleInit = nullptr;
Expr **Args = nullptr;
unsigned NumArgs = 0;
if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
Args = ParenList->getExprs();
NumArgs = ParenList->getNumExprs();
} else if (CXXConstructExpr *Construct
= dyn_cast<CXXConstructExpr>(Init)) {
Args = Construct->getArgs();
NumArgs = Construct->getNumArgs();
if (!HasInitializerList) {
Proto += " : ";
Out << Proto;
Proto.clear();
HasInitializerList = true;
} else
SimpleInit = Init;
if (SimpleInit)
SimpleInit->printPretty(Out, nullptr, Policy, Indentation);
else {
for (unsigned I = 0; I != NumArgs; ++I) {
assert(Args[I] != nullptr && "Expected non-null Expr");
if (isa<CXXDefaultArgExpr>(Args[I]))
break;
if (I)
Out << ", ";
Args[I]->printPretty(Out, nullptr, Policy, Indentation);
Out << ", ";
if (BMInitializer->isAnyMemberInitializer()) {
FieldDecl *FD = BMInitializer->getAnyMember();
Out << *FD;
} else {
Out << QualType(BMInitializer->getBaseClass(), 0)
.getAsString(Policy);
}
Out << "(";
if (!BMInitializer->getInit()) {
// Nothing to print
} else {
Expr *Init = BMInitializer->getInit();
if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
Init = Tmp->getSubExpr();
Init = Init->IgnoreParens();
Expr *SimpleInit = nullptr;
Expr **Args = nullptr;
unsigned NumArgs = 0;
if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
Args = ParenList->getExprs();
NumArgs = ParenList->getNumExprs();
} else if (CXXConstructExpr *Construct =
dyn_cast<CXXConstructExpr>(Init)) {
Args = Construct->getArgs();
NumArgs = Construct->getNumArgs();
} else
SimpleInit = Init;
if (SimpleInit)
SimpleInit->printPretty(Out, nullptr, Policy, Indentation);
else {
for (unsigned I = 0; I != NumArgs; ++I) {
assert(Args[I] != nullptr && "Expected non-null Expr");
if (isa<CXXDefaultArgExpr>(Args[I]))
break;
if (I)
Out << ", ";
Args[I]->printPretty(Out, nullptr, Policy, Indentation);
}
}
}
Out << ")";
if (BMInitializer->isPackExpansion())
Out << "...";
}
Out << ")";
if (BMInitializer->isPackExpansion())
Out << "...";
}
} else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) {
if (FT && FT->hasTrailingReturn()) {
@ -712,7 +715,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (D->getBody())
D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation);
} else {
if (isa<CXXConstructorDecl>(*D))
if (!Policy.TerseOutput && isa<CXXConstructorDecl>(*D))
Out << " {}";
}
}

View File

@ -46,7 +46,7 @@ protected:
data* reserved;
};
// CHECK: <Declaration>class Test {}</Declaration>
// CHECK: <Declaration>Test() : reserved(new Test::data()) {}</Declaration>
// CHECK: <Declaration>Test()</Declaration>
// CHECK: <Declaration>unsigned int getID() const</Declaration>
// CHECK: <Declaration>~Test(){{( noexcept)?}}</Declaration>
// CHECK: <Declaration>Test::data *reserved</Declaration>

View File

@ -31,18 +31,25 @@ using namespace tooling;
namespace {
void PrintDecl(raw_ostream &Out, const ASTContext *Context, const Decl *D) {
using PrintingPolicyModifier = void (*)(PrintingPolicy &policy);
void PrintDecl(raw_ostream &Out, const ASTContext *Context, const Decl *D,
PrintingPolicyModifier PolicyModifier) {
PrintingPolicy Policy = Context->getPrintingPolicy();
Policy.TerseOutput = true;
if (PolicyModifier)
PolicyModifier(Policy);
D->print(Out, Policy, /*Indentation*/ 0, /*PrintInstantiation*/ false);
}
class PrintMatch : public MatchFinder::MatchCallback {
SmallString<1024> Printed;
unsigned NumFoundDecls;
PrintingPolicyModifier PolicyModifier;
public:
PrintMatch() : NumFoundDecls(0) {}
PrintMatch(PrintingPolicyModifier PolicyModifier)
: NumFoundDecls(0), PolicyModifier(PolicyModifier) {}
void run(const MatchFinder::MatchResult &Result) override {
const Decl *D = Result.Nodes.getNodeAs<Decl>("id");
@ -53,7 +60,7 @@ public:
return;
llvm::raw_svector_ostream Out(Printed);
PrintDecl(Out, Result.Context, D);
PrintDecl(Out, Result.Context, D, PolicyModifier);
}
StringRef getPrinted() const {
@ -65,13 +72,12 @@ public:
}
};
::testing::AssertionResult PrintedDeclMatches(
StringRef Code,
const std::vector<std::string> &Args,
const DeclarationMatcher &NodeMatch,
StringRef ExpectedPrinted,
StringRef FileName) {
PrintMatch Printer;
::testing::AssertionResult
PrintedDeclMatches(StringRef Code, const std::vector<std::string> &Args,
const DeclarationMatcher &NodeMatch,
StringRef ExpectedPrinted, StringRef FileName,
PrintingPolicyModifier PolicyModifier = nullptr) {
PrintMatch Printer(PolicyModifier);
MatchFinder Finder;
Finder.addMatcher(NodeMatch, &Printer);
std::unique_ptr<FrontendActionFactory> Factory(
@ -109,16 +115,17 @@ public:
"input.cc");
}
::testing::AssertionResult PrintedDeclCXX98Matches(
StringRef Code,
const DeclarationMatcher &NodeMatch,
StringRef ExpectedPrinted) {
::testing::AssertionResult
PrintedDeclCXX98Matches(StringRef Code, const DeclarationMatcher &NodeMatch,
StringRef ExpectedPrinted,
PrintingPolicyModifier PolicyModifier = nullptr) {
std::vector<std::string> Args(1, "-std=c++98");
return PrintedDeclMatches(Code,
Args,
NodeMatch,
ExpectedPrinted,
"input.cc");
"input.cc",
PolicyModifier);
}
::testing::AssertionResult PrintedDeclCXX11Matches(StringRef Code,
@ -478,6 +485,27 @@ TEST(DeclPrinter, TestCXXConstructorDecl4) {
"A(const A &a, int = 0)"));
}
TEST(DeclPrinter, TestCXXConstructorDeclWithMemberInitializer) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
"struct A {"
" int m;"
" A() : m(2) {}"
"};",
cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
"A()"));
}
TEST(DeclPrinter, TestCXXConstructorDeclWithMemberInitializer_NoTerseOutput) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
"struct A {"
" int m;"
" A() : m(2) {}"
"};",
cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
"A() : m(2) {\n}\n",
[](PrintingPolicy &Policy){ Policy.TerseOutput = false; }));
}
TEST(DeclPrinter, TestCXXConstructorDecl5) {
ASSERT_TRUE(PrintedDeclCXX11Matches(
"struct A {"
@ -540,7 +568,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl11) {
" A(T&&... ts) : T(ts)... {}"
"};",
cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
"A<T...>(T &&...ts) : T(ts)... {}"));
"A<T...>(T &&...ts)"));
}
TEST(DeclPrinter, TestCXXDestructorDecl1) {