RecursiveASTVisitorTestPostOrderVisitor.cpp 3.6 KB

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