Fixed handling of template function specialization arguments
This commit is contained in:
@@ -126,9 +126,19 @@ int class_::calculate_template_specialization_match(
|
|||||||
{
|
{
|
||||||
int res{};
|
int res{};
|
||||||
|
|
||||||
|
LOG_DBG("### Comparing {} with {}", this->full_name(false),
|
||||||
|
other.full_name(false));
|
||||||
|
|
||||||
|
if (this->full_name(false) ==
|
||||||
|
"clanguml::t00044::signal_handler<Ret(Args...),A>" &&
|
||||||
|
other.full_name(false) ==
|
||||||
|
"clanguml::t00044::signal_handler<void(int),bool>") {
|
||||||
|
LOG_DBG("AAAAAAAAA");
|
||||||
|
}
|
||||||
|
|
||||||
const std::string left = name_and_ns();
|
const std::string left = name_and_ns();
|
||||||
// TODO: handle variadic templates
|
// TODO: handle variadic templates
|
||||||
if ((name_and_ns() != full_name) ||
|
if ((left != full_name) ||
|
||||||
(templates().size() != other.templates().size())) {
|
(templates().size() != other.templates().size())) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -142,6 +152,10 @@ int class_::calculate_template_specialization_match(
|
|||||||
res++;
|
res++;
|
||||||
}
|
}
|
||||||
else if (other_template_arg.is_specialization_of(template_arg)) {
|
else if (other_template_arg.is_specialization_of(template_arg)) {
|
||||||
|
if (template_arg.is_function_template() &&
|
||||||
|
other_template_arg.is_function_template()) {
|
||||||
|
res++;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ bool translation_unit_visitor::VisitTypeAliasTemplateDecl(
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto template_specialization_ptr =
|
auto template_specialization_ptr =
|
||||||
build_template_instantiation(*template_type_specialization_ptr);
|
build_template_instantiation(cls, *template_type_specialization_ptr);
|
||||||
|
|
||||||
if (!template_specialization_ptr)
|
if (!template_specialization_ptr)
|
||||||
return true;
|
return true;
|
||||||
@@ -630,8 +630,8 @@ void translation_unit_visitor::process_concept_specialization_relationships(
|
|||||||
std::vector<std::string> constrained_template_params;
|
std::vector<std::string> constrained_template_params;
|
||||||
|
|
||||||
size_t argument_index{};
|
size_t argument_index{};
|
||||||
for (const auto ta : concept_specialization->getTemplateArguments()) {
|
|
||||||
|
|
||||||
|
for (const auto ta : concept_specialization->getTemplateArguments()) {
|
||||||
if (ta.getKind() == clang::TemplateArgument::Type) {
|
if (ta.getKind() == clang::TemplateArgument::Type) {
|
||||||
auto type_name =
|
auto type_name =
|
||||||
common::to_string(ta.getAsType(), cpt->getASTContext());
|
common::to_string(ta.getAsType(), cpt->getASTContext());
|
||||||
@@ -1092,7 +1092,7 @@ void translation_unit_visitor::process_class_bases(
|
|||||||
base.getType()->getAs<clang::TemplateSpecializationType>();
|
base.getType()->getAs<clang::TemplateSpecializationType>();
|
||||||
tsp != nullptr) {
|
tsp != nullptr) {
|
||||||
auto template_specialization_ptr =
|
auto template_specialization_ptr =
|
||||||
build_template_instantiation(*tsp, {});
|
build_template_instantiation(cls, *tsp, {});
|
||||||
if (template_specialization_ptr) {
|
if (template_specialization_ptr) {
|
||||||
cp.set_id(template_specialization_ptr->id());
|
cp.set_id(template_specialization_ptr->id());
|
||||||
}
|
}
|
||||||
@@ -1350,7 +1350,7 @@ void translation_unit_visitor::process_method(
|
|||||||
}
|
}
|
||||||
else if (const auto *atsp = underlying_type->getAs<clang::AutoType>();
|
else if (const auto *atsp = underlying_type->getAs<clang::AutoType>();
|
||||||
atsp != nullptr) {
|
atsp != nullptr) {
|
||||||
process_function_parameter_find_relatinoships_in_autotype(c, atsp);
|
process_function_parameter_find_relationships_in_autotype(c, atsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("Adding method: {}", method.name());
|
LOG_DBG("Adding method: {}", method.name());
|
||||||
@@ -1359,7 +1359,7 @@ void translation_unit_visitor::process_method(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void translation_unit_visitor::
|
void translation_unit_visitor::
|
||||||
process_function_parameter_find_relatinoships_in_autotype(
|
process_function_parameter_find_relationships_in_autotype(
|
||||||
class_ &c, const clang::AutoType *atsp)
|
class_ &c, const clang::AutoType *atsp)
|
||||||
{
|
{
|
||||||
auto desugared_atsp = atsp->getDeducedType();
|
auto desugared_atsp = atsp->getDeducedType();
|
||||||
@@ -1665,8 +1665,9 @@ void translation_unit_visitor::
|
|||||||
template_instantiation_type.getTemplateName().getAsTemplateDecl()))
|
template_instantiation_type.getTemplateName().getAsTemplateDecl()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto template_specialization_ptr =
|
auto template_specialization_ptr = build_template_instantiation(
|
||||||
build_template_instantiation(template_instantiation_type, &c);
|
template_instantiation_type.getTemplateName().getAsTemplateDecl(),
|
||||||
|
template_instantiation_type, &c);
|
||||||
|
|
||||||
if (template_instantiation_type.isDependentType()) {
|
if (template_instantiation_type.isDependentType()) {
|
||||||
if (template_specialization_ptr) {
|
if (template_specialization_ptr) {
|
||||||
@@ -1816,9 +1817,93 @@ void translation_unit_visitor::process_template_specialization_argument(
|
|||||||
|
|
||||||
// If this is a nested template type - add nested templates as
|
// If this is a nested template type - add nested templates as
|
||||||
// template arguments
|
// template arguments
|
||||||
if (const auto *nested_template_type =
|
if (const auto *function_type =
|
||||||
arg.getAsType()->getAs<clang::TemplateSpecializationType>();
|
arg.getAsType()->getAs<clang::FunctionProtoType>();
|
||||||
nested_template_type != nullptr) {
|
function_type != nullptr) {
|
||||||
|
|
||||||
|
auto a = template_parameter::make_template_type({});
|
||||||
|
|
||||||
|
a.set_function_template(true);
|
||||||
|
|
||||||
|
// Set function template return type
|
||||||
|
const auto return_type_name =
|
||||||
|
function_type->getReturnType().getAsString();
|
||||||
|
|
||||||
|
// Try to match the return type to template parameter in case
|
||||||
|
// the type name is in the form 'type-parameter-X-Y'
|
||||||
|
auto maybe_return_arg =
|
||||||
|
get_template_argument_from_type_parameter_string(
|
||||||
|
cls, return_type_name);
|
||||||
|
|
||||||
|
if (maybe_return_arg)
|
||||||
|
a .add_template_param(*maybe_return_arg);
|
||||||
|
else {
|
||||||
|
a.add_template_param(
|
||||||
|
template_parameter::make_argument(return_type_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set function template argument types
|
||||||
|
for (const auto ¶m_type : function_type->param_types()) {
|
||||||
|
auto maybe_arg = get_template_argument_from_type_parameter_string(
|
||||||
|
cls, param_type.getAsString());
|
||||||
|
|
||||||
|
if (maybe_arg) {
|
||||||
|
a.add_template_param(*maybe_arg);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param_type->isBuiltinType()) {
|
||||||
|
a.add_template_param(template_parameter::make_argument(
|
||||||
|
param_type.getAsString()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto *param_record_type =
|
||||||
|
param_type->getAs<clang::RecordType>();
|
||||||
|
if (param_record_type == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// auto *classTemplateSpecialization =
|
||||||
|
// llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(
|
||||||
|
// param_type->getAsRecordDecl());
|
||||||
|
/*
|
||||||
|
if (classTemplateSpecialization != nullptr) {
|
||||||
|
// Read arg info as needed.
|
||||||
|
auto nested_template_instantiation =
|
||||||
|
build_template_instantiation_from_class_template_specialization(
|
||||||
|
*classTemplateSpecialization, *param_record_type,
|
||||||
|
diagram().should_include(
|
||||||
|
full_template_specialization_name)
|
||||||
|
? std::make_optional(&template_instantiation)
|
||||||
|
: parent);
|
||||||
|
|
||||||
|
const auto nested_template_name =
|
||||||
|
classTemplateSpecialization->getQualifiedNameAsString();
|
||||||
|
|
||||||
|
if (nested_template_instantiation) {
|
||||||
|
if (parent.has_value())
|
||||||
|
parent.value()->add_relationship(
|
||||||
|
{relationship_t::kDependency,
|
||||||
|
nested_template_instantiation->id()});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto nested_template_instantiation_full_name =
|
||||||
|
nested_template_instantiation->full_name(false);
|
||||||
|
if (diagram().should_include(
|
||||||
|
nested_template_instantiation_full_name)) {
|
||||||
|
diagram().add_class(
|
||||||
|
std::move(nested_template_instantiation));
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
}
|
||||||
|
argument = a;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (const auto *nested_template_type =
|
||||||
|
arg.getAsType()
|
||||||
|
->getAs<clang::TemplateSpecializationType>();
|
||||||
|
nested_template_type != nullptr) {
|
||||||
argument = template_parameter::make_argument({});
|
argument = template_parameter::make_argument({});
|
||||||
|
|
||||||
const auto nested_template_name =
|
const auto nested_template_name =
|
||||||
@@ -1829,7 +1914,7 @@ void translation_unit_visitor::process_template_specialization_argument(
|
|||||||
argument->set_type(nested_template_name);
|
argument->set_type(nested_template_name);
|
||||||
|
|
||||||
auto nested_template_instantiation = build_template_instantiation(
|
auto nested_template_instantiation = build_template_instantiation(
|
||||||
*nested_template_type, {&template_instantiation});
|
cls, *nested_template_type, {&template_instantiation});
|
||||||
|
|
||||||
argument->set_id(nested_template_instantiation->id());
|
argument->set_id(nested_template_instantiation->id());
|
||||||
|
|
||||||
@@ -2054,7 +2139,7 @@ std::unique_ptr<class_> translation_unit_visitor::
|
|||||||
std::hash<std::string>{}(full_template_specialization_name) >> 4U));
|
std::hash<std::string>{}(full_template_specialization_name) >> 4U));
|
||||||
|
|
||||||
build_template_instantiation_process_template_arguments(parent,
|
build_template_instantiation_process_template_arguments(parent,
|
||||||
template_base_params,
|
&template_specialization, template_base_params,
|
||||||
template_specialization.getTemplateArgs().asArray(),
|
template_specialization.getTemplateArgs().asArray(),
|
||||||
template_instantiation, full_template_specialization_name,
|
template_instantiation, full_template_specialization_name,
|
||||||
template_decl);
|
template_decl);
|
||||||
@@ -2106,6 +2191,7 @@ std::unique_ptr<class_> translation_unit_visitor::
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
|
std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
|
||||||
|
const clang::Decl *cls,
|
||||||
const clang::TemplateSpecializationType &template_type_decl,
|
const clang::TemplateSpecializationType &template_type_decl,
|
||||||
std::optional<clanguml::class_diagram::model::class_ *> parent)
|
std::optional<clanguml::class_diagram::model::class_ *> parent)
|
||||||
{
|
{
|
||||||
@@ -2136,7 +2222,9 @@ std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
|
|||||||
//
|
//
|
||||||
auto template_instantiation_ptr =
|
auto template_instantiation_ptr =
|
||||||
std::make_unique<class_>(config_.using_namespace());
|
std::make_unique<class_>(config_.using_namespace());
|
||||||
|
|
||||||
auto &template_instantiation = *template_instantiation_ptr;
|
auto &template_instantiation = *template_instantiation_ptr;
|
||||||
|
|
||||||
std::string full_template_specialization_name = common::to_string(
|
std::string full_template_specialization_name = common::to_string(
|
||||||
template_type.desugar(),
|
template_type.desugar(),
|
||||||
template_type.getTemplateName().getAsTemplateDecl()->getASTContext());
|
template_type.getTemplateName().getAsTemplateDecl()->getASTContext());
|
||||||
@@ -2240,7 +2328,7 @@ std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
|
|||||||
base_index++;
|
base_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
build_template_instantiation_process_template_arguments(parent,
|
build_template_instantiation_process_template_arguments(parent, cls,
|
||||||
template_base_params, template_type.template_arguments(),
|
template_base_params, template_type.template_arguments(),
|
||||||
template_instantiation, full_template_specialization_name,
|
template_instantiation, full_template_specialization_name,
|
||||||
template_decl);
|
template_decl);
|
||||||
@@ -2302,6 +2390,7 @@ std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
|
|||||||
void translation_unit_visitor::
|
void translation_unit_visitor::
|
||||||
build_template_instantiation_process_template_arguments(
|
build_template_instantiation_process_template_arguments(
|
||||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||||
|
const clang::Decl *cls,
|
||||||
std::deque<std::tuple<std::string, int, bool>> &template_base_params,
|
std::deque<std::tuple<std::string, int, bool>> &template_base_params,
|
||||||
const clang::ArrayRef<clang::TemplateArgument> &template_args,
|
const clang::ArrayRef<clang::TemplateArgument> &template_args,
|
||||||
class_ &template_instantiation,
|
class_ &template_instantiation,
|
||||||
@@ -2318,8 +2407,8 @@ void translation_unit_visitor::
|
|||||||
}
|
}
|
||||||
else if (argument_kind == clang::TemplateArgument::Type) {
|
else if (argument_kind == clang::TemplateArgument::Type) {
|
||||||
argument = build_template_instantiation_process_type_argument(
|
argument = build_template_instantiation_process_type_argument(
|
||||||
parent, full_template_specialization_name, template_decl, arg,
|
parent, cls, full_template_specialization_name, template_decl,
|
||||||
template_instantiation);
|
arg, template_instantiation);
|
||||||
}
|
}
|
||||||
else if (argument_kind == clang::TemplateArgument::Integral) {
|
else if (argument_kind == clang::TemplateArgument::Integral) {
|
||||||
argument =
|
argument =
|
||||||
@@ -2374,6 +2463,7 @@ template_parameter translation_unit_visitor::
|
|||||||
template_parameter
|
template_parameter
|
||||||
translation_unit_visitor::build_template_instantiation_process_type_argument(
|
translation_unit_visitor::build_template_instantiation_process_type_argument(
|
||||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||||
|
const clang::Decl *cls,
|
||||||
const std::string &full_template_specialization_name,
|
const std::string &full_template_specialization_name,
|
||||||
const clang::TemplateDecl *template_decl,
|
const clang::TemplateDecl *template_decl,
|
||||||
const clang::TemplateArgument &arg, class_ &template_instantiation)
|
const clang::TemplateArgument &arg, class_ &template_instantiation)
|
||||||
@@ -2382,13 +2472,45 @@ translation_unit_visitor::build_template_instantiation_process_type_argument(
|
|||||||
|
|
||||||
auto argument = template_parameter::make_argument({});
|
auto argument = template_parameter::make_argument({});
|
||||||
|
|
||||||
// If this is a nested template type - add nested templates as
|
|
||||||
// template arguments
|
|
||||||
if (const auto *function_type =
|
if (const auto *function_type =
|
||||||
arg.getAsType()->getAs<clang::FunctionProtoType>();
|
arg.getAsType()->getAs<clang::FunctionProtoType>();
|
||||||
function_type != nullptr) {
|
function_type != nullptr) {
|
||||||
|
|
||||||
|
argument.set_function_template(true);
|
||||||
|
|
||||||
|
// Set function template return type
|
||||||
|
const auto return_type_name =
|
||||||
|
function_type->getReturnType().getAsString();
|
||||||
|
|
||||||
|
// Try to match the return type to template parameter in case
|
||||||
|
// the type name is in the form 'type-parameter-X-Y'
|
||||||
|
auto maybe_return_arg =
|
||||||
|
get_template_argument_from_type_parameter_string(
|
||||||
|
cls, return_type_name);
|
||||||
|
|
||||||
|
if (maybe_return_arg)
|
||||||
|
argument.add_template_param(*maybe_return_arg);
|
||||||
|
else {
|
||||||
|
argument.add_template_param(
|
||||||
|
template_parameter::make_argument(return_type_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set function template argument types
|
||||||
for (const auto ¶m_type : function_type->param_types()) {
|
for (const auto ¶m_type : function_type->param_types()) {
|
||||||
|
auto maybe_arg = get_template_argument_from_type_parameter_string(
|
||||||
|
cls, param_type.getAsString());
|
||||||
|
|
||||||
|
if (maybe_arg) {
|
||||||
|
argument.add_template_param(*maybe_arg);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param_type->isBuiltinType()) {
|
||||||
|
argument.add_template_param(template_parameter::make_argument(
|
||||||
|
param_type.getAsString()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const auto *param_record_type =
|
const auto *param_record_type =
|
||||||
param_type->getAs<clang::RecordType>();
|
param_type->getAs<clang::RecordType>();
|
||||||
if (param_record_type == nullptr)
|
if (param_record_type == nullptr)
|
||||||
@@ -2428,6 +2550,14 @@ translation_unit_visitor::build_template_instantiation_process_type_argument(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (const auto maybe_arg =
|
||||||
|
get_template_argument_from_type_parameter_string(
|
||||||
|
cls, arg.getAsType().getAsString());
|
||||||
|
maybe_arg) {
|
||||||
|
// The type is only in the form 'type-parameter-X-Y' so we have
|
||||||
|
// to match it to a template parameter name in the 'cls' template
|
||||||
|
argument = *maybe_arg;
|
||||||
|
}
|
||||||
else if (const auto *nested_template_type =
|
else if (const auto *nested_template_type =
|
||||||
arg.getAsType()->getAs<clang::TemplateSpecializationType>();
|
arg.getAsType()->getAs<clang::TemplateSpecializationType>();
|
||||||
nested_template_type != nullptr) {
|
nested_template_type != nullptr) {
|
||||||
@@ -2439,7 +2569,7 @@ translation_unit_visitor::build_template_instantiation_process_type_argument(
|
|||||||
argument.set_type(nested_type_name);
|
argument.set_type(nested_type_name);
|
||||||
|
|
||||||
auto nested_template_instantiation =
|
auto nested_template_instantiation =
|
||||||
build_template_instantiation(*nested_template_type,
|
build_template_instantiation(cls, *nested_template_type,
|
||||||
diagram().should_include(full_template_specialization_name)
|
diagram().should_include(full_template_specialization_name)
|
||||||
? std::make_optional(&template_instantiation)
|
? std::make_optional(&template_instantiation)
|
||||||
: parent);
|
: parent);
|
||||||
@@ -2492,6 +2622,40 @@ translation_unit_visitor::build_template_instantiation_process_type_argument(
|
|||||||
return argument;
|
return argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<template_parameter>
|
||||||
|
translation_unit_visitor::get_template_argument_from_type_parameter_string(
|
||||||
|
const clang::Decl *decl, const std::string &return_type_name) const
|
||||||
|
{
|
||||||
|
if (const auto *template_decl =
|
||||||
|
llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(decl);
|
||||||
|
template_decl && return_type_name.find("type-parameter-") == 0) {
|
||||||
|
|
||||||
|
[[maybe_unused]] const auto [depth, index] =
|
||||||
|
common::extract_template_parameter_index(return_type_name);
|
||||||
|
|
||||||
|
std::string param_name = return_type_name;
|
||||||
|
|
||||||
|
for (auto i = 0U;
|
||||||
|
i < template_decl->getDescribedTemplateParams()->size(); i++) {
|
||||||
|
const auto *param =
|
||||||
|
template_decl->getDescribedTemplateParams()->getParam(i);
|
||||||
|
|
||||||
|
if (i == index) {
|
||||||
|
param_name = param->getNameAsString();
|
||||||
|
|
||||||
|
auto template_param =
|
||||||
|
template_parameter::make_template_type(param_name);
|
||||||
|
|
||||||
|
template_param.is_variadic(param->isParameterPack());
|
||||||
|
|
||||||
|
return template_param;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
template_parameter translation_unit_visitor::
|
template_parameter translation_unit_visitor::
|
||||||
build_template_instantiation_process_integral_argument(
|
build_template_instantiation_process_integral_argument(
|
||||||
const clang::TemplateArgument &arg) const
|
const clang::TemplateArgument &arg) const
|
||||||
@@ -2690,8 +2854,8 @@ void translation_unit_visitor::process_field(
|
|||||||
!field_type_is_template_template_parameter) {
|
!field_type_is_template_template_parameter) {
|
||||||
|
|
||||||
// Build the template instantiation for the field type
|
// Build the template instantiation for the field type
|
||||||
auto template_specialization_ptr =
|
auto template_specialization_ptr = build_template_instantiation(
|
||||||
build_template_instantiation(*template_field_type, {&c});
|
&field_declaration, *template_field_type, {&c});
|
||||||
|
|
||||||
if (!field.skip_relationship() && template_specialization_ptr) {
|
if (!field.skip_relationship() && template_specialization_ptr) {
|
||||||
const auto &template_specialization = *template_specialization_ptr;
|
const auto &template_specialization = *template_specialization_ptr;
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ private:
|
|||||||
bool break_on_first_aggregation = false);
|
bool break_on_first_aggregation = false);
|
||||||
|
|
||||||
std::unique_ptr<clanguml::class_diagram::model::class_>
|
std::unique_ptr<clanguml::class_diagram::model::class_>
|
||||||
build_template_instantiation(
|
build_template_instantiation(const clang::Decl *cls,
|
||||||
const clang::TemplateSpecializationType &template_type,
|
const clang::TemplateSpecializationType &template_type,
|
||||||
std::optional<clanguml::class_diagram::model::class_ *> parent = {});
|
std::optional<clanguml::class_diagram::model::class_ *> parent = {});
|
||||||
|
|
||||||
@@ -205,6 +205,7 @@ private:
|
|||||||
|
|
||||||
void build_template_instantiation_process_template_arguments(
|
void build_template_instantiation_process_template_arguments(
|
||||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||||
|
const clang::Decl *cls,
|
||||||
std::deque<std::tuple<std::string, int, bool>> &template_base_params,
|
std::deque<std::tuple<std::string, int, bool>> &template_base_params,
|
||||||
const clang::ArrayRef<clang::TemplateArgument> &template_args,
|
const clang::ArrayRef<clang::TemplateArgument> &template_args,
|
||||||
model::class_ &template_instantiation,
|
model::class_ &template_instantiation,
|
||||||
@@ -226,6 +227,7 @@ private:
|
|||||||
|
|
||||||
template_parameter build_template_instantiation_process_type_argument(
|
template_parameter build_template_instantiation_process_type_argument(
|
||||||
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
std::optional<clanguml::class_diagram::model::class_ *> &parent,
|
||||||
|
const clang::Decl *cls,
|
||||||
const std::string &full_template_specialization_name,
|
const std::string &full_template_specialization_name,
|
||||||
const clang::TemplateDecl *template_decl,
|
const clang::TemplateDecl *template_decl,
|
||||||
const clang::TemplateArgument &arg,
|
const clang::TemplateArgument &arg,
|
||||||
@@ -240,7 +242,7 @@ private:
|
|||||||
void process_record_parent(
|
void process_record_parent(
|
||||||
clang::RecordDecl *cls, class_ &c, const namespace_ &ns);
|
clang::RecordDecl *cls, class_ &c, const namespace_ &ns);
|
||||||
|
|
||||||
void process_function_parameter_find_relatinoships_in_autotype(
|
void process_function_parameter_find_relationships_in_autotype(
|
||||||
model::class_ &c, const clang::AutoType *atsp);
|
model::class_ &c, const clang::AutoType *atsp);
|
||||||
|
|
||||||
void process_function_parameter_find_relationships_in_template(
|
void process_function_parameter_find_relationships_in_template(
|
||||||
@@ -279,6 +281,10 @@ private:
|
|||||||
std::vector<std::string> &constrained_template_params,
|
std::vector<std::string> &constrained_template_params,
|
||||||
size_t argument_index, std::string &type_name) const;
|
size_t argument_index, std::string &type_name) const;
|
||||||
|
|
||||||
|
std::optional<template_parameter>
|
||||||
|
get_template_argument_from_type_parameter_string(
|
||||||
|
const clang::Decl *decl, const std::string &return_type_name) const;
|
||||||
|
|
||||||
/// Store the mapping from local clang entity id (obtained using
|
/// Store the mapping from local clang entity id (obtained using
|
||||||
/// getID()) method to clang-uml global id
|
/// getID()) method to clang-uml global id
|
||||||
void set_ast_local_id(
|
void set_ast_local_id(
|
||||||
|
|||||||
@@ -250,6 +250,19 @@ std::string get_source_text(
|
|||||||
return get_source_text_raw(printable_range, sm);
|
return get_source_text_raw(printable_range, sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<unsigned int, unsigned int> extract_template_parameter_index(
|
||||||
|
const std::string &type_parameter)
|
||||||
|
{
|
||||||
|
assert(type_parameter.find("type-parameter-") == 0);
|
||||||
|
|
||||||
|
auto toks =
|
||||||
|
util::split(type_parameter.substr(strlen("type-parameter-")), "-");
|
||||||
|
|
||||||
|
assert(toks.size() == 2);
|
||||||
|
|
||||||
|
return {std::stoi(toks.at(0)), std::stoi(toks.at(1))};
|
||||||
|
}
|
||||||
|
|
||||||
bool is_subexpr_of(const clang::Stmt *parent_stmt, const clang::Stmt *sub_stmt)
|
bool is_subexpr_of(const clang::Stmt *parent_stmt, const clang::Stmt *sub_stmt)
|
||||||
{
|
{
|
||||||
if (parent_stmt == nullptr || sub_stmt == nullptr)
|
if (parent_stmt == nullptr || sub_stmt == nullptr)
|
||||||
|
|||||||
@@ -95,6 +95,9 @@ std::string get_source_text_raw(
|
|||||||
std::string get_source_text(
|
std::string get_source_text(
|
||||||
clang::SourceRange range, const clang::SourceManager &sm);
|
clang::SourceRange range, const clang::SourceManager &sm);
|
||||||
|
|
||||||
|
std::pair<unsigned int, unsigned int> extract_template_parameter_index(
|
||||||
|
const std::string &type_parameter);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if an expression is contained in another expression
|
* @brief Check if an expression is contained in another expression
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -111,6 +111,11 @@ bool template_parameter::is_variadic() const noexcept { return is_variadic_; }
|
|||||||
bool template_parameter::is_specialization_of(
|
bool template_parameter::is_specialization_of(
|
||||||
const template_parameter &ct) const
|
const template_parameter &ct) const
|
||||||
{
|
{
|
||||||
|
if(is_function_template() && ct.is_function_template()) {
|
||||||
|
bool res{true};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return (ct.is_template_parameter() ||
|
return (ct.is_template_parameter() ||
|
||||||
ct.is_template_template_parameter()) &&
|
ct.is_template_template_parameter()) &&
|
||||||
!is_template_parameter();
|
!is_template_parameter();
|
||||||
@@ -139,6 +144,9 @@ bool operator==(const template_parameter &l, const template_parameter &r)
|
|||||||
if (l.is_template_parameter() != r.is_template_parameter())
|
if (l.is_template_parameter() != r.is_template_parameter())
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
if (l.is_function_template() != r.is_function_template())
|
||||||
|
return res;
|
||||||
|
|
||||||
if (l.is_template_parameter()) {
|
if (l.is_template_parameter()) {
|
||||||
// If this is a template parameter (e.g. 'typename T' or 'typename U'
|
// If this is a template parameter (e.g. 'typename T' or 'typename U'
|
||||||
// we don't actually care what it is called
|
// we don't actually care what it is called
|
||||||
@@ -165,6 +173,19 @@ std::string template_parameter::to_string(
|
|||||||
|
|
||||||
assert(!(type().has_value() && concept_constraint().has_value()));
|
assert(!(type().has_value() && concept_constraint().has_value()));
|
||||||
|
|
||||||
|
if (is_function_template()) {
|
||||||
|
auto it = template_params_.begin();
|
||||||
|
auto return_type = it->to_string(using_namespace, relative);
|
||||||
|
std::advance(it, 1);
|
||||||
|
|
||||||
|
std::vector<std::string> function_args;
|
||||||
|
for (; it != template_params_.end(); it++)
|
||||||
|
function_args.push_back(it->to_string(using_namespace, relative));
|
||||||
|
|
||||||
|
return fmt::format(
|
||||||
|
"{}({})", return_type, fmt::join(function_args, ","));
|
||||||
|
}
|
||||||
|
|
||||||
std::string res;
|
std::string res;
|
||||||
const auto maybe_type = type();
|
const auto maybe_type = type();
|
||||||
if (maybe_type) {
|
if (maybe_type) {
|
||||||
|
|||||||
@@ -176,6 +176,10 @@ public:
|
|||||||
|
|
||||||
void set_unexposed(bool unexposed) { is_unexposed_ = unexposed; }
|
void set_unexposed(bool unexposed) { is_unexposed_ = unexposed; }
|
||||||
|
|
||||||
|
void set_function_template(bool ft) { is_function_template_ = ft; }
|
||||||
|
|
||||||
|
bool is_function_template() const { return is_function_template_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template_parameter() = default;
|
template_parameter() = default;
|
||||||
|
|
||||||
@@ -202,11 +206,14 @@ private:
|
|||||||
/// Whether the template parameter is variadic
|
/// Whether the template parameter is variadic
|
||||||
bool is_variadic_{false};
|
bool is_variadic_{false};
|
||||||
|
|
||||||
|
bool is_function_template_{false};
|
||||||
|
|
||||||
/// Stores optional fully qualified name of constraint for this template
|
/// Stores optional fully qualified name of constraint for this template
|
||||||
/// parameter
|
/// parameter
|
||||||
std::optional<std::string> concept_constraint_;
|
std::optional<std::string> concept_constraint_;
|
||||||
|
|
||||||
// Nested template parameters
|
// Nested template parameters
|
||||||
|
// If this is a function template, the first element is the return type
|
||||||
std::vector<template_parameter> template_params_;
|
std::vector<template_parameter> template_params_;
|
||||||
|
|
||||||
std::optional<int64_t> id_;
|
std::optional<int64_t> id_;
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ sink(signal_handler<Ret(Args...), A> &)
|
|||||||
|
|
||||||
signal_handler<void(int), bool> int_handler;
|
signal_handler<void(int), bool> int_handler;
|
||||||
|
|
||||||
sink sink1{int_handler};
|
struct R {
|
||||||
|
sink<signal_handler<void(int), bool>> sink1{int_handler};
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace clanguml::t00044
|
} // namespace clanguml::t00044
|
||||||
|
|||||||
@@ -35,10 +35,28 @@ TEST_CASE("t00044", "[test-case][class]")
|
|||||||
REQUIRE_THAT(puml, StartsWith("@startuml"));
|
REQUIRE_THAT(puml, StartsWith("@startuml"));
|
||||||
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
|
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
|
||||||
|
|
||||||
// TODO:
|
REQUIRE_THAT(puml, IsClassTemplate("sink", "T"));
|
||||||
// Check dependants filter<void(int), bool>
|
REQUIRE_THAT(puml, IsClassTemplate("signal_handler", "T,A"));
|
||||||
// REQUIRE_THAT(puml, IsClassTemplate("signal_handler",
|
|
||||||
// "Ret,Args...,A"));
|
REQUIRE_THAT(puml, IsClassTemplate("signal_handler", "Ret(Args...),A"));
|
||||||
|
REQUIRE_THAT(puml, IsClassTemplate("signal_handler", "void(int),bool"));
|
||||||
|
|
||||||
|
REQUIRE_THAT(puml,
|
||||||
|
IsClassTemplate(
|
||||||
|
"sink", "clanguml::t00044::signal_handler<Ret(Args...),A>"));
|
||||||
|
|
||||||
|
REQUIRE_THAT(puml,
|
||||||
|
IsInstantiation(_A("sink<T>"),
|
||||||
|
_A("sink<clanguml::t00044::signal_handler<Ret(Args...),A>>")));
|
||||||
|
|
||||||
|
REQUIRE_THAT(puml, IsClassTemplate("signal_handler", "T,A"));
|
||||||
|
REQUIRE_THAT(puml,
|
||||||
|
IsInstantiation(_A("signal_handler<T,A>"),
|
||||||
|
_A("signal_handler<Ret(Args...),A>")));
|
||||||
|
|
||||||
|
REQUIRE_THAT(puml,
|
||||||
|
IsInstantiation(_A("signal_handler<Ret(Args...),A>"),
|
||||||
|
_A("signal_handler<void(int),bool>")));
|
||||||
|
|
||||||
save_puml(
|
save_puml(
|
||||||
config.output_directory() + "/" + diagram->name + ".puml", puml);
|
config.output_directory() + "/" + diagram->name + ".puml", puml);
|
||||||
|
|||||||
Reference in New Issue
Block a user