114 lines · 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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains tests for the post-order traversing functionality10// of RecursiveASTVisitor.11//12//===----------------------------------------------------------------------===//13 14#include "CRTPTestVisitor.h"15 16using namespace clang;17 18namespace {19class RecordingVisitor : public CRTPTestVisitor<RecordingVisitor> {20 bool VisitPostOrder;21 22public: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} // namespace73 74TEST(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 of89 // 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 96TEST(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 of108 // 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