diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp index 0eb9a43ecb14..66aa1d763833 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/Callbacks.cpp @@ -41,6 +41,11 @@ public: 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,6 +395,386 @@ WalkUpFromStmt CompoundStmt )txt")); } +TEST(RecursiveASTVisitor, StmtCallbacks_TraverseUnaryOperator) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool TraverseUnaryOperator(UnaryOperator *UO) { + recordCallback(__func__, UO, [&]() { + RecordingVisitorBase::TraverseUnaryOperator(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"; + + // 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 UnaryOperator(-) +WalkUpFromStmt IntegerLiteral(2) +WalkUpFromStmt IntegerLiteral(3) +)txt")); + + EXPECT_TRUE(visitorCallbackLogEqual( + RecordingVisitor(ShouldTraversePostOrder::Yes), Code, + R"txt( +WalkUpFromStmt IntegerLiteral(1) +WalkUpFromStmt IntegerLiteral(2) +WalkUpFromStmt UnaryOperator(-) +WalkUpFromStmt IntegerLiteral(3) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST(RecursiveASTVisitor, + StmtCallbacks_TraverseUnaryOperator_WalkUpFromUnaryOperator) { + class RecordingVisitor : public RecordingVisitorBase { + public: + RecordingVisitor(ShouldTraversePostOrder ShouldTraversePostOrderValue) + : RecordingVisitorBase(ShouldTraversePostOrderValue) {} + + bool TraverseUnaryOperator(UnaryOperator *UO) { + recordCallback(__func__, UO, [&]() { + RecordingVisitorBase::TraverseUnaryOperator(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 WalkUpFromUnaryOperator(UnaryOperator *UO) { + recordCallback(__func__, UO, [&]() { + RecordingVisitorBase::WalkUpFromUnaryOperator(UO); + }); + return true; + } + }; + + StringRef Code = R"cpp( +void test() { + 1; + -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 +WalkUpFromExpr IntegerLiteral(1) + WalkUpFromStmt IntegerLiteral(1) +WalkUpFromUnaryOperator UnaryOperator(-) + WalkUpFromExpr UnaryOperator(-) + WalkUpFromStmt UnaryOperator(-) +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 IntegerLiteral(2) + WalkUpFromStmt IntegerLiteral(2) +WalkUpFromUnaryOperator UnaryOperator(-) + WalkUpFromExpr UnaryOperator(-) + WalkUpFromStmt UnaryOperator(-) +WalkUpFromExpr IntegerLiteral(3) + WalkUpFromStmt IntegerLiteral(3) +WalkUpFromStmt CompoundStmt +)txt")); +} + +TEST(RecursiveASTVisitor, StmtCallbacks_WalkUpFromUnaryOperator) { + 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 WalkUpFromUnaryOperator(UnaryOperator *UO) { + recordCallback(__func__, UO, [&]() { + RecordingVisitorBase::WalkUpFromUnaryOperator(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) +WalkUpFromUnaryOperator UnaryOperator(-) + WalkUpFromExpr UnaryOperator(-) + WalkUpFromStmt UnaryOperator(-) +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 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: @@ -411,14 +796,16 @@ TEST(RecursiveASTVisitor, StmtCallbacks_TraverseBinaryOperator) { }; StringRef Code = R"cpp( -void add(int, int); void test() { 1; 2 + 3; - add(4, 5); + 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( @@ -427,11 +814,7 @@ WalkUpFromStmt IntegerLiteral(1) WalkUpFromStmt BinaryOperator(+) WalkUpFromStmt IntegerLiteral(2) WalkUpFromStmt IntegerLiteral(3) -WalkUpFromStmt CallExpr(add) -WalkUpFromStmt ImplicitCastExpr -WalkUpFromStmt DeclRefExpr(add) WalkUpFromStmt IntegerLiteral(4) -WalkUpFromStmt IntegerLiteral(5) )txt")); EXPECT_TRUE(visitorCallbackLogEqual( @@ -441,11 +824,7 @@ WalkUpFromStmt IntegerLiteral(1) WalkUpFromStmt IntegerLiteral(2) WalkUpFromStmt IntegerLiteral(3) WalkUpFromStmt BinaryOperator(+) -WalkUpFromStmt DeclRefExpr(add) -WalkUpFromStmt ImplicitCastExpr WalkUpFromStmt IntegerLiteral(4) -WalkUpFromStmt IntegerLiteral(5) -WalkUpFromStmt CallExpr(add) WalkUpFromStmt CompoundStmt )txt")); } @@ -485,17 +864,16 @@ TEST(RecursiveASTVisitor, }; StringRef Code = R"cpp( -void add(int, int); void test() { 1; 2 + 3; - add(4, 5); + 4; } )cpp"; - // FIXME: It is arguably a bug in RecursiveASTVisitor that - // WalkUpFromBinaryOperator is called, but TraverseBinaryOperator is not - // called. + // 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( @@ -509,16 +887,8 @@ 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( @@ -533,16 +903,8 @@ WalkUpFromExpr 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")); } @@ -574,11 +936,10 @@ TEST(RecursiveASTVisitor, StmtCallbacks_WalkUpFromBinaryOperator) { }; StringRef Code = R"cpp( -void add(int, int); void test() { 1; 2 + 3; - add(4, 5); + 4; } )cpp"; @@ -595,16 +956,8 @@ 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( @@ -619,16 +972,609 @@ WalkUpFromExpr 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_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) WalkUpFromStmt CompoundStmt )txt")); }