Added automatic call tracing through lambdas passed to functions as params
This commit is contained in:
@@ -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 =
|
||||
|
||||
@@ -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); });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user