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