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;
for (const auto &arg : template_args) {
const auto argument_kind = arg.getKind();
std::optional<template_parameter> argument;
if (argument_kind == clang::TemplateArgument::Template) {
argument =
build_template_instantiation_process_template_argument(arg);
// Argument can be a parameter pack in which case it gives multiple
// arguments
std::vector<template_parameter> argument;
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(
parent, cls, full_template_specialization_name, template_decl,
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());
if (argument.empty()) {
arg_index++;
continue;
}
@@ -2405,18 +2426,20 @@ void translation_unit_visitor::
if (!template_base_params.empty()) {
variadic_params = build_template_instantiation_add_base_classes(
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 "
"specialization/instantiation {}",
argument.value().to_string(config().using_namespace(), false),
arg.to_string(config().using_namespace(), false),
template_instantiation.name());
simplify_system_template(argument.value(),
argument.value().to_string(config().using_namespace(), false));
template_instantiation.add_template(std::move(argument.value()));
template_instantiation.add_template(std::move(arg));
}
arg_index++;
}
@@ -2468,7 +2491,8 @@ translation_unit_visitor::build_template_instantiation_process_type_argument(
// Set function template argument 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());
if (maybe_arg) {
@@ -2477,7 +2501,8 @@ translation_unit_visitor::build_template_instantiation_process_type_argument(
}
if (param_type->isBuiltinType()) {
argument.add_template_param(template_parameter::make_argument(
argument.add_template_param(
template_parameter::make_argument(
param_type.getAsString()));
continue;
}
@@ -2559,7 +2584,8 @@ translation_unit_visitor::build_template_instantiation_process_type_argument(
if (nested_template_instantiation &&
diagram().should_include(
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(
{relationship_t::kDependency,
nested_template_instantiation->id()});
@@ -2638,6 +2664,24 @@ template_parameter translation_unit_visitor::
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::
build_template_instantiation_process_expression_argument(
const clang::TemplateArgument &arg) const
@@ -2647,6 +2691,16 @@ template_parameter translation_unit_visitor::
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::
build_template_instantiation_process_tag_argument(
class_ &template_instantiation,
@@ -2668,7 +2722,8 @@ void translation_unit_visitor::
record_type_decl != nullptr) {
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
// template
template_instantiation.add_relationship(
@@ -2686,7 +2741,8 @@ void translation_unit_visitor::
#if LLVM_VERSION_MAJOR >= 16
argument.set_type(record_type_decl->getQualifiedNameAsString());
#endif
if (diagram().should_include(full_template_specialization_name)) {
if (diagram().should_include(
full_template_specialization_name)) {
// Add dependency relationship to the parent
// template
template_instantiation.add_relationship(
@@ -2830,7 +2886,8 @@ void translation_unit_visitor::process_field(
&field_declaration, *template_field_type, {&c});
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
// 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 :
template_specialization.template_params()) {
LOG_DBG("Looking for nested relationships from {}::{} in "
LOG_DBG(
"Looking for nested relationships from {}::{} in "
"template {}",
c.full_name(false), field_name,
template_argument.to_string(
@@ -2871,7 +2929,8 @@ void translation_unit_visitor::process_field(
[&d = diagram()](const std::string &full_name) {
if (full_name.empty())
return false;
auto [ns, name] = common::split_ns(full_name);
auto [ns, name] =
common::split_ns(full_name);
return d.should_include(ns, name);
});
}
@@ -2897,10 +2956,10 @@ void translation_unit_visitor::process_field(
field_type->getAsRecordDecl()->getNameAsString().empty()) {
// Relationships to fields whose type is an anonymous nested
// struct have to be handled separately here
anonymous_struct_relationships_[field_type->getAsRecordDecl()
->getID()] =
std::make_tuple(
field.name(), relationship_hint, field.access());
anonymous_struct_relationships_
[field_type->getAsRecordDecl()->getID()] =
std::make_tuple(field.name(), relationship_hint,
field.access());
}
else
find_relationships(
@@ -2932,7 +2991,8 @@ void translation_unit_visitor::resolve_local_to_global_ids()
if (rel.type() == relationship_t::kInstantiation) {
const auto maybe_id = get_ast_local_id(rel.destination());
if (maybe_id) {
LOG_DBG("= Resolved instantiation destination from local "
LOG_DBG(
"= Resolved instantiation destination from local "
"id {} to global id {}",
rel.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()) {
// Handle typename constraint in requires clause
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()) +
cpt->getNameAsString().size() + 1);

View File

@@ -225,6 +225,15 @@ private:
template_parameter build_template_instantiation_process_integral_argument(
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(
std::optional<clanguml::class_diagram::model::class_ *> &parent,
const clang::Decl *cls,