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);
|
RecursiveASTVisitor<translation_unit_visitor>::TraverseLambdaExpr(expr);
|
||||||
|
|
||||||
LOG_DBG("Leaving lambda expression {} at {}", lambda_full_name,
|
|
||||||
expr->getBeginLoc().printToString(source_manager()));
|
|
||||||
|
|
||||||
context().leave_lambda_expression();
|
context().leave_lambda_expression();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -517,18 +514,10 @@ bool translation_unit_visitor::TraverseLambdaExpr(clang::LambdaExpr *expr)
|
|||||||
|
|
||||||
bool translation_unit_visitor::TraverseCallExpr(clang::CallExpr *expr)
|
bool translation_unit_visitor::TraverseCallExpr(clang::CallExpr *expr)
|
||||||
{
|
{
|
||||||
LOG_DBG("Entering call expression at {}",
|
context().current_function_call_expr_ = expr;
|
||||||
expr->getBeginLoc().printToString(source_manager()));
|
|
||||||
|
|
||||||
if (expr->getCalleeDecl() &&
|
|
||||||
expr->getCalleeDecl()->isFunctionOrFunctionTemplate())
|
|
||||||
context().current_function_call_expr_ = expr;
|
|
||||||
|
|
||||||
RecursiveASTVisitor<translation_unit_visitor>::TraverseCallExpr(expr);
|
RecursiveASTVisitor<translation_unit_visitor>::TraverseCallExpr(expr);
|
||||||
|
|
||||||
LOG_DBG("Leaving call expression at {}",
|
|
||||||
expr->getBeginLoc().printToString(source_manager()));
|
|
||||||
|
|
||||||
context().current_function_call_expr_ = nullptr;
|
context().current_function_call_expr_ = nullptr;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -544,10 +533,6 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
|
|||||||
if (context().caller_id() == 0)
|
if (context().caller_id() == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
LOG_DBG("Visiting call expression at {} [caller_id = {}]",
|
|
||||||
expr->getBeginLoc().printToString(source_manager()),
|
|
||||||
context().caller_id());
|
|
||||||
|
|
||||||
// Skip casts, moves and such
|
// Skip casts, moves and such
|
||||||
if (expr->isCallToStdMove())
|
if (expr->isCallToStdMove())
|
||||||
return true;
|
return true;
|
||||||
@@ -561,6 +546,10 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
|
|||||||
if (!context().valid())
|
if (!context().valid())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
LOG_DBG("Visiting call expression at {} [caller_id = {}]",
|
||||||
|
expr->getBeginLoc().printToString(source_manager()),
|
||||||
|
context().caller_id());
|
||||||
|
|
||||||
message m;
|
message m;
|
||||||
m.type = message_t::kCall;
|
m.type = message_t::kCall;
|
||||||
m.from = context().caller_id();
|
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
|
// If we're currently inside a lambda expression, set it's id as
|
||||||
// message source rather then enclosing context
|
// message source rather then enclosing context
|
||||||
// Unless the lambda is declared in a function or method call
|
// Unless the lambda is declared in a function or method call
|
||||||
if (context().lambda_caller_id() != 0 &&
|
if (context().lambda_caller_id() != 0) {
|
||||||
context().current_function_call_expr_ == nullptr) {
|
if (context().current_function_call_expr_ == nullptr) {
|
||||||
m.from = context().lambda_caller_id();
|
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 =
|
if (const auto *operator_call_expr =
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@@ -27,6 +28,10 @@ struct C {
|
|||||||
void ccc() { }
|
void ccc() { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct D {
|
||||||
|
int add5(int arg) const { return arg + 5; }
|
||||||
|
};
|
||||||
|
|
||||||
template <typename F> struct R {
|
template <typename F> struct R {
|
||||||
R(F &&f)
|
R(F &&f)
|
||||||
: f_{std::move(f)}
|
: f_{std::move(f)}
|
||||||
@@ -68,6 +73,12 @@ void tmain()
|
|||||||
R r{[&c]() { c.c(); }};
|
R r{[&c]() { c.c(); }};
|
||||||
|
|
||||||
r.r();
|
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
|
// Check if all calls exist
|
||||||
REQUIRE_THAT(puml,
|
REQUIRE_THAT(puml,
|
||||||
HasCall(_A("tmain()"), _A("tmain()::(lambda t20012.cc:49:20)"),
|
HasCall(_A("tmain()"), _A("tmain()::(lambda t20012.cc:54:20)"),
|
||||||
"operator()()"));
|
"operator()()"));
|
||||||
REQUIRE_THAT(
|
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"), "aa()"));
|
||||||
REQUIRE_THAT(puml, HasCall(_A("A"), _A("A"), "aaa()"));
|
REQUIRE_THAT(puml, HasCall(_A("A"), _A("A"), "aaa()"));
|
||||||
|
|
||||||
REQUIRE_THAT(
|
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"), "bb()"));
|
||||||
REQUIRE_THAT(puml, HasCall(_A("B"), _A("B"), "bbb()"));
|
REQUIRE_THAT(puml, HasCall(_A("B"), _A("B"), "bbb()"));
|
||||||
|
|
||||||
REQUIRE_THAT(
|
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"), "cc()"));
|
||||||
REQUIRE_THAT(puml, HasCall(_A("C"), _A("C"), "ccc()"));
|
REQUIRE_THAT(puml, HasCall(_A("C"), _A("C"), "ccc()"));
|
||||||
REQUIRE_THAT(puml,
|
REQUIRE_THAT(puml,
|
||||||
HasCall(_A("tmain()::(lambda t20012.cc:62:20)"),
|
HasCall(_A("tmain()::(lambda t20012.cc:67:20)"),
|
||||||
_A("tmain()::(lambda t20012.cc:49:20)"), "operator()()"));
|
_A("tmain()::(lambda t20012.cc:54:20)"), "operator()()"));
|
||||||
|
|
||||||
REQUIRE_THAT(puml, HasCall(_A("C"), _A("C"), "ccc()"));
|
REQUIRE_THAT(puml, HasCall(_A("C"), _A("C"), "ccc()"));
|
||||||
|
|
||||||
REQUIRE_THAT(puml,
|
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,
|
REQUIRE_THAT(puml,
|
||||||
HasCall(_A("R<R::(lambda t20012.cc:68:9)>"),
|
HasCall(_A("R<R::(lambda t20012.cc:73:9)>"),
|
||||||
_A("tmain()::(lambda t20012.cc:68:9)"), "operator()()"));
|
_A("tmain()::(lambda t20012.cc:73:9)"), "operator()()"));
|
||||||
REQUIRE_THAT(
|
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(
|
save_puml(
|
||||||
"./" + config.output_directory() + "/" + diagram->name + ".puml", puml);
|
"./" + config.output_directory() + "/" + diagram->name + ".puml", puml);
|
||||||
|
|||||||
@@ -3,15 +3,5 @@
|
|||||||
namespace clanguml {
|
namespace clanguml {
|
||||||
namespace t20014 {
|
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