diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/CMakeLists.txt | 2 | ||||
-rw-r--r-- | lib/Frontend/ASTConsumers.cpp | 36 | ||||
-rw-r--r-- | lib/Frontend/DocumentXML.cpp | 577 | ||||
-rw-r--r-- | lib/Frontend/StmtXML.cpp | 409 |
4 files changed, 1024 insertions, 0 deletions
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index a282f202f2..74d872463a 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -13,6 +13,7 @@ add_clang_library(clangAST DeclGroup.cpp DeclObjC.cpp DeclTemplate.cpp + DocumentXML.cpp ExprConstant.cpp Expr.cpp ExprCXX.cpp @@ -24,6 +25,7 @@ add_clang_library(clangAST StmtIterator.cpp StmtPrinter.cpp StmtViz.cpp + StmtXML.cpp TemplateName.cpp Type.cpp ) diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp index 53034e96d9..ba482b049a 100644 --- a/lib/Frontend/ASTConsumers.cpp +++ b/lib/Frontend/ASTConsumers.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/ASTConsumers.h" +#include "clang/Frontend/DocumentXML.h" #include "clang/Frontend/PathDiagnosticClients.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" @@ -587,6 +588,41 @@ ASTConsumer *clang::CreateASTPrinter(llvm::raw_ostream* out) { } //===----------------------------------------------------------------------===// +/// ASTPrinterXML - XML-printer of ASTs + +namespace { + class ASTPrinterXML : public ASTConsumer { + DocumentXML Doc; + + public: + ASTPrinterXML(llvm::raw_ostream& o) : Doc("CLANG_XML", o) {} + + void Initialize(ASTContext &Context) { + Doc.initialize(Context); + } + + virtual void HandleTranslationUnit(ASTContext &Ctx) { + Doc.addSubNode("TranslationUnit"); + for (DeclContext::decl_iterator + D = Ctx.getTranslationUnitDecl()->decls_begin(Ctx), + DEnd = Ctx.getTranslationUnitDecl()->decls_end(Ctx); + D != DEnd; + ++D) + { + Doc.PrintDecl(*D); + } + Doc.toParent(); + Doc.finalize(); + } + }; +} // end anonymous namespace + + +ASTConsumer *clang::CreateASTPrinterXML(llvm::raw_ostream* out) { + return new ASTPrinterXML(out ? *out : llvm::outs()); +} + +//===----------------------------------------------------------------------===// /// ASTDumper - Low-level dumper of ASTs namespace { diff --git a/lib/Frontend/DocumentXML.cpp b/lib/Frontend/DocumentXML.cpp new file mode 100644 index 0000000000..80060f5b73 --- /dev/null +++ b/lib/Frontend/DocumentXML.cpp @@ -0,0 +1,577 @@ +//===--- DocumentXML.cpp - XML document for ASTs --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the XML document class, which provides the means to +// dump out the AST in a XML form that exposes type details and other fields. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/DocumentXML.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Expr.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/StringExtras.h" + +namespace clang { + +//--------------------------------------------------------- +struct DocumentXML::NodeXML +{ + std::string Name; + NodeXML* Parent; + + NodeXML(const std::string& name, NodeXML* parent) : + Name(name), + Parent(parent) + {} +}; + +//--------------------------------------------------------- +DocumentXML::DocumentXML(const std::string& rootName, llvm::raw_ostream& out) : + Root(new NodeXML(rootName, 0)), + CurrentNode(Root), + Out(out), + Ctx(0), + CurrentIndent(0), + HasCurrentNodeSubNodes(false) +{ + Out << "<?xml version=\"1.0\"?>\n<" << rootName; +} + +//--------------------------------------------------------- +DocumentXML::~DocumentXML() +{ + assert(CurrentNode == Root && "not completely backtracked"); + delete Root; +} + +//--------------------------------------------------------- +DocumentXML& DocumentXML::addSubNode(const std::string& name) +{ + if (!HasCurrentNodeSubNodes) + { + Out << ">\n"; + } + CurrentNode = new NodeXML(name, CurrentNode); + HasCurrentNodeSubNodes = false; + CurrentIndent += 2; + Indent(); + Out << "<" << CurrentNode->Name; + return *this; +} + +//--------------------------------------------------------- +void DocumentXML::Indent() +{ + for (int i = 0; i < CurrentIndent; ++i) + Out << ' '; +} + +//--------------------------------------------------------- +DocumentXML& DocumentXML::toParent() +{ + assert(CurrentNode != Root && "to much backtracking"); + + if (HasCurrentNodeSubNodes) + { + Indent(); + Out << "</" << CurrentNode->Name << ">\n"; + } + else + { + Out << "/>\n"; + } + NodeXML* NodeToDelete = CurrentNode; + CurrentNode = CurrentNode->Parent; + delete NodeToDelete; + HasCurrentNodeSubNodes = true; + CurrentIndent -= 2; + return *this; +} + +//--------------------------------------------------------- +namespace { + +enum tIdType { ID_NORMAL, ID_FILE, ID_LAST }; + +unsigned getNewId(tIdType idType) +{ + static unsigned int idCounts[ID_LAST] = { 0 }; + return ++idCounts[idType]; +} + +//--------------------------------------------------------- +inline std::string getPrefixedId(unsigned uId, tIdType idType) +{ + static const char idPrefix[ID_LAST] = { '_', 'f' }; + char buffer[20]; + char* BufPtr = llvm::utohex_buffer(uId, buffer + 20); + *--BufPtr = idPrefix[idType]; + return BufPtr; +} + +//--------------------------------------------------------- +template<class T, class V> +bool addToMap(T& idMap, const V& value, tIdType idType = ID_NORMAL) +{ + typename T::iterator i = idMap.find(value); + bool toAdd = i == idMap.end(); + if (toAdd) + { + idMap.insert(typename T::value_type(value, getNewId(idType))); + } + return toAdd; +} + +} // anon NS + +//--------------------------------------------------------- +std::string DocumentXML::escapeString(const char* pStr, std::string::size_type len) +{ + std::string value; + value.reserve(len + 1); + char buffer[16]; + for (unsigned i = 0; i < len; ++i) { + switch (char C = pStr[i]) { + default: + if (isprint(C)) + value += C; + else + { + sprintf(buffer, "\\%03o", C); + value += buffer; + } + break; + + case '\n': value += "\\n"; break; + case '\t': value += "\\t"; break; + case '\a': value += "\\a"; break; + case '\b': value += "\\b"; break; + case '\r': value += "\\r"; break; + + case '&': value += "&"; break; + case '<': value += "<"; break; + case '>': value += ">"; break; + case '"': value += """; break; + case '\'': value += "'"; break; + + } + } + return value; +} + +//--------------------------------------------------------- +void DocumentXML::finalize() +{ + assert(CurrentNode == Root && "not completely backtracked"); + + addSubNode("ReferenceSection"); + addSubNode("Types"); + + for (XML::IdMap<QualType>::iterator i = Types.begin(), e = Types.end(); i != e; ++i) + { + if (i->first.getCVRQualifiers() != 0) + { + addSubNode("CvQualifiedType"); + addAttribute("id", getPrefixedId(i->second, ID_NORMAL)); + addAttribute("type", getPrefixedId(BasicTypes[i->first.getTypePtr()], ID_NORMAL)); + if (i->first.isConstQualified()) addAttribute("const", "1"); + if (i->first.isVolatileQualified()) addAttribute("volatile", "1"); + if (i->first.isRestrictQualified()) addAttribute("restrict", "1"); + toParent(); + } + } + + for (XML::IdMap<const Type*>::iterator i = BasicTypes.begin(), e = BasicTypes.end(); i != e; ++i) + { + // don't use the get methods as they strip of typedef infos + if (const BuiltinType *BT = dyn_cast<BuiltinType>(i->first)) { + addSubNode("FundamentalType"); + addAttribute("name", BT->getName()); + } + else if (const PointerType *PT = dyn_cast<PointerType>(i->first)) { + addSubNode("PointerType"); + addTypeAttribute(PT->getPointeeType()); + } + else if (dyn_cast<FunctionType>(i->first) != 0) { + addSubNode("FunctionType"); + } + else if (const ReferenceType *RT = dyn_cast<ReferenceType>(i->first)) { + addSubNode("ReferenceType"); + addTypeAttribute(RT->getPointeeType()); + } + else if (const TypedefType * TT = dyn_cast<TypedefType>(i->first)) { + addSubNode("Typedef"); + addAttribute("name", TT->getDecl()->getNameAsString()); + addTypeAttribute(TT->getDecl()->getUnderlyingType()); + addContextAttribute(TT->getDecl()->getDeclContext()); + } + else if (const QualifiedNameType *QT = dyn_cast<QualifiedNameType>(i->first)) { + addSubNode("QualifiedNameType"); + addTypeAttribute(QT->getNamedType()); + } + else if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(i->first)) { + addSubNode("ArrayType"); + addAttribute("min", 0); + addAttribute("max", (CAT->getSize() - 1).toString(10, false)); + addTypeAttribute(CAT->getElementType()); + } + else if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(i->first)) { + addSubNode("VariableArrayType"); + addTypeAttribute(VAT->getElementType()); + } + else if (const TagType *RET = dyn_cast<TagType>(i->first)) { + const TagDecl *tagDecl = RET->getDecl(); + std::string tagKind = tagDecl->getKindName(); + tagKind[0] = std::toupper(tagKind[0]); + addSubNode(tagKind); + addAttribute("name", tagDecl->getNameAsString()); + addContextAttribute(tagDecl->getDeclContext()); + } + else if (const VectorType* VT = dyn_cast<VectorType>(i->first)) { + addSubNode("VectorType"); + addTypeAttribute(VT->getElementType()); + addAttribute("num_elements", VT->getNumElements()); + } + else + { + addSubNode("FIXMEType"); + } + addAttribute("id", getPrefixedId(i->second, ID_NORMAL)); + toParent(); + } + + + toParent().addSubNode("Contexts"); + + for (XML::IdMap<const DeclContext*>::iterator i = Contexts.begin(), e = Contexts.end(); i != e; ++i) + { + addSubNode(i->first->getDeclKindName()); + addAttribute("id", getPrefixedId(i->second, ID_NORMAL)); + if (const NamedDecl *ND = dyn_cast<NamedDecl>(i->first)) { + addAttribute("name", ND->getNameAsString()); + } + if (const TagDecl *TD = dyn_cast<TagDecl>(i->first)) { + addAttribute("type", getPrefixedId(BasicTypes[TD->getTypeForDecl()], ID_NORMAL)); + } + else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(i->first)) { + addAttribute("type", getPrefixedId(BasicTypes[FD->getType()->getAsFunctionType()], ID_NORMAL)); + } + + if (const DeclContext* parent = i->first->getParent()) + { + addContextAttribute(parent); + } + toParent(); + } + + toParent().addSubNode("Files"); + + for (XML::IdMap<std::string>::iterator i = SourceFiles.begin(), e = SourceFiles.end(); i != e; ++i) + { + addSubNode("File"); + addAttribute("id", getPrefixedId(i->second, ID_FILE)); + addAttribute("name", escapeString(i->first.c_str(), i->first.size())); + toParent(); + } + + toParent().toParent(); + + // write the root closing node (which has always subnodes) + Out << "</" << CurrentNode->Name << ">\n"; +} + +//--------------------------------------------------------- +void DocumentXML::addTypeAttribute(const QualType& pType) +{ + addTypeRecursively(pType); + addAttribute("type", getPrefixedId(Types[pType], ID_NORMAL)); +} + +//--------------------------------------------------------- +void DocumentXML::addTypeIdAttribute(const Type* pType) +{ + addBasicTypeRecursively(pType); + addAttribute("id", getPrefixedId(BasicTypes[pType], ID_NORMAL)); +} + +//--------------------------------------------------------- +void DocumentXML::addTypeRecursively(const QualType& pType) +{ + if (addToMap(Types, pType)) + { + addBasicTypeRecursively(pType.getTypePtr()); + // beautifier: a non-qualified type shall be transparent + if (pType.getCVRQualifiers() == 0) + { + Types[pType] = BasicTypes[pType.getTypePtr()]; + } + } +} + +//--------------------------------------------------------- +void DocumentXML::addBasicTypeRecursively(const Type* pType) +{ + if (addToMap(BasicTypes, pType)) + { + if (const PointerType *PT = dyn_cast<PointerType>(pType)) { + addTypeRecursively(PT->getPointeeType()); + } + else if (const ReferenceType *RT = dyn_cast<ReferenceType>(pType)) { + addTypeRecursively(RT->getPointeeType()); + } + else if (const TypedefType *TT = dyn_cast<TypedefType>(pType)) { + addTypeRecursively(TT->getDecl()->getUnderlyingType()); + addContextsRecursively(TT->getDecl()->getDeclContext()); + } + else if (const QualifiedNameType *QT = dyn_cast<QualifiedNameType>(pType)) { + addTypeRecursively(QT->getNamedType()); + // FIXME: what to do with NestedNameSpecifier or shall this type be transparent? + } + else if (const ArrayType *AT = dyn_cast<ArrayType>(pType)) { + addTypeRecursively(AT->getElementType()); + // FIXME: doesn't work in the immediate streaming approach + /*if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(AT)) + { + addSubNode("VariableArraySizeExpression"); + PrintStmt(VAT->getSizeExpr()); + toParent(); + }*/ + } + } +} + +//--------------------------------------------------------- +void DocumentXML::addContextAttribute(const DeclContext *DC, tContextUsage usage) +{ + addContextsRecursively(DC); + const char* pAttributeTags[2] = { "context", "id" }; + addAttribute(pAttributeTags[usage], getPrefixedId(Contexts[DC], ID_NORMAL)); +} + +//--------------------------------------------------------- +void DocumentXML::addContextsRecursively(const DeclContext *DC) +{ + if (DC != 0 && addToMap(Contexts, DC)) + { + addContextsRecursively(DC->getParent()); + } +} + +//--------------------------------------------------------- +void DocumentXML::addSourceFileAttribute(const std::string& fileName) +{ + addToMap(SourceFiles, fileName, ID_FILE); + addAttribute("file", getPrefixedId(SourceFiles[fileName], ID_FILE)); +} + +//--------------------------------------------------------- +PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc) +{ + SourceManager& SM = Ctx->getSourceManager(); + SourceLocation SpellingLoc = SM.getSpellingLoc(Loc); + PresumedLoc PLoc; + if (!SpellingLoc.isInvalid()) + { + PLoc = SM.getPresumedLoc(SpellingLoc); + addSourceFileAttribute(PLoc.getFilename()); + addAttribute("line", PLoc.getLine()); + addAttribute("col", PLoc.getColumn()); + } + // else there is no error in some cases (eg. CXXThisExpr) + return PLoc; +} + +//--------------------------------------------------------- +void DocumentXML::addLocationRange(const SourceRange& R) +{ + PresumedLoc PStartLoc = addLocation(R.getBegin()); + if (R.getBegin() != R.getEnd()) + { + SourceManager& SM = Ctx->getSourceManager(); + SourceLocation SpellingLoc = SM.getSpellingLoc(R.getEnd()); + if (!SpellingLoc.isInvalid()) + { + PresumedLoc PLoc = SM.getPresumedLoc(SpellingLoc); + if (PStartLoc.isInvalid() || + strcmp(PLoc.getFilename(), PStartLoc.getFilename()) != 0) { + addToMap(SourceFiles, PLoc.getFilename(), ID_FILE); + addAttribute("endfile", PLoc.getFilename()); + addAttribute("endline", PLoc.getLine()); + addAttribute("endcol", PLoc.getColumn()); + } else if (PLoc.getLine() != PStartLoc.getLine()) { + addAttribute("endline", PLoc.getLine()); + addAttribute("endcol", PLoc.getColumn()); + } else { + addAttribute("endcol", PLoc.getColumn()); + } + } + } +} + +//--------------------------------------------------------- +void DocumentXML::PrintFunctionDecl(FunctionDecl *FD) +{ + switch (FD->getStorageClass()) { + default: assert(0 && "Unknown storage class"); + case FunctionDecl::None: break; + case FunctionDecl::Extern: addAttribute("storage_class", "extern"); break; + case FunctionDecl::Static: addAttribute("storage_class", "static"); break; + case FunctionDecl::PrivateExtern: addAttribute("storage_class", "__private_extern__"); break; + } + + if (FD->isInline()) + addAttribute("inline", "1"); + + const FunctionType *AFT = FD->getType()->getAsFunctionType(); + addTypeAttribute(AFT->getResultType()); + addBasicTypeRecursively(AFT); + + if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(AFT)) { + addAttribute("num_args", FD->getNumParams()); + for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) { + addSubNode("Argument"); + ParmVarDecl *argDecl = FD->getParamDecl(i); + addAttribute("name", argDecl->getNameAsString()); + addTypeAttribute(FT->getArgType(i)); + addDeclIdAttribute(argDecl); + if (argDecl->getDefaultArg()) + { + addAttribute("default_arg", "1"); + PrintStmt(argDecl->getDefaultArg()); + } + toParent(); + } + + if (FT->isVariadic()) { + addSubNode("Ellipsis").toParent(); + } + } else { + assert(isa<FunctionNoProtoType>(AFT)); + } +} + +//--------------------------------------------------------- +void DocumentXML::addRefAttribute(const NamedDecl* D) +{ + // FIXME: in case of CXX inline member functions referring to a member defined + // after the function it needs to be tested, if the ids are already there + // (should work, but I couldn't test it) + if (const DeclContext* DC = dyn_cast<DeclContext>(D)) + { + addAttribute("ref", getPrefixedId(Contexts[DC], ID_NORMAL)); + } + else + { + addAttribute("ref", getPrefixedId(Decls[D], ID_NORMAL)); + } +} + +//--------------------------------------------------------- +void DocumentXML::addDeclIdAttribute(const NamedDecl* D) +{ + addToMap(Decls, D); + addAttribute("id", getPrefixedId(Decls[D], ID_NORMAL)); +} + +//--------------------------------------------------------- +void DocumentXML::PrintDecl(Decl *D) +{ + addSubNode(D->getDeclKindName()); + addContextAttribute(D->getDeclContext()); + addLocation(D->getLocation()); + if (DeclContext* DC = dyn_cast<DeclContext>(D)) + { + addContextAttribute(DC, CONTEXT_AS_ID); + } + + if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) { + addAttribute("name", ND->getNameAsString()); + + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + PrintFunctionDecl(FD); + if (Stmt *Body = FD->getBody(*Ctx)) { + addSubNode("Body"); + PrintStmt(Body); + toParent(); + } + } else if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) { + addBasicTypeRecursively(RD->getTypeForDecl()); + addAttribute("type", getPrefixedId(BasicTypes[RD->getTypeForDecl()], ID_NORMAL)); + if (!RD->isDefinition()) + { + addAttribute("forward", "1"); + } + + for (RecordDecl::field_iterator i = RD->field_begin(*Ctx), e = RD->field_end(*Ctx); i != e; ++i) + { + PrintDecl(*i); + } + } else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) { + const QualType& enumType = ED->getIntegerType(); + if (!enumType.isNull()) + { + addTypeAttribute(enumType); + for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Ctx), e = ED->enumerator_end(*Ctx); i != e; ++i) + { + PrintDecl(*i); + } + } + } else if (EnumConstantDecl* ECD = dyn_cast<EnumConstantDecl>(D)) { + addTypeAttribute(ECD->getType()); + addAttribute("value", ECD->getInitVal().toString(10, true)); + if (ECD->getInitExpr()) + { + PrintStmt(ECD->getInitExpr()); + } + } else if (FieldDecl *FdD = dyn_cast<FieldDecl>(D)) { + addTypeAttribute(FdD->getType()); + addDeclIdAttribute(ND); + if (FdD->isMutable()) + addAttribute("mutable", "1"); + if (FdD->isBitField()) + { + addAttribute("bitfield", "1"); + PrintStmt(FdD->getBitWidth()); + } + } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { + addTypeIdAttribute(Ctx->getTypedefType(TD).getTypePtr()); + addTypeAttribute(TD->getUnderlyingType()); + } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) { + addTypeAttribute(VD->getType()); + addDeclIdAttribute(ND); + + VarDecl *V = dyn_cast<VarDecl>(VD); + if (V && V->getStorageClass() != VarDecl::None) + { + addAttribute("storage_class", VarDecl::getStorageClassSpecifierString(V->getStorageClass())); + } + + if (V && V->getInit()) + { + PrintStmt(V->getInit()); + } + } + } else if (LinkageSpecDecl* LSD = dyn_cast<LinkageSpecDecl>(D)) { + switch (LSD->getLanguage()) + { + case LinkageSpecDecl::lang_c: addAttribute("lang", "C"); break; + case LinkageSpecDecl::lang_cxx: addAttribute("lang", "CXX"); break; + default: assert(0 && "Unexpected lang id"); + } + } else { + assert(0 && "Unexpected decl"); + } + toParent(); +} + +//--------------------------------------------------------- +} // NS clang + diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp new file mode 100644 index 0000000000..c861881486 --- /dev/null +++ b/lib/Frontend/StmtXML.cpp @@ -0,0 +1,409 @@ +//===--- StmtXML.cpp - XML implementation for Stmt ASTs ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Stmt::dumpXML methods, which dump out the +// AST to an XML document. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/DocumentXML.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclCXX.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/Support/Compiler.h" +using namespace clang; + +//===----------------------------------------------------------------------===// +// StmtXML Visitor +//===----------------------------------------------------------------------===// + +namespace { + class VISIBILITY_HIDDEN StmtXML : public StmtVisitor<StmtXML> { + DocumentXML& Doc; + + static const char *getOpcodeStr(UnaryOperator::Opcode Op); + static const char *getOpcodeStr(BinaryOperator::Opcode Op); + + public: + StmtXML(DocumentXML& doc) + : Doc(doc) { + } + + void DumpSubTree(Stmt *S) { + if (S) + { + Doc.addSubNode(S->getStmtClassName()); + Doc.addLocationRange(S->getSourceRange()); + if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) { + VisitDeclStmt(DS); + } else { + Visit(S); + for (Stmt::child_iterator i = S->child_begin(), e = S->child_end(); i != e; ++i) + { + DumpSubTree(*i); + } + } + Doc.toParent(); + } else { + Doc.addSubNode("NULL").toParent(); + } + } + + void DumpTypeExpr(const QualType& T) + { + Doc.addSubNode("TypeExpr"); + Doc.addTypeAttribute(T); + Doc.toParent(); + } + + void DumpExpr(const Expr *Node) { + Doc.addTypeAttribute(Node->getType()); + } + + // Stmts. + void VisitStmt(Stmt *Node); + void VisitDeclStmt(DeclStmt *Node); + void VisitLabelStmt(LabelStmt *Node); + void VisitGotoStmt(GotoStmt *Node); + + // Exprs + void VisitExpr(Expr *Node); + void VisitDeclRefExpr(DeclRefExpr *Node); + void VisitPredefinedExpr(PredefinedExpr *Node); + void VisitCharacterLiteral(CharacterLiteral *Node); + void VisitIntegerLiteral(IntegerLiteral *Node); + void VisitFloatingLiteral(FloatingLiteral *Node); + void VisitStringLiteral(StringLiteral *Str); + void VisitUnaryOperator(UnaryOperator *Node); + void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node); + void VisitMemberExpr(MemberExpr *Node); + void VisitExtVectorElementExpr(ExtVectorElementExpr *Node); + void VisitBinaryOperator(BinaryOperator *Node); + void VisitCompoundAssignOperator(CompoundAssignOperator *Node); + void VisitAddrLabelExpr(AddrLabelExpr *Node); + void VisitTypesCompatibleExpr(TypesCompatibleExpr *Node); + + // C++ + void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node); + void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node); + void VisitCXXThisExpr(CXXThisExpr *Node); + void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node); + + // ObjC + void VisitObjCEncodeExpr(ObjCEncodeExpr *Node); + void VisitObjCMessageExpr(ObjCMessageExpr* Node); + void VisitObjCSelectorExpr(ObjCSelectorExpr *Node); + void VisitObjCProtocolExpr(ObjCProtocolExpr *Node); + void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node); + void VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node); + void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node); + void VisitObjCSuperExpr(ObjCSuperExpr *Node); + }; +} + +//===----------------------------------------------------------------------===// +// Stmt printing methods. +//===----------------------------------------------------------------------===// + +void StmtXML::VisitStmt(Stmt *Node) +{ + // nothing special to do +} + +void StmtXML::VisitDeclStmt(DeclStmt *Node) +{ + for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end(); + DI != DE; ++DI) + { + Doc.PrintDecl(*DI); + } +} + +void StmtXML::VisitLabelStmt(LabelStmt *Node) +{ + Doc.addAttribute("name", Node->getName()); +} + +void StmtXML::VisitGotoStmt(GotoStmt *Node) +{ + Doc.addAttribute("name", Node->getLabel()->getName()); +} + +//===----------------------------------------------------------------------===// +// Expr printing methods. +//===----------------------------------------------------------------------===// + +void StmtXML::VisitExpr(Expr *Node) { + DumpExpr(Node); +} + +void StmtXML::VisitDeclRefExpr(DeclRefExpr *Node) { + DumpExpr(Node); + + const char* pKind; + switch (Node->getDecl()->getKind()) { + case Decl::Function: pKind = "FunctionDecl"; break; + case Decl::Var: pKind = "Var"; break; + case Decl::ParmVar: pKind = "ParmVar"; break; + case Decl::EnumConstant: pKind = "EnumConstant"; break; + case Decl::Typedef: pKind = "Typedef"; break; + case Decl::Record: pKind = "Record"; break; + case Decl::Enum: pKind = "Enum"; break; + case Decl::CXXRecord: pKind = "CXXRecord"; break; + case Decl::ObjCInterface: pKind = "ObjCInterface"; break; + case Decl::ObjCClass: pKind = "ObjCClass"; break; + default: pKind = "Decl"; break; + } + + Doc.addAttribute("kind", pKind); + Doc.addAttribute("name", Node->getDecl()->getNameAsString()); + Doc.addRefAttribute(Node->getDecl()); +} + +void StmtXML::VisitPredefinedExpr(PredefinedExpr *Node) { + DumpExpr(Node); + switch (Node->getIdentType()) { + default: assert(0 && "unknown case"); + case PredefinedExpr::Func: Doc.addAttribute("predefined", " __func__"); break; + case PredefinedExpr::Function: Doc.addAttribute("predefined", " __FUNCTION__"); break; + case PredefinedExpr::PrettyFunction: Doc.addAttribute("predefined", " __PRETTY_FUNCTION__");break; + } +} + +void StmtXML::VisitCharacterLiteral(CharacterLiteral *Node) { + DumpExpr(Node); + Doc.addAttribute("value", Node->getValue()); +} + +void StmtXML::VisitIntegerLiteral(IntegerLiteral *Node) { + DumpExpr(Node); + bool isSigned = Node->getType()->isSignedIntegerType(); + Doc.addAttribute("value", Node->getValue().toString(10, isSigned)); +} + +void StmtXML::VisitFloatingLiteral(FloatingLiteral *Node) { + DumpExpr(Node); + // FIXME: output float as written in source (no approximation or the like) + //Doc.addAttribute("value", Node->getValueAsApproximateDouble())); + Doc.addAttribute("value", "FIXME"); +} + +void StmtXML::VisitStringLiteral(StringLiteral *Str) { + DumpExpr(Str); + if (Str->isWide()) + Doc.addAttribute("is_wide", "1"); + + Doc.addAttribute("value", Doc.escapeString(Str->getStrData(), Str->getByteLength())); +} + + +const char *StmtXML::getOpcodeStr(UnaryOperator::Opcode Op) { + switch (Op) { + default: assert(0 && "Unknown unary operator"); + case UnaryOperator::PostInc: return "postinc"; + case UnaryOperator::PostDec: return "postdec"; + case UnaryOperator::PreInc: return "preinc"; + case UnaryOperator::PreDec: return "predec"; + case UnaryOperator::AddrOf: return "addrof"; + case UnaryOperator::Deref: return "deref"; + case UnaryOperator::Plus: return "plus"; + case UnaryOperator::Minus: return "minus"; + case UnaryOperator::Not: return "not"; + case UnaryOperator::LNot: return "lnot"; + case UnaryOperator::Real: return "__real"; + case UnaryOperator::Imag: return "__imag"; + case UnaryOperator::Extension: return "__extension__"; + case UnaryOperator::OffsetOf: return "__builtin_offsetof"; + } +} + + +const char *StmtXML::getOpcodeStr(BinaryOperator::Opcode Op) { + switch (Op) { + default: assert(0 && "Unknown binary operator"); + case BinaryOperator::PtrMemD: return "ptrmemd"; + case BinaryOperator::PtrMemI: return "ptrmemi"; + case BinaryOperator::Mul: return "mul"; + case BinaryOperator::Div: return "div"; + case BinaryOperator::Rem: return "rem"; + case BinaryOperator::Add: return "add"; + case BinaryOperator::Sub: return "sub"; + case BinaryOperator::Shl: return "shl"; + case BinaryOperator::Shr: return "shr"; + case BinaryOperator::LT: return "lt"; + case BinaryOperator::GT: return "gt"; + case BinaryOperator::LE: return "le"; + case BinaryOperator::GE: return "ge"; + case BinaryOperator::EQ: return "eq"; + case BinaryOperator::NE: return "ne"; + case BinaryOperator::And: return "and"; + case BinaryOperator::Xor: return "xor"; + case BinaryOperator::Or: return "or"; + case BinaryOperator::LAnd: return "land"; + case BinaryOperator::LOr: return "lor"; + case BinaryOperator::Assign: return "assign"; + case BinaryOperator::MulAssign: return "mulassign"; + case BinaryOperator::DivAssign: return "divassign"; + case BinaryOperator::RemAssign: return "remassign"; + case BinaryOperator::AddAssign: return "addassign"; + case BinaryOperator::SubAssign: return "subassign"; + case BinaryOperator::ShlAssign: return "shlassign"; + case BinaryOperator::ShrAssign: return "shrassign"; + case BinaryOperator::AndAssign: return "andassign"; + case BinaryOperator::XorAssign: return "xorassign"; + case BinaryOperator::OrAssign: return "orassign"; + case BinaryOperator::Comma: return "comma"; + } +} + +void StmtXML::VisitUnaryOperator(UnaryOperator *Node) { + DumpExpr(Node); + Doc.addAttribute("op_code", getOpcodeStr(Node->getOpcode())); +} + +void StmtXML::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) { + DumpExpr(Node); + Doc.addAttribute("is_sizeof", Node->isSizeOf() ? "sizeof" : "alignof"); + Doc.addAttribute("is_type", Node->isArgumentType() ? "1" : "0"); + if (Node->isArgumentType()) + { + DumpTypeExpr(Node->getArgumentType()); + } +} + +void StmtXML::VisitMemberExpr(MemberExpr *Node) { + DumpExpr(Node); + Doc.addAttribute("is_deref", Node->isArrow() ? "1" : "0"); + Doc.addAttribute("name", Node->getMemberDecl()->getNameAsString()); + Doc.addRefAttribute(Node->getMemberDecl()); +} + +void StmtXML::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) { + DumpExpr(Node); + Doc.addAttribute("name", Node->getAccessor().getName()); +} + +void StmtXML::VisitBinaryOperator(BinaryOperator *Node) { + DumpExpr(Node); + Doc.addAttribute("op_code", getOpcodeStr(Node->getOpcode())); +} + +void StmtXML::VisitCompoundAssignOperator(CompoundAssignOperator *Node) { + VisitBinaryOperator(Node); +/* FIXME: is this needed in the AST? + DumpExpr(Node); + CurrentNode = CurrentNode->addSubNode("ComputeLHSTy"); + DumpType(Node->getComputationLHSType()); + CurrentNode = CurrentNode->Parent->addSubNode("ComputeResultTy"); + DumpType(Node->getComputationResultType()); + Doc.toParent(); +*/ +} + +// GNU extensions. + +void StmtXML::VisitAddrLabelExpr(AddrLabelExpr *Node) { + DumpExpr(Node); + Doc.addAttribute("name", Node->getLabel()->getName()); +} + +void StmtXML::VisitTypesCompatibleExpr(TypesCompatibleExpr *Node) { + DumpExpr(Node); + DumpTypeExpr(Node->getArgType1()); + DumpTypeExpr(Node->getArgType2()); +} + +//===----------------------------------------------------------------------===// +// C++ Expressions +//===----------------------------------------------------------------------===// + +void StmtXML::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) { + DumpExpr(Node); + Doc.addAttribute("kind", Node->getCastName()); + DumpTypeExpr(Node->getTypeAsWritten()); +} + +void StmtXML::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) { + DumpExpr(Node); + Doc.addAttribute("value", Node->getValue() ? "true" : "false"); +} + +void StmtXML::VisitCXXThisExpr(CXXThisExpr *Node) { + DumpExpr(Node); +} + +void StmtXML::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) { + DumpExpr(Node); + DumpTypeExpr(Node->getTypeAsWritten()); +} + +//===----------------------------------------------------------------------===// +// Obj-C Expressions +//===----------------------------------------------------------------------===// + +void StmtXML::VisitObjCMessageExpr(ObjCMessageExpr* Node) { + DumpExpr(Node); + Doc.addAttribute("selector", Node->getSelector().getAsString()); + IdentifierInfo* clsName = Node->getClassName(); + if (clsName) + Doc.addAttribute("class", clsName->getName()); +} + +void StmtXML::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) { + DumpExpr(Node); + DumpTypeExpr(Node->getEncodedType()); +} + +void StmtXML::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) { + DumpExpr(Node); + Doc.addAttribute("selector", Node->getSelector().getAsString()); +} + +void StmtXML::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) { |