From ebfa75aa8b32369bcf2f06cb7f38273fa74d5d62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Sat, 21 Jan 2017 20:47:51 +0100 Subject: [PATCH] Add first cpp_type infrastructure --- include/cppast/cpp_entity_type.hpp | 4 + include/cppast/cpp_type.hpp | 306 +++++++++++++++++++++++++++++ src/cpp_entity_type.cpp | 16 ++ src/cpp_type.cpp | 15 ++ 4 files changed, 341 insertions(+) create mode 100644 include/cppast/cpp_type.hpp create mode 100644 src/cpp_type.cpp diff --git a/include/cppast/cpp_entity_type.hpp b/include/cppast/cpp_entity_type.hpp index 05c25bc..4d15ed0 100644 --- a/include/cppast/cpp_entity_type.hpp +++ b/include/cppast/cpp_entity_type.hpp @@ -23,7 +23,11 @@ namespace cppast }; /// \returns Whether or not a given entity type is one derived from [cppast::cpp_scope](). + /// One example is [cppast::cpp_entity_type::namespace_t](). bool is_scope(cpp_entity_type type) noexcept; + + /// \returns Whether or not a given entity type is a C++ type. + bool is_type(cpp_entity_type type) noexcept; } // namespace cppast #endif // CPPAST_CPP_ENTITY_TYPE_HPP_INCLUDED diff --git a/include/cppast/cpp_type.hpp b/include/cppast/cpp_type.hpp new file mode 100644 index 0000000..720bf8a --- /dev/null +++ b/include/cppast/cpp_type.hpp @@ -0,0 +1,306 @@ +// 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_TYPE_HPP_INCLUDED +#define CPPAST_CPP_TYPE_HPP_INCLUDED + +#include + +#include +#include + +namespace cppast +{ + /// The kinds of a [cppast::cpp_type](). + enum class cpp_type_kind + { + builtin, + user_defined, + + cv_qualified, + pointer, + reference, + + unexposed, + }; + + /// Base class for all C++ types. + class cpp_type : detail::intrusive_list_node + { + public: + cpp_type(const cpp_type&) = delete; + cpp_type& operator=(const cpp_type&) = delete; + + virtual ~cpp_type() noexcept = default; + + /// \returns The [cppast::cpp_type_kind](). + cpp_type_kind kind() const noexcept + { + return do_get_kind(); + } + + protected: + cpp_type() noexcept = default; + + private: + /// \returns The [cppast::cpp_type_kind](). + virtual cpp_type_kind do_get_kind() const noexcept = 0; + + void on_insert(const cpp_type&) + { + } + + template + friend struct detail::intrusive_list_access; + friend detail::intrusive_list_node; + }; + + /// An unexposed [cppast::cpp_type](). + /// + /// This is one where no further information besides a name is available. + class cpp_unexposed_type final : public cpp_type + { + public: + /// \returns A newly created unexposed type. + std::unique_ptr build(std::string name) + { + return std::unique_ptr(new cpp_unexposed_type(std::move(name))); + } + + /// \returns The name of the type. + const std::string& name() const noexcept + { + return name_; + } + + private: + cpp_unexposed_type(std::string name) : name_(std::move(name)) + { + } + + cpp_type_kind do_get_kind() const noexcept override + { + return cpp_type_kind::unexposed; + } + + std::string name_; + }; + + /// A builtin [cppast::cpp_type](). + /// + /// This is one where there is no associated [cppast::cpp_entity](). + class cpp_builtin_type final : public cpp_type + { + public: + /// \returns A newly created builtin type. + std::unique_ptr build(std::string name) + { + return std::unique_ptr(new cpp_builtin_type(std::move(name))); + } + + /// \returns The name of the type. + const std::string& name() const noexcept + { + return name_; + } + + private: + cpp_builtin_type(std::string name) : name_(std::move(name)) + { + } + + cpp_type_kind do_get_kind() const noexcept override + { + return cpp_type_kind::builtin; + } + + std::string name_; + }; + + /// \exclude + namespace detail + { + struct cpp_type_ref_predicate + { + bool operator()(const cpp_entity& e); + }; + } // namespace detail + + /// Reference to a [cppast::cpp_entity]() representing a new type. + using cpp_type_ref = basic_cpp_entity_ref; + + /// A user-defined [cppast::cpp_type](). + /// + /// It has an associated [cppast::cpp_entity](). + class cpp_user_defined_type final : public cpp_type + { + public: + /// \returns A newly created user-defined type. + std::unique_ptr build(cpp_type_ref entity) + { + return std::unique_ptr( + new cpp_user_defined_type(std::move(entity))); + } + + /// \returns A [cppast::cpp_type_ref]() to the associated [cppast::cpp_entity]() that is the type. + const cpp_type_ref& entity() const noexcept + { + return entity_; + } + + private: + cpp_user_defined_type(cpp_type_ref entity) : entity_(std::move(entity)) + { + } + + cpp_type_kind do_get_kind() const noexcept override + { + return cpp_type_kind::user_defined; + } + + cpp_type_ref entity_; + }; + + /// The kinds of C++ cv qualifiers. + enum cpp_cv + { + cpp_cv_none, + cpp_cv_const, + cpp_cv_volatile, + cpp_cv_const_volatile, + }; + + /// \returns `true` if the qualifier contains `const`. + inline bool is_const(cpp_cv cv) noexcept + { + return cv == cpp_cv_const || cv == cpp_cv_const_volatile; + } + + /// \returns `true` if the qualifier contains `volatile`. + inline bool is_volatile(cpp_cv cv) noexcept + { + return cv == cpp_cv_volatile || cv == cpp_cv_const_volatile; + } + + /// A [cppast::cpp_cv]() qualified [cppast::cpp_type](). + class cpp_cv_qualified_type final : public cpp_type + { + public: + /// \returns A newly created qualified type. + /// \requires `cv` must not be [cppast::cpp_cv::cpp_cv_none](). + static std::unique_ptr build(std::unique_ptr type, + cpp_cv cv) + { + DEBUG_ASSERT(cv != cpp_cv_none, detail::precondition_error_handler{}); + return std::unique_ptr( + new cpp_cv_qualified_type(std::move(type), cv)); + } + + /// \returns A reference to the [cppast::cpp_type]() that is qualified. + const cpp_type& type() const noexcept + { + return *type_; + } + + /// \returns The [cppast::cpp_cv]() qualifier. + cpp_cv cv_qualifier() const noexcept + { + return cv_; + } + + private: + cpp_cv_qualified_type(std::unique_ptr type, cpp_cv cv) + : type_(std::move(type)), cv_(cv) + { + } + + cpp_type_kind do_get_kind() const noexcept override + { + return cpp_type_kind::cv_qualified; + } + + std::unique_ptr type_; + cpp_cv cv_; + }; + + /// A pointer to a [cppast::cpp_type](). + class cpp_pointer_type final : public cpp_type + { + public: + /// \returns A newly created pointer type. + static std::unique_ptr build(std::unique_ptr pointee) + { + return std::unique_ptr(new cpp_pointer_type(std::move(pointee))); + } + + /// \returns A reference to the [cppast::cpp_type]() that is the pointee. + const cpp_type& pointee() const noexcept + { + return *pointee_; + } + + private: + cpp_pointer_type(std::unique_ptr pointee) : pointee_(std::move(pointee)) + { + } + + cpp_type_kind do_get_kind() const noexcept override + { + return cpp_type_kind::pointer; + } + + std::unique_ptr pointee_; + }; + + /// The kinds of C++ references. + enum cpp_reference + { + cpp_ref_none, + cpp_ref_lvalue, + cpp_ref_rvalue, + }; + + /// A reference to a [cppast::cpp_type](). + class cpp_reference_type final : public cpp_type + { + public: + /// \returns A newly created qualified type. + /// \requires `ref` must not be [cppast::cpp_reference::cpp_ref_none](). + static std::unique_ptr build(std::unique_ptr type, + cpp_reference ref) + { + DEBUG_ASSERT(ref != cpp_ref_none, detail::precondition_error_handler{}); + return std::unique_ptr( + new cpp_reference_type(std::move(type), ref)); + } + + /// \returns A reference to the [cppast::cpp_type]() that is referenced. + const cpp_type& referee() const noexcept + { + return *referee_; + } + + /// \returns The [cppast::cpp_reference]() type. + cpp_reference reference_kind() const noexcept + { + return ref_; + } + + private: + cpp_reference_type(std::unique_ptr referee, cpp_reference ref) + : referee_(std::move(referee)), ref_(ref) + { + } + + cpp_type_kind do_get_kind() const noexcept override + { + return cpp_type_kind::reference; + } + + std::unique_ptr referee_; + cpp_reference ref_; + }; +} // namespace cppast + +#endif // CPPAST_CPP_TYPE_HPP_INCLUDED diff --git a/src/cpp_entity_type.cpp b/src/cpp_entity_type.cpp index 83283fa..cd841a5 100644 --- a/src/cpp_entity_type.cpp +++ b/src/cpp_entity_type.cpp @@ -23,3 +23,19 @@ bool cppast::is_scope(cpp_entity_type type) noexcept return false; } + +bool cppast::is_type(cpp_entity_type type) noexcept +{ + switch (type) + { + case cpp_entity_type::file_t: + case cpp_entity_type::namespace_t: + case cpp_entity_type::namespace_alias_t: + case cpp_entity_type::using_directive_t: + case cpp_entity_type::using_declaration_t: + case cpp_entity_type::count: + break; + } + + return false; +} diff --git a/src/cpp_type.cpp b/src/cpp_type.cpp new file mode 100644 index 0000000..ee6f603 --- /dev/null +++ b/src/cpp_type.cpp @@ -0,0 +1,15 @@ +// 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 + +using namespace cppast; + +bool detail::cpp_type_ref_predicate::operator()(const cpp_entity& e) +{ + return is_type(e.type()); +}