Fixed handling of C99 typedef structs (#138)

This commit is contained in:
Bartek Kryza
2023-05-11 19:52:27 +02:00
parent 9a5a1523d9
commit 7e9944ce60
4 changed files with 25 additions and 7 deletions

View File

@@ -137,11 +137,9 @@ bool translation_unit_visitor::VisitEnumDecl(clang::EnumDecl *enm)
} }
} }
if (id_opt) { if (id_opt && diagram_.get_class(*id_opt)) {
auto parent_class = diagram_.get_class(*id_opt); auto parent_class = diagram_.get_class(*id_opt);
assert(parent_class);
e.set_namespace(ns); e.set_namespace(ns);
e.set_name(parent_class.value().name() + "##" + enm->getNameAsString()); e.set_name(parent_class.value().name() + "##" + enm->getNameAsString());
e.set_id(common::to_id(e.full_name(false))); e.set_id(common::to_id(e.full_name(false)));
@@ -696,6 +694,7 @@ bool translation_unit_visitor::VisitCXXRecordDecl(clang::CXXRecordDecl *cls)
LOG_DBG("== isTemplateDecl() = {}", cls->isTemplateDecl()); LOG_DBG("== isTemplateDecl() = {}", cls->isTemplateDecl());
LOG_DBG("== isTemplated() = {}", cls->isTemplated()); LOG_DBG("== isTemplated() = {}", cls->isTemplated());
LOG_DBG("== getParent()->isRecord()() = {}", cls->getParent()->isRecord()); LOG_DBG("== getParent()->isRecord()() = {}", cls->getParent()->isRecord());
if (const auto *parent_record = if (const auto *parent_record =
clang::dyn_cast<clang::RecordDecl>(cls->getParent()); clang::dyn_cast<clang::RecordDecl>(cls->getParent());
parent_record != nullptr) { parent_record != nullptr) {
@@ -799,7 +798,18 @@ std::unique_ptr<class_> translation_unit_visitor::create_record_declaration(
process_record_parent(rec, record, namespace_{}); process_record_parent(rec, record, namespace_{});
if (!record.is_nested()) { if (!record.is_nested()) {
record.set_name(common::get_tag_name(*rec)); auto record_name = rec->getQualifiedNameAsString();
#if LLVM_VERSION_MAJOR < 16
if (record_name == "(anonymous)") {
util::apply_if_not_null(rec->getTypedefNameForAnonDecl(),
[&record_name](const clang::TypedefNameDecl *name) {
record_name = name->getNameAsString();
});
}
#endif
record.set_name(record_name);
record.set_id(common::to_id(record.full_name(false))); record.set_id(common::to_id(record.full_name(false)));
} }
@@ -886,14 +896,12 @@ void translation_unit_visitor::process_record_parent(
} }
} }
if (id_opt) { if (id_opt && diagram_.get_class(*id_opt)) {
// Here we have 2 options, either: // Here we have 2 options, either:
// - the parent is a regular C++ class/struct // - the parent is a regular C++ class/struct
// - the parent is a class template declaration/specialization // - the parent is a class template declaration/specialization
auto parent_class = diagram_.get_class(*id_opt); auto parent_class = diagram_.get_class(*id_opt);
assert(parent_class);
c.set_namespace(parent_ns); c.set_namespace(parent_ns);
const auto cls_name = cls->getNameAsString(); const auto cls_name = cls->getNameAsString();
if (cls_name.empty()) { if (cls_name.empty()) {

View File

@@ -84,6 +84,7 @@ model::namespace_ get_template_namespace(const clang::TemplateDecl &declaration)
std::string get_tag_name(const clang::TagDecl &declaration) std::string get_tag_name(const clang::TagDecl &declaration)
{ {
auto base_name = declaration.getNameAsString(); auto base_name = declaration.getNameAsString();
if (base_name.empty()) { if (base_name.empty()) {
base_name = base_name =
fmt::format("(anonymous_{})", std::to_string(declaration.getID())); fmt::format("(anonymous_{})", std::to_string(declaration.getID()));

View File

@@ -29,6 +29,10 @@ struct t00057_E {
} height; } height;
}; };
typedef struct {
int g1;
} t00057_G;
struct t00057_R { struct t00057_R {
struct t00057_A a; struct t00057_A a;
t00057_B b; t00057_B b;
@@ -36,4 +40,5 @@ struct t00057_R {
union t00057_D d; union t00057_D d;
struct t00057_E *e; struct t00057_E *e;
struct t00057_F *f; struct t00057_F *f;
struct t00057_G *g;
}; };

View File

@@ -41,6 +41,8 @@ TEST_CASE("t00057", "[test-case][class]")
REQUIRE_THAT(puml, IsUnion(_A("t00057_D"))); REQUIRE_THAT(puml, IsUnion(_A("t00057_D")));
REQUIRE_THAT(puml, IsClass(_A("t00057_E"))); REQUIRE_THAT(puml, IsClass(_A("t00057_E")));
REQUIRE_THAT(puml, IsClass(_A("t00057_F"))); REQUIRE_THAT(puml, IsClass(_A("t00057_F")));
REQUIRE_THAT(puml, IsClass(_A("t00057_G")));
REQUIRE_THAT(puml, !IsClass(_A("(anonymous)")));
REQUIRE_THAT(puml, IsClass(_A("t00057_R"))); REQUIRE_THAT(puml, IsClass(_A("t00057_R")));
// Check if all relationships exist // Check if all relationships exist
@@ -70,6 +72,8 @@ TEST_CASE("t00057", "[test-case][class]")
REQUIRE(get_element(j, "t00057_C").value()["type"] == "class"); REQUIRE(get_element(j, "t00057_C").value()["type"] == "class");
REQUIRE(get_element(j, "t00057_D").value()["type"] == "class"); REQUIRE(get_element(j, "t00057_D").value()["type"] == "class");
REQUIRE(get_element(j, "t00057_E").value()["type"] == "class"); REQUIRE(get_element(j, "t00057_E").value()["type"] == "class");
REQUIRE(get_element(j, "t00057_F").value()["type"] == "class");
REQUIRE(get_element(j, "t00057_G").value()["type"] == "class");
REQUIRE(get_element(j, "t00057_R").value()["type"] == "class"); REQUIRE(get_element(j, "t00057_R").value()["type"] == "class");
save_json(config.output_directory() + "/" + diagram->name + ".json", j); save_json(config.output_directory() + "/" + diagram->name + ".json", j);