summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2013-11-06 00:27:12 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2013-11-06 00:27:12 +0000
commit00841f5d6273d9088cfe308bacf6f5a80470c829 (patch)
tree973c941b384a204383742b52cfcc563b726a5c50
parent3f0e0402d8cd40b428f975f1a3607dbbd94d2ca6 (diff)
downloadclang-00841f5d6273d9088cfe308bacf6f5a80470c829.tar.gz
clang-00841f5d6273d9088cfe308bacf6f5a80470c829.tar.bz2
clang-00841f5d6273d9088cfe308bacf6f5a80470c829.tar.xz
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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@194113 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/ASTTypeTraits.h19
-rw-r--r--lib/AST/ASTTypeTraits.cpp47
-rw-r--r--unittests/AST/ASTTypeTraitsTest.cpp52
-rw-r--r--unittests/AST/MatchVerifier.h68
4 files changed, 186 insertions, 0 deletions
diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h
index e0b67c4591..087ad56090 100644
--- a/include/clang/AST/ASTTypeTraits.h
+++ b/include/clang/AST/ASTTypeTraits.h
@@ -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.
///
diff --git a/lib/AST/ASTTypeTraits.cpp b/lib/AST/ASTTypeTraits.cpp
index 7cf07593a7..ae47ea9888 100644
--- a/lib/AST/ASTTypeTraits.cpp
+++ b/lib/AST/ASTTypeTraits.cpp
@@ -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 Base, NodeKindId Derived) {
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
diff --git a/unittests/AST/ASTTypeTraitsTest.cpp b/unittests/AST/ASTTypeTraitsTest.cpp
index 5e3abe25d1..dd73b52206 100644
--- a/unittests/AST/ASTTypeTraitsTest.cpp
+++ b/unittests/AST/ASTTypeTraitsTest.cpp
@@ -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
diff --git a/unittests/AST/MatchVerifier.h b/unittests/AST/MatchVerifier.h
index bc8bf9ea34..5a29cde227 100644
--- a/unittests/AST/MatchVerifier.h
+++ b/unittests/AST/MatchVerifier.h
@@ -125,6 +125,20 @@ void MatchVerifier<NodeType>::run(const MatchFinder::MatchResult &Result) {
}
}
+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