Clang Project

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