MontyKutyi updated this revision to Diff 108241. MontyKutyi added a comment.
Added test for the fix. https://reviews.llvm.org/D34030 Files: include/clang/AST/RecursiveASTVisitor.h unittests/AST/PostOrderASTVisitor.cpp
Index: unittests/AST/PostOrderASTVisitor.cpp =================================================================== --- unittests/AST/PostOrderASTVisitor.cpp +++ unittests/AST/PostOrderASTVisitor.cpp @@ -15,6 +15,7 @@ #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Tooling/Tooling.h" #include "gtest/gtest.h" +#include <algorithm> using namespace clang; @@ -75,7 +76,47 @@ } }; -} + // Serializes the AST. It is not complete! It only serializes the Statement + // and the Declaration nodes. + class ASTSerializerVisitor + : public RecursiveASTVisitor<ASTSerializerVisitor> + { + private: + std::vector<void*>& visitedNodes; + const bool visitPostOrder; + public: + + ASTSerializerVisitor(bool visitPostOrder, std::vector<void*>& visitedNodes) + : visitedNodes (visitedNodes) + , visitPostOrder (visitPostOrder) + {} + + bool shouldTraversePostOrder() const + { + return visitPostOrder; + } + + bool VisitStmt(Stmt *s) + { + visitedNodes.push_back(s); + return true; + } + + bool PostVisitStmt(Stmt *s) + { + if (visitPostOrder) + visitedNodes.push_back(s); + return true; + } + + bool VisitDecl(Decl *d) + { + visitedNodes.push_back(d); + return true; + } + }; + +} // anonymous namespace TEST(RecursiveASTVisitor, PostOrderTraversal) { auto ASTUnit = tooling::buildASTFromCode( @@ -126,3 +167,32 @@ ASSERT_EQ(expected[I], Visitor.VisitedNodes[I]); } } + +TEST(RecursiveASTVisitor, PrePostComparisonTest) { + auto ASTUnit = tooling::buildASTFromCode( + "template <typename> class X {};" + "template class X<int>;" + ); + + auto TU = ASTUnit->getASTContext().getTranslationUnitDecl(); + + std::vector<void*> preorderNodeList, postorderNodeList; + + ASTSerializerVisitor PreVisitor(false, preorderNodeList); + PreVisitor.TraverseTranslationUnitDecl(TU); + + ASTSerializerVisitor PostVisitor(true, postorderNodeList); + PostVisitor.TraverseTranslationUnitDecl(TU); + + // The number of visited nodes must be independent of the ordering mode. + ASSERT_EQ(preorderNodeList.size(), postorderNodeList.size()); + + std::sort(preorderNodeList.begin(), preorderNodeList.end()); + std::sort(postorderNodeList.begin(), postorderNodeList.end()); + + // Both traversal must visit the same nodes. + ASSERT_EQ(std::mismatch(preorderNodeList.begin(), + preorderNodeList.end(), + postorderNodeList.begin()).first, + preorderNodeList.end()); +} Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -1802,11 +1802,10 @@ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); \ if (!getDerived().shouldVisitTemplateInstantiations() && \ D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) \ - /* Returning from here skips traversing the \ - declaration context of the *TemplateSpecializationDecl \ - (embedded in the DEF_TRAVERSE_DECL() macro) \ - which contains the instantiated members of the template. */ \ - return true; \ + /* Skip traversing the declaration context of the \ + *TemplateSpecializationDecl (embedded in the DEF_TRAVERSE_DECL() \ + macro) which contains the instantiated members of the template. */ \ + ShouldVisitChildren = false; \ }) DEF_TRAVERSE_TMPL_SPEC_DECL(Class)
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits