1 //===- unittests/Tooling/RecursiveASTVisitorPostOrderASTVisitor.cpp -------===// 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 contains tests for the post-order traversing functionality 11 // of RecursiveASTVisitor. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "TestVisitor.h" 16 17 using namespace clang; 18 19 namespace { 20 21 class RecordingVisitor : public TestVisitor<RecordingVisitor> { 22 23 bool VisitPostOrder; 24 25 public: 26 explicit RecordingVisitor(bool VisitPostOrder) 27 : VisitPostOrder(VisitPostOrder) {} 28 29 // List of visited nodes during traversal. 30 std::vector<std::string> VisitedNodes; 31 32 bool shouldTraversePostOrder() const { return VisitPostOrder; } 33 34 bool VisitUnaryOperator(UnaryOperator *Op) { 35 VisitedNodes.push_back(Op->getOpcodeStr(Op->getOpcode())); 36 return true; 37 } 38 39 bool VisitBinaryOperator(BinaryOperator *Op) { 40 VisitedNodes.push_back(Op->getOpcodeStr()); 41 return true; 42 } 43 44 bool VisitIntegerLiteral(IntegerLiteral *Lit) { 45 VisitedNodes.push_back(Lit->getValue().toString(10, false)); 46 return true; 47 } 48 49 bool VisitVarDecl(VarDecl *D) { 50 VisitedNodes.push_back(D->getNameAsString()); 51 return true; 52 } 53 54 bool VisitCXXMethodDecl(CXXMethodDecl *D) { 55 VisitedNodes.push_back(D->getQualifiedNameAsString()); 56 return true; 57 } 58 59 bool VisitReturnStmt(ReturnStmt *S) { 60 VisitedNodes.push_back("return"); 61 return true; 62 } 63 64 bool VisitCXXRecordDecl(CXXRecordDecl *D) { 65 if (!D->isImplicit()) 66 VisitedNodes.push_back(D->getQualifiedNameAsString()); 67 return true; 68 } 69 70 bool VisitTemplateTypeParmType(TemplateTypeParmType *T) { 71 VisitedNodes.push_back(T->getDecl()->getQualifiedNameAsString()); 72 return true; 73 } 74 }; 75 } // namespace 76 77 TEST(RecursiveASTVisitor, PostOrderTraversal) { 78 // We traverse the translation unit and store all visited nodes. 79 RecordingVisitor Visitor(true); 80 Visitor.runOver("class A {\n" 81 " class B {\n" 82 " int foo() {\n" 83 " while(4) { int i = 9; int j = -5; }\n" 84 " return (1 + 3) + 2; }\n" 85 " };\n" 86 "};\n"); 87 88 std::vector<std::string> expected = {"4", "9", "i", "5", "-", 89 "j", "1", "3", "+", "2", 90 "+", "return", "A::B::foo", "A::B", "A"}; 91 // Compare the list of actually visited nodes with the expected list of 92 // visited nodes. 93 ASSERT_EQ(expected.size(), Visitor.VisitedNodes.size()); 94 for (std::size_t I = 0; I < expected.size(); I++) { 95 ASSERT_EQ(expected[I], Visitor.VisitedNodes[I]); 96 } 97 } 98 99 TEST(RecursiveASTVisitor, NoPostOrderTraversal) { 100 // We traverse the translation unit and store all visited nodes. 101 RecordingVisitor Visitor(false); 102 Visitor.runOver("class A {\n" 103 " class B {\n" 104 " int foo() { return 1 + 2; }\n" 105 " };\n" 106 "};\n"); 107 108 std::vector<std::string> expected = {"A", "A::B", "A::B::foo", "return", 109 "+", "1", "2"}; 110 // Compare the list of actually visited nodes with the expected list of 111 // visited nodes. 112 ASSERT_EQ(expected.size(), Visitor.VisitedNodes.size()); 113 for (std::size_t I = 0; I < expected.size(); I++) { 114 ASSERT_EQ(expected[I], Visitor.VisitedNodes[I]); 115 } 116 } 117