//===--- DumpXML.cpp - Detailed XML dumping -------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Decl::dumpXML() method, a debugging tool to
// print a detailed graph of an AST in an unspecified XML format.
//
// There is no guarantee of stability for this format.
//
//===----------------------------------------------------------------------===//
// Only pay for this in code size in assertions-enabled builds.
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeLocVisitor.h"
#include "clang/AST/TypeVisitor.h"
#include "llvm/ADT/SmallString.h"
using namespace clang;
#ifndef NDEBUG
namespace {
enum NodeState {
NS_Attrs, NS_LazyChildren, NS_Children
};
struct Node {
StringRef Name;
NodeState State;
Node(StringRef name) : Name(name), State(NS_Attrs) {}
bool isDoneWithAttrs() const { return State != NS_Attrs; }
};
template <class Impl> struct XMLDeclVisitor {
#define DISPATCH(NAME, CLASS) \
static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(D))
void dispatch(Decl *D) {
if (D->isUsed())
static_cast<Impl*>(this)->set("used", "1");
switch (D->getKind()) {
#define DECL(DERIVED, BASE) \
case Decl::DERIVED: \
DISPATCH(dispatch##DERIVED##DeclAttrs, DERIVED##Decl); \
static_cast<Impl*>(this)->completeAttrs(); \
DISPATCH(dispatch##DERIVED##DeclChildren, DERIVED##Decl); \
DISPATCH(dispatch##DERIVED##DeclAsContext, DERIVED##Decl); \
break;
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
}
}
#define DECL(DERIVED, BASE) \
void dispatch##DERIVED##DeclAttrs(DERIVED##Decl *D) { \
DISPATCH(dispatch##BASE##Attrs, BASE); \
DISPATCH(visit##DERIVED##DeclAttrs, DERIVED##Decl); \
} \
void visit##DERIVED##DeclAttrs(DERIVED##Decl *D) {} \
void dispatch##DERIVED##DeclChildren(DERIVED##Decl *D) { \
DISPATCH(dispatch##BASE##Children, BASE); \
DISPATCH(visit##DERIVED##DeclChildren, DERIVED##Decl); \
} \
void visit##DERIVED##DeclChildren(DERIVED##Decl *D) {} \
void dispatch##DERIVED##DeclAsContext(DERIVED##Decl *D) { \
DISPATCH(dispatch##BASE##AsContext, BASE); \
DISPATCH(visit##DERIVED##DeclAsContext, DERIVED##Decl); \
} \
void visit##DERIVED##DeclAsContext(DERIVED##Decl *D) {}
#include "clang/AST/DeclNodes.inc"
void dispatchDeclAttrs(Decl *D) {
DISPATCH(visitDeclAttrs, Decl);
}
void visitDeclAttrs(Decl *D) {}
void dispatchDeclChildren(Decl *D) {
DISPATCH(visitDeclChildren, Decl);
}
void visitDeclChildren(Decl *D) {}
void dispatchDeclAsContext(Decl *D) {
DISPATCH(visitDeclAsContext, Decl);
}
void visitDeclAsContext(Decl *D) {}
#undef DISPATCH
};
template <class Impl> struct XMLTypeVisitor {
#define DISPATCH(NAME, CLASS) \
static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(T))
void dispatch(Type *T) {
switch (T->getTypeClass()) {
#define TYPE(DERIVED, BASE) \
case Type::DERIVED: \
DISPATCH(dispatch##DERIVED##TypeAttrs, DERIVED##Type); \
static_cast<Impl*>(this)->completeAttrs(); \
DISPATCH(dispatch##DERIVED##TypeChildren, DERIVED##Type); \
break;
#define ABSTRACT_TYPE(DERIVED, BASE)
#include "clang/AST/TypeNodes.def"
}
}
#define TYPE(DERIVED, BASE) \
void dispatch##DERIVED##TypeAttrs(DERIVED##Type *T) { \
DISPATCH(dispatch##BASE##Attrs, BASE); \
DISPATCH(visit##DERIVED##TypeAttrs, DERIVED##Type); \
} \
void visit##DERIVED##TypeAttrs(DERIVED##Type *T) {} \
void dispatch##DERIVED##TypeChildren(DERIVED##Type *T) { \
DISPATCH(dispatch##BASE##Children, BASE); \
DISPATCH(visit##DERIVED##TypeChildren, DERIVED##Type); \
} \
void visit##DERIVED##TypeChildren(DERIVED##Type *T) {}
#include "clang/AST/TypeNodes.def"
void dispatchTypeAttrs(Type *T) {
DISPATCH(visitTypeAttrs, Type);
}
void visitTypeAttrs(Type *T) {}
void dispatchTypeChildren(Type *T) {
DISPATCH(visitTypeChildren, Type);
}
void visitTypeChildren(Type *T) {}
#undef DISPATCH
};
static StringRef getTypeKindName(Type *T) {
switch (T->getTypeClass()) {
#define TYPE(DERIVED, BASE) case Type::DERIVED: return #DERIVED "Type";
#define ABSTRACT_TYPE(DERIVED, BASE)
#include "clang/AST/TypeNodes.def"
}
llvm_unreachable("unknown type kind!");
}
struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
public XMLTypeVisitor<XMLDumper> {
raw_ostream &out;
ASTContext &Context;
SmallVector<Node, 16> Stack;
unsigned Indent;
explicit XMLDumper(raw_ostream &OS, ASTContext &context)
: out(OS), Context(context), Indent(0) {}
void indent() {
for (unsigned I = Indent; I; --I)
out << ' ';
}