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