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