| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 1 | //===--- DocumentXML.cpp - XML document for ASTs --------------------------===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 10 | // This file implements the XML document class, which provides the means to | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 11 | // dump out the AST in a XML form that exposes type details and other fields. | 
|  | 12 | // | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
|  | 15 | #include "clang/Frontend/DocumentXML.h" | 
|  | 16 | #include "clang/AST/Decl.h" | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 17 | #include "clang/AST/ASTContext.h" | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 18 | #include "clang/Basic/SourceManager.h" | 
|  | 19 | #include "llvm/ADT/StringExtras.h" | 
|  | 20 |  | 
|  | 21 | namespace clang { | 
|  | 22 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 23 | //--------------------------------------------------------- | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 24 | DocumentXML::DocumentXML(const std::string& rootName, llvm::raw_ostream& out) : | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 25 | Out(out), | 
|  | 26 | Ctx(0), | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 27 | HasCurrentNodeSubNodes(false) { | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 28 | NodeStack.push(rootName); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 29 | Out << "<?xml version=\"1.0\"?>\n<" << rootName; | 
|  | 30 | } | 
|  | 31 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 32 | //--------------------------------------------------------- | 
|  | 33 | DocumentXML& DocumentXML::addSubNode(const std::string& name) { | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 34 | if (!HasCurrentNodeSubNodes) | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 35 | Out << ">\n"; | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 36 | NodeStack.push(name); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 37 | HasCurrentNodeSubNodes = false; | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 38 | Indent(); | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 39 | Out << "<" << NodeStack.top(); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 40 | return *this; | 
|  | 41 | } | 
|  | 42 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 43 | //--------------------------------------------------------- | 
|  | 44 | void DocumentXML::Indent() { | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 45 | for (size_t i = 0, e = (NodeStack.size() - 1) * 2; i < e; ++i) | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 46 | Out << ' '; | 
|  | 47 | } | 
|  | 48 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 49 | //--------------------------------------------------------- | 
|  | 50 | DocumentXML& DocumentXML::toParent() { | 
| Mike Stump | 197c8d9 | 2009-09-16 20:41:09 +0000 | [diff] [blame] | 51 | assert(NodeStack.size() > 1 && "too much backtracking"); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 52 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 53 | if (HasCurrentNodeSubNodes) { | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 54 | Indent(); | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 55 | Out << "</" << NodeStack.top() << ">\n"; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 56 | } else | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 57 | Out << "/>\n"; | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 58 | NodeStack.pop(); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 59 | HasCurrentNodeSubNodes = true; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 60 | return *this; | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 61 | } | 
|  | 62 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 63 | //--------------------------------------------------------- | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 64 | namespace { | 
|  | 65 |  | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 66 | enum tIdType { ID_NORMAL, ID_FILE, ID_LABEL, ID_LAST }; | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 67 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 68 | unsigned getNewId(tIdType idType) { | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 69 | static unsigned int idCounts[ID_LAST] = { 0 }; | 
|  | 70 | return ++idCounts[idType]; | 
|  | 71 | } | 
|  | 72 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 73 | //--------------------------------------------------------- | 
|  | 74 | inline std::string getPrefixedId(unsigned uId, tIdType idType) { | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 75 | static const char idPrefix[ID_LAST] = { '_', 'f', 'l' }; | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 76 | char buffer[20]; | 
|  | 77 | char* BufPtr = llvm::utohex_buffer(uId, buffer + 20); | 
|  | 78 | *--BufPtr = idPrefix[idType]; | 
|  | 79 | return BufPtr; | 
|  | 80 | } | 
|  | 81 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 82 | //--------------------------------------------------------- | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 83 | template<class T, class V> | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 84 | bool addToMap(T& idMap, const V& value, tIdType idType = ID_NORMAL) { | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 85 | typename T::iterator i = idMap.find(value); | 
|  | 86 | bool toAdd = i == idMap.end(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 87 | if (toAdd) | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 88 | idMap.insert(typename T::value_type(value, getNewId(idType))); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 89 | return toAdd; | 
|  | 90 | } | 
|  | 91 |  | 
|  | 92 | } // anon NS | 
|  | 93 |  | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 94 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 95 | //--------------------------------------------------------- | 
|  | 96 | std::string DocumentXML::escapeString(const char* pStr, | 
|  | 97 | std::string::size_type len) { | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 98 | std::string value; | 
|  | 99 | value.reserve(len + 1); | 
|  | 100 | char buffer[16]; | 
|  | 101 | for (unsigned i = 0; i < len; ++i) { | 
|  | 102 | switch (char C = pStr[i]) { | 
|  | 103 | default: | 
|  | 104 | if (isprint(C)) | 
|  | 105 | value += C; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 106 | else { | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 107 | sprintf(buffer, "\\%03o", C); | 
|  | 108 | value += buffer; | 
|  | 109 | } | 
|  | 110 | break; | 
|  | 111 |  | 
|  | 112 | case '\n': value += "\\n"; break; | 
|  | 113 | case '\t': value += "\\t"; break; | 
|  | 114 | case '\a': value += "\\a"; break; | 
|  | 115 | case '\b': value += "\\b"; break; | 
|  | 116 | case '\r': value += "\\r"; break; | 
|  | 117 |  | 
|  | 118 | case '&': value += "&"; break; | 
|  | 119 | case '<': value += "<"; break; | 
|  | 120 | case '>': value += ">"; break; | 
|  | 121 | case '"': value += """; break; | 
|  | 122 | case '\'':  value += "'"; break; | 
|  | 123 |  | 
|  | 124 | } | 
|  | 125 | } | 
|  | 126 | return value; | 
|  | 127 | } | 
|  | 128 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 129 | //--------------------------------------------------------- | 
|  | 130 | void DocumentXML::finalize() { | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 131 | assert(NodeStack.size() == 1 && "not completely backtracked"); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 132 |  | 
|  | 133 | addSubNode("ReferenceSection"); | 
|  | 134 | addSubNode("Types"); | 
|  | 135 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 136 | for (XML::IdMap<QualType>::iterator i = Types.begin(), e = Types.end(); | 
|  | 137 | i != e; ++i) { | 
| Douglas Gregor | a4923eb | 2009-11-16 21:35:15 +0000 | [diff] [blame] | 138 | if (i->first.hasLocalQualifiers()) { | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 139 | writeTypeToXML(i->first); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 140 | addAttribute("id", getPrefixedId(i->second, ID_NORMAL)); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 141 | toParent(); | 
|  | 142 | } | 
|  | 143 | } | 
|  | 144 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 145 | for (XML::IdMap<const Type*>::iterator i = BasicTypes.begin(), | 
|  | 146 | e = BasicTypes.end(); i != e; ++i) { | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 147 | writeTypeToXML(i->first); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 148 | addAttribute("id", getPrefixedId(i->second, ID_NORMAL)); | 
|  | 149 | toParent(); | 
|  | 150 | } | 
|  | 151 |  | 
|  | 152 |  | 
|  | 153 | toParent().addSubNode("Contexts"); | 
|  | 154 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 155 | for (XML::IdMap<const DeclContext*>::iterator i = Contexts.begin(), | 
|  | 156 | e = Contexts.end(); i != e; ++i) { | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 157 | addSubNode(i->first->getDeclKindName()); | 
|  | 158 | addAttribute("id", getPrefixedId(i->second, ID_NORMAL)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 159 | if (const NamedDecl *ND = dyn_cast<NamedDecl>(i->first)) | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 160 | addAttribute("name", ND->getNameAsString()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 161 | if (const TagDecl *TD = dyn_cast<TagDecl>(i->first)) | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 162 | addAttribute("type", getPrefixedId(BasicTypes[TD->getTypeForDecl()], ID_NORMAL)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 163 | else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(i->first)) | 
| John McCall | 183700f | 2009-09-21 23:43:11 +0000 | [diff] [blame] | 164 | addAttribute("type", getPrefixedId(BasicTypes[FD->getType()->getAs<FunctionType>()], ID_NORMAL)); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 165 |  | 
|  | 166 | if (const DeclContext* parent = i->first->getParent()) | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 167 | addAttribute("context", parent); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 168 | toParent(); | 
|  | 169 | } | 
|  | 170 |  | 
|  | 171 | toParent().addSubNode("Files"); | 
|  | 172 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 173 | for (XML::IdMap<std::string>::iterator i = SourceFiles.begin(), | 
|  | 174 | e = SourceFiles.end(); i != e; ++i) { | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 175 | addSubNode("File"); | 
|  | 176 | addAttribute("id", getPrefixedId(i->second, ID_FILE)); | 
|  | 177 | addAttribute("name", escapeString(i->first.c_str(), i->first.size())); | 
|  | 178 | toParent(); | 
|  | 179 | } | 
|  | 180 |  | 
|  | 181 | toParent().toParent(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 182 |  | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 183 | // write the root closing node (which has always subnodes) | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 184 | Out << "</" << NodeStack.top() << ">\n"; | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 185 | } | 
|  | 186 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 187 | //--------------------------------------------------------- | 
|  | 188 | void DocumentXML::addAttribute(const char* pAttributeName, | 
|  | 189 | const QualType& pType) { | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 190 | addTypeRecursively(pType); | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 191 | addAttribute(pAttributeName, getPrefixedId(Types[pType], ID_NORMAL)); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 192 | } | 
|  | 193 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 194 | //--------------------------------------------------------- | 
|  | 195 | void DocumentXML::addPtrAttribute(const char* pAttributeName, | 
|  | 196 | const Type* pType) { | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 197 | addTypeRecursively(pType); | 
|  | 198 | addAttribute(pAttributeName, getPrefixedId(BasicTypes[pType], ID_NORMAL)); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 199 | } | 
|  | 200 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 201 | //--------------------------------------------------------- | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 202 | void DocumentXML::addTypeRecursively(const QualType& pType) | 
|  | 203 | { | 
|  | 204 | if (addToMap(Types, pType)) | 
|  | 205 | { | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 206 | addTypeRecursively(pType.getTypePtr()); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 207 | // beautifier: a non-qualified type shall be transparent | 
| Douglas Gregor | a4923eb | 2009-11-16 21:35:15 +0000 | [diff] [blame] | 208 | if (!pType.hasLocalQualifiers()) | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 209 | { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 210 | Types[pType] = BasicTypes[pType.getTypePtr()]; | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 211 | } | 
|  | 212 | } | 
|  | 213 | } | 
|  | 214 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 215 | //--------------------------------------------------------- | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 216 | void DocumentXML::addTypeRecursively(const Type* pType) | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 217 | { | 
|  | 218 | if (addToMap(BasicTypes, pType)) | 
|  | 219 | { | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 220 | addParentTypes(pType); | 
|  | 221 | /* | 
|  | 222 | // FIXME: doesn't work in the immediate streaming approach | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 223 | if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(pType)) | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 224 | { | 
|  | 225 | addSubNode("VariableArraySizeExpression"); | 
|  | 226 | PrintStmt(VAT->getSizeExpr()); | 
|  | 227 | toParent(); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 228 | } | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 229 | */ | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 230 | } | 
|  | 231 | } | 
|  | 232 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 233 | //--------------------------------------------------------- | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 234 | void DocumentXML::addPtrAttribute(const char* pName, const DeclContext* DC) | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 235 | { | 
|  | 236 | addContextsRecursively(DC); | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 237 | addAttribute(pName, getPrefixedId(Contexts[DC], ID_NORMAL)); | 
|  | 238 | } | 
|  | 239 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 240 | //--------------------------------------------------------- | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 241 | void DocumentXML::addPtrAttribute(const char* pAttributeName, const NamedDecl* D) | 
|  | 242 | { | 
|  | 243 | if (const DeclContext* DC = dyn_cast<DeclContext>(D)) | 
|  | 244 | { | 
|  | 245 | addContextsRecursively(DC); | 
|  | 246 | addAttribute(pAttributeName, getPrefixedId(Contexts[DC], ID_NORMAL)); | 
|  | 247 | } | 
|  | 248 | else | 
|  | 249 | { | 
|  | 250 | addToMap(Decls, D); | 
|  | 251 | addAttribute(pAttributeName, getPrefixedId(Decls[D], ID_NORMAL)); | 
|  | 252 | } | 
|  | 253 | } | 
|  | 254 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 255 | //--------------------------------------------------------- | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 256 | void DocumentXML::addPtrAttribute(const char* pName, const NamespaceDecl* D) | 
|  | 257 | { | 
|  | 258 | addPtrAttribute(pName, static_cast<const DeclContext*>(D)); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 259 | } | 
|  | 260 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 261 | //--------------------------------------------------------- | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 262 | void DocumentXML::addContextsRecursively(const DeclContext *DC) | 
|  | 263 | { | 
|  | 264 | if (DC != 0 && addToMap(Contexts, DC)) | 
|  | 265 | { | 
|  | 266 | addContextsRecursively(DC->getParent()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 267 | } | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 268 | } | 
|  | 269 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 270 | //--------------------------------------------------------- | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 271 | void DocumentXML::addSourceFileAttribute(const std::string& fileName) | 
|  | 272 | { | 
|  | 273 | addToMap(SourceFiles, fileName, ID_FILE); | 
|  | 274 | addAttribute("file", getPrefixedId(SourceFiles[fileName], ID_FILE)); | 
|  | 275 | } | 
|  | 276 |  | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 277 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 278 | //--------------------------------------------------------- | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 279 | void DocumentXML::addPtrAttribute(const char* pName, const LabelStmt* L) | 
|  | 280 | { | 
|  | 281 | addToMap(Labels, L, ID_LABEL); | 
|  | 282 | addAttribute(pName, getPrefixedId(Labels[L], ID_LABEL)); | 
|  | 283 | } | 
|  | 284 |  | 
|  | 285 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 286 | //--------------------------------------------------------- | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 287 | PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc) | 
|  | 288 | { | 
|  | 289 | SourceManager& SM = Ctx->getSourceManager(); | 
|  | 290 | SourceLocation SpellingLoc = SM.getSpellingLoc(Loc); | 
|  | 291 | PresumedLoc PLoc; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 292 | if (!SpellingLoc.isInvalid()) | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 293 | { | 
|  | 294 | PLoc = SM.getPresumedLoc(SpellingLoc); | 
|  | 295 | addSourceFileAttribute(PLoc.getFilename()); | 
|  | 296 | addAttribute("line", PLoc.getLine()); | 
|  | 297 | addAttribute("col", PLoc.getColumn()); | 
|  | 298 | } | 
|  | 299 | // else there is no error in some cases (eg. CXXThisExpr) | 
|  | 300 | return PLoc; | 
|  | 301 | } | 
|  | 302 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 303 | //--------------------------------------------------------- | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 304 | void DocumentXML::addLocationRange(const SourceRange& R) | 
|  | 305 | { | 
|  | 306 | PresumedLoc PStartLoc = addLocation(R.getBegin()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 307 | if (R.getBegin() != R.getEnd()) | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 308 | { | 
|  | 309 | SourceManager& SM = Ctx->getSourceManager(); | 
|  | 310 | SourceLocation SpellingLoc = SM.getSpellingLoc(R.getEnd()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 311 | if (!SpellingLoc.isInvalid()) | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 312 | { | 
|  | 313 | PresumedLoc PLoc = SM.getPresumedLoc(SpellingLoc); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 314 | if (PStartLoc.isInvalid() || | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 315 | strcmp(PLoc.getFilename(), PStartLoc.getFilename()) != 0) { | 
|  | 316 | addToMap(SourceFiles, PLoc.getFilename(), ID_FILE); | 
|  | 317 | addAttribute("endfile", PLoc.getFilename()); | 
|  | 318 | addAttribute("endline", PLoc.getLine()); | 
|  | 319 | addAttribute("endcol", PLoc.getColumn()); | 
|  | 320 | } else if (PLoc.getLine() != PStartLoc.getLine()) { | 
|  | 321 | addAttribute("endline", PLoc.getLine()); | 
|  | 322 | addAttribute("endcol", PLoc.getColumn()); | 
|  | 323 | } else { | 
|  | 324 | addAttribute("endcol", PLoc.getColumn()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 325 | } | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 326 | } | 
|  | 327 | } | 
|  | 328 | } | 
|  | 329 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 330 | //--------------------------------------------------------- | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 331 | void DocumentXML::PrintDecl(Decl *D) | 
|  | 332 | { | 
| Douglas Gregor | 038f75a | 2009-06-15 19:02:54 +0000 | [diff] [blame] | 333 | writeDeclToXML(D); | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 334 | } | 
|  | 335 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 336 | //--------------------------------------------------------- | 
| Douglas Gregor | ee75c05 | 2009-05-21 20:55:50 +0000 | [diff] [blame] | 337 | } // NS clang | 
|  | 338 |  |