[PATCH] D70613: Add method to ignore invisible AST nodes
This revision was automatically updated to reflect the committed changes. Closed by commit rG98e8f774eb6c: Add method to ignore invisible AST nodes (authored by stephenkelly). Changed prior to commit: https://reviews.llvm.org/D70613?vs=233183&id=234623#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D70613/new/ https://reviews.llvm.org/D70613 Files: clang/include/clang/AST/ASTNodeTraverser.h clang/include/clang/AST/ASTTypeTraits.h clang/include/clang/AST/Expr.h clang/lib/AST/ASTContext.cpp clang/lib/AST/Expr.cpp clang/unittests/AST/ASTTraverserTest.cpp clang/unittests/AST/CMakeLists.txt clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -1680,6 +1680,149 @@ 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
[PATCH] D70613: Add method to ignore invisible AST nodes
aaron.ballman accepted this revision. aaron.ballman added a comment. This revision is now accepted and ready to land. LGTM Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D70613/new/ https://reviews.llvm.org/D70613 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D70613: Add method to ignore invisible AST nodes
steveire updated this revision to Diff 233183. steveire added a comment. Update Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D70613/new/ https://reviews.llvm.org/D70613 Files: clang/include/clang/AST/ASTNodeTraverser.h clang/include/clang/AST/ASTTypeTraits.h clang/include/clang/AST/Expr.h clang/lib/AST/ASTContext.cpp clang/lib/AST/Expr.cpp clang/unittests/AST/ASTTraverserTest.cpp clang/unittests/AST/CMakeLists.txt clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -1680,6 +1680,149 @@ 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( +
[PATCH] D70613: Add method to ignore invisible AST nodes
steveire marked 10 inline comments as done. steveire added a comment. It wasn't possible to add the `const` because of the return type. Comment at: clang/include/clang/AST/Expr.h:769-770 + /// implicit conversions. + Expr *IgnoreInvisible(); + const Expr *IgnoreInvisible() const { +return const_cast(this)->IgnoreInvisible(); aaron.ballman wrote: > `Invisible` is a bit of an odd term because the AST nodes themselves are in > fact visible within the AST. I think this means "invisible" as in "not > corresponding directly to syntax the user wrote". Bikeshedding some other > names: > > * IgnoreAllImplicitExprs > * IgnoreAllImplicitNodes > * IgnoreNodesNotWrittenByUser > * IgnoreNotWrittenInSource > > other suggestions welcome. > Changed as discussed on IRC. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D70613/new/ https://reviews.llvm.org/D70613 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D70613: Add method to ignore invisible AST nodes
aaron.ballman added inline comments. Comment at: clang/include/clang/AST/Expr.h:769-770 + /// implicit conversions. + Expr *IgnoreInvisible(); + const Expr *IgnoreInvisible() const { +return const_cast(this)->IgnoreInvisible(); `Invisible` is a bit of an odd term because the AST nodes themselves are in fact visible within the AST. I think this means "invisible" as in "not corresponding directly to syntax the user wrote". Bikeshedding some other names: * IgnoreAllImplicitExprs * IgnoreAllImplicitNodes * IgnoreNodesNotWrittenByUser * IgnoreNotWrittenInSource other suggestions welcome. Comment at: clang/lib/AST/Expr.cpp:3004-3006 + Expr *s = this; + + Expr *lasts = nullptr; Can remove the spurious newline, and these should be named according to the usual naming conventions (I'd go with `E` and `LastE`, but feel free to pick less terrible names). Comment at: clang/lib/AST/Expr.cpp:3012 + +const auto SR = s->getSourceRange(); + Drop top-level `const` (I wouldn't be sad if it also lost the `auto` at the same time). Comment at: clang/lib/AST/Expr.cpp:3014 + +if (auto C = dyn_cast(s)) { + if (C->getNumArgs() == 1) { `const auto *` Comment at: clang/lib/AST/Expr.cpp:3016 + if (C->getNumArgs() == 1) { +auto A = C->getArg(0); +if (A->getSourceRange() == SR || !dyn_cast(C)) `const Expr *` Comment at: clang/lib/AST/Expr.cpp:3017 +auto A = C->getArg(0); +if (A->getSourceRange() == SR || !dyn_cast(C)) + s = A; `!isa(C)` since you're not using the returned value anyway. Comment at: clang/lib/AST/Expr.cpp:3022 + +if (auto C = dyn_cast(s)) { + auto *ExprNode = C->getImplicitObjectArgument()->IgnoreParenImpCasts(); `const auto *` Comment at: clang/lib/AST/Expr.cpp:3023 +if (auto C = dyn_cast(s)) { + auto *ExprNode = C->getImplicitObjectArgument()->IgnoreParenImpCasts(); + if (ExprNode->getSourceRange() == SR) { `const Expr *` Are you sure you mean to skip parens here, as those are written in source? Comment at: clang/lib/AST/Expr.cpp:3024 + auto *ExprNode = C->getImplicitObjectArgument()->IgnoreParenImpCasts(); + if (ExprNode->getSourceRange() == SR) { +s = ExprNode; Elide braces Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D70613/new/ https://reviews.llvm.org/D70613 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D70613: Add method to ignore invisible AST nodes
steveire created this revision. steveire added a reviewer: aaron.ballman. Herald added subscribers: cfe-commits, mgorny. Herald added a project: clang. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D70613 Files: clang/include/clang/AST/ASTNodeTraverser.h clang/include/clang/AST/ASTTypeTraits.h clang/include/clang/AST/Expr.h clang/lib/AST/ASTContext.cpp clang/lib/AST/Expr.cpp clang/unittests/AST/ASTTraverserTest.cpp clang/unittests/AST/CMakeLists.txt clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp === --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -1680,6 +1680,149 @@ functionDecl(hasDescendant(Matcher))); } +TEST(Traversal, traverseInvisible) { + + 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_IgnoreInvisible, + returnStmt(forFunction(functionDecl(hasName("func1"))), +hasReturnValue(integerLiteral(equals(42))); + + EXPECT_TRUE(matches( + Code, + traverse(ast_type_traits::TK_IgnoreInvisible, + returnStmt(forFunction(functionDecl(hasName("func2"))), + hasReturnValue(cxxTemporaryObjectExpr( + hasArgument(0, integerLiteral(equals(42); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreInvisible, + returnStmt(forFunction(functionDecl(hasName("func3"))), +hasReturnValue( +cxxFunctionalCastExpr(hasSourceExpression( +integerLiteral(equals(42); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreInvisible, + returnStmt(forFunction(functionDecl(hasName("func4"))), +hasReturnValue(cxxTemporaryObjectExpr()); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreInvisible, + returnStmt(forFunction(functionDecl(hasName("func5"))), +hasReturnValue(cxxTemporaryObjectExpr()); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreInvisible, + returnStmt(forFunction(functionDecl(hasName("func6"))), +hasReturnValue(cxxTemporaryObjectExpr()); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreInvisible, + returnStmt(forFunction(functionDecl(hasName("func7"))), +hasReturnValue(cxxTemporaryObjectExpr()); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreInvisible, + returnStmt(forFunction(functionDecl(hasName("func8"))), +hasReturnValue(cxxFunctionalCastExpr( +hasSourceExpression(initListExpr(; + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreInvisible, + returnStmt(forFunction(functionDecl(hasName("func9"))), +hasReturnValue(cxxFunctionalCastExpr( +hasSourceExpression(initListExpr(; + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreInvisible, + returnStmt(forFunction(functionDecl(hasName("func10"))), +hasReturnValue( +declRefExpr(to(varDecl(hasName("a"); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreInvisible, + returnStmt(forFunction(functionDecl(hasName("func11"))), +hasReturnValue( +declRefExpr(to(varDecl(hasName("b"); + + EXPECT_TRUE(matches( + Code, traverse(ast_type_traits::TK_IgnoreInvisible, + returnStmt(forFunction(functionDecl(hasName("func12"))), +hasReturnValue( +declRefExpr(to(varDecl(hasName("c"); +} + TEST(IgnoringImpCasts, MatchesImpCasts) { // This test checks that ignoringImp