blob: 2e7b398c3d1fb701d3b5e8d94ac6d2e466de6793 [file] [log] [blame]
Raphael Isemannbe4fbca2018-01-24 09:40:16 +00001//===- 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
17using namespace clang;
18
19namespace {
20
21class RecordingVisitor : public TestVisitor<RecordingVisitor> {
22
23 bool VisitPostOrder;
24
25public:
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
77TEST(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
99TEST(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}