From cb9ad57e87a90e838574bd64f2aca1ce0311b8b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Sat, 18 Mar 2017 11:01:27 +0100 Subject: [PATCH] Register declarations as well Will be overriden by definitions. --- include/cppast/cpp_class.hpp | 10 ++-- include/cppast/cpp_entity_index.hpp | 64 +++++++++++++++++++---- include/cppast/cpp_enum.hpp | 7 +-- include/cppast/cpp_file.hpp | 2 +- include/cppast/cpp_forward_declarable.hpp | 5 +- include/cppast/cpp_function.hpp | 5 +- include/cppast/cpp_namespace.hpp | 2 +- include/cppast/cpp_template.hpp | 2 +- include/cppast/cpp_template_parameter.hpp | 2 +- src/cpp_class.cpp | 13 +++-- src/cpp_enum.cpp | 2 +- src/cpp_function.cpp | 2 +- src/cpp_member_variable.cpp | 4 +- src/cpp_namespace.cpp | 2 +- src/cpp_template_parameter.cpp | 4 +- src/cpp_type_alias.cpp | 2 +- src/cpp_variable.cpp | 2 +- src/libclang/class_parser.cpp | 2 +- src/libclang/debug_helper.cpp | 5 +- src/libclang/enum_parser.cpp | 2 +- src/libclang/function_parser.cpp | 2 +- 21 files changed, 98 insertions(+), 43 deletions(-) diff --git a/include/cppast/cpp_class.hpp b/include/cppast/cpp_class.hpp index 7bf21c8..cf65fcf 100644 --- a/include/cppast/cpp_class.hpp +++ b/include/cppast/cpp_class.hpp @@ -174,17 +174,13 @@ namespace cppast /// \effects Registers the class in the [cppast::cpp_entity_index](), /// using the given [cppast::cpp_entity_id](). /// \returns The finished class. - std::unique_ptr finish(const cpp_entity_index& idx, - cpp_entity_id id) noexcept; + std::unique_ptr finish(const cpp_entity_index& idx, cpp_entity_id id); /// \effects Marks the class as forward declaration. /// \returns The finished class. /// \notes It will not be registered, as it is not the main definition. - std::unique_ptr finish_declaration(cpp_entity_id definition_id) noexcept - { - class_->set_definition(definition_id); - return std::move(class_); - } + std::unique_ptr finish_declaration(const cpp_entity_index& idx, + cpp_entity_id definition_id); private: std::unique_ptr class_; diff --git a/include/cppast/cpp_entity_index.hpp b/include/cppast/cpp_entity_index.hpp index 59cb361..919bb0a 100644 --- a/include/cppast/cpp_entity_index.hpp +++ b/include/cppast/cpp_entity_index.hpp @@ -62,19 +62,40 @@ namespace cppast class cpp_entity_index { public: - /// \effects Registers a new [cppast::cpp_entity]() also giving its [cppast::cpp_entity_id](). - /// \requires The entity must not have been registered before, - /// and it must live as long as the index lives. + /// \effects Registers a new [cppast::cpp_entity]() which is a definition. + /// It will override any previously registered declarations of the same entity. + /// \requires If the entity has been registered before, it must be as declaration, + /// and the entity must live as long as the index lives. /// \notes This operation is thread safe. - void register_entity(cpp_entity_id id, type_safe::object_ref entity) const + void register_definition(cpp_entity_id id, + type_safe::object_ref entity) const { std::lock_guard lock(mutex_); - auto result = map_.emplace(std::move(id), std::move(entity)); - DEBUG_ASSERT(result.second, detail::precondition_error_handler{}, - "duplicate index registration"); + auto result = map_.emplace(std::move(id), value(entity, true)); + if (!result.second) + { + // already in map, override declaration + auto& value = result.first->second; + DEBUG_ASSERT(!value.is_definition, detail::precondition_error_handler{}, + "duplicate entity registration"); + value.is_definition = true; + value.entity = entity; + } + } + + /// \effects Registers a new [cppast::cpp_entity]() which is a declaration. + /// Only the first declaration will be registered. + /// \requires The entity must live as long as the index lives. + /// \notes This operaiton is thread safe. + void register_forward_declaration(cpp_entity_id id, + type_safe::object_ref entity) const + { + std::lock_guard lock(mutex_); + map_.emplace(std::move(id), value(entity, false)); } /// \returns A [ts::optional_ref]() corresponding to the entity of the given [cppast::cpp_entity_id](). + /// If no definition has been registered, it return the first declaration that was registered. /// \notes This operation is thread safe. type_safe::optional_ref lookup(const cpp_entity_id& id) const noexcept { @@ -82,7 +103,20 @@ namespace cppast auto iter = map_.find(id); if (iter == map_.end()) return {}; - return iter->second.get(); + return iter->second.entity.get(); + } + + /// \returns A [ts::optional_ref]() corresponding to the entity of the given [cppast::cpp_entity_id](). + /// If no definition has been registered, it returns an empty optional. + /// \notes This operation is thread safe. + type_safe::optional_ref lookup_definition(const cpp_entity_id& id) const + noexcept + { + std::lock_guard lock(mutex_); + auto iter = map_.find(id); + if (iter == map_.end() || !iter->second.is_definition) + return {}; + return iter->second.entity.get(); } private: @@ -94,9 +128,19 @@ namespace cppast } }; + struct value + { + type_safe::object_ref entity; + bool is_definition; + + value(type_safe::object_ref e, bool def) + : entity(std::move(e)), is_definition(def) + { + } + }; + mutable std::mutex mutex_; - mutable std::unordered_map, hash> - map_; + mutable std::unordered_map map_; }; } // namespace cppast diff --git a/include/cppast/cpp_enum.hpp b/include/cppast/cpp_enum.hpp index a6bbf17..aae1965 100644 --- a/include/cppast/cpp_enum.hpp +++ b/include/cppast/cpp_enum.hpp @@ -87,16 +87,17 @@ namespace cppast /// \returns The finished enum. std::unique_ptr finish(const cpp_entity_index& idx, cpp_entity_id id) noexcept { - idx.register_entity(std::move(id), type_safe::ref(*enum_)); + idx.register_definition(std::move(id), type_safe::ref(*enum_)); return std::move(enum_); } /// \effects Marks the enum as forward declaration. /// \returns The finished enum. - /// \notes It will not be registered, as it is not the main definition. - std::unique_ptr finish_declaration(cpp_entity_id definition_id) noexcept + std::unique_ptr finish_declaration(const cpp_entity_index& idx, + cpp_entity_id definition_id) noexcept { enum_->set_definition(definition_id); + idx.register_forward_declaration(std::move(definition_id), type_safe::ref(*enum_)); return std::move(enum_); } diff --git a/include/cppast/cpp_file.hpp b/include/cppast/cpp_file.hpp index e860bea..0ef4a11 100644 --- a/include/cppast/cpp_file.hpp +++ b/include/cppast/cpp_file.hpp @@ -53,7 +53,7 @@ namespace cppast /// \returns The finished file. std::unique_ptr finish(const cpp_entity_index& idx) noexcept { - idx.register_entity(cpp_entity_id(file_->name()), type_safe::ref(*file_)); + idx.register_definition(cpp_entity_id(file_->name()), type_safe::ref(*file_)); return std::move(file_); } diff --git a/include/cppast/cpp_forward_declarable.hpp b/include/cppast/cpp_forward_declarable.hpp index 7539172..a81eaf6 100644 --- a/include/cppast/cpp_forward_declarable.hpp +++ b/include/cppast/cpp_forward_declarable.hpp @@ -69,10 +69,13 @@ namespace cppast 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(entity.definition().value()) + .lookup_definition(entity.definition().value()) // downcast .map([](const cpp_entity& e) -> const T& { DEBUG_ASSERT(e.kind() == T::kind(), detail::assert_handler{}); diff --git a/include/cppast/cpp_function.hpp b/include/cppast/cpp_function.hpp index 5a4c488..6dc06e0 100644 --- a/include/cppast/cpp_function.hpp +++ b/include/cppast/cpp_function.hpp @@ -136,9 +136,12 @@ namespace cppast { function->body_ = body_kind; if (cppast::is_definition(body_kind)) - idx.register_entity(std::move(id), type_safe::cref(*function)); + idx.register_definition(std::move(id), type_safe::ref(*function)); else + { function->set_definition(id); + idx.register_forward_declaration(std::move(id), type_safe::ref(*function)); + } return std::move(function); } diff --git a/include/cppast/cpp_namespace.hpp b/include/cppast/cpp_namespace.hpp index ec646ce..3c2ac63 100644 --- a/include/cppast/cpp_namespace.hpp +++ b/include/cppast/cpp_namespace.hpp @@ -46,7 +46,7 @@ namespace cppast /// \returns The finished namespace. std::unique_ptr finish(const cpp_entity_index& idx, cpp_entity_id id) { - idx.register_entity(std::move(id), type_safe::ref(*namespace_)); + idx.register_definition(std::move(id), type_safe::ref(*namespace_)); return std::move(namespace_); } diff --git a/include/cppast/cpp_template.hpp b/include/cppast/cpp_template.hpp index c74cfe5..5c0cc2f 100644 --- a/include/cppast/cpp_template.hpp +++ b/include/cppast/cpp_template.hpp @@ -50,7 +50,7 @@ namespace cppast /// \returns The finished template. std::unique_ptr finish(const cpp_entity_index& idx, cpp_entity_id id) { - idx.register_entity(std::move(id), type_safe::cref(*template_entity)); + idx.register_definition(std::move(id), type_safe::cref(*template_entity)); return std::move(template_entity); } diff --git a/include/cppast/cpp_template_parameter.hpp b/include/cppast/cpp_template_parameter.hpp index a2fd485..82f1dad 100644 --- a/include/cppast/cpp_template_parameter.hpp +++ b/include/cppast/cpp_template_parameter.hpp @@ -206,7 +206,7 @@ namespace cppast std::unique_ptr finish(const cpp_entity_index& idx, cpp_entity_id id) { - idx.register_entity(std::move(id), type_safe::ref(*parameter_)); + idx.register_definition(std::move(id), type_safe::ref(*parameter_)); return std::move(parameter_); } diff --git a/src/cpp_class.cpp b/src/cpp_class.cpp index 4b204d8..2f84aa6 100644 --- a/src/cpp_class.cpp +++ b/src/cpp_class.cpp @@ -9,10 +9,17 @@ using namespace cppast; -std::unique_ptr cpp_class::builder::finish(const cpp_entity_index& idx, - cpp_entity_id id) noexcept +std::unique_ptr cpp_class::builder::finish(const cpp_entity_index& idx, cpp_entity_id id) { - idx.register_entity(std::move(id), type_safe::ref(*class_)); + idx.register_definition(std::move(id), type_safe::ref(*class_)); + return std::move(class_); +} + +std::unique_ptr cpp_class::builder::finish_declaration(const cpp_entity_index& idx, + cpp_entity_id definition_id) +{ + class_->set_definition(definition_id); + idx.register_forward_declaration(std::move(definition_id), type_safe::ref(*class_)); return std::move(class_); } diff --git a/src/cpp_enum.cpp b/src/cpp_enum.cpp index 11d2f00..355b977 100644 --- a/src/cpp_enum.cpp +++ b/src/cpp_enum.cpp @@ -19,7 +19,7 @@ std::unique_ptr cpp_enum_value::build(const cpp_entity_index& id { auto result = std::unique_ptr(new cpp_enum_value(std::move(name), std::move(value))); - idx.register_entity(std::move(id), type_safe::ref(*result)); + idx.register_definition(std::move(id), type_safe::ref(*result)); return result; } diff --git a/src/cpp_function.cpp b/src/cpp_function.cpp index ff96ade..dec9e98 100644 --- a/src/cpp_function.cpp +++ b/src/cpp_function.cpp @@ -19,7 +19,7 @@ std::unique_ptr cpp_function_parameter::build( { auto result = std::unique_ptr( new cpp_function_parameter(std::move(name), std::move(type), std::move(def))); - idx.register_entity(std::move(id), type_safe::cref(*result)); + idx.register_definition(std::move(id), type_safe::cref(*result)); return result; } diff --git a/src/cpp_member_variable.cpp b/src/cpp_member_variable.cpp index 6875287..8aebf9b 100644 --- a/src/cpp_member_variable.cpp +++ b/src/cpp_member_variable.cpp @@ -21,7 +21,7 @@ std::unique_ptr cpp_member_variable::build(const cpp_entity { auto result = std::unique_ptr( new cpp_member_variable(std::move(name), std::move(type), std::move(def), is_mutable)); - idx.register_entity(std::move(id), type_safe::cref(*result)); + idx.register_definition(std::move(id), type_safe::cref(*result)); return result; } @@ -41,7 +41,7 @@ std::unique_ptr cpp_bitfield::build(const cpp_entity_index& idx, c { auto result = std::unique_ptr( new cpp_bitfield(std::move(name), std::move(type), no_bits, is_mutable)); - idx.register_entity(std::move(id), type_safe::cref(*result)); + idx.register_definition(std::move(id), type_safe::cref(*result)); return result; } diff --git a/src/cpp_namespace.cpp b/src/cpp_namespace.cpp index caee2be..79df2a4 100644 --- a/src/cpp_namespace.cpp +++ b/src/cpp_namespace.cpp @@ -29,7 +29,7 @@ std::unique_ptr cpp_namespace_alias::build(const cpp_entity { auto ptr = std::unique_ptr( new cpp_namespace_alias(std::move(name), std::move(target))); - idx.register_entity(std::move(id), type_safe::ref(*ptr)); + idx.register_definition(std::move(id), type_safe::ref(*ptr)); return ptr; } diff --git a/src/cpp_template_parameter.cpp b/src/cpp_template_parameter.cpp index 375b8cd..7b640f2 100644 --- a/src/cpp_template_parameter.cpp +++ b/src/cpp_template_parameter.cpp @@ -27,7 +27,7 @@ std::unique_ptr cpp_template_type_parameter::build( { std::unique_ptr result( new cpp_template_type_parameter(std::move(name), kw, variadic, std::move(default_type))); - idx.register_entity(std::move(id), type_safe::cref(*result)); + idx.register_definition(std::move(id), type_safe::cref(*result)); return result; } @@ -48,7 +48,7 @@ std::unique_ptr cpp_non_type_template_parameter std::unique_ptr result( new cpp_non_type_template_parameter(std::move(name), std::move(type), is_variadic, std::move(default_value))); - idx.register_entity(std::move(id), type_safe::cref(*result)); + idx.register_definition(std::move(id), type_safe::cref(*result)); return result; } diff --git a/src/cpp_type_alias.cpp b/src/cpp_type_alias.cpp index a22ec1f..d0cdd30 100644 --- a/src/cpp_type_alias.cpp +++ b/src/cpp_type_alias.cpp @@ -18,7 +18,7 @@ std::unique_ptr cpp_type_alias::build(const cpp_entity_index& id std::unique_ptr type) { auto result = build(std::move(name), std::move(type)); - idx.register_entity(std::move(id), type_safe::cref(*result)); + idx.register_definition(std::move(id), type_safe::cref(*result)); return result; } diff --git a/src/cpp_variable.cpp b/src/cpp_variable.cpp index 368ede8..eefe9b3 100644 --- a/src/cpp_variable.cpp +++ b/src/cpp_variable.cpp @@ -21,7 +21,7 @@ std::unique_ptr cpp_variable::build(const cpp_entity_index& idx, c { auto result = std::unique_ptr( new cpp_variable(std::move(name), std::move(type), std::move(def), spec, is_constexpr)); - idx.register_entity(std::move(id), type_safe::cref(*result)); + idx.register_definition(std::move(id), type_safe::cref(*result)); return result; } diff --git a/src/libclang/class_parser.cpp b/src/libclang/class_parser.cpp index 1e749a5..0d236e6 100644 --- a/src/libclang/class_parser.cpp +++ b/src/libclang/class_parser.cpp @@ -107,5 +107,5 @@ std::unique_ptr detail::parse_cpp_class(const detail::parse_context& if (clang_isCursorDefinition(cur)) return builder.finish(*context.idx, get_entity_id(cur)); else - return builder.finish_declaration(get_entity_id(cur)); + return builder.finish_declaration(*context.idx, get_entity_id(cur)); } diff --git a/src/libclang/debug_helper.cpp b/src/libclang/debug_helper.cpp index eba7bdd..43f2624 100644 --- a/src/libclang/debug_helper.cpp +++ b/src/libclang/debug_helper.cpp @@ -34,8 +34,9 @@ namespace void detail::print_cursor_info(const CXCursor& cur) noexcept { std::lock_guard lock(mtx); - std::printf("[debug] cursor '%s' (%s)\n", get_display_name(cur).c_str(), - cxstring(clang_getCursorKindSpelling(cur.kind)).c_str()); + std::printf("[debug] cursor '%s' (%s): %s\n", get_display_name(cur).c_str(), + cxstring(clang_getCursorKindSpelling(cur.kind)).c_str(), + cxstring(clang_getCursorUSR(cur)).c_str()); } void detail::print_tokens(const CXTranslationUnit& tu, const CXFile& file, diff --git a/src/libclang/enum_parser.cpp b/src/libclang/enum_parser.cpp index 4efe853..91be43d 100644 --- a/src/libclang/enum_parser.cpp +++ b/src/libclang/enum_parser.cpp @@ -85,5 +85,5 @@ std::unique_ptr detail::parse_cpp_enum(const detail::parse_context& if (clang_isCursorDefinition(cur)) return builder.finish(*context.idx, get_entity_id(cur)); else - return builder.finish_declaration(get_entity_id(cur)); + return builder.finish_declaration(*context.idx, get_entity_id(cur)); } diff --git a/src/libclang/function_parser.cpp b/src/libclang/function_parser.cpp index 3e990a0..1631cb6 100644 --- a/src/libclang/function_parser.cpp +++ b/src/libclang/function_parser.cpp @@ -176,7 +176,7 @@ namespace DEBUG_ASSERT(allow_virtual, detail::parse_error_handler{}, stream.cursor(), "unexpected token"); if (result.virtual_keywords) - result.virtual_keywords.value() &= cpp_virtual_flags::pure; + result.virtual_keywords.value() |= cpp_virtual_flags::pure; else result.virtual_keywords = cpp_virtual_flags::pure; }