diff --git a/include/cppast/cpp_entity.hpp b/include/cppast/cpp_entity.hpp index 049a6bc..47b5fa0 100644 --- a/include/cppast/cpp_entity.hpp +++ b/include/cppast/cpp_entity.hpp @@ -36,15 +36,20 @@ namespace cppast } /// \returns A [ts::optional_ref]() to the parent entity in the AST. - type_safe::optional_ref parent() const noexcept + type_safe::optional_ref parent() const noexcept { return parent_; } protected: /// \effects Creates it giving it the parent entity and the name. - cpp_entity(type_safe::optional_ref parent, std::string name) - : parent_(std::move(parent)), name_(std::move(name)) + cpp_entity(const cpp_entity& parent, std::string name) + : parent_(parent), name_(std::move(name)) + { + } + + /// \effects Creates it giving it no parent and the name. + cpp_entity(std::nullptr_t, std::string name) : name_(std::move(name)) { } @@ -52,10 +57,11 @@ namespace cppast /// \returns The type of the entity. virtual cpp_entity_type do_get_entity_type() const noexcept = 0; - type_safe::optional_ref parent_; - std::string name_; + type_safe::optional_ref parent_; + std::string name_; - friend detail::intrusive_list; + template + friend struct detail::intrusive_list_access; }; } // namespace cppast diff --git a/include/cppast/cpp_entity_type.hpp b/include/cppast/cpp_entity_type.hpp index 8f1efe4..838624c 100644 --- a/include/cppast/cpp_entity_type.hpp +++ b/include/cppast/cpp_entity_type.hpp @@ -11,6 +11,8 @@ namespace cppast enum class cpp_entity_type { file_t, + + namespace_t, }; /// \returns Whether or not a given entity type is one derived from [cppast::cpp_scope](). diff --git a/include/cppast/cpp_file.hpp b/include/cppast/cpp_file.hpp index 6c78dd4..c809a1f 100644 --- a/include/cppast/cpp_file.hpp +++ b/include/cppast/cpp_file.hpp @@ -9,7 +9,7 @@ namespace cppast { - /// A [cppast::cpp_entity]() referring to a file. + /// A [cppast::cpp_entity]() modelling a file. /// /// This is the top-level entity of the AST. class cpp_file final : public cpp_entity @@ -36,6 +36,12 @@ namespace cppast return std::move(file_); } + /// \returns A reference to (not yet finished) file. + const cpp_file& get() const noexcept + { + return *file_; + } + private: std::unique_ptr file_; }; diff --git a/include/cppast/cpp_namespace.hpp b/include/cppast/cpp_namespace.hpp new file mode 100644 index 0000000..54f7b49 --- /dev/null +++ b/include/cppast/cpp_namespace.hpp @@ -0,0 +1,66 @@ +// 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. + +#ifndef CPPAST_CPP_NAMESPACE_HPP_INCLUDED +#define CPPAST_CPP_NAMESPACE_HPP_INCLUDED + +#include + +namespace cppast +{ + /// A [cppast::cpp_entity]() modelling a namespace. + class cpp_namespace : public cpp_scope + { + public: + /// Builds a [cppast::cpp_namespace](). + class builder + { + public: + /// \effects Sets the namespace name and whether it is inline. + explicit builder(const cpp_entity& parent, std::string name, bool is_inline) + : namespace_(new cpp_namespace(parent, std::move(name), is_inline)) + { + } + + /// \effects Adds an entity. + void add_child(std::unique_ptr child) noexcept + { + namespace_->add_child(std::move(child)); + } + + /// \returns The finished namespace. + std::unique_ptr finish() noexcept + { + return std::move(namespace_); + } + + /// \returns A reference to (not yet finished) namespace. + const cpp_namespace& get() const noexcept + { + return *namespace_; + } + + private: + std::unique_ptr namespace_; + }; + + /// \returns Whether or not the namespace is an `inline namespace`. + bool is_inline() const noexcept + { + return inline_; + } + + private: + cpp_namespace(const cpp_entity& parent, std::string name, bool is_inline) + : cpp_scope(parent, std::move(name)), inline_(is_inline) + { + } + + cpp_entity_type do_get_entity_type() const noexcept override; + + bool inline_; + }; +} // namespace cppast + +#endif // CPPAST_CPP_NAMESPACE_HPP_INCLUDED diff --git a/include/cppast/cpp_scope.hpp b/include/cppast/cpp_scope.hpp index da3593a..cae376a 100644 --- a/include/cppast/cpp_scope.hpp +++ b/include/cppast/cpp_scope.hpp @@ -44,6 +44,8 @@ namespace cppast /// \effects Adds a new child to the scope. void add_child(std::unique_ptr ptr) noexcept { + DEBUG_ASSERT(ptr->parent() == *this, detail::precondition_error_handler{}, + "parent not set properly"); children_.push_back(std::move(ptr)); } diff --git a/include/cppast/detail/assert.hpp b/include/cppast/detail/assert.hpp index e855936..1093b6e 100644 --- a/include/cppast/detail/assert.hpp +++ b/include/cppast/detail/assert.hpp @@ -14,6 +14,11 @@ namespace cppast struct assert_handler : debug_assert::set_level<1>, debug_assert::default_handler { }; + + struct precondition_error_handler : debug_assert::set_level<1>, + debug_assert::default_handler + { + }; } } // namespace cppast::detail diff --git a/include/cppast/detail/intrusive_list.hpp b/include/cppast/detail/intrusive_list.hpp index cb5cb9d..94bd3ec 100644 --- a/include/cppast/detail/intrusive_list.hpp +++ b/include/cppast/detail/intrusive_list.hpp @@ -29,14 +29,14 @@ namespace cppast struct intrusive_list_access { template - static T* get_next(const intrusive_list_node& obj) + static T* get_next(const U& obj) { static_assert(std::is_base_of::value, "must be a base"); return static_cast(obj.next_.get()); } template - static T* set_next(intrusive_list_node& obj, std::unique_ptr node) + static T* set_next(U& obj, std::unique_ptr node) { static_assert(std::is_base_of::value, "must be a base"); obj.next_ = std::move(node); diff --git a/src/cpp_entity_type.cpp b/src/cpp_entity_type.cpp index 4f5525f..b602ad3 100644 --- a/src/cpp_entity_type.cpp +++ b/src/cpp_entity_type.cpp @@ -10,6 +10,9 @@ bool cppast::is_scope(cpp_entity_type type) noexcept { switch (type) { + case cpp_entity_type::namespace_t: + return true; + case cpp_entity_type::file_t: break; } diff --git a/src/cpp_namespace.cpp b/src/cpp_namespace.cpp new file mode 100644 index 0000000..bb8e706 --- /dev/null +++ b/src/cpp_namespace.cpp @@ -0,0 +1,14 @@ +// 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 + +using namespace cppast; + +cpp_entity_type cpp_namespace::do_get_entity_type() const noexcept +{ + return cpp_entity_type::namespace_t; +}