From 599524a894869a65082b1670eec2d79bfd7dd1f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Tue, 11 Apr 2017 18:33:49 +0200 Subject: [PATCH] Add definition info to AST dump --- include/cppast/cpp_forward_declarable.hpp | 64 ++++------- src/CMakeLists.txt | 1 + src/cpp_forward_declarable.cpp | 129 ++++++++++++++++++++++ src/libclang/function_parser.cpp | 2 +- tool/main.cpp | 9 +- 5 files changed, 162 insertions(+), 43 deletions(-) create mode 100644 src/cpp_forward_declarable.cpp diff --git a/include/cppast/cpp_forward_declarable.hpp b/include/cppast/cpp_forward_declarable.hpp index d7e51db..c9c7b6b 100644 --- a/include/cppast/cpp_forward_declarable.hpp +++ b/include/cppast/cpp_forward_declarable.hpp @@ -60,52 +60,36 @@ namespace cppast type_safe::optional definition_; }; - /// \exclude - namespace detail - { - template - auto get_definition_impl(const cpp_entity_index& idx, const T& entity) -> - typename std::enable_if::value, - type_safe::optional_ref>::type - { - if (!entity.definition()) - // entity is definition itself - return type_safe::opt_cref(&entity); - else - // entity is not a definition - // lookup the definition - return idx - .lookup_definition(entity.definition().value()) - // downcast - .map([](const cpp_entity& e) { - DEBUG_ASSERT(e.kind() == T::kind(), detail::assert_handler{}); - return type_safe::ref(static_cast(e)); - }); - } + /// \returns Whether or not the given entity is a definition. + bool is_definition(const cpp_entity& e) noexcept; - template - auto get_definition_impl(const cpp_entity_index&, const T& entity) -> - typename std::enable_if::value, - type_safe::optional_ref>::type - { - return type_safe::opt_cref(&entity); - } - } // namespace detail + class cpp_enum; + class cpp_class; + class cpp_variable; + class cpp_function_base; /// Gets the definition of an entity. /// \returns A [ts::optional_ref]() to the entity that is the definition. - /// If the entity is a definition or not derived from [cppast::cpp_forward_declarable](), + /// If the entity is a definition or not derived from [cppast::cpp_forward_declarable]() (only valid for the generic entity overload), /// returns a reference to the entity itself. /// Otherwise lookups the definition id and returns it. - /// \requires `entity` must be derived from [cppast::cpp_entity](). - /// \param 1 - /// \exclude - template ::value>::type> - type_safe::optional_ref get_definition(const cpp_entity_index& idx, const T& entity) - { - return detail::get_definition_impl(idx, entity); - } + /// \notes The return value will only be `nullptr`, if the definition is not registered. + /// \group get_definition + type_safe::optional_ref get_definition(const cpp_entity_index& idx, + const cpp_entity& e); + /// \group get_definition + type_safe::optional_ref get_definition(const cpp_entity_index& idx, + const cpp_enum& e); + /// \group get_definition + type_safe::optional_ref get_definition(const cpp_entity_index& idx, + const cpp_class& e); + /// \group get_definition + type_safe::optional_ref get_definition(const cpp_entity_index& idx, + const cpp_variable& e); + /// \group get_definition + type_safe::optional_ref get_definition(const cpp_entity_index& idx, + const cpp_function_base& e); + } // namespace cppast #endif // CPPAST_CPP_FORWARD_DECLARABLE_HPP_INCLUDED diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba8290e..fa2f003 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -55,6 +55,7 @@ set(source cpp_enum.cpp cpp_expression.cpp cpp_file.cpp + cpp_forward_declarable.cpp cpp_friend.cpp cpp_function.cpp cpp_function_template.cpp diff --git a/src/cpp_forward_declarable.cpp b/src/cpp_forward_declarable.cpp new file mode 100644 index 0000000..5957b6c --- /dev/null +++ b/src/cpp_forward_declarable.cpp @@ -0,0 +1,129 @@ +// Copyright (C) 2017 Jonathan Müller +// This file is subject to the license terms in the LICENSE file +// found in the top-level directory of this distribution. + +#include + +#include +#include +#include +#include +#include + +using namespace cppast; + +namespace +{ + type_safe::optional_ref get_declarable(const cpp_entity& e) + { + switch (e.kind()) + { + case cpp_entity_kind::enum_t: + return type_safe::ref(static_cast(e)); + case cpp_entity_kind::class_t: + return type_safe::ref(static_cast(e)); + case cpp_entity_kind::variable_t: + return type_safe::ref(static_cast(e)); + case cpp_entity_kind::function_t: + case cpp_entity_kind::member_function_t: + case cpp_entity_kind::conversion_op_t: + case cpp_entity_kind::constructor_t: + case cpp_entity_kind::destructor_t: + return type_safe::ref(static_cast(e)); + + case cpp_entity_kind::file_t: + case cpp_entity_kind::macro_definition_t: + case cpp_entity_kind::include_directive_t: + case cpp_entity_kind::language_linkage_t: + case cpp_entity_kind::namespace_t: + case cpp_entity_kind::namespace_alias_t: + case cpp_entity_kind::using_directive_t: + case cpp_entity_kind::using_declaration_t: + case cpp_entity_kind::type_alias_t: + case cpp_entity_kind::enum_value_t: + case cpp_entity_kind::access_specifier_t: + case cpp_entity_kind::base_class_t: + case cpp_entity_kind::member_variable_t: + case cpp_entity_kind::bitfield_t: + case cpp_entity_kind::function_parameter_t: + case cpp_entity_kind::friend_t: + case cpp_entity_kind::template_type_parameter_t: + case cpp_entity_kind::non_type_template_parameter_t: + case cpp_entity_kind::template_template_parameter_t: + case cpp_entity_kind::alias_template_t: + case cpp_entity_kind::variable_template_t: + case cpp_entity_kind::function_template_t: + case cpp_entity_kind::function_template_specialization_t: + case cpp_entity_kind::class_template_t: + case cpp_entity_kind::class_template_specialization_t: + case cpp_entity_kind::unexposed_t: + return nullptr; + + case cpp_entity_kind::count: + break; + } + + DEBUG_UNREACHABLE(detail::assert_handler{}); + return nullptr; + } + + type_safe::optional_ref get_definition_impl(const cpp_entity_index& idx, + const cpp_entity& e) + { + auto declarable = get_declarable(e); + if (!declarable || declarable.value().is_definition()) + // not declarable or is a definition + // return reference to entity itself + return type_safe::ref(e); + // else lookup definition + return idx.lookup_definition(declarable.value().definition().value()); + } +} + +bool cppast::is_definition(const cpp_entity& e) noexcept +{ + auto declarable = get_declarable(e); + return declarable && declarable.value().is_definition(); +} + +type_safe::optional_ref cppast::get_definition(const cpp_entity_index& idx, + const cpp_entity& e) +{ + return get_definition_impl(idx, e); +} + +type_safe::optional_ref cppast::get_definition(const cpp_entity_index& idx, + const cpp_enum& e) +{ + return get_definition_impl(idx, e).map([](const cpp_entity& e) { + DEBUG_ASSERT(e.kind() == cpp_entity_kind::enum_t, detail::assert_handler{}); + return type_safe::ref(static_cast(e)); + }); +} + +type_safe::optional_ref cppast::get_definition(const cpp_entity_index& idx, + const cpp_class& e) +{ + return get_definition_impl(idx, e).map([](const cpp_entity& e) { + DEBUG_ASSERT(e.kind() == cpp_entity_kind::class_t, detail::assert_handler{}); + return type_safe::ref(static_cast(e)); + }); +} + +type_safe::optional_ref cppast::get_definition(const cpp_entity_index& idx, + const cpp_variable& e) +{ + return get_definition_impl(idx, e).map([](const cpp_entity& e) { + DEBUG_ASSERT(e.kind() == cpp_entity_kind::variable_t, detail::assert_handler{}); + return type_safe::ref(static_cast(e)); + }); +} + +type_safe::optional_ref cppast::get_definition(const cpp_entity_index& idx, + const cpp_function_base& e) +{ + return get_definition_impl(idx, e).map([](const cpp_entity& e) { + DEBUG_ASSERT(is_function(e.kind()), detail::assert_handler{}); + return type_safe::ref(static_cast(e)); + }); +} diff --git a/src/libclang/function_parser.cpp b/src/libclang/function_parser.cpp index a5e6fe7..34749b1 100644 --- a/src/libclang/function_parser.cpp +++ b/src/libclang/function_parser.cpp @@ -316,8 +316,8 @@ namespace } else if (detail::skip_if(stream, "final")) { - "unexpected token"); DEBUG_ASSERT(allow_virtual, detail::parse_error_handler{}, stream.cursor(), + "unexpected token"); if (result.virtual_keywords) result.virtual_keywords.value() |= cpp_virtual_flags::final; else diff --git a/tool/main.cpp b/tool/main.cpp index af2b3ce..65d5a90 100644 --- a/tool/main.cpp +++ b/tool/main.cpp @@ -9,8 +9,9 @@ #include // for libclang_parser, libclang_compile_config, cpp_entity,... #include // for visit() #include // for generate_code() -#include // for the cpp_entity_kind definition -#include // for cpp_namespace +#include // for the cpp_entity_kind definition +#include // for is_definition() +#include // for cpp_namespace // print help options void print_help(const cxxopts::Options& options) @@ -31,6 +32,10 @@ void print_entity(std::ostream& out, const cppast::cpp_entity& e) // print name and the kind of the entity out << e.name() << " (" << cppast::to_string(e.kind()) << ")"; + // print whether or not it is a definition + if (cppast::is_definition(e)) + out << " [definition]"; + if (e.kind() == cppast::cpp_entity_kind::language_linkage_t) // no need to print additional information for language linkages out << '\n';