diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp @@ -41,6 +41,11 @@ if (IntegerLiteral *IL = dyn_cast(S)) { return (ClassName + "(" + IL->getValue().toString(10, false) + ")").str(); } + if (UnaryOperator *UO = dyn_cast(S)) { + return (ClassName + "(" + UnaryOperator::getOpcodeStr(UO->getOpcode()) + + ")") + .str(); + } if (BinaryOperator *BO = dyn_cast(S)) { return (ClassName + "(" + BinaryOperator::getOpcodeStr(BO->getOpcode()) + ")") @@ -390,15 +395,15 @@ )txt")); } -TEST(RecursiveASTVisitor, StmtCallbacks_TraverseBinaryOperator) { +TEST(RecursiveASTVisitor, StmtCallbacks_TraverseUnaryOperator) { class RecordingVisitor : public RecordingVisitorBase { public: RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) : RecordingVisitorBase(ShouldTraversePostOrderValue) {} - bool TraverseBinaryOperator(BinaryOperator *BO) { - recordCallback(__func__, BO, [&]() { - RecordingVisitorBase::TraverseBinaryOperator(BO); + bool TraverseUnaryOperator(UnaryOperator *UO) { + recordCallback(__func__, UO, [&]() { + RecordingVisitorBase::TraverseUnaryOperator(UO); }); return true; } @@ -411,27 +416,24 @@ }; StringRef Code = R"cpp( -void add(int, int); void test() { 1; - 2 + 3; - add(4, 5); + -2; + 3; } )cpp"; + // TraverseUnaryOperator is not called because RecursiveASTVisitor treats + // individual operators as subclasses, for which it calls their Traverse + // methods. EXPECT_TRUE(visitorCallbackLogEqual( RecordingVisitor(ShouldTraversePostOrder::No), Code, R"txt( WalkUpFromStmt CompoundStmt WalkUpFromStmt IntegerLiteral(1) -WalkUpFromStmt BinaryOperator(+) +WalkUpFromStmt UnaryOperator(-) WalkUpFromStmt IntegerLiteral(2) WalkUpFromStmt IntegerLiteral(3) -WalkUpFromStmt CallExpr(add) -WalkUpFromStmt ImplicitCastExpr -WalkUpFromStmt DeclRefExpr(add) -WalkUpFromStmt IntegerLiteral(4) -WalkUpFromStmt IntegerLiteral(5) )txt")); EXPECT_TRUE(visitorCallbackLogEqual( @@ -439,27 +441,22 @@ R"txt( WalkUpFromStmt IntegerLiteral(1) WalkUpFromStmt IntegerLiteral(2) +WalkUpFromStmt UnaryOperator(-) WalkUpFromStmt IntegerLiteral(3) -WalkUpFromStmt BinaryOperator(+) -WalkUpFromStmt DeclRefExpr(add) -WalkUpFromStmt ImplicitCastExpr -WalkUpFromStmt IntegerLiteral(4) -WalkUpFromStmt IntegerLiteral(5) -WalkUpFromStmt CallExpr(add) WalkUpFromStmt CompoundStmt )txt")); } TEST(RecursiveASTVisitor, - StmtCallbacks_TraverseBinaryOperator_WalkUpFromBinaryOperator) { + StmtCallbacks_TraverseUnaryOperator_WalkUpFromUnaryOperator) { class RecordingVisitor : public RecordingVisitorBase { public: RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) : RecordingVisitorBase(ShouldTraversePostOrderValue) {} - bool TraverseBinaryOperator(BinaryOperator *BO) { - recordCallback(__func__, BO, [&]() { - RecordingVisitorBase::TraverseBinaryOperator(BO); + bool TraverseUnaryOperator(UnaryOperator *UO) { + recordCallback(__func__, UO, [&]() { + RecordingVisitorBase::TraverseUnaryOperator(UO); }); return true; } @@ -476,49 +473,38 @@ return true; } - bool WalkUpFromBinaryOperator(BinaryOperator *BO) { - recordCallback(__func__, BO, [&]() { - RecordingVisitorBase::WalkUpFromBinaryOperator(BO); + bool WalkUpFromUnaryOperator(UnaryOperator *UO) { + recordCallback(__func__, UO, [&]() { + RecordingVisitorBase::WalkUpFromUnaryOperator(UO); }); return true; } }; StringRef Code = R"cpp( -void add(int, int); void test() { 1; - 2 + 3; - add(4, 5); + -2; + 3; } )cpp"; - // FIXME: It is arguably a bug in RecursiveASTVisitor that - // WalkUpFromBinaryOperator is called, but TraverseBinaryOperator is not - // called. + // TraverseUnaryOperator is not called because RecursiveASTVisitor treats + // individual operators as subclasses, for which it calls their Traverse + // methods. EXPECT_TRUE(visitorCallbackLogEqual( RecordingVisitor(ShouldTraversePostOrder::No), Code, R"txt( WalkUpFromStmt CompoundStmt WalkUpFromExpr IntegerLiteral(1) WalkUpFromStmt IntegerLiteral(1) -WalkUpFromBinaryOperator BinaryOperator(+) - WalkUpFromExpr BinaryOperator(+) - WalkUpFromStmt BinaryOperator(+) +WalkUpFromUnaryOperator UnaryOperator(-) + WalkUpFromExpr UnaryOperator(-) + WalkUpFromStmt UnaryOperator(-) WalkUpFromExpr IntegerLiteral(2) WalkUpFromStmt IntegerLiteral(2) WalkUpFromExpr IntegerLiteral(3) WalkUpFromStmt IntegerLiteral(3) -WalkUpFromExpr CallExpr(add) - WalkUpFromStmt CallExpr(add) -WalkUpFromExpr ImplicitCastExpr - WalkUpFromStmt ImplicitCastExpr -WalkUpFromExpr DeclRefExpr(add) - WalkUpFromStmt DeclRefExpr(add) -WalkUpFromExpr IntegerLiteral(4) - WalkUpFromStmt IntegerLiteral(4) -WalkUpFromExpr IntegerLiteral(5) - WalkUpFromStmt IntegerLiteral(5) )txt")); EXPECT_TRUE(visitorCallbackLogEqual( @@ -528,26 +514,16 @@ WalkUpFromStmt IntegerLiteral(1) WalkUpFromExpr IntegerLiteral(2) WalkUpFromStmt IntegerLiteral(2) +WalkUpFromUnaryOperator UnaryOperator(-) + WalkUpFromExpr UnaryOperator(-) + WalkUpFromStmt UnaryOperator(-) WalkUpFromExpr IntegerLiteral(3) WalkUpFromStmt IntegerLiteral(3) -WalkUpFromBinaryOperator BinaryOperator(+) - WalkUpFromExpr BinaryOperator(+) - WalkUpFromStmt BinaryOperator(+) -WalkUpFromExpr DeclRefExpr(add) - WalkUpFromStmt DeclRefExpr(add) -WalkUpFromExpr ImplicitCastExpr - WalkUpFromStmt ImplicitCastExpr -WalkUpFromExpr IntegerLiteral(4) - WalkUpFromStmt IntegerLiteral(4) -WalkUpFromExpr IntegerLiteral(5) - WalkUpFromStmt IntegerLiteral(5) -WalkUpFromExpr CallExpr(add) - WalkUpFromStmt CallExpr(add) WalkUpFromStmt CompoundStmt )txt")); } -TEST(RecursiveASTVisitor, StmtCallbacks_WalkUpFromBinaryOperator) { +TEST(RecursiveASTVisitor, StmtCallbacks_WalkUpFromUnaryOperator) { class RecordingVisitor : public RecordingVisitorBase { public: RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) @@ -565,20 +541,19 @@ return true; } - bool WalkUpFromBinaryOperator(BinaryOperator *BO) { - recordCallback(__func__, BO, [&]() { - RecordingVisitorBase::WalkUpFromBinaryOperator(BO); + bool WalkUpFromUnaryOperator(UnaryOperator *UO) { + recordCallback(__func__, UO, [&]() { + RecordingVisitorBase::WalkUpFromUnaryOperator(UO); }); return true; } }; StringRef Code = R"cpp( -void add(int, int); void test() { 1; - 2 + 3; - add(4, 5); + -2; + 3; } )cpp"; @@ -588,23 +563,13 @@ WalkUpFromStmt CompoundStmt WalkUpFromExpr IntegerLiteral(1) WalkUpFromStmt IntegerLiteral(1) -WalkUpFromBinaryOperator BinaryOperator(+) - WalkUpFromExpr BinaryOperator(+) - WalkUpFromStmt BinaryOperator(+) +WalkUpFromUnaryOperator UnaryOperator(-) + WalkUpFromExpr UnaryOperator(-) + WalkUpFromStmt UnaryOperator(-) WalkUpFromExpr IntegerLiteral(2) WalkUpFromStmt IntegerLiteral(2) WalkUpFromExpr IntegerLiteral(3) WalkUpFromStmt IntegerLiteral(3) -WalkUpFromExpr CallExpr(add) - WalkUpFromStmt CallExpr(add) -WalkUpFromExpr ImplicitCastExpr - WalkUpFromStmt ImplicitCastExpr -WalkUpFromExpr DeclRefExpr(add) - WalkUpFromStmt DeclRefExpr(add) -WalkUpFromExpr IntegerLiteral(4) - WalkUpFromStmt IntegerLiteral(4) -WalkUpFromExpr IntegerLiteral(5) - WalkUpFromStmt IntegerLiteral(5) )txt")); EXPECT_TRUE(visitorCallbackLogEqual( @@ -614,21 +579,1002 @@ WalkUpFromStmt IntegerLiteral(1) WalkUpFromExpr IntegerLiteral(2) WalkUpFromStmt IntegerLiteral(2) +WalkUpFromUnaryOperator UnaryOperator(-) + WalkUpFromExpr UnaryOperator(-) + WalkUpFromStmt UnaryOperator(-) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST(RecursiveASTVisitor, StmtCallbacks_TraverseUnaryMinus) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool TraverseUnaryMinus(UnaryOperator *UO) { + recordCallback(__func__, UO, + [&]() { RecordingVisitorBase::TraverseUnaryMinus(UO); }); + return true; + } + + bool WalkUpFromStmt(Stmt *S) { + recordCallback(__func__, S, + [&]() { RecordingVisitorBase::WalkUpFromStmt(S); }); + return true; + } + }; + + StringRef Code = R"cpp( +void test() { + 1; + -2; + 3; +} +)cpp"; + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::No), Code, + R"txt( +WalkUpFromStmt CompoundStmt +WalkUpFromStmt IntegerLiteral(1) +TraverseUnaryMinus UnaryOperator(-) + WalkUpFromStmt UnaryOperator(-) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromStmt IntegerLiteral(3) +)txt")); + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::Yes), Code, + R"txt( +WalkUpFromStmt IntegerLiteral(1) +TraverseUnaryMinus UnaryOperator(-) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromStmt UnaryOperator(-) +WalkUpFromStmt IntegerLiteral(3) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST(RecursiveASTVisitor, + StmtCallbacks_TraverseUnaryMinus_WalkUpFromUnaryMinus) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool TraverseUnaryMinus(UnaryOperator *UO) { + recordCallback(__func__, UO, + [&]() { RecordingVisitorBase::TraverseUnaryMinus(UO); }); + return true; + } + + bool WalkUpFromStmt(Stmt *S) { + recordCallback(__func__, S, + [&]() { RecordingVisitorBase::WalkUpFromStmt(S); }); + return true; + } + + bool WalkUpFromExpr(Expr *E) { + recordCallback(__func__, E, + [&]() { RecordingVisitorBase::WalkUpFromExpr(E); }); + return true; + } + + bool WalkUpFromUnaryMinus(UnaryOperator *UO) { + recordCallback(__func__, UO, + [&]() { RecordingVisitorBase::WalkUpFromUnaryMinus(UO); }); + return true; + } + }; + + StringRef Code = R"cpp( +void test() { + 1; + -2; + 3; +} +)cpp"; + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::No), Code, + R"txt( +WalkUpFromStmt CompoundStmt +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +TraverseUnaryMinus UnaryOperator(-) + WalkUpFromUnaryMinus UnaryOperator(-) + WalkUpFromExpr UnaryOperator(-) + WalkUpFromStmt UnaryOperator(-) + WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +)txt")); + + // FIXME: The following log should include a call to WalkUpFromUnaryMinus. + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::Yes), Code, + R"txt( +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +TraverseUnaryMinus UnaryOperator(-) + WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromExpr UnaryOperator(-) + WalkUpFromStmt UnaryOperator(-) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST(RecursiveASTVisitor, StmtCallbacks_WalkUpFromUnaryMinus) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool WalkUpFromStmt(Stmt *S) { + recordCallback(__func__, S, + [&]() { RecordingVisitorBase::WalkUpFromStmt(S); }); + return true; + } + + bool WalkUpFromExpr(Expr *E) { + recordCallback(__func__, E, + [&]() { RecordingVisitorBase::WalkUpFromExpr(E); }); + return true; + } + + bool WalkUpFromUnaryMinus(UnaryOperator *UO) { + recordCallback(__func__, UO, + [&]() { RecordingVisitorBase::WalkUpFromUnaryMinus(UO); }); + return true; + } + }; + + StringRef Code = R"cpp( +void test() { + 1; + -2; + 3; +} +)cpp"; + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::No), Code, + R"txt( +WalkUpFromStmt CompoundStmt +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +WalkUpFromUnaryMinus UnaryOperator(-) + WalkUpFromExpr UnaryOperator(-) + WalkUpFromStmt UnaryOperator(-) +WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +)txt")); + + // FIXME: The following log should include a call to WalkUpFromUnaryMinus. + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::Yes), Code, + R"txt( +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromExpr UnaryOperator(-) + WalkUpFromStmt UnaryOperator(-) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST(RecursiveASTVisitor, StmtCallbacks_TraverseBinaryOperator) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool TraverseBinaryOperator(BinaryOperator *BO) { + recordCallback(__func__, BO, [&]() { + RecordingVisitorBase::TraverseBinaryOperator(BO); + }); + return true; + } + + bool WalkUpFromStmt(Stmt *S) { + recordCallback(__func__, S, + [&]() { RecordingVisitorBase::WalkUpFromStmt(S); }); + return true; + } + }; + + StringRef Code = R"cpp( +void test() { + 1; + 2 + 3; + 4; +} +)cpp"; + + // TraverseBinaryOperator is not called because RecursiveASTVisitor treats + // individual operators as subclasses, for which it calls their Traverse + // methods. + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::No), Code, + R"txt( +WalkUpFromStmt CompoundStmt +WalkUpFromStmt IntegerLiteral(1) +WalkUpFromStmt BinaryOperator(+) +WalkUpFromStmt IntegerLiteral(2) +WalkUpFromStmt IntegerLiteral(3) +WalkUpFromStmt IntegerLiteral(4) +)txt")); + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::Yes), Code, + R"txt( +WalkUpFromStmt IntegerLiteral(1) +WalkUpFromStmt IntegerLiteral(2) +WalkUpFromStmt IntegerLiteral(3) +WalkUpFromStmt BinaryOperator(+) +WalkUpFromStmt IntegerLiteral(4) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST(RecursiveASTVisitor, + StmtCallbacks_TraverseBinaryOperator_WalkUpFromBinaryOperator) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool TraverseBinaryOperator(BinaryOperator *BO) { + recordCallback(__func__, BO, [&]() { + RecordingVisitorBase::TraverseBinaryOperator(BO); + }); + return true; + } + + bool WalkUpFromStmt(Stmt *S) { + recordCallback(__func__, S, + [&]() { RecordingVisitorBase::WalkUpFromStmt(S); }); + return true; + } + + bool WalkUpFromExpr(Expr *E) { + recordCallback(__func__, E, + [&]() { RecordingVisitorBase::WalkUpFromExpr(E); }); + return true; + } + + bool WalkUpFromBinaryOperator(BinaryOperator *BO) { + recordCallback(__func__, BO, [&]() { + RecordingVisitorBase::WalkUpFromBinaryOperator(BO); + }); + return true; + } + }; + + StringRef Code = R"cpp( +void test() { + 1; + 2 + 3; + 4; +} +)cpp"; + + // TraverseBinaryOperator is not called because RecursiveASTVisitor treats + // individual operators as subclasses, for which it calls their Traverse + // methods. + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::No), Code, + R"txt( +WalkUpFromStmt CompoundStmt +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +WalkUpFromBinaryOperator BinaryOperator(+) + WalkUpFromExpr BinaryOperator(+) + WalkUpFromStmt BinaryOperator(+) +WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromExpr IntegerLiteral(4) + WalkUpFromStmt IntegerLiteral(4) +)txt")); + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::Yes), Code, + R"txt( +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromBinaryOperator BinaryOperator(+) + WalkUpFromExpr BinaryOperator(+) + WalkUpFromStmt BinaryOperator(+) +WalkUpFromExpr IntegerLiteral(4) + WalkUpFromStmt IntegerLiteral(4) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST(RecursiveASTVisitor, StmtCallbacks_WalkUpFromBinaryOperator) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool WalkUpFromStmt(Stmt *S) { + recordCallback(__func__, S, + [&]() { RecordingVisitorBase::WalkUpFromStmt(S); }); + return true; + } + + bool WalkUpFromExpr(Expr *E) { + recordCallback(__func__, E, + [&]() { RecordingVisitorBase::WalkUpFromExpr(E); }); + return true; + } + + bool WalkUpFromBinaryOperator(BinaryOperator *BO) { + recordCallback(__func__, BO, [&]() { + RecordingVisitorBase::WalkUpFromBinaryOperator(BO); + }); + return true; + } + }; + + StringRef Code = R"cpp( +void test() { + 1; + 2 + 3; + 4; +} +)cpp"; + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::No), Code, + R"txt( +WalkUpFromStmt CompoundStmt +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +WalkUpFromBinaryOperator BinaryOperator(+) + WalkUpFromExpr BinaryOperator(+) + WalkUpFromStmt BinaryOperator(+) +WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromExpr IntegerLiteral(4) + WalkUpFromStmt IntegerLiteral(4) +)txt")); + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::Yes), Code, + R"txt( +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromBinaryOperator BinaryOperator(+) + WalkUpFromExpr BinaryOperator(+) + WalkUpFromStmt BinaryOperator(+) +WalkUpFromExpr IntegerLiteral(4) + WalkUpFromStmt IntegerLiteral(4) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST(RecursiveASTVisitor, StmtCallbacks_TraverseBinAdd) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool TraverseBinAdd(BinaryOperator *BO) { + recordCallback(__func__, BO, + [&]() { RecordingVisitorBase::TraverseBinAdd(BO); }); + return true; + } + + bool WalkUpFromStmt(Stmt *S) { + recordCallback(__func__, S, + [&]() { RecordingVisitorBase::WalkUpFromStmt(S); }); + return true; + } + }; + + StringRef Code = R"cpp( +void test() { + 1; + 2 + 3; + 4; +} +)cpp"; + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::No), Code, + R"txt( +WalkUpFromStmt CompoundStmt +WalkUpFromStmt IntegerLiteral(1) +TraverseBinAdd BinaryOperator(+) + WalkUpFromStmt BinaryOperator(+) + WalkUpFromStmt IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromStmt IntegerLiteral(4) +)txt")); + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::Yes), Code, + R"txt( +WalkUpFromStmt IntegerLiteral(1) +TraverseBinAdd BinaryOperator(+) + WalkUpFromStmt IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromStmt BinaryOperator(+) +WalkUpFromStmt IntegerLiteral(4) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST(RecursiveASTVisitor, StmtCallbacks_TraverseBinAdd_WalkUpFromBinAdd) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool TraverseBinAdd(BinaryOperator *BO) { + recordCallback(__func__, BO, + [&]() { RecordingVisitorBase::TraverseBinAdd(BO); }); + return true; + } + + bool WalkUpFromStmt(Stmt *S) { + recordCallback(__func__, S, + [&]() { RecordingVisitorBase::WalkUpFromStmt(S); }); + return true; + } + + bool WalkUpFromExpr(Expr *E) { + recordCallback(__func__, E, + [&]() { RecordingVisitorBase::WalkUpFromExpr(E); }); + return true; + } + + bool WalkUpFromBinAdd(BinaryOperator *BO) { + recordCallback(__func__, BO, + [&]() { RecordingVisitorBase::WalkUpFromBinAdd(BO); }); + return true; + } + }; + + StringRef Code = R"cpp( +void test() { + 1; + 2 + 3; + 4; +} +)cpp"; + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::No), Code, + R"txt( +WalkUpFromStmt CompoundStmt +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +TraverseBinAdd BinaryOperator(+) + WalkUpFromBinAdd BinaryOperator(+) + WalkUpFromExpr BinaryOperator(+) + WalkUpFromStmt BinaryOperator(+) + WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) + WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromExpr IntegerLiteral(4) + WalkUpFromStmt IntegerLiteral(4) +)txt")); + + // FIXME: The following log should include a call to WalkUpFromBinAdd. + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::Yes), Code, + R"txt( +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +TraverseBinAdd BinaryOperator(+) + WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) + WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromExpr BinaryOperator(+) + WalkUpFromStmt BinaryOperator(+) +WalkUpFromExpr IntegerLiteral(4) + WalkUpFromStmt IntegerLiteral(4) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST(RecursiveASTVisitor, StmtCallbacks_WalkUpFromBinAdd) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool WalkUpFromStmt(Stmt *S) { + recordCallback(__func__, S, + [&]() { RecordingVisitorBase::WalkUpFromStmt(S); }); + return true; + } + + bool WalkUpFromExpr(Expr *E) { + recordCallback(__func__, E, + [&]() { RecordingVisitorBase::WalkUpFromExpr(E); }); + return true; + } + + bool WalkUpFromBinAdd(BinaryOperator *BO) { + recordCallback(__func__, BO, + [&]() { RecordingVisitorBase::WalkUpFromBinAdd(BO); }); + return true; + } + }; + + StringRef Code = R"cpp( +void test() { + 1; + 2 + 3; + 4; +} +)cpp"; + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::No), Code, + R"txt( +WalkUpFromStmt CompoundStmt +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +WalkUpFromBinAdd BinaryOperator(+) + WalkUpFromExpr BinaryOperator(+) + WalkUpFromStmt BinaryOperator(+) +WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromExpr IntegerLiteral(4) + WalkUpFromStmt IntegerLiteral(4) +)txt")); + + // FIXME: The following log should include a call to WalkUpFromBinAdd. + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::Yes), Code, + R"txt( +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromExpr BinaryOperator(+) + WalkUpFromStmt BinaryOperator(+) +WalkUpFromExpr IntegerLiteral(4) + WalkUpFromStmt IntegerLiteral(4) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST(RecursiveASTVisitor, StmtCallbacks_TraverseCompoundAssignOperator) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool TraverseCompoundAssignOperator(CompoundAssignOperator *CAO) { + recordCallback(__func__, CAO, [&]() { + RecordingVisitorBase::TraverseCompoundAssignOperator(CAO); + }); + return true; + } + + bool WalkUpFromStmt(Stmt *S) { + recordCallback(__func__, S, + [&]() { RecordingVisitorBase::WalkUpFromStmt(S); }); + return true; + } + }; + + StringRef Code = R"cpp( +void test(int a) { + 1; + a += 2; + 3; +} +)cpp"; + + // TraverseCompoundAssignOperator is not called because RecursiveASTVisitor + // treats individual operators as subclasses, for which it calls their + // Traverse methods. + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::No), Code, + R"txt( +WalkUpFromStmt CompoundStmt +WalkUpFromStmt IntegerLiteral(1) +WalkUpFromStmt CompoundAssignOperator(+=) +WalkUpFromStmt DeclRefExpr(a) +WalkUpFromStmt IntegerLiteral(2) +WalkUpFromStmt IntegerLiteral(3) +)txt")); + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::Yes), Code, + R"txt( +WalkUpFromStmt IntegerLiteral(1) +WalkUpFromStmt DeclRefExpr(a) +WalkUpFromStmt IntegerLiteral(2) +WalkUpFromStmt CompoundAssignOperator(+=) +WalkUpFromStmt IntegerLiteral(3) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST( + RecursiveASTVisitor, + StmtCallbacks_TraverseCompoundAssignOperator_WalkUpFromCompoundAssignOperator) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool TraverseCompoundAssignOperator(CompoundAssignOperator *CAO) { + recordCallback(__func__, CAO, [&]() { + RecordingVisitorBase::TraverseCompoundAssignOperator(CAO); + }); + return true; + } + + bool WalkUpFromStmt(Stmt *S) { + recordCallback(__func__, S, + [&]() { RecordingVisitorBase::WalkUpFromStmt(S); }); + return true; + } + + bool WalkUpFromExpr(Expr *E) { + recordCallback(__func__, E, + [&]() { RecordingVisitorBase::WalkUpFromExpr(E); }); + return true; + } + + bool WalkUpFromCompoundAssignOperator(CompoundAssignOperator *CAO) { + recordCallback(__func__, CAO, [&]() { + RecordingVisitorBase::WalkUpFromCompoundAssignOperator(CAO); + }); + return true; + } + }; + + StringRef Code = R"cpp( +void test(int a) { + 1; + a += 2; + 3; +} +)cpp"; + + // TraverseCompoundAssignOperator is not called because RecursiveASTVisitor + // treats individual operators as subclasses, for which it calls their + // Traverse methods. + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::No), Code, + R"txt( +WalkUpFromStmt CompoundStmt +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +WalkUpFromCompoundAssignOperator CompoundAssignOperator(+=) + WalkUpFromExpr CompoundAssignOperator(+=) + WalkUpFromStmt CompoundAssignOperator(+=) +WalkUpFromExpr DeclRefExpr(a) + WalkUpFromStmt DeclRefExpr(a) +WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +)txt")); + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::Yes), Code, + R"txt( +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +WalkUpFromExpr DeclRefExpr(a) + WalkUpFromStmt DeclRefExpr(a) +WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromCompoundAssignOperator CompoundAssignOperator(+=) + WalkUpFromExpr CompoundAssignOperator(+=) + WalkUpFromStmt CompoundAssignOperator(+=) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST(RecursiveASTVisitor, StmtCallbacks_WalkUpFromCompoundAssignOperator) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool WalkUpFromStmt(Stmt *S) { + recordCallback(__func__, S, + [&]() { RecordingVisitorBase::WalkUpFromStmt(S); }); + return true; + } + + bool WalkUpFromExpr(Expr *E) { + recordCallback(__func__, E, + [&]() { RecordingVisitorBase::WalkUpFromExpr(E); }); + return true; + } + + bool WalkUpFromCompoundAssignOperator(CompoundAssignOperator *CAO) { + recordCallback(__func__, CAO, [&]() { + RecordingVisitorBase::WalkUpFromCompoundAssignOperator(CAO); + }); + return true; + } + }; + + StringRef Code = R"cpp( +void test(int a) { + 1; + a += 2; + 3; +} +)cpp"; + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::No), Code, + R"txt( +WalkUpFromStmt CompoundStmt +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +WalkUpFromCompoundAssignOperator CompoundAssignOperator(+=) + WalkUpFromExpr CompoundAssignOperator(+=) + WalkUpFromStmt CompoundAssignOperator(+=) +WalkUpFromExpr DeclRefExpr(a) + WalkUpFromStmt DeclRefExpr(a) +WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +)txt")); + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::Yes), Code, + R"txt( +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +WalkUpFromExpr DeclRefExpr(a) + WalkUpFromStmt DeclRefExpr(a) +WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromCompoundAssignOperator CompoundAssignOperator(+=) + WalkUpFromExpr CompoundAssignOperator(+=) + WalkUpFromStmt CompoundAssignOperator(+=) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST(RecursiveASTVisitor, StmtCallbacks_TraverseBinAddAssign) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool TraverseBinAddAssign(CompoundAssignOperator *CAO) { + recordCallback(__func__, CAO, [&]() { + RecordingVisitorBase::TraverseBinAddAssign(CAO); + }); + return true; + } + + bool WalkUpFromStmt(Stmt *S) { + recordCallback(__func__, S, + [&]() { RecordingVisitorBase::WalkUpFromStmt(S); }); + return true; + } + }; + + StringRef Code = R"cpp( +void test(int a) { + 1; + a += 2; + 3; +} +)cpp"; + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::No), Code, + R"txt( +WalkUpFromStmt CompoundStmt +WalkUpFromStmt IntegerLiteral(1) +TraverseBinAddAssign CompoundAssignOperator(+=) + WalkUpFromStmt CompoundAssignOperator(+=) + WalkUpFromStmt DeclRefExpr(a) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromStmt IntegerLiteral(3) +)txt")); + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::Yes), Code, + R"txt( +WalkUpFromStmt IntegerLiteral(1) +TraverseBinAddAssign CompoundAssignOperator(+=) + WalkUpFromStmt DeclRefExpr(a) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromStmt CompoundAssignOperator(+=) +WalkUpFromStmt IntegerLiteral(3) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST(RecursiveASTVisitor, + StmtCallbacks_TraverseBinAddAssign_WalkUpFromBinAddAssign) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool TraverseBinAddAssign(CompoundAssignOperator *CAO) { + recordCallback(__func__, CAO, [&]() { + RecordingVisitorBase::TraverseBinAddAssign(CAO); + }); + return true; + } + + bool WalkUpFromStmt(Stmt *S) { + recordCallback(__func__, S, + [&]() { RecordingVisitorBase::WalkUpFromStmt(S); }); + return true; + } + + bool WalkUpFromExpr(Expr *E) { + recordCallback(__func__, E, + [&]() { RecordingVisitorBase::WalkUpFromExpr(E); }); + return true; + } + + bool WalkUpFromBinAddAssign(CompoundAssignOperator *CAO) { + recordCallback(__func__, CAO, [&]() { + RecordingVisitorBase::WalkUpFromBinAddAssign(CAO); + }); + return true; + } + }; + + StringRef Code = R"cpp( +void test(int a) { + 1; + a += 2; + 3; +} +)cpp"; + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::No), Code, + R"txt( +WalkUpFromStmt CompoundStmt +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +TraverseBinAddAssign CompoundAssignOperator(+=) + WalkUpFromBinAddAssign CompoundAssignOperator(+=) + WalkUpFromExpr CompoundAssignOperator(+=) + WalkUpFromStmt CompoundAssignOperator(+=) + WalkUpFromExpr DeclRefExpr(a) + WalkUpFromStmt DeclRefExpr(a) + WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +)txt")); + + // FIXME: The following log should include a call to WalkUpFromBinAddAssign. + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::Yes), Code, + R"txt( +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +TraverseBinAddAssign CompoundAssignOperator(+=) + WalkUpFromExpr DeclRefExpr(a) + WalkUpFromStmt DeclRefExpr(a) + WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromExpr CompoundAssignOperator(+=) + WalkUpFromStmt CompoundAssignOperator(+=) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST(RecursiveASTVisitor, StmtCallbacks_WalkUpFromBinAddAssign) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool WalkUpFromStmt(Stmt *S) { + recordCallback(__func__, S, + [&]() { RecordingVisitorBase::WalkUpFromStmt(S); }); + return true; + } + + bool WalkUpFromExpr(Expr *E) { + recordCallback(__func__, E, + [&]() { RecordingVisitorBase::WalkUpFromExpr(E); }); + return true; + } + + bool WalkUpFromBinAddAssign(CompoundAssignOperator *CAO) { + recordCallback(__func__, CAO, [&]() { + RecordingVisitorBase::WalkUpFromBinAddAssign(CAO); + }); + return true; + } + }; + + StringRef Code = R"cpp( +void test(int a) { + 1; + a += 2; + 3; +} +)cpp"; + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::No), Code, + R"txt( +WalkUpFromStmt CompoundStmt +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +WalkUpFromBinAddAssign CompoundAssignOperator(+=) + WalkUpFromExpr CompoundAssignOperator(+=) + WalkUpFromStmt CompoundAssignOperator(+=) +WalkUpFromExpr DeclRefExpr(a) + WalkUpFromStmt DeclRefExpr(a) +WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +)txt")); + + // FIXME: The following log should include a call to WalkUpFromBinAddAssign. + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::Yes), Code, + R"txt( +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +WalkUpFromExpr DeclRefExpr(a) + WalkUpFromStmt DeclRefExpr(a) +WalkUpFromExpr IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromExpr CompoundAssignOperator(+=) + WalkUpFromStmt CompoundAssignOperator(+=) WalkUpFromExpr IntegerLiteral(3) WalkUpFromStmt IntegerLiteral(3) -WalkUpFromBinaryOperator BinaryOperator(+) - WalkUpFromExpr BinaryOperator(+) - WalkUpFromStmt BinaryOperator(+) -WalkUpFromExpr DeclRefExpr(add) - WalkUpFromStmt DeclRefExpr(add) -WalkUpFromExpr ImplicitCastExpr - WalkUpFromStmt ImplicitCastExpr -WalkUpFromExpr IntegerLiteral(4) - WalkUpFromStmt IntegerLiteral(4) -WalkUpFromExpr IntegerLiteral(5) - WalkUpFromStmt IntegerLiteral(5) -WalkUpFromExpr CallExpr(add) - WalkUpFromStmt CallExpr(add) WalkUpFromStmt CompoundStmt )txt")); }