summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManuel Klimek <klimek@google.com>2012-11-07 00:33:12 +0000
committerManuel Klimek <klimek@google.com>2012-11-07 00:33:12 +0000
commitcb7b45e6d80c14d7d12db1eff17dc14b4ae8a35e (patch)
tree6b539f5a022f802e0abd47560f914400a156d0ce
parent530564196fe7e2e30fbc2b0edae45975447583e0 (diff)
downloadclang-cb7b45e6d80c14d7d12db1eff17dc14b4ae8a35e.tar.gz
clang-cb7b45e6d80c14d7d12db1eff17dc14b4ae8a35e.tar.bz2
clang-cb7b45e6d80c14d7d12db1eff17dc14b4ae8a35e.tar.xz
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
-rw-r--r--lib/AST/StmtDumper.cpp113
-rw-r--r--test/Misc/ast-dump-stmt.c35
-rw-r--r--test/Misc/ast-dump-stmt.m36
3 files changed, 127 insertions, 57 deletions
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp
index 3695bf3430..fbc990f6b3 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -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);
-
- // Print out children.
- Stmt::child_range CI = S->children();
- if (CI) {
- while (CI) {
- OS << '\n';
- DumpSubTree(*CI++);
- }
- }
- }
- OS << ')';
- } else {
- Indent();
+ IndentScope Indent(*this);
+
+ if (!S) {
OS << "<<<NULL>>>";
+ return;
+ }
+
+ if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
+ VisitDeclStmt(DS);
+ return;
}
- --IndentLevel;
+
+ 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";
}
diff --git a/test/Misc/ast-dump-stmt.c b/test/Misc/ast-dump-stmt.c
new file mode 100644
index 0000000000..d7fdce8d59
--- /dev/null
+++ b/test/Misc/ast-dump-stmt.c
@@ -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
diff --git a/test/Misc/ast-dump-stmt.m b/test/Misc/ast-dump-stmt.m
new file mode 100644
index 0000000000..8dfee74ab5
--- /dev/null
+++ b/test/Misc/ast-dump-stmt.m
@@ -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