Skip to content

Commit

Permalink
[DeclPrinter] Honor TerseOutput for constructors
Browse files Browse the repository at this point in the history
Patch by Nikolai Kosjar!

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

llvm-svn: 318365
  • Loading branch information
hyp committed Nov 16, 2017
1 parent fe059c7 commit 35019db
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 73 deletions.
115 changes: 59 additions & 56 deletions clang/lib/AST/DeclPrinter.cpp
Expand Up @@ -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 (!HasInitializerList) {
Proto += " : ";
Out << Proto;
Proto.clear();
HasInitializerList = true;
} else
Out << ", ";
if (!Policy.TerseOutput) {
bool HasInitializerList = false;
for (const auto *BMInitializer : CDecl->inits()) {
if (BMInitializer->isInClassMemberInitializer())
continue;

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()) {
Expand Down Expand Up @@ -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 << " {}";
}
}
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Index/comment-cplus-decls.cpp
Expand Up @@ -46,7 +46,7 @@ class Test
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>
Expand Down
60 changes: 44 additions & 16 deletions clang/unittests/AST/DeclPrinterTest.cpp
Expand Up @@ -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");
Expand All @@ -53,7 +60,7 @@ class PrintMatch : public MatchFinder::MatchCallback {
return;

llvm::raw_svector_ostream Out(Printed);
PrintDecl(Out, Result.Context, D);
PrintDecl(Out, Result.Context, D, PolicyModifier);
}

StringRef getPrinted() const {
Expand All @@ -65,13 +72,12 @@ class PrintMatch : public MatchFinder::MatchCallback {
}
};

::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(
Expand Down Expand Up @@ -109,16 +115,17 @@ ::testing::AssertionResult PrintedDeclCXX98Matches(StringRef Code,
"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,
Expand Down Expand Up @@ -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 {"
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 35019db

Please sign in to comment.