diff options
author | Vassil Vassilev <v.g.vassilev@gmail.com> | 2016-07-08 08:33:56 +0000 |
---|---|---|
committer | Vassil Vassilev <v.g.vassilev@gmail.com> | 2016-07-08 08:33:56 +0000 |
commit | f339de408790ba9a321810b9486538e4f04459ed (patch) | |
tree | 5f670f9f6b62bb86bd8a93574ed029a017445064 /unittests/AST | |
parent | 37858de4a1d12dc43e0628a72ef2c3f815eb5c33 (diff) | |
download | clang-f339de408790ba9a321810b9486538e4f04459ed.tar.gz |
Recommit r274348 and r274349. The Windows failures should be fixed.
Original commit message:
"Add postorder traversal support to the RecursiveASTVisitor.
This feature needs to be explicitly enabled by overriding shouldTraversePostOrder()
as it has performance drawbacks for the iterative Stmt-traversal.
Patch by Raphael Isemann!
Reviewed by Richard Smith and Benjamin Kramer."
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@274830 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests/AST')
-rw-r--r-- | unittests/AST/CMakeLists.txt | 1 | ||||
-rw-r--r-- | unittests/AST/PostOrderASTVisitor.cpp | 123 |
2 files changed, 124 insertions, 0 deletions
diff --git a/unittests/AST/CMakeLists.txt b/unittests/AST/CMakeLists.txt index 7e9f320e94..a7008f3e7e 100644 --- a/unittests/AST/CMakeLists.txt +++ b/unittests/AST/CMakeLists.txt @@ -14,6 +14,7 @@ add_clang_unittest(ASTTests EvaluateAsRValueTest.cpp ExternalASTSourceTest.cpp NamedDeclPrinterTest.cpp + PostOrderASTVisitor.cpp SourceLocationTest.cpp StmtPrinterTest.cpp ) diff --git a/unittests/AST/PostOrderASTVisitor.cpp b/unittests/AST/PostOrderASTVisitor.cpp new file mode 100644 index 0000000000..012f63a48a --- /dev/null +++ b/unittests/AST/PostOrderASTVisitor.cpp @@ -0,0 +1,123 @@ +//===- unittests/AST/PostOrderASTVisitor.cpp - Declaration printer tests --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains tests for the post-order traversing functionality +// of RecursiveASTVisitor. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Tooling/Tooling.h" +#include "gtest/gtest.h" + +using namespace clang; + +namespace { + + class RecordingVisitor + : public RecursiveASTVisitor<RecordingVisitor> { + + bool VisitPostOrder; + public: + explicit RecordingVisitor(bool VisitPostOrder) + : VisitPostOrder(VisitPostOrder) { + } + + // List of visited nodes during traversal. + std::vector<std::string> VisitedNodes; + + bool shouldTraversePostOrder() const { return VisitPostOrder; } + + bool VisitBinaryOperator(BinaryOperator *Op) { + VisitedNodes.push_back(Op->getOpcodeStr()); + return true; + } + + bool VisitIntegerLiteral(IntegerLiteral *Lit) { + VisitedNodes.push_back(Lit->getValue().toString(10, false)); + return true; + } + + bool VisitVarDecl(VarDecl* D) { + VisitedNodes.push_back(D->getNameAsString()); + return true; + } + + bool VisitCXXMethodDecl(CXXMethodDecl *D) { + VisitedNodes.push_back(D->getQualifiedNameAsString()); + return true; + } + + bool VisitReturnStmt(ReturnStmt *S) { + VisitedNodes.push_back("return"); + return true; + } + + bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) { + VisitedNodes.push_back(Declaration->getQualifiedNameAsString()); + return true; + } + + bool VisitTemplateTypeParmType(TemplateTypeParmType *T) { + VisitedNodes.push_back(T->getDecl()->getQualifiedNameAsString()); + return true; + } + }; + +} + +TEST(RecursiveASTVisitor, PostOrderTraversal) { + auto ASTUnit = tooling::buildASTFromCode( + "class A {" + " class B {" + " int foo() { while(4) { int i = 9; } return (1 + 3) + 2; }" + " };" + "};" + ); + auto TU = ASTUnit->getASTContext().getTranslationUnitDecl(); + // We traverse the translation unit and store all + // visited nodes. + RecordingVisitor Visitor(true); + Visitor.TraverseTranslationUnitDecl(TU); + + std::vector<std::string> expected = { + "4", "9", "i", "1", "3", "+", "2", "+", "return", "A::B::foo", "A::B", "A" + }; + // Compare the list of actually visited nodes + // with the expected list of visited nodes. + ASSERT_EQ(expected.size(), Visitor.VisitedNodes.size()); + for (std::size_t I = 0; I < expected.size(); I++) { + ASSERT_EQ(expected[I], Visitor.VisitedNodes[I]); + } +} + +TEST(RecursiveASTVisitor, NoPostOrderTraversal) { + auto ASTUnit = tooling::buildASTFromCode( + "class A {" + " class B {" + " int foo() { return 1 + 2; }" + " };" + "};" + ); + auto TU = ASTUnit->getASTContext().getTranslationUnitDecl(); + // We traverse the translation unit and store all + // visited nodes. + RecordingVisitor Visitor(false); + Visitor.TraverseTranslationUnitDecl(TU); + + std::vector<std::string> expected = { + "A", "A::B", "A::B::foo", "return", "+", "1", "2" + }; + // Compare the list of actually visited nodes + // with the expected list of visited nodes. + ASSERT_EQ(expected.size(), Visitor.VisitedNodes.size()); + for (std::size_t I = 0; I < expected.size(); I++) { + ASSERT_EQ(expected[I], Visitor.VisitedNodes[I]); + } +} |