summaryrefslogtreecommitdiff
path: root/unittests/AST
diff options
context:
space:
mode:
authorVassil Vassilev <v.g.vassilev@gmail.com>2016-07-08 08:33:56 +0000
committerVassil Vassilev <v.g.vassilev@gmail.com>2016-07-08 08:33:56 +0000
commitf339de408790ba9a321810b9486538e4f04459ed (patch)
tree5f670f9f6b62bb86bd8a93574ed029a017445064 /unittests/AST
parent37858de4a1d12dc43e0628a72ef2c3f815eb5c33 (diff)
downloadclang-f339de408790ba9a321810b9486538e4f04459ed.tar.gz
Recommit r274348 and r274349. The Windows failures should be fixed.
Original commit message: "Add postorder traversal support to the RecursiveASTVisitor. This feature needs to be explicitly enabled by overriding shouldTraversePostOrder() as it has performance drawbacks for the iterative Stmt-traversal. Patch by Raphael Isemann! Reviewed by Richard Smith and Benjamin Kramer." git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@274830 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests/AST')
-rw-r--r--unittests/AST/CMakeLists.txt1
-rw-r--r--unittests/AST/PostOrderASTVisitor.cpp123
2 files changed, 124 insertions, 0 deletions
diff --git a/unittests/AST/CMakeLists.txt b/unittests/AST/CMakeLists.txt
index 7e9f320e94..a7008f3e7e 100644
--- a/unittests/AST/CMakeLists.txt
+++ b/unittests/AST/CMakeLists.txt
@@ -14,6 +14,7 @@ add_clang_unittest(ASTTests
EvaluateAsRValueTest.cpp
ExternalASTSourceTest.cpp
NamedDeclPrinterTest.cpp
+ PostOrderASTVisitor.cpp
SourceLocationTest.cpp
StmtPrinterTest.cpp
)
diff --git a/unittests/AST/PostOrderASTVisitor.cpp b/unittests/AST/PostOrderASTVisitor.cpp
new file mode 100644
index 0000000000..012f63a48a
--- /dev/null
+++ b/unittests/AST/PostOrderASTVisitor.cpp
@@ -0,0 +1,123 @@
+//===- unittests/AST/PostOrderASTVisitor.cpp - Declaration printer tests --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains tests for the post-order traversing functionality
+// of RecursiveASTVisitor.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+
+namespace {
+
+ class RecordingVisitor
+ : public RecursiveASTVisitor<RecordingVisitor> {
+
+ bool VisitPostOrder;
+ public:
+ explicit RecordingVisitor(bool VisitPostOrder)
+ : VisitPostOrder(VisitPostOrder) {
+ }
+
+ // List of visited nodes during traversal.
+ std::vector<std::string> VisitedNodes;
+
+ bool shouldTraversePostOrder() const { return VisitPostOrder; }
+
+ bool VisitBinaryOperator(BinaryOperator *Op) {
+ VisitedNodes.push_back(Op->getOpcodeStr());
+ return true;
+ }
+
+ bool VisitIntegerLiteral(IntegerLiteral *Lit) {
+ VisitedNodes.push_back(Lit->getValue().toString(10, false));
+ return true;
+ }
+
+ bool VisitVarDecl(VarDecl* D) {
+ VisitedNodes.push_back(D->getNameAsString());
+ return true;
+ }
+
+ bool VisitCXXMethodDecl(CXXMethodDecl *D) {
+ VisitedNodes.push_back(D->getQualifiedNameAsString());
+ return true;
+ }
+
+ bool VisitReturnStmt(ReturnStmt *S) {
+ VisitedNodes.push_back("return");
+ return true;
+ }
+
+ bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {
+ VisitedNodes.push_back(Declaration->getQualifiedNameAsString());
+ return true;
+ }
+
+ bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
+ VisitedNodes.push_back(T->getDecl()->getQualifiedNameAsString());
+ return true;
+ }
+ };
+
+}
+
+TEST(RecursiveASTVisitor, PostOrderTraversal) {
+ auto ASTUnit = tooling::buildASTFromCode(
+ "class A {"
+ " class B {"
+ " int foo() { while(4) { int i = 9; } return (1 + 3) + 2; }"
+ " };"
+ "};"
+ );
+ auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
+ // We traverse the translation unit and store all
+ // visited nodes.
+ RecordingVisitor Visitor(true);
+ Visitor.TraverseTranslationUnitDecl(TU);
+
+ std::vector<std::string> expected = {
+ "4", "9", "i", "1", "3", "+", "2", "+", "return", "A::B::foo", "A::B", "A"
+ };
+ // Compare the list of actually visited nodes
+ // with the expected list of visited nodes.
+ ASSERT_EQ(expected.size(), Visitor.VisitedNodes.size());
+ for (std::size_t I = 0; I < expected.size(); I++) {
+ ASSERT_EQ(expected[I], Visitor.VisitedNodes[I]);
+ }
+}
+
+TEST(RecursiveASTVisitor, NoPostOrderTraversal) {
+ auto ASTUnit = tooling::buildASTFromCode(
+ "class A {"
+ " class B {"
+ " int foo() { return 1 + 2; }"
+ " };"
+ "};"
+ );
+ auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
+ // We traverse the translation unit and store all
+ // visited nodes.
+ RecordingVisitor Visitor(false);
+ Visitor.TraverseTranslationUnitDecl(TU);
+
+ std::vector<std::string> expected = {
+ "A", "A::B", "A::B::foo", "return", "+", "1", "2"
+ };
+ // Compare the list of actually visited nodes
+ // with the expected list of visited nodes.
+ ASSERT_EQ(expected.size(), Visitor.VisitedNodes.size());
+ for (std::size_t I = 0; I < expected.size(); I++) {
+ ASSERT_EQ(expected[I], Visitor.VisitedNodes[I]);
+ }
+}