zcov: / lib/Frontend/DocumentXML.cpp


Files: 1 Branches Taken: 81.6% 71 / 87
Generated: 2010-02-10 01:31 Branches Executed: 95.4% 83 / 87
Line Coverage: 89.9% 152 / 169


Programs: 1 Runs 2897


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

Generated: 2010-02-10 01:31 by zcov