In preparation for some docs on source locations I want to write I came up
with the little helper method that visualizes source locations as a tree.
This is especially helpful when you have many nested levels of macro
expansions.

Example output:
(SP=(:6:14),
 EX=(SP=(:2:14),
     ES=(:6:8),
     EE=(:6:15)))

SP = spelling
EX = expansion (if there's only a single location)
ES/EE = expansion start, expansion end (in case there's a range)

Feel free to bikeshed about the details :D

http://llvm-reviews.chandlerc.com/D768

Files:
  include/clang/Basic/SourceLocation.h
  lib/Basic/SourceLocation.cpp

Index: include/clang/Basic/SourceLocation.h
===================================================================
--- include/clang/Basic/SourceLocation.h
+++ include/clang/Basic/SourceLocation.h
@@ -174,6 +174,8 @@
   void print(raw_ostream &OS, const SourceManager &SM) const;
   LLVM_ATTRIBUTE_USED std::string printToString(const SourceManager &SM) const;
   void dump(const SourceManager &SM) const;
+  LLVM_ATTRIBUTE_USED std::string printTreeToString(const SourceManager &SM,
+                                                    unsigned Indent = 0) const;
 };
 
 inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
Index: lib/Basic/SourceLocation.cpp
===================================================================
--- lib/Basic/SourceLocation.cpp
+++ lib/Basic/SourceLocation.cpp
@@ -61,6 +61,32 @@
   OS << '>';
 }
 
+std::string SourceLocation::printTreeToString(const SourceManager &SM,
+                                              unsigned Indent) const {
+  std::string IndentStr(Indent * 4 + 1, ' ');
+  std::string S;
+  llvm::raw_string_ostream OS(S);
+  OS << "(";
+  if (!isValid() || !isMacroID()) {
+    OS << printToString(SM);
+  } else {
+    SourceLocation SpellingLoc = SM.getImmediateSpellingLoc(*this);
+    std::pair<SourceLocation, SourceLocation> ExpansionLoc =
+        SM.getImmediateExpansionRange(*this);
+    OS << "SP=" << SpellingLoc.printTreeToString(SM, Indent + 1) << ",\n"
+       << IndentStr;
+    if (ExpansionLoc.first != ExpansionLoc.second) {
+      OS << "ES=" << ExpansionLoc.first.printTreeToString(SM, Indent + 1)
+         << ",\n" << IndentStr
+         << "EE=" << ExpansionLoc.second.printTreeToString(SM, Indent + 1);
+    } else {
+      OS << "EX=" << ExpansionLoc.first.printTreeToString(SM, Indent + 1);
+    }
+  }
+  OS << ")";
+  return OS.str();
+}
+
 std::string SourceLocation::printToString(const SourceManager &SM) const {
   std::string S;
   llvm::raw_string_ostream OS(S);
Index: include/clang/Basic/SourceLocation.h
===================================================================
--- include/clang/Basic/SourceLocation.h
+++ include/clang/Basic/SourceLocation.h
@@ -174,6 +174,8 @@
   void print(raw_ostream &OS, const SourceManager &SM) const;
   LLVM_ATTRIBUTE_USED std::string printToString(const SourceManager &SM) const;
   void dump(const SourceManager &SM) const;
+  LLVM_ATTRIBUTE_USED std::string printTreeToString(const SourceManager &SM,
+                                                    unsigned Indent = 0) const;
 };
 
 inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
Index: lib/Basic/SourceLocation.cpp
===================================================================
--- lib/Basic/SourceLocation.cpp
+++ lib/Basic/SourceLocation.cpp
@@ -61,6 +61,32 @@
   OS << '>';
 }
 
+std::string SourceLocation::printTreeToString(const SourceManager &SM,
+                                              unsigned Indent) const {
+  std::string IndentStr(Indent * 4 + 1, ' ');
+  std::string S;
+  llvm::raw_string_ostream OS(S);
+  OS << "(";
+  if (!isValid() || !isMacroID()) {
+    OS << printToString(SM);
+  } else {
+    SourceLocation SpellingLoc = SM.getImmediateSpellingLoc(*this);
+    std::pair<SourceLocation, SourceLocation> ExpansionLoc =
+        SM.getImmediateExpansionRange(*this);
+    OS << "SP=" << SpellingLoc.printTreeToString(SM, Indent + 1) << ",\n"
+       << IndentStr;
+    if (ExpansionLoc.first != ExpansionLoc.second) {
+      OS << "ES=" << ExpansionLoc.first.printTreeToString(SM, Indent + 1)
+         << ",\n" << IndentStr
+         << "EE=" << ExpansionLoc.second.printTreeToString(SM, Indent + 1);
+    } else {
+      OS << "EX=" << ExpansionLoc.first.printTreeToString(SM, Indent + 1);
+    }
+  }
+  OS << ")";
+  return OS.str();
+}
+
 std::string SourceLocation::printToString(const SourceManager &SM) const {
   std::string S;
   llvm::raw_string_ostream OS(S);
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to