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