Added case handling of template argument kinds

This commit is contained in:
Bartek Kryza
2023-04-15 11:48:21 +02:00
parent 0d524b38a4
commit f034b554de
2 changed files with 285 additions and 215 deletions

View File

@@ -2370,27 +2370,48 @@ void translation_unit_visitor::
{ {
auto arg_index = 0; auto arg_index = 0;
for (const auto &arg : template_args) { for (const auto &arg : template_args) {
const auto argument_kind = arg.getKind(); // Argument can be a parameter pack in which case it gives multiple
std::optional<template_parameter> argument; // arguments
if (argument_kind == clang::TemplateArgument::Template) { std::vector<template_parameter> argument;
argument =
build_template_instantiation_process_template_argument(arg); switch (arg.getKind()) {
case clang::TemplateArgument::Null:
argument.push_back(
build_template_instantiation_process_null_argument(arg));
break;
case clang::TemplateArgument::Type:
argument.push_back(
build_template_instantiation_process_type_argument(parent, cls,
full_template_specialization_name, template_decl, arg,
template_instantiation));
break;
case clang::TemplateArgument::Declaration:
break;
case clang::TemplateArgument::NullPtr:
argument.push_back(
build_template_instantiation_process_nullptr_argument(arg));
break;
case clang::TemplateArgument::Integral:
argument.push_back(
build_template_instantiation_process_integral_argument(arg));
break;
case clang::TemplateArgument::Template:
argument.push_back(
build_template_instantiation_process_template_argument(arg));
break;
case clang::TemplateArgument::TemplateExpansion:
break;
case clang::TemplateArgument::Expression:
argument.push_back(
build_template_instantiation_process_expression_argument(arg));
break;
case clang::TemplateArgument::Pack:
build_template_instantiation_process_pack_argument(arg, argument));
break;
} }
else if (argument_kind == clang::TemplateArgument::Type) {
argument = build_template_instantiation_process_type_argument( if (argument.empty()) {
parent, cls, full_template_specialization_name, template_decl, arg_index++;
arg, template_instantiation);
}
else if (argument_kind == clang::TemplateArgument::Integral) {
argument =
build_template_instantiation_process_integral_argument(arg);
}
else if (argument_kind == clang::TemplateArgument::Expression) {
argument =
build_template_instantiation_process_expression_argument(arg);
}
else {
LOG_ERROR("Unsupported argument type {}", arg.getKind());
continue; continue;
} }
@@ -2405,18 +2426,20 @@ void translation_unit_visitor::
if (!template_base_params.empty()) { if (!template_base_params.empty()) {
variadic_params = build_template_instantiation_add_base_classes( variadic_params = build_template_instantiation_add_base_classes(
template_instantiation, template_base_params, arg_index, template_instantiation, template_base_params, arg_index,
variadic_params, argument.value()); variadic_params, argument.front());
} }
for (auto &arg : argument) {
simplify_system_template(
arg, arg.to_string(config().using_namespace(), false));
LOG_DBG("Adding template argument {} to template " LOG_DBG("Adding template argument {} to template "
"specialization/instantiation {}", "specialization/instantiation {}",
argument.value().to_string(config().using_namespace(), false), arg.to_string(config().using_namespace(), false),
template_instantiation.name()); template_instantiation.name());
simplify_system_template(argument.value(), template_instantiation.add_template(std::move(arg));
argument.value().to_string(config().using_namespace(), false)); }
template_instantiation.add_template(std::move(argument.value()));
arg_index++; arg_index++;
} }
@@ -2468,7 +2491,8 @@ translation_unit_visitor::build_template_instantiation_process_type_argument(
// Set function template argument types // Set function template argument types
for (const auto &param_type : function_type->param_types()) { for (const auto &param_type : function_type->param_types()) {
auto maybe_arg = get_template_argument_from_type_parameter_string( auto maybe_arg =
get_template_argument_from_type_parameter_string(
cls, param_type.getAsString()); cls, param_type.getAsString());
if (maybe_arg) { if (maybe_arg) {
@@ -2477,7 +2501,8 @@ translation_unit_visitor::build_template_instantiation_process_type_argument(
} }
if (param_type->isBuiltinType()) { if (param_type->isBuiltinType()) {
argument.add_template_param(template_parameter::make_argument( argument.add_template_param(
template_parameter::make_argument(
param_type.getAsString())); param_type.getAsString()));
continue; continue;
} }
@@ -2559,7 +2584,8 @@ translation_unit_visitor::build_template_instantiation_process_type_argument(
if (nested_template_instantiation && if (nested_template_instantiation &&
diagram().should_include( diagram().should_include(
nested_template_instantiation->full_name(false))) { nested_template_instantiation->full_name(false))) {
if (diagram().should_include(full_template_specialization_name)) { if (diagram().should_include(
full_template_specialization_name)) {
template_instantiation.add_relationship( template_instantiation.add_relationship(
{relationship_t::kDependency, {relationship_t::kDependency,
nested_template_instantiation->id()}); nested_template_instantiation->id()});
@@ -2638,6 +2664,24 @@ template_parameter translation_unit_visitor::
std::to_string(arg.getAsIntegral().getExtValue())); std::to_string(arg.getAsIntegral().getExtValue()));
} }
template_parameter
translation_unit_visitor::build_template_instantiation_process_null_argument(
const clang::TemplateArgument &arg) const
{
assert(arg.getKind() == clang::TemplateArgument::Null);
return template_parameter::make_argument("");
}
template_parameter
translation_unit_visitor::build_template_instantiation_process_nullptr_argument(
const clang::TemplateArgument &arg) const
{
assert(arg.getKind() == clang::TemplateArgument::NullPtr);
return template_parameter::make_argument("nullptr");
}
template_parameter translation_unit_visitor:: template_parameter translation_unit_visitor::
build_template_instantiation_process_expression_argument( build_template_instantiation_process_expression_argument(
const clang::TemplateArgument &arg) const const clang::TemplateArgument &arg) const
@@ -2647,6 +2691,16 @@ template_parameter translation_unit_visitor::
arg.getAsExpr()->getSourceRange(), source_manager())); arg.getAsExpr()->getSourceRange(), source_manager()));
} }
template_parameter
translation_unit_visitor::build_template_instantiation_process_pack_argument(
const clang::TemplateArgument &arg) const
{
assert(arg.getKind() == clang::TemplateArgument::Pack);
arg.getPackAsArray().front().return template_parameter::make_argument(
std::to_string(arg.get));
}
void translation_unit_visitor:: void translation_unit_visitor::
build_template_instantiation_process_tag_argument( build_template_instantiation_process_tag_argument(
class_ &template_instantiation, class_ &template_instantiation,
@@ -2668,7 +2722,8 @@ void translation_unit_visitor::
record_type_decl != nullptr) { record_type_decl != nullptr) {
argument.set_id(common::to_id(arg)); argument.set_id(common::to_id(arg));
if (diagram().should_include(full_template_specialization_name)) { if (diagram().should_include(
full_template_specialization_name)) {
// Add dependency relationship to the parent // Add dependency relationship to the parent
// template // template
template_instantiation.add_relationship( template_instantiation.add_relationship(
@@ -2686,7 +2741,8 @@ void translation_unit_visitor::
#if LLVM_VERSION_MAJOR >= 16 #if LLVM_VERSION_MAJOR >= 16
argument.set_type(record_type_decl->getQualifiedNameAsString()); argument.set_type(record_type_decl->getQualifiedNameAsString());
#endif #endif
if (diagram().should_include(full_template_specialization_name)) { if (diagram().should_include(
full_template_specialization_name)) {
// Add dependency relationship to the parent // Add dependency relationship to the parent
// template // template
template_instantiation.add_relationship( template_instantiation.add_relationship(
@@ -2830,7 +2886,8 @@ void translation_unit_visitor::process_field(
&field_declaration, *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;
// Check if this template instantiation should be added to the // Check if this template instantiation should be added to the
// current diagram. Even if the top level template type for // current diagram. Even if the top level template type for
@@ -2859,7 +2916,8 @@ void translation_unit_visitor::process_field(
for (const auto &template_argument : for (const auto &template_argument :
template_specialization.template_params()) { template_specialization.template_params()) {
LOG_DBG("Looking for nested relationships from {}::{} in " LOG_DBG(
"Looking for nested relationships from {}::{} in "
"template {}", "template {}",
c.full_name(false), field_name, c.full_name(false), field_name,
template_argument.to_string( template_argument.to_string(
@@ -2871,7 +2929,8 @@ void translation_unit_visitor::process_field(
[&d = diagram()](const std::string &full_name) { [&d = diagram()](const std::string &full_name) {
if (full_name.empty()) if (full_name.empty())
return false; return false;
auto [ns, name] = common::split_ns(full_name); auto [ns, name] =
common::split_ns(full_name);
return d.should_include(ns, name); return d.should_include(ns, name);
}); });
} }
@@ -2897,10 +2956,10 @@ void translation_unit_visitor::process_field(
field_type->getAsRecordDecl()->getNameAsString().empty()) { field_type->getAsRecordDecl()->getNameAsString().empty()) {
// Relationships to fields whose type is an anonymous nested // Relationships to fields whose type is an anonymous nested
// struct have to be handled separately here // struct have to be handled separately here
anonymous_struct_relationships_[field_type->getAsRecordDecl() anonymous_struct_relationships_
->getID()] = [field_type->getAsRecordDecl()->getID()] =
std::make_tuple( std::make_tuple(field.name(), relationship_hint,
field.name(), relationship_hint, field.access()); field.access());
} }
else else
find_relationships( find_relationships(
@@ -2932,7 +2991,8 @@ void translation_unit_visitor::resolve_local_to_global_ids()
if (rel.type() == relationship_t::kInstantiation) { if (rel.type() == relationship_t::kInstantiation) {
const auto maybe_id = get_ast_local_id(rel.destination()); const auto maybe_id = get_ast_local_id(rel.destination());
if (maybe_id) { if (maybe_id) {
LOG_DBG("= Resolved instantiation destination from local " LOG_DBG(
"= Resolved instantiation destination from local "
"id {} to global id {}", "id {} to global id {}",
rel.destination(), *maybe_id); rel.destination(), *maybe_id);
rel.set_destination(*maybe_id); rel.set_destination(*maybe_id);
@@ -3002,7 +3062,8 @@ void translation_unit_visitor::extract_constrained_template_param_name(
if (!full_declaration_text.empty()) { if (!full_declaration_text.empty()) {
// Handle typename constraint in requires clause // Handle typename constraint in requires clause
if (type_name.find("type-parameter-") == 0) { if (type_name.find("type-parameter-") == 0) {
const auto concept_declaration_text = full_declaration_text.substr( const auto concept_declaration_text =
full_declaration_text.substr(
full_declaration_text.find(cpt->getNameAsString()) + full_declaration_text.find(cpt->getNameAsString()) +
cpt->getNameAsString().size() + 1); cpt->getNameAsString().size() + 1);

View File

@@ -225,6 +225,15 @@ private:
template_parameter build_template_instantiation_process_integral_argument( template_parameter build_template_instantiation_process_integral_argument(
const clang::TemplateArgument &arg) const; const clang::TemplateArgument &arg) const;
template_parameter build_template_instantiation_process_nullptr_argument(
const clang::TemplateArgument &arg) const;
template_parameter build_template_instantiation_process_null_argument(
const clang::TemplateArgument &arg) const;
template_parameter build_template_instantiation_process_pack_argument(
const clang::TemplateArgument &arg) const;
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 clang::Decl *cls,