r194113 - Introduce DynTypedNode::print, dump and getSourceRange.

Peter Collingbourne peter at pcc.me.uk
Tue Nov 5 16:27:12 PST 2013


Author: pcc
Date: Tue Nov  5 18:27:12 2013
New Revision: 194113

URL: http://llvm.org/viewvc/llvm-project?rev=194113&view=rev
Log:
Introduce DynTypedNode::print, dump and getSourceRange.

These functions can generally be applied to multiple kinds of AST node,
so it makes sense to add them to DynTypedNode.

Differential Revision: http://llvm-reviews.chandlerc.com/D2096

Modified:
    cfe/trunk/include/clang/AST/ASTTypeTraits.h
    cfe/trunk/lib/AST/ASTTypeTraits.cpp
    cfe/trunk/unittests/AST/ASTTypeTraitsTest.cpp
    cfe/trunk/unittests/AST/MatchVerifier.h

Modified: cfe/trunk/include/clang/AST/ASTTypeTraits.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTTypeTraits.h?rev=194113&r1=194112&r2=194113&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTTypeTraits.h (original)
+++ cfe/trunk/include/clang/AST/ASTTypeTraits.h Tue Nov  5 18:27:12 2013
@@ -25,7 +25,16 @@
 #include "clang/Basic/LLVM.h"
 #include "llvm/Support/AlignOf.h"
 
+namespace llvm {
+
+class raw_ostream;
+
+}
+
 namespace clang {
+
+struct PrintingPolicy;
+
 namespace ast_type_traits {
 
 /// \brief Kind identifier.
@@ -168,6 +177,16 @@ public:
   /// method returns NULL.
   const void *getMemoizationData() const;
 
+  /// \brief Prints the node to the given output stream.
+  void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const;
+
+  /// \brief Dumps the node to the given output stream.
+  void dump(llvm::raw_ostream &OS, SourceManager &SM) const;
+
+  /// \brief For nodes which represent textual entities in the source code,
+  /// return their SourceRange.  For all other nodes, return SourceRange().
+  SourceRange getSourceRange() const;
+
   /// @{
   /// \brief Imposes an order on \c DynTypedNode.
   ///

Modified: cfe/trunk/lib/AST/ASTTypeTraits.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTTypeTraits.cpp?rev=194113&r1=194112&r2=194113&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTTypeTraits.cpp (original)
+++ cfe/trunk/lib/AST/ASTTypeTraits.cpp Tue Nov  5 18:27:12 2013
@@ -14,6 +14,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
 
 namespace clang {
 namespace ast_type_traits {
@@ -54,5 +56,50 @@ bool ASTNodeKind::isBaseOf(NodeKindId Ba
 
 StringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; }
 
+void DynTypedNode::print(llvm::raw_ostream &OS,
+                         const PrintingPolicy &PP) const {
+  if (const TemplateArgument *TA = get<TemplateArgument>())
+    TA->print(PP, OS);
+  else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>())
+    NNS->print(OS, PP);
+  else if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>())
+    NNSL->getNestedNameSpecifier()->print(OS, PP);
+  else if (const QualType *QT = get<QualType>())
+    QT->print(OS, PP);
+  else if (const TypeLoc *TL = get<TypeLoc>())
+    TL->getType().print(OS, PP);
+  else if (const Decl *D = get<Decl>())
+    D->print(OS, PP);
+  else if (const Stmt *S = get<Stmt>())
+    S->printPretty(OS, 0, PP);
+  else if (const Type *T = get<Type>())
+    QualType(T, 0).print(OS, PP);
+  else
+    OS << "Unable to print values of type " << NodeKind.asStringRef() << "\n";
+}
+
+void DynTypedNode::dump(llvm::raw_ostream &OS, SourceManager &SM) const {
+  if (const Decl *D = get<Decl>())
+    D->dump(OS);
+  else if (const Stmt *S = get<Stmt>())
+    S->dump(OS, SM);
+  else
+    OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n";
+}
+
+SourceRange DynTypedNode::getSourceRange() const {
+  if (const CXXCtorInitializer *CCI = get<CXXCtorInitializer>())
+    return CCI->getSourceRange();
+  if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>())
+    return NNSL->getSourceRange();
+  if (const TypeLoc *TL = get<TypeLoc>())
+    return TL->getSourceRange();
+  if (const Decl *D = get<Decl>())
+    return D->getSourceRange();
+  if (const Stmt *S = get<Stmt>())
+    return S->getSourceRange();
+  return SourceRange();
+}
+
 } // end namespace ast_type_traits
 } // end namespace clang

Modified: cfe/trunk/unittests/AST/ASTTypeTraitsTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTTypeTraitsTest.cpp?rev=194113&r1=194112&r2=194113&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/ASTTypeTraitsTest.cpp (original)
+++ cfe/trunk/unittests/AST/ASTTypeTraitsTest.cpp Tue Nov  5 18:27:12 2013
@@ -10,6 +10,9 @@
 
 #include "clang/AST/ASTTypeTraits.h"
 #include "gtest/gtest.h"
