• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 using namespace clang;
20 
21 namespace {
22 
23   class RecordingVisitor
24     : public RecursiveASTVisitor<RecordingVisitor> {
25 
26     bool VisitPostOrder;
27   public:
RecordingVisitor(bool VisitPostOrder)28     explicit RecordingVisitor(bool VisitPostOrder)
29       : VisitPostOrder(VisitPostOrder) {
30     }
31 
32     // List of visited nodes during traversal.
33     std::vector<std::string> VisitedNodes;
34 
shouldTraversePostOrder() const35     bool shouldTraversePostOrder() const { return VisitPostOrder; }
36 
VisitBinaryOperator(BinaryOperator * Op)37     bool VisitBinaryOperator(BinaryOperator *Op) {
38       VisitedNodes.push_back(Op->getOpcodeStr());
39       return true;
40     }
41 
VisitIntegerLiteral(IntegerLiteral * Lit)42     bool VisitIntegerLiteral(IntegerLiteral *Lit) {
43       VisitedNodes.push_back(Lit->getValue().toString(10, false));
44       return true;
45     }
46 
VisitVarDecl(VarDecl * D)47     bool VisitVarDecl(VarDecl* D) {
48       VisitedNodes.push_back(D->getNameAsString());
49       return true;
50     }
51 
VisitCXXMethodDecl(CXXMethodDecl * D)52     bool VisitCXXMethodDecl(CXXMethodDecl *D) {
53       VisitedNodes.push_back(D->getQualifiedNameAsString());
54       return true;
55     }
56 
VisitReturnStmt(ReturnStmt * S)57     bool VisitReturnStmt(ReturnStmt *S) {
58       VisitedNodes.push_back("return");
59       return true;
60     }
61 
VisitCXXRecordDecl(CXXRecordDecl * Declaration)62     bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {
63       VisitedNodes.push_back(Declaration->getQualifiedNameAsString());
64       return true;
65     }
66 
VisitTemplateTypeParmType(TemplateTypeParmType * T)67     bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
68       VisitedNodes.push_back(T->getDecl()->getQualifiedNameAsString());
69       return true;
70     }
71   };
72 
73 }
74 
TEST(RecursiveASTVisitor,PostOrderTraversal)75 TEST(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 
TEST(RecursiveASTVisitor,NoPostOrderTraversal)100 TEST(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