Added nontype variadic instantiation support

This commit is contained in:
Bartek Kryza
2021-03-14 10:53:10 +01:00
parent 2033ca29c0
commit 0fc862332a
5 changed files with 87 additions and 9 deletions

View File

@@ -266,6 +266,40 @@ public:
return res;
}
std::vector<std::string> tokenize_template_parameters() const
{
const auto &toks = tokenize();
std::vector<std::string> res;
bool inside_template{false};
bool is_namespace{false};
for (const auto &tok : toks) {
auto t = clanguml::util::trim(tok);
if (t == ">") {
break;
}
if (inside_template) {
if (t == ",")
continue;
if (t == "::") {
is_namespace = true;
res.back() += t;
}
else if (is_namespace) {
is_namespace = false;
res.back() += t;
}
else {
res.push_back(t);
}
}
if (t == "<") {
inside_template = true;
}
}
return res;
}
const CXCursor &get() const { return m_cursor; }
private:

View File

@@ -69,6 +69,8 @@ public:
return clang_isRestrictQualifiedType(m_type);
}
bool is_invalid() const { return kind() == CXType_Invalid; }
std::string typedef_name() const
{
return to_string(clang_getTypedefName(m_type));

View File

@@ -345,13 +345,18 @@ static enum CXChildVisitResult class_visitor(
ret = CXChildVisit_Continue;
} break;
case CXCursor_NonTypeTemplateParameter: {
spdlog::info("Found template nontype parameter: {}: {}",
cursor.spelling(), cursor.type());
spdlog::info(
"Found template nontype parameter: {}: {}, isvariadic={}",
cursor.spelling(), cursor.type(),
cursor.is_template_parameter_variadic());
class_template ct;
ct.type = cursor.type().canonical().spelling();
ct.name = cursor.spelling();
ct.default_value = "";
ct.is_variadic = cursor.is_template_parameter_variadic();
if (ct.is_variadic)
ct.name += "...";
ctx->element.templates.emplace_back(std::move(ct));
ret = CXChildVisit_Continue;
@@ -456,13 +461,38 @@ static enum CXChildVisitResult class_visitor(
else {
tinst.usr = tr.type_declaration().usr();
}
for (int i = 0; i < tr.template_arguments_count();
i++) {
class_template ct;
ct.type =
tr.template_argument_type(i).spelling();
tinst.templates.emplace_back(std::move(ct));
if (!tr.template_argument_type(0).is_invalid()) {
for (int i = 0;
i < tr.template_arguments_count(); i++) {
auto template_param =
tr.template_argument_type(i);
class_template ct;
ct.type = template_param.spelling();
tinst.templates.emplace_back(std::move(ct));
spdlog::info(
"Adding template argument '{}'",
template_param);
}
}
else {
const auto &instantiation_params =
cursor.tokenize_template_parameters();
for (const auto &template_param :
instantiation_params) {
class_template ct;
ct.type = template_param;
tinst.templates.emplace_back(std::move(ct));
spdlog::info(
"Adding template argument '{}'",
template_param);
}
}
if (partial_specialization) {
tinst.base_template_usr = template_type.usr();
}
@@ -496,7 +526,6 @@ static enum CXChildVisitResult class_visitor(
}
}
if (!added_relation_to_instantiation) {
relationship_t relationship_type =
relationship_t::kNone;

View File

@@ -9,5 +9,17 @@ template <typename T, typename... Ts> class A {
T value;
std::variant<Ts...> values;
};
template <int... Is> class B {
std::array<int, sizeof...(Is)> ints;
};
class R {
A<int, std::string, float> a1;
A<int, std::string, bool> a2;
B<3, 2, 1> b1;
B<1, 1, 1, 1> b2;
};
}
}

View File

@@ -45,6 +45,7 @@ TEST_CASE("Test t00012", "[unit-test]")
REQUIRE_THAT(puml, StartsWith("@startuml"));
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
REQUIRE_THAT(puml, IsClassTemplate("A", "T, Ts..."));
REQUIRE_THAT(puml, IsClassTemplate("B", "int Is..."));
save_puml(
"./" + config.output_directory + "/" + diagram->name + ".puml", puml);