diff options
| author | Stephen Kelly <steveire@gmail.com> | 2019-05-04 16:51:58 +0100 |
|---|---|---|
| committer | Stephen Kelly <steveire@gmail.com> | 2019-12-18 22:33:23 +0000 |
| commit | 98e8f774eb6ca8946b3104b4e82beefd41ca2c35 (patch) | |
| tree | a8452417e927406cee681323fa71bae48cd5ef76 /clang/unittests | |
| parent | 84fd2bedf4096e78b892165138051b8563169fe3 (diff) | |
| download | bcm5719-llvm-98e8f774eb6ca8946b3104b4e82beefd41ca2c35.tar.gz bcm5719-llvm-98e8f774eb6ca8946b3104b4e82beefd41ca2c35.zip | |
Add method to ignore invisible AST nodes
Reviewers: aaron.ballman
Subscribers: mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D70613
Diffstat (limited to 'clang/unittests')
| -rw-r--r-- | clang/unittests/AST/ASTTraverserTest.cpp | 235 | ||||
| -rw-r--r-- | clang/unittests/AST/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp | 143 |
3 files changed, 379 insertions, 0 deletions
diff --git a/clang/unittests/AST/ASTTraverserTest.cpp b/clang/unittests/AST/ASTTraverserTest.cpp index 6debdf10eda..c995f55d3c8 100644 --- a/clang/unittests/AST/ASTTraverserTest.cpp +++ b/clang/unittests/AST/ASTTraverserTest.cpp @@ -95,6 +95,21 @@ template <typename... NodeType> std::string dumpASTString(NodeType &&... N) { return OS.str(); } +template <typename... NodeType> +std::string dumpASTString(ast_type_traits::TraversalKind TK, NodeType &&... N) { + std::string Buffer; + llvm::raw_string_ostream OS(Buffer); + + TestASTDumper Dumper(OS); + Dumper.SetTraversalKind(TK); + + OS << "\n"; + + Dumper.Visit(std::forward<NodeType &&>(N)...); + + return OS.str(); +} + const FunctionDecl *getFunctionNode(clang::ASTUnit *AST, const std::string &Name) { auto Result = ast_matchers::match(functionDecl(hasName(Name)).bind("fn"), @@ -244,4 +259,224 @@ TemplateArgument EXPECT_EQ(toTargetAddressSpace(static_cast<LangAS>(AS->getAddressSpace())), 19u); } + +TEST(Traverse, IgnoreUnlessSpelledInSource) { + + auto AST = buildASTFromCode(R"cpp( + +struct A +{ +}; + +struct B +{ + B(int); + B(A const& a); + B(); +}; + +struct C +{ + operator B(); +}; + +B func1() { + return 42; +} + +B func2() { + return B{42}; +} + +B func3() { + return B(42); +} + +B func4() { + return B(); +} + +B func5() { + return B{}; +} + +B func6() { + return C(); +} + +B func7() { + return A(); +} + +B func8() { + return C{}; +} + +B func9() { + return A{}; +} + +B func10() { + A a; + return a; +} + +B func11() { + B b; + return b; +} + +B func12() { + C c; + return c; +} + +)cpp"); + + auto getFunctionNode = [&AST](const std::string &name) { + auto BN = ast_matchers::match(functionDecl(hasName(name)).bind("fn"), + AST->getASTContext()); + EXPECT_EQ(BN.size(), 1u); + return BN[0].getNodeAs<Decl>("fn"); + }; + + { + auto FN = getFunctionNode("func1"); + + EXPECT_EQ(dumpASTString(ast_type_traits::TK_AsIs, FN), + R"cpp( +FunctionDecl 'func1' +`-CompoundStmt + `-ReturnStmt + `-ExprWithCleanups + `-CXXConstructExpr + `-MaterializeTemporaryExpr + `-ImplicitCastExpr + `-CXXConstructExpr + `-IntegerLiteral +)cpp"); + + EXPECT_EQ( + dumpASTString(ast_type_traits::TK_IgnoreUnlessSpelledInSource, FN), + R"cpp( +FunctionDecl 'func1' +`-CompoundStmt + `-ReturnStmt + `-IntegerLiteral +)cpp"); + } + + EXPECT_EQ(dumpASTString(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + getFunctionNode("func2")), + R"cpp( +FunctionDecl 'func2' +`-CompoundStmt + `-ReturnStmt + `-CXXTemporaryObjectExpr + `-IntegerLiteral +)cpp"); + + EXPECT_EQ(dumpASTString(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + getFunctionNode("func3")), + R"cpp( +FunctionDecl 'func3' +`-CompoundStmt + `-ReturnStmt + `-CXXFunctionalCastExpr + `-IntegerLiteral +)cpp"); + + EXPECT_EQ(dumpASTString(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + getFunctionNode("func4")), + R"cpp( +FunctionDecl 'func4' +`-CompoundStmt + `-ReturnStmt + `-CXXTemporaryObjectExpr +)cpp"); + + EXPECT_EQ(dumpASTString(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + getFunctionNode("func5")), + R"cpp( +FunctionDecl 'func5' +`-CompoundStmt + `-ReturnStmt + `-CXXTemporaryObjectExpr +)cpp"); + + EXPECT_EQ(dumpASTString(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + getFunctionNode("func6")), + R"cpp( +FunctionDecl 'func6' +`-CompoundStmt + `-ReturnStmt + `-CXXTemporaryObjectExpr +)cpp"); + + EXPECT_EQ(dumpASTString(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + getFunctionNode("func7")), + R"cpp( +FunctionDecl 'func7' +`-CompoundStmt + `-ReturnStmt + `-CXXTemporaryObjectExpr +)cpp"); + + EXPECT_EQ(dumpASTString(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + getFunctionNode("func8")), + R"cpp( +FunctionDecl 'func8' +`-CompoundStmt + `-ReturnStmt + `-CXXFunctionalCastExpr + `-InitListExpr +)cpp"); + + EXPECT_EQ(dumpASTString(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + getFunctionNode("func9")), + R"cpp( +FunctionDecl 'func9' +`-CompoundStmt + `-ReturnStmt + `-CXXFunctionalCastExpr + `-InitListExpr +)cpp"); + + EXPECT_EQ(dumpASTString(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + getFunctionNode("func10")), + R"cpp( +FunctionDecl 'func10' +`-CompoundStmt + |-DeclStmt + | `-VarDecl 'a' + | `-CXXConstructExpr + `-ReturnStmt + `-DeclRefExpr 'a' +)cpp"); + + EXPECT_EQ(dumpASTString(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + getFunctionNode("func11")), + R"cpp( +FunctionDecl 'func11' +`-CompoundStmt + |-DeclStmt + | `-VarDecl 'b' + | `-CXXConstructExpr + `-ReturnStmt + `-DeclRefExpr 'b' +)cpp"); + + EXPECT_EQ(dumpASTString(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + getFunctionNode("func12")), + R"cpp( +FunctionDecl 'func12' +`-CompoundStmt + |-DeclStmt + | `-VarDecl 'c' + | `-CXXConstructExpr + `-ReturnStmt + `-DeclRefExpr 'c' +)cpp"); +} + } // namespace clang diff --git a/clang/unittests/AST/CMakeLists.txt b/clang/unittests/AST/CMakeLists.txt index 4d463d1cc30..be585efc7a2 100644 --- a/clang/unittests/AST/CMakeLists.txt +++ b/clang/unittests/AST/CMakeLists.txt @@ -15,6 +15,7 @@ add_clang_unittest(ASTTests ASTImporterVisibilityTest.cpp ASTTraverserTest.cpp ASTTypeTraitsTest.cpp + ASTTraverserTest.cpp ASTVectorTest.cpp CommentLexer.cpp CommentParser.cpp diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index f67e4d965b5..a21ed04b32d 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -1680,6 +1680,149 @@ void foo() functionDecl(hasDescendant(Matcher))))))); } +TEST(Traversal, traverseUnlessSpelledInSource) { + + StringRef Code = R"cpp( + +struct A +{ +}; + +struct B +{ + B(int); + B(A const& a); + B(); +}; + +struct C +{ + operator B(); +}; + +B func1() { + return 42; +} + +B func2() { + return B{42}; +} + +B func3() { + return B(42); +} + +B func4() { + return B(); +} + +B func5() { + return B{}; +} + +B func6() { + return C(); +} + +B func7() { + return A(); +} + +B func8() { + return C{}; +} + +B func9() { + return A{}; +} + +B func10() { + A a; + return a; +} + +B func11() { + B b; + return b; +} + +B func12() { + C c; + return c; +} + +)cpp"; + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + returnStmt(forFunction(functionDecl(hasName("func1"))), + hasReturnValue(integerLiteral(equals(42))))))); + + EXPECT_TRUE(matches( + Code, + traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + returnStmt(forFunction(functionDecl(hasName("func2"))), + hasReturnValue(cxxTemporaryObjectExpr( + hasArgument(0, integerLiteral(equals(42))))))))); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + returnStmt(forFunction(functionDecl(hasName("func3"))), + hasReturnValue( + cxxFunctionalCastExpr(hasSourceExpression( + integerLiteral(equals(42))))))))); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + returnStmt(forFunction(functionDecl(hasName("func4"))), + hasReturnValue(cxxTemporaryObjectExpr()))))); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + returnStmt(forFunction(functionDecl(hasName("func5"))), + hasReturnValue(cxxTemporaryObjectExpr()))))); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + returnStmt(forFunction(functionDecl(hasName("func6"))), + hasReturnValue(cxxTemporaryObjectExpr()))))); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + returnStmt(forFunction(functionDecl(hasName("func7"))), + hasReturnValue(cxxTemporaryObjectExpr()))))); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + returnStmt(forFunction(functionDecl(hasName("func8"))), + hasReturnValue(cxxFunctionalCastExpr( + hasSourceExpression(initListExpr()))))))); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + returnStmt(forFunction(functionDecl(hasName("func9"))), + hasReturnValue(cxxFunctionalCastExpr( + hasSourceExpression(initListExpr()))))))); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + returnStmt(forFunction(functionDecl(hasName("func10"))), + hasReturnValue( + declRefExpr(to(varDecl(hasName("a"))))))))); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + returnStmt(forFunction(functionDecl(hasName("func11"))), + hasReturnValue( + declRefExpr(to(varDecl(hasName("b"))))))))); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + returnStmt(forFunction(functionDecl(hasName("func12"))), + hasReturnValue( + declRefExpr(to(varDecl(hasName("c"))))))))); +} + TEST(IgnoringImpCasts, MatchesImpCasts) { // This test checks that ignoringImpCasts matches when implicit casts are // present and its inner matcher alone does not match. |

