From 8d8b3415f72c7b371a4721e345968cec90d6e949 Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Tue, 6 Dec 2022 20:14:42 +0100 Subject: [PATCH] Added automatic call tracing through lambdas passed to functions as params --- .../visitor/translation_unit_visitor.cc | 32 ++++++++----------- tests/t20012/t20012.cc | 11 +++++++ tests/t20012/test_case.h | 22 +++++++------ tests/t20014/t20014_c.cc | 10 ------ 4 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/sequence_diagram/visitor/translation_unit_visitor.cc b/src/sequence_diagram/visitor/translation_unit_visitor.cc index b99d19c3..ab29c275 100644 --- a/src/sequence_diagram/visitor/translation_unit_visitor.cc +++ b/src/sequence_diagram/visitor/translation_unit_visitor.cc @@ -507,9 +507,6 @@ bool translation_unit_visitor::TraverseLambdaExpr(clang::LambdaExpr *expr) RecursiveASTVisitor::TraverseLambdaExpr(expr); - LOG_DBG("Leaving lambda expression {} at {}", lambda_full_name, - expr->getBeginLoc().printToString(source_manager())); - context().leave_lambda_expression(); return true; @@ -517,18 +514,10 @@ bool translation_unit_visitor::TraverseLambdaExpr(clang::LambdaExpr *expr) bool translation_unit_visitor::TraverseCallExpr(clang::CallExpr *expr) { - LOG_DBG("Entering call expression at {}", - expr->getBeginLoc().printToString(source_manager())); - - if (expr->getCalleeDecl() && - expr->getCalleeDecl()->isFunctionOrFunctionTemplate()) - context().current_function_call_expr_ = expr; + context().current_function_call_expr_ = expr; RecursiveASTVisitor::TraverseCallExpr(expr); - LOG_DBG("Leaving call expression at {}", - expr->getBeginLoc().printToString(source_manager())); - context().current_function_call_expr_ = nullptr; return true; @@ -544,10 +533,6 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr) if (context().caller_id() == 0) return true; - LOG_DBG("Visiting call expression at {} [caller_id = {}]", - expr->getBeginLoc().printToString(source_manager()), - context().caller_id()); - // Skip casts, moves and such if (expr->isCallToStdMove()) return true; @@ -561,6 +546,10 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr) if (!context().valid()) return true; + LOG_DBG("Visiting call expression at {} [caller_id = {}]", + expr->getBeginLoc().printToString(source_manager()), + context().caller_id()); + message m; m.type = message_t::kCall; m.from = context().caller_id(); @@ -568,9 +557,14 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr) // If we're currently inside a lambda expression, set it's id as // message source rather then enclosing context // Unless the lambda is declared in a function or method call - if (context().lambda_caller_id() != 0 && - context().current_function_call_expr_ == nullptr) { - m.from = context().lambda_caller_id(); + if (context().lambda_caller_id() != 0) { + if (context().current_function_call_expr_ == nullptr) { + m.from = context().lambda_caller_id(); + } + else { + LOG_DBG("Current lambda declaration is passed to a method or " + "function - keep the original caller id"); + } } if (const auto *operator_call_expr = diff --git a/tests/t20012/t20012.cc b/tests/t20012/t20012.cc index 488211a3..50c5fe72 100644 --- a/tests/t20012/t20012.cc +++ b/tests/t20012/t20012.cc @@ -1,3 +1,4 @@ +#include #include #include @@ -27,6 +28,10 @@ struct C { void ccc() { } }; +struct D { + int add5(int arg) const { return arg + 5; } +}; + template struct R { R(F &&f) : f_{std::move(f)} @@ -68,6 +73,12 @@ void tmain() R r{[&c]() { c.c(); }}; r.r(); + + D d; + + std::vector ints{0, 1, 2, 3, 4}; + std::transform(ints.begin(), ints.end(), ints.begin(), + [&d](auto i) { return d.add5(i); }); } } } \ No newline at end of file diff --git a/tests/t20012/test_case.h b/tests/t20012/test_case.h index b40f10e8..6440d03b 100644 --- a/tests/t20012/test_case.h +++ b/tests/t20012/test_case.h @@ -36,35 +36,37 @@ TEST_CASE("t20012", "[test-case][sequence]") // Check if all calls exist REQUIRE_THAT(puml, - HasCall(_A("tmain()"), _A("tmain()::(lambda t20012.cc:49:20)"), + HasCall(_A("tmain()"), _A("tmain()::(lambda t20012.cc:54:20)"), "operator()()")); REQUIRE_THAT( - puml, HasCall(_A("tmain()::(lambda t20012.cc:49:20)"), _A("A"), "a()")); + puml, HasCall(_A("tmain()::(lambda t20012.cc:54:20)"), _A("A"), "a()")); REQUIRE_THAT(puml, HasCall(_A("A"), _A("A"), "aa()")); REQUIRE_THAT(puml, HasCall(_A("A"), _A("A"), "aaa()")); REQUIRE_THAT( - puml, HasCall(_A("tmain()::(lambda t20012.cc:49:20)"), _A("B"), "b()")); + puml, HasCall(_A("tmain()::(lambda t20012.cc:54:20)"), _A("B"), "b()")); REQUIRE_THAT(puml, HasCall(_A("B"), _A("B"), "bb()")); REQUIRE_THAT(puml, HasCall(_A("B"), _A("B"), "bbb()")); REQUIRE_THAT( - puml, HasCall(_A("tmain()::(lambda t20012.cc:62:20)"), _A("C"), "c()")); + puml, HasCall(_A("tmain()::(lambda t20012.cc:67:20)"), _A("C"), "c()")); REQUIRE_THAT(puml, HasCall(_A("C"), _A("C"), "cc()")); REQUIRE_THAT(puml, HasCall(_A("C"), _A("C"), "ccc()")); REQUIRE_THAT(puml, - HasCall(_A("tmain()::(lambda t20012.cc:62:20)"), - _A("tmain()::(lambda t20012.cc:49:20)"), "operator()()")); + HasCall(_A("tmain()::(lambda t20012.cc:67:20)"), + _A("tmain()::(lambda t20012.cc:54:20)"), "operator()()")); REQUIRE_THAT(puml, HasCall(_A("C"), _A("C"), "ccc()")); REQUIRE_THAT(puml, - HasCall(_A("tmain()"), _A("R"), "r()")); + HasCall(_A("tmain()"), _A("R"), "r()")); REQUIRE_THAT(puml, - HasCall(_A("R"), - _A("tmain()::(lambda t20012.cc:68:9)"), "operator()()")); + HasCall(_A("R"), + _A("tmain()::(lambda t20012.cc:73:9)"), "operator()()")); REQUIRE_THAT( - puml, HasCall(_A("tmain()::(lambda t20012.cc:68:9)"), _A("C"), "c()")); + puml, HasCall(_A("tmain()::(lambda t20012.cc:73:9)"), _A("C"), "c()")); + + REQUIRE_THAT(puml, HasCall(_A("tmain()"), _A("D"), "add5(int)")); save_puml( "./" + config.output_directory() + "/" + diagram->name + ".puml", puml); diff --git a/tests/t20014/t20014_c.cc b/tests/t20014/t20014_c.cc index 363fc63d..3a4a45ff 100644 --- a/tests/t20014/t20014_c.cc +++ b/tests/t20014/t20014_c.cc @@ -3,15 +3,5 @@ namespace clanguml { namespace t20014 { -//template F C::c1(F i, F j) -//{ -// return c_.b1(i, j); -//} -// -//template F C::c2(F i, F j) -//{ -// return c_.b2(i, j); -//} - } } \ No newline at end of file