Create helper functions in StmtDumper for outputting the indentation, newlines, and brackets.

This is preparation for adding Decl dumping.

Patch by Philip Craig.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167509 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Manuel Klimek 2012-11-07 00:33:12 +00:00
Родитель 530564196f
Коммит cb7b45e6d8
3 изменённых файлов: 126 добавлений и 56 удалений

Просмотреть файл

@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
// This file implements the Stmt::dump/Stmt::print methods, which dump out the
// This file implements the Stmt::dump method, which dumps out the
// AST in a form that exposes type details and other fields.
//
//===----------------------------------------------------------------------===//
@ -30,6 +30,7 @@ namespace {
SourceManager *SM;
raw_ostream &OS;
unsigned IndentLevel;
bool IsFirstLine;
/// MaxDepth - When doing a normal dump (not dumpAll) we only want to dump
/// the first few levels of an AST. This keeps track of how many ast levels
@ -41,46 +42,64 @@ namespace {
const char *LastLocFilename;
unsigned LastLocLine;
class IndentScope {
StmtDumper &Dumper;
public:
IndentScope(StmtDumper &Dumper) : Dumper(Dumper) {
Dumper.indent();
}
~IndentScope() {
Dumper.unindent();
}
};
public:
StmtDumper(SourceManager *sm, raw_ostream &os, unsigned maxDepth)
: SM(sm), OS(os), IndentLevel(0-1), MaxDepth(maxDepth) {
: SM(sm), OS(os), IndentLevel(0), IsFirstLine(true), MaxDepth(maxDepth) {
LastLocFilename = "";
LastLocLine = ~0U;
}
~StmtDumper() {
OS << "\n";
}
void DumpSubTree(Stmt *S) {
// Prune the recursion if not using dump all.
if (MaxDepth == 0) return;
++IndentLevel;
if (S) {
if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
VisitDeclStmt(DS);
else {
Visit(S);
IndentScope Indent(*this);
// Print out children.
Stmt::child_range CI = S->children();
if (CI) {
while (CI) {
OS << '\n';
DumpSubTree(*CI++);
}
}
}
OS << ')';
} else {
Indent();
if (!S) {
OS << "<<<NULL>>>";
return;
}
--IndentLevel;
if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
VisitDeclStmt(DS);
return;
}
Visit(S);
for (Stmt::child_range CI = S->children(); CI; CI++)
DumpSubTree(*CI);
}
void DumpDeclarator(Decl *D);
void Indent() const {
for (int i = 0, e = IndentLevel; i < e; ++i)
OS << " ";
void indent() {
if (IsFirstLine)
IsFirstLine = false;
else
OS << "\n";
OS.indent(IndentLevel * 2);
OS << "(";
IndentLevel++;
}
void unindent() {
OS << ")";
IndentLevel--;
}
void DumpType(QualType T) {
@ -96,8 +115,7 @@ namespace {
}
void DumpDeclRef(Decl *node);
void DumpStmt(const Stmt *Node) {
Indent();
OS << "(" << Node->getStmtClassName()
OS << Node->getStmtClassName()
<< " " << (const void*)Node;
DumpSourceRange(Node);
}
@ -262,7 +280,7 @@ void StmtDumper::DumpDeclarator(Decl *D) {
// If this is a vardecl with an initializer, emit it.
if (VarDecl *V = dyn_cast<VarDecl>(VD)) {
if (V->getInit()) {
OS << " =\n";
OS << " =";
DumpSubTree(V->getInit());
}
}
@ -294,9 +312,9 @@ void StmtDumper::DumpDeclarator(Decl *D) {
} else if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) {
OS << "label " << *LD;
} else if (StaticAssertDecl *SAD = dyn_cast<StaticAssertDecl>(D)) {
OS << "\"static_assert(\n";
OS << "\"static_assert(";
DumpSubTree(SAD->getAssertExpr());
OS << ",\n";
OS << ",";
DumpSubTree(SAD->getMessage());
OS << ");\"";
} else {
@ -306,17 +324,12 @@ void StmtDumper::DumpDeclarator(Decl *D) {
void StmtDumper::VisitDeclStmt(DeclStmt *Node) {
DumpStmt(Node);
OS << "\n";
for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end();
DI != DE; ++DI) {
IndentScope Indent(*this);
Decl* D = *DI;
++IndentLevel;
Indent();
OS << (void*) D << " ";
DumpDeclarator(D);
if (DI+1 != DE)
OS << "\n";
--IndentLevel;
}
}
@ -503,35 +516,29 @@ void StmtDumper::VisitBlockExpr(BlockExpr *Node) {
BlockDecl *block = Node->getBlockDecl();
OS << " decl=" << block;
IndentLevel++;
if (block->capturesCXXThis()) {
OS << '\n'; Indent(); OS << "(capture this)";
IndentScope Indent(*this);
OS << "capture this";
}
for (BlockDecl::capture_iterator
i = block->capture_begin(), e = block->capture_end(); i != e; ++i) {
OS << '\n';
Indent();
OS << "(capture ";
IndentScope Indent(*this);
OS << "capture ";
if (i->isByRef()) OS << "byref ";
if (i->isNested()) OS << "nested ";
if (i->getVariable())
DumpDeclRef(i->getVariable());
if (i->hasCopyExpr()) DumpSubTree(i->getCopyExpr());
OS << ")";
}
IndentLevel--;
OS << '\n';
DumpSubTree(block->getBody());
}
void StmtDumper::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {
DumpExpr(Node);
if (Expr *Source = Node->getSourceExpr()) {
OS << '\n';
if (Expr *Source = Node->getSourceExpr())
DumpSubTree(Source);
}
}
// GNU extensions.
@ -589,15 +596,11 @@ void StmtDumper::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
void StmtDumper::VisitExprWithCleanups(ExprWithCleanups *Node) {
DumpExpr(Node);
++IndentLevel;
for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) {
OS << "\n";
Indent();
OS << "(cleanup ";
IndentScope Indent(*this);
OS << "cleanup ";
DumpDeclRef(Node->getObject(i));
OS << ")";
}
--IndentLevel;
}
void StmtDumper::DumpCXXTemporary(CXXTemporary *Temporary) {
@ -734,7 +737,6 @@ void Stmt::dump(SourceManager &SM) const {
void Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
StmtDumper P(&SM, OS, 4);
P.DumpSubTree(const_cast<Stmt*>(this));
OS << "\n";
}
/// dump - This does a local dump of the specified AST fragment. It dumps the
@ -743,19 +745,16 @@ void Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
void Stmt::dump() const {
StmtDumper P(0, llvm::errs(), 4);
P.DumpSubTree(const_cast<Stmt*>(this));
llvm::errs() << "\n";
}
/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
void Stmt::dumpAll(SourceManager &SM) const {
StmtDumper P(&SM, llvm::errs(), ~0U);
P.DumpSubTree(const_cast<Stmt*>(this));
llvm::errs() << "\n";
}
/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
void Stmt::dumpAll() const {
StmtDumper P(0, llvm::errs(), ~0U);
P.DumpSubTree(const_cast<Stmt*>(this));
llvm::errs() << "\n";
}

35
test/Misc/ast-dump-stmt.c Normal file
Просмотреть файл

@ -0,0 +1,35 @@
// RUN: %clang_cc1 -ast-dump -ast-dump-filter Test %s | FileCheck -strict-whitespace %s
int TestLocation = 0;
// CHECK: Dumping TestLocation
// CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <{{.*}}:3:20> 'int' 0
int TestIndent = 1 + (1);
// CHECK: Dumping TestIndent
// CHECK-NEXT: {{\(BinaryOperator[^()]*$}}
// CHECK-NEXT: {{^ \(IntegerLiteral.*0[^()]*\)$}}
// CHECK-NEXT: {{^ \(ParenExpr.*0[^()]*$}}
// CHECK-NEXT: {{^ \(IntegerLiteral.*0[^()]*\)\)\)$}}
void TestDeclStmt() {
int x = 0;
int y, z;
}
// CHECK: Dumping TestDeclStmt
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: DeclStmt
// CHECK-NEXT: int x =
// CHECK-NEXT: IntegerLiteral
// CHECK-NEXT: DeclStmt
// CHECK-NEXT: int y
// CHECK-NEXT: int z
int TestOpaqueValueExpr = 0 ?: 1;
// CHECK: Dumping TestOpaqueValueExpr
// CHECK-NEXT: BinaryConditionalOperator
// CHECK-NEXT: IntegerLiteral
// CHECK-NEXT: OpaqueValueExpr
// CHECK-NEXT: IntegerLiteral
// CHECK-NEXT: OpaqueValueExpr
// CHECK-NEXT: IntegerLiteral
// CHECK-NEXT: IntegerLiteral

36
test/Misc/ast-dump-stmt.m Normal file
Просмотреть файл

@ -0,0 +1,36 @@
// RUN: %clang_cc1 -Wno-unused -fblocks -fobjc-exceptions -ast-dump -ast-dump-filter Test %s | FileCheck -strict-whitespace %s
void TestBlockExpr(int x) {
^{ x; };
}
// CHECK: Dumping TestBlockExpr
// CHECK: BlockExpr{{.*}} decl=
// CHECK-NEXT: capture ParmVar
// CHECK-NEXT: CompoundStmt
void TestExprWithCleanup(int x) {
^{ x; };
}
// CHECK: Dumping TestExprWithCleanup
// CHECK: ExprWithCleanups
// CHECK-NEXT: cleanup Block
// CHECK-NEXT: BlockExpr
@interface A
@end
void TestObjCAtCatchStmt() {
@try {
} @catch(A *a) {
} @catch(...) {
} @finally {
}
}
// CHECK: Dumping TestObjCAtCatchStmt
// CHECK: ObjCAtTryStmt
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: ObjCAtCatchStmt{{.*}} catch parm = "A *a"
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: ObjCAtCatchStmt{{.*}} catch all
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: ObjCAtFinallyStmt