Merge pull request #117 from bkryza/fix-building-on-llvm-16
Fix building on llvm 16 #108
This commit is contained in:
@@ -25,11 +25,6 @@ set(CMAKE_CXX_STANDARD 17)
|
|||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
if(APPLE)
|
|
||||||
set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES
|
|
||||||
${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
|
|
||||||
endif(APPLE)
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# clang-uml custom defines
|
# clang-uml custom defines
|
||||||
#
|
#
|
||||||
@@ -124,6 +119,11 @@ else()
|
|||||||
message(STATUS "Found LibTooling libraries: ${LIBTOOLING_LIBS}")
|
message(STATUS "Found LibTooling libraries: ${LIBTOOLING_LIBS}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(APPLE OR (LLVM_VERSION_MAJOR GREATER_EQUAL 16))
|
||||||
|
set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES
|
||||||
|
${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
#
|
#
|
||||||
# Setup threads library
|
# Setup threads library
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -34,8 +34,12 @@ common::model::access_t class_element::access() const { return access_; }
|
|||||||
|
|
||||||
std::string class_element::name() const { return name_; }
|
std::string class_element::name() const { return name_; }
|
||||||
|
|
||||||
|
void class_element::set_name(const std::string &name) { name_ = name; }
|
||||||
|
|
||||||
std::string class_element::type() const { return type_; }
|
std::string class_element::type() const { return type_; }
|
||||||
|
|
||||||
|
void class_element::set_type(const std::string &type) { type_ = type; }
|
||||||
|
|
||||||
inja::json class_element::context() const
|
inja::json class_element::context() const
|
||||||
{
|
{
|
||||||
inja::json ctx;
|
inja::json ctx;
|
||||||
|
|||||||
@@ -36,7 +36,10 @@ public:
|
|||||||
|
|
||||||
common::model::access_t access() const;
|
common::model::access_t access() const;
|
||||||
std::string name() const;
|
std::string name() const;
|
||||||
|
void set_name(const std::string &name);
|
||||||
|
|
||||||
std::string type() const;
|
std::string type() const;
|
||||||
|
void set_type(const std::string &type);
|
||||||
|
|
||||||
virtual inja::json context() const;
|
virtual inja::json context() const;
|
||||||
|
|
||||||
|
|||||||
@@ -986,10 +986,13 @@ bool translation_unit_visitor::process_template_parameters(
|
|||||||
const auto *template_nontype_parameter =
|
const auto *template_nontype_parameter =
|
||||||
clang::dyn_cast_or_null<clang::NonTypeTemplateParmDecl>(
|
clang::dyn_cast_or_null<clang::NonTypeTemplateParmDecl>(
|
||||||
parameter);
|
parameter);
|
||||||
|
|
||||||
std::optional<std::string> default_arg;
|
std::optional<std::string> default_arg;
|
||||||
|
|
||||||
if (template_nontype_parameter->hasDefaultArgument())
|
if (template_nontype_parameter->hasDefaultArgument())
|
||||||
default_arg = common::to_string(
|
default_arg = common::to_string(
|
||||||
template_nontype_parameter->getDefaultArgument());
|
template_nontype_parameter->getDefaultArgument());
|
||||||
|
|
||||||
auto ct = template_parameter::make_non_type_template(
|
auto ct = template_parameter::make_non_type_template(
|
||||||
template_nontype_parameter->getType().getAsString(),
|
template_nontype_parameter->getType().getAsString(),
|
||||||
template_nontype_parameter->getNameAsString(), default_arg,
|
template_nontype_parameter->getNameAsString(), default_arg,
|
||||||
@@ -1082,6 +1085,7 @@ void translation_unit_visitor::process_class_bases(
|
|||||||
if (const auto *record_type =
|
if (const auto *record_type =
|
||||||
base.getType()->getAs<clang::RecordType>();
|
base.getType()->getAs<clang::RecordType>();
|
||||||
record_type != nullptr) {
|
record_type != nullptr) {
|
||||||
|
cp.set_name(record_type->getDecl()->getQualifiedNameAsString());
|
||||||
cp.set_id(common::to_id(*record_type->getDecl()));
|
cp.set_id(common::to_id(*record_type->getDecl()));
|
||||||
}
|
}
|
||||||
else if (const auto *tsp =
|
else if (const auto *tsp =
|
||||||
@@ -1488,7 +1492,8 @@ bool translation_unit_visitor::find_relationships(const clang::QualType &type,
|
|||||||
->getID(),
|
->getID(),
|
||||||
relationship_hint);
|
relationship_hint);
|
||||||
}
|
}
|
||||||
for (const auto &template_argument : *type_instantiation_decl) {
|
for (const auto &template_argument :
|
||||||
|
type_instantiation_decl->template_arguments()) {
|
||||||
const auto template_argument_kind = template_argument.getKind();
|
const auto template_argument_kind = template_argument.getKind();
|
||||||
if (template_argument_kind ==
|
if (template_argument_kind ==
|
||||||
clang::TemplateArgument::ArgKind::Integral) {
|
clang::TemplateArgument::ArgKind::Integral) {
|
||||||
@@ -2520,12 +2525,31 @@ void translation_unit_visitor::
|
|||||||
argument.set_type(
|
argument.set_type(
|
||||||
common::to_string(arg.getAsType(), template_decl->getASTContext()));
|
common::to_string(arg.getAsType(), template_decl->getASTContext()));
|
||||||
|
|
||||||
if (const auto *record_type = arg.getAsType()->getAs<clang::RecordType>();
|
if (const auto *tsp =
|
||||||
record_type != nullptr) {
|
arg.getAsType()->getAs<clang::TemplateSpecializationType>();
|
||||||
|
tsp != nullptr) {
|
||||||
|
if (const auto *record_type_decl = tsp->getAsRecordDecl();
|
||||||
|
record_type_decl != nullptr) {
|
||||||
|
|
||||||
|
argument.set_id(common::to_id(arg));
|
||||||
|
if (diagram().should_include(full_template_specialization_name)) {
|
||||||
|
// Add dependency relationship to the parent
|
||||||
|
// template
|
||||||
|
template_instantiation.add_relationship(
|
||||||
|
{relationship_t::kDependency, common::to_id(arg)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (const auto *record_type =
|
||||||
|
arg.getAsType()->getAs<clang::RecordType>();
|
||||||
|
record_type != nullptr) {
|
||||||
if (const auto *record_type_decl = record_type->getAsRecordDecl();
|
if (const auto *record_type_decl = record_type->getAsRecordDecl();
|
||||||
record_type_decl != nullptr) {
|
record_type_decl != nullptr) {
|
||||||
argument.set_id(common::to_id(arg));
|
|
||||||
|
|
||||||
|
argument.set_id(common::to_id(arg));
|
||||||
|
#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
|
// Add dependency relationship to the parent
|
||||||
// template
|
// template
|
||||||
@@ -2635,11 +2659,10 @@ void translation_unit_visitor::process_field(
|
|||||||
if (type_name.find("std::weak_ptr") == 0)
|
if (type_name.find("std::weak_ptr") == 0)
|
||||||
relationship_hint = relationship_t::kAssociation;
|
relationship_hint = relationship_t::kAssociation;
|
||||||
|
|
||||||
const auto *template_field_type =
|
|
||||||
field_type->getAs<clang::TemplateSpecializationType>();
|
|
||||||
|
|
||||||
found_relationships_t relationships;
|
found_relationships_t relationships;
|
||||||
|
|
||||||
|
const auto *template_field_type =
|
||||||
|
field_type->getAs<clang::TemplateSpecializationType>();
|
||||||
// TODO: Refactor to an unalias_type() method
|
// TODO: Refactor to an unalias_type() method
|
||||||
if (template_field_type != nullptr)
|
if (template_field_type != nullptr)
|
||||||
if (template_field_type->isTypeAlias())
|
if (template_field_type->isTypeAlias())
|
||||||
@@ -2803,11 +2826,14 @@ void translation_unit_visitor::finalize()
|
|||||||
bool translation_unit_visitor::simplify_system_template(
|
bool translation_unit_visitor::simplify_system_template(
|
||||||
template_parameter &ct, const std::string &full_name) const
|
template_parameter &ct, const std::string &full_name) const
|
||||||
{
|
{
|
||||||
if (config().type_aliases().count(full_name) > 0) {
|
auto simplified = config().simplify_template_type(full_name);
|
||||||
ct.set_type(config().type_aliases().at(full_name));
|
|
||||||
|
if (simplified != full_name) {
|
||||||
|
ct.set_type(simplified);
|
||||||
ct.clear_params();
|
ct.clear_params();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -268,13 +268,10 @@ cli_flow_t cli_handler::handle_post_config_options()
|
|||||||
|
|
||||||
cli_flow_t cli_handler::print_version()
|
cli_flow_t cli_handler::print_version()
|
||||||
{
|
{
|
||||||
constexpr auto kLLVMBackendPackageStringLength{5};
|
|
||||||
ostr_ << "clang-uml " << clanguml::version::CLANG_UML_VERSION << '\n';
|
ostr_ << "clang-uml " << clanguml::version::CLANG_UML_VERSION << '\n';
|
||||||
ostr_ << "Copyright (C) 2021-2023 Bartek Kryza <bkryza@gmail.com>" << '\n';
|
ostr_ << "Copyright (C) 2021-2023 Bartek Kryza <bkryza@gmail.com>" << '\n';
|
||||||
ostr_ << "Built against LLVM/Clang libraries version: "
|
ostr_ << "Built against LLVM/Clang libraries version: "
|
||||||
<< std::string{BACKEND_PACKAGE_STRING}.substr(
|
<< LLVM_VERSION_STRING << std::endl;
|
||||||
kLLVMBackendPackageStringLength)
|
|
||||||
<< std::endl;
|
|
||||||
ostr_ << "Using LLVM/Clang libraries version: "
|
ostr_ << "Using LLVM/Clang libraries version: "
|
||||||
<< clang::getClangFullVersion() << std::endl;
|
<< clang::getClangFullVersion() << std::endl;
|
||||||
|
|
||||||
|
|||||||
@@ -115,9 +115,13 @@ std::string get_tag_name(const clang::TagDecl &declaration)
|
|||||||
std::string to_string(const clang::QualType &type, const clang::ASTContext &ctx,
|
std::string to_string(const clang::QualType &type, const clang::ASTContext &ctx,
|
||||||
bool try_canonical)
|
bool try_canonical)
|
||||||
{
|
{
|
||||||
const clang::PrintingPolicy print_policy(ctx.getLangOpts());
|
clang::PrintingPolicy print_policy(ctx.getLangOpts());
|
||||||
|
print_policy.SuppressScope = false;
|
||||||
|
print_policy.PrintCanonicalTypes = false;
|
||||||
|
|
||||||
auto result{type.getAsString(print_policy)};
|
std::string result;
|
||||||
|
|
||||||
|
result = type.getAsString(print_policy);
|
||||||
|
|
||||||
if (try_canonical && result.find('<') != std::string::npos) {
|
if (try_canonical && result.find('<') != std::string::npos) {
|
||||||
auto canonical_type_name =
|
auto canonical_type_name =
|
||||||
|
|||||||
@@ -121,7 +121,8 @@ void inheritable_diagram_options::inherit(
|
|||||||
std::string inheritable_diagram_options::simplify_template_type(
|
std::string inheritable_diagram_options::simplify_template_type(
|
||||||
std::string full_name) const
|
std::string full_name) const
|
||||||
{
|
{
|
||||||
const auto &aliases = type_aliases();
|
type_aliases_longer_first_t aliases;
|
||||||
|
aliases.insert(type_aliases().begin(), type_aliases().end());
|
||||||
|
|
||||||
for (const auto &[pattern, replacement] : aliases) {
|
for (const auto &[pattern, replacement] : aliases) {
|
||||||
util::replace_all(full_name, pattern, replacement);
|
util::replace_all(full_name, pattern, replacement);
|
||||||
@@ -204,6 +205,11 @@ void diagram::initialize_type_aliases()
|
|||||||
type_aliases().insert(
|
type_aliases().insert(
|
||||||
{"std::integral_constant<bool,false>", "std::false_type"});
|
{"std::integral_constant<bool,false>", "std::false_type"});
|
||||||
}
|
}
|
||||||
|
#if LLVM_VERSION_MAJOR >= 16
|
||||||
|
if (type_aliases().count("std::basic_string") == 0U) {
|
||||||
|
type_aliases().insert({"std::basic_string", "std::string"});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
common::model::diagram_t class_diagram::type() const
|
common::model::diagram_t class_diagram::type() const
|
||||||
|
|||||||
@@ -133,6 +133,8 @@ struct relationship_hint_t {
|
|||||||
using relationship_hints_t = std::map<std::string, relationship_hint_t>;
|
using relationship_hints_t = std::map<std::string, relationship_hint_t>;
|
||||||
|
|
||||||
using type_aliases_t = std::map<std::string, std::string>;
|
using type_aliases_t = std::map<std::string, std::string>;
|
||||||
|
using type_aliases_longer_first_t =
|
||||||
|
std::map<std::string, std::string, std::greater<>>;
|
||||||
|
|
||||||
enum class location_t { marker, fileline, function };
|
enum class location_t { marker, fileline, function };
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,15 @@ translation_unit_visitor::include_visitor::include_visitor(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LLVM_VERSION_MAJOR > 14
|
#if LLVM_VERSION_MAJOR >= 16
|
||||||
|
void translation_unit_visitor::include_visitor::InclusionDirective(
|
||||||
|
clang::SourceLocation hash_loc, const clang::Token & /*include_tok*/,
|
||||||
|
clang::StringRef /*file_name*/, bool is_angled,
|
||||||
|
clang::CharSourceRange /*filename_range*/, clang::OptionalFileEntryRef file,
|
||||||
|
clang::StringRef /*search_path*/, clang::StringRef relative_path,
|
||||||
|
const clang::Module * /*imported*/,
|
||||||
|
clang::SrcMgr::CharacteristicKind file_type)
|
||||||
|
#elif LLVM_VERSION_MAJOR > 14
|
||||||
void translation_unit_visitor::include_visitor::InclusionDirective(
|
void translation_unit_visitor::include_visitor::InclusionDirective(
|
||||||
clang::SourceLocation hash_loc, const clang::Token & /*include_tok*/,
|
clang::SourceLocation hash_loc, const clang::Token & /*include_tok*/,
|
||||||
clang::StringRef /*file_name*/, bool is_angled,
|
clang::StringRef /*file_name*/, bool is_angled,
|
||||||
|
|||||||
@@ -49,7 +49,14 @@ public:
|
|||||||
|
|
||||||
~include_visitor() override = default;
|
~include_visitor() override = default;
|
||||||
|
|
||||||
#if LLVM_VERSION_MAJOR > 14
|
#if LLVM_VERSION_MAJOR >= 16
|
||||||
|
void InclusionDirective(clang::SourceLocation HashLoc,
|
||||||
|
const clang::Token &IncludeTok, clang::StringRef FileName,
|
||||||
|
bool IsAngled, clang::CharSourceRange FilenameRange,
|
||||||
|
clang::OptionalFileEntryRef File, clang::StringRef SearchPath,
|
||||||
|
clang::StringRef RelativePath, const clang::Module *Imported,
|
||||||
|
clang::SrcMgr::CharacteristicKind FileType) override;
|
||||||
|
#elif LLVM_VERSION_MAJOR > 14
|
||||||
void InclusionDirective(clang::SourceLocation hash_loc,
|
void InclusionDirective(clang::SourceLocation hash_loc,
|
||||||
const clang::Token &include_tok, clang::StringRef file_name,
|
const clang::Token &include_tok, clang::StringRef file_name,
|
||||||
bool is_angled, clang::CharSourceRange filename_range,
|
bool is_angled, clang::CharSourceRange filename_range,
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ bool translation_unit_visitor::find_relationships(const clang::QualType &type,
|
|||||||
type->getAs<clang::TemplateSpecializationType>()) {
|
type->getAs<clang::TemplateSpecializationType>()) {
|
||||||
if (template_specialization_type != nullptr) {
|
if (template_specialization_type != nullptr) {
|
||||||
for (const auto &template_argument :
|
for (const auto &template_argument :
|
||||||
*template_specialization_type) {
|
template_specialization_type->template_arguments()) {
|
||||||
const auto template_argument_kind = template_argument.getKind();
|
const auto template_argument_kind = template_argument.getKind();
|
||||||
if (template_argument_kind ==
|
if (template_argument_kind ==
|
||||||
clang::TemplateArgument::ArgKind::Integral) {
|
clang::TemplateArgument::ArgKind::Integral) {
|
||||||
|
|||||||
@@ -2064,12 +2064,7 @@ bool translation_unit_visitor::simplify_system_template(
|
|||||||
std::string translation_unit_visitor::simplify_system_template(
|
std::string translation_unit_visitor::simplify_system_template(
|
||||||
const std::string &full_name) const
|
const std::string &full_name) const
|
||||||
{
|
{
|
||||||
std::string result{full_name};
|
return config().simplify_template_type(full_name);
|
||||||
for (const auto &[k, v] : config().type_aliases()) {
|
|
||||||
util::replace_all(result, k, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string translation_unit_visitor::make_lambda_name(
|
std::string translation_unit_visitor::make_lambda_name(
|
||||||
|
|||||||
@@ -64,8 +64,12 @@ TEST_CASE("t00008", "[test-case][class]")
|
|||||||
|
|
||||||
using namespace json;
|
using namespace json;
|
||||||
|
|
||||||
|
#if LLVM_VERSION_MAJOR >= 16
|
||||||
|
REQUIRE(IsClassTemplate(j, "A<T,P=T,CMP=nullptr,int N=3>"));
|
||||||
|
#else
|
||||||
REQUIRE(IsClassTemplate(
|
REQUIRE(IsClassTemplate(
|
||||||
j, "A<T,P=T,clanguml::t00008::CMP=nullptr,int N=3>"));
|
j, "A<T,P=T,clanguml::t00008::CMP=nullptr,int N=3>"));
|
||||||
|
#endif
|
||||||
REQUIRE(IsClassTemplate(j, "E::nested_template<ET>"));
|
REQUIRE(IsClassTemplate(j, "E::nested_template<ET>"));
|
||||||
REQUIRE(IsClass(j, "E::nested_template<char>"));
|
REQUIRE(IsClass(j, "E::nested_template<char>"));
|
||||||
|
|
||||||
|
|||||||
@@ -70,8 +70,13 @@ TEST_CASE("t00014", "[test-case][class]")
|
|||||||
|
|
||||||
REQUIRE_THAT(
|
REQUIRE_THAT(
|
||||||
puml, IsField<Public>("cb", "SimpleCallback<ACharString>"));
|
puml, IsField<Public>("cb", "SimpleCallback<ACharString>"));
|
||||||
|
#if LLVM_VERSION_MAJOR >= 16
|
||||||
|
REQUIRE_THAT(
|
||||||
|
puml, IsField<Public>("gcb", "GenericCallback<AWCharString>"));
|
||||||
|
#else
|
||||||
REQUIRE_THAT(
|
REQUIRE_THAT(
|
||||||
puml, IsField<Public>("gcb", "GenericCallback<R::AWCharString>"));
|
puml, IsField<Public>("gcb", "GenericCallback<R::AWCharString>"));
|
||||||
|
#endif
|
||||||
REQUIRE_THAT(puml, IsField<Public>("vcb", "VoidCallback"));
|
REQUIRE_THAT(puml, IsField<Public>("vcb", "VoidCallback"));
|
||||||
|
|
||||||
REQUIRE_THAT(puml,
|
REQUIRE_THAT(puml,
|
||||||
|
|||||||
@@ -620,6 +620,26 @@ struct File {
|
|||||||
const std::string file;
|
const std::string file;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::optional<nlohmann::json> get_element_by_id(
|
||||||
|
const nlohmann::json &j, const std::string &id)
|
||||||
|
{
|
||||||
|
if (!j.contains("elements"))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
for (const nlohmann::json &e : j["elements"]) {
|
||||||
|
if (e["id"] == id)
|
||||||
|
return {e};
|
||||||
|
|
||||||
|
if (e["type"] == "namespace" || e["type"] == "folder") {
|
||||||
|
auto maybe_e = get_element_by_id(e, id);
|
||||||
|
if (maybe_e)
|
||||||
|
return maybe_e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<nlohmann::json> get_element(
|
std::optional<nlohmann::json> get_element(
|
||||||
const nlohmann::json &j, const std::string &name)
|
const nlohmann::json &j, const std::string &name)
|
||||||
{
|
{
|
||||||
@@ -744,15 +764,16 @@ bool IsDeprecated(const nlohmann::json &j, const std::string &name)
|
|||||||
bool IsBaseClass(const nlohmann::json &j, const std::string &base,
|
bool IsBaseClass(const nlohmann::json &j, const std::string &base,
|
||||||
const std::string &subclass)
|
const std::string &subclass)
|
||||||
{
|
{
|
||||||
auto sc = get_element(j, expand_name(j, subclass));
|
auto base_el = get_element(j, expand_name(j, base));
|
||||||
|
auto subclass_el = get_element(j, expand_name(j, subclass));
|
||||||
|
|
||||||
if (!sc)
|
if (!base_el || !subclass_el)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const nlohmann::json &bases = (*sc)["bases"];
|
const nlohmann::json &bases = (*subclass_el)["bases"];
|
||||||
|
|
||||||
return std::find_if(bases.begin(), bases.end(), [&](const auto &it) {
|
return std::find_if(bases.begin(), bases.end(), [&](const auto &it) {
|
||||||
return it["name"] == expand_name(j, base);
|
return it["id"] == base_el.value()["id"];
|
||||||
}) != bases.end();
|
}) != bases.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user