Added automatic call tracing through lambdas passed to functions as params

This commit is contained in:
Bartek Kryza
2022-12-06 20:14:42 +01:00
parent 1ca44c5a0d
commit 8d8b3415f7
4 changed files with 36 additions and 39 deletions

View File

@@ -507,9 +507,6 @@ bool translation_unit_visitor::TraverseLambdaExpr(clang::LambdaExpr *expr)
RecursiveASTVisitor<translation_unit_visitor>::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<translation_unit_visitor>::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 =

View File

@@ -1,3 +1,4 @@
#include <algorithm>
#include <functional>
#include <utility>
@@ -27,6 +28,10 @@ struct C {
void ccc() { }
};
struct D {
int add5(int arg) const { return arg + 5; }
};
template <typename F> 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<int> ints{0, 1, 2, 3, 4};
std::transform(ints.begin(), ints.end(), ints.begin(),
[&d](auto i) { return d.add5(i); });
}
}
}

View File

@@ -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::(lambda t20012.cc:68:9)>"), "r()"));
HasCall(_A("tmain()"), _A("R<R::(lambda t20012.cc:73:9)>"), "r()"));
REQUIRE_THAT(puml,
HasCall(_A("R<R::(lambda t20012.cc:68:9)>"),
_A("tmain()::(lambda t20012.cc:68:9)"), "operator()()"));
HasCall(_A("R<R::(lambda t20012.cc:73:9)>"),
_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);

View File

@@ -3,15 +3,5 @@
namespace clanguml {
namespace t20014 {
//template <typename T, typename F> F C<T, F>::c1(F i, F j)
//{
// return c_.b1(i, j);
//}
//
//template <typename T, typename F> F C<T, F>::c2(F i, F j)
//{
// return c_.b2(i, j);
//}
}
}