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