diff options
Diffstat (limited to 'lib/Frontend')
-rw-r--r-- | lib/Frontend/CMakeLists.txt | 2 | ||||
-rw-r--r-- | lib/Frontend/DeclXML.cpp | 161 | ||||
-rw-r--r-- | lib/Frontend/DocumentXML.cpp | 348 | ||||
-rw-r--r-- | lib/Frontend/StmtXML.cpp | 100 | ||||
-rw-r--r-- | lib/Frontend/TypeXML.cpp | 127 |
5 files changed, 436 insertions, 302 deletions
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index 649f9dae37..72d9a7ead9 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -5,6 +5,7 @@ add_clang_library(clangFrontend ASTConsumers.cpp Backend.cpp CacheTokens.cpp + DeclXML.cpp DependencyFile.cpp DiagChecker.cpp DocumentXML.cpp @@ -31,5 +32,6 @@ add_clang_library(clangFrontend StmtXML.cpp TextDiagnosticBuffer.cpp TextDiagnosticPrinter.cpp + TypeXML.cpp Warnings.cpp ) diff --git a/lib/Frontend/DeclXML.cpp b/lib/Frontend/DeclXML.cpp new file mode 100644 index 0000000000..5c21999bfa --- /dev/null +++ b/lib/Frontend/DeclXML.cpp @@ -0,0 +1,161 @@ +//===--- DeclXML.cpp - XML implementation for Decl 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/DeclVisitor.h" +#include "clang/AST/Expr.h" + +namespace clang { + +//--------------------------------------------------------- +class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter> +{ + DocumentXML& Doc; + + void addSubNodes(FunctionDecl* FD) + { + for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) + { + Visit(FD->getParamDecl(i)); + Doc.toParent(); + } + } + + void addSubNodes(RecordDecl* RD) + { + for (RecordDecl::field_iterator i = RD->field_begin(*Doc.Ctx), e = RD->field_end(*Doc.Ctx); i != e; ++i) + { + Visit(*i); + Doc.toParent(); + } + } + + void addSubNodes(EnumDecl* ED) + { + for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Doc.Ctx), e = ED->enumerator_end(*Doc.Ctx); i != e; ++i) + { + Visit(*i); + Doc.toParent(); + } + } + + void addSubNodes(EnumConstantDecl* ECD) + { + if (ECD->getInitExpr()) + { + Doc.PrintStmt(ECD->getInitExpr()); + } + } + + void addSubNodes(FieldDecl* FdD) + { + if (FdD->isBitField()) + { + Doc.PrintStmt(FdD->getBitWidth()); + } + } + + void addSubNodes(VarDecl* V) + { + if (V->getInit()) + { + Doc.PrintStmt(V->getInit()); + } + } + + void addSubNodes(ParmVarDecl* argDecl) + { + if (argDecl->getDefaultArg()) + { + Doc.PrintStmt(argDecl->getDefaultArg()); + } + } + + void addSpecialAttribute(const char* pName, EnumDecl* ED) + { + const QualType& enumType = ED->getIntegerType(); + if (!enumType.isNull()) + { + Doc.addAttribute(pName, enumType); + } + } + + void addIdAttribute(LinkageSpecDecl* ED) + { + Doc.addAttribute("id", ED); + } + + void addIdAttribute(NamedDecl* ND) + { + Doc.addAttribute("id", ND); + } + +public: + DeclPrinter(DocumentXML& doc) : Doc(doc) {} + +#define NODE_XML( CLASS, NAME ) \ + void Visit##CLASS(CLASS* T) \ + { \ + Doc.addSubNode(NAME); + +#define ID_ATTRIBUTE_XML addIdAttribute(T); +#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN); +#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN); +#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocation(T->getLocation()); +#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T); + +#define ATTRIBUTE_ENUM_XML( FN, NAME ) \ + { \ + const char* pAttributeName = NAME; \ + const bool optional = false; \ + switch (T->FN) { \ + default: assert(0 && "unknown enum value"); + +#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \ + { \ + const char* pAttributeName = NAME; \ + const bool optional = true; \ + switch (T->FN) { \ + default: assert(0 && "unknown enum value"); + +#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break; +#define END_ENUM_XML } } +#define END_NODE_XML } + +#define SUB_NODE_XML( CLASS ) addSubNodes(T); +#define SUB_NODE_SEQUENCE_XML( CLASS ) addSubNodes(T); +#define SUB_NODE_OPT_XML( CLASS ) addSubNodes(T); + +#include "clang/Frontend/DeclXML.def" +}; + + +//--------------------------------------------------------- +void DocumentXML::writeDeclToXML(Decl *D) +{ + DeclPrinter(*this).Visit(D); + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + { + if (Stmt *Body = FD->getBody(*Ctx)) { + addSubNode("Body"); + PrintStmt(Body); + toParent(); + } + } + toParent(); +} + +//--------------------------------------------------------- +} // NS clang + diff --git a/lib/Frontend/DocumentXML.cpp b/lib/Frontend/DocumentXML.cpp index 7562d2ae87..19a757303f 100644 --- a/lib/Frontend/DocumentXML.cpp +++ b/lib/Frontend/DocumentXML.cpp @@ -14,92 +14,66 @@ #include "clang/Frontend/DocumentXML.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/Expr.h" +#include "clang/AST/ASTContext.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) { + NodeStack.push(rootName); 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); + NodeStack.push(name); HasCurrentNodeSubNodes = false; - CurrentIndent += 2; Indent(); - Out << "<" << CurrentNode->Name; + Out << "<" << NodeStack.top(); return *this; } //--------------------------------------------------------- void DocumentXML::Indent() { - for (int i = 0; i < CurrentIndent; ++i) + for (size_t i = 0, e = (NodeStack.size() - 1) * 2; i < e; ++i) Out << ' '; } //--------------------------------------------------------- DocumentXML& DocumentXML::toParent() { - assert(CurrentNode != Root && "to much backtracking"); + assert(NodeStack.size() > 1 && "to much backtracking"); if (HasCurrentNodeSubNodes) { Indent(); - Out << "</" << CurrentNode->Name << ">\n"; + Out << "</" << NodeStack.top() << ">\n"; } else { Out << "/>\n"; } - NodeXML* NodeToDelete = CurrentNode; - CurrentNode = CurrentNode->Parent; - delete NodeToDelete; + NodeStack.pop(); HasCurrentNodeSubNodes = true; - CurrentIndent -= 2; return *this; } //--------------------------------------------------------- namespace { -enum tIdType { ID_NORMAL, ID_FILE, ID_LAST }; +enum tIdType { ID_NORMAL, ID_FILE, ID_LABEL, ID_LAST }; unsigned getNewId(tIdType idType) { @@ -110,7 +84,7 @@ unsigned getNewId(tIdType idType) //--------------------------------------------------------- inline std::string getPrefixedId(unsigned uId, tIdType idType) { - static const char idPrefix[ID_LAST] = { '_', 'f' }; + static const char idPrefix[ID_LAST] = { '_', 'f', 'l' }; char buffer[20]; char* BufPtr = llvm::utohex_buffer(uId, buffer + 20); *--BufPtr = idPrefix[idType]; @@ -132,6 +106,7 @@ bool addToMap(T& idMap, const V& value, tIdType idType = ID_NORMAL) } // anon NS + //--------------------------------------------------------- std::string DocumentXML::escapeString(const char* pStr, std::string::size_type len) { @@ -170,7 +145,7 @@ std::string DocumentXML::escapeString(const char* pStr, std::string::size_type l //--------------------------------------------------------- void DocumentXML::finalize() { - assert(CurrentNode == Root && "not completely backtracked"); + assert(NodeStack.size() == 1 && "not completely backtracked"); addSubNode("ReferenceSection"); addSubNode("Types"); @@ -179,71 +154,15 @@ void DocumentXML::finalize() { if (i->first.getCVRQualifiers() != 0) { - addSubNode("CvQualifiedType"); + writeTypeToXML(i->first); 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(Ctx->getLangOptions().CPlusPlus)); - } - 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"); - } + writeTypeToXML(i->first); addAttribute("id", getPrefixedId(i->second, ID_NORMAL)); toParent(); } @@ -267,7 +186,7 @@ void DocumentXML::finalize() if (const DeclContext* parent = i->first->getParent()) { - addContextAttribute(parent); + addAttribute("context", parent); } toParent(); } @@ -285,21 +204,21 @@ void DocumentXML::finalize() toParent().toParent(); // write the root closing node (which has always subnodes) - Out << "</" << CurrentNode->Name << ">\n"; + Out << "</" << NodeStack.top() << ">\n"; } //--------------------------------------------------------- -void DocumentXML::addTypeAttribute(const QualType& pType) +void DocumentXML::addAttribute(const char* pAttributeName, const QualType& pType) { addTypeRecursively(pType); - addAttribute("type", getPrefixedId(Types[pType], ID_NORMAL)); + addAttribute(pAttributeName, getPrefixedId(Types[pType], ID_NORMAL)); } //--------------------------------------------------------- -void DocumentXML::addTypeIdAttribute(const Type* pType) +void DocumentXML::addPtrAttribute(const char* pAttributeName, const Type* pType) { - addBasicTypeRecursively(pType); - addAttribute("id", getPrefixedId(BasicTypes[pType], ID_NORMAL)); + addTypeRecursively(pType); + addAttribute(pAttributeName, getPrefixedId(BasicTypes[pType], ID_NORMAL)); } //--------------------------------------------------------- @@ -307,7 +226,7 @@ void DocumentXML::addTypeRecursively(const QualType& pType) { if (addToMap(Types, pType)) { - addBasicTypeRecursively(pType.getTypePtr()); + addTypeRecursively(pType.getTypePtr()); // beautifier: a non-qualified type shall be transparent if (pType.getCVRQualifiers() == 0) { @@ -317,43 +236,49 @@ void DocumentXML::addTypeRecursively(const QualType& pType) } //--------------------------------------------------------- -void DocumentXML::addBasicTypeRecursively(const Type* pType) +void DocumentXML::addTypeRecursively(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(); - }*/ + addParentTypes(pType); +/* + // FIXME: doesn't work in the immediate streaming approach + if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(pType)) + { + addSubNode("VariableArraySizeExpression"); + PrintStmt(VAT->getSizeExpr()); + toParent(); } +*/ } } //--------------------------------------------------------- -void DocumentXML::addContextAttribute(const DeclContext *DC, tContextUsage usage) +void DocumentXML::addPtrAttribute(const char* pName, const DeclContext* DC) { addContextsRecursively(DC); - const char* pAttributeTags[2] = { "context", "id" }; - addAttribute(pAttributeTags[usage], getPrefixedId(Contexts[DC], ID_NORMAL)); + addAttribute(pName, getPrefixedId(Contexts[DC], ID_NORMAL)); +} + +//--------------------------------------------------------- +void DocumentXML::addPtrAttribute(const char* pAttributeName, const NamedDecl* D) +{ + if (const DeclContext* DC = dyn_cast<DeclContext>(D)) + { + addContextsRecursively(DC); + addAttribute(pAttributeName, getPrefixedId(Contexts[DC], ID_NORMAL)); + } + else + { + addToMap(Decls, D); + addAttribute(pAttributeName, getPrefixedId(Decls[D], ID_NORMAL)); + } +} + +//--------------------------------------------------------- +void DocumentXML::addPtrAttribute(const char* pName, const NamespaceDecl* D) +{ + addPtrAttribute(pName, static_cast<const DeclContext*>(D)); } //--------------------------------------------------------- @@ -372,6 +297,15 @@ void DocumentXML::addSourceFileAttribute(const std::string& fileName) addAttribute("file", getPrefixedId(SourceFiles[fileName], ID_FILE)); } + +//--------------------------------------------------------- +void DocumentXML::addPtrAttribute(const char* pName, const LabelStmt* L) +{ + addToMap(Labels, L, ID_LABEL); + addAttribute(pName, getPrefixedId(Labels[L], ID_LABEL)); +} + + //--------------------------------------------------------- PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc) { @@ -417,161 +351,9 @@ void DocumentXML::addLocationRange(const SourceRange& R) } //--------------------------------------------------------- -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 if (isa<FileScopeAsmDecl>(D)) { - // FIXME: Implement this - } else { - assert(0 && "Unexpected decl"); - } - toParent(); + writeDeclToXML(D); } //--------------------------------------------------------- diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp index c861881486..6ba0a28c7d 100644 --- a/lib/Frontend/StmtXML.cpp +++ b/lib/Frontend/StmtXML.cpp @@ -28,8 +28,31 @@ namespace { class VISIBILITY_HIDDEN StmtXML : public StmtVisitor<StmtXML> { DocumentXML& Doc; - static const char *getOpcodeStr(UnaryOperator::Opcode Op); - static const char *getOpcodeStr(BinaryOperator::Opcode Op); + //static const char *getOpcodeStr(UnaryOperator::Opcode Op); + //static const char *getOpcodeStr(BinaryOperator::Opcode Op); + + + void addSpecialAttribute(const char* pName, StringLiteral* Str) + { + Doc.addAttribute(pName, Doc.escapeString(Str->getStrData(), Str->getByteLength())); + } + + void addSpecialAttribute(const char* pName, SizeOfAlignOfExpr* S) + { + if (S->isArgumentType()) + { + Doc.addAttribute(pName, S->getArgumentType()); + } + } + + void addSpecialAttribute(const char* pName, CXXTypeidExpr* S) + { + if (S->isTypeOperand()) + { + Doc.addAttribute(pName, S->getTypeOperand()); + } + } + public: StmtXML(DocumentXML& doc) @@ -39,12 +62,21 @@ namespace { 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); + Visit(S); + if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) + { + for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); + DI != DE; ++DI) + { + Doc.PrintDecl(*DI); + } + } + else + { + if (CXXConditionDeclExpr* CCDE = dyn_cast<CXXConditionDeclExpr>(S)) + { + Doc.PrintDecl(CCDE->getVarDecl()); + } for (Stmt::child_iterator i = S->child_begin(), e = S->child_end(); i != e; ++i) { DumpSubTree(*i); @@ -56,17 +88,46 @@ namespace { } } - void DumpTypeExpr(const QualType& T) - { - Doc.addSubNode("TypeExpr"); - Doc.addTypeAttribute(T); - Doc.toParent(); - } - void DumpExpr(const Expr *Node) { - Doc.addTypeAttribute(Node->getType()); - } +#define NODE_XML( CLASS, NAME ) \ + void Visit##CLASS(CLASS* S) \ + { \ + typedef CLASS tStmtType; \ + Doc.addSubNode(NAME); + +#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, S->FN); +#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") +#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, S->FN); +#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, S); +#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocationRange(S->getSourceRange()); + +#define ATTRIBUTE_ENUM_XML( FN, NAME ) \ + { \ + const char* pAttributeName = NAME; \ + const bool optional = false; \ + switch (S->FN) { \ + default: assert(0 && "unknown enum value"); + +#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \ + { \ + const char* pAttributeName = NAME; \ + const bool optional = true; \ + switch (S->FN) { \ + default: assert(0 && "unknown enum value"); + +#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break; +#define END_ENUM_XML } } +#define END_NODE_XML } + +#define ID_ATTRIBUTE_XML Doc.addAttribute("id", S); +#define SUB_NODE_XML( CLASS ) +#define SUB_NODE_SEQUENCE_XML( CLASS ) +#define SUB_NODE_OPT_XML( CLASS ) + +#include "clang/Frontend/StmtXML.def" + +#if (0) // Stmts. void VisitStmt(Stmt *Node); void VisitDeclStmt(DeclStmt *Node); @@ -105,13 +166,14 @@ namespace { void VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node); void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node); void VisitObjCSuperExpr(ObjCSuperExpr *Node); +#endif }; } //===----------------------------------------------------------------------===// // Stmt printing methods. //===----------------------------------------------------------------------===// - +#if (0) void StmtXML::VisitStmt(Stmt *Node) { // nothing special to do @@ -396,7 +458,7 @@ void StmtXML::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { if (Node->isFreeIvar()) Doc.addAttribute("isFreeIvar", "1"); } - +#endif //===----------------------------------------------------------------------===// // Stmt method implementations //===----------------------------------------------------------------------===// diff --git a/lib/Frontend/TypeXML.cpp b/lib/Frontend/TypeXML.cpp new file mode 100644 index 0000000000..f32fbbd241 --- /dev/null +++ b/lib/Frontend/TypeXML.cpp @@ -0,0 +1,127 @@ +//===--- 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/TypeVisitor.h" +#include "clang/AST/Type.h" +#include "clang/AST/Decl.h" + +namespace clang { + namespace XML { + namespace { + +//--------------------------------------------------------- +class TypeWriter : public TypeVisitor<TypeWriter> +{ + DocumentXML& Doc; + +public: + TypeWriter(DocumentXML& doc) : Doc(doc) {} + +#define NODE_XML( CLASS, NAME ) \ + void Visit##CLASS(CLASS* T) \ + { \ + Doc.addSubNode(NAME); + +#define ID_ATTRIBUTE_XML // done by the Document class itself +#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN); +#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") +#define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") +#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN); + +#define ATTRIBUTE_ENUM_XML( FN, NAME ) \ + { \ + const char* pAttributeName = NAME; \ + const bool optional = false; \ + switch (T->FN) { \ + default: assert(0 && "unknown enum value"); + +#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \ + { \ + const char* pAttributeName = NAME; \ + const bool optional = true; \ + switch (T->FN) { \ + default: assert(0 && "unknown enum value"); + +#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break; +#define END_ENUM_XML } } +#define END_NODE_XML } + +#include "clang/Frontend/TypeXML.def" + +}; + +//--------------------------------------------------------- + } // anon clang + } // NS XML + +//--------------------------------------------------------- +class DocumentXML::TypeAdder : public TypeVisitor<DocumentXML::TypeAdder> +{ + DocumentXML& Doc; + + void addIfType(const Type* pType) + { + Doc.addTypeRecursively(pType); + } + + void addIfType(const QualType& pType) + { + Doc.addTypeRecursively(pType); + } + + template<class T> void addIfType(T) {} + +public: + TypeAdder(DocumentXML& doc) : Doc(doc) {} + +#define NODE_XML( CLASS, NAME ) \ + void Visit##CLASS(CLASS* T) \ + { + +#define ID_ATTRIBUTE_XML +#define TYPE_ATTRIBUTE_XML( FN ) Doc.addTypeRecursively(T->FN); +#define CONTEXT_ATTRIBUTE_XML( FN ) +#define ATTRIBUTE_XML( FN, NAME ) addIfType(T->FN); +#define ATTRIBUTE_OPT_XML( FN, NAME ) +#define ATTRIBUTE_ENUM_XML( FN, NAME ) +#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) +#define ENUM_XML( VALUE, NAME ) +#define END_ENUM_XML +#define END_NODE_XML } + +#include "clang/Frontend/TypeXML.def" +}; + +//--------------------------------------------------------- +void DocumentXML::addParentTypes(const Type* pType) +{ + TypeAdder(*this).Visit(const_cast<Type*>(pType)); +} + +//--------------------------------------------------------- +void DocumentXML::writeTypeToXML(const Type* pType) +{ + XML::TypeWriter(*this).Visit(const_cast<Type*>(pType)); +} + +//--------------------------------------------------------- +void DocumentXML::writeTypeToXML(const QualType& pType) +{ + XML::TypeWriter(*this).VisitQualType(const_cast<QualType*>(&pType)); +} + +//--------------------------------------------------------- +} // NS clang + |