From 3e4beef80bf2884e034dfe7d4c58c3c5376f01d7 Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Sun, 24 Jul 2022 23:46:52 +0200 Subject: [PATCH] Fixed building main --- src/class_diagram/model/diagram.cc | 2 +- .../visitor/translation_unit_visitor.cc | 74 ++++++++++++++++--- .../visitor/translation_unit_visitor.h | 8 ++ src/common/generators/plantuml/generator.h | 2 + src/common/model/diagram_filter.cc | 3 +- .../visitor/translation_unit_visitor.h | 1 + src/main.cc | 18 ++++- .../visitor/translation_unit_visitor.h | 2 +- .../visitor/translation_unit_visitor.h | 1 + tests/t00038/t00038.cc | 2 +- 10 files changed, 93 insertions(+), 20 deletions(-) diff --git a/src/class_diagram/model/diagram.cc b/src/class_diagram/model/diagram.cc index 5daf3fb3..00d71c14 100644 --- a/src/class_diagram/model/diagram.cc +++ b/src/class_diagram/model/diagram.cc @@ -204,7 +204,7 @@ void diagram::get_parents( bool found_new{false}; for (const auto &parent : parents) { for (const auto &pp : parent.get().parents()) { - const auto p = get_class(pp.name()); + const auto p = get_class(pp.id()); if (p.has_value()) { auto [it, found] = parents.emplace(p.value()); if (found) diff --git a/src/class_diagram/visitor/translation_unit_visitor.cc b/src/class_diagram/visitor/translation_unit_visitor.cc index 640f5842..9b0912f3 100644 --- a/src/class_diagram/visitor/translation_unit_visitor.cc +++ b/src/class_diagram/visitor/translation_unit_visitor.cc @@ -233,12 +233,17 @@ bool translation_unit_visitor::VisitClassTemplateSpecializationDecl( return true; // Skip forward declarations - if (!cls->isCompleteDefinition()) + if (!cls->isCompleteDefinition()) { + // Register this forward declaration in case there is no complete + // definition (see t00036) return true; + } + else - // Check if the class was already processed within VisitClassTemplateDecl() - if (diagram_.has_element(cls->getID())) - return true; + // Check if the class was already processed within + // VisitClassTemplateDecl() + if (diagram_.has_element(cls->getID())) + return true; // TODO: Add support for classes defined in function/method bodies if (cls->isLocalClass()) @@ -253,6 +258,9 @@ bool translation_unit_visitor::VisitClassTemplateSpecializationDecl( process_template_specialization_children(cls, template_specialization); + // Process template specialization bases + process_class_bases(cls, template_specialization); + template_specialization.add_relationship({relationship_t::kInstantiation, cls->getSpecializedTemplate()->getID()}); @@ -269,6 +277,10 @@ bool translation_unit_visitor::VisitClassTemplateDecl( if (source_manager_.isInSystemHeader(cls->getSourceRange().getBegin())) return true; + // Skip forward declarations + if (!cls->getTemplatedDecl()->isCompleteDefinition()) + return true; + auto c_ptr = process_class_declaration(cls->getTemplatedDecl()); if (!c_ptr) @@ -278,8 +290,17 @@ bool translation_unit_visitor::VisitClassTemplateDecl( // underlying templated class id c_ptr->set_id(cls->getID()); + auto id = c_ptr->id(); + process_template_parameters(*cls, *c_ptr); + if(!cls->getTemplatedDecl()->isCompleteDefinition()) { + forward_declarations_.emplace(id, std::move(c_ptr)); + return true; + } + else + forward_declarations_.erase(id); + if (diagram_.should_include(*c_ptr)) { LOG_DBG("Adding class {} with id {}", c_ptr->full_name(), c_ptr->id()); diagram_.add_class(std::move(c_ptr)); @@ -298,10 +319,6 @@ bool translation_unit_visitor::VisitCXXRecordDecl(clang::CXXRecordDecl *cls) if (cls->isTemplated() || cls->isTemplateDecl()) return true; - // Skip forward declarations - if (!cls->isCompleteDefinition()) - return true; - // Check if the class was already processed within VisitClassTemplateDecl() if (diagram_.has_element(cls->getID())) return true; @@ -315,6 +332,14 @@ bool translation_unit_visitor::VisitCXXRecordDecl(clang::CXXRecordDecl *cls) if (!c_ptr) return true; + auto id = c_ptr->id(); + if(!cls->isCompleteDefinition()) { + forward_declarations_.emplace(id, std::move(c_ptr)); + return true; + } + else + forward_declarations_.erase(id); + if (diagram_.should_include(*c_ptr)) { diagram_.add_class(std::move(c_ptr)); } @@ -349,6 +374,9 @@ std::unique_ptr translation_unit_visitor::process_class_declaration( c.set_style(c.style_spec()); + if (!cls->isCompleteDefinition()) + return c_ptr; + // Process class child entities process_class_children(cls, c); @@ -597,7 +625,8 @@ void translation_unit_visitor::process_class_children( } for (const auto *friend_declaration : cls->friends()) { - process_friend(*friend_declaration, c); + if (friend_declaration != nullptr) + process_friend(*friend_declaration, c); } } @@ -947,7 +976,6 @@ translation_unit_visitor::process_template_specialization( // If this is a nested template type - add nested templates as // template arguments if (arg.getAsType()->getAs()) { - const auto *nested_template_type = arg.getAsType()->getAs(); @@ -973,8 +1001,17 @@ translation_unit_visitor::process_template_specialization( argument.to_string(config().using_namespace(), false)); } else { - argument.set_name( - to_string(arg.getAsType(), cls->getASTContext())); + auto type_name = + to_string(arg.getAsType(), cls->getASTContext()); + // Sometimes template instantiation is reported as RecordType in + // the AST and getAs to TemplateSpecializationType returns null + // pointer so we have to at least make sure it's properly + // formatted + // TODO: Change this to manual parsing of the template + // instantiation + if (type_name.find('<') != std::string::npos) + util::replace_all(type_name, ", ", ","); + argument.set_name(type_name); } template_instantiation.add_template(std::move(argument)); @@ -1210,6 +1247,19 @@ void translation_unit_visitor::set_source_location( } } +void translation_unit_visitor::add_incomplete_forward_declarations() { + for(auto & [id, c] : forward_declarations_) { + if(diagram().should_include(c->full_name(false))) { + diagram().add_class(std::move(c)); + } + } + forward_declarations_.clear(); +} + +void translation_unit_visitor::finalize() { + add_incomplete_forward_declarations(); +} + bool translation_unit_visitor::simplify_system_template( template_parameter &ct, const std::string &full_name) { diff --git a/src/class_diagram/visitor/translation_unit_visitor.h b/src/class_diagram/visitor/translation_unit_visitor.h index bd447f4b..25f513cc 100644 --- a/src/class_diagram/visitor/translation_unit_visitor.h +++ b/src/class_diagram/visitor/translation_unit_visitor.h @@ -63,6 +63,8 @@ public: // void operator()(); + void finalize(); + private: std::unique_ptr process_class_declaration(clang::CXXRecordDecl *cls); @@ -143,6 +145,8 @@ private: } } + void add_incomplete_forward_declarations(); + bool simplify_system_template( model::template_parameter &ct, const std::string &full_name); @@ -153,5 +157,9 @@ private: // Reference to class diagram config const clanguml::config::class_diagram &config_; + + std::map> + forward_declarations_; }; } diff --git a/src/common/generators/plantuml/generator.h b/src/common/generators/plantuml/generator.h index 79f64a82..421910be 100644 --- a/src/common/generators/plantuml/generator.h +++ b/src/common/generators/plantuml/generator.h @@ -260,6 +260,7 @@ public: // const auto* tud = ast_context.getTranslationUnitDecl(); //// tud->dump(); visitor_.TraverseDecl(ast_context.getTranslationUnitDecl()); + visitor_.finalize(); } }; @@ -273,6 +274,7 @@ public: , config_{config} { } + virtual std::unique_ptr CreateASTConsumer( clang::CompilerInstance &CI, clang::StringRef file) { diff --git a/src/common/model/diagram_filter.cc b/src/common/model/diagram_filter.cc index 65612561..1dec64dd 100644 --- a/src/common/model/diagram_filter.cc +++ b/src/common/model/diagram_filter.cc @@ -237,7 +237,8 @@ tvl::value_t subclass_filter::match(const diagram &d, const element &e) const // filter config for (const auto &root : roots_) { for (const auto &parent : parents) { - if (root == parent.get().full_name(false)) + auto full_name = parent.get().full_name(false); + if (root == full_name) return true; } } diff --git a/src/include_diagram/visitor/translation_unit_visitor.h b/src/include_diagram/visitor/translation_unit_visitor.h index 9a488889..6a1541ce 100644 --- a/src/include_diagram/visitor/translation_unit_visitor.h +++ b/src/include_diagram/visitor/translation_unit_visitor.h @@ -42,6 +42,7 @@ public: void operator()(const cppast::cpp_entity &file); + void finalize() {} private: clang::SourceManager &source_manager_; diff --git a/src/main.cc b/src/main.cc index 367565ff..c1a3633a 100644 --- a/src/main.cc +++ b/src/main.cc @@ -46,7 +46,7 @@ bool check_output_directory(const std::string &dir); void generate_diagram(const std::string &od, const std::string &name, std::shared_ptr diagram, - const cppast::libclang_compilation_database &db, bool verbose); + const clang::tooling::CompilationDatabase &db, bool verbose); int main(int argc, const char *argv[]) { @@ -104,7 +104,17 @@ int main(int argc, const char *argv[]) LOG_INFO("Loading compilation database from {} directory", config.compilation_database_dir()); - cppast::libclang_compilation_database db{config.compilation_database_dir()}; + std::string err{}; + + auto db = + clang::tooling::CompilationDatabase::autoDetectFromDirectory( + config.compilation_database_dir(), err); + + if (!err.empty()) { + LOG_ERROR("Failed to load compilation database from {}", + config.compilation_database_dir()); + return 1; + } auto od = config.output_directory(); if (output_directory) @@ -124,7 +134,7 @@ int main(int argc, const char *argv[]) futs.emplace_back(generator_executor.add( [&od, &name = name, &diagram = diagram, &db = db, verbose]() { - generate_diagram(od, name, diagram, db, verbose); + generate_diagram(od, name, diagram, *db, verbose); })); } @@ -137,7 +147,7 @@ int main(int argc, const char *argv[]) void generate_diagram(const std::string &od, const std::string &name, std::shared_ptr diagram, - const cppast::libclang_compilation_database &db, bool verbose) + const clang::tooling::CompilationDatabase &db, bool verbose) { using clanguml::common::model::diagram_t; using clanguml::config::class_diagram; diff --git a/src/package_diagram/visitor/translation_unit_visitor.h b/src/package_diagram/visitor/translation_unit_visitor.h index 8fbe9578..cddd657a 100644 --- a/src/package_diagram/visitor/translation_unit_visitor.h +++ b/src/package_diagram/visitor/translation_unit_visitor.h @@ -40,7 +40,7 @@ public: clanguml::package_diagram::model::diagram &diagram, const clanguml::config::package_diagram &config); - + void finalize() {} private: clang::SourceManager &source_manager_; diff --git a/src/sequence_diagram/visitor/translation_unit_visitor.h b/src/sequence_diagram/visitor/translation_unit_visitor.h index 67262772..b1ed7845 100644 --- a/src/sequence_diagram/visitor/translation_unit_visitor.h +++ b/src/sequence_diagram/visitor/translation_unit_visitor.h @@ -33,6 +33,7 @@ public: clanguml::sequence_diagram::model::diagram &diagram, const clanguml::config::sequence_diagram &config); + void finalize() {} private: clang::SourceManager &source_manager_; diff --git a/tests/t00038/t00038.cc b/tests/t00038/t00038.cc index e33b091e..05a96b56 100644 --- a/tests/t00038/t00038.cc +++ b/tests/t00038/t00038.cc @@ -32,7 +32,7 @@ struct key_t { std::string key; }; -template struct map; +template struct map {}; using namespace thirdparty::ns1;