+#include "MatchVerifier.h"
+
+using namespace clang::ast_matchers;
 
 namespace clang {
 namespace ast_type_traits {
@@ -58,5 +61,54 @@ TEST(ASTNodeKind, Name) {
   EXPECT_EQ("<None>", ASTNodeKind().asStringRef());
 }
 
+TEST(DynTypedNode, DeclSourceRange) {
+  RangeVerifier<DynTypedNode> Verifier;
+  Verifier.expectRange(1, 1, 1, 11);
+  EXPECT_TRUE(Verifier.match("void f() {}", decl()));
+}
+
+TEST(DynTypedNode, StmtSourceRange) {
+  RangeVerifier<DynTypedNode> Verifier;
+  Verifier.expectRange(1, 10, 1, 11);
+  EXPECT_TRUE(Verifier.match("void f() {}", stmt()));
+}
+
+TEST(DynTypedNode, TypeLocSourceRange) {
+  RangeVerifier<DynTypedNode> Verifier;
+  Verifier.expectRange(1, 1, 1, 8);
+  EXPECT_TRUE(Verifier.match("void f() {}", typeLoc(loc(functionType()))));
+}
+
+TEST(DynTypedNode, NNSLocSourceRange) {
+  RangeVerifier<DynTypedNode> Verifier;
+  Verifier.expectRange(1, 33, 1, 34);
+  EXPECT_TRUE(Verifier.match("namespace N { typedef void T; } N::T f() {}",
+                             nestedNameSpecifierLoc()));
+}
+
+TEST(DynTypedNode, DeclDump) {
+  DumpVerifier Verifier;
+  Verifier.expectSubstring("FunctionDecl");
+  EXPECT_TRUE(Verifier.match("void f() {}", functionDecl()));
+}
+
+TEST(DynTypedNode, StmtDump) {
+  DumpVerifier Verifier;
+  Verifier.expectSubstring("CompoundStmt");
+  EXPECT_TRUE(Verifier.match("void f() {}", stmt()));
+}
+
+TEST(DynTypedNode, DeclPrint) {
+  PrintVerifier Verifier;
+  Verifier.expectString("void f() {\n}\n\n");
+  EXPECT_TRUE(Verifier.match("void f() {}", functionDecl()));
+}
+
+TEST(DynTypedNode, StmtPrint) {
+  PrintVerifier Verifier;
+  Verifier.expectString("{\n}\n");
+  EXPECT_TRUE(Verifier.match("void f() {}", stmt()));
+}
+
 }  // namespace ast_type_traits
 }  // namespace clang

Modified: cfe/trunk/unittests/AST/MatchVerifier.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/MatchVerifier.h?rev=194113&r1=194112&r2=194113&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/MatchVerifier.h (original)
+++ cfe/trunk/unittests/AST/MatchVerifier.h Tue Nov  5 18:27:12 2013
@@ -125,6 +125,20 @@ void MatchVerifier<NodeType>::run(const
   }
 }
 
+template <>
+inline void MatchVerifier<ast_type_traits::DynTypedNode>::run(
+    const MatchFinder::MatchResult &Result) {
+  BoundNodes::IDToNodeMap M = Result.Nodes.getMap();
+  BoundNodes::IDToNodeMap::const_iterator I = M.find("");
+  if (I == M.end()) {
+    setFailure("Node was not bound");
+  } else {
+    // Callback has been called, default to success.
+    setSuccess();
+    verify(Result, I->second);
+  }
+}
+
 /// \brief Verify whether a node has the correct source location.
 ///
 /// By default, Node.getSourceLocation() is checked. This can be changed
@@ -207,5 +221,59 @@ private:
   unsigned ExpectBeginLine, ExpectBeginColumn, ExpectEndLine, ExpectEndColumn;
 };
 
+/// \brief Verify whether a node's dump contains a given substring.
+class DumpVerifier : public MatchVerifier<ast_type_traits::DynTypedNode> {
+public:
+  void expectSubstring(const std::string &Str) {
+    ExpectSubstring = Str;
+  }
+
+protected:
+  void verify(const MatchFinder::MatchResult &Result,
+              const ast_type_traits::DynTypedNode &Node) {
+    std::string DumpStr;
+    llvm::raw_string_ostream Dump(DumpStr);
+    Node.dump(Dump, *Result.SourceManager);
+
+    if (Dump.str().find(ExpectSubstring) == std::string::npos) {
+      std::string MsgStr;
+      llvm::raw_string_ostream Msg(MsgStr);
+      Msg << "Expected dump substring <" << ExpectSubstring << ">, found <"
+          << Dump.str() << '>';
+      this->setFailure(Msg.str());
+    }
+  }
+
+private:
+  std::string ExpectSubstring;
+};
+
+/// \brief Verify whether a node's pretty print matches a given string.
+class PrintVerifier : public MatchVerifier<ast_type_traits::DynTypedNode> {
+public:
+  void expectString(const std::string &Str) {
+    ExpectString = Str;
+  }
+
+protected:
+  void verify(const MatchFinder::MatchResult &Result,
+              const ast_type_traits::DynTypedNode &Node) {
+    std::string PrintStr;
+    llvm::raw_string_ostream Print(PrintStr);
+    Node.print(Print, Result.Context->getPrintingPolicy());
+
+    if (Print.str() != ExpectString) {
+      std::string MsgStr;
+      llvm::raw_string_ostream Msg(MsgStr);
+      Msg << "Expected pretty print <" << ExpectString << ">, found <"
+          << Print.str() << '>';
+      this->setFailure(Msg.str());
+    }
+  }
+
+private:
+  std::string ExpectString;
+};
+
 } // end namespace ast_matchers
 } // end namespace clang





More information about the cfe-commits mailing list